1 //===-- lib/Parser/Fortran-parsers.cpp ------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // Top-level grammar specification for Fortran. These parsers drive 10 // the tokenization parsers in cooked-tokens.h to consume characters, 11 // recognize the productions of Fortran, and to construct a parse tree. 12 // See ParserCombinators.md for documentation on the parser combinator 13 // library used here to implement an LL recursive descent recognizer. 14 15 // The productions that follow are derived from the draft Fortran 2018 16 // standard, with some necessary modifications to remove left recursion 17 // and some generalization in order to defer cases where parses depend 18 // on the definitions of symbols. The "Rxxx" numbers that appear in 19 // comments refer to these numbered requirements in the Fortran standard. 20 21 // The whole Fortran grammar originally constituted one header file, 22 // but that turned out to require more memory to compile with current 23 // C++ compilers than some people were willing to accept, so now the 24 // various per-type parsers are partitioned into several C++ source 25 // files. This file contains parsers for constants, types, declarations, 26 // and misfits (mostly clauses 7, 8, & 9 of Fortran 2018). The others: 27 // executable-parsers.cpp Executable statements 28 // expr-parsers.cpp Expressions 29 // io-parsers.cpp I/O statements and FORMAT 30 // openmp-parsers.cpp OpenMP directives 31 // program-parsers.cpp Program units 32 33 #include "basic-parsers.h" 34 #include "expr-parsers.h" 35 #include "misc-parsers.h" 36 #include "stmt-parser.h" 37 #include "token-parsers.h" 38 #include "type-parser-implementation.h" 39 #include "flang/Parser/parse-tree.h" 40 #include "flang/Parser/user-state.h" 41 42 namespace Fortran::parser { 43 44 // R601 alphanumeric-character -> letter | digit | underscore 45 // R603 name -> letter [alphanumeric-character]... 46 constexpr auto nonDigitIdChar{letter || otherIdChar}; 47 constexpr auto rawName{nonDigitIdChar >> many(nonDigitIdChar || digit)}; 48 TYPE_PARSER(space >> sourced(rawName >> construct<Name>())) 49 50 // R608 intrinsic-operator -> 51 // power-op | mult-op | add-op | concat-op | rel-op | 52 // not-op | and-op | or-op | equiv-op 53 // R610 extended-intrinsic-op -> intrinsic-operator 54 // These parsers must be ordered carefully to avoid misrecognition. 55 constexpr auto namedIntrinsicOperator{ 56 ".LT." >> pure(DefinedOperator::IntrinsicOperator::LT) || 57 ".LE." >> pure(DefinedOperator::IntrinsicOperator::LE) || 58 ".EQ." >> pure(DefinedOperator::IntrinsicOperator::EQ) || 59 ".NE." >> pure(DefinedOperator::IntrinsicOperator::NE) || 60 ".GE." >> pure(DefinedOperator::IntrinsicOperator::GE) || 61 ".GT." >> pure(DefinedOperator::IntrinsicOperator::GT) || 62 ".NOT." >> pure(DefinedOperator::IntrinsicOperator::NOT) || 63 ".AND." >> pure(DefinedOperator::IntrinsicOperator::AND) || 64 ".OR." >> pure(DefinedOperator::IntrinsicOperator::OR) || 65 ".EQV." >> pure(DefinedOperator::IntrinsicOperator::EQV) || 66 ".NEQV." >> pure(DefinedOperator::IntrinsicOperator::NEQV) || 67 extension<LanguageFeature::XOROperator>( 68 ".XOR." >> pure(DefinedOperator::IntrinsicOperator::NEQV)) || 69 extension<LanguageFeature::LogicalAbbreviations>( 70 ".N." >> pure(DefinedOperator::IntrinsicOperator::NOT) || 71 ".A." >> pure(DefinedOperator::IntrinsicOperator::AND) || 72 ".O." >> pure(DefinedOperator::IntrinsicOperator::OR) || 73 extension<LanguageFeature::XOROperator>( 74 ".X." >> pure(DefinedOperator::IntrinsicOperator::NEQV)))}; 75 76 constexpr auto intrinsicOperator{ 77 "**" >> pure(DefinedOperator::IntrinsicOperator::Power) || 78 "*" >> pure(DefinedOperator::IntrinsicOperator::Multiply) || 79 "//" >> pure(DefinedOperator::IntrinsicOperator::Concat) || 80 "/=" >> pure(DefinedOperator::IntrinsicOperator::NE) || 81 "/" >> pure(DefinedOperator::IntrinsicOperator::Divide) || 82 "+" >> pure(DefinedOperator::IntrinsicOperator::Add) || 83 "-" >> pure(DefinedOperator::IntrinsicOperator::Subtract) || 84 "<=" >> pure(DefinedOperator::IntrinsicOperator::LE) || 85 extension<LanguageFeature::AlternativeNE>( 86 "<>" >> pure(DefinedOperator::IntrinsicOperator::NE)) || 87 "<" >> pure(DefinedOperator::IntrinsicOperator::LT) || 88 "==" >> pure(DefinedOperator::IntrinsicOperator::EQ) || 89 ">=" >> pure(DefinedOperator::IntrinsicOperator::GE) || 90 ">" >> pure(DefinedOperator::IntrinsicOperator::GT) || 91 namedIntrinsicOperator}; 92 93 // R609 defined-operator -> 94 // defined-unary-op | defined-binary-op | extended-intrinsic-op 95 TYPE_PARSER(construct<DefinedOperator>(intrinsicOperator) || 96 construct<DefinedOperator>(definedOpName)) 97 98 // R505 implicit-part -> [implicit-part-stmt]... implicit-stmt 99 // N.B. PARAMETER, FORMAT, & ENTRY statements that appear before any 100 // other kind of declaration-construct will be parsed into the 101 // implicit-part. 102 TYPE_CONTEXT_PARSER("implicit part"_en_US, 103 construct<ImplicitPart>(many(Parser<ImplicitPartStmt>{}))) 104 105 // R506 implicit-part-stmt -> 106 // implicit-stmt | parameter-stmt | format-stmt | entry-stmt 107 TYPE_PARSER(first( 108 construct<ImplicitPartStmt>(statement(indirect(Parser<ImplicitStmt>{}))), 109 construct<ImplicitPartStmt>(statement(indirect(parameterStmt))), 110 construct<ImplicitPartStmt>(statement(indirect(oldParameterStmt))), 111 construct<ImplicitPartStmt>(statement(indirect(formatStmt))), 112 construct<ImplicitPartStmt>(statement(indirect(entryStmt))), 113 construct<ImplicitPartStmt>(indirect(compilerDirective)))) 114 115 // R512 internal-subprogram -> function-subprogram | subroutine-subprogram 116 // Internal subprograms are not program units, so their END statements 117 // can be followed by ';' and another statement on the same line. 118 TYPE_CONTEXT_PARSER("internal subprogram"_en_US, 119 (construct<InternalSubprogram>(indirect(functionSubprogram)) || 120 construct<InternalSubprogram>(indirect(subroutineSubprogram))) / 121 forceEndOfStmt) 122 123 // R511 internal-subprogram-part -> contains-stmt [internal-subprogram]... 124 TYPE_CONTEXT_PARSER("internal subprogram part"_en_US, 125 construct<InternalSubprogramPart>(statement(containsStmt), 126 many(StartNewSubprogram{} >> Parser<InternalSubprogram>{}))) 127 128 // R605 literal-constant -> 129 // int-literal-constant | real-literal-constant | 130 // complex-literal-constant | logical-literal-constant | 131 // char-literal-constant | boz-literal-constant 132 TYPE_PARSER( 133 first(construct<LiteralConstant>(Parser<HollerithLiteralConstant>{}), 134 construct<LiteralConstant>(realLiteralConstant), 135 construct<LiteralConstant>(intLiteralConstant), 136 construct<LiteralConstant>(Parser<ComplexLiteralConstant>{}), 137 construct<LiteralConstant>(Parser<BOZLiteralConstant>{}), 138 construct<LiteralConstant>(charLiteralConstant), 139 construct<LiteralConstant>(Parser<LogicalLiteralConstant>{}))) 140 141 // R606 named-constant -> name 142 TYPE_PARSER(construct<NamedConstant>(name)) 143 144 // R701 type-param-value -> scalar-int-expr | * | : 145 TYPE_PARSER(construct<TypeParamValue>(scalarIntExpr) || 146 construct<TypeParamValue>(star) || 147 construct<TypeParamValue>(construct<TypeParamValue::Deferred>(":"_tok))) 148 149 // R702 type-spec -> intrinsic-type-spec | derived-type-spec 150 // N.B. This type-spec production is one of two instances in the Fortran 151 // grammar where intrinsic types and bare derived type names can clash; 152 // the other is below in R703 declaration-type-spec. Look-ahead is required 153 // to disambiguate the cases where a derived type name begins with the name 154 // of an intrinsic type, e.g., REALITY. 155 TYPE_CONTEXT_PARSER("type spec"_en_US, 156 construct<TypeSpec>(intrinsicTypeSpec / lookAhead("::"_tok || ")"_tok)) || 157 construct<TypeSpec>(derivedTypeSpec)) 158 159 // R703 declaration-type-spec -> 160 // intrinsic-type-spec | TYPE ( intrinsic-type-spec ) | 161 // TYPE ( derived-type-spec ) | CLASS ( derived-type-spec ) | 162 // CLASS ( * ) | TYPE ( * ) 163 // N.B. It is critical to distribute "parenthesized()" over the alternatives 164 // for TYPE (...), rather than putting the alternatives within it, which 165 // would fail on "TYPE(real_derived)" with a misrecognition of "real" as an 166 // intrinsic-type-spec. 167 TYPE_CONTEXT_PARSER("declaration type spec"_en_US, 168 construct<DeclarationTypeSpec>(intrinsicTypeSpec) || 169 "TYPE" >> 170 (parenthesized(construct<DeclarationTypeSpec>(intrinsicTypeSpec)) || 171 parenthesized(construct<DeclarationTypeSpec>( 172 construct<DeclarationTypeSpec::Type>(derivedTypeSpec))) || 173 construct<DeclarationTypeSpec>( 174 "( * )" >> construct<DeclarationTypeSpec::TypeStar>())) || 175 "CLASS" >> parenthesized(construct<DeclarationTypeSpec>( 176 construct<DeclarationTypeSpec::Class>( 177 derivedTypeSpec)) || 178 construct<DeclarationTypeSpec>("*" >> 179 construct<DeclarationTypeSpec::ClassStar>())) || 180 extension<LanguageFeature::DECStructures>( 181 construct<DeclarationTypeSpec>( 182 // As is also done for the STRUCTURE statement, the name of 183 // the structure includes the surrounding slashes to avoid 184 // name clashes. 185 construct<DeclarationTypeSpec::Record>( 186 "RECORD" >> sourced("/" >> name / "/"))))) 187 188 // R704 intrinsic-type-spec -> 189 // integer-type-spec | REAL [kind-selector] | DOUBLE PRECISION | 190 // COMPLEX [kind-selector] | CHARACTER [char-selector] | 191 // LOGICAL [kind-selector] 192 // Extensions: DOUBLE COMPLEX, BYTE 193 TYPE_CONTEXT_PARSER("intrinsic type spec"_en_US, 194 first(construct<IntrinsicTypeSpec>(integerTypeSpec), 195 construct<IntrinsicTypeSpec>( 196 construct<IntrinsicTypeSpec::Real>("REAL" >> maybe(kindSelector))), 197 construct<IntrinsicTypeSpec>("DOUBLE PRECISION" >> 198 construct<IntrinsicTypeSpec::DoublePrecision>()), 199 construct<IntrinsicTypeSpec>(construct<IntrinsicTypeSpec::Complex>( 200 "COMPLEX" >> maybe(kindSelector))), 201 construct<IntrinsicTypeSpec>(construct<IntrinsicTypeSpec::Character>( 202 "CHARACTER" >> maybe(Parser<CharSelector>{}))), 203 construct<IntrinsicTypeSpec>(construct<IntrinsicTypeSpec::Logical>( 204 "LOGICAL" >> maybe(kindSelector))), 205 construct<IntrinsicTypeSpec>("DOUBLE COMPLEX" >> 206 extension<LanguageFeature::DoubleComplex>( 207 construct<IntrinsicTypeSpec::DoubleComplex>())), 208 extension<LanguageFeature::Byte>( 209 construct<IntrinsicTypeSpec>(construct<IntegerTypeSpec>( 210 "BYTE" >> construct<std::optional<KindSelector>>(pure(1))))))) 211 212 // R705 integer-type-spec -> INTEGER [kind-selector] 213 TYPE_PARSER(construct<IntegerTypeSpec>("INTEGER" >> maybe(kindSelector))) 214 215 // R706 kind-selector -> ( [KIND =] scalar-int-constant-expr ) 216 // Legacy extension: kind-selector -> * digit-string 217 TYPE_PARSER(construct<KindSelector>( 218 parenthesized(maybe("KIND ="_tok) >> scalarIntConstantExpr)) || 219 extension<LanguageFeature::StarKind>(construct<KindSelector>( 220 construct<KindSelector::StarSize>("*" >> digitString64 / spaceCheck)))) 221 222 // R707 signed-int-literal-constant -> [sign] int-literal-constant 223 TYPE_PARSER(sourced(construct<SignedIntLiteralConstant>( 224 SignedIntLiteralConstantWithoutKind{}, maybe(underscore >> kindParam)))) 225 226 // R708 int-literal-constant -> digit-string [_ kind-param] 227 // The negated look-ahead for a trailing underscore prevents misrecognition 228 // when the digit string is a numeric kind parameter of a character literal. 229 TYPE_PARSER(construct<IntLiteralConstant>( 230 space >> digitString, maybe(underscore >> kindParam) / !underscore)) 231 232 // R709 kind-param -> digit-string | scalar-int-constant-name 233 TYPE_PARSER(construct<KindParam>(digitString64) || 234 construct<KindParam>(scalar(integer(constant(name))))) 235 236 // R712 sign -> + | - 237 // N.B. A sign constitutes a whole token, so a space is allowed in free form 238 // after the sign and before a real-literal-constant or 239 // complex-literal-constant. A sign is not a unary operator in these contexts. 240 constexpr auto sign{ 241 "+"_tok >> pure(Sign::Positive) || "-"_tok >> pure(Sign::Negative)}; 242 243 // R713 signed-real-literal-constant -> [sign] real-literal-constant 244 constexpr auto signedRealLiteralConstant{ 245 construct<SignedRealLiteralConstant>(maybe(sign), realLiteralConstant)}; 246 247 // R714 real-literal-constant -> 248 // significand [exponent-letter exponent] [_ kind-param] | 249 // digit-string exponent-letter exponent [_ kind-param] 250 // R715 significand -> digit-string . [digit-string] | . digit-string 251 // R716 exponent-letter -> E | D 252 // Extension: Q 253 // R717 exponent -> signed-digit-string 254 constexpr auto exponentPart{ 255 ("ed"_ch || extension<LanguageFeature::QuadPrecision>("q"_ch)) >> 256 SignedDigitString{}}; 257 258 TYPE_CONTEXT_PARSER("REAL literal constant"_en_US, 259 space >> 260 construct<RealLiteralConstant>( 261 sourced((digitString >> "."_ch >> 262 !(some(letter) >> 263 "."_ch /* don't misinterpret 1.AND. */) >> 264 maybe(digitString) >> maybe(exponentPart) >> ok || 265 "."_ch >> digitString >> maybe(exponentPart) >> ok || 266 digitString >> exponentPart >> ok) >> 267 construct<RealLiteralConstant::Real>()), 268 maybe(underscore >> kindParam))) 269 270 // R718 complex-literal-constant -> ( real-part , imag-part ) 271 TYPE_CONTEXT_PARSER("COMPLEX literal constant"_en_US, 272 parenthesized(construct<ComplexLiteralConstant>( 273 Parser<ComplexPart>{} / ",", Parser<ComplexPart>{}))) 274 275 // PGI/Intel extension: signed complex literal constant 276 TYPE_PARSER(construct<SignedComplexLiteralConstant>( 277 sign, Parser<ComplexLiteralConstant>{})) 278 279 // R719 real-part -> 280 // signed-int-literal-constant | signed-real-literal-constant | 281 // named-constant 282 // R720 imag-part -> 283 // signed-int-literal-constant | signed-real-literal-constant | 284 // named-constant 285 TYPE_PARSER(construct<ComplexPart>(signedRealLiteralConstant) || 286 construct<ComplexPart>(signedIntLiteralConstant) || 287 construct<ComplexPart>(namedConstant)) 288 289 // R721 char-selector -> 290 // length-selector | 291 // ( LEN = type-param-value , KIND = scalar-int-constant-expr ) | 292 // ( type-param-value , [KIND =] scalar-int-constant-expr ) | 293 // ( KIND = scalar-int-constant-expr [, LEN = type-param-value] ) 294 TYPE_PARSER(construct<CharSelector>(Parser<LengthSelector>{}) || 295 parenthesized(construct<CharSelector>( 296 "LEN =" >> typeParamValue, ", KIND =" >> scalarIntConstantExpr)) || 297 parenthesized(construct<CharSelector>( 298 typeParamValue / ",", maybe("KIND ="_tok) >> scalarIntConstantExpr)) || 299 parenthesized(construct<CharSelector>( 300 "KIND =" >> scalarIntConstantExpr, maybe(", LEN =" >> typeParamValue)))) 301 302 // R722 length-selector -> ( [LEN =] type-param-value ) | * char-length [,] 303 // N.B. The trailing [,] in the production is permitted by the Standard 304 // only in the context of a type-declaration-stmt, but even with that 305 // limitation, it would seem to be unnecessary and buggy to consume the comma 306 // here. 307 TYPE_PARSER(construct<LengthSelector>( 308 parenthesized(maybe("LEN ="_tok) >> typeParamValue)) || 309 construct<LengthSelector>("*" >> charLength /* / maybe(","_tok) */)) 310 311 // R723 char-length -> ( type-param-value ) | digit-string 312 TYPE_PARSER(construct<CharLength>(parenthesized(typeParamValue)) || 313 construct<CharLength>(space >> digitString64 / spaceCheck)) 314 315 // R724 char-literal-constant -> 316 // [kind-param _] ' [rep-char]... ' | 317 // [kind-param _] " [rep-char]... " 318 // "rep-char" is any non-control character. Doubled interior quotes are 319 // combined. Backslash escapes can be enabled. 320 // N.B. the parsing of "kind-param" takes care to not consume the '_'. 321 TYPE_CONTEXT_PARSER("CHARACTER literal constant"_en_US, 322 construct<CharLiteralConstant>( 323 kindParam / underscore, charLiteralConstantWithoutKind) || 324 construct<CharLiteralConstant>(construct<std::optional<KindParam>>(), 325 space >> charLiteralConstantWithoutKind)) 326 327 TYPE_CONTEXT_PARSER( 328 "Hollerith"_en_US, construct<HollerithLiteralConstant>(rawHollerithLiteral)) 329 330 // R725 logical-literal-constant -> 331 // .TRUE. [_ kind-param] | .FALSE. [_ kind-param] 332 // Also accept .T. and .F. as extensions. 333 TYPE_PARSER(construct<LogicalLiteralConstant>( 334 logicalTRUE, maybe(underscore >> kindParam)) || 335 construct<LogicalLiteralConstant>( 336 logicalFALSE, maybe(underscore >> kindParam))) 337 338 // R726 derived-type-def -> 339 // derived-type-stmt [type-param-def-stmt]... 340 // [private-or-sequence]... [component-part] 341 // [type-bound-procedure-part] end-type-stmt 342 // R735 component-part -> [component-def-stmt]... 343 TYPE_CONTEXT_PARSER("derived type definition"_en_US, 344 construct<DerivedTypeDef>(statement(Parser<DerivedTypeStmt>{}), 345 many(unambiguousStatement(Parser<TypeParamDefStmt>{})), 346 many(statement(Parser<PrivateOrSequence>{})), 347 many(inContext("component"_en_US, 348 unambiguousStatement(Parser<ComponentDefStmt>{}))), 349 maybe(Parser<TypeBoundProcedurePart>{}), 350 statement(Parser<EndTypeStmt>{}))) 351 352 // R727 derived-type-stmt -> 353 // TYPE [[, type-attr-spec-list] ::] type-name [( 354 // type-param-name-list )] 355 TYPE_CONTEXT_PARSER("TYPE statement"_en_US, 356 construct<DerivedTypeStmt>( 357 "TYPE" >> optionalListBeforeColons(Parser<TypeAttrSpec>{}), name, 358 defaulted(parenthesized(nonemptyList(name))))) 359 360 // R728 type-attr-spec -> 361 // ABSTRACT | access-spec | BIND(C) | EXTENDS ( parent-type-name ) 362 TYPE_PARSER(construct<TypeAttrSpec>(construct<Abstract>("ABSTRACT"_tok)) || 363 construct<TypeAttrSpec>(construct<TypeAttrSpec::BindC>("BIND ( C )"_tok)) || 364 construct<TypeAttrSpec>( 365 construct<TypeAttrSpec::Extends>("EXTENDS" >> parenthesized(name))) || 366 construct<TypeAttrSpec>(accessSpec)) 367 368 // R729 private-or-sequence -> private-components-stmt | sequence-stmt 369 TYPE_PARSER(construct<PrivateOrSequence>(Parser<PrivateStmt>{}) || 370 construct<PrivateOrSequence>(Parser<SequenceStmt>{})) 371 372 // R730 end-type-stmt -> END TYPE [type-name] 373 TYPE_PARSER(construct<EndTypeStmt>( 374 recovery("END TYPE" >> maybe(name), endStmtErrorRecovery))) 375 376 // R731 sequence-stmt -> SEQUENCE 377 TYPE_PARSER(construct<SequenceStmt>("SEQUENCE"_tok)) 378 379 // R732 type-param-def-stmt -> 380 // integer-type-spec , type-param-attr-spec :: type-param-decl-list 381 // R734 type-param-attr-spec -> KIND | LEN 382 constexpr auto kindOrLen{"KIND" >> pure(common::TypeParamAttr::Kind) || 383 "LEN" >> pure(common::TypeParamAttr::Len)}; 384 TYPE_PARSER(construct<TypeParamDefStmt>(integerTypeSpec / ",", kindOrLen, 385 "::" >> nonemptyList("expected type parameter declarations"_err_en_US, 386 Parser<TypeParamDecl>{}))) 387 388 // R733 type-param-decl -> type-param-name [= scalar-int-constant-expr] 389 TYPE_PARSER(construct<TypeParamDecl>(name, maybe("=" >> scalarIntConstantExpr))) 390 391 // R736 component-def-stmt -> data-component-def-stmt | 392 // proc-component-def-stmt 393 // Accidental extension not enabled here: PGI accepts type-param-def-stmt in 394 // component-part of derived-type-def. 395 TYPE_PARSER(recovery( 396 withMessage("expected component definition"_err_en_US, 397 first(construct<ComponentDefStmt>(Parser<DataComponentDefStmt>{}), 398 construct<ComponentDefStmt>(Parser<ProcComponentDefStmt>{}))), 399 construct<ComponentDefStmt>(inStmtErrorRecovery))) 400 401 // R737 data-component-def-stmt -> 402 // declaration-type-spec [[, component-attr-spec-list] ::] 403 // component-decl-list 404 // N.B. The standard requires double colons if there's an initializer. 405 TYPE_PARSER(construct<DataComponentDefStmt>(declarationTypeSpec, 406 optionalListBeforeColons(Parser<ComponentAttrSpec>{}), 407 nonemptyList("expected component declarations"_err_en_US, 408 Parser<ComponentOrFill>{}))) 409 410 // R738 component-attr-spec -> 411 // access-spec | ALLOCATABLE | 412 // CODIMENSION lbracket coarray-spec rbracket | 413 // CONTIGUOUS | DIMENSION ( component-array-spec ) | POINTER 414 TYPE_PARSER(construct<ComponentAttrSpec>(accessSpec) || 415 construct<ComponentAttrSpec>(allocatable) || 416 construct<ComponentAttrSpec>("CODIMENSION" >> coarraySpec) || 417 construct<ComponentAttrSpec>(contiguous) || 418 construct<ComponentAttrSpec>("DIMENSION" >> Parser<ComponentArraySpec>{}) || 419 construct<ComponentAttrSpec>(pointer) || 420 construct<ComponentAttrSpec>(recovery( 421 fail<ErrorRecovery>( 422 "type parameter definitions must appear before component declarations"_err_en_US), 423 kindOrLen >> construct<ErrorRecovery>()))) 424 425 // R739 component-decl -> 426 // component-name [( component-array-spec )] 427 // [lbracket coarray-spec rbracket] [* char-length] 428 // [component-initialization] 429 TYPE_CONTEXT_PARSER("component declaration"_en_US, 430 construct<ComponentDecl>(name, maybe(Parser<ComponentArraySpec>{}), 431 maybe(coarraySpec), maybe("*" >> charLength), maybe(initialization))) 432 // The source field of the Name will be replaced with a distinct generated name. 433 TYPE_CONTEXT_PARSER("%FILL item"_en_US, 434 extension<LanguageFeature::DECStructures>( 435 construct<FillDecl>(space >> sourced("%FILL" >> construct<Name>()), 436 maybe(Parser<ComponentArraySpec>{}), maybe("*" >> charLength)))) 437 TYPE_PARSER(construct<ComponentOrFill>(Parser<ComponentDecl>{}) || 438 construct<ComponentOrFill>(Parser<FillDecl>{})) 439 440 // R740 component-array-spec -> 441 // explicit-shape-spec-list | deferred-shape-spec-list 442 // N.B. Parenthesized here rather than around references to this production. 443 TYPE_PARSER(construct<ComponentArraySpec>(parenthesized( 444 nonemptyList("expected explicit shape specifications"_err_en_US, 445 explicitShapeSpec))) || 446 construct<ComponentArraySpec>(parenthesized(deferredShapeSpecList))) 447 448 // R741 proc-component-def-stmt -> 449 // PROCEDURE ( [proc-interface] ) , proc-component-attr-spec-list 450 // :: proc-decl-list 451 TYPE_CONTEXT_PARSER("PROCEDURE component definition statement"_en_US, 452 construct<ProcComponentDefStmt>( 453 "PROCEDURE" >> parenthesized(maybe(procInterface)), 454 localRecovery("expected PROCEDURE component attributes"_err_en_US, 455 "," >> nonemptyList(Parser<ProcComponentAttrSpec>{}), ok), 456 localRecovery("expected PROCEDURE declarations"_err_en_US, 457 "::" >> nonemptyList(procDecl), SkipTo<'\n'>{}))) 458 459 // R742 proc-component-attr-spec -> 460 // access-spec | NOPASS | PASS [(arg-name)] | POINTER 461 constexpr auto noPass{construct<NoPass>("NOPASS"_tok)}; 462 constexpr auto pass{construct<Pass>("PASS" >> maybe(parenthesized(name)))}; 463 TYPE_PARSER(construct<ProcComponentAttrSpec>(accessSpec) || 464 construct<ProcComponentAttrSpec>(noPass) || 465 construct<ProcComponentAttrSpec>(pass) || 466 construct<ProcComponentAttrSpec>(pointer)) 467 468 // R744 initial-data-target -> designator 469 constexpr auto initialDataTarget{indirect(designator)}; 470 471 // R743 component-initialization -> 472 // = constant-expr | => null-init | => initial-data-target 473 // R805 initialization -> 474 // = constant-expr | => null-init | => initial-data-target 475 // Universal extension: initialization -> / data-stmt-value-list / 476 TYPE_PARSER(construct<Initialization>("=>" >> nullInit) || 477 construct<Initialization>("=>" >> initialDataTarget) || 478 construct<Initialization>("=" >> constantExpr) || 479 extension<LanguageFeature::SlashInitialization>(construct<Initialization>( 480 "/" >> nonemptyList("expected values"_err_en_US, 481 indirect(Parser<DataStmtValue>{})) / 482 "/"))) 483 484 // R745 private-components-stmt -> PRIVATE 485 // R747 binding-private-stmt -> PRIVATE 486 TYPE_PARSER(construct<PrivateStmt>("PRIVATE"_tok)) 487 488 // R746 type-bound-procedure-part -> 489 // contains-stmt [binding-private-stmt] [type-bound-proc-binding]... 490 TYPE_CONTEXT_PARSER("type bound procedure part"_en_US, 491 construct<TypeBoundProcedurePart>(statement(containsStmt), 492 maybe(statement(Parser<PrivateStmt>{})), 493 many(statement(Parser<TypeBoundProcBinding>{})))) 494 495 // R748 type-bound-proc-binding -> 496 // type-bound-procedure-stmt | type-bound-generic-stmt | 497 // final-procedure-stmt 498 TYPE_CONTEXT_PARSER("type bound procedure binding"_en_US, 499 recovery( 500 first(construct<TypeBoundProcBinding>(Parser<TypeBoundProcedureStmt>{}), 501 construct<TypeBoundProcBinding>(Parser<TypeBoundGenericStmt>{}), 502 construct<TypeBoundProcBinding>(Parser<FinalProcedureStmt>{})), 503 construct<TypeBoundProcBinding>( 504 !"END"_tok >> SkipTo<'\n'>{} >> construct<ErrorRecovery>()))) 505 506 // R749 type-bound-procedure-stmt -> 507 // PROCEDURE [[, bind-attr-list] ::] type-bound-proc-decl-list | 508 // PROCEDURE ( interface-name ) , bind-attr-list :: binding-name-list 509 TYPE_CONTEXT_PARSER("type bound PROCEDURE statement"_en_US, 510 "PROCEDURE" >> 511 (construct<TypeBoundProcedureStmt>( 512 construct<TypeBoundProcedureStmt::WithInterface>( 513 parenthesized(name), 514 localRecovery("expected list of binding attributes"_err_en_US, 515 "," >> nonemptyList(Parser<BindAttr>{}), ok), 516 localRecovery("expected list of binding names"_err_en_US, 517 "::" >> listOfNames, SkipTo<'\n'>{}))) || 518 construct<TypeBoundProcedureStmt>( 519 construct<TypeBoundProcedureStmt::WithoutInterface>( 520 optionalListBeforeColons(Parser<BindAttr>{}), 521 nonemptyList( 522 "expected type bound procedure declarations"_err_en_US, 523 Parser<TypeBoundProcDecl>{}))))) 524 525 // R750 type-bound-proc-decl -> binding-name [=> procedure-name] 526 TYPE_PARSER(construct<TypeBoundProcDecl>(name, maybe("=>" >> name))) 527 528 // R751 type-bound-generic-stmt -> 529 // GENERIC [, access-spec] :: generic-spec => binding-name-list 530 TYPE_CONTEXT_PARSER("type bound GENERIC statement"_en_US, 531 construct<TypeBoundGenericStmt>("GENERIC" >> maybe("," >> accessSpec), 532 "::" >> indirect(genericSpec), "=>" >> listOfNames)) 533 534 // R752 bind-attr -> 535 // access-spec | DEFERRED | NON_OVERRIDABLE | NOPASS | PASS [(arg-name)] 536 TYPE_PARSER(construct<BindAttr>(accessSpec) || 537 construct<BindAttr>(construct<BindAttr::Deferred>("DEFERRED"_tok)) || 538 construct<BindAttr>( 539 construct<BindAttr::Non_Overridable>("NON_OVERRIDABLE"_tok)) || 540 construct<BindAttr>(noPass) || construct<BindAttr>(pass)) 541 542 // R753 final-procedure-stmt -> FINAL [::] final-subroutine-name-list 543 TYPE_CONTEXT_PARSER("FINAL statement"_en_US, 544 construct<FinalProcedureStmt>("FINAL" >> maybe("::"_tok) >> listOfNames)) 545 546 // R754 derived-type-spec -> type-name [(type-param-spec-list)] 547 TYPE_PARSER(construct<DerivedTypeSpec>(name, 548 defaulted(parenthesized(nonemptyList( 549 "expected type parameters"_err_en_US, Parser<TypeParamSpec>{}))))) 550 551 // R755 type-param-spec -> [keyword =] type-param-value 552 TYPE_PARSER(construct<TypeParamSpec>(maybe(keyword / "="), typeParamValue)) 553 554 // R756 structure-constructor -> derived-type-spec ( [component-spec-list] ) 555 TYPE_PARSER((construct<StructureConstructor>(derivedTypeSpec, 556 parenthesized(optionalList(Parser<ComponentSpec>{}))) || 557 // This alternative corrects misrecognition of the 558 // component-spec-list as the type-param-spec-list in 559 // derived-type-spec. 560 construct<StructureConstructor>( 561 construct<DerivedTypeSpec>( 562 name, construct<std::list<TypeParamSpec>>()), 563 parenthesized(optionalList(Parser<ComponentSpec>{})))) / 564 !"("_tok) 565 566 // R757 component-spec -> [keyword =] component-data-source 567 TYPE_PARSER(construct<ComponentSpec>( 568 maybe(keyword / "="), Parser<ComponentDataSource>{})) 569 570 // R758 component-data-source -> expr | data-target | proc-target 571 TYPE_PARSER(construct<ComponentDataSource>(indirect(expr))) 572 573 // R759 enum-def -> 574 // enum-def-stmt enumerator-def-stmt [enumerator-def-stmt]... 575 // end-enum-stmt 576 TYPE_CONTEXT_PARSER("enum definition"_en_US, 577 construct<EnumDef>(statement(Parser<EnumDefStmt>{}), 578 some(unambiguousStatement(Parser<EnumeratorDefStmt>{})), 579 statement(Parser<EndEnumStmt>{}))) 580 581 // R760 enum-def-stmt -> ENUM, BIND(C) 582 TYPE_PARSER(construct<EnumDefStmt>("ENUM , BIND ( C )"_tok)) 583 584 // R761 enumerator-def-stmt -> ENUMERATOR [::] enumerator-list 585 TYPE_CONTEXT_PARSER("ENUMERATOR statement"_en_US, 586 construct<EnumeratorDefStmt>("ENUMERATOR" >> maybe("::"_tok) >> 587 nonemptyList("expected enumerators"_err_en_US, Parser<Enumerator>{}))) 588 589 // R762 enumerator -> named-constant [= scalar-int-constant-expr] 590 TYPE_PARSER( 591 construct<Enumerator>(namedConstant, maybe("=" >> scalarIntConstantExpr))) 592 593 // R763 end-enum-stmt -> END ENUM 594 TYPE_PARSER(recovery("END ENUM"_tok, "END" >> SkipPast<'\n'>{}) >> 595 construct<EndEnumStmt>()) 596 597 // R801 type-declaration-stmt -> 598 // declaration-type-spec [[, attr-spec]... ::] entity-decl-list 599 constexpr auto entityDeclWithoutEqInit{construct<EntityDecl>(name, 600 maybe(arraySpec), maybe(coarraySpec), maybe("*" >> charLength), 601 !"="_tok >> maybe(initialization))}; // old-style REAL A/0/ still works 602 TYPE_PARSER( 603 construct<TypeDeclarationStmt>(declarationTypeSpec, 604 defaulted("," >> nonemptyList(Parser<AttrSpec>{})) / "::", 605 nonemptyList("expected entity declarations"_err_en_US, entityDecl)) || 606 // C806: no initializers allowed without colons ("REALA=1" is ambiguous) 607 construct<TypeDeclarationStmt>(declarationTypeSpec, 608 construct<std::list<AttrSpec>>(), 609 nonemptyList("expected entity declarations"_err_en_US, 610 entityDeclWithoutEqInit)) || 611 // PGI-only extension: comma in place of doubled colons 612 extension<LanguageFeature::MissingColons>(construct<TypeDeclarationStmt>( 613 declarationTypeSpec, defaulted("," >> nonemptyList(Parser<AttrSpec>{})), 614 withMessage("expected entity declarations"_err_en_US, 615 "," >> nonemptyList(entityDecl))))) 616 617 // R802 attr-spec -> 618 // access-spec | ALLOCATABLE | ASYNCHRONOUS | 619 // CODIMENSION lbracket coarray-spec rbracket | CONTIGUOUS | 620 // DIMENSION ( array-spec ) | EXTERNAL | INTENT ( intent-spec ) | 621 // INTRINSIC | language-binding-spec | OPTIONAL | PARAMETER | POINTER | 622 // PROTECTED | SAVE | TARGET | VALUE | VOLATILE 623 TYPE_PARSER(construct<AttrSpec>(accessSpec) || 624 construct<AttrSpec>(allocatable) || 625 construct<AttrSpec>(construct<Asynchronous>("ASYNCHRONOUS"_tok)) || 626 construct<AttrSpec>("CODIMENSION" >> coarraySpec) || 627 construct<AttrSpec>(contiguous) || 628 construct<AttrSpec>("DIMENSION" >> arraySpec) || 629 construct<AttrSpec>(construct<External>("EXTERNAL"_tok)) || 630 construct<AttrSpec>("INTENT" >> parenthesized(intentSpec)) || 631 construct<AttrSpec>(construct<Intrinsic>("INTRINSIC"_tok)) || 632 construct<AttrSpec>(languageBindingSpec) || construct<AttrSpec>(optional) || 633 construct<AttrSpec>(construct<Parameter>("PARAMETER"_tok)) || 634 construct<AttrSpec>(pointer) || construct<AttrSpec>(protectedAttr) || 635 construct<AttrSpec>(save) || 636 construct<AttrSpec>(construct<Target>("TARGET"_tok)) || 637 construct<AttrSpec>(construct<Value>("VALUE"_tok)) || 638 construct<AttrSpec>(construct<Volatile>("VOLATILE"_tok))) 639 640 // R804 object-name -> name 641 constexpr auto objectName{name}; 642 643 // R803 entity-decl -> 644 // object-name [( array-spec )] [lbracket coarray-spec rbracket] 645 // [* char-length] [initialization] | 646 // function-name [* char-length] 647 TYPE_PARSER(construct<EntityDecl>(objectName, maybe(arraySpec), 648 maybe(coarraySpec), maybe("*" >> charLength), maybe(initialization))) 649 650 // R806 null-init -> function-reference ... which must resolve to NULL() 651 TYPE_PARSER(lookAhead(name / "( )") >> construct<NullInit>(expr)) 652 653 // R807 access-spec -> PUBLIC | PRIVATE 654 TYPE_PARSER(construct<AccessSpec>("PUBLIC" >> pure(AccessSpec::Kind::Public)) || 655 construct<AccessSpec>("PRIVATE" >> pure(AccessSpec::Kind::Private))) 656 657 // R808 language-binding-spec -> 658 // BIND ( C [, NAME = scalar-default-char-constant-expr] ) 659 // R1528 proc-language-binding-spec -> language-binding-spec 660 TYPE_PARSER(construct<LanguageBindingSpec>( 661 "BIND ( C" >> maybe(", NAME =" >> scalarDefaultCharConstantExpr) / ")")) 662 663 // R809 coarray-spec -> deferred-coshape-spec-list | explicit-coshape-spec 664 // N.B. Bracketed here rather than around references, for consistency with 665 // array-spec. 666 TYPE_PARSER( 667 construct<CoarraySpec>(bracketed(Parser<DeferredCoshapeSpecList>{})) || 668 construct<CoarraySpec>(bracketed(Parser<ExplicitCoshapeSpec>{}))) 669 670 // R810 deferred-coshape-spec -> : 671 // deferred-coshape-spec-list - just a list of colons 672 inline int listLength(std::list<Success> &&xs) { return xs.size(); } 673 674 TYPE_PARSER(construct<DeferredCoshapeSpecList>( 675 applyFunction(listLength, nonemptyList(":"_tok)))) 676 677 // R811 explicit-coshape-spec -> 678 // [[lower-cobound :] upper-cobound ,]... [lower-cobound :] * 679 // R812 lower-cobound -> specification-expr 680 // R813 upper-cobound -> specification-expr 681 TYPE_PARSER(construct<ExplicitCoshapeSpec>( 682 many(explicitShapeSpec / ","), maybe(specificationExpr / ":") / "*")) 683 684 // R815 array-spec -> 685 // explicit-shape-spec-list | assumed-shape-spec-list | 686 // deferred-shape-spec-list | assumed-size-spec | implied-shape-spec | 687 // implied-shape-or-assumed-size-spec | assumed-rank-spec 688 // N.B. Parenthesized here rather than around references to avoid 689 // a need for forced look-ahead. 690 // Shape specs that could be deferred-shape-spec or assumed-shape-spec 691 // (e.g. '(:,:)') are parsed as the former. 692 TYPE_PARSER( 693 construct<ArraySpec>(parenthesized(nonemptyList(explicitShapeSpec))) || 694 construct<ArraySpec>(parenthesized(deferredShapeSpecList)) || 695 construct<ArraySpec>( 696 parenthesized(nonemptyList(Parser<AssumedShapeSpec>{}))) || 697 construct<ArraySpec>(parenthesized(Parser<AssumedSizeSpec>{})) || 698 construct<ArraySpec>(parenthesized(Parser<ImpliedShapeSpec>{})) || 699 construct<ArraySpec>(parenthesized(Parser<AssumedRankSpec>{}))) 700 701 // R816 explicit-shape-spec -> [lower-bound :] upper-bound 702 // R817 lower-bound -> specification-expr 703 // R818 upper-bound -> specification-expr 704 TYPE_PARSER(construct<ExplicitShapeSpec>( 705 maybe(specificationExpr / ":"), specificationExpr)) 706 707 // R819 assumed-shape-spec -> [lower-bound] : 708 TYPE_PARSER(construct<AssumedShapeSpec>(maybe(specificationExpr) / ":")) 709 710 // R820 deferred-shape-spec -> : 711 // deferred-shape-spec-list - just a list of colons 712 TYPE_PARSER(construct<DeferredShapeSpecList>( 713 applyFunction(listLength, nonemptyList(":"_tok)))) 714 715 // R821 assumed-implied-spec -> [lower-bound :] * 716 TYPE_PARSER(construct<AssumedImpliedSpec>(maybe(specificationExpr / ":") / "*")) 717 718 // R822 assumed-size-spec -> explicit-shape-spec-list , assumed-implied-spec 719 TYPE_PARSER(construct<AssumedSizeSpec>( 720 nonemptyList(explicitShapeSpec) / ",", assumedImpliedSpec)) 721 722 // R823 implied-shape-or-assumed-size-spec -> assumed-implied-spec 723 // R824 implied-shape-spec -> assumed-implied-spec , assumed-implied-spec-list 724 // I.e., when the assumed-implied-spec-list has a single item, it constitutes an 725 // implied-shape-or-assumed-size-spec; otherwise, an implied-shape-spec. 726 TYPE_PARSER(construct<ImpliedShapeSpec>(nonemptyList(assumedImpliedSpec))) 727 728 // R825 assumed-rank-spec -> .. 729 TYPE_PARSER(construct<AssumedRankSpec>(".."_tok)) 730 731 // R826 intent-spec -> IN | OUT | INOUT 732 TYPE_PARSER(construct<IntentSpec>("IN OUT" >> pure(IntentSpec::Intent::InOut) || 733 "IN" >> pure(IntentSpec::Intent::In) || 734 "OUT" >> pure(IntentSpec::Intent::Out))) 735 736 // R827 access-stmt -> access-spec [[::] access-id-list] 737 TYPE_PARSER(construct<AccessStmt>(accessSpec, 738 defaulted(maybe("::"_tok) >> 739 nonemptyList("expected names and generic specifications"_err_en_US, 740 Parser<AccessId>{})))) 741 742 // R828 access-id -> access-name | generic-spec 743 TYPE_PARSER(construct<AccessId>(indirect(genericSpec)) || 744 construct<AccessId>(name)) // initially ambiguous with genericSpec 745 746 // R829 allocatable-stmt -> ALLOCATABLE [::] allocatable-decl-list 747 TYPE_PARSER(construct<AllocatableStmt>("ALLOCATABLE" >> maybe("::"_tok) >> 748 nonemptyList( 749 "expected object declarations"_err_en_US, Parser<ObjectDecl>{}))) 750 751 // R830 allocatable-decl -> 752 // object-name [( array-spec )] [lbracket coarray-spec rbracket] 753 // R860 target-decl -> 754 // object-name [( array-spec )] [lbracket coarray-spec rbracket] 755 TYPE_PARSER( 756 construct<ObjectDecl>(objectName, maybe(arraySpec), maybe(coarraySpec))) 757 758 // R831 asynchronous-stmt -> ASYNCHRONOUS [::] object-name-list 759 TYPE_PARSER(construct<AsynchronousStmt>("ASYNCHRONOUS" >> maybe("::"_tok) >> 760 nonemptyList("expected object names"_err_en_US, objectName))) 761 762 // R832 bind-stmt -> language-binding-spec [::] bind-entity-list 763 TYPE_PARSER(construct<BindStmt>(languageBindingSpec / maybe("::"_tok), 764 nonemptyList("expected bind entities"_err_en_US, Parser<BindEntity>{}))) 765 766 // R833 bind-entity -> entity-name | / common-block-name / 767 TYPE_PARSER(construct<BindEntity>(pure(BindEntity::Kind::Object), name) || 768 construct<BindEntity>("/" >> pure(BindEntity::Kind::Common), name / "/")) 769 770 // R834 codimension-stmt -> CODIMENSION [::] codimension-decl-list 771 TYPE_PARSER(construct<CodimensionStmt>("CODIMENSION" >> maybe("::"_tok) >> 772 nonemptyList("expected codimension declarations"_err_en_US, 773 Parser<CodimensionDecl>{}))) 774 775 // R835 codimension-decl -> coarray-name lbracket coarray-spec rbracket 776 TYPE_PARSER(construct<CodimensionDecl>(name, coarraySpec)) 777 778 // R836 contiguous-stmt -> CONTIGUOUS [::] object-name-list 779 TYPE_PARSER(construct<ContiguousStmt>("CONTIGUOUS" >> maybe("::"_tok) >> 780 nonemptyList("expected object names"_err_en_US, objectName))) 781 782 // R837 data-stmt -> DATA data-stmt-set [[,] data-stmt-set]... 783 TYPE_CONTEXT_PARSER("DATA statement"_en_US, 784 construct<DataStmt>( 785 "DATA" >> nonemptySeparated(Parser<DataStmtSet>{}, maybe(","_tok)))) 786 787 // R838 data-stmt-set -> data-stmt-object-list / data-stmt-value-list / 788 TYPE_PARSER(construct<DataStmtSet>( 789 nonemptyList( 790 "expected DATA statement objects"_err_en_US, Parser<DataStmtObject>{}), 791 withMessage("expected DATA statement value list"_err_en_US, 792 "/"_tok >> nonemptyList("expected DATA statement values"_err_en_US, 793 Parser<DataStmtValue>{})) / 794 "/")) 795 796 // R839 data-stmt-object -> variable | data-implied-do 797 TYPE_PARSER(construct<DataStmtObject>(indirect(variable)) || 798 construct<DataStmtObject>(dataImpliedDo)) 799 800 // R840 data-implied-do -> 801 // ( data-i-do-object-list , [integer-type-spec ::] data-i-do-variable 802 // = scalar-int-constant-expr , scalar-int-constant-expr 803 // [, scalar-int-constant-expr] ) 804 // R842 data-i-do-variable -> do-variable 805 TYPE_PARSER(parenthesized(construct<DataImpliedDo>( 806 nonemptyList(Parser<DataIDoObject>{} / lookAhead(","_tok)) / ",", 807 maybe(integerTypeSpec / "::"), loopBounds(scalarIntConstantExpr)))) 808 809 // R841 data-i-do-object -> 810 // array-element | scalar-structure-component | data-implied-do 811 TYPE_PARSER(construct<DataIDoObject>(scalar(indirect(designator))) || 812 construct<DataIDoObject>(indirect(dataImpliedDo))) 813 814 // R843 data-stmt-value -> [data-stmt-repeat *] data-stmt-constant 815 TYPE_PARSER(construct<DataStmtValue>( 816 maybe(Parser<DataStmtRepeat>{} / "*"), Parser<DataStmtConstant>{})) 817 818 // R847 constant-subobject -> designator 819 // R846 int-constant-subobject -> constant-subobject 820 constexpr auto constantSubobject{constant(indirect(designator))}; 821 822 // R844 data-stmt-repeat -> scalar-int-constant | scalar-int-constant-subobject 823 // R607 int-constant -> constant 824 // Factored into: constant -> literal-constant -> int-literal-constant 825 // The named-constant alternative of constant is subsumed by constant-subobject 826 TYPE_PARSER(construct<DataStmtRepeat>(intLiteralConstant) || 827 construct<DataStmtRepeat>(scalar(integer(constantSubobject)))) 828 829 // R845 data-stmt-constant -> 830 // scalar-constant | scalar-constant-subobject | 831 // signed-int-literal-constant | signed-real-literal-constant | 832 // null-init | initial-data-target | 833 // constant-structure-constructor 834 // N.B. scalar-constant and scalar-constant-subobject are ambiguous with 835 // initial-data-target; null-init and structure-constructor are ambiguous 836 // in the absence of parameters and components; structure-constructor with 837 // components can be ambiguous with a scalar-constant-subobject. 838 // So we parse literal constants, designator, null-init, and 839 // structure-constructor, so that semantics can figure things out later 840 // with the symbol table. 841 TYPE_PARSER(sourced(first(construct<DataStmtConstant>(literalConstant), 842 construct<DataStmtConstant>(signedRealLiteralConstant), 843 construct<DataStmtConstant>(signedIntLiteralConstant), 844 extension<LanguageFeature::SignedComplexLiteral>( 845 construct<DataStmtConstant>(Parser<SignedComplexLiteralConstant>{})), 846 construct<DataStmtConstant>(nullInit), 847 construct<DataStmtConstant>(indirect(designator) / !"("_tok), 848 construct<DataStmtConstant>(Parser<StructureConstructor>{})))) 849 850 // R848 dimension-stmt -> 851 // DIMENSION [::] array-name ( array-spec ) 852 // [, array-name ( array-spec )]... 853 TYPE_CONTEXT_PARSER("DIMENSION statement"_en_US, 854 construct<DimensionStmt>("DIMENSION" >> maybe("::"_tok) >> 855 nonemptyList("expected array specifications"_err_en_US, 856 construct<DimensionStmt::Declaration>(name, arraySpec)))) 857 858 // R849 intent-stmt -> INTENT ( intent-spec ) [::] dummy-arg-name-list 859 TYPE_CONTEXT_PARSER("INTENT statement"_en_US, 860 construct<IntentStmt>( 861 "INTENT" >> parenthesized(intentSpec) / maybe("::"_tok), listOfNames)) 862 863 // R850 optional-stmt -> OPTIONAL [::] dummy-arg-name-list 864 TYPE_PARSER( 865 construct<OptionalStmt>("OPTIONAL" >> maybe("::"_tok) >> listOfNames)) 866 867 // R851 parameter-stmt -> PARAMETER ( named-constant-def-list ) 868 // Legacy extension: omitted parentheses, no implicit typing from names 869 TYPE_CONTEXT_PARSER("PARAMETER statement"_en_US, 870 construct<ParameterStmt>( 871 "PARAMETER" >> parenthesized(nonemptyList(Parser<NamedConstantDef>{})))) 872 TYPE_CONTEXT_PARSER("old style PARAMETER statement"_en_US, 873 extension<LanguageFeature::OldStyleParameter>(construct<OldParameterStmt>( 874 "PARAMETER" >> nonemptyList(Parser<NamedConstantDef>{})))) 875 876 // R852 named-constant-def -> named-constant = constant-expr 877 TYPE_PARSER(construct<NamedConstantDef>(namedConstant, "=" >> constantExpr)) 878 879 // R853 pointer-stmt -> POINTER [::] pointer-decl-list 880 TYPE_PARSER(construct<PointerStmt>("POINTER" >> maybe("::"_tok) >> 881 nonemptyList( 882 "expected pointer declarations"_err_en_US, Parser<PointerDecl>{}))) 883 884 // R854 pointer-decl -> 885 // object-name [( deferred-shape-spec-list )] | proc-entity-name 886 TYPE_PARSER( 887 construct<PointerDecl>(name, maybe(parenthesized(deferredShapeSpecList)))) 888 889 // R855 protected-stmt -> PROTECTED [::] entity-name-list 890 TYPE_PARSER( 891 construct<ProtectedStmt>("PROTECTED" >> maybe("::"_tok) >> listOfNames)) 892 893 // R856 save-stmt -> SAVE [[::] saved-entity-list] 894 TYPE_PARSER(construct<SaveStmt>( 895 "SAVE" >> defaulted(maybe("::"_tok) >> 896 nonemptyList("expected SAVE entities"_err_en_US, 897 Parser<SavedEntity>{})))) 898 899 // R857 saved-entity -> object-name | proc-pointer-name | / common-block-name / 900 // R858 proc-pointer-name -> name 901 TYPE_PARSER(construct<SavedEntity>(pure(SavedEntity::Kind::Entity), name) || 902 construct<SavedEntity>("/" >> pure(SavedEntity::Kind::Common), name / "/")) 903 904 // R859 target-stmt -> TARGET [::] target-decl-list 905 TYPE_PARSER(construct<TargetStmt>("TARGET" >> maybe("::"_tok) >> 906 nonemptyList("expected objects"_err_en_US, Parser<ObjectDecl>{}))) 907 908 // R861 value-stmt -> VALUE [::] dummy-arg-name-list 909 TYPE_PARSER(construct<ValueStmt>("VALUE" >> maybe("::"_tok) >> listOfNames)) 910 911 // R862 volatile-stmt -> VOLATILE [::] object-name-list 912 TYPE_PARSER(construct<VolatileStmt>("VOLATILE" >> maybe("::"_tok) >> 913 nonemptyList("expected object names"_err_en_US, objectName))) 914 915 // R866 implicit-name-spec -> EXTERNAL | TYPE 916 constexpr auto implicitNameSpec{ 917 "EXTERNAL" >> pure(ImplicitStmt::ImplicitNoneNameSpec::External) || 918 "TYPE" >> pure(ImplicitStmt::ImplicitNoneNameSpec::Type)}; 919 920 // R863 implicit-stmt -> 921 // IMPLICIT implicit-spec-list | 922 // IMPLICIT NONE [( [implicit-name-spec-list] )] 923 TYPE_CONTEXT_PARSER("IMPLICIT statement"_en_US, 924 construct<ImplicitStmt>( 925 "IMPLICIT" >> nonemptyList("expected IMPLICIT specifications"_err_en_US, 926 Parser<ImplicitSpec>{})) || 927 construct<ImplicitStmt>("IMPLICIT NONE"_sptok >> 928 defaulted(parenthesized(optionalList(implicitNameSpec))))) 929 930 // R864 implicit-spec -> declaration-type-spec ( letter-spec-list ) 931 // The variant form of declarationTypeSpec is meant to avoid misrecognition 932 // of a letter-spec as a simple parenthesized expression for kind or character 933 // length, e.g., PARAMETER(I=5,N=1); IMPLICIT REAL(I-N)(O-Z) vs. 934 // IMPLICIT REAL(I-N). The variant form needs to attempt to reparse only 935 // types with optional parenthesized kind/length expressions, so derived 936 // type specs, DOUBLE PRECISION, and DOUBLE COMPLEX need not be considered. 937 constexpr auto noKindSelector{construct<std::optional<KindSelector>>()}; 938 constexpr auto implicitSpecDeclarationTypeSpecRetry{ 939 construct<DeclarationTypeSpec>(first( 940 construct<IntrinsicTypeSpec>( 941 construct<IntegerTypeSpec>("INTEGER" >> noKindSelector)), 942 construct<IntrinsicTypeSpec>( 943 construct<IntrinsicTypeSpec::Real>("REAL" >> noKindSelector)), 944 construct<IntrinsicTypeSpec>( 945 construct<IntrinsicTypeSpec::Complex>("COMPLEX" >> noKindSelector)), 946 construct<IntrinsicTypeSpec>(construct<IntrinsicTypeSpec::Character>( 947 "CHARACTER" >> construct<std::optional<CharSelector>>())), 948 construct<IntrinsicTypeSpec>(construct<IntrinsicTypeSpec::Logical>( 949 "LOGICAL" >> noKindSelector))))}; 950 951 TYPE_PARSER(construct<ImplicitSpec>(declarationTypeSpec, 952 parenthesized(nonemptyList(Parser<LetterSpec>{}))) || 953 construct<ImplicitSpec>(implicitSpecDeclarationTypeSpecRetry, 954 parenthesized(nonemptyList(Parser<LetterSpec>{})))) 955 956 // R865 letter-spec -> letter [- letter] 957 TYPE_PARSER(space >> (construct<LetterSpec>(letter, maybe("-" >> letter)) || 958 construct<LetterSpec>(otherIdChar, 959 construct<std::optional<const char *>>()))) 960 961 // R867 import-stmt -> 962 // IMPORT [[::] import-name-list] | 963 // IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL 964 TYPE_CONTEXT_PARSER("IMPORT statement"_en_US, 965 construct<ImportStmt>( 966 "IMPORT , ONLY :" >> pure(common::ImportKind::Only), listOfNames) || 967 construct<ImportStmt>( 968 "IMPORT , NONE" >> pure(common::ImportKind::None)) || 969 construct<ImportStmt>( 970 "IMPORT , ALL" >> pure(common::ImportKind::All)) || 971 construct<ImportStmt>( 972 "IMPORT" >> maybe("::"_tok) >> optionalList(name))) 973 974 // R868 namelist-stmt -> 975 // NAMELIST / namelist-group-name / namelist-group-object-list 976 // [[,] / namelist-group-name / namelist-group-object-list]... 977 // R869 namelist-group-object -> variable-name 978 TYPE_PARSER(construct<NamelistStmt>("NAMELIST" >> 979 nonemptySeparated( 980 construct<NamelistStmt::Group>("/" >> name / "/", listOfNames), 981 maybe(","_tok)))) 982 983 // R870 equivalence-stmt -> EQUIVALENCE equivalence-set-list 984 // R871 equivalence-set -> ( equivalence-object , equivalence-object-list ) 985 TYPE_PARSER(construct<EquivalenceStmt>("EQUIVALENCE" >> 986 nonemptyList( 987 parenthesized(nonemptyList("expected EQUIVALENCE objects"_err_en_US, 988 Parser<EquivalenceObject>{}))))) 989 990 // R872 equivalence-object -> variable-name | array-element | substring 991 TYPE_PARSER(construct<EquivalenceObject>(indirect(designator))) 992 993 // R873 common-stmt -> 994 // COMMON [/ [common-block-name] /] common-block-object-list 995 // [[,] / [common-block-name] / common-block-object-list]... 996 TYPE_PARSER( 997 construct<CommonStmt>("COMMON" >> defaulted("/" >> maybe(name) / "/"), 998 nonemptyList("expected COMMON block objects"_err_en_US, 999 Parser<CommonBlockObject>{}), 1000 many(maybe(","_tok) >> 1001 construct<CommonStmt::Block>("/" >> maybe(name) / "/", 1002 nonemptyList("expected COMMON block objects"_err_en_US, 1003 Parser<CommonBlockObject>{}))))) 1004 1005 // R874 common-block-object -> variable-name [( array-spec )] 1006 TYPE_PARSER(construct<CommonBlockObject>(name, maybe(arraySpec))) 1007 1008 // R901 designator -> object-name | array-element | array-section | 1009 // coindexed-named-object | complex-part-designator | 1010 // structure-component | substring 1011 // The Standard's productions for designator and its alternatives are 1012 // ambiguous without recourse to a symbol table. Many of the alternatives 1013 // for designator (viz., array-element, coindexed-named-object, 1014 // and structure-component) are all syntactically just data-ref. 1015 // What designator boils down to is this: 1016 // It starts with either a name or a character literal. 1017 // If it starts with a character literal, it must be a substring. 1018 // If it starts with a name, it's a sequence of %-separated parts; 1019 // each part is a name, maybe a (section-subscript-list), and 1020 // maybe an [image-selector]. 1021 // If it's a substring, it ends with (substring-range). 1022 TYPE_CONTEXT_PARSER("designator"_en_US, 1023 sourced(construct<Designator>(substring) || construct<Designator>(dataRef))) 1024 1025 constexpr auto percentOrDot{"%"_tok || 1026 // legacy VAX extension for RECORD field access 1027 extension<LanguageFeature::DECStructures>( 1028 "."_tok / lookAhead(OldStructureComponentName{}))}; 1029 1030 // R902 variable -> designator | function-reference 1031 // This production appears to be left-recursive in the grammar via 1032 // function-reference -> procedure-designator -> proc-component-ref -> 1033 // scalar-variable 1034 // and would be so if we were to allow functions to be called via procedure 1035 // pointer components within derived type results of other function references 1036 // (a reasonable extension, esp. in the case of procedure pointer components 1037 // that are NOPASS). However, Fortran constrains the use of a variable in a 1038 // proc-component-ref to be a data-ref without coindices (C1027). 1039 // Some array element references will be misrecognized as function references. 1040 constexpr auto noMoreAddressing{!"("_tok >> !"["_tok >> !percentOrDot}; 1041 TYPE_CONTEXT_PARSER("variable"_en_US, 1042 construct<Variable>(indirect(functionReference / noMoreAddressing)) || 1043 construct<Variable>(indirect(designator))) 1044 1045 // R908 substring -> parent-string ( substring-range ) 1046 // R909 parent-string -> 1047 // scalar-variable-name | array-element | coindexed-named-object | 1048 // scalar-structure-component | scalar-char-literal-constant | 1049 // scalar-named-constant 1050 TYPE_PARSER( 1051 construct<Substring>(dataRef, parenthesized(Parser<SubstringRange>{}))) 1052 1053 TYPE_PARSER(construct<CharLiteralConstantSubstring>( 1054 charLiteralConstant, parenthesized(Parser<SubstringRange>{}))) 1055 1056 // R910 substring-range -> [scalar-int-expr] : [scalar-int-expr] 1057 TYPE_PARSER(construct<SubstringRange>( 1058 maybe(scalarIntExpr), ":" >> maybe(scalarIntExpr))) 1059 1060 // R911 data-ref -> part-ref [% part-ref]... 1061 // R914 coindexed-named-object -> data-ref 1062 // R917 array-element -> data-ref 1063 TYPE_PARSER( 1064 construct<DataRef>(nonemptySeparated(Parser<PartRef>{}, percentOrDot))) 1065 1066 // R912 part-ref -> part-name [( section-subscript-list )] [image-selector] 1067 TYPE_PARSER(construct<PartRef>(name, 1068 defaulted( 1069 parenthesized(nonemptyList(Parser<SectionSubscript>{})) / !"=>"_tok), 1070 maybe(Parser<ImageSelector>{}))) 1071 1072 // R913 structure-component -> data-ref 1073 // The final part-ref in the data-ref is not allowed to have subscripts. 1074 TYPE_PARSER(construct<StructureComponent>( 1075 construct<DataRef>(some(Parser<PartRef>{} / percentOrDot)), name)) 1076 1077 // R919 subscript -> scalar-int-expr 1078 constexpr auto subscript{scalarIntExpr}; 1079 1080 // R920 section-subscript -> subscript | subscript-triplet | vector-subscript 1081 // R923 vector-subscript -> int-expr 1082 // N.B. The distinction that needs to be made between "subscript" and 1083 // "vector-subscript" is deferred to semantic analysis. 1084 TYPE_PARSER(construct<SectionSubscript>(Parser<SubscriptTriplet>{}) || 1085 construct<SectionSubscript>(intExpr)) 1086 1087 // R921 subscript-triplet -> [subscript] : [subscript] [: stride] 1088 TYPE_PARSER(construct<SubscriptTriplet>( 1089 maybe(subscript), ":" >> maybe(subscript), maybe(":" >> subscript))) 1090 1091 // R925 cosubscript -> scalar-int-expr 1092 constexpr auto cosubscript{scalarIntExpr}; 1093 1094 // R924 image-selector -> 1095 // lbracket cosubscript-list [, image-selector-spec-list] rbracket 1096 TYPE_CONTEXT_PARSER("image selector"_en_US, 1097 construct<ImageSelector>( 1098 "[" >> nonemptyList(cosubscript / lookAhead(space / ",]"_ch)), 1099 defaulted("," >> nonemptyList(Parser<ImageSelectorSpec>{})) / "]")) 1100 1101 // R926 image-selector-spec -> 1102 // STAT = stat-variable | TEAM = team-value | 1103 // TEAM_NUMBER = scalar-int-expr 1104 TYPE_PARSER(construct<ImageSelectorSpec>(construct<ImageSelectorSpec::Stat>( 1105 "STAT =" >> scalar(integer(indirect(variable))))) || 1106 construct<ImageSelectorSpec>(construct<TeamValue>("TEAM =" >> teamValue)) || 1107 construct<ImageSelectorSpec>(construct<ImageSelectorSpec::Team_Number>( 1108 "TEAM_NUMBER =" >> scalarIntExpr))) 1109 1110 // R927 allocate-stmt -> 1111 // ALLOCATE ( [type-spec ::] allocation-list [, alloc-opt-list] ) 1112 TYPE_CONTEXT_PARSER("ALLOCATE statement"_en_US, 1113 construct<AllocateStmt>("ALLOCATE (" >> maybe(typeSpec / "::"), 1114 nonemptyList(Parser<Allocation>{}), 1115 defaulted("," >> nonemptyList(Parser<AllocOpt>{})) / ")")) 1116 1117 // R928 alloc-opt -> 1118 // ERRMSG = errmsg-variable | MOLD = source-expr | 1119 // SOURCE = source-expr | STAT = stat-variable 1120 // R931 source-expr -> expr 1121 TYPE_PARSER(construct<AllocOpt>( 1122 construct<AllocOpt::Mold>("MOLD =" >> indirect(expr))) || 1123 construct<AllocOpt>( 1124 construct<AllocOpt::Source>("SOURCE =" >> indirect(expr))) || 1125 construct<AllocOpt>(statOrErrmsg)) 1126 1127 // R929 stat-variable -> scalar-int-variable 1128 TYPE_PARSER(construct<StatVariable>(scalar(integer(variable)))) 1129 1130 // R932 allocation -> 1131 // allocate-object [( allocate-shape-spec-list )] 1132 // [lbracket allocate-coarray-spec rbracket] 1133 TYPE_PARSER(construct<Allocation>(Parser<AllocateObject>{}, 1134 defaulted(parenthesized(nonemptyList(Parser<AllocateShapeSpec>{}))), 1135 maybe(bracketed(Parser<AllocateCoarraySpec>{})))) 1136 1137 // R933 allocate-object -> variable-name | structure-component 1138 TYPE_PARSER(construct<AllocateObject>(structureComponent) || 1139 construct<AllocateObject>(name / !"="_tok)) 1140 1141 // R934 allocate-shape-spec -> [lower-bound-expr :] upper-bound-expr 1142 // R938 allocate-coshape-spec -> [lower-bound-expr :] upper-bound-expr 1143 TYPE_PARSER(construct<AllocateShapeSpec>(maybe(boundExpr / ":"), boundExpr)) 1144 1145 // R937 allocate-coarray-spec -> 1146 // [allocate-coshape-spec-list ,] [lower-bound-expr :] * 1147 TYPE_PARSER(construct<AllocateCoarraySpec>( 1148 defaulted(nonemptyList(Parser<AllocateShapeSpec>{}) / ","), 1149 maybe(boundExpr / ":") / "*")) 1150 1151 // R939 nullify-stmt -> NULLIFY ( pointer-object-list ) 1152 TYPE_CONTEXT_PARSER("NULLIFY statement"_en_US, 1153 "NULLIFY" >> parenthesized(construct<NullifyStmt>( 1154 nonemptyList(Parser<PointerObject>{})))) 1155 1156 // R940 pointer-object -> 1157 // variable-name | structure-component | proc-pointer-name 1158 TYPE_PARSER(construct<PointerObject>(structureComponent) || 1159 construct<PointerObject>(name)) 1160 1161 // R941 deallocate-stmt -> 1162 // DEALLOCATE ( allocate-object-list [, dealloc-opt-list] ) 1163 TYPE_CONTEXT_PARSER("DEALLOCATE statement"_en_US, 1164 construct<DeallocateStmt>( 1165 "DEALLOCATE (" >> nonemptyList(Parser<AllocateObject>{}), 1166 defaulted("," >> nonemptyList(statOrErrmsg)) / ")")) 1167 1168 // R942 dealloc-opt -> STAT = stat-variable | ERRMSG = errmsg-variable 1169 // R1165 sync-stat -> STAT = stat-variable | ERRMSG = errmsg-variable 1170 TYPE_PARSER(construct<StatOrErrmsg>("STAT =" >> statVariable) || 1171 construct<StatOrErrmsg>("ERRMSG =" >> msgVariable)) 1172 1173 // Directives, extensions, and deprecated statements 1174 // !DIR$ IGNORE_TKR [ [(tkr...)] name ]... 1175 // !DIR$ name... 1176 constexpr auto beginDirective{skipStuffBeforeStatement >> "!"_ch}; 1177 constexpr auto endDirective{space >> endOfLine}; 1178 constexpr auto ignore_tkr{ 1179 "DIR$ IGNORE_TKR" >> optionalList(construct<CompilerDirective::IgnoreTKR>( 1180 defaulted(parenthesized(some("tkr"_ch))), name))}; 1181 TYPE_PARSER(beginDirective >> 1182 sourced(construct<CompilerDirective>(ignore_tkr) || 1183 construct<CompilerDirective>( 1184 "DIR$" >> many(construct<CompilerDirective::NameValue>(name, 1185 maybe(("="_tok || ":"_tok) >> digitString64))))) / 1186 endDirective) 1187 1188 TYPE_PARSER(extension<LanguageFeature::CrayPointer>(construct<BasedPointerStmt>( 1189 "POINTER" >> nonemptyList("expected POINTER associations"_err_en_US, 1190 construct<BasedPointer>("(" >> objectName / ",", 1191 objectName, maybe(Parser<ArraySpec>{}) / ")"))))) 1192 1193 // Subtle: the name includes the surrounding slashes, which avoids 1194 // clashes with other uses of the name in the same scope. 1195 TYPE_PARSER(construct<StructureStmt>( 1196 "STRUCTURE" >> maybe(sourced("/" >> name / "/")), optionalList(entityDecl))) 1197 1198 constexpr auto nestedStructureDef{ 1199 CONTEXT_PARSER("nested STRUCTURE definition"_en_US, 1200 construct<StructureDef>(statement(NestedStructureStmt{}), 1201 many(Parser<StructureField>{}), 1202 statement(construct<StructureDef::EndStructureStmt>( 1203 "END STRUCTURE"_tok))))}; 1204 1205 TYPE_PARSER(construct<StructureField>(statement(StructureComponents{})) || 1206 construct<StructureField>(indirect(Parser<Union>{})) || 1207 construct<StructureField>(indirect(nestedStructureDef))) 1208 1209 TYPE_CONTEXT_PARSER("STRUCTURE definition"_en_US, 1210 extension<LanguageFeature::DECStructures>(construct<StructureDef>( 1211 statement(Parser<StructureStmt>{}), many(Parser<StructureField>{}), 1212 statement( 1213 construct<StructureDef::EndStructureStmt>("END STRUCTURE"_tok))))) 1214 1215 TYPE_CONTEXT_PARSER("UNION definition"_en_US, 1216 construct<Union>(statement(construct<Union::UnionStmt>("UNION"_tok)), 1217 many(Parser<Map>{}), 1218 statement(construct<Union::EndUnionStmt>("END UNION"_tok)))) 1219 1220 TYPE_CONTEXT_PARSER("MAP definition"_en_US, 1221 construct<Map>(statement(construct<Map::MapStmt>("MAP"_tok)), 1222 many(Parser<StructureField>{}), 1223 statement(construct<Map::EndMapStmt>("END MAP"_tok)))) 1224 1225 TYPE_CONTEXT_PARSER("arithmetic IF statement"_en_US, 1226 deprecated<LanguageFeature::ArithmeticIF>(construct<ArithmeticIfStmt>( 1227 "IF" >> parenthesized(expr), label / ",", label / ",", label))) 1228 1229 TYPE_CONTEXT_PARSER("ASSIGN statement"_en_US, 1230 deprecated<LanguageFeature::Assign>( 1231 construct<AssignStmt>("ASSIGN" >> label, "TO" >> name))) 1232 1233 TYPE_CONTEXT_PARSER("assigned GOTO statement"_en_US, 1234 deprecated<LanguageFeature::AssignedGOTO>(construct<AssignedGotoStmt>( 1235 "GO TO" >> name, 1236 defaulted(maybe(","_tok) >> 1237 parenthesized(nonemptyList("expected labels"_err_en_US, label)))))) 1238 1239 TYPE_CONTEXT_PARSER("PAUSE statement"_en_US, 1240 deprecated<LanguageFeature::Pause>( 1241 construct<PauseStmt>("PAUSE" >> maybe(Parser<StopCode>{})))) 1242 1243 // These requirement productions are defined by the Fortran standard but never 1244 // used directly by the grammar: 1245 // R620 delimiter -> ( | ) | / | [ | ] | (/ | /) 1246 // R1027 numeric-expr -> expr 1247 // R1031 int-constant-expr -> int-expr 1248 // R1221 dtv-type-spec -> TYPE ( derived-type-spec ) | 1249 // CLASS ( derived-type-spec ) 1250 // 1251 // These requirement productions are defined and used, but need not be 1252 // defined independently here in this file: 1253 // R771 lbracket -> [ 1254 // R772 rbracket -> ] 1255 // 1256 // Further note that: 1257 // R607 int-constant -> constant 1258 // is used only once via R844 scalar-int-constant 1259 // R904 logical-variable -> variable 1260 // is used only via scalar-logical-variable 1261 // R906 default-char-variable -> variable 1262 // is used only via scalar-default-char-variable 1263 // R907 int-variable -> variable 1264 // is used only via scalar-int-variable 1265 // R915 complex-part-designator -> designator % RE | designator % IM 1266 // %RE and %IM are initially recognized as structure components 1267 // R916 type-param-inquiry -> designator % type-param-name 1268 // is occulted by structure component designators 1269 // R918 array-section -> 1270 // data-ref [( substring-range )] | complex-part-designator 1271 // is not used because parsing is not sensitive to rank 1272 // R1030 default-char-constant-expr -> default-char-expr 1273 // is only used via scalar-default-char-constant-expr 1274 } // namespace Fortran::parser 1275