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