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