xref: /llvm-project/flang/lib/Parser/program-parsers.cpp (revision fe5a64d1160209f22624b112b2629b0d6c4bb264)
164ab3302SCarolineConcatto //===-- lib/Parser/program-parsers.cpp ------------------------------------===//
264ab3302SCarolineConcatto //
364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664ab3302SCarolineConcatto //
764ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
864ab3302SCarolineConcatto 
964ab3302SCarolineConcatto // Per-type parsers for program units
1064ab3302SCarolineConcatto 
1164ab3302SCarolineConcatto #include "basic-parsers.h"
1264ab3302SCarolineConcatto #include "expr-parsers.h"
1364ab3302SCarolineConcatto #include "misc-parsers.h"
1464ab3302SCarolineConcatto #include "stmt-parser.h"
1564ab3302SCarolineConcatto #include "token-parsers.h"
1664ab3302SCarolineConcatto #include "type-parser-implementation.h"
1764ab3302SCarolineConcatto #include "flang/Parser/characters.h"
1864ab3302SCarolineConcatto #include "flang/Parser/parse-tree.h"
1964ab3302SCarolineConcatto 
2064ab3302SCarolineConcatto namespace Fortran::parser {
2164ab3302SCarolineConcatto 
2299a0a12aSPeter Klausler // R1530 function-stmt ->
2399a0a12aSPeter Klausler //         [prefix] FUNCTION function-name ( [dummy-arg-name-list] ) [suffix]
2499a0a12aSPeter Klausler // R1526 prefix -> prefix-spec [prefix-spec]...
2599a0a12aSPeter Klausler // R1531 dummy-arg-name -> name
2699a0a12aSPeter Klausler 
2799a0a12aSPeter Klausler static constexpr auto validFunctionStmt{
2899a0a12aSPeter Klausler     construct<FunctionStmt>(many(prefixSpec), "FUNCTION" >> name,
2999a0a12aSPeter Klausler         parenthesized(optionalList(name)), maybe(suffix)) /
3099a0a12aSPeter Klausler         atEndOfStmt ||
3199a0a12aSPeter Klausler     construct<FunctionStmt>(many(prefixSpec), "FUNCTION" >> name / atEndOfStmt,
3299a0a12aSPeter Klausler         // PGI & Intel accept "FUNCTION F"
3399a0a12aSPeter Klausler         extension<LanguageFeature::OmitFunctionDummies>(
3499a0a12aSPeter Klausler             "nonstandard usage: FUNCTION statement without dummy argument list"_port_en_US,
3599a0a12aSPeter Klausler             pure<std::list<Name>>()),
3699a0a12aSPeter Klausler         pure<std::optional<Suffix>>())};
3799a0a12aSPeter Klausler 
3899a0a12aSPeter Klausler // function-stmt with error recovery -- used in interfaces and internal
3999a0a12aSPeter Klausler // subprograms, but not at the top level, where REALFUNCTIONF and
4099a0a12aSPeter Klausler // INTEGERPUREELEMENTALFUNCTIONG(10) might appear as the first statement
4199a0a12aSPeter Klausler // of a main program.
4299a0a12aSPeter Klausler TYPE_PARSER(validFunctionStmt ||
4399a0a12aSPeter Klausler     construct<FunctionStmt>(many(prefixSpec), "FUNCTION" >> name,
4499a0a12aSPeter Klausler         defaulted(parenthesized(optionalList(name))), maybe(suffix)) /
4599a0a12aSPeter Klausler         checkEndOfKnownStmt)
4699a0a12aSPeter Klausler 
4764ab3302SCarolineConcatto // R502 program-unit ->
4864ab3302SCarolineConcatto //        main-program | external-subprogram | module | submodule | block-data
4964ab3302SCarolineConcatto // R503 external-subprogram -> function-subprogram | subroutine-subprogram
5064ab3302SCarolineConcatto // N.B. "module" must precede "external-subprogram" in this sequence of
5164ab3302SCarolineConcatto // alternatives to avoid ambiguity with the MODULE keyword prefix that
5264ab3302SCarolineConcatto // they recognize.  I.e., "modulesubroutinefoo" should start a module
5364ab3302SCarolineConcatto // "subroutinefoo", not a subroutine "foo" with the MODULE prefix.  The
5464ab3302SCarolineConcatto // ambiguity is exacerbated by the extension that accepts a function
5564ab3302SCarolineConcatto // statement without an otherwise empty list of dummy arguments.  That
5664ab3302SCarolineConcatto // MODULE prefix is disallowed by a constraint (C1547) in this context,
5764ab3302SCarolineConcatto // so the standard language is not ambiguous, but disabling its misrecognition
58619b5bfcSPeter Klausler // here would require context-sensitive keyword recognition or variant parsers
59619b5bfcSPeter Klausler // for several productions; giving the "module" production priority here is a
60619b5bfcSPeter Klausler // cleaner solution, though regrettably subtle.
61619b5bfcSPeter Klausler // Enforcing C1547 is done in semantics.
6213cee14bSpeter klausler static constexpr auto programUnit{
6313cee14bSpeter klausler     construct<ProgramUnit>(indirect(Parser<Module>{})) ||
6464ab3302SCarolineConcatto     construct<ProgramUnit>(indirect(subroutineSubprogram)) ||
6564ab3302SCarolineConcatto     construct<ProgramUnit>(indirect(Parser<Submodule>{})) ||
6664ab3302SCarolineConcatto     construct<ProgramUnit>(indirect(Parser<BlockData>{})) ||
6799a0a12aSPeter Klausler     lookAhead(validFunctionStmt) >>
6899a0a12aSPeter Klausler         construct<ProgramUnit>(indirect(functionSubprogram)) ||
6913cee14bSpeter klausler     construct<ProgramUnit>(indirect(Parser<MainProgram>{}))};
7013cee14bSpeter klausler static constexpr auto normalProgramUnit{StartNewSubprogram{} >> programUnit /
7113cee14bSpeter klausler         skipMany(";"_tok) / space / recovery(endOfLine, SkipPast<'\n'>{})};
7213cee14bSpeter klausler static constexpr auto globalCompilerDirective{
7313cee14bSpeter klausler     construct<ProgramUnit>(indirect(compilerDirective))};
7413cee14bSpeter klausler 
7582867439SValentin Clement (バレンタイン クレメン) static constexpr auto globalOpenACCCompilerDirective{
7682867439SValentin Clement (バレンタイン クレメン)     construct<ProgramUnit>(indirect(skipStuffBeforeStatement >>
7782867439SValentin Clement (バレンタイン クレメン)         "!$ACC "_sptok >> Parser<OpenACCRoutineConstruct>{}))};
7882867439SValentin Clement (バレンタイン クレメン) 
7913cee14bSpeter klausler // R501 program -> program-unit [program-unit]...
8013cee14bSpeter klausler // This is the top-level production for the Fortran language.
8113cee14bSpeter klausler // F'2018 6.3.1 defines a program unit as a sequence of one or more lines,
8213cee14bSpeter klausler // implying that a line can't be part of two distinct program units.
8313cee14bSpeter klausler // Consequently, a program unit END statement should be the last statement
8413cee14bSpeter klausler // on its line.  We parse those END statements via unterminatedStatement()
8513cee14bSpeter klausler // and then skip over the end of the line here.
862d8b6a47SPeter Klausler TYPE_PARSER(
872d8b6a47SPeter Klausler     construct<Program>(extension<LanguageFeature::EmptySourceFile>(
882d8b6a47SPeter Klausler                            "nonstandard usage: empty source file"_port_en_US,
892d8b6a47SPeter Klausler                            skipStuffBeforeStatement >> !nextCh >>
902d8b6a47SPeter Klausler                                pure<std::list<ProgramUnit>>()) ||
9182867439SValentin Clement (バレンタイン クレメン)         some(globalCompilerDirective || globalOpenACCCompilerDirective ||
9282867439SValentin Clement (バレンタイン クレメン)             normalProgramUnit) /
9313cee14bSpeter klausler             skipStuffBeforeStatement))
9464ab3302SCarolineConcatto 
9564ab3302SCarolineConcatto // R507 declaration-construct ->
9664ab3302SCarolineConcatto //        specification-construct | data-stmt | format-stmt |
9764ab3302SCarolineConcatto //        entry-stmt | stmt-function-stmt
9864ab3302SCarolineConcatto // N.B. These parsers incorporate recognition of some other statements that
9964ab3302SCarolineConcatto // may have been misplaced in the sequence of statements that are acceptable
10064ab3302SCarolineConcatto // as a specification part in order to improve error recovery.
10164ab3302SCarolineConcatto // Also note that many instances of specification-part in the standard grammar
10264ab3302SCarolineConcatto // are in contexts that impose constraints on the kinds of statements that
10364ab3302SCarolineConcatto // are allowed, and so we have a variant production for declaration-construct
10464ab3302SCarolineConcatto // that implements those constraints.
105010c55bfSPeter Klausler constexpr auto actionStmtLookAhead{first(actionStmt >> ok,
106010c55bfSPeter Klausler     // Also accept apparent action statements with errors if they might be
107010c55bfSPeter Klausler     // first in the execution part
108010c55bfSPeter Klausler     "ALLOCATE ("_tok, "CALL" >> name >> "("_tok, "GO TO"_tok, "OPEN ("_tok,
109010c55bfSPeter Klausler     "PRINT"_tok / space / !"("_tok, "READ ("_tok, "WRITE ("_tok)};
110010c55bfSPeter Klausler constexpr auto execPartLookAhead{first(actionStmtLookAhead >> ok,
111010c55bfSPeter Klausler     openaccConstruct >> ok, openmpConstruct >> ok, "ASSOCIATE ("_tok,
112010c55bfSPeter Klausler     "BLOCK"_tok, "SELECT"_tok, "CHANGE TEAM"_sptok, "CRITICAL"_tok, "DO"_tok,
113010c55bfSPeter Klausler     "IF ("_tok, "WHERE ("_tok, "FORALL ("_tok, "!$CUF"_tok)};
11464ab3302SCarolineConcatto constexpr auto declErrorRecovery{
11564ab3302SCarolineConcatto     stmtErrorRecoveryStart >> !execPartLookAhead >> skipStmtErrorRecovery};
11664ab3302SCarolineConcatto constexpr auto misplacedSpecificationStmt{Parser<UseStmt>{} >>
11764ab3302SCarolineConcatto         fail<DeclarationConstruct>("misplaced USE statement"_err_en_US) ||
11864ab3302SCarolineConcatto     Parser<ImportStmt>{} >>
11964ab3302SCarolineConcatto         fail<DeclarationConstruct>(
12064ab3302SCarolineConcatto             "IMPORT statements must follow any USE statements and precede all other declarations"_err_en_US) ||
12164ab3302SCarolineConcatto     Parser<ImplicitStmt>{} >>
12264ab3302SCarolineConcatto         fail<DeclarationConstruct>(
12364ab3302SCarolineConcatto             "IMPLICIT statements must follow USE and IMPORT and precede all other declarations"_err_en_US)};
12464ab3302SCarolineConcatto 
125fffbabfdSPeter Klausler TYPE_CONTEXT_PARSER("declaration construct"_en_US,
12664ab3302SCarolineConcatto     first(construct<DeclarationConstruct>(specificationConstruct),
12764ab3302SCarolineConcatto         construct<DeclarationConstruct>(statement(indirect(dataStmt))),
128fffbabfdSPeter Klausler         construct<DeclarationConstruct>(statement(indirect(formatStmt))),
12964ab3302SCarolineConcatto         construct<DeclarationConstruct>(statement(indirect(entryStmt))),
13064ab3302SCarolineConcatto         construct<DeclarationConstruct>(
13164ab3302SCarolineConcatto             statement(indirect(Parser<StmtFunctionStmt>{}))),
132fffbabfdSPeter Klausler         misplacedSpecificationStmt))
133fffbabfdSPeter Klausler 
134fffbabfdSPeter Klausler constexpr auto recoveredDeclarationConstruct{
135fffbabfdSPeter Klausler     recovery(withMessage("expected declaration construct"_err_en_US,
136fffbabfdSPeter Klausler                  declarationConstruct),
137fffbabfdSPeter Klausler         construct<DeclarationConstruct>(declErrorRecovery))};
138fffbabfdSPeter Klausler 
139fffbabfdSPeter Klausler // R504 specification-part ->
140fffbabfdSPeter Klausler //         [use-stmt]... [import-stmt]... [implicit-part]
141fffbabfdSPeter Klausler //         [declaration-construct]...
142fffbabfdSPeter Klausler TYPE_CONTEXT_PARSER("specification part"_en_US,
143fffbabfdSPeter Klausler     construct<SpecificationPart>(many(openaccDeclarativeConstruct),
144fffbabfdSPeter Klausler         many(openmpDeclarativeConstruct), many(indirect(compilerDirective)),
145fffbabfdSPeter Klausler         many(statement(indirect(Parser<UseStmt>{}))),
146fffbabfdSPeter Klausler         many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
147fffbabfdSPeter Klausler         implicitPart, many(recoveredDeclarationConstruct)))
14864ab3302SCarolineConcatto 
14964ab3302SCarolineConcatto // R507 variant of declaration-construct for use in limitedSpecificationPart.
15064ab3302SCarolineConcatto constexpr auto invalidDeclarationStmt{formatStmt >>
15164ab3302SCarolineConcatto         fail<DeclarationConstruct>(
15264ab3302SCarolineConcatto             "FORMAT statements are not permitted in this specification part"_err_en_US) ||
15364ab3302SCarolineConcatto     entryStmt >>
15464ab3302SCarolineConcatto         fail<DeclarationConstruct>(
15564ab3302SCarolineConcatto             "ENTRY statements are not permitted in this specification part"_err_en_US)};
15664ab3302SCarolineConcatto 
15764ab3302SCarolineConcatto constexpr auto limitedDeclarationConstruct{recovery(
15864ab3302SCarolineConcatto     withMessage("expected declaration construct"_err_en_US,
15964ab3302SCarolineConcatto         inContext("declaration construct"_en_US,
16064ab3302SCarolineConcatto             first(construct<DeclarationConstruct>(specificationConstruct),
16164ab3302SCarolineConcatto                 construct<DeclarationConstruct>(statement(indirect(dataStmt))),
16264ab3302SCarolineConcatto                 misplacedSpecificationStmt, invalidDeclarationStmt))),
16364ab3302SCarolineConcatto     construct<DeclarationConstruct>(
16464ab3302SCarolineConcatto         stmtErrorRecoveryStart >> skipStmtErrorRecovery))};
16564ab3302SCarolineConcatto 
16664ab3302SCarolineConcatto // R504 variant for many contexts (modules, submodules, BLOCK DATA subprograms,
16764ab3302SCarolineConcatto // and interfaces) which have constraints on their specification parts that
16864ab3302SCarolineConcatto // preclude FORMAT, ENTRY, and statement functions, and benefit from
16964ab3302SCarolineConcatto // specialized error recovery in the event of a spurious executable
17064ab3302SCarolineConcatto // statement.
17164ab3302SCarolineConcatto constexpr auto limitedSpecificationPart{inContext("specification part"_en_US,
1720a90ffa7SValentin Clement     construct<SpecificationPart>(many(openaccDeclarativeConstruct),
173cf715717STim Keith         many(openmpDeclarativeConstruct), many(indirect(compilerDirective)),
17464ab3302SCarolineConcatto         many(statement(indirect(Parser<UseStmt>{}))),
17564ab3302SCarolineConcatto         many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
17664ab3302SCarolineConcatto         implicitPart, many(limitedDeclarationConstruct)))};
17764ab3302SCarolineConcatto 
17864ab3302SCarolineConcatto // R508 specification-construct ->
17964ab3302SCarolineConcatto //        derived-type-def | enum-def | generic-stmt | interface-block |
18064ab3302SCarolineConcatto //        parameter-stmt | procedure-declaration-stmt |
18164ab3302SCarolineConcatto //        other-specification-stmt | type-declaration-stmt
18264ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("specification construct"_en_US,
18364ab3302SCarolineConcatto     first(construct<SpecificationConstruct>(indirect(Parser<DerivedTypeDef>{})),
18464ab3302SCarolineConcatto         construct<SpecificationConstruct>(indirect(Parser<EnumDef>{})),
18564ab3302SCarolineConcatto         construct<SpecificationConstruct>(
18664ab3302SCarolineConcatto             statement(indirect(Parser<GenericStmt>{}))),
18764ab3302SCarolineConcatto         construct<SpecificationConstruct>(indirect(interfaceBlock)),
18864ab3302SCarolineConcatto         construct<SpecificationConstruct>(statement(indirect(parameterStmt))),
18964ab3302SCarolineConcatto         construct<SpecificationConstruct>(
19064ab3302SCarolineConcatto             statement(indirect(oldParameterStmt))),
19164ab3302SCarolineConcatto         construct<SpecificationConstruct>(
19264ab3302SCarolineConcatto             statement(indirect(Parser<ProcedureDeclarationStmt>{}))),
19364ab3302SCarolineConcatto         construct<SpecificationConstruct>(
19464ab3302SCarolineConcatto             statement(Parser<OtherSpecificationStmt>{})),
19564ab3302SCarolineConcatto         construct<SpecificationConstruct>(
19664ab3302SCarolineConcatto             statement(indirect(typeDeclarationStmt))),
19764ab3302SCarolineConcatto         construct<SpecificationConstruct>(indirect(Parser<StructureDef>{})),
1980a90ffa7SValentin Clement         construct<SpecificationConstruct>(
1990a90ffa7SValentin Clement             indirect(openaccDeclarativeConstruct)),
20064ab3302SCarolineConcatto         construct<SpecificationConstruct>(indirect(openmpDeclarativeConstruct)),
20164ab3302SCarolineConcatto         construct<SpecificationConstruct>(indirect(compilerDirective))))
20264ab3302SCarolineConcatto 
20364ab3302SCarolineConcatto // R513 other-specification-stmt ->
20464ab3302SCarolineConcatto //        access-stmt | allocatable-stmt | asynchronous-stmt | bind-stmt |
20564ab3302SCarolineConcatto //        codimension-stmt | contiguous-stmt | dimension-stmt | external-stmt |
20664ab3302SCarolineConcatto //        intent-stmt | intrinsic-stmt | namelist-stmt | optional-stmt |
20764ab3302SCarolineConcatto //        pointer-stmt | protected-stmt | save-stmt | target-stmt |
2084ad72793SPeter Klausler //        volatile-stmt | value-stmt | common-stmt | equivalence-stmt |
2094ad72793SPeter Klausler // (CUDA) CUDA-attributes-stmt
21064ab3302SCarolineConcatto TYPE_PARSER(first(
21164ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<AccessStmt>{})),
21264ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<AllocatableStmt>{})),
21364ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<AsynchronousStmt>{})),
21464ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<BindStmt>{})),
21564ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<CodimensionStmt>{})),
21664ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<ContiguousStmt>{})),
21764ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<DimensionStmt>{})),
21864ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<ExternalStmt>{})),
21964ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<IntentStmt>{})),
22064ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<IntrinsicStmt>{})),
22164ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<NamelistStmt>{})),
22264ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<OptionalStmt>{})),
22364ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<PointerStmt>{})),
22464ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<ProtectedStmt>{})),
22564ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<SaveStmt>{})),
22664ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<TargetStmt>{})),
22764ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<ValueStmt>{})),
22864ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<VolatileStmt>{})),
22964ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<CommonStmt>{})),
23064ab3302SCarolineConcatto     construct<OtherSpecificationStmt>(indirect(Parser<EquivalenceStmt>{})),
2314ad72793SPeter Klausler     construct<OtherSpecificationStmt>(indirect(Parser<BasedPointerStmt>{})),
2324ad72793SPeter Klausler     construct<OtherSpecificationStmt>(indirect(Parser<CUDAAttributesStmt>{}))))
23364ab3302SCarolineConcatto 
23464ab3302SCarolineConcatto // R1401 main-program ->
23564ab3302SCarolineConcatto //         [program-stmt] [specification-part] [execution-part]
23664ab3302SCarolineConcatto //         [internal-subprogram-part] end-program-stmt
23764ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("main program"_en_US,
23864ab3302SCarolineConcatto     construct<MainProgram>(maybe(statement(Parser<ProgramStmt>{})),
23964ab3302SCarolineConcatto         specificationPart, executionPart, maybe(internalSubprogramPart),
24064ab3302SCarolineConcatto         unterminatedStatement(Parser<EndProgramStmt>{})))
24164ab3302SCarolineConcatto 
24264ab3302SCarolineConcatto // R1402 program-stmt -> PROGRAM program-name
24364ab3302SCarolineConcatto // PGI allows empty parentheses after the name.
24464ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("PROGRAM statement"_en_US,
24564ab3302SCarolineConcatto     construct<ProgramStmt>("PROGRAM" >> name /
24664ab3302SCarolineConcatto             maybe(extension<LanguageFeature::ProgramParentheses>(
2472d8b6a47SPeter Klausler                 "nonstandard usage: parentheses in PROGRAM statement"_port_en_US,
24864ab3302SCarolineConcatto                 parenthesized(ok)))))
24964ab3302SCarolineConcatto 
25064ab3302SCarolineConcatto // R1403 end-program-stmt -> END [PROGRAM [program-name]]
25164ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END PROGRAM statement"_en_US,
252b5aea329SPeter Klausler     construct<EndProgramStmt>(
253b5aea329SPeter Klausler         recovery("END" >> defaulted("PROGRAM" >> maybe(name)) / atEndOfStmt,
254b5aea329SPeter Klausler             progUnitEndStmtErrorRecovery)))
25564ab3302SCarolineConcatto 
25664ab3302SCarolineConcatto // R1404 module ->
25764ab3302SCarolineConcatto //         module-stmt [specification-part] [module-subprogram-part]
25864ab3302SCarolineConcatto //         end-module-stmt
25964ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("module"_en_US,
26064ab3302SCarolineConcatto     construct<Module>(statement(Parser<ModuleStmt>{}), limitedSpecificationPart,
26164ab3302SCarolineConcatto         maybe(Parser<ModuleSubprogramPart>{}),
26264ab3302SCarolineConcatto         unterminatedStatement(Parser<EndModuleStmt>{})))
26364ab3302SCarolineConcatto 
26464ab3302SCarolineConcatto // R1405 module-stmt -> MODULE module-name
26564ab3302SCarolineConcatto TYPE_CONTEXT_PARSER(
26664ab3302SCarolineConcatto     "MODULE statement"_en_US, construct<ModuleStmt>("MODULE" >> name))
26764ab3302SCarolineConcatto 
26864ab3302SCarolineConcatto // R1406 end-module-stmt -> END [MODULE [module-name]]
26964ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END MODULE statement"_en_US,
270b5aea329SPeter Klausler     construct<EndModuleStmt>(
271b5aea329SPeter Klausler         recovery("END" >> defaulted("MODULE" >> maybe(name)) / atEndOfStmt,
272b5aea329SPeter Klausler             progUnitEndStmtErrorRecovery)))
27364ab3302SCarolineConcatto 
27464ab3302SCarolineConcatto // R1407 module-subprogram-part -> contains-stmt [module-subprogram]...
27564ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("module subprogram part"_en_US,
27664ab3302SCarolineConcatto     construct<ModuleSubprogramPart>(statement(containsStmt),
27764ab3302SCarolineConcatto         many(StartNewSubprogram{} >> Parser<ModuleSubprogram>{})))
27864ab3302SCarolineConcatto 
27964ab3302SCarolineConcatto // R1408 module-subprogram ->
28064ab3302SCarolineConcatto //         function-subprogram | subroutine-subprogram |
28164ab3302SCarolineConcatto //         separate-module-subprogram
28264ab3302SCarolineConcatto TYPE_PARSER(construct<ModuleSubprogram>(indirect(functionSubprogram)) ||
28364ab3302SCarolineConcatto     construct<ModuleSubprogram>(indirect(subroutineSubprogram)) ||
2847c1b2898SPeter Klausler     construct<ModuleSubprogram>(indirect(Parser<SeparateModuleSubprogram>{})) ||
2857c1b2898SPeter Klausler     construct<ModuleSubprogram>(indirect(compilerDirective)))
28664ab3302SCarolineConcatto 
28764ab3302SCarolineConcatto // R1410 module-nature -> INTRINSIC | NON_INTRINSIC
28864ab3302SCarolineConcatto constexpr auto moduleNature{
28964ab3302SCarolineConcatto     "INTRINSIC" >> pure(UseStmt::ModuleNature::Intrinsic) ||
29064ab3302SCarolineConcatto     "NON_INTRINSIC" >> pure(UseStmt::ModuleNature::Non_Intrinsic)};
29164ab3302SCarolineConcatto 
29264ab3302SCarolineConcatto // R1409 use-stmt ->
29364ab3302SCarolineConcatto //         USE [[, module-nature] ::] module-name [, rename-list] |
29464ab3302SCarolineConcatto //         USE [[, module-nature] ::] module-name , ONLY : [only-list]
29564ab3302SCarolineConcatto // N.B. Lookahead to the end of the statement is necessary to resolve
29664ab3302SCarolineConcatto // ambiguity with assignments and statement function definitions that
29764ab3302SCarolineConcatto // begin with the letters "USE".
29864ab3302SCarolineConcatto TYPE_PARSER(construct<UseStmt>("USE" >> optionalBeforeColons(moduleNature),
29964ab3302SCarolineConcatto                 name, ", ONLY :" >> optionalList(Parser<Only>{})) ||
30064ab3302SCarolineConcatto     construct<UseStmt>("USE" >> optionalBeforeColons(moduleNature), name,
30164ab3302SCarolineConcatto         defaulted("," >>
30264ab3302SCarolineConcatto             nonemptyList("expected renamings"_err_en_US, Parser<Rename>{})) /
30364ab3302SCarolineConcatto             lookAhead(endOfStmt)))
30464ab3302SCarolineConcatto 
30564ab3302SCarolineConcatto // R1411 rename ->
30664ab3302SCarolineConcatto //         local-name => use-name |
30764ab3302SCarolineConcatto //         OPERATOR ( local-defined-operator ) =>
30864ab3302SCarolineConcatto //           OPERATOR ( use-defined-operator )
30964ab3302SCarolineConcatto TYPE_PARSER(construct<Rename>("OPERATOR (" >>
31064ab3302SCarolineConcatto                 construct<Rename::Operators>(
31164ab3302SCarolineConcatto                     definedOpName / ") => OPERATOR (", definedOpName / ")")) ||
31264ab3302SCarolineConcatto     construct<Rename>(construct<Rename::Names>(name, "=>" >> name)))
31364ab3302SCarolineConcatto 
31464ab3302SCarolineConcatto // R1412 only -> generic-spec | only-use-name | rename
31564ab3302SCarolineConcatto // R1413 only-use-name -> use-name
3169a883bfaSpeter klausler // N.B. generic-spec and only-use-name are ambiguous; resolved with symbols
31764ab3302SCarolineConcatto TYPE_PARSER(construct<Only>(Parser<Rename>{}) ||
3189a883bfaSpeter klausler     construct<Only>(indirect(genericSpec)) || construct<Only>(name))
31964ab3302SCarolineConcatto 
32064ab3302SCarolineConcatto // R1416 submodule ->
32164ab3302SCarolineConcatto //         submodule-stmt [specification-part] [module-subprogram-part]
32264ab3302SCarolineConcatto //         end-submodule-stmt
32364ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("submodule"_en_US,
32464ab3302SCarolineConcatto     construct<Submodule>(statement(Parser<SubmoduleStmt>{}),
32564ab3302SCarolineConcatto         limitedSpecificationPart, maybe(Parser<ModuleSubprogramPart>{}),
32664ab3302SCarolineConcatto         unterminatedStatement(Parser<EndSubmoduleStmt>{})))
32764ab3302SCarolineConcatto 
32864ab3302SCarolineConcatto // R1417 submodule-stmt -> SUBMODULE ( parent-identifier ) submodule-name
32964ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("SUBMODULE statement"_en_US,
33064ab3302SCarolineConcatto     construct<SubmoduleStmt>(
33164ab3302SCarolineConcatto         "SUBMODULE" >> parenthesized(Parser<ParentIdentifier>{}), name))
33264ab3302SCarolineConcatto 
33364ab3302SCarolineConcatto // R1418 parent-identifier -> ancestor-module-name [: parent-submodule-name]
33464ab3302SCarolineConcatto TYPE_PARSER(construct<ParentIdentifier>(name, maybe(":" >> name)))
33564ab3302SCarolineConcatto 
33664ab3302SCarolineConcatto // R1419 end-submodule-stmt -> END [SUBMODULE [submodule-name]]
33764ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END SUBMODULE statement"_en_US,
33864ab3302SCarolineConcatto     construct<EndSubmoduleStmt>(
339b5aea329SPeter Klausler         recovery("END" >> defaulted("SUBMODULE" >> maybe(name)) / atEndOfStmt,
34064ab3302SCarolineConcatto             progUnitEndStmtErrorRecovery)))
34164ab3302SCarolineConcatto 
34264ab3302SCarolineConcatto // R1420 block-data -> block-data-stmt [specification-part] end-block-data-stmt
34364ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("BLOCK DATA subprogram"_en_US,
34464ab3302SCarolineConcatto     construct<BlockData>(statement(Parser<BlockDataStmt>{}),
34564ab3302SCarolineConcatto         limitedSpecificationPart,
34664ab3302SCarolineConcatto         unterminatedStatement(Parser<EndBlockDataStmt>{})))
34764ab3302SCarolineConcatto 
34864ab3302SCarolineConcatto // R1421 block-data-stmt -> BLOCK DATA [block-data-name]
34964ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("BLOCK DATA statement"_en_US,
35064ab3302SCarolineConcatto     construct<BlockDataStmt>("BLOCK DATA" >> maybe(name)))
35164ab3302SCarolineConcatto 
35264ab3302SCarolineConcatto // R1422 end-block-data-stmt -> END [BLOCK DATA [block-data-name]]
35364ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END BLOCK DATA statement"_en_US,
35464ab3302SCarolineConcatto     construct<EndBlockDataStmt>(
355b5aea329SPeter Klausler         recovery("END" >> defaulted("BLOCK DATA" >> maybe(name)) / atEndOfStmt,
35664ab3302SCarolineConcatto             progUnitEndStmtErrorRecovery)))
35764ab3302SCarolineConcatto 
35864ab3302SCarolineConcatto // R1501 interface-block ->
35964ab3302SCarolineConcatto //         interface-stmt [interface-specification]... end-interface-stmt
36064ab3302SCarolineConcatto TYPE_PARSER(construct<InterfaceBlock>(statement(Parser<InterfaceStmt>{}),
36164ab3302SCarolineConcatto     many(Parser<InterfaceSpecification>{}),
36264ab3302SCarolineConcatto     statement(Parser<EndInterfaceStmt>{})))
36364ab3302SCarolineConcatto 
36464ab3302SCarolineConcatto // R1502 interface-specification -> interface-body | procedure-stmt
36564ab3302SCarolineConcatto TYPE_PARSER(construct<InterfaceSpecification>(Parser<InterfaceBody>{}) ||
36664ab3302SCarolineConcatto     construct<InterfaceSpecification>(statement(Parser<ProcedureStmt>{})))
36764ab3302SCarolineConcatto 
36864ab3302SCarolineConcatto // R1503 interface-stmt -> INTERFACE [generic-spec] | ABSTRACT INTERFACE
36964ab3302SCarolineConcatto TYPE_PARSER(construct<InterfaceStmt>("INTERFACE" >> maybe(genericSpec)) ||
37064ab3302SCarolineConcatto     construct<InterfaceStmt>(construct<Abstract>("ABSTRACT INTERFACE"_sptok)))
37164ab3302SCarolineConcatto 
37264ab3302SCarolineConcatto // R1504 end-interface-stmt -> END INTERFACE [generic-spec]
373619b5bfcSPeter Klausler TYPE_PARSER(
374619b5bfcSPeter Klausler     construct<EndInterfaceStmt>(recovery("END INTERFACE" >> maybe(genericSpec),
375619b5bfcSPeter Klausler         constructEndStmtErrorRecovery >> pure<std::optional<GenericSpec>>())))
37664ab3302SCarolineConcatto 
37764ab3302SCarolineConcatto // R1505 interface-body ->
37864ab3302SCarolineConcatto //         function-stmt [specification-part] end-function-stmt |
37964ab3302SCarolineConcatto //         subroutine-stmt [specification-part] end-subroutine-stmt
38064ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("interface body"_en_US,
38164ab3302SCarolineConcatto     construct<InterfaceBody>(
38264ab3302SCarolineConcatto         construct<InterfaceBody::Function>(statement(functionStmt),
38364ab3302SCarolineConcatto             indirect(limitedSpecificationPart), statement(endFunctionStmt))) ||
38464ab3302SCarolineConcatto         construct<InterfaceBody>(construct<InterfaceBody::Subroutine>(
38564ab3302SCarolineConcatto             statement(subroutineStmt), indirect(limitedSpecificationPart),
38664ab3302SCarolineConcatto             statement(endSubroutineStmt))))
38764ab3302SCarolineConcatto 
38864ab3302SCarolineConcatto // R1507 specific-procedure -> procedure-name
38964ab3302SCarolineConcatto constexpr auto specificProcedures{
39064ab3302SCarolineConcatto     nonemptyList("expected specific procedure names"_err_en_US, name)};
39164ab3302SCarolineConcatto 
39264ab3302SCarolineConcatto // R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list
39364ab3302SCarolineConcatto TYPE_PARSER(construct<ProcedureStmt>("MODULE PROCEDURE"_sptok >>
39464ab3302SCarolineConcatto                     pure(ProcedureStmt::Kind::ModuleProcedure),
39564ab3302SCarolineConcatto                 maybe("::"_tok) >> specificProcedures) ||
39664ab3302SCarolineConcatto     construct<ProcedureStmt>(
39764ab3302SCarolineConcatto         "PROCEDURE" >> pure(ProcedureStmt::Kind::Procedure),
39864ab3302SCarolineConcatto         maybe("::"_tok) >> specificProcedures))
39964ab3302SCarolineConcatto 
40064ab3302SCarolineConcatto // R1508 generic-spec ->
40164ab3302SCarolineConcatto //         generic-name | OPERATOR ( defined-operator ) |
40264ab3302SCarolineConcatto //         ASSIGNMENT ( = ) | defined-io-generic-spec
40364ab3302SCarolineConcatto // R1509 defined-io-generic-spec ->
40464ab3302SCarolineConcatto //         READ ( FORMATTED ) | READ ( UNFORMATTED ) |
40564ab3302SCarolineConcatto //         WRITE ( FORMATTED ) | WRITE ( UNFORMATTED )
40664ab3302SCarolineConcatto TYPE_PARSER(sourced(first(construct<GenericSpec>("OPERATOR" >>
40764ab3302SCarolineConcatto                               parenthesized(Parser<DefinedOperator>{})),
40864ab3302SCarolineConcatto     construct<GenericSpec>(
40964ab3302SCarolineConcatto         construct<GenericSpec::Assignment>("ASSIGNMENT ( = )"_tok)),
41064ab3302SCarolineConcatto     construct<GenericSpec>(
41164ab3302SCarolineConcatto         construct<GenericSpec::ReadFormatted>("READ ( FORMATTED )"_tok)),
41264ab3302SCarolineConcatto     construct<GenericSpec>(
41364ab3302SCarolineConcatto         construct<GenericSpec::ReadUnformatted>("READ ( UNFORMATTED )"_tok)),
41464ab3302SCarolineConcatto     construct<GenericSpec>(
41564ab3302SCarolineConcatto         construct<GenericSpec::WriteFormatted>("WRITE ( FORMATTED )"_tok)),
41664ab3302SCarolineConcatto     construct<GenericSpec>(
41764ab3302SCarolineConcatto         construct<GenericSpec::WriteUnformatted>("WRITE ( UNFORMATTED )"_tok)),
41864ab3302SCarolineConcatto     construct<GenericSpec>(name))))
41964ab3302SCarolineConcatto 
42064ab3302SCarolineConcatto // R1510 generic-stmt ->
42164ab3302SCarolineConcatto //         GENERIC [, access-spec] :: generic-spec => specific-procedure-list
42264ab3302SCarolineConcatto TYPE_PARSER(construct<GenericStmt>("GENERIC" >> maybe("," >> accessSpec),
42364ab3302SCarolineConcatto     "::" >> genericSpec, "=>" >> specificProcedures))
42464ab3302SCarolineConcatto 
42564ab3302SCarolineConcatto // R1511 external-stmt -> EXTERNAL [::] external-name-list
42664ab3302SCarolineConcatto TYPE_PARSER(
42764ab3302SCarolineConcatto     "EXTERNAL" >> maybe("::"_tok) >> construct<ExternalStmt>(listOfNames))
42864ab3302SCarolineConcatto 
42964ab3302SCarolineConcatto // R1512 procedure-declaration-stmt ->
43064ab3302SCarolineConcatto //         PROCEDURE ( [proc-interface] ) [[, proc-attr-spec]... ::]
43164ab3302SCarolineConcatto //         proc-decl-list
43264ab3302SCarolineConcatto TYPE_PARSER("PROCEDURE" >>
43364ab3302SCarolineConcatto     construct<ProcedureDeclarationStmt>(parenthesized(maybe(procInterface)),
43464ab3302SCarolineConcatto         optionalListBeforeColons(Parser<ProcAttrSpec>{}),
43564ab3302SCarolineConcatto         nonemptyList("expected procedure declarations"_err_en_US, procDecl)))
43664ab3302SCarolineConcatto 
43764ab3302SCarolineConcatto // R1513 proc-interface -> interface-name | declaration-type-spec
43864ab3302SCarolineConcatto // R1516 interface-name -> name
43964ab3302SCarolineConcatto // N.B. Simple names of intrinsic types (e.g., "REAL") are not
44064ab3302SCarolineConcatto // ambiguous here - they take precedence over derived type names
44164ab3302SCarolineConcatto // thanks to C1516.
44264ab3302SCarolineConcatto TYPE_PARSER(
44364ab3302SCarolineConcatto     construct<ProcInterface>(declarationTypeSpec / lookAhead(")"_tok)) ||
44464ab3302SCarolineConcatto     construct<ProcInterface>(name))
44564ab3302SCarolineConcatto 
44664ab3302SCarolineConcatto // R1514 proc-attr-spec ->
44764ab3302SCarolineConcatto //         access-spec | proc-language-binding-spec | INTENT ( intent-spec ) |
44864ab3302SCarolineConcatto //         OPTIONAL | POINTER | PROTECTED | SAVE
44964ab3302SCarolineConcatto TYPE_PARSER(construct<ProcAttrSpec>(accessSpec) ||
45064ab3302SCarolineConcatto     construct<ProcAttrSpec>(languageBindingSpec) ||
45164ab3302SCarolineConcatto     construct<ProcAttrSpec>("INTENT" >> parenthesized(intentSpec)) ||
45264ab3302SCarolineConcatto     construct<ProcAttrSpec>(optional) || construct<ProcAttrSpec>(pointer) ||
45364ab3302SCarolineConcatto     construct<ProcAttrSpec>(protectedAttr) || construct<ProcAttrSpec>(save))
45464ab3302SCarolineConcatto 
45564ab3302SCarolineConcatto // R1515 proc-decl -> procedure-entity-name [=> proc-pointer-init]
45664ab3302SCarolineConcatto TYPE_PARSER(construct<ProcDecl>(name, maybe("=>" >> Parser<ProcPointerInit>{})))
45764ab3302SCarolineConcatto 
45864ab3302SCarolineConcatto // R1517 proc-pointer-init -> null-init | initial-proc-target
45964ab3302SCarolineConcatto // R1518 initial-proc-target -> procedure-name
46064ab3302SCarolineConcatto TYPE_PARSER(
46164ab3302SCarolineConcatto     construct<ProcPointerInit>(nullInit) || construct<ProcPointerInit>(name))
46264ab3302SCarolineConcatto 
46364ab3302SCarolineConcatto // R1519 intrinsic-stmt -> INTRINSIC [::] intrinsic-procedure-name-list
46464ab3302SCarolineConcatto TYPE_PARSER(
46564ab3302SCarolineConcatto     "INTRINSIC" >> maybe("::"_tok) >> construct<IntrinsicStmt>(listOfNames))
46664ab3302SCarolineConcatto 
4674ad72793SPeter Klausler // R1520 function-reference -> procedure-designator
4684ad72793SPeter Klausler //                               ( [actual-arg-spec-list] )
46964ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("function reference"_en_US,
4704ad72793SPeter Klausler     sourced(construct<FunctionReference>(
4714ad72793SPeter Klausler         construct<Call>(Parser<ProcedureDesignator>{},
47264ab3302SCarolineConcatto             parenthesized(optionalList(actualArgSpec))))) /
47364ab3302SCarolineConcatto         !"["_tok)
47464ab3302SCarolineConcatto 
4754ad72793SPeter Klausler // R1521 call-stmt -> CALL procedure-designator [chevrons]
4764ad72793SPeter Klausler ///                          [( [actual-arg-spec-list] )]
477*fe5a64d1SValentin Clement (バレンタイン クレメン) // (CUDA) chevrons -> <<< * | scalar-expr, scalar-expr [, scalar-int-expr
4784ad72793SPeter Klausler //                      [, scalar-int-expr ] ] >>>
479*fe5a64d1SValentin Clement (バレンタイン クレメン) constexpr auto starOrExpr{
480*fe5a64d1SValentin Clement (バレンタイン クレメン)     construct<CallStmt::StarOrExpr>("*" >> pure<std::optional<ScalarExpr>>() ||
481*fe5a64d1SValentin Clement (バレンタイン クレメン)         applyFunction(presentOptional<ScalarExpr>, scalarExpr))};
4824ad72793SPeter Klausler TYPE_PARSER(extension<LanguageFeature::CUDA>(
483*fe5a64d1SValentin Clement (バレンタイン クレメン)     "<<<" >> construct<CallStmt::Chevrons>(starOrExpr, ", " >> scalarExpr,
4844ad72793SPeter Klausler                  maybe("," >> scalarIntExpr), maybe("," >> scalarIntExpr)) /
4854ad72793SPeter Klausler         ">>>"))
486010c55bfSPeter Klausler constexpr auto actualArgSpecList{optionalList(actualArgSpec)};
487010c55bfSPeter Klausler TYPE_CONTEXT_PARSER("CALL statement"_en_US,
488010c55bfSPeter Klausler     construct<CallStmt>(
4894ad72793SPeter Klausler         sourced(construct<CallStmt>("CALL" >> Parser<ProcedureDesignator>{},
490010c55bfSPeter Klausler             maybe(Parser<CallStmt::Chevrons>{}) / space,
491010c55bfSPeter Klausler             "(" >> actualArgSpecList / ")" ||
492010c55bfSPeter Klausler                 lookAhead(endOfStmt) >> defaulted(actualArgSpecList)))))
49364ab3302SCarolineConcatto 
49464ab3302SCarolineConcatto // R1522 procedure-designator ->
49564ab3302SCarolineConcatto //         procedure-name | proc-component-ref | data-ref % binding-name
49664ab3302SCarolineConcatto TYPE_PARSER(construct<ProcedureDesignator>(Parser<ProcComponentRef>{}) ||
49764ab3302SCarolineConcatto     construct<ProcedureDesignator>(name))
49864ab3302SCarolineConcatto 
49964ab3302SCarolineConcatto // R1523 actual-arg-spec -> [keyword =] actual-arg
50064ab3302SCarolineConcatto TYPE_PARSER(construct<ActualArgSpec>(
50164ab3302SCarolineConcatto     maybe(keyword / "=" / !"="_ch), Parser<ActualArg>{}))
50264ab3302SCarolineConcatto 
50364ab3302SCarolineConcatto // R1524 actual-arg ->
50464ab3302SCarolineConcatto //         expr | variable | procedure-name | proc-component-ref |
50564ab3302SCarolineConcatto //         alt-return-spec
50664ab3302SCarolineConcatto // N.B. the "procedure-name" and "proc-component-ref" alternatives can't
50764ab3302SCarolineConcatto // yet be distinguished from "variable", many instances of which can't be
50864ab3302SCarolineConcatto // distinguished from "expr" anyway (to do so would misparse structure
50964ab3302SCarolineConcatto // constructors and function calls as array elements).
51064ab3302SCarolineConcatto // Semantics sorts it all out later.
51164ab3302SCarolineConcatto TYPE_PARSER(construct<ActualArg>(expr) ||
51264ab3302SCarolineConcatto     construct<ActualArg>(Parser<AltReturnSpec>{}) ||
5132d8b6a47SPeter Klausler     extension<LanguageFeature::PercentRefAndVal>(
5142d8b6a47SPeter Klausler         "nonstandard usage: %REF"_port_en_US,
515930c2d91SPeter Klausler         construct<ActualArg>(
516930c2d91SPeter Klausler             construct<ActualArg::PercentRef>("%REF" >> parenthesized(expr)))) ||
5172d8b6a47SPeter Klausler     extension<LanguageFeature::PercentRefAndVal>(
5182d8b6a47SPeter Klausler         "nonstandard usage: %VAL"_port_en_US,
5192d8b6a47SPeter Klausler         construct<ActualArg>(
52064ab3302SCarolineConcatto             construct<ActualArg::PercentVal>("%VAL" >> parenthesized(expr)))))
52164ab3302SCarolineConcatto 
52264ab3302SCarolineConcatto // R1525 alt-return-spec -> * label
52364ab3302SCarolineConcatto TYPE_PARSER(construct<AltReturnSpec>(star >> label))
52464ab3302SCarolineConcatto 
52564ab3302SCarolineConcatto // R1527 prefix-spec ->
52664ab3302SCarolineConcatto //         declaration-type-spec | ELEMENTAL | IMPURE | MODULE |
5274ad72793SPeter Klausler //         NON_RECURSIVE | PURE | RECURSIVE |
5284ad72793SPeter Klausler // (CUDA)  ATTRIBUTES ( (DEVICE | GLOBAL | GRID_GLOBAL | HOST)... ) |
5294ad72793SPeter Klausler //         LAUNCH_BOUNDS(expr-list) | CLUSTER_DIMS(expr-list)
5304ad72793SPeter Klausler TYPE_PARSER(first("DEVICE" >> pure(common::CUDASubprogramAttrs::Device),
5314ad72793SPeter Klausler     "GLOBAL" >> pure(common::CUDASubprogramAttrs::Global),
5324ad72793SPeter Klausler     "GRID_GLOBAL" >> pure(common::CUDASubprogramAttrs::Grid_Global),
5334ad72793SPeter Klausler     "HOST" >> pure(common::CUDASubprogramAttrs::Host)))
53464ab3302SCarolineConcatto TYPE_PARSER(first(construct<PrefixSpec>(declarationTypeSpec),
53564ab3302SCarolineConcatto     construct<PrefixSpec>(construct<PrefixSpec::Elemental>("ELEMENTAL"_tok)),
53664ab3302SCarolineConcatto     construct<PrefixSpec>(construct<PrefixSpec::Impure>("IMPURE"_tok)),
53764ab3302SCarolineConcatto     construct<PrefixSpec>(construct<PrefixSpec::Module>("MODULE"_tok)),
53864ab3302SCarolineConcatto     construct<PrefixSpec>(
53964ab3302SCarolineConcatto         construct<PrefixSpec::Non_Recursive>("NON_RECURSIVE"_tok)),
54064ab3302SCarolineConcatto     construct<PrefixSpec>(construct<PrefixSpec::Pure>("PURE"_tok)),
5414ad72793SPeter Klausler     construct<PrefixSpec>(construct<PrefixSpec::Recursive>("RECURSIVE"_tok)),
5424ad72793SPeter Klausler     extension<LanguageFeature::CUDA>(
5434ad72793SPeter Klausler         construct<PrefixSpec>(construct<PrefixSpec::Attributes>("ATTRIBUTES" >>
5444ad72793SPeter Klausler             parenthesized(
5454ad72793SPeter Klausler                 optionalList(Parser<common::CUDASubprogramAttrs>{}))))),
5464ad72793SPeter Klausler     extension<LanguageFeature::CUDA>(construct<PrefixSpec>(
5474ad72793SPeter Klausler         construct<PrefixSpec::Launch_Bounds>("LAUNCH_BOUNDS" >>
5484ad72793SPeter Klausler             parenthesized(nonemptyList(
5494ad72793SPeter Klausler                 "expected launch bounds"_err_en_US, scalarIntConstantExpr))))),
5504ad72793SPeter Klausler     extension<LanguageFeature::CUDA>(construct<PrefixSpec>(
5514ad72793SPeter Klausler         construct<PrefixSpec::Cluster_Dims>("CLUSTER_DIMS" >>
5524ad72793SPeter Klausler             parenthesized(nonemptyList("expected cluster dimensions"_err_en_US,
5534ad72793SPeter Klausler                 scalarIntConstantExpr)))))))
55464ab3302SCarolineConcatto 
55564ab3302SCarolineConcatto // R1529 function-subprogram ->
55664ab3302SCarolineConcatto //         function-stmt [specification-part] [execution-part]
55764ab3302SCarolineConcatto //         [internal-subprogram-part] end-function-stmt
55864ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("FUNCTION subprogram"_en_US,
55964ab3302SCarolineConcatto     construct<FunctionSubprogram>(statement(functionStmt), specificationPart,
56064ab3302SCarolineConcatto         executionPart, maybe(internalSubprogramPart),
56164ab3302SCarolineConcatto         unterminatedStatement(endFunctionStmt)))
56264ab3302SCarolineConcatto 
56364ab3302SCarolineConcatto // R1532 suffix ->
56464ab3302SCarolineConcatto //         proc-language-binding-spec [RESULT ( result-name )] |
56564ab3302SCarolineConcatto //         RESULT ( result-name ) [proc-language-binding-spec]
56664ab3302SCarolineConcatto TYPE_PARSER(construct<Suffix>(
56764ab3302SCarolineConcatto                 languageBindingSpec, maybe("RESULT" >> parenthesized(name))) ||
56864ab3302SCarolineConcatto     construct<Suffix>(
56964ab3302SCarolineConcatto         "RESULT" >> parenthesized(name), maybe(languageBindingSpec)))
57064ab3302SCarolineConcatto 
57164ab3302SCarolineConcatto // R1533 end-function-stmt -> END [FUNCTION [function-name]]
572b5aea329SPeter Klausler TYPE_PARSER(construct<EndFunctionStmt>(
573b5aea329SPeter Klausler     recovery("END" >> defaulted("FUNCTION" >> maybe(name)) / atEndOfStmt,
574b5aea329SPeter Klausler         progUnitEndStmtErrorRecovery)))
57564ab3302SCarolineConcatto 
57664ab3302SCarolineConcatto // R1534 subroutine-subprogram ->
57764ab3302SCarolineConcatto //         subroutine-stmt [specification-part] [execution-part]
57864ab3302SCarolineConcatto //         [internal-subprogram-part] end-subroutine-stmt
57964ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("SUBROUTINE subprogram"_en_US,
58064ab3302SCarolineConcatto     construct<SubroutineSubprogram>(statement(subroutineStmt),
58164ab3302SCarolineConcatto         specificationPart, executionPart, maybe(internalSubprogramPart),
58264ab3302SCarolineConcatto         unterminatedStatement(endSubroutineStmt)))
58364ab3302SCarolineConcatto 
58464ab3302SCarolineConcatto // R1535 subroutine-stmt ->
58564ab3302SCarolineConcatto //         [prefix] SUBROUTINE subroutine-name [( [dummy-arg-list] )
58664ab3302SCarolineConcatto //         [proc-language-binding-spec]]
58764ab3302SCarolineConcatto TYPE_PARSER(
58899a0a12aSPeter Klausler     (construct<SubroutineStmt>(many(prefixSpec), "SUBROUTINE" >> name,
58999a0a12aSPeter Klausler          !"("_tok >> pure<std::list<DummyArg>>(),
59099a0a12aSPeter Klausler          pure<std::optional<LanguageBindingSpec>>()) ||
59164ab3302SCarolineConcatto         construct<SubroutineStmt>(many(prefixSpec), "SUBROUTINE" >> name,
59299a0a12aSPeter Klausler             defaulted(parenthesized(optionalList(dummyArg))),
59399a0a12aSPeter Klausler             maybe(languageBindingSpec))) /
59499a0a12aSPeter Klausler     checkEndOfKnownStmt)
59564ab3302SCarolineConcatto 
59664ab3302SCarolineConcatto // R1536 dummy-arg -> dummy-arg-name | *
59764ab3302SCarolineConcatto TYPE_PARSER(construct<DummyArg>(name) || construct<DummyArg>(star))
59864ab3302SCarolineConcatto 
59964ab3302SCarolineConcatto // R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]]
600b5aea329SPeter Klausler TYPE_PARSER(construct<EndSubroutineStmt>(
601b5aea329SPeter Klausler     recovery("END" >> defaulted("SUBROUTINE" >> maybe(name)) / atEndOfStmt,
602b5aea329SPeter Klausler         progUnitEndStmtErrorRecovery)))
60364ab3302SCarolineConcatto 
60464ab3302SCarolineConcatto // R1538 separate-module-subprogram ->
60564ab3302SCarolineConcatto //         mp-subprogram-stmt [specification-part] [execution-part]
60664ab3302SCarolineConcatto //         [internal-subprogram-part] end-mp-subprogram-stmt
60764ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("separate module subprogram"_en_US,
60864ab3302SCarolineConcatto     construct<SeparateModuleSubprogram>(statement(Parser<MpSubprogramStmt>{}),
60964ab3302SCarolineConcatto         specificationPart, executionPart, maybe(internalSubprogramPart),
61064ab3302SCarolineConcatto         statement(Parser<EndMpSubprogramStmt>{})))
61164ab3302SCarolineConcatto 
61264ab3302SCarolineConcatto // R1539 mp-subprogram-stmt -> MODULE PROCEDURE procedure-name
61364ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("MODULE PROCEDURE statement"_en_US,
61464ab3302SCarolineConcatto     construct<MpSubprogramStmt>("MODULE PROCEDURE"_sptok >> name))
61564ab3302SCarolineConcatto 
61664ab3302SCarolineConcatto // R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]]
61764ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END PROCEDURE statement"_en_US,
61864ab3302SCarolineConcatto     construct<EndMpSubprogramStmt>(
619b5aea329SPeter Klausler         recovery("END" >> defaulted("PROCEDURE" >> maybe(name)) / atEndOfStmt,
62064ab3302SCarolineConcatto             progUnitEndStmtErrorRecovery)))
62164ab3302SCarolineConcatto 
62264ab3302SCarolineConcatto // R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]]
62364ab3302SCarolineConcatto TYPE_PARSER(
62464ab3302SCarolineConcatto     "ENTRY" >> (construct<EntryStmt>(name,
62564ab3302SCarolineConcatto                     parenthesized(optionalList(dummyArg)), maybe(suffix)) ||
62664ab3302SCarolineConcatto                    construct<EntryStmt>(name, construct<std::list<DummyArg>>(),
62764ab3302SCarolineConcatto                        construct<std::optional<Suffix>>())))
62864ab3302SCarolineConcatto 
62964ab3302SCarolineConcatto // R1542 return-stmt -> RETURN [scalar-int-expr]
63064ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("RETURN statement"_en_US,
63164ab3302SCarolineConcatto     construct<ReturnStmt>("RETURN" >> maybe(scalarIntExpr)))
63264ab3302SCarolineConcatto 
63364ab3302SCarolineConcatto // R1543 contains-stmt -> CONTAINS
63464ab3302SCarolineConcatto TYPE_PARSER(construct<ContainsStmt>("CONTAINS"_tok))
63564ab3302SCarolineConcatto 
63664ab3302SCarolineConcatto // R1544 stmt-function-stmt ->
63764ab3302SCarolineConcatto //         function-name ( [dummy-arg-name-list] ) = scalar-expr
63864ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("statement function definition"_en_US,
63964ab3302SCarolineConcatto     construct<StmtFunctionStmt>(
64064ab3302SCarolineConcatto         name, parenthesized(optionalList(name)), "=" >> scalar(expr)))
6411f879005STim Keith } // namespace Fortran::parser
642