-
Notifications
You must be signed in to change notification settings - Fork 13.3k
/
Copy pathparse-tree.h
4623 lines (4044 loc) · 156 KB
/
parse-tree.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//===-- include/flang/Parser/parse-tree.h -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_PARSER_PARSE_TREE_H_
#define FORTRAN_PARSER_PARSE_TREE_H_
// Defines the classes used to represent successful reductions of productions
// in the Fortran grammar. The names and content of these definitions
// adhere closely to the syntax specifications in the language standard (q.v.)
// that are transcribed here and referenced via their requirement numbers.
// The representations of some productions that may also be of use in the
// run-time I/O support library have been isolated into a distinct header file
// (viz., format-specification.h).
#include "char-block.h"
#include "characters.h"
#include "format-specification.h"
#include "message.h"
#include "provenance.h"
#include "flang/Common/Fortran.h"
#include "flang/Common/idioms.h"
#include "flang/Common/indirection.h"
#include "llvm/Frontend/OpenACC/ACC.h.inc"
#include "llvm/Frontend/OpenMP/OMP.h"
#include "llvm/Frontend/OpenMP/OMPConstants.h"
#include <cinttypes>
#include <list>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
// Parse tree node class types do not have default constructors. They
// explicitly declare "T() {} = delete;" to make this clear. This restriction
// prevents the introduction of what would be a viral requirement to include
// std::monostate among most std::variant<> discriminated union members.
// Parse tree node class types do not have copy constructors or copy assignment
// operators. They are explicitly declared "= delete;" to make this clear,
// although a C++ compiler wouldn't default them anyway due to the presence
// of explicitly defaulted move constructors and move assignments.
CLASS_TRAIT(EmptyTrait)
CLASS_TRAIT(WrapperTrait)
CLASS_TRAIT(UnionTrait)
CLASS_TRAIT(TupleTrait)
CLASS_TRAIT(ConstraintTrait)
// Some parse tree nodes have fields in them to cache the results of a
// successful semantic analysis later. Their types are forward declared
// here.
namespace Fortran::semantics {
class Symbol;
class DeclTypeSpec;
class DerivedTypeSpec;
} // namespace Fortran::semantics
// Expressions in the parse tree have owning pointers that can be set to
// type-checked generic expression representations by semantic analysis.
namespace Fortran::evaluate {
struct GenericExprWrapper; // forward definition, wraps Expr<SomeType>
struct GenericAssignmentWrapper; // forward definition, represent assignment
class ProcedureRef; // forward definition, represents a CALL or function ref
} // namespace Fortran::evaluate
// Most non-template classes in this file use these default definitions
// for their move constructor and move assignment operator=, and disable
// their copy constructor and copy assignment operator=.
#define COPY_AND_ASSIGN_BOILERPLATE(classname) \
classname(classname &&) = default; \
classname &operator=(classname &&) = default; \
classname(const classname &) = delete; \
classname &operator=(const classname &) = delete
// Almost all classes in this file have no default constructor.
#define BOILERPLATE(classname) \
COPY_AND_ASSIGN_BOILERPLATE(classname); \
classname() = delete
// Empty classes are often used below as alternatives in std::variant<>
// discriminated unions.
#define EMPTY_CLASS(classname) \
struct classname { \
classname() {} \
classname(const classname &) {} \
classname(classname &&) {} \
classname &operator=(const classname &) { return *this; }; \
classname &operator=(classname &&) { return *this; }; \
using EmptyTrait = std::true_type; \
}
// Many classes below simply wrap a std::variant<> discriminated union,
// which is conventionally named "u".
#define UNION_CLASS_BOILERPLATE(classname) \
template <typename A, typename = common::NoLvalue<A>> \
classname(A &&x) : u(std::move(x)) {} \
using UnionTrait = std::true_type; \
BOILERPLATE(classname)
// Many other classes below simply wrap a std::tuple<> structure, which
// is conventionally named "t".
#define TUPLE_CLASS_BOILERPLATE(classname) \
template <typename... Ts, typename = common::NoLvalue<Ts...>> \
classname(Ts &&...args) : t(std::move(args)...) {} \
using TupleTrait = std::true_type; \
BOILERPLATE(classname)
// Many other classes below simply wrap a single data member, which is
// conventionally named "v".
#define WRAPPER_CLASS_BOILERPLATE(classname, type) \
BOILERPLATE(classname); \
classname(type &&x) : v(std::move(x)) {} \
using WrapperTrait = std::true_type; \
type v
#define WRAPPER_CLASS(classname, type) \
struct classname { \
WRAPPER_CLASS_BOILERPLATE(classname, type); \
}
namespace Fortran::parser {
// These are the unavoidable recursively-defined productions of Fortran.
// Some references to the representations of their parses require
// indirection. The Indirect<> pointer wrapper class is used to
// enforce ownership semantics and non-nullability.
struct SpecificationPart; // R504
struct ExecutableConstruct; // R514
struct ActionStmt; // R515
struct AcImpliedDo; // R774
struct DataImpliedDo; // R840
struct Designator; // R901
struct Variable; // R902
struct Expr; // R1001
struct WhereConstruct; // R1042
struct ForallConstruct; // R1050
struct InputImpliedDo; // R1218
struct OutputImpliedDo; // R1218
struct FunctionReference; // R1520
struct FunctionSubprogram; // R1529
struct SubroutineSubprogram; // R1534
// These additional forward references are declared so that the order of
// class definitions in this header file can remain reasonably consistent
// with order of the the requirement productions in the grammar.
struct DerivedTypeDef; // R726
struct EnumDef; // R759
struct TypeDeclarationStmt; // R801
struct AccessStmt; // R827
struct AllocatableStmt; // R829
struct AsynchronousStmt; // R831
struct BindStmt; // R832
struct CodimensionStmt; // R834
struct ContiguousStmt; // R836
struct DataStmt; // R837
struct DataStmtValue; // R843
struct DimensionStmt; // R848
struct IntentStmt; // R849
struct OptionalStmt; // R850
struct ParameterStmt; // R851
struct OldParameterStmt;
struct PointerStmt; // R853
struct ProtectedStmt; // R855
struct SaveStmt; // R856
struct TargetStmt; // R859
struct ValueStmt; // R861
struct VolatileStmt; // R862
struct ImplicitStmt; // R863
struct ImportStmt; // R867
struct NamelistStmt; // R868
struct EquivalenceStmt; // R870
struct CommonStmt; // R873
struct Substring; // R908
struct CharLiteralConstantSubstring;
struct SubstringInquiry;
struct DataRef; // R911
struct StructureComponent; // R913
struct CoindexedNamedObject; // R914
struct ArrayElement; // R917
struct AllocateStmt; // R927
struct NullifyStmt; // R939
struct DeallocateStmt; // R941
struct AssignmentStmt; // R1032
struct PointerAssignmentStmt; // R1033
struct WhereStmt; // R1041, R1045, R1046
struct ForallStmt; // R1055
struct AssociateConstruct; // R1102
struct BlockConstruct; // R1107
struct ChangeTeamConstruct; // R1111
struct CriticalConstruct; // R1116
struct DoConstruct; // R1119
struct LabelDoStmt; // R1121
struct ConcurrentHeader; // R1125
struct EndDoStmt; // R1132
struct CycleStmt; // R1133
struct IfConstruct; // R1134
struct IfStmt; // R1139
struct CaseConstruct; // R1140
struct SelectRankConstruct; // R1148
struct SelectTypeConstruct; // R1152
struct ExitStmt; // R1156
struct GotoStmt; // R1157
struct ComputedGotoStmt; // R1158
struct StopStmt; // R1160, R1161
struct NotifyWaitStmt; // F2023: R1166
struct SyncAllStmt; // R1164
struct SyncImagesStmt; // R1166
struct SyncMemoryStmt; // R1168
struct SyncTeamStmt; // R1169
struct EventPostStmt; // R1170, R1171
struct EventWaitSpec; // F2023: R1177
struct EventWaitStmt; // R1172, R1173, R1174
struct FormTeamStmt; // R1175, R1176, R1177
struct LockStmt; // R1178
struct UnlockStmt; // R1180
struct OpenStmt; // R1204
struct CloseStmt; // R1208
struct ReadStmt; // R1210
struct WriteStmt; // R1211
struct PrintStmt; // R1212
struct WaitStmt; // R1222
struct BackspaceStmt; // R1224
struct EndfileStmt; // R1225
struct RewindStmt; // R1226
struct FlushStmt; // R1228
struct InquireStmt; // R1230
struct FormatStmt; // R1301
struct MainProgram; // R1401
struct Module; // R1404
struct UseStmt; // R1409
struct Submodule; // R1416
struct BlockData; // R1420
struct InterfaceBlock; // R1501
struct GenericSpec; // R1508
struct GenericStmt; // R1510
struct ExternalStmt; // R1511
struct ProcedureDeclarationStmt; // R1512
struct IntrinsicStmt; // R1519
struct Call; // R1520 & R1521
struct CallStmt; // R1521
struct ProcedureDesignator; // R1522
struct ActualArg; // R1524
struct SeparateModuleSubprogram; // R1538
struct EntryStmt; // R1541
struct ReturnStmt; // R1542
struct StmtFunctionStmt; // R1544
// Directives, extensions, and deprecated statements
struct CompilerDirective;
struct BasedPointerStmt;
struct CUDAAttributesStmt;
struct StructureDef;
struct ArithmeticIfStmt;
struct AssignStmt;
struct AssignedGotoStmt;
struct PauseStmt;
struct OpenACCConstruct;
struct AccEndCombinedDirective;
struct OpenACCDeclarativeConstruct;
struct OpenACCRoutineConstruct;
struct OpenMPConstruct;
struct OpenMPDeclarativeConstruct;
struct OmpEndLoopDirective;
struct CUFKernelDoConstruct;
// Cooked character stream locations
using Location = const char *;
// A parse tree node with provenance only
struct Verbatim {
// Allow a no-arg constructor for Verbatim so parsers can return `RESULT{}`.
constexpr Verbatim() {}
COPY_AND_ASSIGN_BOILERPLATE(Verbatim);
using EmptyTrait = std::true_type;
CharBlock source;
};
// Implicit definitions of the Standard
// R403 scalar-xyz -> xyz
// These template class wrappers correspond to the Standard's modifiers
// scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz.
template <typename A> struct Scalar {
using ConstraintTrait = std::true_type;
Scalar(Scalar &&that) = default;
Scalar(A &&that) : thing(std::move(that)) {}
Scalar &operator=(Scalar &&) = default;
A thing;
};
template <typename A> struct Constant {
using ConstraintTrait = std::true_type;
Constant(Constant &&that) = default;
Constant(A &&that) : thing(std::move(that)) {}
Constant &operator=(Constant &&) = default;
A thing;
};
template <typename A> struct Integer {
using ConstraintTrait = std::true_type;
Integer(Integer &&that) = default;
Integer(A &&that) : thing(std::move(that)) {}
Integer &operator=(Integer &&) = default;
A thing;
};
template <typename A> struct Logical {
using ConstraintTrait = std::true_type;
Logical(Logical &&that) = default;
Logical(A &&that) : thing(std::move(that)) {}
Logical &operator=(Logical &&) = default;
A thing;
};
template <typename A> struct DefaultChar {
using ConstraintTrait = std::true_type;
DefaultChar(DefaultChar &&that) = default;
DefaultChar(A &&that) : thing(std::move(that)) {}
DefaultChar &operator=(DefaultChar &&) = default;
A thing;
};
using LogicalExpr = Logical<common::Indirection<Expr>>; // R1024
using DefaultCharExpr = DefaultChar<common::Indirection<Expr>>; // R1025
using IntExpr = Integer<common::Indirection<Expr>>; // R1026
using ConstantExpr = Constant<common::Indirection<Expr>>; // R1029
using IntConstantExpr = Integer<ConstantExpr>; // R1031
using ScalarLogicalExpr = Scalar<LogicalExpr>;
using ScalarIntExpr = Scalar<IntExpr>;
using ScalarIntConstantExpr = Scalar<IntConstantExpr>;
using ScalarDefaultCharExpr = Scalar<DefaultCharExpr>;
// R1030 default-char-constant-expr is used in the Standard only as part of
// scalar-default-char-constant-expr.
using ScalarDefaultCharConstantExpr = Scalar<DefaultChar<ConstantExpr>>;
// R611 label -> digit [digit]...
using Label = common::Label; // validated later, must be in [1..99999]
// A wrapper for xzy-stmt productions that are statements, so that
// source provenances and labels have a uniform representation.
template <typename A> struct UnlabeledStatement {
explicit UnlabeledStatement(A &&s) : statement(std::move(s)) {}
CharBlock source;
A statement;
};
template <typename A> struct Statement : public UnlabeledStatement<A> {
Statement(std::optional<long> &&lab, A &&s)
: UnlabeledStatement<A>{std::move(s)}, label(std::move(lab)) {}
std::optional<Label> label;
};
// Error recovery marker
EMPTY_CLASS(ErrorRecovery);
// R513 other-specification-stmt ->
// access-stmt | allocatable-stmt | asynchronous-stmt | bind-stmt |
// codimension-stmt | contiguous-stmt | dimension-stmt | external-stmt |
// intent-stmt | intrinsic-stmt | namelist-stmt | optional-stmt |
// pointer-stmt | protected-stmt | save-stmt | target-stmt |
// volatile-stmt | value-stmt | common-stmt | equivalence-stmt
// Extension: (Cray) based POINTER statement
// Extension: CUDA data attribute statement
struct OtherSpecificationStmt {
UNION_CLASS_BOILERPLATE(OtherSpecificationStmt);
std::variant<common::Indirection<AccessStmt>,
common::Indirection<AllocatableStmt>,
common::Indirection<AsynchronousStmt>, common::Indirection<BindStmt>,
common::Indirection<CodimensionStmt>, common::Indirection<ContiguousStmt>,
common::Indirection<DimensionStmt>, common::Indirection<ExternalStmt>,
common::Indirection<IntentStmt>, common::Indirection<IntrinsicStmt>,
common::Indirection<NamelistStmt>, common::Indirection<OptionalStmt>,
common::Indirection<PointerStmt>, common::Indirection<ProtectedStmt>,
common::Indirection<SaveStmt>, common::Indirection<TargetStmt>,
common::Indirection<ValueStmt>, common::Indirection<VolatileStmt>,
common::Indirection<CommonStmt>, common::Indirection<EquivalenceStmt>,
common::Indirection<BasedPointerStmt>,
common::Indirection<CUDAAttributesStmt>>
u;
};
// R508 specification-construct ->
// derived-type-def | enum-def | generic-stmt | interface-block |
// parameter-stmt | procedure-declaration-stmt |
// other-specification-stmt | type-declaration-stmt
struct SpecificationConstruct {
UNION_CLASS_BOILERPLATE(SpecificationConstruct);
std::variant<common::Indirection<DerivedTypeDef>,
common::Indirection<EnumDef>, Statement<common::Indirection<GenericStmt>>,
common::Indirection<InterfaceBlock>,
Statement<common::Indirection<ParameterStmt>>,
Statement<common::Indirection<OldParameterStmt>>,
Statement<common::Indirection<ProcedureDeclarationStmt>>,
Statement<OtherSpecificationStmt>,
Statement<common::Indirection<TypeDeclarationStmt>>,
common::Indirection<StructureDef>,
common::Indirection<OpenACCDeclarativeConstruct>,
common::Indirection<OpenMPDeclarativeConstruct>,
common::Indirection<CompilerDirective>>
u;
};
// R506 implicit-part-stmt ->
// implicit-stmt | parameter-stmt | format-stmt | entry-stmt
struct ImplicitPartStmt {
UNION_CLASS_BOILERPLATE(ImplicitPartStmt);
std::variant<Statement<common::Indirection<ImplicitStmt>>,
Statement<common::Indirection<ParameterStmt>>,
Statement<common::Indirection<OldParameterStmt>>,
Statement<common::Indirection<FormatStmt>>,
Statement<common::Indirection<EntryStmt>>,
common::Indirection<CompilerDirective>,
common::Indirection<OpenACCDeclarativeConstruct>>
u;
};
// R505 implicit-part -> [implicit-part-stmt]... implicit-stmt
WRAPPER_CLASS(ImplicitPart, std::list<ImplicitPartStmt>);
// R507 declaration-construct ->
// specification-construct | data-stmt | format-stmt |
// entry-stmt | stmt-function-stmt
struct DeclarationConstruct {
UNION_CLASS_BOILERPLATE(DeclarationConstruct);
std::variant<SpecificationConstruct, Statement<common::Indirection<DataStmt>>,
Statement<common::Indirection<FormatStmt>>,
Statement<common::Indirection<EntryStmt>>,
Statement<common::Indirection<StmtFunctionStmt>>, ErrorRecovery>
u;
};
// R504 specification-part -> [use-stmt]... [import-stmt]... [implicit-part]
// [declaration-construct]...
// PARAMETER, FORMAT, and ENTRY statements that appear before any other
// kind of declaration-construct will be parsed into the implicit-part,
// even if there are no IMPLICIT statements.
struct SpecificationPart {
TUPLE_CLASS_BOILERPLATE(SpecificationPart);
std::tuple<std::list<OpenACCDeclarativeConstruct>,
std::list<OpenMPDeclarativeConstruct>,
std::list<common::Indirection<CompilerDirective>>,
std::list<Statement<common::Indirection<UseStmt>>>,
std::list<Statement<common::Indirection<ImportStmt>>>, ImplicitPart,
std::list<DeclarationConstruct>>
t;
};
// R512 internal-subprogram -> function-subprogram | subroutine-subprogram
struct InternalSubprogram {
UNION_CLASS_BOILERPLATE(InternalSubprogram);
std::variant<common::Indirection<FunctionSubprogram>,
common::Indirection<SubroutineSubprogram>,
common::Indirection<CompilerDirective>>
u;
};
// R1543 contains-stmt -> CONTAINS
EMPTY_CLASS(ContainsStmt);
// R511 internal-subprogram-part -> contains-stmt [internal-subprogram]...
struct InternalSubprogramPart {
TUPLE_CLASS_BOILERPLATE(InternalSubprogramPart);
std::tuple<Statement<ContainsStmt>, std::list<InternalSubprogram>> t;
};
// R1159 continue-stmt -> CONTINUE
EMPTY_CLASS(ContinueStmt);
// R1163 fail-image-stmt -> FAIL IMAGE
EMPTY_CLASS(FailImageStmt);
// R515 action-stmt ->
// allocate-stmt | assignment-stmt | backspace-stmt | call-stmt |
// close-stmt | continue-stmt | cycle-stmt | deallocate-stmt |
// endfile-stmt | error-stop-stmt | event-post-stmt | event-wait-stmt |
// exit-stmt | fail-image-stmt | flush-stmt | form-team-stmt |
// goto-stmt | if-stmt | inquire-stmt | lock-stmt | notify-wait-stmt |
// nullify-stmt | open-stmt | pointer-assignment-stmt | print-stmt |
// read-stmt | return-stmt | rewind-stmt | stop-stmt | sync-all-stmt |
// sync-images-stmt | sync-memory-stmt | sync-team-stmt | unlock-stmt |
// wait-stmt | where-stmt | write-stmt | computed-goto-stmt | forall-stmt
struct ActionStmt {
UNION_CLASS_BOILERPLATE(ActionStmt);
std::variant<common::Indirection<AllocateStmt>,
common::Indirection<AssignmentStmt>, common::Indirection<BackspaceStmt>,
common::Indirection<CallStmt>, common::Indirection<CloseStmt>,
ContinueStmt, common::Indirection<CycleStmt>,
common::Indirection<DeallocateStmt>, common::Indirection<EndfileStmt>,
common::Indirection<EventPostStmt>, common::Indirection<EventWaitStmt>,
common::Indirection<ExitStmt>, FailImageStmt,
common::Indirection<FlushStmt>, common::Indirection<FormTeamStmt>,
common::Indirection<GotoStmt>, common::Indirection<IfStmt>,
common::Indirection<InquireStmt>, common::Indirection<LockStmt>,
common::Indirection<NotifyWaitStmt>, common::Indirection<NullifyStmt>,
common::Indirection<OpenStmt>, common::Indirection<PointerAssignmentStmt>,
common::Indirection<PrintStmt>, common::Indirection<ReadStmt>,
common::Indirection<ReturnStmt>, common::Indirection<RewindStmt>,
common::Indirection<StopStmt>, common::Indirection<SyncAllStmt>,
common::Indirection<SyncImagesStmt>, common::Indirection<SyncMemoryStmt>,
common::Indirection<SyncTeamStmt>, common::Indirection<UnlockStmt>,
common::Indirection<WaitStmt>, common::Indirection<WhereStmt>,
common::Indirection<WriteStmt>, common::Indirection<ComputedGotoStmt>,
common::Indirection<ForallStmt>, common::Indirection<ArithmeticIfStmt>,
common::Indirection<AssignStmt>, common::Indirection<AssignedGotoStmt>,
common::Indirection<PauseStmt>>
u;
};
// R514 executable-construct ->
// action-stmt | associate-construct | block-construct |
// case-construct | change-team-construct | critical-construct |
// do-construct | if-construct | select-rank-construct |
// select-type-construct | where-construct | forall-construct |
// (CUDA) CUF-kernel-do-construct
struct ExecutableConstruct {
UNION_CLASS_BOILERPLATE(ExecutableConstruct);
std::variant<Statement<ActionStmt>, common::Indirection<AssociateConstruct>,
common::Indirection<BlockConstruct>, common::Indirection<CaseConstruct>,
common::Indirection<ChangeTeamConstruct>,
common::Indirection<CriticalConstruct>,
Statement<common::Indirection<LabelDoStmt>>,
Statement<common::Indirection<EndDoStmt>>,
common::Indirection<DoConstruct>, common::Indirection<IfConstruct>,
common::Indirection<SelectRankConstruct>,
common::Indirection<SelectTypeConstruct>,
common::Indirection<WhereConstruct>, common::Indirection<ForallConstruct>,
common::Indirection<CompilerDirective>,
common::Indirection<OpenACCConstruct>,
common::Indirection<AccEndCombinedDirective>,
common::Indirection<OpenMPConstruct>,
common::Indirection<OmpEndLoopDirective>,
common::Indirection<CUFKernelDoConstruct>>
u;
};
// R510 execution-part-construct ->
// executable-construct | format-stmt | entry-stmt | data-stmt
// Extension (PGI/Intel): also accept NAMELIST in execution part
struct ExecutionPartConstruct {
UNION_CLASS_BOILERPLATE(ExecutionPartConstruct);
std::variant<ExecutableConstruct, Statement<common::Indirection<FormatStmt>>,
Statement<common::Indirection<EntryStmt>>,
Statement<common::Indirection<DataStmt>>,
Statement<common::Indirection<NamelistStmt>>, ErrorRecovery>
u;
};
// R509 execution-part -> executable-construct [execution-part-construct]...
// R1101 block -> [execution-part-construct]...
using Block = std::list<ExecutionPartConstruct>;
WRAPPER_CLASS(ExecutionPart, Block);
// R502 program-unit ->
// main-program | external-subprogram | module | submodule | block-data
// R503 external-subprogram -> function-subprogram | subroutine-subprogram
struct ProgramUnit {
UNION_CLASS_BOILERPLATE(ProgramUnit);
std::variant<common::Indirection<MainProgram>,
common::Indirection<FunctionSubprogram>,
common::Indirection<SubroutineSubprogram>, common::Indirection<Module>,
common::Indirection<Submodule>, common::Indirection<BlockData>,
common::Indirection<CompilerDirective>,
common::Indirection<OpenACCRoutineConstruct>>
u;
};
// R501 program -> program-unit [program-unit]...
// This is the top-level production.
WRAPPER_CLASS(Program, std::list<ProgramUnit>);
// R603 name -> letter [alphanumeric-character]...
struct Name {
std::string ToString() const { return source.ToString(); }
CharBlock source;
mutable semantics::Symbol *symbol{nullptr}; // filled in during semantics
};
// R516 keyword -> name
WRAPPER_CLASS(Keyword, Name);
// R606 named-constant -> name
WRAPPER_CLASS(NamedConstant, Name);
// R1003 defined-unary-op -> . letter [letter]... .
// R1023 defined-binary-op -> . letter [letter]... .
// R1414 local-defined-operator -> defined-unary-op | defined-binary-op
// R1415 use-defined-operator -> defined-unary-op | defined-binary-op
// The Name here is stored with the dots; e.g., .FOO.
WRAPPER_CLASS(DefinedOpName, Name);
// R608 intrinsic-operator ->
// ** | * | / | + | - | // | .LT. | .LE. | .EQ. | .NE. | .GE. | .GT. |
// .NOT. | .AND. | .OR. | .EQV. | .NEQV.
// R609 defined-operator ->
// defined-unary-op | defined-binary-op | extended-intrinsic-op
// R610 extended-intrinsic-op -> intrinsic-operator
struct DefinedOperator {
UNION_CLASS_BOILERPLATE(DefinedOperator);
ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add, Subtract, Concat,
LT, LE, EQ, NE, GE, GT, NOT, AND, OR, EQV, NEQV)
std::variant<DefinedOpName, IntrinsicOperator> u;
};
// R804 object-name -> name
using ObjectName = Name;
// R867 import-stmt ->
// IMPORT [[::] import-name-list] |
// IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL
struct ImportStmt {
BOILERPLATE(ImportStmt);
ImportStmt(common::ImportKind &&k) : kind{k} {}
ImportStmt(std::list<Name> &&n) : names(std::move(n)) {}
ImportStmt(common::ImportKind &&, std::list<Name> &&);
common::ImportKind kind{common::ImportKind::Default};
std::list<Name> names;
};
// R868 namelist-stmt ->
// NAMELIST / namelist-group-name / namelist-group-object-list
// [[,] / namelist-group-name / namelist-group-object-list]...
// R869 namelist-group-object -> variable-name
struct NamelistStmt {
struct Group {
TUPLE_CLASS_BOILERPLATE(Group);
std::tuple<Name, std::list<Name>> t;
};
WRAPPER_CLASS_BOILERPLATE(NamelistStmt, std::list<Group>);
};
// R701 type-param-value -> scalar-int-expr | * | :
EMPTY_CLASS(Star);
struct TypeParamValue {
UNION_CLASS_BOILERPLATE(TypeParamValue);
EMPTY_CLASS(Deferred); // :
std::variant<ScalarIntExpr, Star, Deferred> u;
};
// R706 kind-selector -> ( [KIND =] scalar-int-constant-expr )
// Legacy extension: kind-selector -> * digit-string
// N.B. These are not semantically identical in the case of COMPLEX.
struct KindSelector {
UNION_CLASS_BOILERPLATE(KindSelector);
WRAPPER_CLASS(StarSize, std::uint64_t);
std::variant<ScalarIntConstantExpr, StarSize> u;
};
// R705 integer-type-spec -> INTEGER [kind-selector]
WRAPPER_CLASS(IntegerTypeSpec, std::optional<KindSelector>);
// R723 char-length -> ( type-param-value ) | digit-string
struct CharLength {
UNION_CLASS_BOILERPLATE(CharLength);
std::variant<TypeParamValue, std::uint64_t> u;
};
// R722 length-selector -> ( [LEN =] type-param-value ) | * char-length [,]
struct LengthSelector {
UNION_CLASS_BOILERPLATE(LengthSelector);
std::variant<TypeParamValue, CharLength> u;
};
// R721 char-selector ->
// length-selector |
// ( LEN = type-param-value , KIND = scalar-int-constant-expr ) |
// ( type-param-value , [KIND =] scalar-int-constant-expr ) |
// ( KIND = scalar-int-constant-expr [, LEN = type-param-value] )
struct CharSelector {
UNION_CLASS_BOILERPLATE(CharSelector);
struct LengthAndKind {
BOILERPLATE(LengthAndKind);
LengthAndKind(std::optional<TypeParamValue> &&l, ScalarIntConstantExpr &&k)
: length(std::move(l)), kind(std::move(k)) {}
std::optional<TypeParamValue> length;
ScalarIntConstantExpr kind;
};
CharSelector(TypeParamValue &&l, ScalarIntConstantExpr &&k)
: u{LengthAndKind{std::make_optional(std::move(l)), std::move(k)}} {}
CharSelector(ScalarIntConstantExpr &&k, std::optional<TypeParamValue> &&l)
: u{LengthAndKind{std::move(l), std::move(k)}} {}
std::variant<LengthSelector, LengthAndKind> u;
};
// R704 intrinsic-type-spec ->
// integer-type-spec | REAL [kind-selector] | DOUBLE PRECISION |
// COMPLEX [kind-selector] | CHARACTER [char-selector] |
// LOGICAL [kind-selector]
// Extensions: DOUBLE COMPLEX
struct IntrinsicTypeSpec {
UNION_CLASS_BOILERPLATE(IntrinsicTypeSpec);
struct Real {
BOILERPLATE(Real);
Real(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
std::optional<KindSelector> kind;
};
EMPTY_CLASS(DoublePrecision);
struct Complex {
BOILERPLATE(Complex);
Complex(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
std::optional<KindSelector> kind;
};
struct Character {
BOILERPLATE(Character);
Character(std::optional<CharSelector> &&s) : selector{std::move(s)} {}
std::optional<CharSelector> selector;
};
struct Logical {
BOILERPLATE(Logical);
Logical(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
std::optional<KindSelector> kind;
};
EMPTY_CLASS(DoubleComplex);
std::variant<IntegerTypeSpec, Real, DoublePrecision, Complex, Character,
Logical, DoubleComplex>
u;
};
// Extension: Vector type
WRAPPER_CLASS(UnsignedTypeSpec, std::optional<KindSelector>);
struct VectorElementType {
UNION_CLASS_BOILERPLATE(VectorElementType);
std::variant<IntegerTypeSpec, IntrinsicTypeSpec::Real, UnsignedTypeSpec> u;
};
WRAPPER_CLASS(IntrinsicVectorTypeSpec, VectorElementType);
struct VectorTypeSpec {
UNION_CLASS_BOILERPLATE(VectorTypeSpec);
EMPTY_CLASS(PairVectorTypeSpec);
EMPTY_CLASS(QuadVectorTypeSpec);
std::variant<IntrinsicVectorTypeSpec, PairVectorTypeSpec, QuadVectorTypeSpec>
u;
};
// R755 type-param-spec -> [keyword =] type-param-value
struct TypeParamSpec {
TUPLE_CLASS_BOILERPLATE(TypeParamSpec);
std::tuple<std::optional<Keyword>, TypeParamValue> t;
};
// R754 derived-type-spec -> type-name [(type-param-spec-list)]
struct DerivedTypeSpec {
TUPLE_CLASS_BOILERPLATE(DerivedTypeSpec);
mutable const semantics::DerivedTypeSpec *derivedTypeSpec{nullptr};
std::tuple<Name, std::list<TypeParamSpec>> t;
};
// R702 type-spec -> intrinsic-type-spec | derived-type-spec
struct TypeSpec {
UNION_CLASS_BOILERPLATE(TypeSpec);
mutable const semantics::DeclTypeSpec *declTypeSpec{nullptr};
std::variant<IntrinsicTypeSpec, DerivedTypeSpec> u;
};
// R703 declaration-type-spec ->
// intrinsic-type-spec | TYPE ( intrinsic-type-spec ) |
// TYPE ( derived-type-spec ) | CLASS ( derived-type-spec ) |
// CLASS ( * ) | TYPE ( * )
// Legacy extension: RECORD /struct/
struct DeclarationTypeSpec {
UNION_CLASS_BOILERPLATE(DeclarationTypeSpec);
struct Type {
BOILERPLATE(Type);
Type(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
DerivedTypeSpec derived;
};
struct Class {
BOILERPLATE(Class);
Class(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
DerivedTypeSpec derived;
};
EMPTY_CLASS(ClassStar);
EMPTY_CLASS(TypeStar);
WRAPPER_CLASS(Record, Name);
std::variant<IntrinsicTypeSpec, Type, Class, ClassStar, TypeStar, Record,
VectorTypeSpec>
u;
};
// R709 kind-param -> digit-string | scalar-int-constant-name
struct KindParam {
UNION_CLASS_BOILERPLATE(KindParam);
std::variant<std::uint64_t, Scalar<Integer<Constant<Name>>>> u;
};
// R707 signed-int-literal-constant -> [sign] int-literal-constant
struct SignedIntLiteralConstant {
TUPLE_CLASS_BOILERPLATE(SignedIntLiteralConstant);
CharBlock source;
std::tuple<CharBlock, std::optional<KindParam>> t;
};
// R708 int-literal-constant -> digit-string [_ kind-param]
struct IntLiteralConstant {
TUPLE_CLASS_BOILERPLATE(IntLiteralConstant);
std::tuple<CharBlock, std::optional<KindParam>> t;
};
// R712 sign -> + | -
enum class Sign { Positive, Negative };
// R714 real-literal-constant ->
// significand [exponent-letter exponent] [_ kind-param] |
// digit-string exponent-letter exponent [_ kind-param]
// R715 significand -> digit-string . [digit-string] | . digit-string
// R717 exponent -> signed-digit-string
struct RealLiteralConstant {
BOILERPLATE(RealLiteralConstant);
struct Real {
COPY_AND_ASSIGN_BOILERPLATE(Real);
Real() {}
CharBlock source;
};
RealLiteralConstant(Real &&r, std::optional<KindParam> &&k)
: real{std::move(r)}, kind{std::move(k)} {}
Real real;
std::optional<KindParam> kind;
};
// R713 signed-real-literal-constant -> [sign] real-literal-constant
struct SignedRealLiteralConstant {
TUPLE_CLASS_BOILERPLATE(SignedRealLiteralConstant);
std::tuple<std::optional<Sign>, RealLiteralConstant> t;
};
// R719 real-part ->
// signed-int-literal-constant | signed-real-literal-constant |
// named-constant
// R720 imag-part ->
// signed-int-literal-constant | signed-real-literal-constant |
// named-constant
struct ComplexPart {
UNION_CLASS_BOILERPLATE(ComplexPart);
std::variant<SignedIntLiteralConstant, SignedRealLiteralConstant,
NamedConstant>
u;
};
// R718 complex-literal-constant -> ( real-part , imag-part )
struct ComplexLiteralConstant {
TUPLE_CLASS_BOILERPLATE(ComplexLiteralConstant);
std::tuple<ComplexPart, ComplexPart> t; // real, imaginary
};
// Extension: signed COMPLEX constant
struct SignedComplexLiteralConstant {
TUPLE_CLASS_BOILERPLATE(SignedComplexLiteralConstant);
std::tuple<Sign, ComplexLiteralConstant> t;
};
// R724 char-literal-constant ->
// [kind-param _] ' [rep-char]... ' |
// [kind-param _] " [rep-char]... "
struct CharLiteralConstant {
TUPLE_CLASS_BOILERPLATE(CharLiteralConstant);
std::tuple<std::optional<KindParam>, std::string> t;
std::string GetString() const { return std::get<std::string>(t); }
};
// legacy extension
struct HollerithLiteralConstant {
WRAPPER_CLASS_BOILERPLATE(HollerithLiteralConstant, std::string);
std::string GetString() const { return v; }
};
// R725 logical-literal-constant ->
// .TRUE. [_ kind-param] | .FALSE. [_ kind-param]
struct LogicalLiteralConstant {
TUPLE_CLASS_BOILERPLATE(LogicalLiteralConstant);
std::tuple<bool, std::optional<KindParam>> t;
};
// R764 boz-literal-constant -> binary-constant | octal-constant | hex-constant
// R765 binary-constant -> B ' digit [digit]... ' | B " digit [digit]... "
// R766 octal-constant -> O ' digit [digit]... ' | O " digit [digit]... "
// R767 hex-constant ->
// Z ' hex-digit [hex-digit]... ' | Z " hex-digit [hex-digit]... "
// The constant must be large enough to hold any real or integer scalar
// of any supported kind (F'2018 7.7).
WRAPPER_CLASS(BOZLiteralConstant, std::string);
// R605 literal-constant ->
// int-literal-constant | real-literal-constant |
// complex-literal-constant | logical-literal-constant |
// char-literal-constant | boz-literal-constant
struct LiteralConstant {
UNION_CLASS_BOILERPLATE(LiteralConstant);
std::variant<HollerithLiteralConstant, IntLiteralConstant,
RealLiteralConstant, ComplexLiteralConstant, BOZLiteralConstant,
CharLiteralConstant, LogicalLiteralConstant>
u;
};
// R807 access-spec -> PUBLIC | PRIVATE
struct AccessSpec {
ENUM_CLASS(Kind, Public, Private)
WRAPPER_CLASS_BOILERPLATE(AccessSpec, Kind);
};
// R728 type-attr-spec ->
// ABSTRACT | access-spec | BIND(C) | EXTENDS ( parent-type-name )
EMPTY_CLASS(Abstract);
struct TypeAttrSpec {
UNION_CLASS_BOILERPLATE(TypeAttrSpec);
EMPTY_CLASS(BindC);
WRAPPER_CLASS(Extends, Name);
std::variant<Abstract, AccessSpec, BindC, Extends> u;
};
// R727 derived-type-stmt ->
// TYPE [[, type-attr-spec-list] ::] type-name [( type-param-name-list )]
struct DerivedTypeStmt {
TUPLE_CLASS_BOILERPLATE(DerivedTypeStmt);
std::tuple<std::list<TypeAttrSpec>, Name, std::list<Name>> t;
};
// R731 sequence-stmt -> SEQUENCE
EMPTY_CLASS(SequenceStmt);
// R745 private-components-stmt -> PRIVATE
// R747 binding-private-stmt -> PRIVATE
EMPTY_CLASS(PrivateStmt);
// R729 private-or-sequence -> private-components-stmt | sequence-stmt
struct PrivateOrSequence {
UNION_CLASS_BOILERPLATE(PrivateOrSequence);
std::variant<PrivateStmt, SequenceStmt> u;
};
// R733 type-param-decl -> type-param-name [= scalar-int-constant-expr]
struct TypeParamDecl {
TUPLE_CLASS_BOILERPLATE(TypeParamDecl);
std::tuple<Name, std::optional<ScalarIntConstantExpr>> t;
};
// R732 type-param-def-stmt ->
// integer-type-spec , type-param-attr-spec :: type-param-decl-list
// R734 type-param-attr-spec -> KIND | LEN
struct TypeParamDefStmt {
TUPLE_CLASS_BOILERPLATE(TypeParamDefStmt);
std::tuple<IntegerTypeSpec, common::TypeParamAttr, std::list<TypeParamDecl>>
t;
};
// R1028 specification-expr -> scalar-int-expr
WRAPPER_CLASS(SpecificationExpr, ScalarIntExpr);
// R816 explicit-shape-spec -> [lower-bound :] upper-bound
// R817 lower-bound -> specification-expr
// R818 upper-bound -> specification-expr
struct ExplicitShapeSpec {
TUPLE_CLASS_BOILERPLATE(ExplicitShapeSpec);
std::tuple<std::optional<SpecificationExpr>, SpecificationExpr> t;
};
// R810 deferred-coshape-spec -> :
// deferred-coshape-spec-list is just a count of the colons (i.e., the rank).
WRAPPER_CLASS(DeferredCoshapeSpecList, int);
// R811 explicit-coshape-spec ->
// [[lower-cobound :] upper-cobound ,]... [lower-cobound :] *
// R812 lower-cobound -> specification-expr
// R813 upper-cobound -> specification-expr
struct ExplicitCoshapeSpec {
TUPLE_CLASS_BOILERPLATE(ExplicitCoshapeSpec);
std::tuple<std::list<ExplicitShapeSpec>, std::optional<SpecificationExpr>> t;
};
// R809 coarray-spec -> deferred-coshape-spec-list | explicit-coshape-spec
struct CoarraySpec {
UNION_CLASS_BOILERPLATE(CoarraySpec);
std::variant<DeferredCoshapeSpecList, ExplicitCoshapeSpec> u;
};
// R820 deferred-shape-spec -> :
// deferred-shape-spec-list is just a count of the colons (i.e., the rank).
WRAPPER_CLASS(DeferredShapeSpecList, int);
// R740 component-array-spec ->
// explicit-shape-spec-list | deferred-shape-spec-list
struct ComponentArraySpec {
UNION_CLASS_BOILERPLATE(ComponentArraySpec);
std::variant<std::list<ExplicitShapeSpec>, DeferredShapeSpecList> u;
};
// R738 component-attr-spec ->
// access-spec | ALLOCATABLE |
// CODIMENSION lbracket coarray-spec rbracket |
// CONTIGUOUS | DIMENSION ( component-array-spec ) | POINTER |
// (CUDA) CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE | UNIFIED
EMPTY_CLASS(Allocatable);
EMPTY_CLASS(Pointer);
EMPTY_CLASS(Contiguous);
struct ComponentAttrSpec {