Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- include/flang/Parser/parse-tree.h -----------------------*- C++ -*-===// |
---|---|
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 | #ifndef FORTRAN_PARSER_PARSE_TREE_H_ |
10 | #define FORTRAN_PARSER_PARSE_TREE_H_ |
11 | |
12 | // Defines the classes used to represent successful reductions of productions |
13 | // in the Fortran grammar. The names and content of these definitions |
14 | // adhere closely to the syntax specifications in the language standard (q.v.) |
15 | // that are transcribed here and referenced via their requirement numbers. |
16 | // The representations of some productions that may also be of use in the |
17 | // run-time I/O support library have been isolated into a distinct header file |
18 | // (viz., format-specification.h). |
19 | |
20 | #include "char-block.h" |
21 | #include "characters.h" |
22 | #include "format-specification.h" |
23 | #include "message.h" |
24 | #include "provenance.h" |
25 | #include "flang/Common/Fortran.h" |
26 | #include "flang/Common/idioms.h" |
27 | #include "flang/Common/indirection.h" |
28 | #include "llvm/Frontend/OpenACC/ACC.h.inc" |
29 | #include "llvm/Frontend/OpenMP/OMPConstants.h" |
30 | #include <cinttypes> |
31 | #include <list> |
32 | #include <memory> |
33 | #include <optional> |
34 | #include <string> |
35 | #include <tuple> |
36 | #include <type_traits> |
37 | #include <utility> |
38 | #include <variant> |
39 | |
40 | // Parse tree node class types do not have default constructors. They |
41 | // explicitly declare "T() {} = delete;" to make this clear. This restriction |
42 | // prevents the introduction of what would be a viral requirement to include |
43 | // std::monostate among most std::variant<> discriminated union members. |
44 | |
45 | // Parse tree node class types do not have copy constructors or copy assignment |
46 | // operators. They are explicitly declared "= delete;" to make this clear, |
47 | // although a C++ compiler wouldn't default them anyway due to the presence |
48 | // of explicitly defaulted move constructors and move assignments. |
49 | |
50 | CLASS_TRAIT(EmptyTrait) |
51 | CLASS_TRAIT(WrapperTrait) |
52 | CLASS_TRAIT(UnionTrait) |
53 | CLASS_TRAIT(TupleTrait) |
54 | CLASS_TRAIT(ConstraintTrait) |
55 | |
56 | // Some parse tree nodes have fields in them to cache the results of a |
57 | // successful semantic analysis later. Their types are forward declared |
58 | // here. |
59 | namespace Fortran::semantics { |
60 | class Symbol; |
61 | class DeclTypeSpec; |
62 | class DerivedTypeSpec; |
63 | } // namespace Fortran::semantics |
64 | |
65 | // Expressions in the parse tree have owning pointers that can be set to |
66 | // type-checked generic expression representations by semantic analysis. |
67 | namespace Fortran::evaluate { |
68 | struct GenericExprWrapper; // forward definition, wraps Expr<SomeType> |
69 | struct GenericAssignmentWrapper; // forward definition, represent assignment |
70 | class ProcedureRef; // forward definition, represents a CALL or function ref |
71 | } // namespace Fortran::evaluate |
72 | |
73 | // Most non-template classes in this file use these default definitions |
74 | // for their move constructor and move assignment operator=, and disable |
75 | // their copy constructor and copy assignment operator=. |
76 | #define COPY_AND_ASSIGN_BOILERPLATE(classname) \ |
77 | classname(classname &&) = default; \ |
78 | classname &operator=(classname &&) = default; \ |
79 | classname(const classname &) = delete; \ |
80 | classname &operator=(const classname &) = delete |
81 | |
82 | // Almost all classes in this file have no default constructor. |
83 | #define BOILERPLATE(classname) \ |
84 | COPY_AND_ASSIGN_BOILERPLATE(classname); \ |
85 | classname() = delete |
86 | |
87 | // Empty classes are often used below as alternatives in std::variant<> |
88 | // discriminated unions. |
89 | #define EMPTY_CLASS(classname) \ |
90 | struct classname { \ |
91 | classname() {} \ |
92 | classname(const classname &) {} \ |
93 | classname(classname &&) {} \ |
94 | classname &operator=(const classname &) { return *this; }; \ |
95 | classname &operator=(classname &&) { return *this; }; \ |
96 | using EmptyTrait = std::true_type; \ |
97 | } |
98 | |
99 | // Many classes below simply wrap a std::variant<> discriminated union, |
100 | // which is conventionally named "u". |
101 | #define UNION_CLASS_BOILERPLATE(classname) \ |
102 | template <typename A, typename = common::NoLvalue<A>> \ |
103 | classname(A &&x) : u(std::move(x)) {} \ |
104 | using UnionTrait = std::true_type; \ |
105 | BOILERPLATE(classname) |
106 | |
107 | // Many other classes below simply wrap a std::tuple<> structure, which |
108 | // is conventionally named "t". |
109 | #define TUPLE_CLASS_BOILERPLATE(classname) \ |
110 | template <typename... Ts, typename = common::NoLvalue<Ts...>> \ |
111 | classname(Ts &&...args) : t(std::move(args)...) {} \ |
112 | using TupleTrait = std::true_type; \ |
113 | BOILERPLATE(classname) |
114 | |
115 | // Many other classes below simply wrap a single data member, which is |
116 | // conventionally named "v". |
117 | #define WRAPPER_CLASS_BOILERPLATE(classname, type) \ |
118 | BOILERPLATE(classname); \ |
119 | classname(type &&x) : v(std::move(x)) {} \ |
120 | using WrapperTrait = std::true_type; \ |
121 | type v |
122 | |
123 | #define WRAPPER_CLASS(classname, type) \ |
124 | struct classname { \ |
125 | WRAPPER_CLASS_BOILERPLATE(classname, type); \ |
126 | } |
127 | |
128 | namespace Fortran::parser { |
129 | |
130 | // These are the unavoidable recursively-defined productions of Fortran. |
131 | // Some references to the representations of their parses require |
132 | // indirection. The Indirect<> pointer wrapper class is used to |
133 | // enforce ownership semantics and non-nullability. |
134 | struct SpecificationPart; // R504 |
135 | struct ExecutableConstruct; // R514 |
136 | struct ActionStmt; // R515 |
137 | struct AcImpliedDo; // R774 |
138 | struct DataImpliedDo; // R840 |
139 | struct Designator; // R901 |
140 | struct Variable; // R902 |
141 | struct Expr; // R1001 |
142 | struct WhereConstruct; // R1042 |
143 | struct ForallConstruct; // R1050 |
144 | struct InputImpliedDo; // R1218 |
145 | struct OutputImpliedDo; // R1218 |
146 | struct FunctionReference; // R1520 |
147 | struct FunctionSubprogram; // R1529 |
148 | struct SubroutineSubprogram; // R1534 |
149 | |
150 | // These additional forward references are declared so that the order of |
151 | // class definitions in this header file can remain reasonably consistent |
152 | // with order of the the requirement productions in the grammar. |
153 | struct DerivedTypeDef; // R726 |
154 | struct EnumDef; // R759 |
155 | struct TypeDeclarationStmt; // R801 |
156 | struct AccessStmt; // R827 |
157 | struct AllocatableStmt; // R829 |
158 | struct AsynchronousStmt; // R831 |
159 | struct BindStmt; // R832 |
160 | struct CodimensionStmt; // R834 |
161 | struct ContiguousStmt; // R836 |
162 | struct DataStmt; // R837 |
163 | struct DataStmtValue; // R843 |
164 | struct DimensionStmt; // R848 |
165 | struct IntentStmt; // R849 |
166 | struct OptionalStmt; // R850 |
167 | struct ParameterStmt; // R851 |
168 | struct OldParameterStmt; |
169 | struct PointerStmt; // R853 |
170 | struct ProtectedStmt; // R855 |
171 | struct SaveStmt; // R856 |
172 | struct TargetStmt; // R859 |
173 | struct ValueStmt; // R861 |
174 | struct VolatileStmt; // R862 |
175 | struct ImplicitStmt; // R863 |
176 | struct ImportStmt; // R867 |
177 | struct NamelistStmt; // R868 |
178 | struct EquivalenceStmt; // R870 |
179 | struct CommonStmt; // R873 |
180 | struct Substring; // R908 |
181 | struct CharLiteralConstantSubstring; |
182 | struct SubstringInquiry; |
183 | struct DataRef; // R911 |
184 | struct StructureComponent; // R913 |
185 | struct CoindexedNamedObject; // R914 |
186 | struct ArrayElement; // R917 |
187 | struct AllocateStmt; // R927 |
188 | struct NullifyStmt; // R939 |
189 | struct DeallocateStmt; // R941 |
190 | struct AssignmentStmt; // R1032 |
191 | struct PointerAssignmentStmt; // R1033 |
192 | struct WhereStmt; // R1041, R1045, R1046 |
193 | struct ForallStmt; // R1055 |
194 | struct AssociateConstruct; // R1102 |
195 | struct BlockConstruct; // R1107 |
196 | struct ChangeTeamConstruct; // R1111 |
197 | struct CriticalConstruct; // R1116 |
198 | struct DoConstruct; // R1119 |
199 | struct LabelDoStmt; // R1121 |
200 | struct ConcurrentHeader; // R1125 |
201 | struct EndDoStmt; // R1132 |
202 | struct CycleStmt; // R1133 |
203 | struct IfConstruct; // R1134 |
204 | struct IfStmt; // R1139 |
205 | struct CaseConstruct; // R1140 |
206 | struct SelectRankConstruct; // R1148 |
207 | struct SelectTypeConstruct; // R1152 |
208 | struct ExitStmt; // R1156 |
209 | struct GotoStmt; // R1157 |
210 | struct ComputedGotoStmt; // R1158 |
211 | struct StopStmt; // R1160, R1161 |
212 | struct NotifyWaitStmt; // F2023: R1166 |
213 | struct SyncAllStmt; // R1164 |
214 | struct SyncImagesStmt; // R1166 |
215 | struct SyncMemoryStmt; // R1168 |
216 | struct SyncTeamStmt; // R1169 |
217 | struct EventPostStmt; // R1170, R1171 |
218 | struct EventWaitSpec; // F2023: R1177 |
219 | struct EventWaitStmt; // R1172, R1173, R1174 |
220 | struct FormTeamStmt; // R1175, R1176, R1177 |
221 | struct LockStmt; // R1178 |
222 | struct UnlockStmt; // R1180 |
223 | struct OpenStmt; // R1204 |
224 | struct CloseStmt; // R1208 |
225 | struct ReadStmt; // R1210 |
226 | struct WriteStmt; // R1211 |
227 | struct PrintStmt; // R1212 |
228 | struct WaitStmt; // R1222 |
229 | struct BackspaceStmt; // R1224 |
230 | struct EndfileStmt; // R1225 |
231 | struct RewindStmt; // R1226 |
232 | struct FlushStmt; // R1228 |
233 | struct InquireStmt; // R1230 |
234 | struct FormatStmt; // R1301 |
235 | struct MainProgram; // R1401 |
236 | struct Module; // R1404 |
237 | struct UseStmt; // R1409 |
238 | struct Submodule; // R1416 |
239 | struct BlockData; // R1420 |
240 | struct InterfaceBlock; // R1501 |
241 | struct GenericSpec; // R1508 |
242 | struct GenericStmt; // R1510 |
243 | struct ExternalStmt; // R1511 |
244 | struct ProcedureDeclarationStmt; // R1512 |
245 | struct IntrinsicStmt; // R1519 |
246 | struct Call; // R1520 & R1521 |
247 | struct CallStmt; // R1521 |
248 | struct ProcedureDesignator; // R1522 |
249 | struct ActualArg; // R1524 |
250 | struct SeparateModuleSubprogram; // R1538 |
251 | struct EntryStmt; // R1541 |
252 | struct ReturnStmt; // R1542 |
253 | struct StmtFunctionStmt; // R1544 |
254 | |
255 | // Directives, extensions, and deprecated statements |
256 | struct CompilerDirective; |
257 | struct BasedPointerStmt; |
258 | struct CUDAAttributesStmt; |
259 | struct StructureDef; |
260 | struct ArithmeticIfStmt; |
261 | struct AssignStmt; |
262 | struct AssignedGotoStmt; |
263 | struct PauseStmt; |
264 | struct OpenACCConstruct; |
265 | struct AccEndCombinedDirective; |
266 | struct OpenACCDeclarativeConstruct; |
267 | struct OpenACCRoutineConstruct; |
268 | struct OpenMPConstruct; |
269 | struct OpenMPDeclarativeConstruct; |
270 | struct OmpEndLoopDirective; |
271 | struct CUFKernelDoConstruct; |
272 | |
273 | // Cooked character stream locations |
274 | using Location = const char *; |
275 | |
276 | // A parse tree node with provenance only |
277 | struct Verbatim { |
278 | // Allow a no-arg constructor for Verbatim so parsers can return `RESULT{}`. |
279 | constexpr Verbatim() {} |
280 | COPY_AND_ASSIGN_BOILERPLATE(Verbatim); |
281 | using EmptyTrait = std::true_type; |
282 | CharBlock source; |
283 | }; |
284 | |
285 | // Implicit definitions of the Standard |
286 | |
287 | // R403 scalar-xyz -> xyz |
288 | // These template class wrappers correspond to the Standard's modifiers |
289 | // scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz. |
290 | template <typename A> struct Scalar { |
291 | using ConstraintTrait = std::true_type; |
292 | Scalar(Scalar &&that) = default; |
293 | Scalar(A &&that) : thing(std::move(that)) {} |
294 | Scalar &operator=(Scalar &&) = default; |
295 | A thing; |
296 | }; |
297 | |
298 | template <typename A> struct Constant { |
299 | using ConstraintTrait = std::true_type; |
300 | Constant(Constant &&that) = default; |
301 | Constant(A &&that) : thing(std::move(that)) {} |
302 | Constant &operator=(Constant &&) = default; |
303 | A thing; |
304 | }; |
305 | |
306 | template <typename A> struct Integer { |
307 | using ConstraintTrait = std::true_type; |
308 | Integer(Integer &&that) = default; |
309 | Integer(A &&that) : thing(std::move(that)) {} |
310 | Integer &operator=(Integer &&) = default; |
311 | A thing; |
312 | }; |
313 | |
314 | template <typename A> struct Logical { |
315 | using ConstraintTrait = std::true_type; |
316 | Logical(Logical &&that) = default; |
317 | Logical(A &&that) : thing(std::move(that)) {} |
318 | Logical &operator=(Logical &&) = default; |
319 | A thing; |
320 | }; |
321 | |
322 | template <typename A> struct DefaultChar { |
323 | using ConstraintTrait = std::true_type; |
324 | DefaultChar(DefaultChar &&that) = default; |
325 | DefaultChar(A &&that) : thing(std::move(that)) {} |
326 | DefaultChar &operator=(DefaultChar &&) = default; |
327 | A thing; |
328 | }; |
329 | |
330 | using LogicalExpr = Logical<common::Indirection<Expr>>; // R1024 |
331 | using DefaultCharExpr = DefaultChar<common::Indirection<Expr>>; // R1025 |
332 | using IntExpr = Integer<common::Indirection<Expr>>; // R1026 |
333 | using ConstantExpr = Constant<common::Indirection<Expr>>; // R1029 |
334 | using IntConstantExpr = Integer<ConstantExpr>; // R1031 |
335 | using ScalarLogicalExpr = Scalar<LogicalExpr>; |
336 | using ScalarIntExpr = Scalar<IntExpr>; |
337 | using ScalarIntConstantExpr = Scalar<IntConstantExpr>; |
338 | using ScalarDefaultCharExpr = Scalar<DefaultCharExpr>; |
339 | // R1030 default-char-constant-expr is used in the Standard only as part of |
340 | // scalar-default-char-constant-expr. |
341 | using ScalarDefaultCharConstantExpr = Scalar<DefaultChar<ConstantExpr>>; |
342 | |
343 | // R611 label -> digit [digit]... |
344 | using Label = common::Label; // validated later, must be in [1..99999] |
345 | |
346 | // A wrapper for xzy-stmt productions that are statements, so that |
347 | // source provenances and labels have a uniform representation. |
348 | template <typename A> struct UnlabeledStatement { |
349 | explicit UnlabeledStatement(A &&s) : statement(std::move(s)) {} |
350 | CharBlock source; |
351 | A statement; |
352 | }; |
353 | template <typename A> struct Statement : public UnlabeledStatement<A> { |
354 | Statement(std::optional<long> &&lab, A &&s) |
355 | : UnlabeledStatement<A>{std::move(s)}, label(std::move(lab)) {} |
356 | std::optional<Label> label; |
357 | }; |
358 | |
359 | // Error recovery marker |
360 | EMPTY_CLASS(ErrorRecovery); |
361 | |
362 | // R513 other-specification-stmt -> |
363 | // access-stmt | allocatable-stmt | asynchronous-stmt | bind-stmt | |
364 | // codimension-stmt | contiguous-stmt | dimension-stmt | external-stmt | |
365 | // intent-stmt | intrinsic-stmt | namelist-stmt | optional-stmt | |
366 | // pointer-stmt | protected-stmt | save-stmt | target-stmt | |
367 | // volatile-stmt | value-stmt | common-stmt | equivalence-stmt |
368 | // Extension: (Cray) based POINTER statement |
369 | // Extension: CUDA data attribute statement |
370 | struct OtherSpecificationStmt { |
371 | UNION_CLASS_BOILERPLATE(OtherSpecificationStmt); |
372 | std::variant<common::Indirection<AccessStmt>, |
373 | common::Indirection<AllocatableStmt>, |
374 | common::Indirection<AsynchronousStmt>, common::Indirection<BindStmt>, |
375 | common::Indirection<CodimensionStmt>, common::Indirection<ContiguousStmt>, |
376 | common::Indirection<DimensionStmt>, common::Indirection<ExternalStmt>, |
377 | common::Indirection<IntentStmt>, common::Indirection<IntrinsicStmt>, |
378 | common::Indirection<NamelistStmt>, common::Indirection<OptionalStmt>, |
379 | common::Indirection<PointerStmt>, common::Indirection<ProtectedStmt>, |
380 | common::Indirection<SaveStmt>, common::Indirection<TargetStmt>, |
381 | common::Indirection<ValueStmt>, common::Indirection<VolatileStmt>, |
382 | common::Indirection<CommonStmt>, common::Indirection<EquivalenceStmt>, |
383 | common::Indirection<BasedPointerStmt>, |
384 | common::Indirection<CUDAAttributesStmt>> |
385 | u; |
386 | }; |
387 | |
388 | // R508 specification-construct -> |
389 | // derived-type-def | enum-def | generic-stmt | interface-block | |
390 | // parameter-stmt | procedure-declaration-stmt | |
391 | // other-specification-stmt | type-declaration-stmt |
392 | struct SpecificationConstruct { |
393 | UNION_CLASS_BOILERPLATE(SpecificationConstruct); |
394 | std::variant<common::Indirection<DerivedTypeDef>, |
395 | common::Indirection<EnumDef>, Statement<common::Indirection<GenericStmt>>, |
396 | common::Indirection<InterfaceBlock>, |
397 | Statement<common::Indirection<ParameterStmt>>, |
398 | Statement<common::Indirection<OldParameterStmt>>, |
399 | Statement<common::Indirection<ProcedureDeclarationStmt>>, |
400 | Statement<OtherSpecificationStmt>, |
401 | Statement<common::Indirection<TypeDeclarationStmt>>, |
402 | common::Indirection<StructureDef>, |
403 | common::Indirection<OpenACCDeclarativeConstruct>, |
404 | common::Indirection<OpenMPDeclarativeConstruct>, |
405 | common::Indirection<CompilerDirective>> |
406 | u; |
407 | }; |
408 | |
409 | // R506 implicit-part-stmt -> |
410 | // implicit-stmt | parameter-stmt | format-stmt | entry-stmt |
411 | struct ImplicitPartStmt { |
412 | UNION_CLASS_BOILERPLATE(ImplicitPartStmt); |
413 | std::variant<Statement<common::Indirection<ImplicitStmt>>, |
414 | Statement<common::Indirection<ParameterStmt>>, |
415 | Statement<common::Indirection<OldParameterStmt>>, |
416 | Statement<common::Indirection<FormatStmt>>, |
417 | Statement<common::Indirection<EntryStmt>>, |
418 | common::Indirection<CompilerDirective>, |
419 | common::Indirection<OpenACCDeclarativeConstruct>> |
420 | u; |
421 | }; |
422 | |
423 | // R505 implicit-part -> [implicit-part-stmt]... implicit-stmt |
424 | WRAPPER_CLASS(ImplicitPart, std::list<ImplicitPartStmt>); |
425 | |
426 | // R507 declaration-construct -> |
427 | // specification-construct | data-stmt | format-stmt | |
428 | // entry-stmt | stmt-function-stmt |
429 | struct DeclarationConstruct { |
430 | UNION_CLASS_BOILERPLATE(DeclarationConstruct); |
431 | std::variant<SpecificationConstruct, Statement<common::Indirection<DataStmt>>, |
432 | Statement<common::Indirection<FormatStmt>>, |
433 | Statement<common::Indirection<EntryStmt>>, |
434 | Statement<common::Indirection<StmtFunctionStmt>>, ErrorRecovery> |
435 | u; |
436 | }; |
437 | |
438 | // R504 specification-part -> [use-stmt]... [import-stmt]... [implicit-part] |
439 | // [declaration-construct]... |
440 | // PARAMETER, FORMAT, and ENTRY statements that appear before any other |
441 | // kind of declaration-construct will be parsed into the implicit-part, |
442 | // even if there are no IMPLICIT statements. |
443 | struct SpecificationPart { |
444 | TUPLE_CLASS_BOILERPLATE(SpecificationPart); |
445 | std::tuple<std::list<OpenACCDeclarativeConstruct>, |
446 | std::list<OpenMPDeclarativeConstruct>, |
447 | std::list<common::Indirection<CompilerDirective>>, |
448 | std::list<Statement<common::Indirection<UseStmt>>>, |
449 | std::list<Statement<common::Indirection<ImportStmt>>>, ImplicitPart, |
450 | std::list<DeclarationConstruct>> |
451 | t; |
452 | }; |
453 | |
454 | // R512 internal-subprogram -> function-subprogram | subroutine-subprogram |
455 | struct InternalSubprogram { |
456 | UNION_CLASS_BOILERPLATE(InternalSubprogram); |
457 | std::variant<common::Indirection<FunctionSubprogram>, |
458 | common::Indirection<SubroutineSubprogram>> |
459 | u; |
460 | }; |
461 | |
462 | // R1543 contains-stmt -> CONTAINS |
463 | EMPTY_CLASS(ContainsStmt); |
464 | |
465 | // R511 internal-subprogram-part -> contains-stmt [internal-subprogram]... |
466 | struct InternalSubprogramPart { |
467 | TUPLE_CLASS_BOILERPLATE(InternalSubprogramPart); |
468 | std::tuple<Statement<ContainsStmt>, std::list<InternalSubprogram>> t; |
469 | }; |
470 | |
471 | // R1159 continue-stmt -> CONTINUE |
472 | EMPTY_CLASS(ContinueStmt); |
473 | |
474 | // R1163 fail-image-stmt -> FAIL IMAGE |
475 | EMPTY_CLASS(FailImageStmt); |
476 | |
477 | // R515 action-stmt -> |
478 | // allocate-stmt | assignment-stmt | backspace-stmt | call-stmt | |
479 | // close-stmt | continue-stmt | cycle-stmt | deallocate-stmt | |
480 | // endfile-stmt | error-stop-stmt | event-post-stmt | event-wait-stmt | |
481 | // exit-stmt | fail-image-stmt | flush-stmt | form-team-stmt | |
482 | // goto-stmt | if-stmt | inquire-stmt | lock-stmt | notify-wait-stmt | |
483 | // nullify-stmt | open-stmt | pointer-assignment-stmt | print-stmt | |
484 | // read-stmt | return-stmt | rewind-stmt | stop-stmt | sync-all-stmt | |
485 | // sync-images-stmt | sync-memory-stmt | sync-team-stmt | unlock-stmt | |
486 | // wait-stmt | where-stmt | write-stmt | computed-goto-stmt | forall-stmt |
487 | struct ActionStmt { |
488 | UNION_CLASS_BOILERPLATE(ActionStmt); |
489 | std::variant<common::Indirection<AllocateStmt>, |
490 | common::Indirection<AssignmentStmt>, common::Indirection<BackspaceStmt>, |
491 | common::Indirection<CallStmt>, common::Indirection<CloseStmt>, |
492 | ContinueStmt, common::Indirection<CycleStmt>, |
493 | common::Indirection<DeallocateStmt>, common::Indirection<EndfileStmt>, |
494 | common::Indirection<EventPostStmt>, common::Indirection<EventWaitStmt>, |
495 | common::Indirection<ExitStmt>, FailImageStmt, |
496 | common::Indirection<FlushStmt>, common::Indirection<FormTeamStmt>, |
497 | common::Indirection<GotoStmt>, common::Indirection<IfStmt>, |
498 | common::Indirection<InquireStmt>, common::Indirection<LockStmt>, |
499 | common::Indirection<NotifyWaitStmt>, common::Indirection<NullifyStmt>, |
500 | common::Indirection<OpenStmt>, common::Indirection<PointerAssignmentStmt>, |
501 | common::Indirection<PrintStmt>, common::Indirection<ReadStmt>, |
502 | common::Indirection<ReturnStmt>, common::Indirection<RewindStmt>, |
503 | common::Indirection<StopStmt>, common::Indirection<SyncAllStmt>, |
504 | common::Indirection<SyncImagesStmt>, common::Indirection<SyncMemoryStmt>, |
505 | common::Indirection<SyncTeamStmt>, common::Indirection<UnlockStmt>, |
506 | common::Indirection<WaitStmt>, common::Indirection<WhereStmt>, |
507 | common::Indirection<WriteStmt>, common::Indirection<ComputedGotoStmt>, |
508 | common::Indirection<ForallStmt>, common::Indirection<ArithmeticIfStmt>, |
509 | common::Indirection<AssignStmt>, common::Indirection<AssignedGotoStmt>, |
510 | common::Indirection<PauseStmt>> |
511 | u; |
512 | }; |
513 | |
514 | // R514 executable-construct -> |
515 | // action-stmt | associate-construct | block-construct | |
516 | // case-construct | change-team-construct | critical-construct | |
517 | // do-construct | if-construct | select-rank-construct | |
518 | // select-type-construct | where-construct | forall-construct | |
519 | // (CUDA) CUF-kernel-do-construct |
520 | struct ExecutableConstruct { |
521 | UNION_CLASS_BOILERPLATE(ExecutableConstruct); |
522 | std::variant<Statement<ActionStmt>, common::Indirection<AssociateConstruct>, |
523 | common::Indirection<BlockConstruct>, common::Indirection<CaseConstruct>, |
524 | common::Indirection<ChangeTeamConstruct>, |
525 | common::Indirection<CriticalConstruct>, |
526 | Statement<common::Indirection<LabelDoStmt>>, |
527 | Statement<common::Indirection<EndDoStmt>>, |
528 | common::Indirection<DoConstruct>, common::Indirection<IfConstruct>, |
529 | common::Indirection<SelectRankConstruct>, |
530 | common::Indirection<SelectTypeConstruct>, |
531 | common::Indirection<WhereConstruct>, common::Indirection<ForallConstruct>, |
532 | common::Indirection<CompilerDirective>, |
533 | common::Indirection<OpenACCConstruct>, |
534 | common::Indirection<AccEndCombinedDirective>, |
535 | common::Indirection<OpenMPConstruct>, |
536 | common::Indirection<OmpEndLoopDirective>, |
537 | common::Indirection<CUFKernelDoConstruct>> |
538 | u; |
539 | }; |
540 | |
541 | // R510 execution-part-construct -> |
542 | // executable-construct | format-stmt | entry-stmt | data-stmt |
543 | // Extension (PGI/Intel): also accept NAMELIST in execution part |
544 | struct ExecutionPartConstruct { |
545 | UNION_CLASS_BOILERPLATE(ExecutionPartConstruct); |
546 | std::variant<ExecutableConstruct, Statement<common::Indirection<FormatStmt>>, |
547 | Statement<common::Indirection<EntryStmt>>, |
548 | Statement<common::Indirection<DataStmt>>, |
549 | Statement<common::Indirection<NamelistStmt>>, ErrorRecovery> |
550 | u; |
551 | }; |
552 | |
553 | // R509 execution-part -> executable-construct [execution-part-construct]... |
554 | // R1101 block -> [execution-part-construct]... |
555 | using Block = std::list<ExecutionPartConstruct>; |
556 | WRAPPER_CLASS(ExecutionPart, Block); |
557 | |
558 | // R502 program-unit -> |
559 | // main-program | external-subprogram | module | submodule | block-data |
560 | // R503 external-subprogram -> function-subprogram | subroutine-subprogram |
561 | struct ProgramUnit { |
562 | UNION_CLASS_BOILERPLATE(ProgramUnit); |
563 | std::variant<common::Indirection<MainProgram>, |
564 | common::Indirection<FunctionSubprogram>, |
565 | common::Indirection<SubroutineSubprogram>, common::Indirection<Module>, |
566 | common::Indirection<Submodule>, common::Indirection<BlockData>, |
567 | common::Indirection<CompilerDirective>, |
568 | common::Indirection<OpenACCRoutineConstruct>> |
569 | u; |
570 | }; |
571 | |
572 | // R501 program -> program-unit [program-unit]... |
573 | // This is the top-level production. |
574 | WRAPPER_CLASS(Program, std::list<ProgramUnit>); |
575 | |
576 | // R603 name -> letter [alphanumeric-character]... |
577 | struct Name { |
578 | std::string ToString() const { return source.ToString(); } |
579 | CharBlock source; |
580 | mutable semantics::Symbol *symbol{nullptr}; // filled in during semantics |
581 | }; |
582 | |
583 | // R516 keyword -> name |
584 | WRAPPER_CLASS(Keyword, Name); |
585 | |
586 | // R606 named-constant -> name |
587 | WRAPPER_CLASS(NamedConstant, Name); |
588 | |
589 | // R1003 defined-unary-op -> . letter [letter]... . |
590 | // R1023 defined-binary-op -> . letter [letter]... . |
591 | // R1414 local-defined-operator -> defined-unary-op | defined-binary-op |
592 | // R1415 use-defined-operator -> defined-unary-op | defined-binary-op |
593 | // The Name here is stored with the dots; e.g., .FOO. |
594 | WRAPPER_CLASS(DefinedOpName, Name); |
595 | |
596 | // R608 intrinsic-operator -> |
597 | // ** | * | / | + | - | // | .LT. | .LE. | .EQ. | .NE. | .GE. | .GT. | |
598 | // .NOT. | .AND. | .OR. | .EQV. | .NEQV. |
599 | // R609 defined-operator -> |
600 | // defined-unary-op | defined-binary-op | extended-intrinsic-op |
601 | // R610 extended-intrinsic-op -> intrinsic-operator |
602 | struct DefinedOperator { |
603 | UNION_CLASS_BOILERPLATE(DefinedOperator); |
604 | ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add, Subtract, Concat, |
605 | LT, LE, EQ, NE, GE, GT, NOT, AND, OR, EQV, NEQV) |
606 | std::variant<DefinedOpName, IntrinsicOperator> u; |
607 | }; |
608 | |
609 | // R804 object-name -> name |
610 | using ObjectName = Name; |
611 | |
612 | // R867 import-stmt -> |
613 | // IMPORT [[::] import-name-list] | |
614 | // IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL |
615 | struct ImportStmt { |
616 | BOILERPLATE(ImportStmt); |
617 | ImportStmt(common::ImportKind &&k) : kind{k} {} |
618 | ImportStmt(std::list<Name> &&n) : names(std::move(n)) {} |
619 | ImportStmt(common::ImportKind &&, std::list<Name> &&); |
620 | common::ImportKind kind{common::ImportKind::Default}; |
621 | std::list<Name> names; |
622 | }; |
623 | |
624 | // R868 namelist-stmt -> |
625 | // NAMELIST / namelist-group-name / namelist-group-object-list |
626 | // [[,] / namelist-group-name / namelist-group-object-list]... |
627 | // R869 namelist-group-object -> variable-name |
628 | struct NamelistStmt { |
629 | struct Group { |
630 | TUPLE_CLASS_BOILERPLATE(Group); |
631 | std::tuple<Name, std::list<Name>> t; |
632 | }; |
633 | WRAPPER_CLASS_BOILERPLATE(NamelistStmt, std::list<Group>); |
634 | }; |
635 | |
636 | // R701 type-param-value -> scalar-int-expr | * | : |
637 | EMPTY_CLASS(Star); |
638 | |
639 | struct TypeParamValue { |
640 | UNION_CLASS_BOILERPLATE(TypeParamValue); |
641 | EMPTY_CLASS(Deferred); // : |
642 | std::variant<ScalarIntExpr, Star, Deferred> u; |
643 | }; |
644 | |
645 | // R706 kind-selector -> ( [KIND =] scalar-int-constant-expr ) |
646 | // Legacy extension: kind-selector -> * digit-string |
647 | // N.B. These are not semantically identical in the case of COMPLEX. |
648 | struct KindSelector { |
649 | UNION_CLASS_BOILERPLATE(KindSelector); |
650 | WRAPPER_CLASS(StarSize, std::uint64_t); |
651 | std::variant<ScalarIntConstantExpr, StarSize> u; |
652 | }; |
653 | |
654 | // R705 integer-type-spec -> INTEGER [kind-selector] |
655 | WRAPPER_CLASS(IntegerTypeSpec, std::optional<KindSelector>); |
656 | |
657 | // R723 char-length -> ( type-param-value ) | digit-string |
658 | struct CharLength { |
659 | UNION_CLASS_BOILERPLATE(CharLength); |
660 | std::variant<TypeParamValue, std::uint64_t> u; |
661 | }; |
662 | |
663 | // R722 length-selector -> ( [LEN =] type-param-value ) | * char-length [,] |
664 | struct LengthSelector { |
665 | UNION_CLASS_BOILERPLATE(LengthSelector); |
666 | std::variant<TypeParamValue, CharLength> u; |
667 | }; |
668 | |
669 | // R721 char-selector -> |
670 | // length-selector | |
671 | // ( LEN = type-param-value , KIND = scalar-int-constant-expr ) | |
672 | // ( type-param-value , [KIND =] scalar-int-constant-expr ) | |
673 | // ( KIND = scalar-int-constant-expr [, LEN = type-param-value] ) |
674 | struct CharSelector { |
675 | UNION_CLASS_BOILERPLATE(CharSelector); |
676 | struct LengthAndKind { |
677 | BOILERPLATE(LengthAndKind); |
678 | LengthAndKind(std::optional<TypeParamValue> &&l, ScalarIntConstantExpr &&k) |
679 | : length(std::move(l)), kind(std::move(k)) {} |
680 | std::optional<TypeParamValue> length; |
681 | ScalarIntConstantExpr kind; |
682 | }; |
683 | CharSelector(TypeParamValue &&l, ScalarIntConstantExpr &&k) |
684 | : u{LengthAndKind{std::make_optional(std::move(l)), std::move(k)}} {} |
685 | CharSelector(ScalarIntConstantExpr &&k, std::optional<TypeParamValue> &&l) |
686 | : u{LengthAndKind{std::move(l), std::move(k)}} {} |
687 | std::variant<LengthSelector, LengthAndKind> u; |
688 | }; |
689 | |
690 | // R704 intrinsic-type-spec -> |
691 | // integer-type-spec | REAL [kind-selector] | DOUBLE PRECISION | |
692 | // COMPLEX [kind-selector] | CHARACTER [char-selector] | |
693 | // LOGICAL [kind-selector] |
694 | // Extensions: DOUBLE COMPLEX |
695 | struct IntrinsicTypeSpec { |
696 | UNION_CLASS_BOILERPLATE(IntrinsicTypeSpec); |
697 | struct Real { |
698 | BOILERPLATE(Real); |
699 | Real(std::optional<KindSelector> &&k) : kind{std::move(k)} {} |
700 | std::optional<KindSelector> kind; |
701 | }; |
702 | EMPTY_CLASS(DoublePrecision); |
703 | struct Complex { |
704 | BOILERPLATE(Complex); |
705 | Complex(std::optional<KindSelector> &&k) : kind{std::move(k)} {} |
706 | std::optional<KindSelector> kind; |
707 | }; |
708 | struct Character { |
709 | BOILERPLATE(Character); |
710 | Character(std::optional<CharSelector> &&s) : selector{std::move(s)} {} |
711 | std::optional<CharSelector> selector; |
712 | }; |
713 | struct Logical { |
714 | BOILERPLATE(Logical); |
715 | Logical(std::optional<KindSelector> &&k) : kind{std::move(k)} {} |
716 | std::optional<KindSelector> kind; |
717 | }; |
718 | EMPTY_CLASS(DoubleComplex); |
719 | std::variant<IntegerTypeSpec, Real, DoublePrecision, Complex, Character, |
720 | Logical, DoubleComplex> |
721 | u; |
722 | }; |
723 | |
724 | // Extension: Vector type |
725 | WRAPPER_CLASS(UnsignedTypeSpec, std::optional<KindSelector>); |
726 | struct VectorElementType { |
727 | UNION_CLASS_BOILERPLATE(VectorElementType); |
728 | std::variant<IntegerTypeSpec, IntrinsicTypeSpec::Real, UnsignedTypeSpec> u; |
729 | }; |
730 | WRAPPER_CLASS(IntrinsicVectorTypeSpec, VectorElementType); |
731 | struct VectorTypeSpec { |
732 | UNION_CLASS_BOILERPLATE(VectorTypeSpec); |
733 | EMPTY_CLASS(PairVectorTypeSpec); |
734 | EMPTY_CLASS(QuadVectorTypeSpec); |
735 | std::variant<IntrinsicVectorTypeSpec, PairVectorTypeSpec, QuadVectorTypeSpec> |
736 | u; |
737 | }; |
738 | |
739 | // R755 type-param-spec -> [keyword =] type-param-value |
740 | struct TypeParamSpec { |
741 | TUPLE_CLASS_BOILERPLATE(TypeParamSpec); |
742 | std::tuple<std::optional<Keyword>, TypeParamValue> t; |
743 | }; |
744 | |
745 | // R754 derived-type-spec -> type-name [(type-param-spec-list)] |
746 | struct DerivedTypeSpec { |
747 | TUPLE_CLASS_BOILERPLATE(DerivedTypeSpec); |
748 | mutable const semantics::DerivedTypeSpec *derivedTypeSpec{nullptr}; |
749 | std::tuple<Name, std::list<TypeParamSpec>> t; |
750 | }; |
751 | |
752 | // R702 type-spec -> intrinsic-type-spec | derived-type-spec |
753 | struct TypeSpec { |
754 | UNION_CLASS_BOILERPLATE(TypeSpec); |
755 | mutable const semantics::DeclTypeSpec *declTypeSpec{nullptr}; |
756 | std::variant<IntrinsicTypeSpec, DerivedTypeSpec> u; |
757 | }; |
758 | |
759 | // R703 declaration-type-spec -> |
760 | // intrinsic-type-spec | TYPE ( intrinsic-type-spec ) | |
761 | // TYPE ( derived-type-spec ) | CLASS ( derived-type-spec ) | |
762 | // CLASS ( * ) | TYPE ( * ) |
763 | // Legacy extension: RECORD /struct/ |
764 | struct DeclarationTypeSpec { |
765 | UNION_CLASS_BOILERPLATE(DeclarationTypeSpec); |
766 | struct Type { |
767 | BOILERPLATE(Type); |
768 | Type(DerivedTypeSpec &&dt) : derived(std::move(dt)) {} |
769 | DerivedTypeSpec derived; |
770 | }; |
771 | struct Class { |
772 | BOILERPLATE(Class); |
773 | Class(DerivedTypeSpec &&dt) : derived(std::move(dt)) {} |
774 | DerivedTypeSpec derived; |
775 | }; |
776 | EMPTY_CLASS(ClassStar); |
777 | EMPTY_CLASS(TypeStar); |
778 | WRAPPER_CLASS(Record, Name); |
779 | std::variant<IntrinsicTypeSpec, Type, Class, ClassStar, TypeStar, Record, |
780 | VectorTypeSpec> |
781 | u; |
782 | }; |
783 | |
784 | // R709 kind-param -> digit-string | scalar-int-constant-name |
785 | struct KindParam { |
786 | UNION_CLASS_BOILERPLATE(KindParam); |
787 | std::variant<std::uint64_t, Scalar<Integer<Constant<Name>>>> u; |
788 | }; |
789 | |
790 | // R707 signed-int-literal-constant -> [sign] int-literal-constant |
791 | struct SignedIntLiteralConstant { |
792 | TUPLE_CLASS_BOILERPLATE(SignedIntLiteralConstant); |
793 | CharBlock source; |
794 | std::tuple<CharBlock, std::optional<KindParam>> t; |
795 | }; |
796 | |
797 | // R708 int-literal-constant -> digit-string [_ kind-param] |
798 | struct IntLiteralConstant { |
799 | TUPLE_CLASS_BOILERPLATE(IntLiteralConstant); |
800 | std::tuple<CharBlock, std::optional<KindParam>> t; |
801 | }; |
802 | |
803 | // R712 sign -> + | - |
804 | enum class Sign { Positive, Negative }; |
805 | |
806 | // R714 real-literal-constant -> |
807 | // significand [exponent-letter exponent] [_ kind-param] | |
808 | // digit-string exponent-letter exponent [_ kind-param] |
809 | // R715 significand -> digit-string . [digit-string] | . digit-string |
810 | // R717 exponent -> signed-digit-string |
811 | struct RealLiteralConstant { |
812 | BOILERPLATE(RealLiteralConstant); |
813 | struct Real { |
814 | COPY_AND_ASSIGN_BOILERPLATE(Real); |
815 | Real() {} |
816 | CharBlock source; |
817 | }; |
818 | RealLiteralConstant(Real &&r, std::optional<KindParam> &&k) |
819 | : real{std::move(r)}, kind{std::move(k)} {} |
820 | Real real; |
821 | std::optional<KindParam> kind; |
822 | }; |
823 | |
824 | // R713 signed-real-literal-constant -> [sign] real-literal-constant |
825 | struct SignedRealLiteralConstant { |
826 | TUPLE_CLASS_BOILERPLATE(SignedRealLiteralConstant); |
827 | std::tuple<std::optional<Sign>, RealLiteralConstant> t; |
828 | }; |
829 | |
830 | // R719 real-part -> |
831 | // signed-int-literal-constant | signed-real-literal-constant | |
832 | // named-constant |
833 | // R720 imag-part -> |
834 | // signed-int-literal-constant | signed-real-literal-constant | |
835 | // named-constant |
836 | struct ComplexPart { |
837 | UNION_CLASS_BOILERPLATE(ComplexPart); |
838 | std::variant<SignedIntLiteralConstant, SignedRealLiteralConstant, |
839 | NamedConstant> |
840 | u; |
841 | }; |
842 | |
843 | // R718 complex-literal-constant -> ( real-part , imag-part ) |
844 | struct ComplexLiteralConstant { |
845 | TUPLE_CLASS_BOILERPLATE(ComplexLiteralConstant); |
846 | std::tuple<ComplexPart, ComplexPart> t; // real, imaginary |
847 | }; |
848 | |
849 | // Extension: signed COMPLEX constant |
850 | struct SignedComplexLiteralConstant { |
851 | TUPLE_CLASS_BOILERPLATE(SignedComplexLiteralConstant); |
852 | std::tuple<Sign, ComplexLiteralConstant> t; |
853 | }; |
854 | |
855 | // R724 char-literal-constant -> |
856 | // [kind-param _] ' [rep-char]... ' | |
857 | // [kind-param _] " [rep-char]... " |
858 | struct CharLiteralConstant { |
859 | TUPLE_CLASS_BOILERPLATE(CharLiteralConstant); |
860 | std::tuple<std::optional<KindParam>, std::string> t; |
861 | std::string GetString() const { return std::get<std::string>(t); } |
862 | }; |
863 | |
864 | // legacy extension |
865 | struct HollerithLiteralConstant { |
866 | WRAPPER_CLASS_BOILERPLATE(HollerithLiteralConstant, std::string); |
867 | std::string GetString() const { return v; } |
868 | }; |
869 | |
870 | // R725 logical-literal-constant -> |
871 | // .TRUE. [_ kind-param] | .FALSE. [_ kind-param] |
872 | struct LogicalLiteralConstant { |
873 | TUPLE_CLASS_BOILERPLATE(LogicalLiteralConstant); |
874 | std::tuple<bool, std::optional<KindParam>> t; |
875 | }; |
876 | |
877 | // R764 boz-literal-constant -> binary-constant | octal-constant | hex-constant |
878 | // R765 binary-constant -> B ' digit [digit]... ' | B " digit [digit]... " |
879 | // R766 octal-constant -> O ' digit [digit]... ' | O " digit [digit]... " |
880 | // R767 hex-constant -> |
881 | // Z ' hex-digit [hex-digit]... ' | Z " hex-digit [hex-digit]... " |
882 | // The constant must be large enough to hold any real or integer scalar |
883 | // of any supported kind (F'2018 7.7). |
884 | WRAPPER_CLASS(BOZLiteralConstant, std::string); |
885 | |
886 | // R605 literal-constant -> |
887 | // int-literal-constant | real-literal-constant | |
888 | // complex-literal-constant | logical-literal-constant | |
889 | // char-literal-constant | boz-literal-constant |
890 | struct LiteralConstant { |
891 | UNION_CLASS_BOILERPLATE(LiteralConstant); |
892 | std::variant<HollerithLiteralConstant, IntLiteralConstant, |
893 | RealLiteralConstant, ComplexLiteralConstant, BOZLiteralConstant, |
894 | CharLiteralConstant, LogicalLiteralConstant> |
895 | u; |
896 | }; |
897 | |
898 | // R807 access-spec -> PUBLIC | PRIVATE |
899 | struct AccessSpec { |
900 | ENUM_CLASS(Kind, Public, Private) |
901 | WRAPPER_CLASS_BOILERPLATE(AccessSpec, Kind); |
902 | }; |
903 | |
904 | // R728 type-attr-spec -> |
905 | // ABSTRACT | access-spec | BIND(C) | EXTENDS ( parent-type-name ) |
906 | EMPTY_CLASS(Abstract); |
907 | struct TypeAttrSpec { |
908 | UNION_CLASS_BOILERPLATE(TypeAttrSpec); |
909 | EMPTY_CLASS(BindC); |
910 | WRAPPER_CLASS(Extends, Name); |
911 | std::variant<Abstract, AccessSpec, BindC, Extends> u; |
912 | }; |
913 | |
914 | // R727 derived-type-stmt -> |
915 | // TYPE [[, type-attr-spec-list] ::] type-name [( type-param-name-list )] |
916 | struct DerivedTypeStmt { |
917 | TUPLE_CLASS_BOILERPLATE(DerivedTypeStmt); |
918 | std::tuple<std::list<TypeAttrSpec>, Name, std::list<Name>> t; |
919 | }; |
920 | |
921 | // R731 sequence-stmt -> SEQUENCE |
922 | EMPTY_CLASS(SequenceStmt); |
923 | |
924 | // R745 private-components-stmt -> PRIVATE |
925 | // R747 binding-private-stmt -> PRIVATE |
926 | EMPTY_CLASS(PrivateStmt); |
927 | |
928 | // R729 private-or-sequence -> private-components-stmt | sequence-stmt |
929 | struct PrivateOrSequence { |
930 | UNION_CLASS_BOILERPLATE(PrivateOrSequence); |
931 | std::variant<PrivateStmt, SequenceStmt> u; |
932 | }; |
933 | |
934 | // R733 type-param-decl -> type-param-name [= scalar-int-constant-expr] |
935 | struct TypeParamDecl { |
936 | TUPLE_CLASS_BOILERPLATE(TypeParamDecl); |
937 | std::tuple<Name, std::optional<ScalarIntConstantExpr>> t; |
938 | }; |
939 | |
940 | // R732 type-param-def-stmt -> |
941 | // integer-type-spec , type-param-attr-spec :: type-param-decl-list |
942 | // R734 type-param-attr-spec -> KIND | LEN |
943 | struct TypeParamDefStmt { |
944 | TUPLE_CLASS_BOILERPLATE(TypeParamDefStmt); |
945 | std::tuple<IntegerTypeSpec, common::TypeParamAttr, std::list<TypeParamDecl>> |
946 | t; |
947 | }; |
948 | |
949 | // R1028 specification-expr -> scalar-int-expr |
950 | WRAPPER_CLASS(SpecificationExpr, ScalarIntExpr); |
951 | |
952 | // R816 explicit-shape-spec -> [lower-bound :] upper-bound |
953 | // R817 lower-bound -> specification-expr |
954 | // R818 upper-bound -> specification-expr |
955 | struct ExplicitShapeSpec { |
956 | TUPLE_CLASS_BOILERPLATE(ExplicitShapeSpec); |
957 | std::tuple<std::optional<SpecificationExpr>, SpecificationExpr> t; |
958 | }; |
959 | |
960 | // R810 deferred-coshape-spec -> : |
961 | // deferred-coshape-spec-list is just a count of the colons (i.e., the rank). |
962 | WRAPPER_CLASS(DeferredCoshapeSpecList, int); |
963 | |
964 | // R811 explicit-coshape-spec -> |
965 | // [[lower-cobound :] upper-cobound ,]... [lower-cobound :] * |
966 | // R812 lower-cobound -> specification-expr |
967 | // R813 upper-cobound -> specification-expr |
968 | struct ExplicitCoshapeSpec { |
969 | TUPLE_CLASS_BOILERPLATE(ExplicitCoshapeSpec); |
970 | std::tuple<std::list<ExplicitShapeSpec>, std::optional<SpecificationExpr>> t; |
971 | }; |
972 | |
973 | // R809 coarray-spec -> deferred-coshape-spec-list | explicit-coshape-spec |
974 | struct CoarraySpec { |
975 | UNION_CLASS_BOILERPLATE(CoarraySpec); |
976 | std::variant<DeferredCoshapeSpecList, ExplicitCoshapeSpec> u; |
977 | }; |
978 | |
979 | // R820 deferred-shape-spec -> : |
980 | // deferred-shape-spec-list is just a count of the colons (i.e., the rank). |
981 | WRAPPER_CLASS(DeferredShapeSpecList, int); |
982 | |
983 | // R740 component-array-spec -> |
984 | // explicit-shape-spec-list | deferred-shape-spec-list |
985 | struct ComponentArraySpec { |
986 | UNION_CLASS_BOILERPLATE(ComponentArraySpec); |
987 | std::variant<std::list<ExplicitShapeSpec>, DeferredShapeSpecList> u; |
988 | }; |
989 | |
990 | // R738 component-attr-spec -> |
991 | // access-spec | ALLOCATABLE | |
992 | // CODIMENSION lbracket coarray-spec rbracket | |
993 | // CONTIGUOUS | DIMENSION ( component-array-spec ) | POINTER | |
994 | // (CUDA) CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE | UNIFIED |
995 | EMPTY_CLASS(Allocatable); |
996 | EMPTY_CLASS(Pointer); |
997 | EMPTY_CLASS(Contiguous); |
998 | struct ComponentAttrSpec { |
999 | UNION_CLASS_BOILERPLATE(ComponentAttrSpec); |
1000 | std::variant<AccessSpec, Allocatable, CoarraySpec, Contiguous, |
1001 | ComponentArraySpec, Pointer, common::CUDADataAttr, ErrorRecovery> |
1002 | u; |
1003 | }; |
1004 | |
1005 | // R806 null-init -> function-reference ... which must be NULL() |
1006 | WRAPPER_CLASS(NullInit, common::Indirection<Expr>); |
1007 | |
1008 | // R744 initial-data-target -> designator |
1009 | using InitialDataTarget = common::Indirection<Designator>; |
1010 | |
1011 | // R743 component-initialization -> |
1012 | // = constant-expr | => null-init | => initial-data-target |
1013 | // R805 initialization -> |
1014 | // = constant-expr | => null-init | => initial-data-target |
1015 | // Universal extension: initialization -> / data-stmt-value-list / |
1016 | struct Initialization { |
1017 | UNION_CLASS_BOILERPLATE(Initialization); |
1018 | std::variant<ConstantExpr, NullInit, InitialDataTarget, |
1019 | std::list<common::Indirection<DataStmtValue>>> |
1020 | u; |
1021 | }; |
1022 | |
1023 | // R739 component-decl -> |
1024 | // component-name [( component-array-spec )] |
1025 | // [lbracket coarray-spec rbracket] [* char-length] |
1026 | // [component-initialization] |
1027 | struct ComponentDecl { |
1028 | TUPLE_CLASS_BOILERPLATE(ComponentDecl); |
1029 | std::tuple<Name, std::optional<ComponentArraySpec>, |
1030 | std::optional<CoarraySpec>, std::optional<CharLength>, |
1031 | std::optional<Initialization>> |
1032 | t; |
1033 | }; |
1034 | |
1035 | // A %FILL component for a DEC STRUCTURE. The name will be replaced |
1036 | // with a distinct compiler-generated name. |
1037 | struct FillDecl { |
1038 | TUPLE_CLASS_BOILERPLATE(FillDecl); |
1039 | std::tuple<Name, std::optional<ComponentArraySpec>, std::optional<CharLength>> |
1040 | t; |
1041 | }; |
1042 | |
1043 | struct ComponentOrFill { |
1044 | UNION_CLASS_BOILERPLATE(ComponentOrFill); |
1045 | std::variant<ComponentDecl, FillDecl> u; |
1046 | }; |
1047 | |
1048 | // R737 data-component-def-stmt -> |
1049 | // declaration-type-spec [[, component-attr-spec-list] ::] |
1050 | // component-decl-list |
1051 | struct DataComponentDefStmt { |
1052 | TUPLE_CLASS_BOILERPLATE(DataComponentDefStmt); |
1053 | std::tuple<DeclarationTypeSpec, std::list<ComponentAttrSpec>, |
1054 | std::list<ComponentOrFill>> |
1055 | t; |
1056 | }; |
1057 | |
1058 | // R742 proc-component-attr-spec -> |
1059 | // access-spec | NOPASS | PASS [(arg-name)] | POINTER |
1060 | EMPTY_CLASS(NoPass); |
1061 | WRAPPER_CLASS(Pass, std::optional<Name>); |
1062 | struct ProcComponentAttrSpec { |
1063 | UNION_CLASS_BOILERPLATE(ProcComponentAttrSpec); |
1064 | std::variant<AccessSpec, NoPass, Pass, Pointer> u; |
1065 | }; |
1066 | |
1067 | // R1517 proc-pointer-init -> null-init | initial-proc-target |
1068 | // R1518 initial-proc-target -> procedure-name |
1069 | struct ProcPointerInit { |
1070 | UNION_CLASS_BOILERPLATE(ProcPointerInit); |
1071 | std::variant<NullInit, Name> u; |
1072 | }; |
1073 | |
1074 | // R1513 proc-interface -> interface-name | declaration-type-spec |
1075 | // R1516 interface-name -> name |
1076 | struct ProcInterface { |
1077 | UNION_CLASS_BOILERPLATE(ProcInterface); |
1078 | std::variant<Name, DeclarationTypeSpec> u; |
1079 | }; |
1080 | |
1081 | // R1515 proc-decl -> procedure-entity-name [=> proc-pointer-init] |
1082 | struct ProcDecl { |
1083 | TUPLE_CLASS_BOILERPLATE(ProcDecl); |
1084 | std::tuple<Name, std::optional<ProcPointerInit>> t; |
1085 | }; |
1086 | |
1087 | // R741 proc-component-def-stmt -> |
1088 | // PROCEDURE ( [proc-interface] ) , proc-component-attr-spec-list |
1089 | // :: proc-decl-list |
1090 | struct ProcComponentDefStmt { |
1091 | TUPLE_CLASS_BOILERPLATE(ProcComponentDefStmt); |
1092 | std::tuple<std::optional<ProcInterface>, std::list<ProcComponentAttrSpec>, |
1093 | std::list<ProcDecl>> |
1094 | t; |
1095 | }; |
1096 | |
1097 | // R736 component-def-stmt -> data-component-def-stmt | proc-component-def-stmt |
1098 | struct ComponentDefStmt { |
1099 | UNION_CLASS_BOILERPLATE(ComponentDefStmt); |
1100 | std::variant<DataComponentDefStmt, ProcComponentDefStmt, |
1101 | common::Indirection<CompilerDirective>, ErrorRecovery |
1102 | // , TypeParamDefStmt -- PGI accidental extension, not enabled |
1103 | > |
1104 | u; |
1105 | }; |
1106 | |
1107 | // R752 bind-attr -> |
1108 | // access-spec | DEFERRED | NON_OVERRIDABLE | NOPASS | PASS [(arg-name)] |
1109 | struct BindAttr { |
1110 | UNION_CLASS_BOILERPLATE(BindAttr); |
1111 | EMPTY_CLASS(Deferred); |
1112 | EMPTY_CLASS(Non_Overridable); |
1113 | std::variant<AccessSpec, Deferred, Non_Overridable, NoPass, Pass> u; |
1114 | }; |
1115 | |
1116 | // R750 type-bound-proc-decl -> binding-name [=> procedure-name] |
1117 | struct TypeBoundProcDecl { |
1118 | TUPLE_CLASS_BOILERPLATE(TypeBoundProcDecl); |
1119 | std::tuple<Name, std::optional<Name>> t; |
1120 | }; |
1121 | |
1122 | // R749 type-bound-procedure-stmt -> |
1123 | // PROCEDURE [[, bind-attr-list] ::] type-bound-proc-decl-list | |
1124 | // PROCEDURE ( interface-name ) , bind-attr-list :: binding-name-list |
1125 | // The second form, with interface-name, requires DEFERRED in bind-attr-list, |
1126 | // and thus can appear only in an abstract type. |
1127 | struct TypeBoundProcedureStmt { |
1128 | UNION_CLASS_BOILERPLATE(TypeBoundProcedureStmt); |
1129 | struct WithoutInterface { |
1130 | BOILERPLATE(WithoutInterface); |
1131 | WithoutInterface( |
1132 | std::list<BindAttr> &&as, std::list<TypeBoundProcDecl> &&ds) |
1133 | : attributes(std::move(as)), declarations(std::move(ds)) {} |
1134 | std::list<BindAttr> attributes; |
1135 | std::list<TypeBoundProcDecl> declarations; |
1136 | }; |
1137 | struct WithInterface { |
1138 | BOILERPLATE(WithInterface); |
1139 | WithInterface(Name &&n, std::list<BindAttr> &&as, std::list<Name> &&bs) |
1140 | : interfaceName(std::move(n)), attributes(std::move(as)), |
1141 | bindingNames(std::move(bs)) {} |
1142 | Name interfaceName; |
1143 | std::list<BindAttr> attributes; |
1144 | std::list<Name> bindingNames; |
1145 | }; |
1146 | std::variant<WithoutInterface, WithInterface> u; |
1147 | }; |
1148 | |
1149 | // R751 type-bound-generic-stmt -> |
1150 | // GENERIC [, access-spec] :: generic-spec => binding-name-list |
1151 | struct TypeBoundGenericStmt { |
1152 | TUPLE_CLASS_BOILERPLATE(TypeBoundGenericStmt); |
1153 | std::tuple<std::optional<AccessSpec>, common::Indirection<GenericSpec>, |
1154 | std::list<Name>> |
1155 | t; |
1156 | }; |
1157 | |
1158 | // R753 final-procedure-stmt -> FINAL [::] final-subroutine-name-list |
1159 | WRAPPER_CLASS(FinalProcedureStmt, std::list<Name>); |
1160 | |
1161 | // R748 type-bound-proc-binding -> |
1162 | // type-bound-procedure-stmt | type-bound-generic-stmt | |
1163 | // final-procedure-stmt |
1164 | struct TypeBoundProcBinding { |
1165 | UNION_CLASS_BOILERPLATE(TypeBoundProcBinding); |
1166 | std::variant<TypeBoundProcedureStmt, TypeBoundGenericStmt, FinalProcedureStmt, |
1167 | ErrorRecovery> |
1168 | u; |
1169 | }; |
1170 | |
1171 | // R746 type-bound-procedure-part -> |
1172 | // contains-stmt [binding-private-stmt] [type-bound-proc-binding]... |
1173 | struct TypeBoundProcedurePart { |
1174 | TUPLE_CLASS_BOILERPLATE(TypeBoundProcedurePart); |
1175 | std::tuple<Statement<ContainsStmt>, std::optional<Statement<PrivateStmt>>, |
1176 | std::list<Statement<TypeBoundProcBinding>>> |
1177 | t; |
1178 | }; |
1179 | |
1180 | // R730 end-type-stmt -> END TYPE [type-name] |
1181 | WRAPPER_CLASS(EndTypeStmt, std::optional<Name>); |
1182 | |
1183 | // R726 derived-type-def -> |
1184 | // derived-type-stmt [type-param-def-stmt]... [private-or-sequence]... |
1185 | // [component-part] [type-bound-procedure-part] end-type-stmt |
1186 | // R735 component-part -> [component-def-stmt]... |
1187 | struct DerivedTypeDef { |
1188 | TUPLE_CLASS_BOILERPLATE(DerivedTypeDef); |
1189 | std::tuple<Statement<DerivedTypeStmt>, std::list<Statement<TypeParamDefStmt>>, |
1190 | std::list<Statement<PrivateOrSequence>>, |
1191 | std::list<Statement<ComponentDefStmt>>, |
1192 | std::optional<TypeBoundProcedurePart>, Statement<EndTypeStmt>> |
1193 | t; |
1194 | }; |
1195 | |
1196 | // R758 component-data-source -> expr | data-target | proc-target |
1197 | // R1037 data-target -> expr |
1198 | // R1040 proc-target -> expr | procedure-name | proc-component-ref |
1199 | WRAPPER_CLASS(ComponentDataSource, common::Indirection<Expr>); |
1200 | |
1201 | // R757 component-spec -> [keyword =] component-data-source |
1202 | struct ComponentSpec { |
1203 | TUPLE_CLASS_BOILERPLATE(ComponentSpec); |
1204 | std::tuple<std::optional<Keyword>, ComponentDataSource> t; |
1205 | }; |
1206 | |
1207 | // R756 structure-constructor -> derived-type-spec ( [component-spec-list] ) |
1208 | struct StructureConstructor { |
1209 | TUPLE_CLASS_BOILERPLATE(StructureConstructor); |
1210 | std::tuple<DerivedTypeSpec, std::list<ComponentSpec>> t; |
1211 | }; |
1212 | |
1213 | // R760 enum-def-stmt -> ENUM, BIND(C) |
1214 | EMPTY_CLASS(EnumDefStmt); |
1215 | |
1216 | // R762 enumerator -> named-constant [= scalar-int-constant-expr] |
1217 | struct Enumerator { |
1218 | TUPLE_CLASS_BOILERPLATE(Enumerator); |
1219 | std::tuple<NamedConstant, std::optional<ScalarIntConstantExpr>> t; |
1220 | }; |
1221 | |
1222 | // R761 enumerator-def-stmt -> ENUMERATOR [::] enumerator-list |
1223 | WRAPPER_CLASS(EnumeratorDefStmt, std::list<Enumerator>); |
1224 | |
1225 | // R763 end-enum-stmt -> END ENUM |
1226 | EMPTY_CLASS(EndEnumStmt); |
1227 | |
1228 | // R759 enum-def -> |
1229 | // enum-def-stmt enumerator-def-stmt [enumerator-def-stmt]... |
1230 | // end-enum-stmt |
1231 | struct EnumDef { |
1232 | TUPLE_CLASS_BOILERPLATE(EnumDef); |
1233 | std::tuple<Statement<EnumDefStmt>, std::list<Statement<EnumeratorDefStmt>>, |
1234 | Statement<EndEnumStmt>> |
1235 | t; |
1236 | }; |
1237 | |
1238 | // R773 ac-value -> expr | ac-implied-do |
1239 | struct AcValue { |
1240 | struct Triplet { // PGI/Intel extension |
1241 | TUPLE_CLASS_BOILERPLATE(Triplet); |
1242 | std::tuple<ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>> t; |
1243 | }; |
1244 | UNION_CLASS_BOILERPLATE(AcValue); |
1245 | std::variant<Triplet, common::Indirection<Expr>, |
1246 | common::Indirection<AcImpliedDo>> |
1247 | u; |
1248 | }; |
1249 | |
1250 | // R770 ac-spec -> type-spec :: | [type-spec ::] ac-value-list |
1251 | struct AcSpec { |
1252 | BOILERPLATE(AcSpec); |
1253 | AcSpec(std::optional<TypeSpec> &&ts, std::list<AcValue> &&xs) |
1254 | : type(std::move(ts)), values(std::move(xs)) {} |
1255 | explicit AcSpec(TypeSpec &&ts) : type{std::move(ts)} {} |
1256 | std::optional<TypeSpec> type; |
1257 | std::list<AcValue> values; |
1258 | }; |
1259 | |
1260 | // R769 array-constructor -> (/ ac-spec /) | lbracket ac-spec rbracket |
1261 | WRAPPER_CLASS(ArrayConstructor, AcSpec); |
1262 | |
1263 | // R1124 do-variable -> scalar-int-variable-name |
1264 | using DoVariable = Scalar<Integer<Name>>; |
1265 | |
1266 | template <typename VAR, typename BOUND> struct LoopBounds { |
1267 | LoopBounds(LoopBounds &&that) = default; |
1268 | LoopBounds( |
1269 | VAR &&name, BOUND &&lower, BOUND &&upper, std::optional<BOUND> &&step) |
1270 | : name{std::move(name)}, lower{std::move(lower)}, upper{std::move(upper)}, |
1271 | step{std::move(step)} {} |
1272 | LoopBounds &operator=(LoopBounds &&) = default; |
1273 | VAR name; |
1274 | BOUND lower, upper; |
1275 | std::optional<BOUND> step; |
1276 | }; |
1277 | |
1278 | using ScalarName = Scalar<Name>; |
1279 | using ScalarExpr = Scalar<common::Indirection<Expr>>; |
1280 | |
1281 | // R775 ac-implied-do-control -> |
1282 | // [integer-type-spec ::] ac-do-variable = scalar-int-expr , |
1283 | // scalar-int-expr [, scalar-int-expr] |
1284 | // R776 ac-do-variable -> do-variable |
1285 | struct AcImpliedDoControl { |
1286 | TUPLE_CLASS_BOILERPLATE(AcImpliedDoControl); |
1287 | using Bounds = LoopBounds<DoVariable, ScalarIntExpr>; |
1288 | std::tuple<std::optional<IntegerTypeSpec>, Bounds> t; |
1289 | }; |
1290 | |
1291 | // R774 ac-implied-do -> ( ac-value-list , ac-implied-do-control ) |
1292 | struct AcImpliedDo { |
1293 | TUPLE_CLASS_BOILERPLATE(AcImpliedDo); |
1294 | std::tuple<std::list<AcValue>, AcImpliedDoControl> t; |
1295 | }; |
1296 | |
1297 | // R808 language-binding-spec -> |
1298 | // BIND ( C [, NAME = scalar-default-char-constant-expr] ) |
1299 | // R1528 proc-language-binding-spec -> language-binding-spec |
1300 | WRAPPER_CLASS( |
1301 | LanguageBindingSpec, std::optional<ScalarDefaultCharConstantExpr>); |
1302 | |
1303 | // R852 named-constant-def -> named-constant = constant-expr |
1304 | struct NamedConstantDef { |
1305 | TUPLE_CLASS_BOILERPLATE(NamedConstantDef); |
1306 | std::tuple<NamedConstant, ConstantExpr> t; |
1307 | }; |
1308 | |
1309 | // R851 parameter-stmt -> PARAMETER ( named-constant-def-list ) |
1310 | WRAPPER_CLASS(ParameterStmt, std::list<NamedConstantDef>); |
1311 | |
1312 | // R819 assumed-shape-spec -> [lower-bound] : |
1313 | WRAPPER_CLASS(AssumedShapeSpec, std::optional<SpecificationExpr>); |
1314 | |
1315 | // R821 assumed-implied-spec -> [lower-bound :] * |
1316 | WRAPPER_CLASS(AssumedImpliedSpec, std::optional<SpecificationExpr>); |
1317 | |
1318 | // R822 assumed-size-spec -> explicit-shape-spec-list , assumed-implied-spec |
1319 | struct AssumedSizeSpec { |
1320 | TUPLE_CLASS_BOILERPLATE(AssumedSizeSpec); |
1321 | std::tuple<std::list<ExplicitShapeSpec>, AssumedImpliedSpec> t; |
1322 | }; |
1323 | |
1324 | // R823 implied-shape-or-assumed-size-spec -> assumed-implied-spec |
1325 | // R824 implied-shape-spec -> assumed-implied-spec , assumed-implied-spec-list |
1326 | // I.e., when the assumed-implied-spec-list has a single item, it constitutes an |
1327 | // implied-shape-or-assumed-size-spec; otherwise, an implied-shape-spec. |
1328 | WRAPPER_CLASS(ImpliedShapeSpec, std::list<AssumedImpliedSpec>); |
1329 | |
1330 | // R825 assumed-rank-spec -> .. |
1331 | EMPTY_CLASS(AssumedRankSpec); |
1332 | |
1333 | // R815 array-spec -> |
1334 | // explicit-shape-spec-list | assumed-shape-spec-list | |
1335 | // deferred-shape-spec-list | assumed-size-spec | implied-shape-spec | |
1336 | // implied-shape-or-assumed-size-spec | assumed-rank-spec |
1337 | struct ArraySpec { |
1338 | UNION_CLASS_BOILERPLATE(ArraySpec); |
1339 | std::variant<std::list<ExplicitShapeSpec>, std::list<AssumedShapeSpec>, |
1340 | DeferredShapeSpecList, AssumedSizeSpec, ImpliedShapeSpec, AssumedRankSpec> |
1341 | u; |
1342 | }; |
1343 | |
1344 | // R826 intent-spec -> IN | OUT | INOUT |
1345 | struct IntentSpec { |
1346 | ENUM_CLASS(Intent, In, Out, InOut) |
1347 | WRAPPER_CLASS_BOILERPLATE(IntentSpec, Intent); |
1348 | }; |
1349 | |
1350 | // R802 attr-spec -> |
1351 | // access-spec | ALLOCATABLE | ASYNCHRONOUS | |
1352 | // CODIMENSION lbracket coarray-spec rbracket | CONTIGUOUS | |
1353 | // DIMENSION ( array-spec ) | EXTERNAL | INTENT ( intent-spec ) | |
1354 | // INTRINSIC | language-binding-spec | OPTIONAL | PARAMETER | POINTER | |
1355 | // PROTECTED | SAVE | TARGET | VALUE | VOLATILE | |
1356 | // (CUDA) CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE |
1357 | EMPTY_CLASS(Asynchronous); |
1358 | EMPTY_CLASS(External); |
1359 | EMPTY_CLASS(Intrinsic); |
1360 | EMPTY_CLASS(Optional); |
1361 | EMPTY_CLASS(Parameter); |
1362 | EMPTY_CLASS(Protected); |
1363 | EMPTY_CLASS(Save); |
1364 | EMPTY_CLASS(Target); |
1365 | EMPTY_CLASS(Value); |
1366 | EMPTY_CLASS(Volatile); |
1367 | struct AttrSpec { |
1368 | UNION_CLASS_BOILERPLATE(AttrSpec); |
1369 | std::variant<AccessSpec, Allocatable, Asynchronous, CoarraySpec, Contiguous, |
1370 | ArraySpec, External, IntentSpec, Intrinsic, LanguageBindingSpec, Optional, |
1371 | Parameter, Pointer, Protected, Save, Target, Value, Volatile, |
1372 | common::CUDADataAttr> |
1373 | u; |
1374 | }; |
1375 | |
1376 | // R803 entity-decl -> |
1377 | // object-name [( array-spec )] [lbracket coarray-spec rbracket] |
1378 | // [* char-length] [initialization] | |
1379 | // function-name [* char-length] |
1380 | struct EntityDecl { |
1381 | TUPLE_CLASS_BOILERPLATE(EntityDecl); |
1382 | std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>, |
1383 | std::optional<CharLength>, std::optional<Initialization>> |
1384 | t; |
1385 | }; |
1386 | |
1387 | // R801 type-declaration-stmt -> |
1388 | // declaration-type-spec [[, attr-spec]... ::] entity-decl-list |
1389 | struct TypeDeclarationStmt { |
1390 | TUPLE_CLASS_BOILERPLATE(TypeDeclarationStmt); |
1391 | std::tuple<DeclarationTypeSpec, std::list<AttrSpec>, std::list<EntityDecl>> t; |
1392 | }; |
1393 | |
1394 | // R828 access-id -> access-name | generic-spec |
1395 | // "access-name" is ambiguous with "generic-spec", so that's what's parsed |
1396 | WRAPPER_CLASS(AccessId, common::Indirection<GenericSpec>); |
1397 | |
1398 | // R827 access-stmt -> access-spec [[::] access-id-list] |
1399 | struct AccessStmt { |
1400 | TUPLE_CLASS_BOILERPLATE(AccessStmt); |
1401 | std::tuple<AccessSpec, std::list<AccessId>> t; |
1402 | }; |
1403 | |
1404 | // R830 allocatable-decl -> |
1405 | // object-name [( array-spec )] [lbracket coarray-spec rbracket] |
1406 | // R860 target-decl -> |
1407 | // object-name [( array-spec )] [lbracket coarray-spec rbracket] |
1408 | struct ObjectDecl { |
1409 | TUPLE_CLASS_BOILERPLATE(ObjectDecl); |
1410 | std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>> |
1411 | t; |
1412 | }; |
1413 | |
1414 | // R829 allocatable-stmt -> ALLOCATABLE [::] allocatable-decl-list |
1415 | WRAPPER_CLASS(AllocatableStmt, std::list<ObjectDecl>); |
1416 | |
1417 | // R831 asynchronous-stmt -> ASYNCHRONOUS [::] object-name-list |
1418 | WRAPPER_CLASS(AsynchronousStmt, std::list<ObjectName>); |
1419 | |
1420 | // R833 bind-entity -> entity-name | / common-block-name / |
1421 | struct BindEntity { |
1422 | TUPLE_CLASS_BOILERPLATE(BindEntity); |
1423 | ENUM_CLASS(Kind, Object, Common) |
1424 | std::tuple<Kind, Name> t; |
1425 | }; |
1426 | |
1427 | // R832 bind-stmt -> language-binding-spec [::] bind-entity-list |
1428 | struct BindStmt { |
1429 | TUPLE_CLASS_BOILERPLATE(BindStmt); |
1430 | std::tuple<LanguageBindingSpec, std::list<BindEntity>> t; |
1431 | }; |
1432 | |
1433 | // R835 codimension-decl -> coarray-name lbracket coarray-spec rbracket |
1434 | struct CodimensionDecl { |
1435 | TUPLE_CLASS_BOILERPLATE(CodimensionDecl); |
1436 | std::tuple<Name, CoarraySpec> t; |
1437 | }; |
1438 | |
1439 | // R834 codimension-stmt -> CODIMENSION [::] codimension-decl-list |
1440 | WRAPPER_CLASS(CodimensionStmt, std::list<CodimensionDecl>); |
1441 | |
1442 | // R836 contiguous-stmt -> CONTIGUOUS [::] object-name-list |
1443 | WRAPPER_CLASS(ContiguousStmt, std::list<ObjectName>); |
1444 | |
1445 | // R847 constant-subobject -> designator |
1446 | // R846 int-constant-subobject -> constant-subobject |
1447 | using ConstantSubobject = Constant<common::Indirection<Designator>>; |
1448 | |
1449 | // Represents an analyzed expression |
1450 | using TypedExpr = common::ForwardOwningPointer<evaluate::GenericExprWrapper>; |
1451 | |
1452 | // R845 data-stmt-constant -> |
1453 | // scalar-constant | scalar-constant-subobject | |
1454 | // signed-int-literal-constant | signed-real-literal-constant | |
1455 | // null-init | initial-data-target | |
1456 | // structure-constructor |
1457 | // N.B. Parsing ambiguities abound here without recourse to symbols |
1458 | // (see comments on R845's parser). |
1459 | struct DataStmtConstant { |
1460 | UNION_CLASS_BOILERPLATE(DataStmtConstant); |
1461 | CharBlock source; |
1462 | mutable TypedExpr typedExpr; |
1463 | std::variant<LiteralConstant, SignedIntLiteralConstant, |
1464 | SignedRealLiteralConstant, SignedComplexLiteralConstant, NullInit, |
1465 | common::Indirection<Designator>, StructureConstructor> |
1466 | u; |
1467 | }; |
1468 | |
1469 | // R844 data-stmt-repeat -> scalar-int-constant | scalar-int-constant-subobject |
1470 | // R607 int-constant -> constant |
1471 | // R604 constant -> literal-constant | named-constant |
1472 | // (only literal-constant -> int-literal-constant applies) |
1473 | struct DataStmtRepeat { |
1474 | UNION_CLASS_BOILERPLATE(DataStmtRepeat); |
1475 | std::variant<IntLiteralConstant, Scalar<Integer<ConstantSubobject>>> u; |
1476 | }; |
1477 | |
1478 | // R843 data-stmt-value -> [data-stmt-repeat *] data-stmt-constant |
1479 | struct DataStmtValue { |
1480 | TUPLE_CLASS_BOILERPLATE(DataStmtValue); |
1481 | mutable std::int64_t repetitions{1}; // replaced during semantics |
1482 | std::tuple<std::optional<DataStmtRepeat>, DataStmtConstant> t; |
1483 | }; |
1484 | |
1485 | // R841 data-i-do-object -> |
1486 | // array-element | scalar-structure-component | data-implied-do |
1487 | struct DataIDoObject { |
1488 | UNION_CLASS_BOILERPLATE(DataIDoObject); |
1489 | std::variant<Scalar<common::Indirection<Designator>>, |
1490 | common::Indirection<DataImpliedDo>> |
1491 | u; |
1492 | }; |
1493 | |
1494 | // R840 data-implied-do -> |
1495 | // ( data-i-do-object-list , [integer-type-spec ::] data-i-do-variable |
1496 | // = scalar-int-constant-expr , scalar-int-constant-expr |
1497 | // [, scalar-int-constant-expr] ) |
1498 | // R842 data-i-do-variable -> do-variable |
1499 | struct DataImpliedDo { |
1500 | TUPLE_CLASS_BOILERPLATE(DataImpliedDo); |
1501 | using Bounds = LoopBounds<DoVariable, ScalarIntConstantExpr>; |
1502 | std::tuple<std::list<DataIDoObject>, std::optional<IntegerTypeSpec>, Bounds> |
1503 | t; |
1504 | }; |
1505 | |
1506 | // R839 data-stmt-object -> variable | data-implied-do |
1507 | struct DataStmtObject { |
1508 | UNION_CLASS_BOILERPLATE(DataStmtObject); |
1509 | std::variant<common::Indirection<Variable>, DataImpliedDo> u; |
1510 | }; |
1511 | |
1512 | // R838 data-stmt-set -> data-stmt-object-list / data-stmt-value-list / |
1513 | struct DataStmtSet { |
1514 | TUPLE_CLASS_BOILERPLATE(DataStmtSet); |
1515 | std::tuple<std::list<DataStmtObject>, std::list<DataStmtValue>> t; |
1516 | }; |
1517 | |
1518 | // R837 data-stmt -> DATA data-stmt-set [[,] data-stmt-set]... |
1519 | WRAPPER_CLASS(DataStmt, std::list<DataStmtSet>); |
1520 | |
1521 | // R848 dimension-stmt -> |
1522 | // DIMENSION [::] array-name ( array-spec ) |
1523 | // [, array-name ( array-spec )]... |
1524 | struct DimensionStmt { |
1525 | struct Declaration { |
1526 | TUPLE_CLASS_BOILERPLATE(Declaration); |
1527 | std::tuple<Name, ArraySpec> t; |
1528 | }; |
1529 | WRAPPER_CLASS_BOILERPLATE(DimensionStmt, std::list<Declaration>); |
1530 | }; |
1531 | |
1532 | // R849 intent-stmt -> INTENT ( intent-spec ) [::] dummy-arg-name-list |
1533 | struct IntentStmt { |
1534 | TUPLE_CLASS_BOILERPLATE(IntentStmt); |
1535 | std::tuple<IntentSpec, std::list<Name>> t; |
1536 | }; |
1537 | |
1538 | // R850 optional-stmt -> OPTIONAL [::] dummy-arg-name-list |
1539 | WRAPPER_CLASS(OptionalStmt, std::list<Name>); |
1540 | |
1541 | // R854 pointer-decl -> |
1542 | // object-name [( deferred-shape-spec-list )] | proc-entity-name |
1543 | struct PointerDecl { |
1544 | TUPLE_CLASS_BOILERPLATE(PointerDecl); |
1545 | std::tuple<Name, std::optional<DeferredShapeSpecList>> t; |
1546 | }; |
1547 | |
1548 | // R853 pointer-stmt -> POINTER [::] pointer-decl-list |
1549 | WRAPPER_CLASS(PointerStmt, std::list<PointerDecl>); |
1550 | |
1551 | // R855 protected-stmt -> PROTECTED [::] entity-name-list |
1552 | WRAPPER_CLASS(ProtectedStmt, std::list<Name>); |
1553 | |
1554 | // R857 saved-entity -> object-name | proc-pointer-name | / common-block-name / |
1555 | // R858 proc-pointer-name -> name |
1556 | struct SavedEntity { |
1557 | TUPLE_CLASS_BOILERPLATE(SavedEntity); |
1558 | ENUM_CLASS(Kind, Entity, Common) |
1559 | std::tuple<Kind, Name> t; |
1560 | }; |
1561 | |
1562 | // R856 save-stmt -> SAVE [[::] saved-entity-list] |
1563 | WRAPPER_CLASS(SaveStmt, std::list<SavedEntity>); |
1564 | |
1565 | // R859 target-stmt -> TARGET [::] target-decl-list |
1566 | WRAPPER_CLASS(TargetStmt, std::list<ObjectDecl>); |
1567 | |
1568 | // R861 value-stmt -> VALUE [::] dummy-arg-name-list |
1569 | WRAPPER_CLASS(ValueStmt, std::list<Name>); |
1570 | |
1571 | // R862 volatile-stmt -> VOLATILE [::] object-name-list |
1572 | WRAPPER_CLASS(VolatileStmt, std::list<ObjectName>); |
1573 | |
1574 | // R865 letter-spec -> letter [- letter] |
1575 | struct LetterSpec { |
1576 | TUPLE_CLASS_BOILERPLATE(LetterSpec); |
1577 | std::tuple<Location, std::optional<Location>> t; |
1578 | }; |
1579 | |
1580 | // R864 implicit-spec -> declaration-type-spec ( letter-spec-list ) |
1581 | struct ImplicitSpec { |
1582 | TUPLE_CLASS_BOILERPLATE(ImplicitSpec); |
1583 | std::tuple<DeclarationTypeSpec, std::list<LetterSpec>> t; |
1584 | }; |
1585 | |
1586 | // R863 implicit-stmt -> |
1587 | // IMPLICIT implicit-spec-list | |
1588 | // IMPLICIT NONE [( [implicit-name-spec-list] )] |
1589 | // R866 implicit-name-spec -> EXTERNAL | TYPE |
1590 | struct ImplicitStmt { |
1591 | UNION_CLASS_BOILERPLATE(ImplicitStmt); |
1592 | ENUM_CLASS(ImplicitNoneNameSpec, External, Type) // R866 |
1593 | std::variant<std::list<ImplicitSpec>, std::list<ImplicitNoneNameSpec>> u; |
1594 | }; |
1595 | |
1596 | // R874 common-block-object -> variable-name [( array-spec )] |
1597 | struct CommonBlockObject { |
1598 | TUPLE_CLASS_BOILERPLATE(CommonBlockObject); |
1599 | std::tuple<Name, std::optional<ArraySpec>> t; |
1600 | }; |
1601 | |
1602 | // R873 common-stmt -> |
1603 | // COMMON [/ [common-block-name] /] common-block-object-list |
1604 | // [[,] / [common-block-name] / common-block-object-list]... |
1605 | struct CommonStmt { |
1606 | struct Block { |
1607 | TUPLE_CLASS_BOILERPLATE(Block); |
1608 | std::tuple<std::optional<Name>, std::list<CommonBlockObject>> t; |
1609 | }; |
1610 | BOILERPLATE(CommonStmt); |
1611 | CommonStmt(std::optional<Name> &&, std::list<CommonBlockObject> &&, |
1612 | std::list<Block> &&); |
1613 | std::list<Block> blocks; |
1614 | }; |
1615 | |
1616 | // R872 equivalence-object -> variable-name | array-element | substring |
1617 | WRAPPER_CLASS(EquivalenceObject, common::Indirection<Designator>); |
1618 | |
1619 | // R870 equivalence-stmt -> EQUIVALENCE equivalence-set-list |
1620 | // R871 equivalence-set -> ( equivalence-object , equivalence-object-list ) |
1621 | WRAPPER_CLASS(EquivalenceStmt, std::list<std::list<EquivalenceObject>>); |
1622 | |
1623 | // R910 substring-range -> [scalar-int-expr] : [scalar-int-expr] |
1624 | struct SubstringRange { |
1625 | TUPLE_CLASS_BOILERPLATE(SubstringRange); |
1626 | std::tuple<std::optional<ScalarIntExpr>, std::optional<ScalarIntExpr>> t; |
1627 | }; |
1628 | |
1629 | // R919 subscript -> scalar-int-expr |
1630 | using Subscript = ScalarIntExpr; |
1631 | |
1632 | // R921 subscript-triplet -> [subscript] : [subscript] [: stride] |
1633 | struct SubscriptTriplet { |
1634 | TUPLE_CLASS_BOILERPLATE(SubscriptTriplet); |
1635 | std::tuple<std::optional<Subscript>, std::optional<Subscript>, |
1636 | std::optional<Subscript>> |
1637 | t; |
1638 | }; |
1639 | |
1640 | // R920 section-subscript -> subscript | subscript-triplet | vector-subscript |
1641 | // R923 vector-subscript -> int-expr |
1642 | struct SectionSubscript { |
1643 | UNION_CLASS_BOILERPLATE(SectionSubscript); |
1644 | std::variant<IntExpr, SubscriptTriplet> u; |
1645 | }; |
1646 | |
1647 | // R925 cosubscript -> scalar-int-expr |
1648 | using Cosubscript = ScalarIntExpr; |
1649 | |
1650 | // R1115 team-value -> scalar-expr |
1651 | WRAPPER_CLASS(TeamValue, Scalar<common::Indirection<Expr>>); |
1652 | |
1653 | // R926 image-selector-spec -> |
1654 | // STAT = stat-variable | TEAM = team-value | |
1655 | // TEAM_NUMBER = scalar-int-expr |
1656 | struct ImageSelectorSpec { |
1657 | WRAPPER_CLASS(Stat, Scalar<Integer<common::Indirection<Variable>>>); |
1658 | WRAPPER_CLASS(Team_Number, ScalarIntExpr); |
1659 | UNION_CLASS_BOILERPLATE(ImageSelectorSpec); |
1660 | std::variant<Stat, TeamValue, Team_Number> u; |
1661 | }; |
1662 | |
1663 | // R924 image-selector -> |
1664 | // lbracket cosubscript-list [, image-selector-spec-list] rbracket |
1665 | struct ImageSelector { |
1666 | TUPLE_CLASS_BOILERPLATE(ImageSelector); |
1667 | std::tuple<std::list<Cosubscript>, std::list<ImageSelectorSpec>> t; |
1668 | }; |
1669 | |
1670 | // R1001 - R1022 expressions |
1671 | struct Expr { |
1672 | UNION_CLASS_BOILERPLATE(Expr); |
1673 | |
1674 | WRAPPER_CLASS(IntrinsicUnary, common::Indirection<Expr>); |
1675 | struct Parentheses : public IntrinsicUnary { |
1676 | using IntrinsicUnary::IntrinsicUnary; |
1677 | }; |
1678 | struct UnaryPlus : public IntrinsicUnary { |
1679 | using IntrinsicUnary::IntrinsicUnary; |
1680 | }; |
1681 | struct Negate : public IntrinsicUnary { |
1682 | using IntrinsicUnary::IntrinsicUnary; |
1683 | }; |
1684 | struct NOT : public IntrinsicUnary { |
1685 | using IntrinsicUnary::IntrinsicUnary; |
1686 | }; |
1687 | |
1688 | WRAPPER_CLASS(PercentLoc, common::Indirection<Variable>); // %LOC(v) extension |
1689 | |
1690 | struct DefinedUnary { |
1691 | TUPLE_CLASS_BOILERPLATE(DefinedUnary); |
1692 | std::tuple<DefinedOpName, common::Indirection<Expr>> t; |
1693 | }; |
1694 | |
1695 | struct IntrinsicBinary { |
1696 | TUPLE_CLASS_BOILERPLATE(IntrinsicBinary); |
1697 | std::tuple<common::Indirection<Expr>, common::Indirection<Expr>> t; |
1698 | }; |
1699 | struct Power : public IntrinsicBinary { |
1700 | using IntrinsicBinary::IntrinsicBinary; |
1701 | }; |
1702 | struct Multiply : public IntrinsicBinary { |
1703 | using IntrinsicBinary::IntrinsicBinary; |
1704 | }; |
1705 | struct Divide : public IntrinsicBinary { |
1706 | using IntrinsicBinary::IntrinsicBinary; |
1707 | }; |
1708 | struct Add : public IntrinsicBinary { |
1709 | using IntrinsicBinary::IntrinsicBinary; |
1710 | }; |
1711 | struct Subtract : public IntrinsicBinary { |
1712 | using IntrinsicBinary::IntrinsicBinary; |
1713 | }; |
1714 | struct Concat : public IntrinsicBinary { |
1715 | using IntrinsicBinary::IntrinsicBinary; |
1716 | }; |
1717 | struct LT : public IntrinsicBinary { |
1718 | using IntrinsicBinary::IntrinsicBinary; |
1719 | }; |
1720 | struct LE : public IntrinsicBinary { |
1721 | using IntrinsicBinary::IntrinsicBinary; |
1722 | }; |
1723 | struct EQ : public IntrinsicBinary { |
1724 | using IntrinsicBinary::IntrinsicBinary; |
1725 | }; |
1726 | struct NE : public IntrinsicBinary { |
1727 | using IntrinsicBinary::IntrinsicBinary; |
1728 | }; |
1729 | struct GE : public IntrinsicBinary { |
1730 | using IntrinsicBinary::IntrinsicBinary; |
1731 | }; |
1732 | struct GT : public IntrinsicBinary { |
1733 | using IntrinsicBinary::IntrinsicBinary; |
1734 | }; |
1735 | struct AND : public IntrinsicBinary { |
1736 | using IntrinsicBinary::IntrinsicBinary; |
1737 | }; |
1738 | struct OR : public IntrinsicBinary { |
1739 | using IntrinsicBinary::IntrinsicBinary; |
1740 | }; |
1741 | struct EQV : public IntrinsicBinary { |
1742 | using IntrinsicBinary::IntrinsicBinary; |
1743 | }; |
1744 | struct NEQV : public IntrinsicBinary { |
1745 | using IntrinsicBinary::IntrinsicBinary; |
1746 | }; |
1747 | |
1748 | // PGI/XLF extension: (x,y), not both constant |
1749 | struct ComplexConstructor : public IntrinsicBinary { |
1750 | using IntrinsicBinary::IntrinsicBinary; |
1751 | }; |
1752 | |
1753 | struct DefinedBinary { |
1754 | TUPLE_CLASS_BOILERPLATE(DefinedBinary); |
1755 | std::tuple<DefinedOpName, common::Indirection<Expr>, |
1756 | common::Indirection<Expr>> |
1757 | t; |
1758 | }; |
1759 | |
1760 | explicit Expr(Designator &&); |
1761 | explicit Expr(FunctionReference &&); |
1762 | |
1763 | mutable TypedExpr typedExpr; |
1764 | |
1765 | CharBlock source; |
1766 | |
1767 | std::variant<common::Indirection<CharLiteralConstantSubstring>, |
1768 | LiteralConstant, common::Indirection<Designator>, ArrayConstructor, |
1769 | StructureConstructor, common::Indirection<FunctionReference>, Parentheses, |
1770 | UnaryPlus, Negate, NOT, PercentLoc, DefinedUnary, Power, Multiply, Divide, |
1771 | Add, Subtract, Concat, LT, LE, EQ, NE, GE, GT, AND, OR, EQV, NEQV, |
1772 | DefinedBinary, ComplexConstructor, common::Indirection<SubstringInquiry>> |
1773 | u; |
1774 | }; |
1775 | |
1776 | // R912 part-ref -> part-name [( section-subscript-list )] [image-selector] |
1777 | struct PartRef { |
1778 | BOILERPLATE(PartRef); |
1779 | PartRef(Name &&n, std::list<SectionSubscript> &&ss, |
1780 | std::optional<ImageSelector> &&is) |
1781 | : name{std::move(n)}, |
1782 | subscripts(std::move(ss)), imageSelector{std::move(is)} {} |
1783 | Name name; |
1784 | std::list<SectionSubscript> subscripts; |
1785 | std::optional<ImageSelector> imageSelector; |
1786 | }; |
1787 | |
1788 | // R911 data-ref -> part-ref [% part-ref]... |
1789 | struct DataRef { |
1790 | UNION_CLASS_BOILERPLATE(DataRef); |
1791 | explicit DataRef(std::list<PartRef> &&); |
1792 | std::variant<Name, common::Indirection<StructureComponent>, |
1793 | common::Indirection<ArrayElement>, |
1794 | common::Indirection<CoindexedNamedObject>> |
1795 | u; |
1796 | }; |
1797 | |
1798 | // R908 substring -> parent-string ( substring-range ) |
1799 | // R909 parent-string -> |
1800 | // scalar-variable-name | array-element | coindexed-named-object | |
1801 | // scalar-structure-component | scalar-char-literal-constant | |
1802 | // scalar-named-constant |
1803 | // Substrings of character literals have been factored out into their |
1804 | // own productions so that they can't appear as designators in any context |
1805 | // other than a primary expression. |
1806 | struct Substring { |
1807 | TUPLE_CLASS_BOILERPLATE(Substring); |
1808 | std::tuple<DataRef, SubstringRange> t; |
1809 | }; |
1810 | |
1811 | struct CharLiteralConstantSubstring { |
1812 | TUPLE_CLASS_BOILERPLATE(CharLiteralConstantSubstring); |
1813 | std::tuple<CharLiteralConstant, SubstringRange> t; |
1814 | }; |
1815 | |
1816 | // substring%KIND/LEN type parameter inquiry for cases that could not be |
1817 | // parsed as part-refs and fixed up afterwards. N.B. we only have to |
1818 | // handle inquiries into designator-based substrings, not those based on |
1819 | // char-literal-constants. |
1820 | struct SubstringInquiry { |
1821 | CharBlock source; |
1822 | WRAPPER_CLASS_BOILERPLATE(SubstringInquiry, Substring); |
1823 | }; |
1824 | |
1825 | // R901 designator -> object-name | array-element | array-section | |
1826 | // coindexed-named-object | complex-part-designator | |
1827 | // structure-component | substring |
1828 | struct Designator { |
1829 | UNION_CLASS_BOILERPLATE(Designator); |
1830 | bool EndsInBareName() const; |
1831 | CharBlock source; |
1832 | std::variant<DataRef, Substring> u; |
1833 | }; |
1834 | |
1835 | // R902 variable -> designator | function-reference |
1836 | struct Variable { |
1837 | UNION_CLASS_BOILERPLATE(Variable); |
1838 | mutable TypedExpr typedExpr; |
1839 | CharBlock GetSource() const; |
1840 | std::variant<common::Indirection<Designator>, |
1841 | common::Indirection<FunctionReference>> |
1842 | u; |
1843 | }; |
1844 | |
1845 | // R904 logical-variable -> variable |
1846 | // Appears only as part of scalar-logical-variable. |
1847 | using ScalarLogicalVariable = Scalar<Logical<Variable>>; |
1848 | |
1849 | // R906 default-char-variable -> variable |
1850 | // Appears only as part of scalar-default-char-variable. |
1851 | using ScalarDefaultCharVariable = Scalar<DefaultChar<Variable>>; |
1852 | |
1853 | // R907 int-variable -> variable |
1854 | // Appears only as part of scalar-int-variable. |
1855 | using ScalarIntVariable = Scalar<Integer<Variable>>; |
1856 | |
1857 | // R913 structure-component -> data-ref |
1858 | struct StructureComponent { |
1859 | BOILERPLATE(StructureComponent); |
1860 | StructureComponent(DataRef &&dr, Name &&n) |
1861 | : base{std::move(dr)}, component(std::move(n)) {} |
1862 | DataRef base; |
1863 | Name component; |
1864 | }; |
1865 | |
1866 | // R1039 proc-component-ref -> scalar-variable % procedure-component-name |
1867 | // C1027 constrains the scalar-variable to be a data-ref without coindices. |
1868 | struct ProcComponentRef { |
1869 | WRAPPER_CLASS_BOILERPLATE(ProcComponentRef, Scalar<StructureComponent>); |
1870 | }; |
1871 | |
1872 | // R914 coindexed-named-object -> data-ref |
1873 | struct CoindexedNamedObject { |
1874 | BOILERPLATE(CoindexedNamedObject); |
1875 | CoindexedNamedObject(DataRef &&dr, ImageSelector &&is) |
1876 | : base{std::move(dr)}, imageSelector{std::move(is)} {} |
1877 | DataRef base; |
1878 | ImageSelector imageSelector; |
1879 | }; |
1880 | |
1881 | // R917 array-element -> data-ref |
1882 | struct ArrayElement { |
1883 | BOILERPLATE(ArrayElement); |
1884 | ArrayElement(DataRef &&dr, std::list<SectionSubscript> &&ss) |
1885 | : base{std::move(dr)}, subscripts(std::move(ss)) {} |
1886 | Substring ConvertToSubstring(); |
1887 | StructureConstructor ConvertToStructureConstructor( |
1888 | const semantics::DerivedTypeSpec &); |
1889 | DataRef base; |
1890 | std::list<SectionSubscript> subscripts; |
1891 | }; |
1892 | |
1893 | // R933 allocate-object -> variable-name | structure-component |
1894 | struct AllocateObject { |
1895 | UNION_CLASS_BOILERPLATE(AllocateObject); |
1896 | mutable TypedExpr typedExpr; |
1897 | std::variant<Name, StructureComponent> u; |
1898 | }; |
1899 | |
1900 | // R935 lower-bound-expr -> scalar-int-expr |
1901 | // R936 upper-bound-expr -> scalar-int-expr |
1902 | using BoundExpr = ScalarIntExpr; |
1903 | |
1904 | // R934 allocate-shape-spec -> [lower-bound-expr :] upper-bound-expr |
1905 | // R938 allocate-coshape-spec -> [lower-bound-expr :] upper-bound-expr |
1906 | struct AllocateShapeSpec { |
1907 | TUPLE_CLASS_BOILERPLATE(AllocateShapeSpec); |
1908 | std::tuple<std::optional<BoundExpr>, BoundExpr> t; |
1909 | }; |
1910 | |
1911 | using AllocateCoshapeSpec = AllocateShapeSpec; |
1912 | |
1913 | // R937 allocate-coarray-spec -> |
1914 | // [allocate-coshape-spec-list ,] [lower-bound-expr :] * |
1915 | struct AllocateCoarraySpec { |
1916 | TUPLE_CLASS_BOILERPLATE(AllocateCoarraySpec); |
1917 | std::tuple<std::list<AllocateCoshapeSpec>, std::optional<BoundExpr>> t; |
1918 | }; |
1919 | |
1920 | // R932 allocation -> |
1921 | // allocate-object [( allocate-shape-spec-list )] |
1922 | // [lbracket allocate-coarray-spec rbracket] |
1923 | struct Allocation { |
1924 | TUPLE_CLASS_BOILERPLATE(Allocation); |
1925 | std::tuple<AllocateObject, std::list<AllocateShapeSpec>, |
1926 | std::optional<AllocateCoarraySpec>> |
1927 | t; |
1928 | }; |
1929 | |
1930 | // R929 stat-variable -> scalar-int-variable |
1931 | WRAPPER_CLASS(StatVariable, ScalarIntVariable); |
1932 | |
1933 | // R930 errmsg-variable -> scalar-default-char-variable |
1934 | // R1207 iomsg-variable -> scalar-default-char-variable |
1935 | WRAPPER_CLASS(MsgVariable, ScalarDefaultCharVariable); |
1936 | |
1937 | // R942 dealloc-opt -> STAT = stat-variable | ERRMSG = errmsg-variable |
1938 | // R1165 sync-stat -> STAT = stat-variable | ERRMSG = errmsg-variable |
1939 | struct StatOrErrmsg { |
1940 | UNION_CLASS_BOILERPLATE(StatOrErrmsg); |
1941 | std::variant<StatVariable, MsgVariable> u; |
1942 | }; |
1943 | |
1944 | // R928 alloc-opt -> |
1945 | // ERRMSG = errmsg-variable | MOLD = source-expr | |
1946 | // SOURCE = source-expr | STAT = stat-variable | |
1947 | // (CUDA) STREAM = scalar-int-expr |
1948 | // PINNED = scalar-logical-variable |
1949 | // R931 source-expr -> expr |
1950 | struct AllocOpt { |
1951 | UNION_CLASS_BOILERPLATE(AllocOpt); |
1952 | WRAPPER_CLASS(Mold, common::Indirection<Expr>); |
1953 | WRAPPER_CLASS(Source, common::Indirection<Expr>); |
1954 | WRAPPER_CLASS(Stream, common::Indirection<ScalarIntExpr>); |
1955 | WRAPPER_CLASS(Pinned, common::Indirection<ScalarLogicalVariable>); |
1956 | std::variant<Mold, Source, StatOrErrmsg, Stream, Pinned> u; |
1957 | }; |
1958 | |
1959 | // R927 allocate-stmt -> |
1960 | // ALLOCATE ( [type-spec ::] allocation-list [, alloc-opt-list] ) |
1961 | struct AllocateStmt { |
1962 | TUPLE_CLASS_BOILERPLATE(AllocateStmt); |
1963 | std::tuple<std::optional<TypeSpec>, std::list<Allocation>, |
1964 | std::list<AllocOpt>> |
1965 | t; |
1966 | }; |
1967 | |
1968 | // R940 pointer-object -> |
1969 | // variable-name | structure-component | proc-pointer-name |
1970 | struct PointerObject { |
1971 | UNION_CLASS_BOILERPLATE(PointerObject); |
1972 | mutable TypedExpr typedExpr; |
1973 | std::variant<Name, StructureComponent> u; |
1974 | }; |
1975 | |
1976 | // R939 nullify-stmt -> NULLIFY ( pointer-object-list ) |
1977 | WRAPPER_CLASS(NullifyStmt, std::list<PointerObject>); |
1978 | |
1979 | // R941 deallocate-stmt -> |
1980 | // DEALLOCATE ( allocate-object-list [, dealloc-opt-list] ) |
1981 | struct DeallocateStmt { |
1982 | TUPLE_CLASS_BOILERPLATE(DeallocateStmt); |
1983 | std::tuple<std::list<AllocateObject>, std::list<StatOrErrmsg>> t; |
1984 | }; |
1985 | |
1986 | // R1032 assignment-stmt -> variable = expr |
1987 | struct AssignmentStmt { |
1988 | TUPLE_CLASS_BOILERPLATE(AssignmentStmt); |
1989 | using TypedAssignment = |
1990 | common::ForwardOwningPointer<evaluate::GenericAssignmentWrapper>; |
1991 | mutable TypedAssignment typedAssignment; |
1992 | std::tuple<Variable, Expr> t; |
1993 | }; |
1994 | |
1995 | // R1035 bounds-spec -> lower-bound-expr : |
1996 | WRAPPER_CLASS(BoundsSpec, BoundExpr); |
1997 | |
1998 | // R1036 bounds-remapping -> lower-bound-expr : upper-bound-expr |
1999 | struct BoundsRemapping { |
2000 | TUPLE_CLASS_BOILERPLATE(BoundsRemapping); |
2001 | std::tuple<BoundExpr, BoundExpr> t; |
2002 | }; |
2003 | |
2004 | // R1033 pointer-assignment-stmt -> |
2005 | // data-pointer-object [( bounds-spec-list )] => data-target | |
2006 | // data-pointer-object ( bounds-remapping-list ) => data-target | |
2007 | // proc-pointer-object => proc-target |
2008 | // R1034 data-pointer-object -> |
2009 | // variable-name | scalar-variable % data-pointer-component-name |
2010 | // R1038 proc-pointer-object -> proc-pointer-name | proc-component-ref |
2011 | struct PointerAssignmentStmt { |
2012 | struct Bounds { |
2013 | UNION_CLASS_BOILERPLATE(Bounds); |
2014 | std::variant<std::list<BoundsRemapping>, std::list<BoundsSpec>> u; |
2015 | }; |
2016 | TUPLE_CLASS_BOILERPLATE(PointerAssignmentStmt); |
2017 | mutable AssignmentStmt::TypedAssignment typedAssignment; |
2018 | std::tuple<DataRef, Bounds, Expr> t; |
2019 | }; |
2020 | |
2021 | // R1041 where-stmt -> WHERE ( mask-expr ) where-assignment-stmt |
2022 | // R1045 where-assignment-stmt -> assignment-stmt |
2023 | // R1046 mask-expr -> logical-expr |
2024 | struct WhereStmt { |
2025 | TUPLE_CLASS_BOILERPLATE(WhereStmt); |
2026 | std::tuple<LogicalExpr, AssignmentStmt> t; |
2027 | }; |
2028 | |
2029 | // R1043 where-construct-stmt -> [where-construct-name :] WHERE ( mask-expr ) |
2030 | struct WhereConstructStmt { |
2031 | TUPLE_CLASS_BOILERPLATE(WhereConstructStmt); |
2032 | std::tuple<std::optional<Name>, LogicalExpr> t; |
2033 | }; |
2034 | |
2035 | // R1044 where-body-construct -> |
2036 | // where-assignment-stmt | where-stmt | where-construct |
2037 | struct WhereBodyConstruct { |
2038 | UNION_CLASS_BOILERPLATE(WhereBodyConstruct); |
2039 | std::variant<Statement<AssignmentStmt>, Statement<WhereStmt>, |
2040 | common::Indirection<WhereConstruct>> |
2041 | u; |
2042 | }; |
2043 | |
2044 | // R1047 masked-elsewhere-stmt -> |
2045 | // ELSEWHERE ( mask-expr ) [where-construct-name] |
2046 | struct MaskedElsewhereStmt { |
2047 | TUPLE_CLASS_BOILERPLATE(MaskedElsewhereStmt); |
2048 | std::tuple<LogicalExpr, std::optional<Name>> t; |
2049 | }; |
2050 | |
2051 | // R1048 elsewhere-stmt -> ELSEWHERE [where-construct-name] |
2052 | WRAPPER_CLASS(ElsewhereStmt, std::optional<Name>); |
2053 | |
2054 | // R1049 end-where-stmt -> END WHERE [where-construct-name] |
2055 | WRAPPER_CLASS(EndWhereStmt, std::optional<Name>); |
2056 | |
2057 | // R1042 where-construct -> |
2058 | // where-construct-stmt [where-body-construct]... |
2059 | // [masked-elsewhere-stmt [where-body-construct]...]... |
2060 | // [elsewhere-stmt [where-body-construct]...] end-where-stmt |
2061 | struct WhereConstruct { |
2062 | struct MaskedElsewhere { |
2063 | TUPLE_CLASS_BOILERPLATE(MaskedElsewhere); |
2064 | std::tuple<Statement<MaskedElsewhereStmt>, std::list<WhereBodyConstruct>> t; |
2065 | }; |
2066 | struct Elsewhere { |
2067 | TUPLE_CLASS_BOILERPLATE(Elsewhere); |
2068 | std::tuple<Statement<ElsewhereStmt>, std::list<WhereBodyConstruct>> t; |
2069 | }; |
2070 | TUPLE_CLASS_BOILERPLATE(WhereConstruct); |
2071 | std::tuple<Statement<WhereConstructStmt>, std::list<WhereBodyConstruct>, |
2072 | std::list<MaskedElsewhere>, std::optional<Elsewhere>, |
2073 | Statement<EndWhereStmt>> |
2074 | t; |
2075 | }; |
2076 | |
2077 | // R1051 forall-construct-stmt -> |
2078 | // [forall-construct-name :] FORALL concurrent-header |
2079 | struct ForallConstructStmt { |
2080 | TUPLE_CLASS_BOILERPLATE(ForallConstructStmt); |
2081 | std::tuple<std::optional<Name>, common::Indirection<ConcurrentHeader>> t; |
2082 | }; |
2083 | |
2084 | // R1053 forall-assignment-stmt -> assignment-stmt | pointer-assignment-stmt |
2085 | struct ForallAssignmentStmt { |
2086 | UNION_CLASS_BOILERPLATE(ForallAssignmentStmt); |
2087 | std::variant<AssignmentStmt, PointerAssignmentStmt> u; |
2088 | }; |
2089 | |
2090 | // R1055 forall-stmt -> FORALL concurrent-header forall-assignment-stmt |
2091 | struct ForallStmt { |
2092 | TUPLE_CLASS_BOILERPLATE(ForallStmt); |
2093 | std::tuple<common::Indirection<ConcurrentHeader>, |
2094 | UnlabeledStatement<ForallAssignmentStmt>> |
2095 | t; |
2096 | }; |
2097 | |
2098 | // R1052 forall-body-construct -> |
2099 | // forall-assignment-stmt | where-stmt | where-construct | |
2100 | // forall-construct | forall-stmt |
2101 | struct ForallBodyConstruct { |
2102 | UNION_CLASS_BOILERPLATE(ForallBodyConstruct); |
2103 | std::variant<Statement<ForallAssignmentStmt>, Statement<WhereStmt>, |
2104 | WhereConstruct, common::Indirection<ForallConstruct>, |
2105 | Statement<ForallStmt>> |
2106 | u; |
2107 | }; |
2108 | |
2109 | // R1054 end-forall-stmt -> END FORALL [forall-construct-name] |
2110 | WRAPPER_CLASS(EndForallStmt, std::optional<Name>); |
2111 | |
2112 | // R1050 forall-construct -> |
2113 | // forall-construct-stmt [forall-body-construct]... end-forall-stmt |
2114 | struct ForallConstruct { |
2115 | TUPLE_CLASS_BOILERPLATE(ForallConstruct); |
2116 | std::tuple<Statement<ForallConstructStmt>, std::list<ForallBodyConstruct>, |
2117 | Statement<EndForallStmt>> |
2118 | t; |
2119 | }; |
2120 | |
2121 | // R1105 selector -> expr | variable |
2122 | struct Selector { |
2123 | UNION_CLASS_BOILERPLATE(Selector); |
2124 | std::variant<Expr, Variable> u; |
2125 | }; |
2126 | |
2127 | // R1104 association -> associate-name => selector |
2128 | struct Association { |
2129 | TUPLE_CLASS_BOILERPLATE(Association); |
2130 | std::tuple<Name, Selector> t; |
2131 | }; |
2132 | |
2133 | // R1103 associate-stmt -> |
2134 | // [associate-construct-name :] ASSOCIATE ( association-list ) |
2135 | struct AssociateStmt { |
2136 | TUPLE_CLASS_BOILERPLATE(AssociateStmt); |
2137 | std::tuple<std::optional<Name>, std::list<Association>> t; |
2138 | }; |
2139 | |
2140 | // R1106 end-associate-stmt -> END ASSOCIATE [associate-construct-name] |
2141 | WRAPPER_CLASS(EndAssociateStmt, std::optional<Name>); |
2142 | |
2143 | // R1102 associate-construct -> associate-stmt block end-associate-stmt |
2144 | struct AssociateConstruct { |
2145 | TUPLE_CLASS_BOILERPLATE(AssociateConstruct); |
2146 | std::tuple<Statement<AssociateStmt>, Block, Statement<EndAssociateStmt>> t; |
2147 | }; |
2148 | |
2149 | // R1108 block-stmt -> [block-construct-name :] BLOCK |
2150 | WRAPPER_CLASS(BlockStmt, std::optional<Name>); |
2151 | |
2152 | // R1110 end-block-stmt -> END BLOCK [block-construct-name] |
2153 | WRAPPER_CLASS(EndBlockStmt, std::optional<Name>); |
2154 | |
2155 | // R1109 block-specification-part -> |
2156 | // [use-stmt]... [import-stmt]... |
2157 | // [[declaration-construct]... specification-construct] |
2158 | // N.B. Because BlockSpecificationPart just wraps the more general |
2159 | // SpecificationPart, it can misrecognize an ImplicitPart as part of |
2160 | // the BlockSpecificationPart during parsing, and we have to detect and |
2161 | // flag such usage in semantics. |
2162 | WRAPPER_CLASS(BlockSpecificationPart, SpecificationPart); |
2163 | |
2164 | // R1107 block-construct -> |
2165 | // block-stmt [block-specification-part] block end-block-stmt |
2166 | struct BlockConstruct { |
2167 | TUPLE_CLASS_BOILERPLATE(BlockConstruct); |
2168 | std::tuple<Statement<BlockStmt>, BlockSpecificationPart, Block, |
2169 | Statement<EndBlockStmt>> |
2170 | t; |
2171 | }; |
2172 | |
2173 | // R1113 coarray-association -> codimension-decl => selector |
2174 | struct CoarrayAssociation { |
2175 | TUPLE_CLASS_BOILERPLATE(CoarrayAssociation); |
2176 | std::tuple<CodimensionDecl, Selector> t; |
2177 | }; |
2178 | |
2179 | // R1112 change-team-stmt -> |
2180 | // [team-construct-name :] CHANGE TEAM |
2181 | // ( team-value [, coarray-association-list] [, sync-stat-list] ) |
2182 | struct ChangeTeamStmt { |
2183 | TUPLE_CLASS_BOILERPLATE(ChangeTeamStmt); |
2184 | std::tuple<std::optional<Name>, TeamValue, std::list<CoarrayAssociation>, |
2185 | std::list<StatOrErrmsg>> |
2186 | t; |
2187 | }; |
2188 | |
2189 | // R1114 end-change-team-stmt -> |
2190 | // END TEAM [( [sync-stat-list] )] [team-construct-name] |
2191 | struct EndChangeTeamStmt { |
2192 | TUPLE_CLASS_BOILERPLATE(EndChangeTeamStmt); |
2193 | std::tuple<std::list<StatOrErrmsg>, std::optional<Name>> t; |
2194 | }; |
2195 | |
2196 | // R1111 change-team-construct -> change-team-stmt block end-change-team-stmt |
2197 | struct ChangeTeamConstruct { |
2198 | TUPLE_CLASS_BOILERPLATE(ChangeTeamConstruct); |
2199 | std::tuple<Statement<ChangeTeamStmt>, Block, Statement<EndChangeTeamStmt>> t; |
2200 | }; |
2201 | |
2202 | // R1117 critical-stmt -> |
2203 | // [critical-construct-name :] CRITICAL [( [sync-stat-list] )] |
2204 | struct CriticalStmt { |
2205 | TUPLE_CLASS_BOILERPLATE(CriticalStmt); |
2206 | std::tuple<std::optional<Name>, std::list<StatOrErrmsg>> t; |
2207 | }; |
2208 | |
2209 | // R1118 end-critical-stmt -> END CRITICAL [critical-construct-name] |
2210 | WRAPPER_CLASS(EndCriticalStmt, std::optional<Name>); |
2211 | |
2212 | // R1116 critical-construct -> critical-stmt block end-critical-stmt |
2213 | struct CriticalConstruct { |
2214 | TUPLE_CLASS_BOILERPLATE(CriticalConstruct); |
2215 | std::tuple<Statement<CriticalStmt>, Block, Statement<EndCriticalStmt>> t; |
2216 | }; |
2217 | |
2218 | // R1126 concurrent-control -> |
2219 | // index-name = concurrent-limit : concurrent-limit [: concurrent-step] |
2220 | // R1127 concurrent-limit -> scalar-int-expr |
2221 | // R1128 concurrent-step -> scalar-int-expr |
2222 | struct ConcurrentControl { |
2223 | TUPLE_CLASS_BOILERPLATE(ConcurrentControl); |
2224 | std::tuple<Name, ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>> |
2225 | t; |
2226 | }; |
2227 | |
2228 | // R1125 concurrent-header -> |
2229 | // ( [integer-type-spec ::] concurrent-control-list |
2230 | // [, scalar-mask-expr] ) |
2231 | struct ConcurrentHeader { |
2232 | TUPLE_CLASS_BOILERPLATE(ConcurrentHeader); |
2233 | std::tuple<std::optional<IntegerTypeSpec>, std::list<ConcurrentControl>, |
2234 | std::optional<ScalarLogicalExpr>> |
2235 | t; |
2236 | }; |
2237 | |
2238 | // R1130 locality-spec -> |
2239 | // LOCAL ( variable-name-list ) | LOCAL_INIT ( variable-name-list ) | |
2240 | // SHARED ( variable-name-list ) | DEFAULT ( NONE ) |
2241 | struct LocalitySpec { |
2242 | UNION_CLASS_BOILERPLATE(LocalitySpec); |
2243 | WRAPPER_CLASS(Local, std::list<Name>); |
2244 | WRAPPER_CLASS(LocalInit, std::list<Name>); |
2245 | WRAPPER_CLASS(Shared, std::list<Name>); |
2246 | EMPTY_CLASS(DefaultNone); |
2247 | std::variant<Local, LocalInit, Shared, DefaultNone> u; |
2248 | }; |
2249 | |
2250 | // R1123 loop-control -> |
2251 | // [,] do-variable = scalar-int-expr , scalar-int-expr |
2252 | // [, scalar-int-expr] | |
2253 | // [,] WHILE ( scalar-logical-expr ) | |
2254 | // [,] CONCURRENT concurrent-header concurrent-locality |
2255 | // R1129 concurrent-locality -> [locality-spec]... |
2256 | struct LoopControl { |
2257 | UNION_CLASS_BOILERPLATE(LoopControl); |
2258 | struct Concurrent { |
2259 | TUPLE_CLASS_BOILERPLATE(Concurrent); |
2260 | std::tuple<ConcurrentHeader, std::list<LocalitySpec>> t; |
2261 | }; |
2262 | using Bounds = LoopBounds<ScalarName, ScalarExpr>; |
2263 | std::variant<Bounds, ScalarLogicalExpr, Concurrent> u; |
2264 | }; |
2265 | |
2266 | // R1121 label-do-stmt -> [do-construct-name :] DO label [loop-control] |
2267 | // A label-do-stmt with a do-construct-name is parsed as a non-label-do-stmt. |
2268 | struct LabelDoStmt { |
2269 | TUPLE_CLASS_BOILERPLATE(LabelDoStmt); |
2270 | std::tuple<Label, std::optional<LoopControl>> t; |
2271 | }; |
2272 | |
2273 | // R1122 nonlabel-do-stmt -> [do-construct-name :] DO [loop-control] |
2274 | struct NonLabelDoStmt { |
2275 | TUPLE_CLASS_BOILERPLATE(NonLabelDoStmt); |
2276 | std::tuple<std::optional<Name>, std::optional<Label>, |
2277 | std::optional<LoopControl>> |
2278 | t; |
2279 | }; |
2280 | |
2281 | // R1132 end-do-stmt -> END DO [do-construct-name] |
2282 | WRAPPER_CLASS(EndDoStmt, std::optional<Name>); |
2283 | |
2284 | // R1131 end-do -> end-do-stmt | continue-stmt |
2285 | |
2286 | // R1119 do-construct -> do-stmt block end-do |
2287 | // R1120 do-stmt -> nonlabel-do-stmt | label-do-stmt |
2288 | // Deprecated, but supported: "label DO" loops ending on statements other |
2289 | // than END DO and CONTINUE, and multiple "label DO" loops ending on the |
2290 | // same label. |
2291 | struct DoConstruct { |
2292 | TUPLE_CLASS_BOILERPLATE(DoConstruct); |
2293 | const std::optional<LoopControl> &GetLoopControl() const; |
2294 | bool IsDoNormal() const; |
2295 | bool IsDoWhile() const; |
2296 | bool IsDoConcurrent() const; |
2297 | std::tuple<Statement<NonLabelDoStmt>, Block, Statement<EndDoStmt>> t; |
2298 | }; |
2299 | |
2300 | // R1133 cycle-stmt -> CYCLE [do-construct-name] |
2301 | WRAPPER_CLASS(CycleStmt, std::optional<Name>); |
2302 | |
2303 | // R1135 if-then-stmt -> [if-construct-name :] IF ( scalar-logical-expr ) THEN |
2304 | struct IfThenStmt { |
2305 | TUPLE_CLASS_BOILERPLATE(IfThenStmt); |
2306 | std::tuple<std::optional<Name>, ScalarLogicalExpr> t; |
2307 | }; |
2308 | |
2309 | // R1136 else-if-stmt -> |
2310 | // ELSE IF ( scalar-logical-expr ) THEN [if-construct-name] |
2311 | struct ElseIfStmt { |
2312 | TUPLE_CLASS_BOILERPLATE(ElseIfStmt); |
2313 | std::tuple<ScalarLogicalExpr, std::optional<Name>> t; |
2314 | }; |
2315 | |
2316 | // R1137 else-stmt -> ELSE [if-construct-name] |
2317 | WRAPPER_CLASS(ElseStmt, std::optional<Name>); |
2318 | |
2319 | // R1138 end-if-stmt -> END IF [if-construct-name] |
2320 | WRAPPER_CLASS(EndIfStmt, std::optional<Name>); |
2321 | |
2322 | // R1134 if-construct -> |
2323 | // if-then-stmt block [else-if-stmt block]... |
2324 | // [else-stmt block] end-if-stmt |
2325 | struct IfConstruct { |
2326 | struct ElseIfBlock { |
2327 | TUPLE_CLASS_BOILERPLATE(ElseIfBlock); |
2328 | std::tuple<Statement<ElseIfStmt>, Block> t; |
2329 | }; |
2330 | struct ElseBlock { |
2331 | TUPLE_CLASS_BOILERPLATE(ElseBlock); |
2332 | std::tuple<Statement<ElseStmt>, Block> t; |
2333 | }; |
2334 | TUPLE_CLASS_BOILERPLATE(IfConstruct); |
2335 | std::tuple<Statement<IfThenStmt>, Block, std::list<ElseIfBlock>, |
2336 | std::optional<ElseBlock>, Statement<EndIfStmt>> |
2337 | t; |
2338 | }; |
2339 | |
2340 | // R1139 if-stmt -> IF ( scalar-logical-expr ) action-stmt |
2341 | struct IfStmt { |
2342 | TUPLE_CLASS_BOILERPLATE(IfStmt); |
2343 | std::tuple<ScalarLogicalExpr, UnlabeledStatement<ActionStmt>> t; |
2344 | }; |
2345 | |
2346 | // R1141 select-case-stmt -> [case-construct-name :] SELECT CASE ( case-expr ) |
2347 | // R1144 case-expr -> scalar-expr |
2348 | struct SelectCaseStmt { |
2349 | TUPLE_CLASS_BOILERPLATE(SelectCaseStmt); |
2350 | std::tuple<std::optional<Name>, Scalar<Expr>> t; |
2351 | }; |
2352 | |
2353 | // R1147 case-value -> scalar-constant-expr |
2354 | using CaseValue = Scalar<ConstantExpr>; |
2355 | |
2356 | // R1146 case-value-range -> |
2357 | // case-value | case-value : | : case-value | case-value : case-value |
2358 | struct CaseValueRange { |
2359 | UNION_CLASS_BOILERPLATE(CaseValueRange); |
2360 | struct Range { |
2361 | BOILERPLATE(Range); |
2362 | Range(std::optional<CaseValue> &&l, std::optional<CaseValue> &&u) |
2363 | : lower{std::move(l)}, upper{std::move(u)} {} |
2364 | std::optional<CaseValue> lower, upper; // not both missing |
2365 | }; |
2366 | std::variant<CaseValue, Range> u; |
2367 | }; |
2368 | |
2369 | // R1145 case-selector -> ( case-value-range-list ) | DEFAULT |
2370 | EMPTY_CLASS(Default); |
2371 | |
2372 | struct CaseSelector { |
2373 | UNION_CLASS_BOILERPLATE(CaseSelector); |
2374 | std::variant<std::list<CaseValueRange>, Default> u; |
2375 | }; |
2376 | |
2377 | // R1142 case-stmt -> CASE case-selector [case-construct-name] |
2378 | struct CaseStmt { |
2379 | TUPLE_CLASS_BOILERPLATE(CaseStmt); |
2380 | std::tuple<CaseSelector, std::optional<Name>> t; |
2381 | }; |
2382 | |
2383 | // R1143 end-select-stmt -> END SELECT [case-construct-name] |
2384 | // R1151 end-select-rank-stmt -> END SELECT [select-construct-name] |
2385 | // R1155 end-select-type-stmt -> END SELECT [select-construct-name] |
2386 | WRAPPER_CLASS(EndSelectStmt, std::optional<Name>); |
2387 | |
2388 | // R1140 case-construct -> |
2389 | // select-case-stmt [case-stmt block]... end-select-stmt |
2390 | struct CaseConstruct { |
2391 | struct Case { |
2392 | TUPLE_CLASS_BOILERPLATE(Case); |
2393 | std::tuple<Statement<CaseStmt>, Block> t; |
2394 | }; |
2395 | TUPLE_CLASS_BOILERPLATE(CaseConstruct); |
2396 | std::tuple<Statement<SelectCaseStmt>, std::list<Case>, |
2397 | Statement<EndSelectStmt>> |
2398 | t; |
2399 | }; |
2400 | |
2401 | // R1149 select-rank-stmt -> |
2402 | // [select-construct-name :] SELECT RANK |
2403 | // ( [associate-name =>] selector ) |
2404 | struct SelectRankStmt { |
2405 | TUPLE_CLASS_BOILERPLATE(SelectRankStmt); |
2406 | std::tuple<std::optional<Name>, std::optional<Name>, Selector> t; |
2407 | }; |
2408 | |
2409 | // R1150 select-rank-case-stmt -> |
2410 | // RANK ( scalar-int-constant-expr ) [select-construct-name] | |
2411 | // RANK ( * ) [select-construct-name] | |
2412 | // RANK DEFAULT [select-construct-name] |
2413 | struct SelectRankCaseStmt { |
2414 | struct Rank { |
2415 | UNION_CLASS_BOILERPLATE(Rank); |
2416 | std::variant<ScalarIntConstantExpr, Star, Default> u; |
2417 | }; |
2418 | TUPLE_CLASS_BOILERPLATE(SelectRankCaseStmt); |
2419 | std::tuple<Rank, std::optional<Name>> t; |
2420 | }; |
2421 | |
2422 | // R1148 select-rank-construct -> |
2423 | // select-rank-stmt [select-rank-case-stmt block]... |
2424 | // end-select-rank-stmt |
2425 | struct SelectRankConstruct { |
2426 | TUPLE_CLASS_BOILERPLATE(SelectRankConstruct); |
2427 | struct RankCase { |
2428 | TUPLE_CLASS_BOILERPLATE(RankCase); |
2429 | std::tuple<Statement<SelectRankCaseStmt>, Block> t; |
2430 | }; |
2431 | std::tuple<Statement<SelectRankStmt>, std::list<RankCase>, |
2432 | Statement<EndSelectStmt>> |
2433 | t; |
2434 | }; |
2435 | |
2436 | // R1153 select-type-stmt -> |
2437 | // [select-construct-name :] SELECT TYPE |
2438 | // ( [associate-name =>] selector ) |
2439 | struct SelectTypeStmt { |
2440 | TUPLE_CLASS_BOILERPLATE(SelectTypeStmt); |
2441 | std::tuple<std::optional<Name>, std::optional<Name>, Selector> t; |
2442 | }; |
2443 | |
2444 | // R1154 type-guard-stmt -> |
2445 | // TYPE IS ( type-spec ) [select-construct-name] | |
2446 | // CLASS IS ( derived-type-spec ) [select-construct-name] | |
2447 | // CLASS DEFAULT [select-construct-name] |
2448 | struct TypeGuardStmt { |
2449 | struct Guard { |
2450 | UNION_CLASS_BOILERPLATE(Guard); |
2451 | std::variant<TypeSpec, DerivedTypeSpec, Default> u; |
2452 | }; |
2453 | TUPLE_CLASS_BOILERPLATE(TypeGuardStmt); |
2454 | std::tuple<Guard, std::optional<Name>> t; |
2455 | }; |
2456 | |
2457 | // R1152 select-type-construct -> |
2458 | // select-type-stmt [type-guard-stmt block]... end-select-type-stmt |
2459 | struct SelectTypeConstruct { |
2460 | TUPLE_CLASS_BOILERPLATE(SelectTypeConstruct); |
2461 | struct TypeCase { |
2462 | TUPLE_CLASS_BOILERPLATE(TypeCase); |
2463 | std::tuple<Statement<TypeGuardStmt>, Block> t; |
2464 | }; |
2465 | std::tuple<Statement<SelectTypeStmt>, std::list<TypeCase>, |
2466 | Statement<EndSelectStmt>> |
2467 | t; |
2468 | }; |
2469 | |
2470 | // R1156 exit-stmt -> EXIT [construct-name] |
2471 | WRAPPER_CLASS(ExitStmt, std::optional<Name>); |
2472 | |
2473 | // R1157 goto-stmt -> GO TO label |
2474 | WRAPPER_CLASS(GotoStmt, Label); |
2475 | |
2476 | // R1158 computed-goto-stmt -> GO TO ( label-list ) [,] scalar-int-expr |
2477 | struct ComputedGotoStmt { |
2478 | TUPLE_CLASS_BOILERPLATE(ComputedGotoStmt); |
2479 | std::tuple<std::list<Label>, ScalarIntExpr> t; |
2480 | }; |
2481 | |
2482 | // R1162 stop-code -> scalar-default-char-expr | scalar-int-expr |
2483 | // We can't distinguish character expressions from integer |
2484 | // expressions during parsing, so we just parse an expr and |
2485 | // check its type later. |
2486 | WRAPPER_CLASS(StopCode, Scalar<Expr>); |
2487 | |
2488 | // R1160 stop-stmt -> STOP [stop-code] [, QUIET = scalar-logical-expr] |
2489 | // R1161 error-stop-stmt -> |
2490 | // ERROR STOP [stop-code] [, QUIET = scalar-logical-expr] |
2491 | struct StopStmt { |
2492 | ENUM_CLASS(Kind, Stop, ErrorStop) |
2493 | TUPLE_CLASS_BOILERPLATE(StopStmt); |
2494 | std::tuple<Kind, std::optional<StopCode>, std::optional<ScalarLogicalExpr>> t; |
2495 | }; |
2496 | |
2497 | // F2023: R1166 notify-wait-stmt -> NOTIFY WAIT ( notify-variable [, |
2498 | // event-wait-spec-list] ) |
2499 | struct NotifyWaitStmt { |
2500 | TUPLE_CLASS_BOILERPLATE(NotifyWaitStmt); |
2501 | std::tuple<Scalar<Variable>, std::list<EventWaitSpec>> t; |
2502 | }; |
2503 | |
2504 | // R1164 sync-all-stmt -> SYNC ALL [( [sync-stat-list] )] |
2505 | WRAPPER_CLASS(SyncAllStmt, std::list<StatOrErrmsg>); |
2506 | |
2507 | // R1166 sync-images-stmt -> SYNC IMAGES ( image-set [, sync-stat-list] ) |
2508 | // R1167 image-set -> int-expr | * |
2509 | struct SyncImagesStmt { |
2510 | struct ImageSet { |
2511 | UNION_CLASS_BOILERPLATE(ImageSet); |
2512 | std::variant<IntExpr, Star> u; |
2513 | }; |
2514 | TUPLE_CLASS_BOILERPLATE(SyncImagesStmt); |
2515 | std::tuple<ImageSet, std::list<StatOrErrmsg>> t; |
2516 | }; |
2517 | |
2518 | // R1168 sync-memory-stmt -> SYNC MEMORY [( [sync-stat-list] )] |
2519 | WRAPPER_CLASS(SyncMemoryStmt, std::list<StatOrErrmsg>); |
2520 | |
2521 | // R1169 sync-team-stmt -> SYNC TEAM ( team-value [, sync-stat-list] ) |
2522 | struct SyncTeamStmt { |
2523 | TUPLE_CLASS_BOILERPLATE(SyncTeamStmt); |
2524 | std::tuple<TeamValue, std::list<StatOrErrmsg>> t; |
2525 | }; |
2526 | |
2527 | // R1171 event-variable -> scalar-variable |
2528 | using EventVariable = Scalar<Variable>; |
2529 | |
2530 | // R1170 event-post-stmt -> EVENT POST ( event-variable [, sync-stat-list] ) |
2531 | struct EventPostStmt { |
2532 | TUPLE_CLASS_BOILERPLATE(EventPostStmt); |
2533 | std::tuple<EventVariable, std::list<StatOrErrmsg>> t; |
2534 | }; |
2535 | |
2536 | // R1173 event-wait-spec -> until-spec | sync-stat |
2537 | struct EventWaitSpec { |
2538 | UNION_CLASS_BOILERPLATE(EventWaitSpec); |
2539 | std::variant<ScalarIntExpr, StatOrErrmsg> u; |
2540 | }; |
2541 | |
2542 | // R1172 event-wait-stmt -> |
2543 | // EVENT WAIT ( event-variable [, event-wait-spec-list] ) |
2544 | // R1174 until-spec -> UNTIL_COUNT = scalar-int-expr |
2545 | struct EventWaitStmt { |
2546 | TUPLE_CLASS_BOILERPLATE(EventWaitStmt); |
2547 | std::tuple<EventVariable, std::list<EventWaitSpec>> t; |
2548 | }; |
2549 | |
2550 | // R1177 team-variable -> scalar-variable |
2551 | using TeamVariable = Scalar<Variable>; |
2552 | |
2553 | // R1175 form-team-stmt -> |
2554 | // FORM TEAM ( team-number , team-variable [, form-team-spec-list] ) |
2555 | // R1176 team-number -> scalar-int-expr |
2556 | // R1178 form-team-spec -> NEW_INDEX = scalar-int-expr | sync-stat |
2557 | struct FormTeamStmt { |
2558 | struct FormTeamSpec { |
2559 | UNION_CLASS_BOILERPLATE(FormTeamSpec); |
2560 | std::variant<ScalarIntExpr, StatOrErrmsg> u; |
2561 | }; |
2562 | TUPLE_CLASS_BOILERPLATE(FormTeamStmt); |
2563 | std::tuple<ScalarIntExpr, TeamVariable, std::list<FormTeamSpec>> t; |
2564 | }; |
2565 | |
2566 | // R1182 lock-variable -> scalar-variable |
2567 | using LockVariable = Scalar<Variable>; |
2568 | |
2569 | // R1179 lock-stmt -> LOCK ( lock-variable [, lock-stat-list] ) |
2570 | // R1180 lock-stat -> ACQUIRED_LOCK = scalar-logical-variable | sync-stat |
2571 | struct LockStmt { |
2572 | struct LockStat { |
2573 | UNION_CLASS_BOILERPLATE(LockStat); |
2574 | std::variant<Scalar<Logical<Variable>>, StatOrErrmsg> u; |
2575 | }; |
2576 | TUPLE_CLASS_BOILERPLATE(LockStmt); |
2577 | std::tuple<LockVariable, std::list<LockStat>> t; |
2578 | }; |
2579 | |
2580 | // R1181 unlock-stmt -> UNLOCK ( lock-variable [, sync-stat-list] ) |
2581 | struct UnlockStmt { |
2582 | TUPLE_CLASS_BOILERPLATE(UnlockStmt); |
2583 | std::tuple<LockVariable, std::list<StatOrErrmsg>> t; |
2584 | }; |
2585 | |
2586 | // R1202 file-unit-number -> scalar-int-expr |
2587 | WRAPPER_CLASS(FileUnitNumber, ScalarIntExpr); |
2588 | |
2589 | // R1201 io-unit -> file-unit-number | * | internal-file-variable |
2590 | // R1203 internal-file-variable -> char-variable |
2591 | // R905 char-variable -> variable |
2592 | // When Variable appears as an IoUnit, it must be character of a default, |
2593 | // ASCII, or Unicode kind; this constraint is not automatically checked. |
2594 | // The parse is ambiguous and is repaired if necessary once the types of |
2595 | // symbols are known. |
2596 | struct IoUnit { |
2597 | UNION_CLASS_BOILERPLATE(IoUnit); |
2598 | std::variant<Variable, FileUnitNumber, Star> u; |
2599 | }; |
2600 | |
2601 | // R1206 file-name-expr -> scalar-default-char-expr |
2602 | using FileNameExpr = ScalarDefaultCharExpr; |
2603 | |
2604 | // R1205 connect-spec -> |
2605 | // [UNIT =] file-unit-number | ACCESS = scalar-default-char-expr | |
2606 | // ACTION = scalar-default-char-expr | |
2607 | // ASYNCHRONOUS = scalar-default-char-expr | |
2608 | // BLANK = scalar-default-char-expr | |
2609 | // DECIMAL = scalar-default-char-expr | |
2610 | // DELIM = scalar-default-char-expr | |
2611 | // ENCODING = scalar-default-char-expr | ERR = label | |
2612 | // FILE = file-name-expr | FORM = scalar-default-char-expr | |
2613 | // IOMSG = iomsg-variable | IOSTAT = scalar-int-variable | |
2614 | // NEWUNIT = scalar-int-variable | PAD = scalar-default-char-expr | |
2615 | // POSITION = scalar-default-char-expr | RECL = scalar-int-expr | |
2616 | // ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr | |
2617 | // STATUS = scalar-default-char-expr |
2618 | // @ | CARRIAGECONTROL = scalar-default-char-variable |
2619 | // | CONVERT = scalar-default-char-variable |
2620 | // | DISPOSE = scalar-default-char-variable |
2621 | WRAPPER_CLASS(StatusExpr, ScalarDefaultCharExpr); |
2622 | WRAPPER_CLASS(ErrLabel, Label); |
2623 | |
2624 | struct ConnectSpec { |
2625 | UNION_CLASS_BOILERPLATE(ConnectSpec); |
2626 | struct CharExpr { |
2627 | ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim, |
2628 | Encoding, Form, Pad, Position, Round, Sign, |
2629 | /* extensions: */ Carriagecontrol, Convert, Dispose) |
2630 | TUPLE_CLASS_BOILERPLATE(CharExpr); |
2631 | std::tuple<Kind, ScalarDefaultCharExpr> t; |
2632 | }; |
2633 | WRAPPER_CLASS(Recl, ScalarIntExpr); |
2634 | WRAPPER_CLASS(Newunit, ScalarIntVariable); |
2635 | std::variant<FileUnitNumber, FileNameExpr, CharExpr, MsgVariable, |
2636 | StatVariable, Recl, Newunit, ErrLabel, StatusExpr> |
2637 | u; |
2638 | }; |
2639 | |
2640 | // R1204 open-stmt -> OPEN ( connect-spec-list ) |
2641 | WRAPPER_CLASS(OpenStmt, std::list<ConnectSpec>); |
2642 | |
2643 | // R1208 close-stmt -> CLOSE ( close-spec-list ) |
2644 | // R1209 close-spec -> |
2645 | // [UNIT =] file-unit-number | IOSTAT = scalar-int-variable | |
2646 | // IOMSG = iomsg-variable | ERR = label | |
2647 | // STATUS = scalar-default-char-expr |
2648 | struct CloseStmt { |
2649 | struct CloseSpec { |
2650 | UNION_CLASS_BOILERPLATE(CloseSpec); |
2651 | std::variant<FileUnitNumber, StatVariable, MsgVariable, ErrLabel, |
2652 | StatusExpr> |
2653 | u; |
2654 | }; |
2655 | WRAPPER_CLASS_BOILERPLATE(CloseStmt, std::list<CloseSpec>); |
2656 | }; |
2657 | |
2658 | // R1215 format -> default-char-expr | label | * |
2659 | // deprecated(ASSIGN): | scalar-int-name |
2660 | struct Format { |
2661 | UNION_CLASS_BOILERPLATE(Format); |
2662 | std::variant<Expr, Label, Star> u; |
2663 | }; |
2664 | |
2665 | // R1214 id-variable -> scalar-int-variable |
2666 | WRAPPER_CLASS(IdVariable, ScalarIntVariable); |
2667 | |
2668 | // R1213 io-control-spec -> |
2669 | // [UNIT =] io-unit | [FMT =] format | [NML =] namelist-group-name | |
2670 | // ADVANCE = scalar-default-char-expr | |
2671 | // ASYNCHRONOUS = scalar-default-char-constant-expr | |
2672 | // BLANK = scalar-default-char-expr | |
2673 | // DECIMAL = scalar-default-char-expr | |
2674 | // DELIM = scalar-default-char-expr | END = label | EOR = label | |
2675 | // ERR = label | ID = id-variable | IOMSG = iomsg-variable | |
2676 | // IOSTAT = scalar-int-variable | PAD = scalar-default-char-expr | |
2677 | // POS = scalar-int-expr | REC = scalar-int-expr | |
2678 | // ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr | |
2679 | // SIZE = scalar-int-variable |
2680 | WRAPPER_CLASS(EndLabel, Label); |
2681 | WRAPPER_CLASS(EorLabel, Label); |
2682 | struct IoControlSpec { |
2683 | UNION_CLASS_BOILERPLATE(IoControlSpec); |
2684 | struct CharExpr { |
2685 | ENUM_CLASS(Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign) |
2686 | TUPLE_CLASS_BOILERPLATE(CharExpr); |
2687 | std::tuple<Kind, ScalarDefaultCharExpr> t; |
2688 | }; |
2689 | WRAPPER_CLASS(Asynchronous, ScalarDefaultCharConstantExpr); |
2690 | WRAPPER_CLASS(Pos, ScalarIntExpr); |
2691 | WRAPPER_CLASS(Rec, ScalarIntExpr); |
2692 | WRAPPER_CLASS(Size, ScalarIntVariable); |
2693 | std::variant<IoUnit, Format, Name, CharExpr, Asynchronous, EndLabel, EorLabel, |
2694 | ErrLabel, IdVariable, MsgVariable, StatVariable, Pos, Rec, Size> |
2695 | u; |
2696 | }; |
2697 | |
2698 | // R1216 input-item -> variable | io-implied-do |
2699 | struct InputItem { |
2700 | UNION_CLASS_BOILERPLATE(InputItem); |
2701 | std::variant<Variable, common::Indirection<InputImpliedDo>> u; |
2702 | }; |
2703 | |
2704 | // R1210 read-stmt -> |
2705 | // READ ( io-control-spec-list ) [input-item-list] | |
2706 | // READ format [, input-item-list] |
2707 | struct ReadStmt { |
2708 | BOILERPLATE(ReadStmt); |
2709 | ReadStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f, |
2710 | std::list<IoControlSpec> &&cs, std::list<InputItem> &&its) |
2711 | : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)), |
2712 | items(std::move(its)) {} |
2713 | std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or |
2714 | // followed by untagged format/namelist |
2715 | std::optional<Format> format; // if second in controls without FMT=/NML=, or |
2716 | // no (io-control-spec-list); might be |
2717 | // an untagged namelist group name |
2718 | std::list<IoControlSpec> controls; |
2719 | std::list<InputItem> items; |
2720 | }; |
2721 | |
2722 | // R1217 output-item -> expr | io-implied-do |
2723 | struct OutputItem { |
2724 | UNION_CLASS_BOILERPLATE(OutputItem); |
2725 | std::variant<Expr, common::Indirection<OutputImpliedDo>> u; |
2726 | }; |
2727 | |
2728 | // R1211 write-stmt -> WRITE ( io-control-spec-list ) [output-item-list] |
2729 | struct WriteStmt { |
2730 | BOILERPLATE(WriteStmt); |
2731 | WriteStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f, |
2732 | std::list<IoControlSpec> &&cs, std::list<OutputItem> &&its) |
2733 | : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)), |
2734 | items(std::move(its)) {} |
2735 | std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or |
2736 | // followed by untagged format/namelist |
2737 | std::optional<Format> format; // if second in controls without FMT=/NML=; |
2738 | // might be an untagged namelist group, too |
2739 | std::list<IoControlSpec> controls; |
2740 | std::list<OutputItem> items; |
2741 | }; |
2742 | |
2743 | // R1212 print-stmt PRINT format [, output-item-list] |
2744 | struct PrintStmt { |
2745 | TUPLE_CLASS_BOILERPLATE(PrintStmt); |
2746 | std::tuple<Format, std::list<OutputItem>> t; |
2747 | }; |
2748 | |
2749 | // R1220 io-implied-do-control -> |
2750 | // do-variable = scalar-int-expr , scalar-int-expr [, scalar-int-expr] |
2751 | using IoImpliedDoControl = LoopBounds<DoVariable, ScalarIntExpr>; |
2752 | |
2753 | // R1218 io-implied-do -> ( io-implied-do-object-list , io-implied-do-control ) |
2754 | // R1219 io-implied-do-object -> input-item | output-item |
2755 | struct InputImpliedDo { |
2756 | TUPLE_CLASS_BOILERPLATE(InputImpliedDo); |
2757 | std::tuple<std::list<InputItem>, IoImpliedDoControl> t; |
2758 | }; |
2759 | |
2760 | struct OutputImpliedDo { |
2761 | TUPLE_CLASS_BOILERPLATE(OutputImpliedDo); |
2762 | std::tuple<std::list<OutputItem>, IoImpliedDoControl> t; |
2763 | }; |
2764 | |
2765 | // R1223 wait-spec -> |
2766 | // [UNIT =] file-unit-number | END = label | EOR = label | ERR = label | |
2767 | // ID = scalar-int-expr | IOMSG = iomsg-variable | |
2768 | // IOSTAT = scalar-int-variable |
2769 | WRAPPER_CLASS(IdExpr, ScalarIntExpr); |
2770 | struct WaitSpec { |
2771 | UNION_CLASS_BOILERPLATE(WaitSpec); |
2772 | std::variant<FileUnitNumber, EndLabel, EorLabel, ErrLabel, IdExpr, |
2773 | MsgVariable, StatVariable> |
2774 | u; |
2775 | }; |
2776 | |
2777 | // R1222 wait-stmt -> WAIT ( wait-spec-list ) |
2778 | WRAPPER_CLASS(WaitStmt, std::list<WaitSpec>); |
2779 | |
2780 | // R1227 position-spec -> |
2781 | // [UNIT =] file-unit-number | IOMSG = iomsg-variable | |
2782 | // IOSTAT = scalar-int-variable | ERR = label |
2783 | // R1229 flush-spec -> |
2784 | // [UNIT =] file-unit-number | IOSTAT = scalar-int-variable | |
2785 | // IOMSG = iomsg-variable | ERR = label |
2786 | struct PositionOrFlushSpec { |
2787 | UNION_CLASS_BOILERPLATE(PositionOrFlushSpec); |
2788 | std::variant<FileUnitNumber, MsgVariable, StatVariable, ErrLabel> u; |
2789 | }; |
2790 | |
2791 | // R1224 backspace-stmt -> |
2792 | // BACKSPACE file-unit-number | BACKSPACE ( position-spec-list ) |
2793 | WRAPPER_CLASS(BackspaceStmt, std::list<PositionOrFlushSpec>); |
2794 | |
2795 | // R1225 endfile-stmt -> |
2796 | // ENDFILE file-unit-number | ENDFILE ( position-spec-list ) |
2797 | WRAPPER_CLASS(EndfileStmt, std::list<PositionOrFlushSpec>); |
2798 | |
2799 | // R1226 rewind-stmt -> REWIND file-unit-number | REWIND ( position-spec-list ) |
2800 | WRAPPER_CLASS(RewindStmt, std::list<PositionOrFlushSpec>); |
2801 | |
2802 | // R1228 flush-stmt -> FLUSH file-unit-number | FLUSH ( flush-spec-list ) |
2803 | WRAPPER_CLASS(FlushStmt, std::list<PositionOrFlushSpec>); |
2804 | |
2805 | // R1231 inquire-spec -> |
2806 | // [UNIT =] file-unit-number | FILE = file-name-expr | |
2807 | // ACCESS = scalar-default-char-variable | |
2808 | // ACTION = scalar-default-char-variable | |
2809 | // ASYNCHRONOUS = scalar-default-char-variable | |
2810 | // BLANK = scalar-default-char-variable | |
2811 | // DECIMAL = scalar-default-char-variable | |
2812 | // DELIM = scalar-default-char-variable | |
2813 | // DIRECT = scalar-default-char-variable | |
2814 | // ENCODING = scalar-default-char-variable | |
2815 | // ERR = label | EXIST = scalar-logical-variable | |
2816 | // FORM = scalar-default-char-variable | |
2817 | // FORMATTED = scalar-default-char-variable | |
2818 | // ID = scalar-int-expr | IOMSG = iomsg-variable | |
2819 | // IOSTAT = scalar-int-variable | |
2820 | // NAME = scalar-default-char-variable | |
2821 | // NAMED = scalar-logical-variable | |
2822 | // NEXTREC = scalar-int-variable | NUMBER = scalar-int-variable | |
2823 | // OPENED = scalar-logical-variable | |
2824 | // PAD = scalar-default-char-variable | |
2825 | // PENDING = scalar-logical-variable | POS = scalar-int-variable | |
2826 | // POSITION = scalar-default-char-variable | |
2827 | // READ = scalar-default-char-variable | |
2828 | // READWRITE = scalar-default-char-variable | |
2829 | // RECL = scalar-int-variable | ROUND = scalar-default-char-variable | |
2830 | // SEQUENTIAL = scalar-default-char-variable | |
2831 | // SIGN = scalar-default-char-variable | |
2832 | // SIZE = scalar-int-variable | |
2833 | // STREAM = scalar-default-char-variable | |
2834 | // STATUS = scalar-default-char-variable | |
2835 | // UNFORMATTED = scalar-default-char-variable | |
2836 | // WRITE = scalar-default-char-variable |
2837 | // @ | CARRIAGECONTROL = scalar-default-char-variable |
2838 | // | CONVERT = scalar-default-char-variable |
2839 | // | DISPOSE = scalar-default-char-variable |
2840 | struct InquireSpec { |
2841 | UNION_CLASS_BOILERPLATE(InquireSpec); |
2842 | struct CharVar { |
2843 | ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim, |
2844 | Direct, Encoding, Form, Formatted, Iomsg, Name, Pad, Position, Read, |
2845 | Readwrite, Round, Sequential, Sign, Stream, Status, Unformatted, Write, |
2846 | /* extensions: */ Carriagecontrol, Convert, Dispose) |
2847 | TUPLE_CLASS_BOILERPLATE(CharVar); |
2848 | std::tuple<Kind, ScalarDefaultCharVariable> t; |
2849 | }; |
2850 | struct IntVar { |
2851 | ENUM_CLASS(Kind, Iostat, Nextrec, Number, Pos, Recl, Size) |
2852 | TUPLE_CLASS_BOILERPLATE(IntVar); |
2853 | std::tuple<Kind, ScalarIntVariable> t; |
2854 | }; |
2855 | struct LogVar { |
2856 | ENUM_CLASS(Kind, Exist, Named, Opened, Pending) |
2857 | TUPLE_CLASS_BOILERPLATE(LogVar); |
2858 | std::tuple<Kind, Scalar<Logical<Variable>>> t; |
2859 | }; |
2860 | std::variant<FileUnitNumber, FileNameExpr, CharVar, IntVar, LogVar, IdExpr, |
2861 | ErrLabel> |
2862 | u; |
2863 | }; |
2864 | |
2865 | // R1230 inquire-stmt -> |
2866 | // INQUIRE ( inquire-spec-list ) | |
2867 | // INQUIRE ( IOLENGTH = scalar-int-variable ) output-item-list |
2868 | struct InquireStmt { |
2869 | UNION_CLASS_BOILERPLATE(InquireStmt); |
2870 | struct Iolength { |
2871 | TUPLE_CLASS_BOILERPLATE(Iolength); |
2872 | std::tuple<ScalarIntVariable, std::list<OutputItem>> t; |
2873 | }; |
2874 | std::variant<std::list<InquireSpec>, Iolength> u; |
2875 | }; |
2876 | |
2877 | // R1301 format-stmt -> FORMAT format-specification |
2878 | WRAPPER_CLASS(FormatStmt, format::FormatSpecification); |
2879 | |
2880 | // R1402 program-stmt -> PROGRAM program-name |
2881 | WRAPPER_CLASS(ProgramStmt, Name); |
2882 | |
2883 | // R1403 end-program-stmt -> END [PROGRAM [program-name]] |
2884 | WRAPPER_CLASS(EndProgramStmt, std::optional<Name>); |
2885 | |
2886 | // R1401 main-program -> |
2887 | // [program-stmt] [specification-part] [execution-part] |
2888 | // [internal-subprogram-part] end-program-stmt |
2889 | struct MainProgram { |
2890 | TUPLE_CLASS_BOILERPLATE(MainProgram); |
2891 | std::tuple<std::optional<Statement<ProgramStmt>>, SpecificationPart, |
2892 | ExecutionPart, std::optional<InternalSubprogramPart>, |
2893 | Statement<EndProgramStmt>> |
2894 | t; |
2895 | }; |
2896 | |
2897 | // R1405 module-stmt -> MODULE module-name |
2898 | WRAPPER_CLASS(ModuleStmt, Name); |
2899 | |
2900 | // R1408 module-subprogram -> |
2901 | // function-subprogram | subroutine-subprogram | |
2902 | // separate-module-subprogram |
2903 | struct ModuleSubprogram { |
2904 | UNION_CLASS_BOILERPLATE(ModuleSubprogram); |
2905 | std::variant<common::Indirection<FunctionSubprogram>, |
2906 | common::Indirection<SubroutineSubprogram>, |
2907 | common::Indirection<SeparateModuleSubprogram>> |
2908 | u; |
2909 | }; |
2910 | |
2911 | // R1407 module-subprogram-part -> contains-stmt [module-subprogram]... |
2912 | struct ModuleSubprogramPart { |
2913 | TUPLE_CLASS_BOILERPLATE(ModuleSubprogramPart); |
2914 | std::tuple<Statement<ContainsStmt>, std::list<ModuleSubprogram>> t; |
2915 | }; |
2916 | |
2917 | // R1406 end-module-stmt -> END [MODULE [module-name]] |
2918 | WRAPPER_CLASS(EndModuleStmt, std::optional<Name>); |
2919 | |
2920 | // R1404 module -> |
2921 | // module-stmt [specification-part] [module-subprogram-part] |
2922 | // end-module-stmt |
2923 | struct Module { |
2924 | TUPLE_CLASS_BOILERPLATE(Module); |
2925 | std::tuple<Statement<ModuleStmt>, SpecificationPart, |
2926 | std::optional<ModuleSubprogramPart>, Statement<EndModuleStmt>> |
2927 | t; |
2928 | }; |
2929 | |
2930 | // R1411 rename -> |
2931 | // local-name => use-name | |
2932 | // OPERATOR ( local-defined-operator ) => |
2933 | // OPERATOR ( use-defined-operator ) |
2934 | struct Rename { |
2935 | UNION_CLASS_BOILERPLATE(Rename); |
2936 | struct Names { |
2937 | TUPLE_CLASS_BOILERPLATE(Names); |
2938 | std::tuple<Name, Name> t; |
2939 | }; |
2940 | struct Operators { |
2941 | TUPLE_CLASS_BOILERPLATE(Operators); |
2942 | std::tuple<DefinedOpName, DefinedOpName> t; |
2943 | }; |
2944 | std::variant<Names, Operators> u; |
2945 | }; |
2946 | |
2947 | // R1418 parent-identifier -> ancestor-module-name [: parent-submodule-name] |
2948 | struct ParentIdentifier { |
2949 | TUPLE_CLASS_BOILERPLATE(ParentIdentifier); |
2950 | std::tuple<Name, std::optional<Name>> t; |
2951 | }; |
2952 | |
2953 | // R1417 submodule-stmt -> SUBMODULE ( parent-identifier ) submodule-name |
2954 | struct SubmoduleStmt { |
2955 | TUPLE_CLASS_BOILERPLATE(SubmoduleStmt); |
2956 | std::tuple<ParentIdentifier, Name> t; |
2957 | }; |
2958 | |
2959 | // R1419 end-submodule-stmt -> END [SUBMODULE [submodule-name]] |
2960 | WRAPPER_CLASS(EndSubmoduleStmt, std::optional<Name>); |
2961 | |
2962 | // R1416 submodule -> |
2963 | // submodule-stmt [specification-part] [module-subprogram-part] |
2964 | // end-submodule-stmt |
2965 | struct Submodule { |
2966 | TUPLE_CLASS_BOILERPLATE(Submodule); |
2967 | std::tuple<Statement<SubmoduleStmt>, SpecificationPart, |
2968 | std::optional<ModuleSubprogramPart>, Statement<EndSubmoduleStmt>> |
2969 | t; |
2970 | }; |
2971 | |
2972 | // R1421 block-data-stmt -> BLOCK DATA [block-data-name] |
2973 | WRAPPER_CLASS(BlockDataStmt, std::optional<Name>); |
2974 | |
2975 | // R1422 end-block-data-stmt -> END [BLOCK DATA [block-data-name]] |
2976 | WRAPPER_CLASS(EndBlockDataStmt, std::optional<Name>); |
2977 | |
2978 | // R1420 block-data -> block-data-stmt [specification-part] end-block-data-stmt |
2979 | struct BlockData { |
2980 | TUPLE_CLASS_BOILERPLATE(BlockData); |
2981 | std::tuple<Statement<BlockDataStmt>, SpecificationPart, |
2982 | Statement<EndBlockDataStmt>> |
2983 | t; |
2984 | }; |
2985 | |
2986 | // R1508 generic-spec -> |
2987 | // generic-name | OPERATOR ( defined-operator ) | |
2988 | // ASSIGNMENT ( = ) | defined-io-generic-spec |
2989 | // R1509 defined-io-generic-spec -> |
2990 | // READ ( FORMATTED ) | READ ( UNFORMATTED ) | |
2991 | // WRITE ( FORMATTED ) | WRITE ( UNFORMATTED ) |
2992 | struct GenericSpec { |
2993 | UNION_CLASS_BOILERPLATE(GenericSpec); |
2994 | EMPTY_CLASS(Assignment); |
2995 | EMPTY_CLASS(ReadFormatted); |
2996 | EMPTY_CLASS(ReadUnformatted); |
2997 | EMPTY_CLASS(WriteFormatted); |
2998 | EMPTY_CLASS(WriteUnformatted); |
2999 | CharBlock source; |
3000 | std::variant<Name, DefinedOperator, Assignment, ReadFormatted, |
3001 | ReadUnformatted, WriteFormatted, WriteUnformatted> |
3002 | u; |
3003 | }; |
3004 | |
3005 | // R1510 generic-stmt -> |
3006 | // GENERIC [, access-spec] :: generic-spec => specific-procedure-list |
3007 | struct GenericStmt { |
3008 | TUPLE_CLASS_BOILERPLATE(GenericStmt); |
3009 | std::tuple<std::optional<AccessSpec>, GenericSpec, std::list<Name>> t; |
3010 | }; |
3011 | |
3012 | // R1503 interface-stmt -> INTERFACE [generic-spec] | ABSTRACT INTERFACE |
3013 | struct InterfaceStmt { |
3014 | UNION_CLASS_BOILERPLATE(InterfaceStmt); |
3015 | // Workaround for clang with libstc++10 bug |
3016 | InterfaceStmt(Abstract x) : u{x} {} |
3017 | |
3018 | std::variant<std::optional<GenericSpec>, Abstract> u; |
3019 | }; |
3020 | |
3021 | // R1412 only -> generic-spec | only-use-name | rename |
3022 | // R1413 only-use-name -> use-name |
3023 | struct Only { |
3024 | UNION_CLASS_BOILERPLATE(Only); |
3025 | std::variant<common::Indirection<GenericSpec>, Name, Rename> u; |
3026 | }; |
3027 | |
3028 | // R1409 use-stmt -> |
3029 | // USE [[, module-nature] ::] module-name [, rename-list] | |
3030 | // USE [[, module-nature] ::] module-name , ONLY : [only-list] |
3031 | // R1410 module-nature -> INTRINSIC | NON_INTRINSIC |
3032 | struct UseStmt { |
3033 | BOILERPLATE(UseStmt); |
3034 | ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic) // R1410 |
3035 | template <typename A> |
3036 | UseStmt(std::optional<ModuleNature> &&nat, Name &&n, std::list<A> &&x) |
3037 | : nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {} |
3038 | std::optional<ModuleNature> nature; |
3039 | Name moduleName; |
3040 | std::variant<std::list<Rename>, std::list<Only>> u; |
3041 | }; |
3042 | |
3043 | // R1514 proc-attr-spec -> |
3044 | // access-spec | proc-language-binding-spec | INTENT ( intent-spec ) | |
3045 | // OPTIONAL | POINTER | PROTECTED | SAVE |
3046 | struct ProcAttrSpec { |
3047 | UNION_CLASS_BOILERPLATE(ProcAttrSpec); |
3048 | std::variant<AccessSpec, LanguageBindingSpec, IntentSpec, Optional, Pointer, |
3049 | Protected, Save> |
3050 | u; |
3051 | }; |
3052 | |
3053 | // R1512 procedure-declaration-stmt -> |
3054 | // PROCEDURE ( [proc-interface] ) [[, proc-attr-spec]... ::] |
3055 | // proc-decl-list |
3056 | struct ProcedureDeclarationStmt { |
3057 | TUPLE_CLASS_BOILERPLATE(ProcedureDeclarationStmt); |
3058 | std::tuple<std::optional<ProcInterface>, std::list<ProcAttrSpec>, |
3059 | std::list<ProcDecl>> |
3060 | t; |
3061 | }; |
3062 | |
3063 | // R1527 prefix-spec -> |
3064 | // declaration-type-spec | ELEMENTAL | IMPURE | MODULE | |
3065 | // NON_RECURSIVE | PURE | RECURSIVE | |
3066 | // (CUDA) ATTRIBUTES ( (DEVICE | GLOBAL | GRID_GLOBAL | HOST)... ) |
3067 | // LAUNCH_BOUNDS(expr-list) | CLUSTER_DIMS(expr-list) |
3068 | struct PrefixSpec { |
3069 | UNION_CLASS_BOILERPLATE(PrefixSpec); |
3070 | EMPTY_CLASS(Elemental); |
3071 | EMPTY_CLASS(Impure); |
3072 | EMPTY_CLASS(Module); |
3073 | EMPTY_CLASS(Non_Recursive); |
3074 | EMPTY_CLASS(Pure); |
3075 | EMPTY_CLASS(Recursive); |
3076 | WRAPPER_CLASS(Attributes, std::list<common::CUDASubprogramAttrs>); |
3077 | WRAPPER_CLASS(Launch_Bounds, std::list<ScalarIntConstantExpr>); |
3078 | WRAPPER_CLASS(Cluster_Dims, std::list<ScalarIntConstantExpr>); |
3079 | std::variant<DeclarationTypeSpec, Elemental, Impure, Module, Non_Recursive, |
3080 | Pure, Recursive, Attributes, Launch_Bounds, Cluster_Dims> |
3081 | u; |
3082 | }; |
3083 | |
3084 | // R1532 suffix -> |
3085 | // proc-language-binding-spec [RESULT ( result-name )] | |
3086 | // RESULT ( result-name ) [proc-language-binding-spec] |
3087 | struct Suffix { |
3088 | BOILERPLATE(Suffix); |
3089 | Suffix(LanguageBindingSpec &&lbs, std::optional<Name> &&rn) |
3090 | : binding(std::move(lbs)), resultName(std::move(rn)) {} |
3091 | Suffix(Name &&rn, std::optional<LanguageBindingSpec> &&lbs) |
3092 | : binding(std::move(lbs)), resultName(std::move(rn)) {} |
3093 | std::optional<LanguageBindingSpec> binding; |
3094 | std::optional<Name> resultName; |
3095 | }; |
3096 | |
3097 | // R1530 function-stmt -> |
3098 | // [prefix] FUNCTION function-name ( [dummy-arg-name-list] ) [suffix] |
3099 | // R1526 prefix -> prefix-spec [prefix-spec]... |
3100 | // R1531 dummy-arg-name -> name |
3101 | struct FunctionStmt { |
3102 | TUPLE_CLASS_BOILERPLATE(FunctionStmt); |
3103 | std::tuple<std::list<PrefixSpec>, Name, std::list<Name>, |
3104 | std::optional<Suffix>> |
3105 | t; |
3106 | }; |
3107 | |
3108 | // R1533 end-function-stmt -> END [FUNCTION [function-name]] |
3109 | WRAPPER_CLASS(EndFunctionStmt, std::optional<Name>); |
3110 | |
3111 | // R1536 dummy-arg -> dummy-arg-name | * |
3112 | struct DummyArg { |
3113 | UNION_CLASS_BOILERPLATE(DummyArg); |
3114 | std::variant<Name, Star> u; |
3115 | }; |
3116 | |
3117 | // R1535 subroutine-stmt -> |
3118 | // [prefix] SUBROUTINE subroutine-name [( [dummy-arg-list] ) |
3119 | // [proc-language-binding-spec]] |
3120 | struct SubroutineStmt { |
3121 | TUPLE_CLASS_BOILERPLATE(SubroutineStmt); |
3122 | std::tuple<std::list<PrefixSpec>, Name, std::list<DummyArg>, |
3123 | std::optional<LanguageBindingSpec>> |
3124 | t; |
3125 | }; |
3126 | |
3127 | // R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]] |
3128 | WRAPPER_CLASS(EndSubroutineStmt, std::optional<Name>); |
3129 | |
3130 | // R1505 interface-body -> |
3131 | // function-stmt [specification-part] end-function-stmt | |
3132 | // subroutine-stmt [specification-part] end-subroutine-stmt |
3133 | struct InterfaceBody { |
3134 | UNION_CLASS_BOILERPLATE(InterfaceBody); |
3135 | struct Function { |
3136 | TUPLE_CLASS_BOILERPLATE(Function); |
3137 | std::tuple<Statement<FunctionStmt>, common::Indirection<SpecificationPart>, |
3138 | Statement<EndFunctionStmt>> |
3139 | t; |
3140 | }; |
3141 | struct Subroutine { |
3142 | TUPLE_CLASS_BOILERPLATE(Subroutine); |
3143 | std::tuple<Statement<SubroutineStmt>, |
3144 | common::Indirection<SpecificationPart>, Statement<EndSubroutineStmt>> |
3145 | t; |
3146 | }; |
3147 | std::variant<Function, Subroutine> u; |
3148 | }; |
3149 | |
3150 | // R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list |
3151 | struct ProcedureStmt { |
3152 | ENUM_CLASS(Kind, ModuleProcedure, Procedure) |
3153 | TUPLE_CLASS_BOILERPLATE(ProcedureStmt); |
3154 | std::tuple<Kind, std::list<Name>> t; |
3155 | }; |
3156 | |
3157 | // R1502 interface-specification -> interface-body | procedure-stmt |
3158 | struct InterfaceSpecification { |
3159 | UNION_CLASS_BOILERPLATE(InterfaceSpecification); |
3160 | std::variant<InterfaceBody, Statement<ProcedureStmt>> u; |
3161 | }; |
3162 | |
3163 | // R1504 end-interface-stmt -> END INTERFACE [generic-spec] |
3164 | WRAPPER_CLASS(EndInterfaceStmt, std::optional<GenericSpec>); |
3165 | |
3166 | // R1501 interface-block -> |
3167 | // interface-stmt [interface-specification]... end-interface-stmt |
3168 | struct InterfaceBlock { |
3169 | TUPLE_CLASS_BOILERPLATE(InterfaceBlock); |
3170 | std::tuple<Statement<InterfaceStmt>, std::list<InterfaceSpecification>, |
3171 | Statement<EndInterfaceStmt>> |
3172 | t; |
3173 | }; |
3174 | |
3175 | // R1511 external-stmt -> EXTERNAL [::] external-name-list |
3176 | WRAPPER_CLASS(ExternalStmt, std::list<Name>); |
3177 | |
3178 | // R1519 intrinsic-stmt -> INTRINSIC [::] intrinsic-procedure-name-list |
3179 | WRAPPER_CLASS(IntrinsicStmt, std::list<Name>); |
3180 | |
3181 | // R1522 procedure-designator -> |
3182 | // procedure-name | proc-component-ref | data-ref % binding-name |
3183 | struct ProcedureDesignator { |
3184 | UNION_CLASS_BOILERPLATE(ProcedureDesignator); |
3185 | std::variant<Name, ProcComponentRef> u; |
3186 | }; |
3187 | |
3188 | // R1525 alt-return-spec -> * label |
3189 | WRAPPER_CLASS(AltReturnSpec, Label); |
3190 | |
3191 | // R1524 actual-arg -> |
3192 | // expr | variable | procedure-name | proc-component-ref | |
3193 | // alt-return-spec |
3194 | struct ActualArg { |
3195 | WRAPPER_CLASS(PercentRef, Variable); // %REF(v) extension |
3196 | WRAPPER_CLASS(PercentVal, Expr); // %VAL(x) extension |
3197 | UNION_CLASS_BOILERPLATE(ActualArg); |
3198 | ActualArg(Expr &&x) : u{common::Indirection<Expr>(std::move(x))} {} |
3199 | std::variant<common::Indirection<Expr>, AltReturnSpec, PercentRef, PercentVal> |
3200 | u; |
3201 | }; |
3202 | |
3203 | // R1523 actual-arg-spec -> [keyword =] actual-arg |
3204 | struct ActualArgSpec { |
3205 | TUPLE_CLASS_BOILERPLATE(ActualArgSpec); |
3206 | std::tuple<std::optional<Keyword>, ActualArg> t; |
3207 | }; |
3208 | |
3209 | // R1520 function-reference -> procedure-designator |
3210 | // ( [actual-arg-spec-list] ) |
3211 | struct Call { |
3212 | TUPLE_CLASS_BOILERPLATE(Call); |
3213 | std::tuple<ProcedureDesignator, std::list<ActualArgSpec>> t; |
3214 | }; |
3215 | |
3216 | struct FunctionReference { |
3217 | WRAPPER_CLASS_BOILERPLATE(FunctionReference, Call); |
3218 | CharBlock source; |
3219 | Designator ConvertToArrayElementRef(); |
3220 | StructureConstructor ConvertToStructureConstructor( |
3221 | const semantics::DerivedTypeSpec &); |
3222 | }; |
3223 | |
3224 | // R1521 call-stmt -> CALL procedure-designator [ chevrons ] |
3225 | // [( [actual-arg-spec-list] )] |
3226 | // (CUDA) chevrons -> <<< scalar-expr, scalar-expr [, |
3227 | // scalar-int-expr [, scalar-int-expr ] ] >>> |
3228 | struct CallStmt { |
3229 | BOILERPLATE(CallStmt); |
3230 | struct Chevrons { |
3231 | TUPLE_CLASS_BOILERPLATE(Chevrons); |
3232 | std::tuple<ScalarExpr, ScalarExpr, std::optional<ScalarIntExpr>, |
3233 | std::optional<ScalarIntExpr>> |
3234 | t; |
3235 | }; |
3236 | explicit CallStmt(ProcedureDesignator &&pd, std::optional<Chevrons> &&ch, |
3237 | std::list<ActualArgSpec> &&args) |
3238 | : call{std::move(pd), std::move(args)}, chevrons{std::move(ch)} {} |
3239 | Call call; |
3240 | std::optional<Chevrons> chevrons; |
3241 | CharBlock source; |
3242 | mutable common::ForwardOwningPointer<evaluate::ProcedureRef> |
3243 | typedCall; // filled by semantics |
3244 | }; |
3245 | |
3246 | // R1529 function-subprogram -> |
3247 | // function-stmt [specification-part] [execution-part] |
3248 | // [internal-subprogram-part] end-function-stmt |
3249 | struct FunctionSubprogram { |
3250 | TUPLE_CLASS_BOILERPLATE(FunctionSubprogram); |
3251 | std::tuple<Statement<FunctionStmt>, SpecificationPart, ExecutionPart, |
3252 | std::optional<InternalSubprogramPart>, Statement<EndFunctionStmt>> |
3253 | t; |
3254 | }; |
3255 | |
3256 | // R1534 subroutine-subprogram -> |
3257 | // subroutine-stmt [specification-part] [execution-part] |
3258 | // [internal-subprogram-part] end-subroutine-stmt |
3259 | struct SubroutineSubprogram { |
3260 | TUPLE_CLASS_BOILERPLATE(SubroutineSubprogram); |
3261 | std::tuple<Statement<SubroutineStmt>, SpecificationPart, ExecutionPart, |
3262 | std::optional<InternalSubprogramPart>, Statement<EndSubroutineStmt>> |
3263 | t; |
3264 | }; |
3265 | |
3266 | // R1539 mp-subprogram-stmt -> MODULE PROCEDURE procedure-name |
3267 | WRAPPER_CLASS(MpSubprogramStmt, Name); |
3268 | |
3269 | // R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]] |
3270 | WRAPPER_CLASS(EndMpSubprogramStmt, std::optional<Name>); |
3271 | |
3272 | // R1538 separate-module-subprogram -> |
3273 | // mp-subprogram-stmt [specification-part] [execution-part] |
3274 | // [internal-subprogram-part] end-mp-subprogram-stmt |
3275 | struct SeparateModuleSubprogram { |
3276 | TUPLE_CLASS_BOILERPLATE(SeparateModuleSubprogram); |
3277 | std::tuple<Statement<MpSubprogramStmt>, SpecificationPart, ExecutionPart, |
3278 | std::optional<InternalSubprogramPart>, Statement<EndMpSubprogramStmt>> |
3279 | t; |
3280 | }; |
3281 | |
3282 | // R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]] |
3283 | struct EntryStmt { |
3284 | TUPLE_CLASS_BOILERPLATE(EntryStmt); |
3285 | std::tuple<Name, std::list<DummyArg>, std::optional<Suffix>> t; |
3286 | }; |
3287 | |
3288 | // R1542 return-stmt -> RETURN [scalar-int-expr] |
3289 | WRAPPER_CLASS(ReturnStmt, std::optional<ScalarIntExpr>); |
3290 | |
3291 | // R1544 stmt-function-stmt -> |
3292 | // function-name ( [dummy-arg-name-list] ) = scalar-expr |
3293 | struct StmtFunctionStmt { |
3294 | TUPLE_CLASS_BOILERPLATE(StmtFunctionStmt); |
3295 | std::tuple<Name, std::list<Name>, Scalar<Expr>> t; |
3296 | Statement<ActionStmt> ConvertToAssignment(); |
3297 | }; |
3298 | |
3299 | // Compiler directives |
3300 | // !DIR$ IGNORE_TKR [ [(tkrdmac...)] name ]... |
3301 | // !DIR$ LOOP COUNT (n1[, n2]...) |
3302 | // !DIR$ name[=value] [, name[=value]]... = can be : |
3303 | // !DIR$ <anything else> |
3304 | struct CompilerDirective { |
3305 | UNION_CLASS_BOILERPLATE(CompilerDirective); |
3306 | struct IgnoreTKR { |
3307 | TUPLE_CLASS_BOILERPLATE(IgnoreTKR); |
3308 | std::tuple<std::optional<std::list<const char *>>, Name> t; |
3309 | }; |
3310 | struct LoopCount { |
3311 | WRAPPER_CLASS_BOILERPLATE(LoopCount, std::list<std::uint64_t>); |
3312 | }; |
3313 | struct AssumeAligned { |
3314 | TUPLE_CLASS_BOILERPLATE(AssumeAligned); |
3315 | std::tuple<common::Indirection<Designator>, uint64_t> t; |
3316 | }; |
3317 | struct NameValue { |
3318 | TUPLE_CLASS_BOILERPLATE(NameValue); |
3319 | std::tuple<Name, std::optional<std::uint64_t>> t; |
3320 | }; |
3321 | EMPTY_CLASS(Unrecognized); |
3322 | CharBlock source; |
3323 | std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>, |
3324 | std::list<NameValue>, Unrecognized> |
3325 | u; |
3326 | }; |
3327 | |
3328 | // (CUDA) ATTRIBUTE(attribute) [::] name-list |
3329 | struct CUDAAttributesStmt { |
3330 | TUPLE_CLASS_BOILERPLATE(CUDAAttributesStmt); |
3331 | std::tuple<common::CUDADataAttr, std::list<Name>> t; |
3332 | }; |
3333 | |
3334 | // Legacy extensions |
3335 | struct BasedPointer { |
3336 | TUPLE_CLASS_BOILERPLATE(BasedPointer); |
3337 | std::tuple<ObjectName, ObjectName, std::optional<ArraySpec>> t; |
3338 | }; |
3339 | WRAPPER_CLASS(BasedPointerStmt, std::list<BasedPointer>); |
3340 | |
3341 | struct Union; |
3342 | struct StructureDef; |
3343 | |
3344 | struct StructureField { |
3345 | UNION_CLASS_BOILERPLATE(StructureField); |
3346 | std::variant<Statement<DataComponentDefStmt>, |
3347 | common::Indirection<StructureDef>, common::Indirection<Union>> |
3348 | u; |
3349 | }; |
3350 | |
3351 | struct Map { |
3352 | EMPTY_CLASS(MapStmt); |
3353 | EMPTY_CLASS(EndMapStmt); |
3354 | TUPLE_CLASS_BOILERPLATE(Map); |
3355 | std::tuple<Statement<MapStmt>, std::list<StructureField>, |
3356 | Statement<EndMapStmt>> |
3357 | t; |
3358 | }; |
3359 | |
3360 | struct Union { |
3361 | EMPTY_CLASS(UnionStmt); |
3362 | EMPTY_CLASS(EndUnionStmt); |
3363 | TUPLE_CLASS_BOILERPLATE(Union); |
3364 | std::tuple<Statement<UnionStmt>, std::list<Map>, Statement<EndUnionStmt>> t; |
3365 | }; |
3366 | |
3367 | struct StructureStmt { |
3368 | TUPLE_CLASS_BOILERPLATE(StructureStmt); |
3369 | std::tuple<std::optional<Name>, std::list<EntityDecl>> t; |
3370 | }; |
3371 | |
3372 | struct StructureDef { |
3373 | EMPTY_CLASS(EndStructureStmt); |
3374 | TUPLE_CLASS_BOILERPLATE(StructureDef); |
3375 | std::tuple<Statement<StructureStmt>, std::list<StructureField>, |
3376 | Statement<EndStructureStmt>> |
3377 | t; |
3378 | }; |
3379 | |
3380 | // Old style PARAMETER statement without parentheses. |
3381 | // Types are determined entirely from the right-hand sides, not the names. |
3382 | WRAPPER_CLASS(OldParameterStmt, std::list<NamedConstantDef>); |
3383 | |
3384 | // Deprecations |
3385 | struct ArithmeticIfStmt { |
3386 | TUPLE_CLASS_BOILERPLATE(ArithmeticIfStmt); |
3387 | std::tuple<Expr, Label, Label, Label> t; |
3388 | }; |
3389 | |
3390 | struct AssignStmt { |
3391 | TUPLE_CLASS_BOILERPLATE(AssignStmt); |
3392 | std::tuple<Label, Name> t; |
3393 | }; |
3394 | |
3395 | struct AssignedGotoStmt { |
3396 | TUPLE_CLASS_BOILERPLATE(AssignedGotoStmt); |
3397 | std::tuple<Name, std::list<Label>> t; |
3398 | }; |
3399 | |
3400 | WRAPPER_CLASS(PauseStmt, std::optional<StopCode>); |
3401 | |
3402 | // Parse tree nodes for OpenMP 4.5 directives and clauses |
3403 | |
3404 | // 2.5 proc-bind-clause -> PROC_BIND (MASTER | CLOSE | SPREAD) |
3405 | struct OmpProcBindClause { |
3406 | ENUM_CLASS(Type, Close, Master, Spread, Primary) |
3407 | WRAPPER_CLASS_BOILERPLATE(OmpProcBindClause, Type); |
3408 | }; |
3409 | |
3410 | // 2.15.3.1 default-clause -> DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE) |
3411 | struct OmpDefaultClause { |
3412 | ENUM_CLASS(Type, Private, Firstprivate, Shared, None) |
3413 | WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, Type); |
3414 | }; |
3415 | |
3416 | // 2.1 Directives or clauses may accept a list or extended-list. |
3417 | // A list item is a variable, array section or common block name (enclosed |
3418 | // in slashes). An extended list item is a list item or a procedure Name. |
3419 | // variable-name | / common-block / | array-sections |
3420 | struct OmpObject { |
3421 | UNION_CLASS_BOILERPLATE(OmpObject); |
3422 | std::variant<Designator, /*common block*/ Name> u; |
3423 | }; |
3424 | |
3425 | WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>); |
3426 | |
3427 | // 2.15.5.1 map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE |
3428 | struct OmpMapType { |
3429 | TUPLE_CLASS_BOILERPLATE(OmpMapType); |
3430 | EMPTY_CLASS(Always); |
3431 | ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete) |
3432 | std::tuple<std::optional<Always>, Type> t; |
3433 | }; |
3434 | |
3435 | // 2.15.5.1 map -> MAP ([ [ALWAYS[,]] map-type : ] variable-name-list) |
3436 | struct OmpMapClause { |
3437 | TUPLE_CLASS_BOILERPLATE(OmpMapClause); |
3438 | std::tuple<std::optional<OmpMapType>, OmpObjectList> t; |
3439 | }; |
3440 | |
3441 | // 2.15.5.2 defaultmap -> DEFAULTMAP (implicit-behavior[:variable-category]) |
3442 | struct OmpDefaultmapClause { |
3443 | TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause); |
3444 | ENUM_CLASS( |
3445 | ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default) |
3446 | ENUM_CLASS(VariableCategory, Scalar, Aggregate, Allocatable, Pointer) |
3447 | std::tuple<ImplicitBehavior, std::optional<VariableCategory>> t; |
3448 | }; |
3449 | |
3450 | // 2.7.1 sched-modifier -> MONOTONIC | NONMONOTONIC | SIMD |
3451 | struct OmpScheduleModifierType { |
3452 | ENUM_CLASS(ModType, Monotonic, Nonmonotonic, Simd) |
3453 | WRAPPER_CLASS_BOILERPLATE(OmpScheduleModifierType, ModType); |
3454 | }; |
3455 | |
3456 | struct OmpScheduleModifier { |
3457 | TUPLE_CLASS_BOILERPLATE(OmpScheduleModifier); |
3458 | WRAPPER_CLASS(Modifier1, OmpScheduleModifierType); |
3459 | WRAPPER_CLASS(Modifier2, OmpScheduleModifierType); |
3460 | std::tuple<Modifier1, std::optional<Modifier2>> t; |
3461 | }; |
3462 | |
3463 | // 2.7.1 schedule-clause -> SCHEDULE ([sched-modifier1] [, sched-modifier2]:] |
3464 | // kind[, chunk_size]) |
3465 | struct OmpScheduleClause { |
3466 | TUPLE_CLASS_BOILERPLATE(OmpScheduleClause); |
3467 | ENUM_CLASS(ScheduleType, Static, Dynamic, Guided, Auto, Runtime) |
3468 | std::tuple<std::optional<OmpScheduleModifier>, ScheduleType, |
3469 | std::optional<ScalarIntExpr>> |
3470 | t; |
3471 | }; |
3472 | |
3473 | // device([ device-modifier :] scalar-integer-expression) |
3474 | struct OmpDeviceClause { |
3475 | TUPLE_CLASS_BOILERPLATE(OmpDeviceClause); |
3476 | ENUM_CLASS(DeviceModifier, Ancestor, Device_Num) |
3477 | std::tuple<std::optional<DeviceModifier>, ScalarIntExpr> t; |
3478 | }; |
3479 | |
3480 | // device_type(any | host | nohost) |
3481 | struct OmpDeviceTypeClause { |
3482 | ENUM_CLASS(Type, Any, Host, Nohost) |
3483 | WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, Type); |
3484 | }; |
3485 | |
3486 | // 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr) |
3487 | struct OmpIfClause { |
3488 | TUPLE_CLASS_BOILERPLATE(OmpIfClause); |
3489 | ENUM_CLASS(DirectiveNameModifier, Parallel, Simd, Target, TargetData, |
3490 | TargetEnterData, TargetExitData, TargetUpdate, Task, Taskloop, Teams) |
3491 | std::tuple<std::optional<DirectiveNameModifier>, ScalarLogicalExpr> t; |
3492 | }; |
3493 | |
3494 | // 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant]) |
3495 | struct OmpAlignedClause { |
3496 | TUPLE_CLASS_BOILERPLATE(OmpAlignedClause); |
3497 | CharBlock source; |
3498 | std::tuple<OmpObjectList, std::optional<ScalarIntConstantExpr>> t; |
3499 | }; |
3500 | |
3501 | // 2.9.5 order-clause -> ORDER ([order-modifier :]concurrent) |
3502 | struct OmpOrderModifier { |
3503 | UNION_CLASS_BOILERPLATE(OmpOrderModifier); |
3504 | ENUM_CLASS(Kind, Reproducible, Unconstrained) |
3505 | std::variant<Kind> u; |
3506 | }; |
3507 | |
3508 | struct OmpOrderClause { |
3509 | TUPLE_CLASS_BOILERPLATE(OmpOrderClause); |
3510 | ENUM_CLASS(Type, Concurrent) |
3511 | std::tuple<std::optional<OmpOrderModifier>, Type> t; |
3512 | }; |
3513 | |
3514 | // 2.15.3.7 linear-modifier -> REF | VAL | UVAL |
3515 | struct OmpLinearModifier { |
3516 | ENUM_CLASS(Type, Ref, Val, Uval) |
3517 | WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type); |
3518 | }; |
3519 | |
3520 | // 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step]) |
3521 | // linear-list -> list | linear-modifier(list) |
3522 | struct OmpLinearClause { |
3523 | UNION_CLASS_BOILERPLATE(OmpLinearClause); |
3524 | struct WithModifier { |
3525 | BOILERPLATE(WithModifier); |
3526 | WithModifier(OmpLinearModifier &&m, std::list<Name> &&n, |
3527 | std::optional<ScalarIntConstantExpr> &&s) |
3528 | : modifier(std::move(m)), names(std::move(n)), step(std::move(s)) {} |
3529 | OmpLinearModifier modifier; |
3530 | std::list<Name> names; |
3531 | std::optional<ScalarIntConstantExpr> step; |
3532 | }; |
3533 | struct WithoutModifier { |
3534 | BOILERPLATE(WithoutModifier); |
3535 | WithoutModifier( |
3536 | std::list<Name> &&n, std::optional<ScalarIntConstantExpr> &&s) |
3537 | : names(std::move(n)), step(std::move(s)) {} |
3538 | std::list<Name> names; |
3539 | std::optional<ScalarIntConstantExpr> step; |
3540 | }; |
3541 | std::variant<WithModifier, WithoutModifier> u; |
3542 | }; |
3543 | |
3544 | // 2.15.3.6 reduction-identifier -> + | - | * | .AND. | .OR. | .EQV. | .NEQV. | |
3545 | // MAX | MIN | IAND | IOR | IEOR |
3546 | struct OmpReductionOperator { |
3547 | UNION_CLASS_BOILERPLATE(OmpReductionOperator); |
3548 | std::variant<DefinedOperator, ProcedureDesignator> u; |
3549 | }; |
3550 | |
3551 | // 2.15.3.6 reduction-clause -> REDUCTION (reduction-identifier: |
3552 | // variable-name-list) |
3553 | struct OmpReductionClause { |
3554 | TUPLE_CLASS_BOILERPLATE(OmpReductionClause); |
3555 | ENUM_CLASS(ReductionModifier, Inscan, Task, Default) |
3556 | std::tuple<std::optional<ReductionModifier>, OmpReductionOperator, |
3557 | OmpObjectList> |
3558 | t; |
3559 | }; |
3560 | |
3561 | // OMP 5.0 2.19.5.6 in_reduction-clause -> IN_REDUCTION (reduction-identifier: |
3562 | // variable-name-list) |
3563 | struct OmpInReductionClause { |
3564 | TUPLE_CLASS_BOILERPLATE(OmpInReductionClause); |
3565 | std::tuple<OmpReductionOperator, OmpObjectList> t; |
3566 | }; |
3567 | |
3568 | // OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list) |
3569 | // OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier [, |
3570 | // allocate-modifier] :] |
3571 | // variable-name-list) |
3572 | // allocate-modifier -> allocator | align |
3573 | struct OmpAllocateClause { |
3574 | struct AllocateModifier { |
3575 | WRAPPER_CLASS(Allocator, ScalarIntExpr); |
3576 | WRAPPER_CLASS(Align, ScalarIntExpr); |
3577 | struct ComplexModifier { |
3578 | TUPLE_CLASS_BOILERPLATE(ComplexModifier); |
3579 | std::tuple<Allocator, Align> t; |
3580 | }; |
3581 | UNION_CLASS_BOILERPLATE(AllocateModifier); |
3582 | std::variant<Allocator, ComplexModifier, Align> u; |
3583 | }; |
3584 | TUPLE_CLASS_BOILERPLATE(OmpAllocateClause); |
3585 | std::tuple<std::optional<AllocateModifier>, OmpObjectList> t; |
3586 | }; |
3587 | |
3588 | // 2.13.9 depend-vec-length -> +/- non-negative-constant |
3589 | struct OmpDependSinkVecLength { |
3590 | TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength); |
3591 | std::tuple<DefinedOperator, ScalarIntConstantExpr> t; |
3592 | }; |
3593 | |
3594 | // 2.13.9 depend-vec -> iterator [+/- depend-vec-length],...,iterator[...] |
3595 | struct OmpDependSinkVec { |
3596 | TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec); |
3597 | std::tuple<Name, std::optional<OmpDependSinkVecLength>> t; |
3598 | }; |
3599 | |
3600 | // 2.13.9 depend-type -> IN | OUT | INOUT | SOURCE | SINK |
3601 | struct OmpDependenceType { |
3602 | ENUM_CLASS(Type, In, Out, Inout, Source, Sink) |
3603 | WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type); |
3604 | }; |
3605 | |
3606 | // 2.13.9 depend-clause -> DEPEND (((IN | OUT | INOUT) : variable-name-list) | |
3607 | // SOURCE | SINK : depend-vec) |
3608 | struct OmpDependClause { |
3609 | UNION_CLASS_BOILERPLATE(OmpDependClause); |
3610 | EMPTY_CLASS(Source); |
3611 | WRAPPER_CLASS(Sink, std::list<OmpDependSinkVec>); |
3612 | struct InOut { |
3613 | TUPLE_CLASS_BOILERPLATE(InOut); |
3614 | std::tuple<OmpDependenceType, std::list<Designator>> t; |
3615 | }; |
3616 | std::variant<Source, Sink, InOut> u; |
3617 | }; |
3618 | |
3619 | // OMP 5.0 2.4 atomic-default-mem-order-clause -> |
3620 | // ATOMIC_DEFAULT_MEM_ORDER (SEQ_CST | ACQ_REL | |
3621 | // RELAXED) |
3622 | struct OmpAtomicDefaultMemOrderClause { |
3623 | WRAPPER_CLASS_BOILERPLATE( |
3624 | OmpAtomicDefaultMemOrderClause, common::OmpAtomicDefaultMemOrderType); |
3625 | }; |
3626 | |
3627 | // OpenMP Clauses |
3628 | struct OmpClause { |
3629 | UNION_CLASS_BOILERPLATE(OmpClause); |
3630 | |
3631 | #define GEN_FLANG_CLAUSE_PARSER_CLASSES |
3632 | #include "llvm/Frontend/OpenMP/OMP.inc" |
3633 | |
3634 | CharBlock source; |
3635 | |
3636 | std::variant< |
3637 | #define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST |
3638 | #include "llvm/Frontend/OpenMP/OMP.inc" |
3639 | > |
3640 | u; |
3641 | }; |
3642 | |
3643 | struct OmpClauseList { |
3644 | WRAPPER_CLASS_BOILERPLATE(OmpClauseList, std::list<OmpClause>); |
3645 | CharBlock source; |
3646 | }; |
3647 | |
3648 | // 2.7.2 SECTIONS |
3649 | // 2.11.2 PARALLEL SECTIONS |
3650 | struct OmpSectionsDirective { |
3651 | WRAPPER_CLASS_BOILERPLATE(OmpSectionsDirective, llvm::omp::Directive); |
3652 | CharBlock source; |
3653 | }; |
3654 | |
3655 | struct OmpBeginSectionsDirective { |
3656 | TUPLE_CLASS_BOILERPLATE(OmpBeginSectionsDirective); |
3657 | std::tuple<OmpSectionsDirective, OmpClauseList> t; |
3658 | CharBlock source; |
3659 | }; |
3660 | struct OmpEndSectionsDirective { |
3661 | TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective); |
3662 | std::tuple<OmpSectionsDirective, OmpClauseList> t; |
3663 | CharBlock source; |
3664 | }; |
3665 | |
3666 | // [!$omp section] |
3667 | // structured-block |
3668 | // [!$omp section |
3669 | // structured-block] |
3670 | // ... |
3671 | struct OpenMPSectionConstruct { |
3672 | WRAPPER_CLASS_BOILERPLATE(OpenMPSectionConstruct, Block); |
3673 | CharBlock source; |
3674 | }; |
3675 | |
3676 | // `OmpSectionBlocks` is a list of section constructs. The parser guarentees |
3677 | // that the `OpenMPConstruct` here always encapsulates an |
3678 | // `OpenMPSectionConstruct` and not any other OpenMP construct. |
3679 | WRAPPER_CLASS(OmpSectionBlocks, std::list<OpenMPConstruct>); |
3680 | |
3681 | struct OpenMPSectionsConstruct { |
3682 | TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct); |
3683 | std::tuple<OmpBeginSectionsDirective, OmpSectionBlocks, |
3684 | OmpEndSectionsDirective> |
3685 | t; |
3686 | }; |
3687 | |
3688 | // OpenMP directive beginning or ending a block |
3689 | struct OmpBlockDirective { |
3690 | WRAPPER_CLASS_BOILERPLATE(OmpBlockDirective, llvm::omp::Directive); |
3691 | CharBlock source; |
3692 | }; |
3693 | |
3694 | // 2.10.6 declare-target -> DECLARE TARGET (extended-list) | |
3695 | // DECLARE TARGET [declare-target-clause[ [,] |
3696 | // declare-target-clause]...] |
3697 | struct OmpDeclareTargetWithList { |
3698 | WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetWithList, OmpObjectList); |
3699 | CharBlock source; |
3700 | }; |
3701 | |
3702 | struct OmpDeclareTargetWithClause { |
3703 | WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetWithClause, OmpClauseList); |
3704 | CharBlock source; |
3705 | }; |
3706 | |
3707 | struct OmpDeclareTargetSpecifier { |
3708 | UNION_CLASS_BOILERPLATE(OmpDeclareTargetSpecifier); |
3709 | std::variant<OmpDeclareTargetWithList, OmpDeclareTargetWithClause> u; |
3710 | }; |
3711 | |
3712 | struct OpenMPDeclareTargetConstruct { |
3713 | TUPLE_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct); |
3714 | CharBlock source; |
3715 | std::tuple<Verbatim, OmpDeclareTargetSpecifier> t; |
3716 | }; |
3717 | |
3718 | // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list |
3719 | // : combiner) [initializer-clause] |
3720 | struct OmpReductionCombiner { |
3721 | UNION_CLASS_BOILERPLATE(OmpReductionCombiner); |
3722 | WRAPPER_CLASS(FunctionCombiner, Call); |
3723 | std::variant<AssignmentStmt, FunctionCombiner> u; |
3724 | }; |
3725 | |
3726 | WRAPPER_CLASS(OmpReductionInitializerClause, Expr); |
3727 | |
3728 | struct OpenMPDeclareReductionConstruct { |
3729 | TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct); |
3730 | CharBlock source; |
3731 | std::tuple<Verbatim, OmpReductionOperator, std::list<DeclarationTypeSpec>, |
3732 | OmpReductionCombiner, std::optional<OmpReductionInitializerClause>> |
3733 | t; |
3734 | }; |
3735 | |
3736 | // 2.8.2 declare-simd -> DECLARE SIMD [(proc-name)] [declare-simd-clause[ [,] |
3737 | // declare-simd-clause]...] |
3738 | struct OpenMPDeclareSimdConstruct { |
3739 | TUPLE_CLASS_BOILERPLATE(OpenMPDeclareSimdConstruct); |
3740 | CharBlock source; |
3741 | std::tuple<Verbatim, std::optional<Name>, OmpClauseList> t; |
3742 | }; |
3743 | |
3744 | // 2.4 requires -> REQUIRES requires-clause[ [ [,] requires-clause]...] |
3745 | struct OpenMPRequiresConstruct { |
3746 | TUPLE_CLASS_BOILERPLATE(OpenMPRequiresConstruct); |
3747 | CharBlock source; |
3748 | std::tuple<Verbatim, OmpClauseList> t; |
3749 | }; |
3750 | |
3751 | // 2.15.2 threadprivate -> THREADPRIVATE (variable-name-list) |
3752 | struct OpenMPThreadprivate { |
3753 | TUPLE_CLASS_BOILERPLATE(OpenMPThreadprivate); |
3754 | CharBlock source; |
3755 | std::tuple<Verbatim, OmpObjectList> t; |
3756 | }; |
3757 | |
3758 | // 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause] |
3759 | struct OpenMPDeclarativeAllocate { |
3760 | TUPLE_CLASS_BOILERPLATE(OpenMPDeclarativeAllocate); |
3761 | CharBlock source; |
3762 | std::tuple<Verbatim, OmpObjectList, OmpClauseList> t; |
3763 | }; |
3764 | |
3765 | struct OpenMPDeclarativeConstruct { |
3766 | UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct); |
3767 | CharBlock source; |
3768 | std::variant<OpenMPDeclarativeAllocate, OpenMPDeclareReductionConstruct, |
3769 | OpenMPDeclareSimdConstruct, OpenMPDeclareTargetConstruct, |
3770 | OpenMPThreadprivate, OpenMPRequiresConstruct> |
3771 | u; |
3772 | }; |
3773 | |
3774 | // 2.13.2 CRITICAL [Name] <block> END CRITICAL [Name] |
3775 | struct OmpCriticalDirective { |
3776 | TUPLE_CLASS_BOILERPLATE(OmpCriticalDirective); |
3777 | CharBlock source; |
3778 | std::tuple<Verbatim, std::optional<Name>, OmpClauseList> t; |
3779 | }; |
3780 | struct OmpEndCriticalDirective { |
3781 | TUPLE_CLASS_BOILERPLATE(OmpEndCriticalDirective); |
3782 | CharBlock source; |
3783 | std::tuple<Verbatim, std::optional<Name>> t; |
3784 | }; |
3785 | struct OpenMPCriticalConstruct { |
3786 | TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct); |
3787 | std::tuple<OmpCriticalDirective, Block, OmpEndCriticalDirective> t; |
3788 | }; |
3789 | |
3790 | // 2.11.3 allocate -> ALLOCATE [(variable-name-list)] [clause] |
3791 | // [ALLOCATE (variable-name-list) [clause] [...]] |
3792 | // allocate-statement |
3793 | // clause -> allocator-clause |
3794 | struct OpenMPExecutableAllocate { |
3795 | TUPLE_CLASS_BOILERPLATE(OpenMPExecutableAllocate); |
3796 | CharBlock source; |
3797 | std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList, |
3798 | std::optional<std::list<OpenMPDeclarativeAllocate>>, |
3799 | Statement<AllocateStmt>> |
3800 | t; |
3801 | }; |
3802 | |
3803 | EMPTY_CLASS(OmpEndAllocators); |
3804 | |
3805 | // 6.7 Allocators construct [OpenMP 5.2] |
3806 | // allocators-construct -> ALLOCATORS [allocate-clause [,]] |
3807 | // allocate-stmt |
3808 | // [omp-end-allocators-construct] |
3809 | struct OpenMPAllocatorsConstruct { |
3810 | TUPLE_CLASS_BOILERPLATE(OpenMPAllocatorsConstruct); |
3811 | CharBlock source; |
3812 | std::tuple<Verbatim, OmpClauseList, Statement<AllocateStmt>, |
3813 | std::optional<OmpEndAllocators>> |
3814 | t; |
3815 | }; |
3816 | |
3817 | // 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0] |
3818 | // memory-order-clause -> acq_rel |
3819 | // release |
3820 | // acquire |
3821 | // seq_cst |
3822 | // relaxed |
3823 | struct OmpMemoryOrderClause { |
3824 | WRAPPER_CLASS_BOILERPLATE(OmpMemoryOrderClause, OmpClause); |
3825 | CharBlock source; |
3826 | }; |
3827 | |
3828 | // 2.17.7 Atomic construct |
3829 | // atomic-clause -> memory-order-clause | HINT(hint-expression) |
3830 | struct OmpAtomicClause { |
3831 | UNION_CLASS_BOILERPLATE(OmpAtomicClause); |
3832 | CharBlock source; |
3833 | std::variant<OmpMemoryOrderClause, OmpClause> u; |
3834 | }; |
3835 | |
3836 | // atomic-clause-list -> [atomic-clause, [atomic-clause], ...] |
3837 | struct OmpAtomicClauseList { |
3838 | WRAPPER_CLASS_BOILERPLATE(OmpAtomicClauseList, std::list<OmpAtomicClause>); |
3839 | CharBlock source; |
3840 | }; |
3841 | |
3842 | // END ATOMIC |
3843 | EMPTY_CLASS(OmpEndAtomic); |
3844 | |
3845 | // ATOMIC READ |
3846 | struct OmpAtomicRead { |
3847 | TUPLE_CLASS_BOILERPLATE(OmpAtomicRead); |
3848 | CharBlock source; |
3849 | std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList, |
3850 | Statement<AssignmentStmt>, std::optional<OmpEndAtomic>> |
3851 | t; |
3852 | }; |
3853 | |
3854 | // ATOMIC WRITE |
3855 | struct OmpAtomicWrite { |
3856 | TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite); |
3857 | CharBlock source; |
3858 | std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList, |
3859 | Statement<AssignmentStmt>, std::optional<OmpEndAtomic>> |
3860 | t; |
3861 | }; |
3862 | |
3863 | // ATOMIC UPDATE |
3864 | struct OmpAtomicUpdate { |
3865 | TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate); |
3866 | CharBlock source; |
3867 | std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList, |
3868 | Statement<AssignmentStmt>, std::optional<OmpEndAtomic>> |
3869 | t; |
3870 | }; |
3871 | |
3872 | // ATOMIC CAPTURE |
3873 | struct OmpAtomicCapture { |
3874 | TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture); |
3875 | CharBlock source; |
3876 | WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>); |
3877 | WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>); |
3878 | std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList, Stmt1, Stmt2, |
3879 | OmpEndAtomic> |
3880 | t; |
3881 | }; |
3882 | |
3883 | // ATOMIC |
3884 | struct OmpAtomic { |
3885 | TUPLE_CLASS_BOILERPLATE(OmpAtomic); |
3886 | CharBlock source; |
3887 | std::tuple<Verbatim, OmpAtomicClauseList, Statement<AssignmentStmt>, |
3888 | std::optional<OmpEndAtomic>> |
3889 | t; |
3890 | }; |
3891 | |
3892 | // 2.17.7 atomic -> |
3893 | // ATOMIC [atomic-clause-list] atomic-construct [atomic-clause-list] | |
3894 | // ATOMIC [atomic-clause-list] |
3895 | // atomic-construct -> READ | WRITE | UPDATE | CAPTURE |
3896 | struct OpenMPAtomicConstruct { |
3897 | UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct); |
3898 | std::variant<OmpAtomicRead, OmpAtomicWrite, OmpAtomicCapture, OmpAtomicUpdate, |
3899 | OmpAtomic> |
3900 | u; |
3901 | }; |
3902 | |
3903 | // OpenMP directives that associate with loop(s) |
3904 | struct OmpLoopDirective { |
3905 | WRAPPER_CLASS_BOILERPLATE(OmpLoopDirective, llvm::omp::Directive); |
3906 | CharBlock source; |
3907 | }; |
3908 | |
3909 | // 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP |
3910 | struct OmpCancelType { |
3911 | ENUM_CLASS(Type, Parallel, Sections, Do, Taskgroup) |
3912 | WRAPPER_CLASS_BOILERPLATE(OmpCancelType, Type); |
3913 | CharBlock source; |
3914 | }; |
3915 | |
3916 | // 2.14.2 cancellation-point -> CANCELLATION POINT construct-type-clause |
3917 | struct OpenMPCancellationPointConstruct { |
3918 | TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct); |
3919 | CharBlock source; |
3920 | std::tuple<Verbatim, OmpCancelType> t; |
3921 | }; |
3922 | |
3923 | // 2.14.1 cancel -> CANCEL construct-type-clause [ [,] if-clause] |
3924 | struct OpenMPCancelConstruct { |
3925 | TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct); |
3926 | WRAPPER_CLASS(If, ScalarLogicalExpr); |
3927 | CharBlock source; |
3928 | std::tuple<Verbatim, OmpCancelType, std::optional<If>> t; |
3929 | }; |
3930 | |
3931 | // 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)] |
3932 | struct OpenMPFlushConstruct { |
3933 | TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct); |
3934 | CharBlock source; |
3935 | std::tuple<Verbatim, std::optional<std::list<OmpMemoryOrderClause>>, |
3936 | std::optional<OmpObjectList>> |
3937 | t; |
3938 | }; |
3939 | |
3940 | struct OmpSimpleStandaloneDirective { |
3941 | WRAPPER_CLASS_BOILERPLATE(OmpSimpleStandaloneDirective, llvm::omp::Directive); |
3942 | CharBlock source; |
3943 | }; |
3944 | |
3945 | struct OpenMPSimpleStandaloneConstruct { |
3946 | TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct); |
3947 | CharBlock source; |
3948 | std::tuple<OmpSimpleStandaloneDirective, OmpClauseList> t; |
3949 | }; |
3950 | |
3951 | struct OpenMPStandaloneConstruct { |
3952 | UNION_CLASS_BOILERPLATE(OpenMPStandaloneConstruct); |
3953 | CharBlock source; |
3954 | std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct, |
3955 | OpenMPCancelConstruct, OpenMPCancellationPointConstruct> |
3956 | u; |
3957 | }; |
3958 | |
3959 | struct OmpBeginLoopDirective { |
3960 | TUPLE_CLASS_BOILERPLATE(OmpBeginLoopDirective); |
3961 | std::tuple<OmpLoopDirective, OmpClauseList> t; |
3962 | CharBlock source; |
3963 | }; |
3964 | |
3965 | struct OmpEndLoopDirective { |
3966 | TUPLE_CLASS_BOILERPLATE(OmpEndLoopDirective); |
3967 | std::tuple<OmpLoopDirective, OmpClauseList> t; |
3968 | CharBlock source; |
3969 | }; |
3970 | |
3971 | struct OmpBeginBlockDirective { |
3972 | TUPLE_CLASS_BOILERPLATE(OmpBeginBlockDirective); |
3973 | std::tuple<OmpBlockDirective, OmpClauseList> t; |
3974 | CharBlock source; |
3975 | }; |
3976 | |
3977 | struct OmpEndBlockDirective { |
3978 | TUPLE_CLASS_BOILERPLATE(OmpEndBlockDirective); |
3979 | std::tuple<OmpBlockDirective, OmpClauseList> t; |
3980 | CharBlock source; |
3981 | }; |
3982 | |
3983 | struct OpenMPBlockConstruct { |
3984 | TUPLE_CLASS_BOILERPLATE(OpenMPBlockConstruct); |
3985 | std::tuple<OmpBeginBlockDirective, Block, OmpEndBlockDirective> t; |
3986 | }; |
3987 | |
3988 | // OpenMP directives enclosing do loop |
3989 | struct OpenMPLoopConstruct { |
3990 | TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct); |
3991 | OpenMPLoopConstruct(OmpBeginLoopDirective &&a) |
3992 | : t({std::move(a), std::nullopt, std::nullopt}) {} |
3993 | std::tuple<OmpBeginLoopDirective, std::optional<DoConstruct>, |
3994 | std::optional<OmpEndLoopDirective>> |
3995 | t; |
3996 | }; |
3997 | |
3998 | struct OpenMPConstruct { |
3999 | UNION_CLASS_BOILERPLATE(OpenMPConstruct); |
4000 | std::variant<OpenMPStandaloneConstruct, OpenMPSectionsConstruct, |
4001 | OpenMPSectionConstruct, OpenMPLoopConstruct, OpenMPBlockConstruct, |
4002 | OpenMPAtomicConstruct, OpenMPDeclarativeAllocate, |
4003 | OpenMPExecutableAllocate, OpenMPAllocatorsConstruct, |
4004 | OpenMPCriticalConstruct> |
4005 | u; |
4006 | }; |
4007 | |
4008 | // Parse tree nodes for OpenACC 3.3 directives and clauses |
4009 | |
4010 | struct AccObject { |
4011 | UNION_CLASS_BOILERPLATE(AccObject); |
4012 | std::variant<Designator, /*common block*/ Name> u; |
4013 | }; |
4014 | |
4015 | WRAPPER_CLASS(AccObjectList, std::list<AccObject>); |
4016 | |
4017 | // OpenACC directive beginning or ending a block |
4018 | struct AccBlockDirective { |
4019 | WRAPPER_CLASS_BOILERPLATE(AccBlockDirective, llvm::acc::Directive); |
4020 | CharBlock source; |
4021 | }; |
4022 | |
4023 | struct AccLoopDirective { |
4024 | WRAPPER_CLASS_BOILERPLATE(AccLoopDirective, llvm::acc::Directive); |
4025 | CharBlock source; |
4026 | }; |
4027 | |
4028 | struct AccStandaloneDirective { |
4029 | WRAPPER_CLASS_BOILERPLATE(AccStandaloneDirective, llvm::acc::Directive); |
4030 | CharBlock source; |
4031 | }; |
4032 | |
4033 | // 2.11 Combined constructs |
4034 | struct AccCombinedDirective { |
4035 | WRAPPER_CLASS_BOILERPLATE(AccCombinedDirective, llvm::acc::Directive); |
4036 | CharBlock source; |
4037 | }; |
4038 | |
4039 | struct AccDeclarativeDirective { |
4040 | WRAPPER_CLASS_BOILERPLATE(AccDeclarativeDirective, llvm::acc::Directive); |
4041 | CharBlock source; |
4042 | }; |
4043 | |
4044 | // OpenACC Clauses |
4045 | struct AccBindClause { |
4046 | UNION_CLASS_BOILERPLATE(AccBindClause); |
4047 | std::variant<Name, ScalarDefaultCharExpr> u; |
4048 | CharBlock source; |
4049 | }; |
4050 | |
4051 | struct AccDefaultClause { |
4052 | WRAPPER_CLASS_BOILERPLATE(AccDefaultClause, llvm::acc::DefaultValue); |
4053 | CharBlock source; |
4054 | }; |
4055 | |
4056 | struct AccDataModifier { |
4057 | ENUM_CLASS(Modifier, ReadOnly, Zero) |
4058 | WRAPPER_CLASS_BOILERPLATE(AccDataModifier, Modifier); |
4059 | CharBlock source; |
4060 | }; |
4061 | |
4062 | struct AccObjectListWithModifier { |
4063 | TUPLE_CLASS_BOILERPLATE(AccObjectListWithModifier); |
4064 | std::tuple<std::optional<AccDataModifier>, AccObjectList> t; |
4065 | }; |
4066 | |
4067 | // 2.5.15: + | * | max | min | iand | ior | ieor | .and. | .or. | .eqv. | .neqv. |
4068 | struct AccReductionOperator { |
4069 | ENUM_CLASS( |
4070 | Operator, Plus, Multiply, Max, Min, Iand, Ior, Ieor, And, Or, Eqv, Neqv) |
4071 | WRAPPER_CLASS_BOILERPLATE(AccReductionOperator, Operator); |
4072 | CharBlock source; |
4073 | }; |
4074 | |
4075 | struct AccObjectListWithReduction { |
4076 | TUPLE_CLASS_BOILERPLATE(AccObjectListWithReduction); |
4077 | std::tuple<AccReductionOperator, AccObjectList> t; |
4078 | }; |
4079 | |
4080 | struct AccWaitArgument { |
4081 | TUPLE_CLASS_BOILERPLATE(AccWaitArgument); |
4082 | std::tuple<std::optional<ScalarIntExpr>, std::list<ScalarIntExpr>> t; |
4083 | }; |
4084 | |
4085 | struct AccDeviceTypeExpr { |
4086 | WRAPPER_CLASS_BOILERPLATE( |
4087 | AccDeviceTypeExpr, Fortran::common::OpenACCDeviceType); |
4088 | CharBlock source; |
4089 | }; |
4090 | |
4091 | struct AccDeviceTypeExprList { |
4092 | WRAPPER_CLASS_BOILERPLATE( |
4093 | AccDeviceTypeExprList, std::list<AccDeviceTypeExpr>); |
4094 | }; |
4095 | |
4096 | struct AccTileExpr { |
4097 | TUPLE_CLASS_BOILERPLATE(AccTileExpr); |
4098 | CharBlock source; |
4099 | std::tuple<std::optional<ScalarIntConstantExpr>> t; // if null then * |
4100 | }; |
4101 | |
4102 | struct AccTileExprList { |
4103 | WRAPPER_CLASS_BOILERPLATE(AccTileExprList, std::list<AccTileExpr>); |
4104 | }; |
4105 | |
4106 | struct AccSizeExpr { |
4107 | WRAPPER_CLASS_BOILERPLATE(AccSizeExpr, std::optional<ScalarIntExpr>); |
4108 | }; |
4109 | |
4110 | struct AccSizeExprList { |
4111 | WRAPPER_CLASS_BOILERPLATE(AccSizeExprList, std::list<AccSizeExpr>); |
4112 | }; |
4113 | |
4114 | struct AccSelfClause { |
4115 | UNION_CLASS_BOILERPLATE(AccSelfClause); |
4116 | std::variant<std::optional<ScalarLogicalExpr>, AccObjectList> u; |
4117 | CharBlock source; |
4118 | }; |
4119 | |
4120 | // num, dim, static |
4121 | struct AccGangArg { |
4122 | UNION_CLASS_BOILERPLATE(AccGangArg); |
4123 | WRAPPER_CLASS(Num, ScalarIntExpr); |
4124 | WRAPPER_CLASS(Dim, ScalarIntExpr); |
4125 | WRAPPER_CLASS(Static, AccSizeExpr); |
4126 | std::variant<Num, Dim, Static> u; |
4127 | CharBlock source; |
4128 | }; |
4129 | |
4130 | struct AccGangArgList { |
4131 | WRAPPER_CLASS_BOILERPLATE(AccGangArgList, std::list<AccGangArg>); |
4132 | }; |
4133 | |
4134 | struct AccCollapseArg { |
4135 | TUPLE_CLASS_BOILERPLATE(AccCollapseArg); |
4136 | std::tuple<bool, ScalarIntConstantExpr> t; |
4137 | }; |
4138 | |
4139 | struct AccClause { |
4140 | UNION_CLASS_BOILERPLATE(AccClause); |
4141 | |
4142 | #define GEN_FLANG_CLAUSE_PARSER_CLASSES |
4143 | #include "llvm/Frontend/OpenACC/ACC.inc" |
4144 | |
4145 | CharBlock source; |
4146 | |
4147 | std::variant< |
4148 | #define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST |
4149 | #include "llvm/Frontend/OpenACC/ACC.inc" |
4150 | > |
4151 | u; |
4152 | }; |
4153 | |
4154 | struct AccClauseList { |
4155 | WRAPPER_CLASS_BOILERPLATE(AccClauseList, std::list<AccClause>); |
4156 | CharBlock source; |
4157 | }; |
4158 | |
4159 | struct OpenACCRoutineConstruct { |
4160 | TUPLE_CLASS_BOILERPLATE(OpenACCRoutineConstruct); |
4161 | CharBlock source; |
4162 | std::tuple<Verbatim, std::optional<Name>, AccClauseList> t; |
4163 | }; |
4164 | |
4165 | struct OpenACCCacheConstruct { |
4166 | TUPLE_CLASS_BOILERPLATE(OpenACCCacheConstruct); |
4167 | CharBlock source; |
4168 | std::tuple<Verbatim, AccObjectListWithModifier> t; |
4169 | }; |
4170 | |
4171 | struct OpenACCWaitConstruct { |
4172 | TUPLE_CLASS_BOILERPLATE(OpenACCWaitConstruct); |
4173 | CharBlock source; |
4174 | std::tuple<Verbatim, std::optional<AccWaitArgument>, AccClauseList> t; |
4175 | }; |
4176 | |
4177 | struct AccBeginLoopDirective { |
4178 | TUPLE_CLASS_BOILERPLATE(AccBeginLoopDirective); |
4179 | std::tuple<AccLoopDirective, AccClauseList> t; |
4180 | CharBlock source; |
4181 | }; |
4182 | |
4183 | struct AccBeginBlockDirective { |
4184 | TUPLE_CLASS_BOILERPLATE(AccBeginBlockDirective); |
4185 | CharBlock source; |
4186 | std::tuple<AccBlockDirective, AccClauseList> t; |
4187 | }; |
4188 | |
4189 | struct AccEndBlockDirective { |
4190 | CharBlock source; |
4191 | WRAPPER_CLASS_BOILERPLATE(AccEndBlockDirective, AccBlockDirective); |
4192 | }; |
4193 | |
4194 | // ACC END ATOMIC |
4195 | EMPTY_CLASS(AccEndAtomic); |
4196 | |
4197 | // ACC ATOMIC READ |
4198 | struct AccAtomicRead { |
4199 | TUPLE_CLASS_BOILERPLATE(AccAtomicRead); |
4200 | std::tuple<Verbatim, Statement<AssignmentStmt>, std::optional<AccEndAtomic>> |
4201 | t; |
4202 | }; |
4203 | |
4204 | // ACC ATOMIC WRITE |
4205 | struct AccAtomicWrite { |
4206 | TUPLE_CLASS_BOILERPLATE(AccAtomicWrite); |
4207 | std::tuple<Verbatim, Statement<AssignmentStmt>, std::optional<AccEndAtomic>> |
4208 | t; |
4209 | }; |
4210 | |
4211 | // ACC ATOMIC UPDATE |
4212 | struct AccAtomicUpdate { |
4213 | TUPLE_CLASS_BOILERPLATE(AccAtomicUpdate); |
4214 | std::tuple<std::optional<Verbatim>, Statement<AssignmentStmt>, |
4215 | std::optional<AccEndAtomic>> |
4216 | t; |
4217 | }; |
4218 | |
4219 | // ACC ATOMIC CAPTURE |
4220 | struct AccAtomicCapture { |
4221 | TUPLE_CLASS_BOILERPLATE(AccAtomicCapture); |
4222 | WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>); |
4223 | WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>); |
4224 | std::tuple<Verbatim, Stmt1, Stmt2, AccEndAtomic> t; |
4225 | }; |
4226 | |
4227 | struct OpenACCAtomicConstruct { |
4228 | UNION_CLASS_BOILERPLATE(OpenACCAtomicConstruct); |
4229 | std::variant<AccAtomicRead, AccAtomicWrite, AccAtomicCapture, AccAtomicUpdate> |
4230 | u; |
4231 | CharBlock source; |
4232 | }; |
4233 | |
4234 | struct OpenACCBlockConstruct { |
4235 | TUPLE_CLASS_BOILERPLATE(OpenACCBlockConstruct); |
4236 | std::tuple<AccBeginBlockDirective, Block, AccEndBlockDirective> t; |
4237 | }; |
4238 | |
4239 | struct OpenACCStandaloneDeclarativeConstruct { |
4240 | TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneDeclarativeConstruct); |
4241 | CharBlock source; |
4242 | std::tuple<AccDeclarativeDirective, AccClauseList> t; |
4243 | }; |
4244 | |
4245 | struct AccBeginCombinedDirective { |
4246 | TUPLE_CLASS_BOILERPLATE(AccBeginCombinedDirective); |
4247 | CharBlock source; |
4248 | std::tuple<AccCombinedDirective, AccClauseList> t; |
4249 | }; |
4250 | |
4251 | struct AccEndCombinedDirective { |
4252 | WRAPPER_CLASS_BOILERPLATE(AccEndCombinedDirective, AccCombinedDirective); |
4253 | CharBlock source; |
4254 | }; |
4255 | |
4256 | struct OpenACCCombinedConstruct { |
4257 | TUPLE_CLASS_BOILERPLATE(OpenACCCombinedConstruct); |
4258 | CharBlock source; |
4259 | OpenACCCombinedConstruct(AccBeginCombinedDirective &&a) |
4260 | : t({std::move(a), std::nullopt, std::nullopt}) {} |
4261 | std::tuple<AccBeginCombinedDirective, std::optional<DoConstruct>, |
4262 | std::optional<AccEndCombinedDirective>> |
4263 | t; |
4264 | }; |
4265 | |
4266 | struct OpenACCDeclarativeConstruct { |
4267 | UNION_CLASS_BOILERPLATE(OpenACCDeclarativeConstruct); |
4268 | CharBlock source; |
4269 | std::variant<OpenACCStandaloneDeclarativeConstruct, OpenACCRoutineConstruct> |
4270 | u; |
4271 | }; |
4272 | |
4273 | // OpenACC directives enclosing do loop |
4274 | EMPTY_CLASS(AccEndLoop); |
4275 | struct OpenACCLoopConstruct { |
4276 | TUPLE_CLASS_BOILERPLATE(OpenACCLoopConstruct); |
4277 | OpenACCLoopConstruct(AccBeginLoopDirective &&a) |
4278 | : t({std::move(a), std::nullopt, std::nullopt}) {} |
4279 | std::tuple<AccBeginLoopDirective, std::optional<DoConstruct>, |
4280 | std::optional<AccEndLoop>> |
4281 | t; |
4282 | }; |
4283 | |
4284 | struct OpenACCEndConstruct { |
4285 | WRAPPER_CLASS_BOILERPLATE(OpenACCEndConstruct, llvm::acc::Directive); |
4286 | CharBlock source; |
4287 | }; |
4288 | |
4289 | struct OpenACCStandaloneConstruct { |
4290 | TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneConstruct); |
4291 | CharBlock source; |
4292 | std::tuple<AccStandaloneDirective, AccClauseList> t; |
4293 | }; |
4294 | |
4295 | struct OpenACCConstruct { |
4296 | UNION_CLASS_BOILERPLATE(OpenACCConstruct); |
4297 | std::variant<OpenACCBlockConstruct, OpenACCCombinedConstruct, |
4298 | OpenACCLoopConstruct, OpenACCStandaloneConstruct, OpenACCCacheConstruct, |
4299 | OpenACCWaitConstruct, OpenACCAtomicConstruct, OpenACCEndConstruct> |
4300 | u; |
4301 | }; |
4302 | |
4303 | // CUF-kernel-do-construct -> |
4304 | // !$CUF KERNEL DO [ (scalar-int-constant-expr) ] <<< grid, block [, stream] |
4305 | // >>> do-construct |
4306 | // star-or-expr -> * | scalar-int-expr |
4307 | // grid -> * | scalar-int-expr | ( star-or-expr-list ) |
4308 | // block -> * | scalar-int-expr | ( star-or-expr-list ) |
4309 | // stream -> 0, scalar-int-expr | STREAM = scalar-int-expr |
4310 | struct CUFKernelDoConstruct { |
4311 | TUPLE_CLASS_BOILERPLATE(CUFKernelDoConstruct); |
4312 | WRAPPER_CLASS(StarOrExpr, std::optional<ScalarIntExpr>); |
4313 | struct Directive { |
4314 | TUPLE_CLASS_BOILERPLATE(Directive); |
4315 | CharBlock source; |
4316 | std::tuple<std::optional<ScalarIntConstantExpr>, std::list<StarOrExpr>, |
4317 | std::list<StarOrExpr>, std::optional<ScalarIntExpr>> |
4318 | t; |
4319 | }; |
4320 | std::tuple<Directive, std::optional<DoConstruct>> t; |
4321 | }; |
4322 | |
4323 | } // namespace Fortran::parser |
4324 | #endif // FORTRAN_PARSER_PARSE_TREE_H_ |
4325 |
Warning: This file is not a C or C++ file. It does not have highlighting.