1 //===-- lib/Parser/executable-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 // Per-type parsers for executable statements
10 
11 #include "basic-parsers.h"
12 #include "debug-parser.h"
13 #include "expr-parsers.h"
14 #include "misc-parsers.h"
15 #include "stmt-parser.h"
16 #include "token-parsers.h"
17 #include "type-parser-implementation.h"
18 #include "flang/Parser/characters.h"
19 #include "flang/Parser/parse-tree.h"
20 
21 namespace Fortran::parser {
22 
23 // Fortran allows the statement with the corresponding label at the end of
24 // a do-construct that begins with an old-style label-do-stmt to be a
25 // new-style END DO statement; e.g., DO 10 I=1,N; ...; 10 END DO.  Usually,
26 // END DO statements appear only at the ends of do-constructs that begin
27 // with a nonlabel-do-stmt, so care must be taken to recognize this case and
28 // essentially treat them like CONTINUE statements.
29 
30 // R514 executable-construct ->
31 //        action-stmt | associate-construct | block-construct |
32 //        case-construct | change-team-construct | critical-construct |
33 //        do-construct | if-construct | select-rank-construct |
34 //        select-type-construct | where-construct | forall-construct
35 constexpr auto executableConstruct{
36     first(construct<ExecutableConstruct>(CapturedLabelDoStmt{}),
37         construct<ExecutableConstruct>(EndDoStmtForCapturedLabelDoStmt{}),
38         construct<ExecutableConstruct>(indirect(Parser<DoConstruct>{})),
39         // Attempt DO statements before assignment statements for better
40         // error messages in cases like "DO10I=1,(error)".
41         construct<ExecutableConstruct>(statement(actionStmt)),
42         construct<ExecutableConstruct>(indirect(Parser<AssociateConstruct>{})),
43         construct<ExecutableConstruct>(indirect(Parser<BlockConstruct>{})),
44         construct<ExecutableConstruct>(indirect(Parser<CaseConstruct>{})),
45         construct<ExecutableConstruct>(indirect(Parser<ChangeTeamConstruct>{})),
46         construct<ExecutableConstruct>(indirect(Parser<CriticalConstruct>{})),
47         construct<ExecutableConstruct>(indirect(Parser<IfConstruct>{})),
48         construct<ExecutableConstruct>(indirect(Parser<SelectRankConstruct>{})),
49         construct<ExecutableConstruct>(indirect(Parser<SelectTypeConstruct>{})),
50         construct<ExecutableConstruct>(indirect(whereConstruct)),
51         construct<ExecutableConstruct>(indirect(forallConstruct)),
52         construct<ExecutableConstruct>(indirect(ompEndLoopDirective)),
53         construct<ExecutableConstruct>(indirect(openmpConstruct)),
54         construct<ExecutableConstruct>(indirect(compilerDirective)))};
55 
56 // R510 execution-part-construct ->
57 //        executable-construct | format-stmt | entry-stmt | data-stmt
58 // Extension (PGI/Intel): also accept NAMELIST in execution part
59 constexpr auto obsoleteExecutionPartConstruct{recovery(ignoredStatementPrefix >>
60         fail<ExecutionPartConstruct>(
61             "obsolete legacy extension is not supported"_err_en_US),
62     construct<ExecutionPartConstruct>(construct<ErrorRecovery>(ok /
63         statement("REDIMENSION" >> name /
64                 parenthesized(nonemptyList(Parser<AllocateShapeSpec>{}))))))};
65 
66 TYPE_PARSER(recovery(
67     withMessage("expected execution part construct"_err_en_US,
68         CONTEXT_PARSER("execution part construct"_en_US,
69             first(construct<ExecutionPartConstruct>(executableConstruct),
70                 construct<ExecutionPartConstruct>(
71                     statement(indirect(formatStmt))),
72                 construct<ExecutionPartConstruct>(
73                     statement(indirect(entryStmt))),
74                 construct<ExecutionPartConstruct>(
75                     statement(indirect(dataStmt))),
76                 extension<LanguageFeature::ExecutionPartNamelist>(
77                     construct<ExecutionPartConstruct>(
78                         statement(indirect(Parser<NamelistStmt>{})))),
79                 obsoleteExecutionPartConstruct))),
80     construct<ExecutionPartConstruct>(executionPartErrorRecovery)))
81 
82 // R509 execution-part -> executable-construct [execution-part-construct]...
83 TYPE_CONTEXT_PARSER("execution part"_en_US,
84     construct<ExecutionPart>(many(executionPartConstruct)))
85 
86 // R515 action-stmt ->
87 //        allocate-stmt | assignment-stmt | backspace-stmt | call-stmt |
88 //        close-stmt | continue-stmt | cycle-stmt | deallocate-stmt |
89 //        endfile-stmt | error-stop-stmt | event-post-stmt | event-wait-stmt |
90 //        exit-stmt | fail-image-stmt | flush-stmt | form-team-stmt |
91 //        goto-stmt | if-stmt | inquire-stmt | lock-stmt | nullify-stmt |
92 //        open-stmt | pointer-assignment-stmt | print-stmt | read-stmt |
93 //        return-stmt | rewind-stmt | stop-stmt | sync-all-stmt |
94 //        sync-images-stmt | sync-memory-stmt | sync-team-stmt | unlock-stmt |
95 //        wait-stmt | where-stmt | write-stmt | computed-goto-stmt | forall-stmt
96 // R1159 continue-stmt -> CONTINUE
97 // R1163 fail-image-stmt -> FAIL IMAGE
98 TYPE_PARSER(first(construct<ActionStmt>(indirect(Parser<AllocateStmt>{})),
99     construct<ActionStmt>(indirect(assignmentStmt)),
100     construct<ActionStmt>(indirect(pointerAssignmentStmt)),
101     construct<ActionStmt>(indirect(Parser<BackspaceStmt>{})),
102     construct<ActionStmt>(indirect(Parser<CallStmt>{})),
103     construct<ActionStmt>(indirect(Parser<CloseStmt>{})),
104     construct<ActionStmt>(construct<ContinueStmt>("CONTINUE"_tok)),
105     construct<ActionStmt>(indirect(Parser<CycleStmt>{})),
106     construct<ActionStmt>(indirect(Parser<DeallocateStmt>{})),
107     construct<ActionStmt>(indirect(Parser<EndfileStmt>{})),
108     construct<ActionStmt>(indirect(Parser<EventPostStmt>{})),
109     construct<ActionStmt>(indirect(Parser<EventWaitStmt>{})),
110     construct<ActionStmt>(indirect(Parser<ExitStmt>{})),
111     construct<ActionStmt>(construct<FailImageStmt>("FAIL IMAGE"_sptok)),
112     construct<ActionStmt>(indirect(Parser<FlushStmt>{})),
113     construct<ActionStmt>(indirect(Parser<FormTeamStmt>{})),
114     construct<ActionStmt>(indirect(Parser<GotoStmt>{})),
115     construct<ActionStmt>(indirect(Parser<IfStmt>{})),
116     construct<ActionStmt>(indirect(Parser<InquireStmt>{})),
117     construct<ActionStmt>(indirect(Parser<LockStmt>{})),
118     construct<ActionStmt>(indirect(Parser<NullifyStmt>{})),
119     construct<ActionStmt>(indirect(Parser<OpenStmt>{})),
120     construct<ActionStmt>(indirect(Parser<PrintStmt>{})),
121     construct<ActionStmt>(indirect(Parser<ReadStmt>{})),
122     construct<ActionStmt>(indirect(Parser<ReturnStmt>{})),
123     construct<ActionStmt>(indirect(Parser<RewindStmt>{})),
124     construct<ActionStmt>(indirect(Parser<StopStmt>{})), // & error-stop-stmt
125     construct<ActionStmt>(indirect(Parser<SyncAllStmt>{})),
126     construct<ActionStmt>(indirect(Parser<SyncImagesStmt>{})),
127     construct<ActionStmt>(indirect(Parser<SyncMemoryStmt>{})),
128     construct<ActionStmt>(indirect(Parser<SyncTeamStmt>{})),
129     construct<ActionStmt>(indirect(Parser<UnlockStmt>{})),
130     construct<ActionStmt>(indirect(Parser<WaitStmt>{})),
131     construct<ActionStmt>(indirect(whereStmt)),
132     construct<ActionStmt>(indirect(Parser<WriteStmt>{})),
133     construct<ActionStmt>(indirect(Parser<ComputedGotoStmt>{})),
134     construct<ActionStmt>(indirect(forallStmt)),
135     construct<ActionStmt>(indirect(Parser<ArithmeticIfStmt>{})),
136     construct<ActionStmt>(indirect(Parser<AssignStmt>{})),
137     construct<ActionStmt>(indirect(Parser<AssignedGotoStmt>{})),
138     construct<ActionStmt>(indirect(Parser<PauseStmt>{}))))
139 
140 // R1102 associate-construct -> associate-stmt block end-associate-stmt
141 TYPE_CONTEXT_PARSER("ASSOCIATE construct"_en_US,
142     construct<AssociateConstruct>(statement(Parser<AssociateStmt>{}), block,
143         statement(Parser<EndAssociateStmt>{})))
144 
145 // R1103 associate-stmt ->
146 //        [associate-construct-name :] ASSOCIATE ( association-list )
147 TYPE_CONTEXT_PARSER("ASSOCIATE statement"_en_US,
148     construct<AssociateStmt>(maybe(name / ":"),
149         "ASSOCIATE" >> parenthesized(nonemptyList(Parser<Association>{}))))
150 
151 // R1104 association -> associate-name => selector
152 TYPE_PARSER(construct<Association>(name, "=>" >> selector))
153 
154 // R1105 selector -> expr | variable
155 TYPE_PARSER(construct<Selector>(variable) / lookAhead(","_tok || ")"_tok) ||
156     construct<Selector>(expr))
157 
158 // R1106 end-associate-stmt -> END ASSOCIATE [associate-construct-name]
159 TYPE_PARSER(construct<EndAssociateStmt>(
160     recovery("END ASSOCIATE" >> maybe(name), endStmtErrorRecovery)))
161 
162 // R1107 block-construct ->
163 //         block-stmt [block-specification-part] block end-block-stmt
164 TYPE_CONTEXT_PARSER("BLOCK construct"_en_US,
165     construct<BlockConstruct>(statement(Parser<BlockStmt>{}),
166         Parser<BlockSpecificationPart>{}, // can be empty
167         block, statement(Parser<EndBlockStmt>{})))
168 
169 // R1108 block-stmt -> [block-construct-name :] BLOCK
170 TYPE_PARSER(construct<BlockStmt>(maybe(name / ":") / "BLOCK"))
171 
172 // R1109 block-specification-part ->
173 //         [use-stmt]... [import-stmt]... [implicit-part]
174 //         [[declaration-construct]... specification-construct]
175 // C1107 prohibits COMMON, EQUIVALENCE, INTENT, NAMELIST, OPTIONAL, VALUE,
176 // and statement function definitions.  C1108 prohibits SAVE /common/.
177 // C1570 indirectly prohibits ENTRY.  These constraints are best enforced later.
178 // The odd grammar rule above would have the effect of forcing any
179 // trailing FORMAT and DATA statements after the last specification-construct
180 // to be recognized as part of the block-construct's block part rather than
181 // its block-specification-part, a distinction without any apparent difference.
182 TYPE_PARSER(construct<BlockSpecificationPart>(specificationPart))
183 
184 // R1110 end-block-stmt -> END BLOCK [block-construct-name]
185 TYPE_PARSER(construct<EndBlockStmt>(
186     recovery("END BLOCK" >> maybe(name), endStmtErrorRecovery)))
187 
188 // R1111 change-team-construct -> change-team-stmt block end-change-team-stmt
189 TYPE_CONTEXT_PARSER("CHANGE TEAM construct"_en_US,
190     construct<ChangeTeamConstruct>(statement(Parser<ChangeTeamStmt>{}), block,
191         statement(Parser<EndChangeTeamStmt>{})))
192 
193 // R1112 change-team-stmt ->
194 //         [team-construct-name :] CHANGE TEAM
195 //         ( team-value [, coarray-association-list] [, sync-stat-list] )
196 TYPE_CONTEXT_PARSER("CHANGE TEAM statement"_en_US,
197     construct<ChangeTeamStmt>(maybe(name / ":"),
198         "CHANGE TEAM"_sptok >> "("_tok >> teamValue,
199         defaulted("," >> nonemptyList(Parser<CoarrayAssociation>{})),
200         defaulted("," >> nonemptyList(statOrErrmsg))) /
201         ")")
202 
203 // R1113 coarray-association -> codimension-decl => selector
204 TYPE_PARSER(
205     construct<CoarrayAssociation>(Parser<CodimensionDecl>{}, "=>" >> selector))
206 
207 // R1114 end-change-team-stmt ->
208 //         END TEAM [( [sync-stat-list] )] [team-construct-name]
209 TYPE_CONTEXT_PARSER("END TEAM statement"_en_US,
210     construct<EndChangeTeamStmt>(
211         "END TEAM" >> defaulted(parenthesized(optionalList(statOrErrmsg))),
212         maybe(name)))
213 
214 // R1117 critical-stmt ->
215 //         [critical-construct-name :] CRITICAL [( [sync-stat-list] )]
216 TYPE_CONTEXT_PARSER("CRITICAL statement"_en_US,
217     construct<CriticalStmt>(maybe(name / ":"),
218         "CRITICAL" >> defaulted(parenthesized(optionalList(statOrErrmsg)))))
219 
220 // R1116 critical-construct -> critical-stmt block end-critical-stmt
221 TYPE_CONTEXT_PARSER("CRITICAL construct"_en_US,
222     construct<CriticalConstruct>(statement(Parser<CriticalStmt>{}), block,
223         statement(Parser<EndCriticalStmt>{})))
224 
225 // R1118 end-critical-stmt -> END CRITICAL [critical-construct-name]
226 TYPE_PARSER(construct<EndCriticalStmt>(
227     recovery("END CRITICAL" >> maybe(name), endStmtErrorRecovery)))
228 
229 // R1119 do-construct -> do-stmt block end-do
230 // R1120 do-stmt -> nonlabel-do-stmt | label-do-stmt
231 TYPE_CONTEXT_PARSER("DO construct"_en_US,
232     construct<DoConstruct>(
233         statement(Parser<NonLabelDoStmt>{}) / EnterNonlabelDoConstruct{}, block,
234         statement(Parser<EndDoStmt>{}) / LeaveDoConstruct{}))
235 
236 // R1125 concurrent-header ->
237 //         ( [integer-type-spec ::] concurrent-control-list
238 //         [, scalar-mask-expr] )
239 TYPE_PARSER(parenthesized(construct<ConcurrentHeader>(
240     maybe(integerTypeSpec / "::"), nonemptyList(Parser<ConcurrentControl>{}),
241     maybe("," >> scalarLogicalExpr))))
242 
243 // R1126 concurrent-control ->
244 //         index-name = concurrent-limit : concurrent-limit [: concurrent-step]
245 // R1127 concurrent-limit -> scalar-int-expr
246 // R1128 concurrent-step -> scalar-int-expr
247 TYPE_PARSER(construct<ConcurrentControl>(name / "=", scalarIntExpr / ":",
248     scalarIntExpr, maybe(":" >> scalarIntExpr)))
249 
250 // R1130 locality-spec ->
251 //         LOCAL ( variable-name-list ) | LOCAL_INIT ( variable-name-list ) |
252 //         SHARED ( variable-name-list ) | DEFAULT ( NONE )
253 TYPE_PARSER(construct<LocalitySpec>(construct<LocalitySpec::Local>(
254                 "LOCAL" >> parenthesized(listOfNames))) ||
255     construct<LocalitySpec>(construct<LocalitySpec::LocalInit>(
256         "LOCAL_INIT"_sptok >> parenthesized(listOfNames))) ||
257     construct<LocalitySpec>(construct<LocalitySpec::Shared>(
258         "SHARED" >> parenthesized(listOfNames))) ||
259     construct<LocalitySpec>(
260         construct<LocalitySpec::DefaultNone>("DEFAULT ( NONE )"_tok)))
261 
262 // R1123 loop-control ->
263 //         [,] do-variable = scalar-int-expr , scalar-int-expr
264 //           [, scalar-int-expr] |
265 //         [,] WHILE ( scalar-logical-expr ) |
266 //         [,] CONCURRENT concurrent-header concurrent-locality
267 // R1129 concurrent-locality -> [locality-spec]...
268 TYPE_CONTEXT_PARSER("loop control"_en_US,
269     maybe(","_tok) >>
270         (construct<LoopControl>(loopBounds(scalarExpr)) ||
271             construct<LoopControl>(
272                 "WHILE" >> parenthesized(scalarLogicalExpr)) ||
273             construct<LoopControl>(construct<LoopControl::Concurrent>(
274                 "CONCURRENT" >> concurrentHeader,
275                 many(Parser<LocalitySpec>{})))))
276 
277 // R1121 label-do-stmt -> [do-construct-name :] DO label [loop-control]
278 TYPE_CONTEXT_PARSER("label DO statement"_en_US,
279     construct<LabelDoStmt>(
280         maybe(name / ":"), "DO" >> label, maybe(loopControl)))
281 
282 // R1122 nonlabel-do-stmt -> [do-construct-name :] DO [loop-control]
283 TYPE_CONTEXT_PARSER("nonlabel DO statement"_en_US,
284     construct<NonLabelDoStmt>(maybe(name / ":"), "DO" >> maybe(loopControl)))
285 
286 // R1132 end-do-stmt -> END DO [do-construct-name]
287 TYPE_CONTEXT_PARSER("END DO statement"_en_US,
288     construct<EndDoStmt>(
289         recovery("END DO" >> maybe(name), endStmtErrorRecovery)))
290 
291 // R1133 cycle-stmt -> CYCLE [do-construct-name]
292 TYPE_CONTEXT_PARSER(
293     "CYCLE statement"_en_US, construct<CycleStmt>("CYCLE" >> maybe(name)))
294 
295 // R1134 if-construct ->
296 //         if-then-stmt block [else-if-stmt block]...
297 //         [else-stmt block] end-if-stmt
298 // R1135 if-then-stmt -> [if-construct-name :] IF ( scalar-logical-expr )
299 // THEN R1136 else-if-stmt ->
300 //         ELSE IF ( scalar-logical-expr ) THEN [if-construct-name]
301 // R1137 else-stmt -> ELSE [if-construct-name]
302 // R1138 end-if-stmt -> END IF [if-construct-name]
303 TYPE_CONTEXT_PARSER("IF construct"_en_US,
304     construct<IfConstruct>(
305         statement(construct<IfThenStmt>(maybe(name / ":"),
306             "IF" >> parenthesized(scalarLogicalExpr) / "THEN")),
307         block,
308         many(construct<IfConstruct::ElseIfBlock>(
309             unambiguousStatement(construct<ElseIfStmt>(
310                 "ELSE IF" >> parenthesized(scalarLogicalExpr),
311                 "THEN" >> maybe(name))),
312             block)),
313         maybe(construct<IfConstruct::ElseBlock>(
314             statement(construct<ElseStmt>("ELSE" >> maybe(name))), block)),
315         statement(construct<EndIfStmt>(
316             recovery("END IF" >> maybe(name), endStmtErrorRecovery)))))
317 
318 // R1139 if-stmt -> IF ( scalar-logical-expr ) action-stmt
319 TYPE_CONTEXT_PARSER("IF statement"_en_US,
320     construct<IfStmt>("IF" >> parenthesized(scalarLogicalExpr),
321         unlabeledStatement(actionStmt)))
322 
323 // R1140 case-construct ->
324 //         select-case-stmt [case-stmt block]... end-select-stmt
325 TYPE_CONTEXT_PARSER("SELECT CASE construct"_en_US,
326     construct<CaseConstruct>(statement(Parser<SelectCaseStmt>{}),
327         many(construct<CaseConstruct::Case>(
328             unambiguousStatement(Parser<CaseStmt>{}), block)),
329         statement(endSelectStmt)))
330 
331 // R1141 select-case-stmt -> [case-construct-name :] SELECT CASE ( case-expr
332 // ) R1144 case-expr -> scalar-expr
333 TYPE_CONTEXT_PARSER("SELECT CASE statement"_en_US,
334     construct<SelectCaseStmt>(
335         maybe(name / ":"), "SELECT CASE" >> parenthesized(scalar(expr))))
336 
337 // R1142 case-stmt -> CASE case-selector [case-construct-name]
338 TYPE_CONTEXT_PARSER("CASE statement"_en_US,
339     construct<CaseStmt>("CASE" >> Parser<CaseSelector>{}, maybe(name)))
340 
341 // R1143 end-select-stmt -> END SELECT [case-construct-name]
342 // R1151 end-select-rank-stmt -> END SELECT [select-construct-name]
343 // R1155 end-select-type-stmt -> END SELECT [select-construct-name]
344 TYPE_PARSER(construct<EndSelectStmt>(
345     recovery("END SELECT" >> maybe(name), endStmtErrorRecovery)))
346 
347 // R1145 case-selector -> ( case-value-range-list ) | DEFAULT
348 constexpr auto defaultKeyword{construct<Default>("DEFAULT"_tok)};
349 TYPE_PARSER(parenthesized(construct<CaseSelector>(
350                 nonemptyList(Parser<CaseValueRange>{}))) ||
351     construct<CaseSelector>(defaultKeyword))
352 
353 // R1147 case-value -> scalar-constant-expr
354 constexpr auto caseValue{scalar(constantExpr)};
355 
356 // R1146 case-value-range ->
357 //         case-value | case-value : | : case-value | case-value : case-value
358 TYPE_PARSER(construct<CaseValueRange>(construct<CaseValueRange::Range>(
359                 construct<std::optional<CaseValue>>(caseValue),
360                 ":" >> maybe(caseValue))) ||
361     construct<CaseValueRange>(
362         construct<CaseValueRange::Range>(construct<std::optional<CaseValue>>(),
363             ":" >> construct<std::optional<CaseValue>>(caseValue))) ||
364     construct<CaseValueRange>(caseValue))
365 
366 // R1148 select-rank-construct ->
367 //         select-rank-stmt [select-rank-case-stmt block]...
368 //         end-select-rank-stmt
369 TYPE_CONTEXT_PARSER("SELECT RANK construct"_en_US,
370     construct<SelectRankConstruct>(statement(Parser<SelectRankStmt>{}),
371         many(construct<SelectRankConstruct::RankCase>(
372             unambiguousStatement(Parser<SelectRankCaseStmt>{}), block)),
373         statement(endSelectStmt)))
374 
375 // R1149 select-rank-stmt ->
376 //         [select-construct-name :] SELECT RANK
377 //         ( [associate-name =>] selector )
378 TYPE_CONTEXT_PARSER("SELECT RANK statement"_en_US,
379     construct<SelectRankStmt>(maybe(name / ":"),
380         "SELECT RANK"_sptok >> "("_tok >> maybe(name / "=>"), selector / ")"))
381 
382 // R1150 select-rank-case-stmt ->
383 //         RANK ( scalar-int-constant-expr ) [select-construct-name] |
384 //         RANK ( * ) [select-construct-name] |
385 //         RANK DEFAULT [select-construct-name]
386 TYPE_CONTEXT_PARSER("RANK case statement"_en_US,
387     "RANK" >> (construct<SelectRankCaseStmt>(
388                   parenthesized(construct<SelectRankCaseStmt::Rank>(
389                                     scalarIntConstantExpr) ||
390                       construct<SelectRankCaseStmt::Rank>(star)) ||
391                       construct<SelectRankCaseStmt::Rank>(defaultKeyword),
392                   maybe(name))))
393 
394 // R1152 select-type-construct ->
395 //         select-type-stmt [type-guard-stmt block]... end-select-type-stmt
396 TYPE_CONTEXT_PARSER("SELECT TYPE construct"_en_US,
397     construct<SelectTypeConstruct>(statement(Parser<SelectTypeStmt>{}),
398         many(construct<SelectTypeConstruct::TypeCase>(
399             unambiguousStatement(Parser<TypeGuardStmt>{}), block)),
400         statement(endSelectStmt)))
401 
402 // R1153 select-type-stmt ->
403 //         [select-construct-name :] SELECT TYPE
404 //         ( [associate-name =>] selector )
405 TYPE_CONTEXT_PARSER("SELECT TYPE statement"_en_US,
406     construct<SelectTypeStmt>(maybe(name / ":"),
407         "SELECT TYPE (" >> maybe(name / "=>"), selector / ")"))
408 
409 // R1154 type-guard-stmt ->
410 //         TYPE IS ( type-spec ) [select-construct-name] |
411 //         CLASS IS ( derived-type-spec ) [select-construct-name] |
412 //         CLASS DEFAULT [select-construct-name]
413 TYPE_CONTEXT_PARSER("type guard statement"_en_US,
414     construct<TypeGuardStmt>("TYPE IS"_sptok >>
415                 parenthesized(construct<TypeGuardStmt::Guard>(typeSpec)) ||
416             "CLASS IS"_sptok >> parenthesized(construct<TypeGuardStmt::Guard>(
417                                     derivedTypeSpec)) ||
418             construct<TypeGuardStmt::Guard>("CLASS" >> defaultKeyword),
419         maybe(name)))
420 
421 // R1156 exit-stmt -> EXIT [construct-name]
422 TYPE_CONTEXT_PARSER(
423     "EXIT statement"_en_US, construct<ExitStmt>("EXIT" >> maybe(name)))
424 
425 // R1157 goto-stmt -> GO TO label
426 TYPE_CONTEXT_PARSER(
427     "GOTO statement"_en_US, construct<GotoStmt>("GO TO" >> label))
428 
429 // R1158 computed-goto-stmt -> GO TO ( label-list ) [,] scalar-int-expr
430 TYPE_CONTEXT_PARSER("computed GOTO statement"_en_US,
431     construct<ComputedGotoStmt>("GO TO" >> parenthesized(nonemptyList(label)),
432         maybe(","_tok) >> scalarIntExpr))
433 
434 // R1160 stop-stmt -> STOP [stop-code] [, QUIET = scalar-logical-expr]
435 // R1161 error-stop-stmt ->
436 //         ERROR STOP [stop-code] [, QUIET = scalar-logical-expr]
437 TYPE_CONTEXT_PARSER("STOP statement"_en_US,
438     construct<StopStmt>("STOP" >> pure(StopStmt::Kind::Stop) ||
439             "ERROR STOP"_sptok >> pure(StopStmt::Kind::ErrorStop),
440         maybe(Parser<StopCode>{}), maybe(", QUIET =" >> scalarLogicalExpr)))
441 
442 // R1162 stop-code -> scalar-default-char-expr | scalar-int-expr
443 // The two alternatives for stop-code can't be distinguished at
444 // parse time.
445 TYPE_PARSER(construct<StopCode>(scalar(expr)))
446 
447 // R1164 sync-all-stmt -> SYNC ALL [( [sync-stat-list] )]
448 TYPE_CONTEXT_PARSER("SYNC ALL statement"_en_US,
449     construct<SyncAllStmt>("SYNC ALL"_sptok >>
450         defaulted(parenthesized(optionalList(statOrErrmsg)))))
451 
452 // R1166 sync-images-stmt -> SYNC IMAGES ( image-set [, sync-stat-list] )
453 // R1167 image-set -> int-expr | *
454 TYPE_CONTEXT_PARSER("SYNC IMAGES statement"_en_US,
455     "SYNC IMAGES"_sptok >> parenthesized(construct<SyncImagesStmt>(
456                                construct<SyncImagesStmt::ImageSet>(intExpr) ||
457                                    construct<SyncImagesStmt::ImageSet>(star),
458                                defaulted("," >> nonemptyList(statOrErrmsg)))))
459 
460 // R1168 sync-memory-stmt -> SYNC MEMORY [( [sync-stat-list] )]
461 TYPE_CONTEXT_PARSER("SYNC MEMORY statement"_en_US,
462     construct<SyncMemoryStmt>("SYNC MEMORY"_sptok >>
463         defaulted(parenthesized(optionalList(statOrErrmsg)))))
464 
465 // R1169 sync-team-stmt -> SYNC TEAM ( team-value [, sync-stat-list] )
466 TYPE_CONTEXT_PARSER("SYNC TEAM statement"_en_US,
467     construct<SyncTeamStmt>("SYNC TEAM"_sptok >> "("_tok >> teamValue,
468         defaulted("," >> nonemptyList(statOrErrmsg)) / ")"))
469 
470 // R1170 event-post-stmt -> EVENT POST ( event-variable [, sync-stat-list] )
471 // R1171 event-variable -> scalar-variable
472 TYPE_CONTEXT_PARSER("EVENT POST statement"_en_US,
473     construct<EventPostStmt>("EVENT POST"_sptok >> "("_tok >> scalar(variable),
474         defaulted("," >> nonemptyList(statOrErrmsg)) / ")"))
475 
476 // R1172 event-wait-stmt ->
477 //         EVENT WAIT ( event-variable [, event-wait-spec-list] )
478 TYPE_CONTEXT_PARSER("EVENT WAIT statement"_en_US,
479     construct<EventWaitStmt>("EVENT WAIT"_sptok >> "("_tok >> scalar(variable),
480         defaulted("," >> nonemptyList(Parser<EventWaitStmt::EventWaitSpec>{})) /
481             ")"))
482 
483 // R1174 until-spec -> UNTIL_COUNT = scalar-int-expr
484 constexpr auto untilSpec{"UNTIL_COUNT =" >> scalarIntExpr};
485 
486 // R1173 event-wait-spec -> until-spec | sync-stat
487 TYPE_PARSER(construct<EventWaitStmt::EventWaitSpec>(untilSpec) ||
488     construct<EventWaitStmt::EventWaitSpec>(statOrErrmsg))
489 
490 // R1177 team-variable -> scalar-variable
491 constexpr auto teamVariable{scalar(variable)};
492 
493 // R1175 form-team-stmt ->
494 //         FORM TEAM ( team-number , team-variable [, form-team-spec-list] )
495 // R1176 team-number -> scalar-int-expr
496 TYPE_CONTEXT_PARSER("FORM TEAM statement"_en_US,
497     construct<FormTeamStmt>("FORM TEAM"_sptok >> "("_tok >> scalarIntExpr,
498         "," >> teamVariable,
499         defaulted("," >> nonemptyList(Parser<FormTeamStmt::FormTeamSpec>{})) /
500             ")"))
501 
502 // R1178 form-team-spec -> NEW_INDEX = scalar-int-expr | sync-stat
503 TYPE_PARSER(
504     construct<FormTeamStmt::FormTeamSpec>("NEW_INDEX =" >> scalarIntExpr) ||
505     construct<FormTeamStmt::FormTeamSpec>(statOrErrmsg))
506 
507 // R1182 lock-variable -> scalar-variable
508 constexpr auto lockVariable{scalar(variable)};
509 
510 // R1179 lock-stmt -> LOCK ( lock-variable [, lock-stat-list] )
511 TYPE_CONTEXT_PARSER("LOCK statement"_en_US,
512     construct<LockStmt>("LOCK (" >> lockVariable,
513         defaulted("," >> nonemptyList(Parser<LockStmt::LockStat>{})) / ")"))
514 
515 // R1180 lock-stat -> ACQUIRED_LOCK = scalar-logical-variable | sync-stat
516 TYPE_PARSER(
517     construct<LockStmt::LockStat>("ACQUIRED_LOCK =" >> scalarLogicalVariable) ||
518     construct<LockStmt::LockStat>(statOrErrmsg))
519 
520 // R1181 unlock-stmt -> UNLOCK ( lock-variable [, sync-stat-list] )
521 TYPE_CONTEXT_PARSER("UNLOCK statement"_en_US,
522     construct<UnlockStmt>("UNLOCK (" >> lockVariable,
523         defaulted("," >> nonemptyList(statOrErrmsg)) / ")"))
524 
525 } // namespace Fortran::parser
526