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 "debug-parser.h"
1364ab3302SCarolineConcatto #include "expr-parsers.h"
1464ab3302SCarolineConcatto #include "misc-parsers.h"
1564ab3302SCarolineConcatto #include "stmt-parser.h"
1664ab3302SCarolineConcatto #include "token-parsers.h"
1764ab3302SCarolineConcatto #include "type-parser-implementation.h"
1864ab3302SCarolineConcatto #include "flang/Parser/characters.h"
1964ab3302SCarolineConcatto #include "flang/Parser/parse-tree.h"
2064ab3302SCarolineConcatto
2164ab3302SCarolineConcatto namespace Fortran::parser {
2264ab3302SCarolineConcatto
2364ab3302SCarolineConcatto // R502 program-unit ->
2464ab3302SCarolineConcatto // main-program | external-subprogram | module | submodule | block-data
2564ab3302SCarolineConcatto // R503 external-subprogram -> function-subprogram | subroutine-subprogram
2664ab3302SCarolineConcatto // N.B. "module" must precede "external-subprogram" in this sequence of
2764ab3302SCarolineConcatto // alternatives to avoid ambiguity with the MODULE keyword prefix that
2864ab3302SCarolineConcatto // they recognize. I.e., "modulesubroutinefoo" should start a module
2964ab3302SCarolineConcatto // "subroutinefoo", not a subroutine "foo" with the MODULE prefix. The
3064ab3302SCarolineConcatto // ambiguity is exacerbated by the extension that accepts a function
3164ab3302SCarolineConcatto // statement without an otherwise empty list of dummy arguments. That
3264ab3302SCarolineConcatto // MODULE prefix is disallowed by a constraint (C1547) in this context,
3364ab3302SCarolineConcatto // so the standard language is not ambiguous, but disabling its misrecognition
3464ab3302SCarolineConcatto // here would require context-sensitive keyword recognition or (or via)
3564ab3302SCarolineConcatto // variant parsers for several productions; giving the "module" production
3664ab3302SCarolineConcatto // priority here is a cleaner solution, though regrettably subtle. Enforcing
3764ab3302SCarolineConcatto // C1547 is done in semantics.
3813cee14bSpeter klausler static constexpr auto programUnit{
3913cee14bSpeter klausler construct<ProgramUnit>(indirect(Parser<Module>{})) ||
4064ab3302SCarolineConcatto construct<ProgramUnit>(indirect(functionSubprogram)) ||
4164ab3302SCarolineConcatto construct<ProgramUnit>(indirect(subroutineSubprogram)) ||
4264ab3302SCarolineConcatto construct<ProgramUnit>(indirect(Parser<Submodule>{})) ||
4364ab3302SCarolineConcatto construct<ProgramUnit>(indirect(Parser<BlockData>{})) ||
4413cee14bSpeter klausler construct<ProgramUnit>(indirect(Parser<MainProgram>{}))};
4513cee14bSpeter klausler static constexpr auto normalProgramUnit{StartNewSubprogram{} >> programUnit /
4613cee14bSpeter klausler skipMany(";"_tok) / space / recovery(endOfLine, SkipPast<'\n'>{})};
4713cee14bSpeter klausler static constexpr auto globalCompilerDirective{
4813cee14bSpeter klausler construct<ProgramUnit>(indirect(compilerDirective))};
4913cee14bSpeter klausler
5013cee14bSpeter klausler // R501 program -> program-unit [program-unit]...
5113cee14bSpeter klausler // This is the top-level production for the Fortran language.
5213cee14bSpeter klausler // F'2018 6.3.1 defines a program unit as a sequence of one or more lines,
5313cee14bSpeter klausler // implying that a line can't be part of two distinct program units.
5413cee14bSpeter klausler // Consequently, a program unit END statement should be the last statement
5513cee14bSpeter klausler // on its line. We parse those END statements via unterminatedStatement()
5613cee14bSpeter klausler // and then skip over the end of the line here.
57*2d8b6a47SPeter Klausler TYPE_PARSER(
58*2d8b6a47SPeter Klausler construct<Program>(extension<LanguageFeature::EmptySourceFile>(
59*2d8b6a47SPeter Klausler "nonstandard usage: empty source file"_port_en_US,
60*2d8b6a47SPeter Klausler skipStuffBeforeStatement >> !nextCh >>
61*2d8b6a47SPeter Klausler pure<std::list<ProgramUnit>>()) ||
6213cee14bSpeter klausler some(globalCompilerDirective || normalProgramUnit) /
6313cee14bSpeter klausler skipStuffBeforeStatement))
6464ab3302SCarolineConcatto
6564ab3302SCarolineConcatto // R504 specification-part ->
6664ab3302SCarolineConcatto // [use-stmt]... [import-stmt]... [implicit-part]
6764ab3302SCarolineConcatto // [declaration-construct]...
6864ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("specification part"_en_US,
690a90ffa7SValentin Clement construct<SpecificationPart>(many(openaccDeclarativeConstruct),
70cf715717STim Keith many(openmpDeclarativeConstruct), many(indirect(compilerDirective)),
7164ab3302SCarolineConcatto many(statement(indirect(Parser<UseStmt>{}))),
7264ab3302SCarolineConcatto many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
7364ab3302SCarolineConcatto implicitPart, many(declarationConstruct)))
7464ab3302SCarolineConcatto
7564ab3302SCarolineConcatto // R507 declaration-construct ->
7664ab3302SCarolineConcatto // specification-construct | data-stmt | format-stmt |
7764ab3302SCarolineConcatto // entry-stmt | stmt-function-stmt
7864ab3302SCarolineConcatto // N.B. These parsers incorporate recognition of some other statements that
7964ab3302SCarolineConcatto // may have been misplaced in the sequence of statements that are acceptable
8064ab3302SCarolineConcatto // as a specification part in order to improve error recovery.
8164ab3302SCarolineConcatto // Also note that many instances of specification-part in the standard grammar
8264ab3302SCarolineConcatto // are in contexts that impose constraints on the kinds of statements that
8364ab3302SCarolineConcatto // are allowed, and so we have a variant production for declaration-construct
8464ab3302SCarolineConcatto // that implements those constraints.
8505169af5SValentin Clement constexpr auto execPartLookAhead{
8605169af5SValentin Clement first(actionStmt >> ok, openaccConstruct >> ok, openmpConstruct >> ok,
8764ab3302SCarolineConcatto "ASSOCIATE ("_tok, "BLOCK"_tok, "SELECT"_tok, "CHANGE TEAM"_sptok,
8864ab3302SCarolineConcatto "CRITICAL"_tok, "DO"_tok, "IF ("_tok, "WHERE ("_tok, "FORALL ("_tok)};
8964ab3302SCarolineConcatto constexpr auto declErrorRecovery{
9064ab3302SCarolineConcatto stmtErrorRecoveryStart >> !execPartLookAhead >> skipStmtErrorRecovery};
9164ab3302SCarolineConcatto constexpr auto misplacedSpecificationStmt{Parser<UseStmt>{} >>
9264ab3302SCarolineConcatto fail<DeclarationConstruct>("misplaced USE statement"_err_en_US) ||
9364ab3302SCarolineConcatto Parser<ImportStmt>{} >>
9464ab3302SCarolineConcatto fail<DeclarationConstruct>(
9564ab3302SCarolineConcatto "IMPORT statements must follow any USE statements and precede all other declarations"_err_en_US) ||
9664ab3302SCarolineConcatto Parser<ImplicitStmt>{} >>
9764ab3302SCarolineConcatto fail<DeclarationConstruct>(
9864ab3302SCarolineConcatto "IMPLICIT statements must follow USE and IMPORT and precede all other declarations"_err_en_US)};
9964ab3302SCarolineConcatto
10064ab3302SCarolineConcatto TYPE_PARSER(recovery(
10164ab3302SCarolineConcatto withMessage("expected declaration construct"_err_en_US,
10264ab3302SCarolineConcatto CONTEXT_PARSER("declaration construct"_en_US,
10364ab3302SCarolineConcatto first(construct<DeclarationConstruct>(specificationConstruct),
10464ab3302SCarolineConcatto construct<DeclarationConstruct>(statement(indirect(dataStmt))),
10564ab3302SCarolineConcatto construct<DeclarationConstruct>(
10664ab3302SCarolineConcatto statement(indirect(formatStmt))),
10764ab3302SCarolineConcatto construct<DeclarationConstruct>(statement(indirect(entryStmt))),
10864ab3302SCarolineConcatto construct<DeclarationConstruct>(
10964ab3302SCarolineConcatto statement(indirect(Parser<StmtFunctionStmt>{}))),
11064ab3302SCarolineConcatto misplacedSpecificationStmt))),
11164ab3302SCarolineConcatto construct<DeclarationConstruct>(declErrorRecovery)))
11264ab3302SCarolineConcatto
11364ab3302SCarolineConcatto // R507 variant of declaration-construct for use in limitedSpecificationPart.
11464ab3302SCarolineConcatto constexpr auto invalidDeclarationStmt{formatStmt >>
11564ab3302SCarolineConcatto fail<DeclarationConstruct>(
11664ab3302SCarolineConcatto "FORMAT statements are not permitted in this specification part"_err_en_US) ||
11764ab3302SCarolineConcatto entryStmt >>
11864ab3302SCarolineConcatto fail<DeclarationConstruct>(
11964ab3302SCarolineConcatto "ENTRY statements are not permitted in this specification part"_err_en_US)};
12064ab3302SCarolineConcatto
12164ab3302SCarolineConcatto constexpr auto limitedDeclarationConstruct{recovery(
12264ab3302SCarolineConcatto withMessage("expected declaration construct"_err_en_US,
12364ab3302SCarolineConcatto inContext("declaration construct"_en_US,
12464ab3302SCarolineConcatto first(construct<DeclarationConstruct>(specificationConstruct),
12564ab3302SCarolineConcatto construct<DeclarationConstruct>(statement(indirect(dataStmt))),
12664ab3302SCarolineConcatto misplacedSpecificationStmt, invalidDeclarationStmt))),
12764ab3302SCarolineConcatto construct<DeclarationConstruct>(
12864ab3302SCarolineConcatto stmtErrorRecoveryStart >> skipStmtErrorRecovery))};
12964ab3302SCarolineConcatto
13064ab3302SCarolineConcatto // R504 variant for many contexts (modules, submodules, BLOCK DATA subprograms,
13164ab3302SCarolineConcatto // and interfaces) which have constraints on their specification parts that
13264ab3302SCarolineConcatto // preclude FORMAT, ENTRY, and statement functions, and benefit from
13364ab3302SCarolineConcatto // specialized error recovery in the event of a spurious executable
13464ab3302SCarolineConcatto // statement.
13564ab3302SCarolineConcatto constexpr auto limitedSpecificationPart{inContext("specification part"_en_US,
1360a90ffa7SValentin Clement construct<SpecificationPart>(many(openaccDeclarativeConstruct),
137cf715717STim Keith many(openmpDeclarativeConstruct), many(indirect(compilerDirective)),
13864ab3302SCarolineConcatto many(statement(indirect(Parser<UseStmt>{}))),
13964ab3302SCarolineConcatto many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
14064ab3302SCarolineConcatto implicitPart, many(limitedDeclarationConstruct)))};
14164ab3302SCarolineConcatto
14264ab3302SCarolineConcatto // R508 specification-construct ->
14364ab3302SCarolineConcatto // derived-type-def | enum-def | generic-stmt | interface-block |
14464ab3302SCarolineConcatto // parameter-stmt | procedure-declaration-stmt |
14564ab3302SCarolineConcatto // other-specification-stmt | type-declaration-stmt
14664ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("specification construct"_en_US,
14764ab3302SCarolineConcatto first(construct<SpecificationConstruct>(indirect(Parser<DerivedTypeDef>{})),
14864ab3302SCarolineConcatto construct<SpecificationConstruct>(indirect(Parser<EnumDef>{})),
14964ab3302SCarolineConcatto construct<SpecificationConstruct>(
15064ab3302SCarolineConcatto statement(indirect(Parser<GenericStmt>{}))),
15164ab3302SCarolineConcatto construct<SpecificationConstruct>(indirect(interfaceBlock)),
15264ab3302SCarolineConcatto construct<SpecificationConstruct>(statement(indirect(parameterStmt))),
15364ab3302SCarolineConcatto construct<SpecificationConstruct>(
15464ab3302SCarolineConcatto statement(indirect(oldParameterStmt))),
15564ab3302SCarolineConcatto construct<SpecificationConstruct>(
15664ab3302SCarolineConcatto statement(indirect(Parser<ProcedureDeclarationStmt>{}))),
15764ab3302SCarolineConcatto construct<SpecificationConstruct>(
15864ab3302SCarolineConcatto statement(Parser<OtherSpecificationStmt>{})),
15964ab3302SCarolineConcatto construct<SpecificationConstruct>(
16064ab3302SCarolineConcatto statement(indirect(typeDeclarationStmt))),
16164ab3302SCarolineConcatto construct<SpecificationConstruct>(indirect(Parser<StructureDef>{})),
1620a90ffa7SValentin Clement construct<SpecificationConstruct>(
1630a90ffa7SValentin Clement indirect(openaccDeclarativeConstruct)),
16464ab3302SCarolineConcatto construct<SpecificationConstruct>(indirect(openmpDeclarativeConstruct)),
16564ab3302SCarolineConcatto construct<SpecificationConstruct>(indirect(compilerDirective))))
16664ab3302SCarolineConcatto
16764ab3302SCarolineConcatto // R513 other-specification-stmt ->
16864ab3302SCarolineConcatto // access-stmt | allocatable-stmt | asynchronous-stmt | bind-stmt |
16964ab3302SCarolineConcatto // codimension-stmt | contiguous-stmt | dimension-stmt | external-stmt |
17064ab3302SCarolineConcatto // intent-stmt | intrinsic-stmt | namelist-stmt | optional-stmt |
17164ab3302SCarolineConcatto // pointer-stmt | protected-stmt | save-stmt | target-stmt |
17264ab3302SCarolineConcatto // volatile-stmt | value-stmt | common-stmt | equivalence-stmt
TYPE_PARSER(first (construct<OtherSpecificationStmt> (indirect (Parser<AccessStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<AllocatableStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<AsynchronousStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<BindStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<CodimensionStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<ContiguousStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<DimensionStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<ExternalStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<IntentStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<IntrinsicStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<NamelistStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<OptionalStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<PointerStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<ProtectedStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<SaveStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<TargetStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<ValueStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<VolatileStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<CommonStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<EquivalenceStmt>{})),construct<OtherSpecificationStmt> (indirect (Parser<BasedPointerStmt>{}))))17364ab3302SCarolineConcatto TYPE_PARSER(first(
17464ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<AccessStmt>{})),
17564ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<AllocatableStmt>{})),
17664ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<AsynchronousStmt>{})),
17764ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<BindStmt>{})),
17864ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<CodimensionStmt>{})),
17964ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<ContiguousStmt>{})),
18064ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<DimensionStmt>{})),
18164ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<ExternalStmt>{})),
18264ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<IntentStmt>{})),
18364ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<IntrinsicStmt>{})),
18464ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<NamelistStmt>{})),
18564ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<OptionalStmt>{})),
18664ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<PointerStmt>{})),
18764ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<ProtectedStmt>{})),
18864ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<SaveStmt>{})),
18964ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<TargetStmt>{})),
19064ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<ValueStmt>{})),
19164ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<VolatileStmt>{})),
19264ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<CommonStmt>{})),
19364ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<EquivalenceStmt>{})),
19464ab3302SCarolineConcatto construct<OtherSpecificationStmt>(indirect(Parser<BasedPointerStmt>{}))))
19564ab3302SCarolineConcatto
19664ab3302SCarolineConcatto // R1401 main-program ->
19764ab3302SCarolineConcatto // [program-stmt] [specification-part] [execution-part]
19864ab3302SCarolineConcatto // [internal-subprogram-part] end-program-stmt
19964ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("main program"_en_US,
20064ab3302SCarolineConcatto construct<MainProgram>(maybe(statement(Parser<ProgramStmt>{})),
20164ab3302SCarolineConcatto specificationPart, executionPart, maybe(internalSubprogramPart),
20264ab3302SCarolineConcatto unterminatedStatement(Parser<EndProgramStmt>{})))
20364ab3302SCarolineConcatto
20464ab3302SCarolineConcatto // R1402 program-stmt -> PROGRAM program-name
20564ab3302SCarolineConcatto // PGI allows empty parentheses after the name.
20664ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("PROGRAM statement"_en_US,
20764ab3302SCarolineConcatto construct<ProgramStmt>("PROGRAM" >> name /
20864ab3302SCarolineConcatto maybe(extension<LanguageFeature::ProgramParentheses>(
209*2d8b6a47SPeter Klausler "nonstandard usage: parentheses in PROGRAM statement"_port_en_US,
21064ab3302SCarolineConcatto parenthesized(ok)))))
21164ab3302SCarolineConcatto
21264ab3302SCarolineConcatto // R1403 end-program-stmt -> END [PROGRAM [program-name]]
21364ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END PROGRAM statement"_en_US,
21464ab3302SCarolineConcatto construct<EndProgramStmt>(recovery(
21564ab3302SCarolineConcatto "END PROGRAM" >> maybe(name) || bareEnd, progUnitEndStmtErrorRecovery)))
21664ab3302SCarolineConcatto
21764ab3302SCarolineConcatto // R1404 module ->
21864ab3302SCarolineConcatto // module-stmt [specification-part] [module-subprogram-part]
21964ab3302SCarolineConcatto // end-module-stmt
22064ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("module"_en_US,
22164ab3302SCarolineConcatto construct<Module>(statement(Parser<ModuleStmt>{}), limitedSpecificationPart,
22264ab3302SCarolineConcatto maybe(Parser<ModuleSubprogramPart>{}),
22364ab3302SCarolineConcatto unterminatedStatement(Parser<EndModuleStmt>{})))
22464ab3302SCarolineConcatto
22564ab3302SCarolineConcatto // R1405 module-stmt -> MODULE module-name
22664ab3302SCarolineConcatto TYPE_CONTEXT_PARSER(
22764ab3302SCarolineConcatto "MODULE statement"_en_US, construct<ModuleStmt>("MODULE" >> name))
22864ab3302SCarolineConcatto
22964ab3302SCarolineConcatto // R1406 end-module-stmt -> END [MODULE [module-name]]
23064ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END MODULE statement"_en_US,
23164ab3302SCarolineConcatto construct<EndModuleStmt>(recovery(
23264ab3302SCarolineConcatto "END MODULE" >> maybe(name) || bareEnd, progUnitEndStmtErrorRecovery)))
23364ab3302SCarolineConcatto
23464ab3302SCarolineConcatto // R1407 module-subprogram-part -> contains-stmt [module-subprogram]...
23564ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("module subprogram part"_en_US,
23664ab3302SCarolineConcatto construct<ModuleSubprogramPart>(statement(containsStmt),
23764ab3302SCarolineConcatto many(StartNewSubprogram{} >> Parser<ModuleSubprogram>{})))
23864ab3302SCarolineConcatto
23964ab3302SCarolineConcatto // R1408 module-subprogram ->
24064ab3302SCarolineConcatto // function-subprogram | subroutine-subprogram |
24164ab3302SCarolineConcatto // separate-module-subprogram
24264ab3302SCarolineConcatto TYPE_PARSER(construct<ModuleSubprogram>(indirect(functionSubprogram)) ||
24364ab3302SCarolineConcatto construct<ModuleSubprogram>(indirect(subroutineSubprogram)) ||
24464ab3302SCarolineConcatto construct<ModuleSubprogram>(indirect(Parser<SeparateModuleSubprogram>{})))
24564ab3302SCarolineConcatto
24664ab3302SCarolineConcatto // R1410 module-nature -> INTRINSIC | NON_INTRINSIC
24764ab3302SCarolineConcatto constexpr auto moduleNature{
24864ab3302SCarolineConcatto "INTRINSIC" >> pure(UseStmt::ModuleNature::Intrinsic) ||
24964ab3302SCarolineConcatto "NON_INTRINSIC" >> pure(UseStmt::ModuleNature::Non_Intrinsic)};
25064ab3302SCarolineConcatto
25164ab3302SCarolineConcatto // R1409 use-stmt ->
25264ab3302SCarolineConcatto // USE [[, module-nature] ::] module-name [, rename-list] |
25364ab3302SCarolineConcatto // USE [[, module-nature] ::] module-name , ONLY : [only-list]
25464ab3302SCarolineConcatto // N.B. Lookahead to the end of the statement is necessary to resolve
25564ab3302SCarolineConcatto // ambiguity with assignments and statement function definitions that
25664ab3302SCarolineConcatto // begin with the letters "USE".
25764ab3302SCarolineConcatto TYPE_PARSER(construct<UseStmt>("USE" >> optionalBeforeColons(moduleNature),
25864ab3302SCarolineConcatto name, ", ONLY :" >> optionalList(Parser<Only>{})) ||
25964ab3302SCarolineConcatto construct<UseStmt>("USE" >> optionalBeforeColons(moduleNature), name,
26064ab3302SCarolineConcatto defaulted("," >>
26164ab3302SCarolineConcatto nonemptyList("expected renamings"_err_en_US, Parser<Rename>{})) /
26264ab3302SCarolineConcatto lookAhead(endOfStmt)))
26364ab3302SCarolineConcatto
26464ab3302SCarolineConcatto // R1411 rename ->
26564ab3302SCarolineConcatto // local-name => use-name |
26664ab3302SCarolineConcatto // OPERATOR ( local-defined-operator ) =>
26764ab3302SCarolineConcatto // OPERATOR ( use-defined-operator )
26864ab3302SCarolineConcatto TYPE_PARSER(construct<Rename>("OPERATOR (" >>
26964ab3302SCarolineConcatto construct<Rename::Operators>(
27064ab3302SCarolineConcatto definedOpName / ") => OPERATOR (", definedOpName / ")")) ||
27164ab3302SCarolineConcatto construct<Rename>(construct<Rename::Names>(name, "=>" >> name)))
27264ab3302SCarolineConcatto
27364ab3302SCarolineConcatto // R1412 only -> generic-spec | only-use-name | rename
27464ab3302SCarolineConcatto // R1413 only-use-name -> use-name
2759a883bfaSpeter klausler // N.B. generic-spec and only-use-name are ambiguous; resolved with symbols
27664ab3302SCarolineConcatto TYPE_PARSER(construct<Only>(Parser<Rename>{}) ||
2779a883bfaSpeter klausler construct<Only>(indirect(genericSpec)) || construct<Only>(name))
27864ab3302SCarolineConcatto
27964ab3302SCarolineConcatto // R1416 submodule ->
28064ab3302SCarolineConcatto // submodule-stmt [specification-part] [module-subprogram-part]
28164ab3302SCarolineConcatto // end-submodule-stmt
28264ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("submodule"_en_US,
28364ab3302SCarolineConcatto construct<Submodule>(statement(Parser<SubmoduleStmt>{}),
28464ab3302SCarolineConcatto limitedSpecificationPart, maybe(Parser<ModuleSubprogramPart>{}),
28564ab3302SCarolineConcatto unterminatedStatement(Parser<EndSubmoduleStmt>{})))
28664ab3302SCarolineConcatto
28764ab3302SCarolineConcatto // R1417 submodule-stmt -> SUBMODULE ( parent-identifier ) submodule-name
28864ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("SUBMODULE statement"_en_US,
28964ab3302SCarolineConcatto construct<SubmoduleStmt>(
29064ab3302SCarolineConcatto "SUBMODULE" >> parenthesized(Parser<ParentIdentifier>{}), name))
29164ab3302SCarolineConcatto
29264ab3302SCarolineConcatto // R1418 parent-identifier -> ancestor-module-name [: parent-submodule-name]
29364ab3302SCarolineConcatto TYPE_PARSER(construct<ParentIdentifier>(name, maybe(":" >> name)))
29464ab3302SCarolineConcatto
29564ab3302SCarolineConcatto // R1419 end-submodule-stmt -> END [SUBMODULE [submodule-name]]
29664ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END SUBMODULE statement"_en_US,
29764ab3302SCarolineConcatto construct<EndSubmoduleStmt>(
29864ab3302SCarolineConcatto recovery("END SUBMODULE" >> maybe(name) || bareEnd,
29964ab3302SCarolineConcatto progUnitEndStmtErrorRecovery)))
30064ab3302SCarolineConcatto
30164ab3302SCarolineConcatto // R1420 block-data -> block-data-stmt [specification-part] end-block-data-stmt
30264ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("BLOCK DATA subprogram"_en_US,
30364ab3302SCarolineConcatto construct<BlockData>(statement(Parser<BlockDataStmt>{}),
30464ab3302SCarolineConcatto limitedSpecificationPart,
30564ab3302SCarolineConcatto unterminatedStatement(Parser<EndBlockDataStmt>{})))
30664ab3302SCarolineConcatto
30764ab3302SCarolineConcatto // R1421 block-data-stmt -> BLOCK DATA [block-data-name]
30864ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("BLOCK DATA statement"_en_US,
30964ab3302SCarolineConcatto construct<BlockDataStmt>("BLOCK DATA" >> maybe(name)))
31064ab3302SCarolineConcatto
31164ab3302SCarolineConcatto // R1422 end-block-data-stmt -> END [BLOCK DATA [block-data-name]]
31264ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END BLOCK DATA statement"_en_US,
31364ab3302SCarolineConcatto construct<EndBlockDataStmt>(
31464ab3302SCarolineConcatto recovery("END BLOCK DATA" >> maybe(name) || bareEnd,
31564ab3302SCarolineConcatto progUnitEndStmtErrorRecovery)))
31664ab3302SCarolineConcatto
31764ab3302SCarolineConcatto // R1501 interface-block ->
31864ab3302SCarolineConcatto // interface-stmt [interface-specification]... end-interface-stmt
TYPE_PARSER(construct<InterfaceBlock> (statement (Parser<InterfaceStmt>{}),many (Parser<InterfaceSpecification>{}),statement (Parser<EndInterfaceStmt>{})))31964ab3302SCarolineConcatto TYPE_PARSER(construct<InterfaceBlock>(statement(Parser<InterfaceStmt>{}),
32064ab3302SCarolineConcatto many(Parser<InterfaceSpecification>{}),
32164ab3302SCarolineConcatto statement(Parser<EndInterfaceStmt>{})))
32264ab3302SCarolineConcatto
32364ab3302SCarolineConcatto // R1502 interface-specification -> interface-body | procedure-stmt
32464ab3302SCarolineConcatto TYPE_PARSER(construct<InterfaceSpecification>(Parser<InterfaceBody>{}) ||
32564ab3302SCarolineConcatto construct<InterfaceSpecification>(statement(Parser<ProcedureStmt>{})))
32664ab3302SCarolineConcatto
32764ab3302SCarolineConcatto // R1503 interface-stmt -> INTERFACE [generic-spec] | ABSTRACT INTERFACE
32864ab3302SCarolineConcatto TYPE_PARSER(construct<InterfaceStmt>("INTERFACE" >> maybe(genericSpec)) ||
32964ab3302SCarolineConcatto construct<InterfaceStmt>(construct<Abstract>("ABSTRACT INTERFACE"_sptok)))
33064ab3302SCarolineConcatto
33164ab3302SCarolineConcatto // R1504 end-interface-stmt -> END INTERFACE [generic-spec]
33264ab3302SCarolineConcatto TYPE_PARSER(construct<EndInterfaceStmt>("END INTERFACE" >> maybe(genericSpec)))
33364ab3302SCarolineConcatto
33464ab3302SCarolineConcatto // R1505 interface-body ->
33564ab3302SCarolineConcatto // function-stmt [specification-part] end-function-stmt |
33664ab3302SCarolineConcatto // subroutine-stmt [specification-part] end-subroutine-stmt
33764ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("interface body"_en_US,
33864ab3302SCarolineConcatto construct<InterfaceBody>(
33964ab3302SCarolineConcatto construct<InterfaceBody::Function>(statement(functionStmt),
34064ab3302SCarolineConcatto indirect(limitedSpecificationPart), statement(endFunctionStmt))) ||
34164ab3302SCarolineConcatto construct<InterfaceBody>(construct<InterfaceBody::Subroutine>(
34264ab3302SCarolineConcatto statement(subroutineStmt), indirect(limitedSpecificationPart),
34364ab3302SCarolineConcatto statement(endSubroutineStmt))))
34464ab3302SCarolineConcatto
34564ab3302SCarolineConcatto // R1507 specific-procedure -> procedure-name
34664ab3302SCarolineConcatto constexpr auto specificProcedures{
34764ab3302SCarolineConcatto nonemptyList("expected specific procedure names"_err_en_US, name)};
34864ab3302SCarolineConcatto
34964ab3302SCarolineConcatto // R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list
35064ab3302SCarolineConcatto TYPE_PARSER(construct<ProcedureStmt>("MODULE PROCEDURE"_sptok >>
35164ab3302SCarolineConcatto pure(ProcedureStmt::Kind::ModuleProcedure),
35264ab3302SCarolineConcatto maybe("::"_tok) >> specificProcedures) ||
35364ab3302SCarolineConcatto construct<ProcedureStmt>(
35464ab3302SCarolineConcatto "PROCEDURE" >> pure(ProcedureStmt::Kind::Procedure),
35564ab3302SCarolineConcatto maybe("::"_tok) >> specificProcedures))
35664ab3302SCarolineConcatto
35764ab3302SCarolineConcatto // R1508 generic-spec ->
35864ab3302SCarolineConcatto // generic-name | OPERATOR ( defined-operator ) |
35964ab3302SCarolineConcatto // ASSIGNMENT ( = ) | defined-io-generic-spec
36064ab3302SCarolineConcatto // R1509 defined-io-generic-spec ->
36164ab3302SCarolineConcatto // READ ( FORMATTED ) | READ ( UNFORMATTED ) |
36264ab3302SCarolineConcatto // WRITE ( FORMATTED ) | WRITE ( UNFORMATTED )
36364ab3302SCarolineConcatto TYPE_PARSER(sourced(first(construct<GenericSpec>("OPERATOR" >>
36464ab3302SCarolineConcatto parenthesized(Parser<DefinedOperator>{})),
36564ab3302SCarolineConcatto construct<GenericSpec>(
36664ab3302SCarolineConcatto construct<GenericSpec::Assignment>("ASSIGNMENT ( = )"_tok)),
36764ab3302SCarolineConcatto construct<GenericSpec>(
36864ab3302SCarolineConcatto construct<GenericSpec::ReadFormatted>("READ ( FORMATTED )"_tok)),
36964ab3302SCarolineConcatto construct<GenericSpec>(
37064ab3302SCarolineConcatto construct<GenericSpec::ReadUnformatted>("READ ( UNFORMATTED )"_tok)),
37164ab3302SCarolineConcatto construct<GenericSpec>(
37264ab3302SCarolineConcatto construct<GenericSpec::WriteFormatted>("WRITE ( FORMATTED )"_tok)),
37364ab3302SCarolineConcatto construct<GenericSpec>(
37464ab3302SCarolineConcatto construct<GenericSpec::WriteUnformatted>("WRITE ( UNFORMATTED )"_tok)),
37564ab3302SCarolineConcatto construct<GenericSpec>(name))))
37664ab3302SCarolineConcatto
37764ab3302SCarolineConcatto // R1510 generic-stmt ->
37864ab3302SCarolineConcatto // GENERIC [, access-spec] :: generic-spec => specific-procedure-list
37964ab3302SCarolineConcatto TYPE_PARSER(construct<GenericStmt>("GENERIC" >> maybe("," >> accessSpec),
38064ab3302SCarolineConcatto "::" >> genericSpec, "=>" >> specificProcedures))
38164ab3302SCarolineConcatto
38264ab3302SCarolineConcatto // R1511 external-stmt -> EXTERNAL [::] external-name-list
38364ab3302SCarolineConcatto TYPE_PARSER(
38464ab3302SCarolineConcatto "EXTERNAL" >> maybe("::"_tok) >> construct<ExternalStmt>(listOfNames))
38564ab3302SCarolineConcatto
38664ab3302SCarolineConcatto // R1512 procedure-declaration-stmt ->
38764ab3302SCarolineConcatto // PROCEDURE ( [proc-interface] ) [[, proc-attr-spec]... ::]
38864ab3302SCarolineConcatto // proc-decl-list
38964ab3302SCarolineConcatto TYPE_PARSER("PROCEDURE" >>
39064ab3302SCarolineConcatto construct<ProcedureDeclarationStmt>(parenthesized(maybe(procInterface)),
39164ab3302SCarolineConcatto optionalListBeforeColons(Parser<ProcAttrSpec>{}),
39264ab3302SCarolineConcatto nonemptyList("expected procedure declarations"_err_en_US, procDecl)))
39364ab3302SCarolineConcatto
39464ab3302SCarolineConcatto // R1513 proc-interface -> interface-name | declaration-type-spec
39564ab3302SCarolineConcatto // R1516 interface-name -> name
39664ab3302SCarolineConcatto // N.B. Simple names of intrinsic types (e.g., "REAL") are not
39764ab3302SCarolineConcatto // ambiguous here - they take precedence over derived type names
39864ab3302SCarolineConcatto // thanks to C1516.
39964ab3302SCarolineConcatto TYPE_PARSER(
40064ab3302SCarolineConcatto construct<ProcInterface>(declarationTypeSpec / lookAhead(")"_tok)) ||
40164ab3302SCarolineConcatto construct<ProcInterface>(name))
40264ab3302SCarolineConcatto
40364ab3302SCarolineConcatto // R1514 proc-attr-spec ->
40464ab3302SCarolineConcatto // access-spec | proc-language-binding-spec | INTENT ( intent-spec ) |
40564ab3302SCarolineConcatto // OPTIONAL | POINTER | PROTECTED | SAVE
40664ab3302SCarolineConcatto TYPE_PARSER(construct<ProcAttrSpec>(accessSpec) ||
40764ab3302SCarolineConcatto construct<ProcAttrSpec>(languageBindingSpec) ||
40864ab3302SCarolineConcatto construct<ProcAttrSpec>("INTENT" >> parenthesized(intentSpec)) ||
40964ab3302SCarolineConcatto construct<ProcAttrSpec>(optional) || construct<ProcAttrSpec>(pointer) ||
41064ab3302SCarolineConcatto construct<ProcAttrSpec>(protectedAttr) || construct<ProcAttrSpec>(save))
41164ab3302SCarolineConcatto
41264ab3302SCarolineConcatto // R1515 proc-decl -> procedure-entity-name [=> proc-pointer-init]
41364ab3302SCarolineConcatto TYPE_PARSER(construct<ProcDecl>(name, maybe("=>" >> Parser<ProcPointerInit>{})))
41464ab3302SCarolineConcatto
41564ab3302SCarolineConcatto // R1517 proc-pointer-init -> null-init | initial-proc-target
41664ab3302SCarolineConcatto // R1518 initial-proc-target -> procedure-name
41764ab3302SCarolineConcatto TYPE_PARSER(
41864ab3302SCarolineConcatto construct<ProcPointerInit>(nullInit) || construct<ProcPointerInit>(name))
41964ab3302SCarolineConcatto
42064ab3302SCarolineConcatto // R1519 intrinsic-stmt -> INTRINSIC [::] intrinsic-procedure-name-list
42164ab3302SCarolineConcatto TYPE_PARSER(
42264ab3302SCarolineConcatto "INTRINSIC" >> maybe("::"_tok) >> construct<IntrinsicStmt>(listOfNames))
42364ab3302SCarolineConcatto
42464ab3302SCarolineConcatto // R1520 function-reference -> procedure-designator ( [actual-arg-spec-list] )
42564ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("function reference"_en_US,
42664ab3302SCarolineConcatto construct<FunctionReference>(
42764ab3302SCarolineConcatto sourced(construct<Call>(Parser<ProcedureDesignator>{},
42864ab3302SCarolineConcatto parenthesized(optionalList(actualArgSpec))))) /
42964ab3302SCarolineConcatto !"["_tok)
43064ab3302SCarolineConcatto
43164ab3302SCarolineConcatto // R1521 call-stmt -> CALL procedure-designator [( [actual-arg-spec-list] )]
43264ab3302SCarolineConcatto TYPE_PARSER(construct<CallStmt>(
43364ab3302SCarolineConcatto sourced(construct<Call>("CALL" >> Parser<ProcedureDesignator>{},
43464ab3302SCarolineConcatto defaulted(parenthesized(optionalList(actualArgSpec)))))))
43564ab3302SCarolineConcatto
43664ab3302SCarolineConcatto // R1522 procedure-designator ->
43764ab3302SCarolineConcatto // procedure-name | proc-component-ref | data-ref % binding-name
43864ab3302SCarolineConcatto TYPE_PARSER(construct<ProcedureDesignator>(Parser<ProcComponentRef>{}) ||
43964ab3302SCarolineConcatto construct<ProcedureDesignator>(name))
44064ab3302SCarolineConcatto
44164ab3302SCarolineConcatto // R1523 actual-arg-spec -> [keyword =] actual-arg
44264ab3302SCarolineConcatto TYPE_PARSER(construct<ActualArgSpec>(
44364ab3302SCarolineConcatto maybe(keyword / "=" / !"="_ch), Parser<ActualArg>{}))
44464ab3302SCarolineConcatto
44564ab3302SCarolineConcatto // R1524 actual-arg ->
44664ab3302SCarolineConcatto // expr | variable | procedure-name | proc-component-ref |
44764ab3302SCarolineConcatto // alt-return-spec
44864ab3302SCarolineConcatto // N.B. the "procedure-name" and "proc-component-ref" alternatives can't
44964ab3302SCarolineConcatto // yet be distinguished from "variable", many instances of which can't be
45064ab3302SCarolineConcatto // distinguished from "expr" anyway (to do so would misparse structure
45164ab3302SCarolineConcatto // constructors and function calls as array elements).
45264ab3302SCarolineConcatto // Semantics sorts it all out later.
45364ab3302SCarolineConcatto TYPE_PARSER(construct<ActualArg>(expr) ||
45464ab3302SCarolineConcatto construct<ActualArg>(Parser<AltReturnSpec>{}) ||
455*2d8b6a47SPeter Klausler extension<LanguageFeature::PercentRefAndVal>(
456*2d8b6a47SPeter Klausler "nonstandard usage: %REF"_port_en_US,
457*2d8b6a47SPeter Klausler construct<ActualArg>(construct<ActualArg::PercentRef>(
458*2d8b6a47SPeter Klausler "%REF" >> parenthesized(variable)))) ||
459*2d8b6a47SPeter Klausler extension<LanguageFeature::PercentRefAndVal>(
460*2d8b6a47SPeter Klausler "nonstandard usage: %VAL"_port_en_US,
461*2d8b6a47SPeter Klausler construct<ActualArg>(
46264ab3302SCarolineConcatto construct<ActualArg::PercentVal>("%VAL" >> parenthesized(expr)))))
46364ab3302SCarolineConcatto
46464ab3302SCarolineConcatto // R1525 alt-return-spec -> * label
46564ab3302SCarolineConcatto TYPE_PARSER(construct<AltReturnSpec>(star >> label))
46664ab3302SCarolineConcatto
46764ab3302SCarolineConcatto // R1527 prefix-spec ->
46864ab3302SCarolineConcatto // declaration-type-spec | ELEMENTAL | IMPURE | MODULE |
46964ab3302SCarolineConcatto // NON_RECURSIVE | PURE | RECURSIVE
47064ab3302SCarolineConcatto TYPE_PARSER(first(construct<PrefixSpec>(declarationTypeSpec),
47164ab3302SCarolineConcatto construct<PrefixSpec>(construct<PrefixSpec::Elemental>("ELEMENTAL"_tok)),
47264ab3302SCarolineConcatto construct<PrefixSpec>(construct<PrefixSpec::Impure>("IMPURE"_tok)),
47364ab3302SCarolineConcatto construct<PrefixSpec>(construct<PrefixSpec::Module>("MODULE"_tok)),
47464ab3302SCarolineConcatto construct<PrefixSpec>(
47564ab3302SCarolineConcatto construct<PrefixSpec::Non_Recursive>("NON_RECURSIVE"_tok)),
47664ab3302SCarolineConcatto construct<PrefixSpec>(construct<PrefixSpec::Pure>("PURE"_tok)),
47764ab3302SCarolineConcatto construct<PrefixSpec>(construct<PrefixSpec::Recursive>("RECURSIVE"_tok))))
47864ab3302SCarolineConcatto
47964ab3302SCarolineConcatto // R1529 function-subprogram ->
48064ab3302SCarolineConcatto // function-stmt [specification-part] [execution-part]
48164ab3302SCarolineConcatto // [internal-subprogram-part] end-function-stmt
48264ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("FUNCTION subprogram"_en_US,
48364ab3302SCarolineConcatto construct<FunctionSubprogram>(statement(functionStmt), specificationPart,
48464ab3302SCarolineConcatto executionPart, maybe(internalSubprogramPart),
48564ab3302SCarolineConcatto unterminatedStatement(endFunctionStmt)))
48664ab3302SCarolineConcatto
48764ab3302SCarolineConcatto // R1530 function-stmt ->
48864ab3302SCarolineConcatto // [prefix] FUNCTION function-name ( [dummy-arg-name-list] ) [suffix]
48964ab3302SCarolineConcatto // R1526 prefix -> prefix-spec [prefix-spec]...
49064ab3302SCarolineConcatto // R1531 dummy-arg-name -> name
49164ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("FUNCTION statement"_en_US,
49264ab3302SCarolineConcatto construct<FunctionStmt>(many(prefixSpec), "FUNCTION" >> name,
49364ab3302SCarolineConcatto parenthesized(optionalList(name)), maybe(suffix)) ||
49464ab3302SCarolineConcatto extension<LanguageFeature::OmitFunctionDummies>(
495*2d8b6a47SPeter Klausler "nonstandard usage: FUNCTION statement without dummy argument list"_port_en_US,
49664ab3302SCarolineConcatto construct<FunctionStmt>( // PGI & Intel accept "FUNCTION F"
49764ab3302SCarolineConcatto many(prefixSpec), "FUNCTION" >> name,
49864ab3302SCarolineConcatto construct<std::list<Name>>(),
49964ab3302SCarolineConcatto construct<std::optional<Suffix>>())))
50064ab3302SCarolineConcatto
50164ab3302SCarolineConcatto // R1532 suffix ->
50264ab3302SCarolineConcatto // proc-language-binding-spec [RESULT ( result-name )] |
50364ab3302SCarolineConcatto // RESULT ( result-name ) [proc-language-binding-spec]
50464ab3302SCarolineConcatto TYPE_PARSER(construct<Suffix>(
50564ab3302SCarolineConcatto languageBindingSpec, maybe("RESULT" >> parenthesized(name))) ||
50664ab3302SCarolineConcatto construct<Suffix>(
50764ab3302SCarolineConcatto "RESULT" >> parenthesized(name), maybe(languageBindingSpec)))
50864ab3302SCarolineConcatto
50964ab3302SCarolineConcatto // R1533 end-function-stmt -> END [FUNCTION [function-name]]
51064ab3302SCarolineConcatto TYPE_PARSER(construct<EndFunctionStmt>(recovery(
51164ab3302SCarolineConcatto "END FUNCTION" >> maybe(name) || bareEnd, progUnitEndStmtErrorRecovery)))
51264ab3302SCarolineConcatto
51364ab3302SCarolineConcatto // R1534 subroutine-subprogram ->
51464ab3302SCarolineConcatto // subroutine-stmt [specification-part] [execution-part]
51564ab3302SCarolineConcatto // [internal-subprogram-part] end-subroutine-stmt
51664ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("SUBROUTINE subprogram"_en_US,
51764ab3302SCarolineConcatto construct<SubroutineSubprogram>(statement(subroutineStmt),
51864ab3302SCarolineConcatto specificationPart, executionPart, maybe(internalSubprogramPart),
51964ab3302SCarolineConcatto unterminatedStatement(endSubroutineStmt)))
52064ab3302SCarolineConcatto
52164ab3302SCarolineConcatto // R1535 subroutine-stmt ->
52264ab3302SCarolineConcatto // [prefix] SUBROUTINE subroutine-name [( [dummy-arg-list] )
52364ab3302SCarolineConcatto // [proc-language-binding-spec]]
52464ab3302SCarolineConcatto TYPE_PARSER(
52564ab3302SCarolineConcatto construct<SubroutineStmt>(many(prefixSpec), "SUBROUTINE" >> name,
52664ab3302SCarolineConcatto parenthesized(optionalList(dummyArg)), maybe(languageBindingSpec)) ||
52764ab3302SCarolineConcatto construct<SubroutineStmt>(many(prefixSpec), "SUBROUTINE" >> name,
528a0226f9bSpeter klausler pure<std::list<DummyArg>>(),
529a0226f9bSpeter klausler pure<std::optional<LanguageBindingSpec>>()))
53064ab3302SCarolineConcatto
53164ab3302SCarolineConcatto // R1536 dummy-arg -> dummy-arg-name | *
53264ab3302SCarolineConcatto TYPE_PARSER(construct<DummyArg>(name) || construct<DummyArg>(star))
53364ab3302SCarolineConcatto
53464ab3302SCarolineConcatto // R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]]
53564ab3302SCarolineConcatto TYPE_PARSER(construct<EndSubroutineStmt>(recovery(
53664ab3302SCarolineConcatto "END SUBROUTINE" >> maybe(name) || bareEnd, progUnitEndStmtErrorRecovery)))
53764ab3302SCarolineConcatto
53864ab3302SCarolineConcatto // R1538 separate-module-subprogram ->
53964ab3302SCarolineConcatto // mp-subprogram-stmt [specification-part] [execution-part]
54064ab3302SCarolineConcatto // [internal-subprogram-part] end-mp-subprogram-stmt
54164ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("separate module subprogram"_en_US,
54264ab3302SCarolineConcatto construct<SeparateModuleSubprogram>(statement(Parser<MpSubprogramStmt>{}),
54364ab3302SCarolineConcatto specificationPart, executionPart, maybe(internalSubprogramPart),
54464ab3302SCarolineConcatto statement(Parser<EndMpSubprogramStmt>{})))
54564ab3302SCarolineConcatto
54664ab3302SCarolineConcatto // R1539 mp-subprogram-stmt -> MODULE PROCEDURE procedure-name
54764ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("MODULE PROCEDURE statement"_en_US,
54864ab3302SCarolineConcatto construct<MpSubprogramStmt>("MODULE PROCEDURE"_sptok >> name))
54964ab3302SCarolineConcatto
55064ab3302SCarolineConcatto // R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]]
55164ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("END PROCEDURE statement"_en_US,
55264ab3302SCarolineConcatto construct<EndMpSubprogramStmt>(
55364ab3302SCarolineConcatto recovery("END PROCEDURE" >> maybe(name) || bareEnd,
55464ab3302SCarolineConcatto progUnitEndStmtErrorRecovery)))
55564ab3302SCarolineConcatto
55664ab3302SCarolineConcatto // R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]]
55764ab3302SCarolineConcatto TYPE_PARSER(
55864ab3302SCarolineConcatto "ENTRY" >> (construct<EntryStmt>(name,
55964ab3302SCarolineConcatto parenthesized(optionalList(dummyArg)), maybe(suffix)) ||
56064ab3302SCarolineConcatto construct<EntryStmt>(name, construct<std::list<DummyArg>>(),
56164ab3302SCarolineConcatto construct<std::optional<Suffix>>())))
56264ab3302SCarolineConcatto
56364ab3302SCarolineConcatto // R1542 return-stmt -> RETURN [scalar-int-expr]
56464ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("RETURN statement"_en_US,
56564ab3302SCarolineConcatto construct<ReturnStmt>("RETURN" >> maybe(scalarIntExpr)))
56664ab3302SCarolineConcatto
56764ab3302SCarolineConcatto // R1543 contains-stmt -> CONTAINS
56864ab3302SCarolineConcatto TYPE_PARSER(construct<ContainsStmt>("CONTAINS"_tok))
56964ab3302SCarolineConcatto
57064ab3302SCarolineConcatto // R1544 stmt-function-stmt ->
57164ab3302SCarolineConcatto // function-name ( [dummy-arg-name-list] ) = scalar-expr
57264ab3302SCarolineConcatto TYPE_CONTEXT_PARSER("statement function definition"_en_US,
57364ab3302SCarolineConcatto construct<StmtFunctionStmt>(
57464ab3302SCarolineConcatto name, parenthesized(optionalList(name)), "=" >> scalar(expr)))
5751f879005STim Keith } // namespace Fortran::parser
576