93a59505a5
and initial, final, and step expressions. As a new extension, we want to allow REAL and DOUBLE PRECISION values for them by default. Here's a summary of the changes: - There already existed infrastructure for semantic checking of DO loops that was partially specific to DO CONCURRENT loops. Because I re-used some of this infrastructure, I renamed some files and classes from "concurrent" to "stmt". - I added some functions to distinguish among the different kinds of DO statements. - I added the functions to check-do-stmt.cc to produce the necessary warnins and errors. Note that there are no tests for the warnings since the necessary testing infrastructure does not yet exist. - I changed test-errors.sh so that additional compilation options can be specified in the test source. - I added two new tests to test for the various kinds of values that can be used for the DO variables and control expressions. The two tests are identical except for the use of different compilation options. dosemantics03.f90 specifies the options "-Mstandard -Werror" to produce error messages for the use of REAL and DOUBLE PRECISION DO variables and controls. dosemantics04.f90 uses the default options and only produces error messages for contructs that are erroneous by default. Original-commit: flang-compiler/f18@f484660c75 Reviewed-on: https://github.com/flang-compiler/f18/pull/478 Tree-same-pre-rewrite: false
3738 lines
128 KiB
C++
3738 lines
128 KiB
C++
// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#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 "../common/Fortran.h"
|
|
#include "../common/idioms.h"
|
|
#include "../common/indirection.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;
|
|
}
|
|
|
|
// 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>
|
|
}
|
|
|
|
// 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 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 SyncAllStmt; // R1164
|
|
struct SyncImagesStmt; // R1166
|
|
struct SyncMemoryStmt; // R1168
|
|
struct SyncTeamStmt; // R1169
|
|
struct EventPostStmt; // R1170, R1171
|
|
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 StructureDef;
|
|
struct ArithmeticIfStmt;
|
|
struct AssignStmt;
|
|
struct AssignedGotoStmt;
|
|
struct PauseStmt;
|
|
struct OpenMPConstruct;
|
|
struct OpenMPDeclarativeConstruct;
|
|
struct OmpBlockDirective;
|
|
struct OpenMPEndLoopDirective;
|
|
|
|
// Cooked character stream locations
|
|
using Location = const char *;
|
|
|
|
// 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 = std::uint64_t; // 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
|
|
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>>
|
|
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<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>>>
|
|
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]...
|
|
// TODO: transfer any statements after the last IMPLICIT (if any)
|
|
// from the implicit part to the declaration constructs
|
|
struct SpecificationPart {
|
|
TUPLE_CLASS_BOILERPLATE(SpecificationPart);
|
|
std::tuple<std::list<OpenMPDeclarativeConstruct>,
|
|
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>>
|
|
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 | 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<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
|
|
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<OpenMPConstruct>,
|
|
common::Indirection<OpenMPEndLoopDirective>>
|
|
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]...
|
|
WRAPPER_CLASS(ExecutionPart, std::list<ExecutionPartConstruct>);
|
|
|
|
// 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>>
|
|
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, XOR, 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::int64_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, NCHARACTER (Kanji)
|
|
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);
|
|
WRAPPER_CLASS(NCharacter, std::optional<LengthSelector>);
|
|
std::variant<IntegerTypeSpec, Real, DoublePrecision, Complex, Character,
|
|
Logical, DoubleComplex, NCharacter>
|
|
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> u;
|
|
};
|
|
|
|
// R709 kind-param -> digit-string | scalar-int-constant-name
|
|
struct KindParam {
|
|
UNION_CLASS_BOILERPLATE(KindParam);
|
|
EMPTY_CLASS(Kanji);
|
|
std::variant<std::uint64_t, Scalar<Integer<Constant<Name>>>, Kanji> 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;
|
|
};
|
|
|
|
// R604 constant -> literal-constant | named-constant
|
|
// Renamed to dodge a clash with Constant<> template class.
|
|
struct ConstantValue {
|
|
UNION_CLASS_BOILERPLATE(ConstantValue);
|
|
std::variant<LiteralConstant, NamedConstant> 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
|
|
EMPTY_CLASS(Allocatable);
|
|
EMPTY_CLASS(Pointer);
|
|
EMPTY_CLASS(Contiguous);
|
|
struct ComponentAttrSpec {
|
|
UNION_CLASS_BOILERPLATE(ComponentAttrSpec);
|
|
std::variant<AccessSpec, Allocatable, CoarraySpec, Contiguous,
|
|
ComponentArraySpec, Pointer, ErrorRecovery>
|
|
u;
|
|
};
|
|
|
|
// R806 null-init -> function-reference
|
|
// TODO check that NULL is still intrinsic
|
|
EMPTY_CLASS(NullInit);
|
|
|
|
// R744 initial-data-target -> designator
|
|
using InitialDataTarget = common::Indirection<Designator>;
|
|
|
|
// R743 component-initialization ->
|
|
// = constant-expr | => null-init | => initial-data-target
|
|
// R805 initialization ->
|
|
// = constant-expr | => null-init | => initial-data-target
|
|
// Universal extension: initialization -> / data-stmt-value-list /
|
|
struct Initialization {
|
|
UNION_CLASS_BOILERPLATE(Initialization);
|
|
std::variant<ConstantExpr, NullInit, InitialDataTarget,
|
|
std::list<common::Indirection<DataStmtValue>>>
|
|
u;
|
|
};
|
|
|
|
// R739 component-decl ->
|
|
// component-name [( component-array-spec )]
|
|
// [lbracket coarray-spec rbracket] [* char-length]
|
|
// [component-initialization]
|
|
struct ComponentDecl {
|
|
TUPLE_CLASS_BOILERPLATE(ComponentDecl);
|
|
std::tuple<Name, std::optional<ComponentArraySpec>,
|
|
std::optional<CoarraySpec>, std::optional<CharLength>,
|
|
std::optional<Initialization>>
|
|
t;
|
|
};
|
|
|
|
// R737 data-component-def-stmt ->
|
|
// declaration-type-spec [[, component-attr-spec-list] ::]
|
|
// component-decl-list
|
|
struct DataComponentDefStmt {
|
|
TUPLE_CLASS_BOILERPLATE(DataComponentDefStmt);
|
|
std::tuple<DeclarationTypeSpec, std::list<ComponentAttrSpec>,
|
|
std::list<ComponentDecl>>
|
|
t;
|
|
};
|
|
|
|
// R742 proc-component-attr-spec ->
|
|
// access-spec | NOPASS | PASS [(arg-name)] | POINTER
|
|
EMPTY_CLASS(NoPass);
|
|
WRAPPER_CLASS(Pass, std::optional<Name>);
|
|
struct ProcComponentAttrSpec {
|
|
UNION_CLASS_BOILERPLATE(ProcComponentAttrSpec);
|
|
std::variant<AccessSpec, NoPass, Pass, Pointer> u;
|
|
};
|
|
|
|
// R1517 proc-pointer-init -> null-init | initial-proc-target
|
|
// R1518 initial-proc-target -> procedure-name
|
|
struct ProcPointerInit {
|
|
UNION_CLASS_BOILERPLATE(ProcPointerInit);
|
|
std::variant<NullInit, Name> u;
|
|
};
|
|
|
|
// R1513 proc-interface -> interface-name | declaration-type-spec
|
|
// R1516 interface-name -> name
|
|
struct ProcInterface {
|
|
UNION_CLASS_BOILERPLATE(ProcInterface);
|
|
std::variant<Name, DeclarationTypeSpec> u;
|
|
};
|
|
|
|
// R1515 proc-decl -> procedure-entity-name [=> proc-pointer-init]
|
|
struct ProcDecl {
|
|
TUPLE_CLASS_BOILERPLATE(ProcDecl);
|
|
std::tuple<Name, std::optional<ProcPointerInit>> t;
|
|
};
|
|
|
|
// R741 proc-component-def-stmt ->
|
|
// PROCEDURE ( [proc-interface] ) , proc-component-attr-spec-list
|
|
// :: proc-decl-list
|
|
struct ProcComponentDefStmt {
|
|
TUPLE_CLASS_BOILERPLATE(ProcComponentDefStmt);
|
|
std::tuple<std::optional<ProcInterface>, std::list<ProcComponentAttrSpec>,
|
|
std::list<ProcDecl>>
|
|
t;
|
|
};
|
|
|
|
// R736 component-def-stmt -> data-component-def-stmt | proc-component-def-stmt
|
|
struct ComponentDefStmt {
|
|
UNION_CLASS_BOILERPLATE(ComponentDefStmt);
|
|
std::variant<DataComponentDefStmt, ProcComponentDefStmt, ErrorRecovery
|
|
// , TypeParamDefStmt -- PGI accidental extension, not enabled
|
|
>
|
|
u;
|
|
};
|
|
|
|
// R752 bind-attr ->
|
|
// access-spec | DEFERRED | NON_OVERRIDABLE | NOPASS | PASS [(arg-name)]
|
|
struct BindAttr {
|
|
UNION_CLASS_BOILERPLATE(BindAttr);
|
|
EMPTY_CLASS(Deferred);
|
|
EMPTY_CLASS(Non_Overridable);
|
|
std::variant<AccessSpec, Deferred, Non_Overridable, NoPass, Pass> u;
|
|
};
|
|
|
|
// R750 type-bound-proc-decl -> binding-name [=> procedure-name]
|
|
struct TypeBoundProcDecl {
|
|
TUPLE_CLASS_BOILERPLATE(TypeBoundProcDecl);
|
|
std::tuple<Name, std::optional<Name>> t;
|
|
};
|
|
|
|
// R749 type-bound-procedure-stmt ->
|
|
// PROCEDURE [[, bind-attr-list] ::] type-bound-proc-decl-list |
|
|
// PROCEDURE ( interface-name ) , bind-attr-list :: binding-name-list
|
|
struct TypeBoundProcedureStmt {
|
|
UNION_CLASS_BOILERPLATE(TypeBoundProcedureStmt);
|
|
struct WithoutInterface {
|
|
BOILERPLATE(WithoutInterface);
|
|
WithoutInterface(
|
|
std::list<BindAttr> &&as, std::list<TypeBoundProcDecl> &&ds)
|
|
: attributes(std::move(as)), declarations(std::move(ds)) {}
|
|
std::list<BindAttr> attributes;
|
|
std::list<TypeBoundProcDecl> declarations;
|
|
};
|
|
struct WithInterface {
|
|
BOILERPLATE(WithInterface);
|
|
WithInterface(Name &&n, std::list<BindAttr> &&as, std::list<Name> &&bs)
|
|
: interfaceName(std::move(n)), attributes(std::move(as)),
|
|
bindingNames(std::move(bs)) {}
|
|
Name interfaceName;
|
|
std::list<BindAttr> attributes;
|
|
std::list<Name> bindingNames;
|
|
};
|
|
std::variant<WithoutInterface, WithInterface> u;
|
|
};
|
|
|
|
// R751 type-bound-generic-stmt ->
|
|
// GENERIC [, access-spec] :: generic-spec => binding-name-list
|
|
struct TypeBoundGenericStmt {
|
|
TUPLE_CLASS_BOILERPLATE(TypeBoundGenericStmt);
|
|
std::tuple<std::optional<AccessSpec>, common::Indirection<GenericSpec>,
|
|
std::list<Name>>
|
|
t;
|
|
};
|
|
|
|
// R753 final-procedure-stmt -> FINAL [::] final-subroutine-name-list
|
|
WRAPPER_CLASS(FinalProcedureStmt, std::list<Name>);
|
|
|
|
// R748 type-bound-proc-binding ->
|
|
// type-bound-procedure-stmt | type-bound-generic-stmt |
|
|
// final-procedure-stmt
|
|
struct TypeBoundProcBinding {
|
|
UNION_CLASS_BOILERPLATE(TypeBoundProcBinding);
|
|
std::variant<TypeBoundProcedureStmt, TypeBoundGenericStmt, FinalProcedureStmt,
|
|
ErrorRecovery>
|
|
u;
|
|
};
|
|
|
|
// R746 type-bound-procedure-part ->
|
|
// contains-stmt [binding-private-stmt] [type-bound-proc-binding]...
|
|
struct TypeBoundProcedurePart {
|
|
TUPLE_CLASS_BOILERPLATE(TypeBoundProcedurePart);
|
|
std::tuple<Statement<ContainsStmt>, std::optional<Statement<PrivateStmt>>,
|
|
std::list<Statement<TypeBoundProcBinding>>>
|
|
t;
|
|
};
|
|
|
|
// R730 end-type-stmt -> END TYPE [type-name]
|
|
WRAPPER_CLASS(EndTypeStmt, std::optional<Name>);
|
|
|
|
// R726 derived-type-def ->
|
|
// derived-type-stmt [type-param-def-stmt]... [private-or-sequence]...
|
|
// [component-part] [type-bound-procedure-part] end-type-stmt
|
|
// R735 component-part -> [component-def-stmt]...
|
|
struct DerivedTypeDef {
|
|
TUPLE_CLASS_BOILERPLATE(DerivedTypeDef);
|
|
std::tuple<Statement<DerivedTypeStmt>, std::list<Statement<TypeParamDefStmt>>,
|
|
std::list<Statement<PrivateOrSequence>>,
|
|
std::list<Statement<ComponentDefStmt>>,
|
|
std::optional<TypeBoundProcedurePart>, Statement<EndTypeStmt>>
|
|
t;
|
|
};
|
|
|
|
// R758 component-data-source -> expr | data-target | proc-target
|
|
// R1037 data-target -> expr
|
|
// R1040 proc-target -> expr | procedure-name | proc-component-ref
|
|
WRAPPER_CLASS(ComponentDataSource, common::Indirection<Expr>);
|
|
|
|
// R757 component-spec -> [keyword =] component-data-source
|
|
struct ComponentSpec {
|
|
TUPLE_CLASS_BOILERPLATE(ComponentSpec);
|
|
std::tuple<std::optional<Keyword>, ComponentDataSource> t;
|
|
};
|
|
|
|
// R756 structure-constructor -> derived-type-spec ( [component-spec-list] )
|
|
struct StructureConstructor {
|
|
TUPLE_CLASS_BOILERPLATE(StructureConstructor);
|
|
std::tuple<DerivedTypeSpec, std::list<ComponentSpec>> t;
|
|
};
|
|
|
|
// R760 enum-def-stmt -> ENUM, BIND(C)
|
|
EMPTY_CLASS(EnumDefStmt);
|
|
|
|
// R762 enumerator -> named-constant [= scalar-int-constant-expr]
|
|
struct Enumerator {
|
|
TUPLE_CLASS_BOILERPLATE(Enumerator);
|
|
std::tuple<NamedConstant, std::optional<ScalarIntConstantExpr>> t;
|
|
};
|
|
|
|
// R761 enumerator-def-stmt -> ENUMERATOR [::] enumerator-list
|
|
WRAPPER_CLASS(EnumeratorDefStmt, std::list<Enumerator>);
|
|
|
|
// R763 end-enum-stmt -> END ENUM
|
|
EMPTY_CLASS(EndEnumStmt);
|
|
|
|
// R759 enum-def ->
|
|
// enum-def-stmt enumerator-def-stmt [enumerator-def-stmt]...
|
|
// end-enum-stmt
|
|
struct EnumDef {
|
|
TUPLE_CLASS_BOILERPLATE(EnumDef);
|
|
std::tuple<Statement<EnumDefStmt>, std::list<Statement<EnumeratorDefStmt>>,
|
|
Statement<EndEnumStmt>>
|
|
t;
|
|
};
|
|
|
|
// R773 ac-value -> expr | ac-implied-do
|
|
struct AcValue {
|
|
struct Triplet { // PGI/Intel extension
|
|
TUPLE_CLASS_BOILERPLATE(Triplet);
|
|
std::tuple<ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>> t;
|
|
};
|
|
UNION_CLASS_BOILERPLATE(AcValue);
|
|
std::variant<Triplet, common::Indirection<Expr>,
|
|
common::Indirection<AcImpliedDo>>
|
|
u;
|
|
};
|
|
|
|
// R770 ac-spec -> type-spec :: | [type-spec ::] ac-value-list
|
|
struct AcSpec {
|
|
BOILERPLATE(AcSpec);
|
|
AcSpec(std::optional<TypeSpec> &&ts, std::list<AcValue> &&xs)
|
|
: type(std::move(ts)), values(std::move(xs)) {}
|
|
explicit AcSpec(TypeSpec &&ts) : type{std::move(ts)} {}
|
|
std::optional<TypeSpec> type;
|
|
std::list<AcValue> values;
|
|
};
|
|
|
|
// R769 array-constructor -> (/ ac-spec /) | lbracket ac-spec rbracket
|
|
WRAPPER_CLASS(ArrayConstructor, AcSpec);
|
|
|
|
// R1124 do-variable -> scalar-int-variable-name
|
|
using DoVariable = Scalar<Integer<Name>>;
|
|
|
|
template<typename VAR, typename BOUND> struct LoopBounds {
|
|
LoopBounds(LoopBounds &&that) = default;
|
|
LoopBounds(
|
|
VAR &&name, BOUND &&lower, BOUND &&upper, std::optional<BOUND> &&step)
|
|
: name{std::move(name)}, lower{std::move(lower)}, upper{std::move(upper)},
|
|
step{std::move(step)} {}
|
|
LoopBounds &operator=(LoopBounds &&) = default;
|
|
VAR name;
|
|
BOUND lower, upper;
|
|
std::optional<BOUND> step;
|
|
};
|
|
|
|
using ScalarName = Scalar<Name>;
|
|
using ScalarExpr = Scalar<common::Indirection<Expr>>;
|
|
|
|
// R775 ac-implied-do-control ->
|
|
// [integer-type-spec ::] ac-do-variable = scalar-int-expr ,
|
|
// scalar-int-expr [, scalar-int-expr]
|
|
// R776 ac-do-variable -> do-variable
|
|
struct AcImpliedDoControl {
|
|
TUPLE_CLASS_BOILERPLATE(AcImpliedDoControl);
|
|
using Bounds = LoopBounds<DoVariable, ScalarIntExpr>;
|
|
std::tuple<std::optional<IntegerTypeSpec>, Bounds> t;
|
|
};
|
|
|
|
// R774 ac-implied-do -> ( ac-value-list , ac-implied-do-control )
|
|
struct AcImpliedDo {
|
|
TUPLE_CLASS_BOILERPLATE(AcImpliedDo);
|
|
std::tuple<std::list<AcValue>, AcImpliedDoControl> t;
|
|
};
|
|
|
|
// R808 language-binding-spec ->
|
|
// BIND ( C [, NAME = scalar-default-char-constant-expr] )
|
|
// R1528 proc-language-binding-spec -> language-binding-spec
|
|
WRAPPER_CLASS(
|
|
LanguageBindingSpec, std::optional<ScalarDefaultCharConstantExpr>);
|
|
|
|
// R852 named-constant-def -> named-constant = constant-expr
|
|
struct NamedConstantDef {
|
|
TUPLE_CLASS_BOILERPLATE(NamedConstantDef);
|
|
std::tuple<NamedConstant, ConstantExpr> t;
|
|
};
|
|
|
|
// R851 parameter-stmt -> PARAMETER ( named-constant-def-list )
|
|
WRAPPER_CLASS(ParameterStmt, std::list<NamedConstantDef>);
|
|
|
|
// R819 assumed-shape-spec -> [lower-bound] :
|
|
WRAPPER_CLASS(AssumedShapeSpec, std::optional<SpecificationExpr>);
|
|
|
|
// R821 assumed-implied-spec -> [lower-bound :] *
|
|
WRAPPER_CLASS(AssumedImpliedSpec, std::optional<SpecificationExpr>);
|
|
|
|
// R822 assumed-size-spec -> explicit-shape-spec-list , assumed-implied-spec
|
|
struct AssumedSizeSpec {
|
|
TUPLE_CLASS_BOILERPLATE(AssumedSizeSpec);
|
|
std::tuple<std::list<ExplicitShapeSpec>, AssumedImpliedSpec> t;
|
|
};
|
|
|
|
// R823 implied-shape-or-assumed-size-spec -> assumed-implied-spec
|
|
// R824 implied-shape-spec -> assumed-implied-spec , assumed-implied-spec-list
|
|
// I.e., when the assumed-implied-spec-list has a single item, it constitutes an
|
|
// implied-shape-or-assumed-size-spec; otherwise, an implied-shape-spec.
|
|
WRAPPER_CLASS(ImpliedShapeSpec, std::list<AssumedImpliedSpec>);
|
|
|
|
// R825 assumed-rank-spec -> ..
|
|
EMPTY_CLASS(AssumedRankSpec);
|
|
|
|
// R815 array-spec ->
|
|
// explicit-shape-spec-list | assumed-shape-spec-list |
|
|
// deferred-shape-spec-list | assumed-size-spec | implied-shape-spec |
|
|
// implied-shape-or-assumed-size-spec | assumed-rank-spec
|
|
struct ArraySpec {
|
|
UNION_CLASS_BOILERPLATE(ArraySpec);
|
|
std::variant<std::list<ExplicitShapeSpec>, std::list<AssumedShapeSpec>,
|
|
DeferredShapeSpecList, AssumedSizeSpec, ImpliedShapeSpec, AssumedRankSpec>
|
|
u;
|
|
};
|
|
|
|
// R826 intent-spec -> IN | OUT | INOUT
|
|
struct IntentSpec {
|
|
ENUM_CLASS(Intent, In, Out, InOut)
|
|
WRAPPER_CLASS_BOILERPLATE(IntentSpec, Intent);
|
|
};
|
|
|
|
// R802 attr-spec ->
|
|
// access-spec | ALLOCATABLE | ASYNCHRONOUS |
|
|
// CODIMENSION lbracket coarray-spec rbracket | CONTIGUOUS |
|
|
// DIMENSION ( array-spec ) | EXTERNAL | INTENT ( intent-spec ) |
|
|
// INTRINSIC | language-binding-spec | OPTIONAL | PARAMETER | POINTER |
|
|
// PROTECTED | SAVE | TARGET | VALUE | VOLATILE
|
|
EMPTY_CLASS(Asynchronous);
|
|
EMPTY_CLASS(External);
|
|
EMPTY_CLASS(Intrinsic);
|
|
EMPTY_CLASS(Optional);
|
|
EMPTY_CLASS(Parameter);
|
|
EMPTY_CLASS(Protected);
|
|
EMPTY_CLASS(Save);
|
|
EMPTY_CLASS(Target);
|
|
EMPTY_CLASS(Value);
|
|
EMPTY_CLASS(Volatile);
|
|
struct AttrSpec {
|
|
UNION_CLASS_BOILERPLATE(AttrSpec);
|
|
std::variant<AccessSpec, Allocatable, Asynchronous, CoarraySpec, Contiguous,
|
|
ArraySpec, External, IntentSpec, Intrinsic, LanguageBindingSpec, Optional,
|
|
Parameter, Pointer, Protected, Save, Target, Value, Volatile>
|
|
u;
|
|
};
|
|
|
|
// R803 entity-decl ->
|
|
// object-name [( array-spec )] [lbracket coarray-spec rbracket]
|
|
// [* char-length] [initialization] |
|
|
// function-name [* char-length]
|
|
struct EntityDecl {
|
|
TUPLE_CLASS_BOILERPLATE(EntityDecl);
|
|
std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>,
|
|
std::optional<CharLength>, std::optional<Initialization>>
|
|
t;
|
|
};
|
|
|
|
// R801 type-declaration-stmt ->
|
|
// declaration-type-spec [[, attr-spec]... ::] entity-decl-list
|
|
struct TypeDeclarationStmt {
|
|
TUPLE_CLASS_BOILERPLATE(TypeDeclarationStmt);
|
|
std::tuple<DeclarationTypeSpec, std::list<AttrSpec>, std::list<EntityDecl>> t;
|
|
};
|
|
|
|
// R828 access-id -> access-name | generic-spec
|
|
struct AccessId {
|
|
UNION_CLASS_BOILERPLATE(AccessId);
|
|
std::variant<Name, common::Indirection<GenericSpec>> u;
|
|
};
|
|
|
|
// R827 access-stmt -> access-spec [[::] access-id-list]
|
|
struct AccessStmt {
|
|
TUPLE_CLASS_BOILERPLATE(AccessStmt);
|
|
std::tuple<AccessSpec, std::list<AccessId>> t;
|
|
};
|
|
|
|
// R830 allocatable-decl ->
|
|
// object-name [( array-spec )] [lbracket coarray-spec rbracket]
|
|
// R860 target-decl ->
|
|
// object-name [( array-spec )] [lbracket coarray-spec rbracket]
|
|
struct ObjectDecl {
|
|
TUPLE_CLASS_BOILERPLATE(ObjectDecl);
|
|
std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>>
|
|
t;
|
|
};
|
|
|
|
// R829 allocatable-stmt -> ALLOCATABLE [::] allocatable-decl-list
|
|
WRAPPER_CLASS(AllocatableStmt, std::list<ObjectDecl>);
|
|
|
|
// R831 asynchronous-stmt -> ASYNCHRONOUS [::] object-name-list
|
|
WRAPPER_CLASS(AsynchronousStmt, std::list<ObjectName>);
|
|
|
|
// R833 bind-entity -> entity-name | / common-block-name /
|
|
struct BindEntity {
|
|
TUPLE_CLASS_BOILERPLATE(BindEntity);
|
|
ENUM_CLASS(Kind, Object, Common)
|
|
std::tuple<Kind, Name> t;
|
|
};
|
|
|
|
// R832 bind-stmt -> language-binding-spec [::] bind-entity-list
|
|
struct BindStmt {
|
|
TUPLE_CLASS_BOILERPLATE(BindStmt);
|
|
std::tuple<LanguageBindingSpec, std::list<BindEntity>> t;
|
|
};
|
|
|
|
// R835 codimension-decl -> coarray-name lbracket coarray-spec rbracket
|
|
struct CodimensionDecl {
|
|
TUPLE_CLASS_BOILERPLATE(CodimensionDecl);
|
|
std::tuple<Name, CoarraySpec> t;
|
|
};
|
|
|
|
// R834 codimension-stmt -> CODIMENSION [::] codimension-decl-list
|
|
WRAPPER_CLASS(CodimensionStmt, std::list<CodimensionDecl>);
|
|
|
|
// R836 contiguous-stmt -> CONTIGUOUS [::] object-name-list
|
|
WRAPPER_CLASS(ContiguousStmt, std::list<ObjectName>);
|
|
|
|
// R847 constant-subobject -> designator
|
|
// R846 int-constant-subobject -> constant-subobject
|
|
using ConstantSubobject = Constant<common::Indirection<Designator>>;
|
|
|
|
// R845 data-stmt-constant ->
|
|
// scalar-constant | scalar-constant-subobject |
|
|
// signed-int-literal-constant | signed-real-literal-constant |
|
|
// null-init | initial-data-target | structure-constructor
|
|
struct DataStmtConstant {
|
|
UNION_CLASS_BOILERPLATE(DataStmtConstant);
|
|
std::variant<Scalar<ConstantValue>, Scalar<ConstantSubobject>,
|
|
SignedIntLiteralConstant, SignedRealLiteralConstant,
|
|
SignedComplexLiteralConstant, NullInit, InitialDataTarget,
|
|
StructureConstructor>
|
|
u;
|
|
};
|
|
|
|
// R844 data-stmt-repeat -> scalar-int-constant | scalar-int-constant-subobject
|
|
// R607 int-constant -> constant
|
|
// R604 constant -> literal-constant | named-constant
|
|
// (only literal-constant -> int-literal-constant applies)
|
|
struct DataStmtRepeat {
|
|
UNION_CLASS_BOILERPLATE(DataStmtRepeat);
|
|
std::variant<IntLiteralConstant, Scalar<Integer<NamedConstant>>,
|
|
Scalar<Integer<ConstantSubobject>>>
|
|
u;
|
|
};
|
|
|
|
// R843 data-stmt-value -> [data-stmt-repeat *] data-stmt-constant
|
|
struct DataStmtValue {
|
|
TUPLE_CLASS_BOILERPLATE(DataStmtValue);
|
|
std::tuple<std::optional<DataStmtRepeat>, DataStmtConstant> t;
|
|
};
|
|
|
|
// R841 data-i-do-object ->
|
|
// array-element | scalar-structure-component | data-implied-do
|
|
struct DataIDoObject {
|
|
UNION_CLASS_BOILERPLATE(DataIDoObject);
|
|
std::variant<Scalar<common::Indirection<Designator>>,
|
|
common::Indirection<DataImpliedDo>>
|
|
u;
|
|
};
|
|
|
|
// R840 data-implied-do ->
|
|
// ( data-i-do-object-list , [integer-type-spec ::] data-i-do-variable
|
|
// = scalar-int-constant-expr , scalar-int-constant-expr
|
|
// [, scalar-int-constant-expr] )
|
|
// R842 data-i-do-variable -> do-variable
|
|
struct DataImpliedDo {
|
|
TUPLE_CLASS_BOILERPLATE(DataImpliedDo);
|
|
using Bounds = LoopBounds<DoVariable, ScalarIntConstantExpr>;
|
|
std::tuple<std::list<DataIDoObject>, std::optional<IntegerTypeSpec>, Bounds>
|
|
t;
|
|
};
|
|
|
|
// R839 data-stmt-object -> variable | data-implied-do
|
|
struct DataStmtObject {
|
|
UNION_CLASS_BOILERPLATE(DataStmtObject);
|
|
std::variant<common::Indirection<Variable>, DataImpliedDo> u;
|
|
};
|
|
|
|
// R838 data-stmt-set -> data-stmt-object-list / data-stmt-value-list /
|
|
struct DataStmtSet {
|
|
TUPLE_CLASS_BOILERPLATE(DataStmtSet);
|
|
std::tuple<std::list<DataStmtObject>, std::list<DataStmtValue>> t;
|
|
};
|
|
|
|
// R837 data-stmt -> DATA data-stmt-set [[,] data-stmt-set]...
|
|
WRAPPER_CLASS(DataStmt, std::list<DataStmtSet>);
|
|
|
|
// R848 dimension-stmt ->
|
|
// DIMENSION [::] array-name ( array-spec )
|
|
// [, array-name ( array-spec )]...
|
|
struct DimensionStmt {
|
|
struct Declaration {
|
|
TUPLE_CLASS_BOILERPLATE(Declaration);
|
|
std::tuple<Name, ArraySpec> t;
|
|
};
|
|
WRAPPER_CLASS_BOILERPLATE(DimensionStmt, std::list<Declaration>);
|
|
};
|
|
|
|
// R849 intent-stmt -> INTENT ( intent-spec ) [::] dummy-arg-name-list
|
|
struct IntentStmt {
|
|
TUPLE_CLASS_BOILERPLATE(IntentStmt);
|
|
std::tuple<IntentSpec, std::list<Name>> t;
|
|
};
|
|
|
|
// R850 optional-stmt -> OPTIONAL [::] dummy-arg-name-list
|
|
WRAPPER_CLASS(OptionalStmt, std::list<Name>);
|
|
|
|
// R854 pointer-decl ->
|
|
// object-name [( deferred-shape-spec-list )] | proc-entity-name
|
|
struct PointerDecl {
|
|
TUPLE_CLASS_BOILERPLATE(PointerDecl);
|
|
std::tuple<Name, std::optional<DeferredShapeSpecList>> t;
|
|
};
|
|
|
|
// R853 pointer-stmt -> POINTER [::] pointer-decl-list
|
|
WRAPPER_CLASS(PointerStmt, std::list<PointerDecl>);
|
|
|
|
// R855 protected-stmt -> PROTECTED [::] entity-name-list
|
|
WRAPPER_CLASS(ProtectedStmt, std::list<Name>);
|
|
|
|
// R857 saved-entity -> object-name | proc-pointer-name | / common-block-name /
|
|
// R858 proc-pointer-name -> name
|
|
struct SavedEntity {
|
|
TUPLE_CLASS_BOILERPLATE(SavedEntity);
|
|
ENUM_CLASS(Kind, Entity, Common)
|
|
std::tuple<Kind, Name> t;
|
|
};
|
|
|
|
// R856 save-stmt -> SAVE [[::] saved-entity-list]
|
|
WRAPPER_CLASS(SaveStmt, std::list<SavedEntity>);
|
|
|
|
// R859 target-stmt -> TARGET [::] target-decl-list
|
|
WRAPPER_CLASS(TargetStmt, std::list<ObjectDecl>);
|
|
|
|
// R861 value-stmt -> VALUE [::] dummy-arg-name-list
|
|
WRAPPER_CLASS(ValueStmt, std::list<Name>);
|
|
|
|
// R862 volatile-stmt -> VOLATILE [::] object-name-list
|
|
WRAPPER_CLASS(VolatileStmt, std::list<ObjectName>);
|
|
|
|
// R865 letter-spec -> letter [- letter]
|
|
struct LetterSpec {
|
|
TUPLE_CLASS_BOILERPLATE(LetterSpec);
|
|
std::tuple<Location, std::optional<Location>> t;
|
|
};
|
|
|
|
// R864 implicit-spec -> declaration-type-spec ( letter-spec-list )
|
|
struct ImplicitSpec {
|
|
TUPLE_CLASS_BOILERPLATE(ImplicitSpec);
|
|
std::tuple<DeclarationTypeSpec, std::list<LetterSpec>> t;
|
|
};
|
|
|
|
// R863 implicit-stmt ->
|
|
// IMPLICIT implicit-spec-list |
|
|
// IMPLICIT NONE [( [implicit-name-spec-list] )]
|
|
// R866 implicit-name-spec -> EXTERNAL | TYPE
|
|
struct ImplicitStmt {
|
|
UNION_CLASS_BOILERPLATE(ImplicitStmt);
|
|
ENUM_CLASS(ImplicitNoneNameSpec, External, Type) // R866
|
|
std::variant<std::list<ImplicitSpec>, std::list<ImplicitNoneNameSpec>> u;
|
|
};
|
|
|
|
// R874 common-block-object -> variable-name [( array-spec )]
|
|
struct CommonBlockObject {
|
|
TUPLE_CLASS_BOILERPLATE(CommonBlockObject);
|
|
std::tuple<Name, std::optional<ArraySpec>> t;
|
|
};
|
|
|
|
// R873 common-stmt ->
|
|
// COMMON [/ [common-block-name] /] common-block-object-list
|
|
// [[,] / [common-block-name] / common-block-object-list]...
|
|
struct CommonStmt {
|
|
struct Block {
|
|
TUPLE_CLASS_BOILERPLATE(Block);
|
|
std::tuple<std::optional<Name>, std::list<CommonBlockObject>> t;
|
|
};
|
|
BOILERPLATE(CommonStmt);
|
|
CommonStmt(std::optional<Name> &&, std::list<CommonBlockObject> &&,
|
|
std::list<Block> &&);
|
|
std::list<Block> blocks;
|
|
};
|
|
|
|
// R872 equivalence-object -> variable-name | array-element | substring
|
|
WRAPPER_CLASS(EquivalenceObject, common::Indirection<Designator>);
|
|
|
|
// R870 equivalence-stmt -> EQUIVALENCE equivalence-set-list
|
|
// R871 equivalence-set -> ( equivalence-object , equivalence-object-list )
|
|
WRAPPER_CLASS(EquivalenceStmt, std::list<std::list<EquivalenceObject>>);
|
|
|
|
// R910 substring-range -> [scalar-int-expr] : [scalar-int-expr]
|
|
struct SubstringRange {
|
|
TUPLE_CLASS_BOILERPLATE(SubstringRange);
|
|
std::tuple<std::optional<ScalarIntExpr>, std::optional<ScalarIntExpr>> t;
|
|
};
|
|
|
|
// R919 subscript -> scalar-int-expr
|
|
using Subscript = ScalarIntExpr;
|
|
|
|
// R921 subscript-triplet -> [subscript] : [subscript] [: stride]
|
|
struct SubscriptTriplet {
|
|
TUPLE_CLASS_BOILERPLATE(SubscriptTriplet);
|
|
std::tuple<std::optional<Subscript>, std::optional<Subscript>,
|
|
std::optional<Subscript>>
|
|
t;
|
|
};
|
|
|
|
// R920 section-subscript -> subscript | subscript-triplet | vector-subscript
|
|
// R923 vector-subscript -> int-expr
|
|
struct SectionSubscript {
|
|
UNION_CLASS_BOILERPLATE(SectionSubscript);
|
|
std::variant<IntExpr, SubscriptTriplet> u;
|
|
};
|
|
|
|
// R925 cosubscript -> scalar-int-expr
|
|
using Cosubscript = ScalarIntExpr;
|
|
|
|
// R1115 team-value -> scalar-expr
|
|
WRAPPER_CLASS(TeamValue, Scalar<common::Indirection<Expr>>);
|
|
|
|
// R926 image-selector-spec ->
|
|
// STAT = stat-variable | TEAM = team-value |
|
|
// TEAM_NUMBER = scalar-int-expr
|
|
struct ImageSelectorSpec {
|
|
WRAPPER_CLASS(Stat, Scalar<Integer<common::Indirection<Variable>>>);
|
|
WRAPPER_CLASS(Team_Number, ScalarIntExpr);
|
|
UNION_CLASS_BOILERPLATE(ImageSelectorSpec);
|
|
std::variant<Stat, TeamValue, Team_Number> u;
|
|
};
|
|
|
|
// R924 image-selector ->
|
|
// lbracket cosubscript-list [, image-selector-spec-list] rbracket
|
|
struct ImageSelector {
|
|
TUPLE_CLASS_BOILERPLATE(ImageSelector);
|
|
std::tuple<std::list<Cosubscript>, std::list<ImageSelectorSpec>> t;
|
|
};
|
|
|
|
// R1001 - R1022 expressions
|
|
struct Expr {
|
|
UNION_CLASS_BOILERPLATE(Expr);
|
|
|
|
WRAPPER_CLASS(IntrinsicUnary, common::Indirection<Expr>);
|
|
struct Parentheses : public IntrinsicUnary {
|
|
using IntrinsicUnary::IntrinsicUnary;
|
|
};
|
|
struct UnaryPlus : public IntrinsicUnary {
|
|
using IntrinsicUnary::IntrinsicUnary;
|
|
};
|
|
struct Negate : public IntrinsicUnary {
|
|
using IntrinsicUnary::IntrinsicUnary;
|
|
};
|
|
struct NOT : public IntrinsicUnary {
|
|
using IntrinsicUnary::IntrinsicUnary;
|
|
};
|
|
|
|
WRAPPER_CLASS(
|
|
PercentLoc, common::Indirection<Variable>); // %LOC(v) extension
|
|
|
|
struct DefinedUnary {
|
|
TUPLE_CLASS_BOILERPLATE(DefinedUnary);
|
|
std::tuple<DefinedOpName, common::Indirection<Expr>> t;
|
|
};
|
|
|
|
struct IntrinsicBinary {
|
|
TUPLE_CLASS_BOILERPLATE(IntrinsicBinary);
|
|
std::tuple<common::Indirection<Expr>, common::Indirection<Expr>> t;
|
|
};
|
|
struct Power : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct Multiply : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct Divide : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct Add : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct Subtract : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct Concat : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct LT : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct LE : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct EQ : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct NE : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct GE : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct GT : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct AND : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct OR : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct EQV : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct NEQV : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
struct XOR : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
|
|
// PGI/XLF extension: (x,y), not both constant
|
|
struct ComplexConstructor : public IntrinsicBinary {
|
|
using IntrinsicBinary::IntrinsicBinary;
|
|
};
|
|
|
|
struct DefinedBinary {
|
|
TUPLE_CLASS_BOILERPLATE(DefinedBinary);
|
|
std::tuple<DefinedOpName, common::Indirection<Expr>,
|
|
common::Indirection<Expr>>
|
|
t;
|
|
};
|
|
|
|
explicit Expr(Designator &&);
|
|
explicit Expr(FunctionReference &&);
|
|
|
|
// Filled in with expression after successful semantic analysis.
|
|
using TypedExpr = std::unique_ptr<evaluate::GenericExprWrapper,
|
|
common::Deleter<evaluate::GenericExprWrapper>>;
|
|
mutable TypedExpr typedExpr;
|
|
|
|
CharBlock source;
|
|
|
|
std::variant<common::Indirection<CharLiteralConstantSubstring>,
|
|
LiteralConstant, common::Indirection<Designator>, ArrayConstructor,
|
|
StructureConstructor, common::Indirection<FunctionReference>, Parentheses,
|
|
UnaryPlus, Negate, NOT, PercentLoc, DefinedUnary, Power, Multiply, Divide,
|
|
Add, Subtract, Concat, LT, LE, EQ, NE, GE, GT, AND, OR, EQV, NEQV, XOR,
|
|
DefinedBinary, ComplexConstructor>
|
|
u;
|
|
};
|
|
|
|
// R912 part-ref -> part-name [( section-subscript-list )] [image-selector]
|
|
struct PartRef {
|
|
BOILERPLATE(PartRef);
|
|
PartRef(Name &&n, std::list<SectionSubscript> &&ss,
|
|
std::optional<ImageSelector> &&is)
|
|
: name{std::move(n)},
|
|
subscripts(std::move(ss)), imageSelector{std::move(is)} {}
|
|
Name name;
|
|
std::list<SectionSubscript> subscripts;
|
|
std::optional<ImageSelector> imageSelector;
|
|
};
|
|
|
|
// R911 data-ref -> part-ref [% part-ref]...
|
|
struct DataRef {
|
|
UNION_CLASS_BOILERPLATE(DataRef);
|
|
explicit DataRef(std::list<PartRef> &&);
|
|
std::variant<Name, common::Indirection<StructureComponent>,
|
|
common::Indirection<ArrayElement>,
|
|
common::Indirection<CoindexedNamedObject>>
|
|
u;
|
|
};
|
|
|
|
// R908 substring -> parent-string ( substring-range )
|
|
// R909 parent-string ->
|
|
// scalar-variable-name | array-element | coindexed-named-object |
|
|
// scalar-structure-component | scalar-char-literal-constant |
|
|
// scalar-named-constant
|
|
// Substrings of character literals have been factored out into their
|
|
// own productions so that they can't appear as designators in any context
|
|
// other than a primary expression.
|
|
struct Substring {
|
|
TUPLE_CLASS_BOILERPLATE(Substring);
|
|
std::tuple<DataRef, SubstringRange> t;
|
|
};
|
|
|
|
struct CharLiteralConstantSubstring {
|
|
TUPLE_CLASS_BOILERPLATE(CharLiteralConstantSubstring);
|
|
std::tuple<CharLiteralConstant, SubstringRange> t;
|
|
};
|
|
|
|
// R901 designator -> object-name | array-element | array-section |
|
|
// coindexed-named-object | complex-part-designator |
|
|
// structure-component | substring
|
|
struct Designator {
|
|
UNION_CLASS_BOILERPLATE(Designator);
|
|
bool EndsInBareName() const;
|
|
CharBlock source;
|
|
std::variant<DataRef, Substring> u;
|
|
};
|
|
|
|
// R902 variable -> designator | function-reference
|
|
struct Variable {
|
|
UNION_CLASS_BOILERPLATE(Variable);
|
|
mutable Expr::TypedExpr typedExpr;
|
|
parser::CharBlock GetSource() const;
|
|
std::variant<common::Indirection<Designator>,
|
|
common::Indirection<FunctionReference>>
|
|
u;
|
|
};
|
|
|
|
// R904 logical-variable -> variable
|
|
// Appears only as part of scalar-logical-variable.
|
|
using ScalarLogicalVariable = Scalar<Logical<Variable>>;
|
|
|
|
// R906 default-char-variable -> variable
|
|
// Appears only as part of scalar-default-char-variable.
|
|
using ScalarDefaultCharVariable = Scalar<DefaultChar<Variable>>;
|
|
|
|
// R907 int-variable -> variable
|
|
// Appears only as part of scalar-int-variable.
|
|
using ScalarIntVariable = Scalar<Integer<Variable>>;
|
|
|
|
// R913 structure-component -> data-ref
|
|
struct StructureComponent {
|
|
BOILERPLATE(StructureComponent);
|
|
StructureComponent(DataRef &&dr, Name &&n)
|
|
: base{std::move(dr)}, component(std::move(n)) {}
|
|
DataRef base;
|
|
Name component;
|
|
};
|
|
|
|
// R1039 proc-component-ref -> scalar-variable % procedure-component-name
|
|
// C1027 constrains the scalar-variable to be a data-ref without coindices.
|
|
struct ProcComponentRef {
|
|
WRAPPER_CLASS_BOILERPLATE(ProcComponentRef, Scalar<StructureComponent>);
|
|
};
|
|
|
|
// R914 coindexed-named-object -> data-ref
|
|
struct CoindexedNamedObject {
|
|
BOILERPLATE(CoindexedNamedObject);
|
|
CoindexedNamedObject(DataRef &&dr, ImageSelector &&is)
|
|
: base{std::move(dr)}, imageSelector{std::move(is)} {}
|
|
DataRef base;
|
|
ImageSelector imageSelector;
|
|
};
|
|
|
|
// R917 array-element -> data-ref
|
|
struct ArrayElement {
|
|
BOILERPLATE(ArrayElement);
|
|
ArrayElement(DataRef &&dr, std::list<SectionSubscript> &&ss)
|
|
: base{std::move(dr)}, subscripts(std::move(ss)) {}
|
|
Substring ConvertToSubstring();
|
|
DataRef base;
|
|
std::list<SectionSubscript> subscripts;
|
|
};
|
|
|
|
// R933 allocate-object -> variable-name | structure-component
|
|
struct AllocateObject {
|
|
UNION_CLASS_BOILERPLATE(AllocateObject);
|
|
std::variant<Name, StructureComponent> u;
|
|
};
|
|
|
|
// R935 lower-bound-expr -> scalar-int-expr
|
|
// R936 upper-bound-expr -> scalar-int-expr
|
|
using BoundExpr = ScalarIntExpr;
|
|
|
|
// R934 allocate-shape-spec -> [lower-bound-expr :] upper-bound-expr
|
|
// R938 allocate-coshape-spec -> [lower-bound-expr :] upper-bound-expr
|
|
struct AllocateShapeSpec {
|
|
TUPLE_CLASS_BOILERPLATE(AllocateShapeSpec);
|
|
std::tuple<std::optional<BoundExpr>, BoundExpr> t;
|
|
};
|
|
|
|
using AllocateCoshapeSpec = AllocateShapeSpec;
|
|
|
|
// R937 allocate-coarray-spec ->
|
|
// [allocate-coshape-spec-list ,] [lower-bound-expr :] *
|
|
struct AllocateCoarraySpec {
|
|
TUPLE_CLASS_BOILERPLATE(AllocateCoarraySpec);
|
|
std::tuple<std::list<AllocateCoshapeSpec>, std::optional<BoundExpr>> t;
|
|
};
|
|
|
|
// R932 allocation ->
|
|
// allocate-object [( allocate-shape-spec-list )]
|
|
// [lbracket allocate-coarray-spec rbracket]
|
|
struct Allocation {
|
|
TUPLE_CLASS_BOILERPLATE(Allocation);
|
|
std::tuple<AllocateObject, std::list<AllocateShapeSpec>,
|
|
std::optional<AllocateCoarraySpec>>
|
|
t;
|
|
};
|
|
|
|
// R929 stat-variable -> scalar-int-variable
|
|
WRAPPER_CLASS(StatVariable, ScalarIntVariable);
|
|
|
|
// R930 errmsg-variable -> scalar-default-char-variable
|
|
// R1207 iomsg-variable -> scalar-default-char-variable
|
|
WRAPPER_CLASS(MsgVariable, ScalarDefaultCharVariable);
|
|
|
|
// R942 dealloc-opt -> STAT = stat-variable | ERRMSG = errmsg-variable
|
|
// R1165 sync-stat -> STAT = stat-variable | ERRMSG = errmsg-variable
|
|
struct StatOrErrmsg {
|
|
UNION_CLASS_BOILERPLATE(StatOrErrmsg);
|
|
std::variant<StatVariable, MsgVariable> u;
|
|
};
|
|
|
|
// R928 alloc-opt ->
|
|
// ERRMSG = errmsg-variable | MOLD = source-expr |
|
|
// SOURCE = source-expr | STAT = stat-variable
|
|
// R931 source-expr -> expr
|
|
struct AllocOpt {
|
|
UNION_CLASS_BOILERPLATE(AllocOpt);
|
|
WRAPPER_CLASS(Mold, common::Indirection<Expr>);
|
|
WRAPPER_CLASS(Source, common::Indirection<Expr>);
|
|
std::variant<Mold, Source, StatOrErrmsg> u;
|
|
};
|
|
|
|
// R927 allocate-stmt ->
|
|
// ALLOCATE ( [type-spec ::] allocation-list [, alloc-opt-list] )
|
|
struct AllocateStmt {
|
|
TUPLE_CLASS_BOILERPLATE(AllocateStmt);
|
|
std::tuple<std::optional<TypeSpec>, std::list<Allocation>,
|
|
std::list<AllocOpt>>
|
|
t;
|
|
};
|
|
|
|
// R940 pointer-object ->
|
|
// variable-name | structure-component | proc-pointer-name
|
|
struct PointerObject {
|
|
UNION_CLASS_BOILERPLATE(PointerObject);
|
|
std::variant<Name, StructureComponent> u;
|
|
};
|
|
|
|
// R939 nullify-stmt -> NULLIFY ( pointer-object-list )
|
|
WRAPPER_CLASS(NullifyStmt, std::list<PointerObject>);
|
|
|
|
// R941 deallocate-stmt ->
|
|
// DEALLOCATE ( allocate-object-list [, dealloc-opt-list] )
|
|
struct DeallocateStmt {
|
|
TUPLE_CLASS_BOILERPLATE(DeallocateStmt);
|
|
std::tuple<std::list<AllocateObject>, std::list<StatOrErrmsg>> t;
|
|
};
|
|
|
|
// R1032 assignment-stmt -> variable = expr
|
|
struct AssignmentStmt {
|
|
TUPLE_CLASS_BOILERPLATE(AssignmentStmt);
|
|
std::tuple<Variable, Expr> t;
|
|
};
|
|
|
|
// R1035 bounds-spec -> lower-bound-expr :
|
|
WRAPPER_CLASS(BoundsSpec, BoundExpr);
|
|
|
|
// R1036 bounds-remapping -> lower-bound-expr : upper-bound-expr
|
|
struct BoundsRemapping {
|
|
TUPLE_CLASS_BOILERPLATE(BoundsRemapping);
|
|
std::tuple<BoundExpr, BoundExpr> t;
|
|
};
|
|
|
|
// R1033 pointer-assignment-stmt ->
|
|
// data-pointer-object [( bounds-spec-list )] => data-target |
|
|
// data-pointer-object ( bounds-remapping-list ) => data-target |
|
|
// proc-pointer-object => proc-target
|
|
// R1034 data-pointer-object ->
|
|
// variable-name | scalar-variable % data-pointer-component-name
|
|
// R1038 proc-pointer-object -> proc-pointer-name | proc-component-ref
|
|
struct PointerAssignmentStmt {
|
|
struct Bounds {
|
|
UNION_CLASS_BOILERPLATE(Bounds);
|
|
std::variant<std::list<BoundsRemapping>, std::list<BoundsSpec>> u;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(PointerAssignmentStmt);
|
|
std::tuple<DataRef, Bounds, Expr> t;
|
|
};
|
|
|
|
// R1041 where-stmt -> WHERE ( mask-expr ) where-assignment-stmt
|
|
// R1045 where-assignment-stmt -> assignment-stmt
|
|
// R1046 mask-expr -> logical-expr
|
|
struct WhereStmt {
|
|
TUPLE_CLASS_BOILERPLATE(WhereStmt);
|
|
std::tuple<LogicalExpr, AssignmentStmt> t;
|
|
};
|
|
|
|
// R1043 where-construct-stmt -> [where-construct-name :] WHERE ( mask-expr )
|
|
struct WhereConstructStmt {
|
|
TUPLE_CLASS_BOILERPLATE(WhereConstructStmt);
|
|
std::tuple<std::optional<Name>, LogicalExpr> t;
|
|
};
|
|
|
|
// R1044 where-body-construct ->
|
|
// where-assignment-stmt | where-stmt | where-construct
|
|
struct WhereBodyConstruct {
|
|
UNION_CLASS_BOILERPLATE(WhereBodyConstruct);
|
|
std::variant<Statement<AssignmentStmt>, Statement<WhereStmt>,
|
|
common::Indirection<WhereConstruct>>
|
|
u;
|
|
};
|
|
|
|
// R1047 masked-elsewhere-stmt ->
|
|
// ELSEWHERE ( mask-expr ) [where-construct-name]
|
|
struct MaskedElsewhereStmt {
|
|
TUPLE_CLASS_BOILERPLATE(MaskedElsewhereStmt);
|
|
std::tuple<LogicalExpr, std::optional<Name>> t;
|
|
};
|
|
|
|
// R1048 elsewhere-stmt -> ELSEWHERE [where-construct-name]
|
|
WRAPPER_CLASS(ElsewhereStmt, std::optional<Name>);
|
|
|
|
// R1049 end-where-stmt -> END WHERE [where-construct-name]
|
|
WRAPPER_CLASS(EndWhereStmt, std::optional<Name>);
|
|
|
|
// R1042 where-construct ->
|
|
// where-construct-stmt [where-body-construct]...
|
|
// [masked-elsewhere-stmt [where-body-construct]...]...
|
|
// [elsewhere-stmt [where-body-construct]...] end-where-stmt
|
|
struct WhereConstruct {
|
|
struct MaskedElsewhere {
|
|
TUPLE_CLASS_BOILERPLATE(MaskedElsewhere);
|
|
std::tuple<Statement<MaskedElsewhereStmt>, std::list<WhereBodyConstruct>> t;
|
|
};
|
|
struct Elsewhere {
|
|
TUPLE_CLASS_BOILERPLATE(Elsewhere);
|
|
std::tuple<Statement<ElsewhereStmt>, std::list<WhereBodyConstruct>> t;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(WhereConstruct);
|
|
std::tuple<Statement<WhereConstructStmt>, std::list<WhereBodyConstruct>,
|
|
std::list<MaskedElsewhere>, std::optional<Elsewhere>,
|
|
Statement<EndWhereStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1051 forall-construct-stmt ->
|
|
// [forall-construct-name :] FORALL concurrent-header
|
|
struct ForallConstructStmt {
|
|
TUPLE_CLASS_BOILERPLATE(ForallConstructStmt);
|
|
std::tuple<std::optional<Name>, common::Indirection<ConcurrentHeader>> t;
|
|
};
|
|
|
|
// R1053 forall-assignment-stmt -> assignment-stmt | pointer-assignment-stmt
|
|
struct ForallAssignmentStmt {
|
|
UNION_CLASS_BOILERPLATE(ForallAssignmentStmt);
|
|
std::variant<AssignmentStmt, PointerAssignmentStmt> u;
|
|
};
|
|
|
|
// R1055 forall-stmt -> FORALL concurrent-header forall-assignment-stmt
|
|
struct ForallStmt {
|
|
TUPLE_CLASS_BOILERPLATE(ForallStmt);
|
|
std::tuple<common::Indirection<ConcurrentHeader>,
|
|
UnlabeledStatement<ForallAssignmentStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1052 forall-body-construct ->
|
|
// forall-assignment-stmt | where-stmt | where-construct |
|
|
// forall-construct | forall-stmt
|
|
struct ForallBodyConstruct {
|
|
UNION_CLASS_BOILERPLATE(ForallBodyConstruct);
|
|
std::variant<Statement<ForallAssignmentStmt>, Statement<WhereStmt>,
|
|
WhereConstruct, common::Indirection<ForallConstruct>,
|
|
Statement<ForallStmt>>
|
|
u;
|
|
};
|
|
|
|
// R1054 end-forall-stmt -> END FORALL [forall-construct-name]
|
|
WRAPPER_CLASS(EndForallStmt, std::optional<Name>);
|
|
|
|
// R1050 forall-construct ->
|
|
// forall-construct-stmt [forall-body-construct]... end-forall-stmt
|
|
struct ForallConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(ForallConstruct);
|
|
std::tuple<Statement<ForallConstructStmt>, std::list<ForallBodyConstruct>,
|
|
Statement<EndForallStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1101 block -> [execution-part-construct]...
|
|
using Block = std::list<ExecutionPartConstruct>;
|
|
|
|
// R1105 selector -> expr | variable
|
|
struct Selector {
|
|
UNION_CLASS_BOILERPLATE(Selector);
|
|
std::variant<Expr, Variable> u;
|
|
};
|
|
|
|
// R1104 association -> associate-name => selector
|
|
struct Association {
|
|
TUPLE_CLASS_BOILERPLATE(Association);
|
|
std::tuple<Name, Selector> t;
|
|
};
|
|
|
|
// R1103 associate-stmt ->
|
|
// [associate-construct-name :] ASSOCIATE ( association-list )
|
|
struct AssociateStmt {
|
|
TUPLE_CLASS_BOILERPLATE(AssociateStmt);
|
|
std::tuple<std::optional<Name>, std::list<Association>> t;
|
|
};
|
|
|
|
// R1106 end-associate-stmt -> END ASSOCIATE [associate-construct-name]
|
|
WRAPPER_CLASS(EndAssociateStmt, std::optional<Name>);
|
|
|
|
// R1102 associate-construct -> associate-stmt block end-associate-stmt
|
|
struct AssociateConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(AssociateConstruct);
|
|
std::tuple<Statement<AssociateStmt>, Block, Statement<EndAssociateStmt>> t;
|
|
};
|
|
|
|
// R1108 block-stmt -> [block-construct-name :] BLOCK
|
|
WRAPPER_CLASS(BlockStmt, std::optional<Name>);
|
|
|
|
// R1110 end-block-stmt -> END BLOCK [block-construct-name]
|
|
WRAPPER_CLASS(EndBlockStmt, std::optional<Name>);
|
|
|
|
// R1109 block-specification-part ->
|
|
// [use-stmt]... [import-stmt]...
|
|
// [[declaration-construct]... specification-construct]
|
|
WRAPPER_CLASS(BlockSpecificationPart, SpecificationPart);
|
|
// TODO: Because BlockSpecificationPart just wraps the more general
|
|
// SpecificationPart, it can misrecognize an ImplicitPart as part of
|
|
// the BlockSpecificationPart during parsing, and we have to detect and
|
|
// flag such usage in semantics.
|
|
// TODO: error if any COMMON, EQUIVALENCE, INTENT, NAMELIST, OPTIONAL,
|
|
// VALUE, ENTRY, SAVE /common/, or statement function definition statement
|
|
// appears in a block-specification part (C1107, C1570).
|
|
|
|
// R1107 block-construct ->
|
|
// block-stmt [block-specification-part] block end-block-stmt
|
|
struct BlockConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(BlockConstruct);
|
|
std::tuple<Statement<BlockStmt>, BlockSpecificationPart, Block,
|
|
Statement<EndBlockStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1113 coarray-association -> codimension-decl => selector
|
|
struct CoarrayAssociation {
|
|
TUPLE_CLASS_BOILERPLATE(CoarrayAssociation);
|
|
std::tuple<CodimensionDecl, Selector> t;
|
|
};
|
|
|
|
// R1112 change-team-stmt ->
|
|
// [team-construct-name :] CHANGE TEAM
|
|
// ( team-value [, coarray-association-list] [, sync-stat-list] )
|
|
struct ChangeTeamStmt {
|
|
TUPLE_CLASS_BOILERPLATE(ChangeTeamStmt);
|
|
std::tuple<std::optional<Name>, TeamValue, std::list<CoarrayAssociation>,
|
|
std::list<StatOrErrmsg>>
|
|
t;
|
|
};
|
|
|
|
// R1114 end-change-team-stmt ->
|
|
// END TEAM [( [sync-stat-list] )] [team-construct-name]
|
|
struct EndChangeTeamStmt {
|
|
TUPLE_CLASS_BOILERPLATE(EndChangeTeamStmt);
|
|
std::tuple<std::list<StatOrErrmsg>, std::optional<Name>> t;
|
|
};
|
|
|
|
// R1111 change-team-construct -> change-team-stmt block end-change-team-stmt
|
|
struct ChangeTeamConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(ChangeTeamConstruct);
|
|
std::tuple<Statement<ChangeTeamStmt>, Block, Statement<EndChangeTeamStmt>> t;
|
|
};
|
|
|
|
// R1117 critical-stmt ->
|
|
// [critical-construct-name :] CRITICAL [( [sync-stat-list] )]
|
|
struct CriticalStmt {
|
|
TUPLE_CLASS_BOILERPLATE(CriticalStmt);
|
|
std::tuple<std::optional<Name>, std::list<StatOrErrmsg>> t;
|
|
};
|
|
|
|
// R1118 end-critical-stmt -> END CRITICAL [critical-construct-name]
|
|
WRAPPER_CLASS(EndCriticalStmt, std::optional<Name>);
|
|
|
|
// R1116 critical-construct -> critical-stmt block end-critical-stmt
|
|
struct CriticalConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(CriticalConstruct);
|
|
std::tuple<Statement<CriticalStmt>, Block, Statement<EndCriticalStmt>> t;
|
|
};
|
|
|
|
// R1126 concurrent-control ->
|
|
// index-name = concurrent-limit : concurrent-limit [: concurrent-step]
|
|
// R1127 concurrent-limit -> scalar-int-expr
|
|
// R1128 concurrent-step -> scalar-int-expr
|
|
struct ConcurrentControl {
|
|
TUPLE_CLASS_BOILERPLATE(ConcurrentControl);
|
|
std::tuple<Name, ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>>
|
|
t;
|
|
};
|
|
|
|
// R1125 concurrent-header ->
|
|
// ( [integer-type-spec ::] concurrent-control-list
|
|
// [, scalar-mask-expr] )
|
|
struct ConcurrentHeader {
|
|
TUPLE_CLASS_BOILERPLATE(ConcurrentHeader);
|
|
std::tuple<std::optional<IntegerTypeSpec>, std::list<ConcurrentControl>,
|
|
std::optional<ScalarLogicalExpr>>
|
|
t;
|
|
};
|
|
|
|
// R1130 locality-spec ->
|
|
// LOCAL ( variable-name-list ) | LOCAL_INIT ( variable-name-list ) |
|
|
// SHARED ( variable-name-list ) | DEFAULT ( NONE )
|
|
struct LocalitySpec {
|
|
UNION_CLASS_BOILERPLATE(LocalitySpec);
|
|
WRAPPER_CLASS(Local, std::list<Name>);
|
|
WRAPPER_CLASS(LocalInit, std::list<Name>);
|
|
WRAPPER_CLASS(Shared, std::list<Name>);
|
|
EMPTY_CLASS(DefaultNone);
|
|
std::variant<Local, LocalInit, Shared, DefaultNone> u;
|
|
};
|
|
|
|
// R1123 loop-control ->
|
|
// [,] do-variable = scalar-int-expr , scalar-int-expr
|
|
// [, scalar-int-expr] |
|
|
// [,] WHILE ( scalar-logical-expr ) |
|
|
// [,] CONCURRENT concurrent-header concurrent-locality
|
|
// R1129 concurrent-locality -> [locality-spec]...
|
|
struct LoopControl {
|
|
UNION_CLASS_BOILERPLATE(LoopControl);
|
|
struct Concurrent {
|
|
TUPLE_CLASS_BOILERPLATE(Concurrent);
|
|
std::tuple<ConcurrentHeader, std::list<LocalitySpec>> t;
|
|
};
|
|
using Bounds = LoopBounds<ScalarName, ScalarExpr>;
|
|
std::variant<Bounds, ScalarLogicalExpr, Concurrent> u;
|
|
};
|
|
|
|
// R1121 label-do-stmt -> [do-construct-name :] DO label [loop-control]
|
|
struct LabelDoStmt {
|
|
TUPLE_CLASS_BOILERPLATE(LabelDoStmt);
|
|
std::tuple<std::optional<Name>, Label, std::optional<LoopControl>> t;
|
|
};
|
|
|
|
// R1122 nonlabel-do-stmt -> [do-construct-name :] DO [loop-control]
|
|
struct NonLabelDoStmt {
|
|
TUPLE_CLASS_BOILERPLATE(NonLabelDoStmt);
|
|
std::tuple<std::optional<Name>, std::optional<LoopControl>> t;
|
|
};
|
|
|
|
// R1132 end-do-stmt -> END DO [do-construct-name]
|
|
WRAPPER_CLASS(EndDoStmt, std::optional<Name>);
|
|
|
|
// R1131 end-do -> end-do-stmt | continue-stmt
|
|
|
|
// R1119 do-construct -> do-stmt block end-do
|
|
// R1120 do-stmt -> nonlabel-do-stmt | label-do-stmt
|
|
// TODO: deprecated: DO loop ending on statement types other than END DO and
|
|
// CONTINUE; multiple "label DO" loops ending on the same label
|
|
struct DoConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(DoConstruct);
|
|
const std::optional<LoopControl> &GetLoopControl() const;
|
|
bool IsDoNormal() const;
|
|
bool IsDoWhile() const;
|
|
bool IsDoConcurrent() const;
|
|
std::tuple<Statement<NonLabelDoStmt>, Block, Statement<EndDoStmt>> t;
|
|
};
|
|
|
|
// R1133 cycle-stmt -> CYCLE [do-construct-name]
|
|
WRAPPER_CLASS(CycleStmt, std::optional<Name>);
|
|
|
|
// R1135 if-then-stmt -> [if-construct-name :] IF ( scalar-logical-expr ) THEN
|
|
struct IfThenStmt {
|
|
TUPLE_CLASS_BOILERPLATE(IfThenStmt);
|
|
std::tuple<std::optional<Name>, ScalarLogicalExpr> t;
|
|
};
|
|
|
|
// R1136 else-if-stmt ->
|
|
// ELSE IF ( scalar-logical-expr ) THEN [if-construct-name]
|
|
struct ElseIfStmt {
|
|
TUPLE_CLASS_BOILERPLATE(ElseIfStmt);
|
|
std::tuple<ScalarLogicalExpr, std::optional<Name>> t;
|
|
};
|
|
|
|
// R1137 else-stmt -> ELSE [if-construct-name]
|
|
WRAPPER_CLASS(ElseStmt, std::optional<Name>);
|
|
|
|
// R1138 end-if-stmt -> END IF [if-construct-name]
|
|
WRAPPER_CLASS(EndIfStmt, std::optional<Name>);
|
|
|
|
// R1134 if-construct ->
|
|
// if-then-stmt block [else-if-stmt block]...
|
|
// [else-stmt block] end-if-stmt
|
|
struct IfConstruct {
|
|
struct ElseIfBlock {
|
|
TUPLE_CLASS_BOILERPLATE(ElseIfBlock);
|
|
std::tuple<Statement<ElseIfStmt>, Block> t;
|
|
};
|
|
struct ElseBlock {
|
|
TUPLE_CLASS_BOILERPLATE(ElseBlock);
|
|
std::tuple<Statement<ElseStmt>, Block> t;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(IfConstruct);
|
|
std::tuple<Statement<IfThenStmt>, Block, std::list<ElseIfBlock>,
|
|
std::optional<ElseBlock>, Statement<EndIfStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1139 if-stmt -> IF ( scalar-logical-expr ) action-stmt
|
|
struct IfStmt {
|
|
TUPLE_CLASS_BOILERPLATE(IfStmt);
|
|
std::tuple<ScalarLogicalExpr, UnlabeledStatement<ActionStmt>> t;
|
|
};
|
|
|
|
// R1141 select-case-stmt -> [case-construct-name :] SELECT CASE ( case-expr )
|
|
// R1144 case-expr -> scalar-expr
|
|
struct SelectCaseStmt {
|
|
TUPLE_CLASS_BOILERPLATE(SelectCaseStmt);
|
|
std::tuple<std::optional<Name>, Scalar<Expr>> t;
|
|
};
|
|
|
|
// R1147 case-value -> scalar-constant-expr
|
|
using CaseValue = Scalar<ConstantExpr>;
|
|
|
|
// R1146 case-value-range ->
|
|
// case-value | case-value : | : case-value | case-value : case-value
|
|
struct CaseValueRange {
|
|
UNION_CLASS_BOILERPLATE(CaseValueRange);
|
|
struct Range {
|
|
BOILERPLATE(Range);
|
|
Range(std::optional<CaseValue> &&l, std::optional<CaseValue> &&u)
|
|
: lower{std::move(l)}, upper{std::move(u)} {}
|
|
std::optional<CaseValue> lower, upper; // not both missing
|
|
};
|
|
std::variant<CaseValue, Range> u;
|
|
};
|
|
|
|
// R1145 case-selector -> ( case-value-range-list ) | DEFAULT
|
|
EMPTY_CLASS(Default);
|
|
|
|
struct CaseSelector {
|
|
UNION_CLASS_BOILERPLATE(CaseSelector);
|
|
std::variant<std::list<CaseValueRange>, Default> u;
|
|
};
|
|
|
|
// R1142 case-stmt -> CASE case-selector [case-construct-name]
|
|
struct CaseStmt {
|
|
TUPLE_CLASS_BOILERPLATE(CaseStmt);
|
|
std::tuple<CaseSelector, std::optional<Name>> t;
|
|
};
|
|
|
|
// R1143 end-select-stmt -> END SELECT [case-construct-name]
|
|
// R1151 end-select-rank-stmt -> END SELECT [select-construct-name]
|
|
// R1155 end-select-type-stmt -> END SELECT [select-construct-name]
|
|
WRAPPER_CLASS(EndSelectStmt, std::optional<Name>);
|
|
|
|
// R1140 case-construct ->
|
|
// select-case-stmt [case-stmt block]... end-select-stmt
|
|
struct CaseConstruct {
|
|
struct Case {
|
|
TUPLE_CLASS_BOILERPLATE(Case);
|
|
std::tuple<Statement<CaseStmt>, Block> t;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(CaseConstruct);
|
|
std::tuple<Statement<SelectCaseStmt>, std::list<Case>,
|
|
Statement<EndSelectStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1149 select-rank-stmt ->
|
|
// [select-construct-name :] SELECT RANK
|
|
// ( [associate-name =>] selector )
|
|
struct SelectRankStmt {
|
|
TUPLE_CLASS_BOILERPLATE(SelectRankStmt);
|
|
std::tuple<std::optional<Name>, std::optional<Name>, Selector> t;
|
|
};
|
|
|
|
// R1150 select-rank-case-stmt ->
|
|
// RANK ( scalar-int-constant-expr ) [select-construct-name] |
|
|
// RANK ( * ) [select-construct-name] |
|
|
// RANK DEFAULT [select-construct-name]
|
|
struct SelectRankCaseStmt {
|
|
struct Rank {
|
|
UNION_CLASS_BOILERPLATE(Rank);
|
|
std::variant<ScalarIntConstantExpr, Star, Default> u;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(SelectRankCaseStmt);
|
|
std::tuple<Rank, std::optional<Name>> t;
|
|
};
|
|
|
|
// R1148 select-rank-construct ->
|
|
// select-rank-stmt [select-rank-case-stmt block]...
|
|
// end-select-rank-stmt
|
|
struct SelectRankConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(SelectRankConstruct);
|
|
struct RankCase {
|
|
TUPLE_CLASS_BOILERPLATE(RankCase);
|
|
std::tuple<Statement<SelectRankCaseStmt>, Block> t;
|
|
};
|
|
std::tuple<Statement<SelectRankStmt>, std::list<RankCase>,
|
|
Statement<EndSelectStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1153 select-type-stmt ->
|
|
// [select-construct-name :] SELECT TYPE
|
|
// ( [associate-name =>] selector )
|
|
struct SelectTypeStmt {
|
|
TUPLE_CLASS_BOILERPLATE(SelectTypeStmt);
|
|
std::tuple<std::optional<Name>, std::optional<Name>, Selector> t;
|
|
};
|
|
|
|
// R1154 type-guard-stmt ->
|
|
// TYPE IS ( type-spec ) [select-construct-name] |
|
|
// CLASS IS ( derived-type-spec ) [select-construct-name] |
|
|
// CLASS DEFAULT [select-construct-name]
|
|
struct TypeGuardStmt {
|
|
struct Guard {
|
|
UNION_CLASS_BOILERPLATE(Guard);
|
|
std::variant<TypeSpec, DerivedTypeSpec, Default> u;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(TypeGuardStmt);
|
|
std::tuple<Guard, std::optional<Name>> t;
|
|
};
|
|
|
|
// R1152 select-type-construct ->
|
|
// select-type-stmt [type-guard-stmt block]... end-select-type-stmt
|
|
struct SelectTypeConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(SelectTypeConstruct);
|
|
struct TypeCase {
|
|
TUPLE_CLASS_BOILERPLATE(TypeCase);
|
|
std::tuple<Statement<TypeGuardStmt>, Block> t;
|
|
};
|
|
std::tuple<Statement<SelectTypeStmt>, std::list<TypeCase>,
|
|
Statement<EndSelectStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1156 exit-stmt -> EXIT [construct-name]
|
|
WRAPPER_CLASS(ExitStmt, std::optional<Name>);
|
|
|
|
// R1157 goto-stmt -> GO TO label
|
|
WRAPPER_CLASS(GotoStmt, Label);
|
|
|
|
// R1158 computed-goto-stmt -> GO TO ( label-list ) [,] scalar-int-expr
|
|
struct ComputedGotoStmt {
|
|
TUPLE_CLASS_BOILERPLATE(ComputedGotoStmt);
|
|
std::tuple<std::list<Label>, ScalarIntExpr> t;
|
|
};
|
|
|
|
// R1162 stop-code -> scalar-default-char-expr | scalar-int-expr
|
|
// We can't distinguish character expressions from integer
|
|
// expressions during parsing, so we just parse an expr and
|
|
// check its type later.
|
|
WRAPPER_CLASS(StopCode, Scalar<Expr>);
|
|
|
|
// R1160 stop-stmt -> STOP [stop-code] [, QUIET = scalar-logical-expr]
|
|
// R1161 error-stop-stmt ->
|
|
// ERROR STOP [stop-code] [, QUIET = scalar-logical-expr]
|
|
struct StopStmt {
|
|
ENUM_CLASS(Kind, Stop, ErrorStop)
|
|
TUPLE_CLASS_BOILERPLATE(StopStmt);
|
|
std::tuple<Kind, std::optional<StopCode>, std::optional<ScalarLogicalExpr>> t;
|
|
};
|
|
|
|
// R1164 sync-all-stmt -> SYNC ALL [( [sync-stat-list] )]
|
|
WRAPPER_CLASS(SyncAllStmt, std::list<StatOrErrmsg>);
|
|
|
|
// R1166 sync-images-stmt -> SYNC IMAGES ( image-set [, sync-stat-list] )
|
|
// R1167 image-set -> int-expr | *
|
|
struct SyncImagesStmt {
|
|
struct ImageSet {
|
|
UNION_CLASS_BOILERPLATE(ImageSet);
|
|
std::variant<IntExpr, Star> u;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(SyncImagesStmt);
|
|
std::tuple<ImageSet, std::list<StatOrErrmsg>> t;
|
|
};
|
|
|
|
// R1168 sync-memory-stmt -> SYNC MEMORY [( [sync-stat-list] )]
|
|
WRAPPER_CLASS(SyncMemoryStmt, std::list<StatOrErrmsg>);
|
|
|
|
// R1169 sync-team-stmt -> SYNC TEAM ( team-value [, sync-stat-list] )
|
|
struct SyncTeamStmt {
|
|
TUPLE_CLASS_BOILERPLATE(SyncTeamStmt);
|
|
std::tuple<TeamValue, std::list<StatOrErrmsg>> t;
|
|
};
|
|
|
|
// R1171 event-variable -> scalar-variable
|
|
using EventVariable = Scalar<Variable>;
|
|
|
|
// R1170 event-post-stmt -> EVENT POST ( event-variable [, sync-stat-list] )
|
|
struct EventPostStmt {
|
|
TUPLE_CLASS_BOILERPLATE(EventPostStmt);
|
|
std::tuple<EventVariable, std::list<StatOrErrmsg>> t;
|
|
};
|
|
|
|
// R1172 event-wait-stmt ->
|
|
// EVENT WAIT ( event-variable [, event-wait-spec-list] )
|
|
// R1173 event-wait-spec -> until-spec | sync-stat
|
|
// R1174 until-spec -> UNTIL_COUNT = scalar-int-expr
|
|
struct EventWaitStmt {
|
|
struct EventWaitSpec {
|
|
UNION_CLASS_BOILERPLATE(EventWaitSpec);
|
|
std::variant<ScalarIntExpr, StatOrErrmsg> u;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(EventWaitStmt);
|
|
std::tuple<EventVariable, std::list<EventWaitSpec>> t;
|
|
};
|
|
|
|
// R1177 team-variable -> scalar-variable
|
|
using TeamVariable = Scalar<Variable>;
|
|
|
|
// R1175 form-team-stmt ->
|
|
// FORM TEAM ( team-number , team-variable [, form-team-spec-list] )
|
|
// R1176 team-number -> scalar-int-expr
|
|
// R1178 form-team-spec -> NEW_INDEX = scalar-int-expr | sync-stat
|
|
struct FormTeamStmt {
|
|
struct FormTeamSpec {
|
|
UNION_CLASS_BOILERPLATE(FormTeamSpec);
|
|
std::variant<ScalarIntExpr, StatOrErrmsg> u;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(FormTeamStmt);
|
|
std::tuple<ScalarIntExpr, TeamVariable, std::list<FormTeamSpec>> t;
|
|
};
|
|
|
|
// R1182 lock-variable -> scalar-variable
|
|
using LockVariable = Scalar<Variable>;
|
|
|
|
// R1179 lock-stmt -> LOCK ( lock-variable [, lock-stat-list] )
|
|
// R1180 lock-stat -> ACQUIRED_LOCK = scalar-logical-variable | sync-stat
|
|
struct LockStmt {
|
|
struct LockStat {
|
|
UNION_CLASS_BOILERPLATE(LockStat);
|
|
std::variant<Scalar<Logical<Variable>>, StatOrErrmsg> u;
|
|
};
|
|
TUPLE_CLASS_BOILERPLATE(LockStmt);
|
|
std::tuple<LockVariable, std::list<LockStat>> t;
|
|
};
|
|
|
|
// R1181 unlock-stmt -> UNLOCK ( lock-variable [, sync-stat-list] )
|
|
struct UnlockStmt {
|
|
TUPLE_CLASS_BOILERPLATE(UnlockStmt);
|
|
std::tuple<LockVariable, std::list<StatOrErrmsg>> t;
|
|
};
|
|
|
|
// R1202 file-unit-number -> scalar-int-expr
|
|
WRAPPER_CLASS(FileUnitNumber, ScalarIntExpr);
|
|
|
|
// R1201 io-unit -> file-unit-number | * | internal-file-variable
|
|
// R1203 internal-file-variable -> char-variable
|
|
// R905 char-variable -> variable
|
|
// When Variable appears as an IoUnit, it must be character of a default,
|
|
// ASCII, or Unicode kind; this constraint is not automatically checked.
|
|
// The parse is ambiguous and is repaired if necessary once the types of
|
|
// symbols are known.
|
|
struct IoUnit {
|
|
UNION_CLASS_BOILERPLATE(IoUnit);
|
|
std::variant<Variable, FileUnitNumber, Star> u;
|
|
};
|
|
|
|
// R1206 file-name-expr -> scalar-default-char-expr
|
|
using FileNameExpr = ScalarDefaultCharExpr;
|
|
|
|
// R1205 connect-spec ->
|
|
// [UNIT =] file-unit-number | ACCESS = scalar-default-char-expr |
|
|
// ACTION = scalar-default-char-expr |
|
|
// ASYNCHRONOUS = scalar-default-char-expr |
|
|
// BLANK = scalar-default-char-expr |
|
|
// DECIMAL = scalar-default-char-expr |
|
|
// DELIM = scalar-default-char-expr |
|
|
// ENCODING = scalar-default-char-expr | ERR = label |
|
|
// FILE = file-name-expr | FORM = scalar-default-char-expr |
|
|
// IOMSG = iomsg-variable | IOSTAT = scalar-int-variable |
|
|
// NEWUNIT = scalar-int-variable | PAD = scalar-default-char-expr |
|
|
// POSITION = scalar-default-char-expr | RECL = scalar-int-expr |
|
|
// ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr |
|
|
// STATUS = scalar-default-char-expr
|
|
// @ | CONVERT = scalar-default-char-variable
|
|
// | DISPOSE = scalar-default-char-variable
|
|
WRAPPER_CLASS(StatusExpr, ScalarDefaultCharExpr);
|
|
WRAPPER_CLASS(ErrLabel, Label);
|
|
|
|
struct ConnectSpec {
|
|
UNION_CLASS_BOILERPLATE(ConnectSpec);
|
|
struct CharExpr {
|
|
ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
|
|
Encoding, Form, Pad, Position, Round, Sign,
|
|
/* extensions: */ Convert, Dispose)
|
|
TUPLE_CLASS_BOILERPLATE(CharExpr);
|
|
std::tuple<Kind, ScalarDefaultCharExpr> t;
|
|
};
|
|
WRAPPER_CLASS(Recl, ScalarIntExpr);
|
|
WRAPPER_CLASS(Newunit, ScalarIntVariable);
|
|
std::variant<FileUnitNumber, FileNameExpr, CharExpr, MsgVariable,
|
|
StatVariable, Recl, Newunit, ErrLabel, StatusExpr>
|
|
u;
|
|
};
|
|
|
|
// R1204 open-stmt -> OPEN ( connect-spec-list )
|
|
WRAPPER_CLASS(OpenStmt, std::list<ConnectSpec>);
|
|
|
|
// R1208 close-stmt -> CLOSE ( close-spec-list )
|
|
// R1209 close-spec ->
|
|
// [UNIT =] file-unit-number | IOSTAT = scalar-int-variable |
|
|
// IOMSG = iomsg-variable | ERR = label |
|
|
// STATUS = scalar-default-char-expr
|
|
struct CloseStmt {
|
|
struct CloseSpec {
|
|
UNION_CLASS_BOILERPLATE(CloseSpec);
|
|
std::variant<FileUnitNumber, StatVariable, MsgVariable, ErrLabel,
|
|
StatusExpr>
|
|
u;
|
|
};
|
|
WRAPPER_CLASS_BOILERPLATE(CloseStmt, std::list<CloseSpec>);
|
|
};
|
|
|
|
// R1215 format -> default-char-expr | label | *
|
|
struct Format {
|
|
UNION_CLASS_BOILERPLATE(Format);
|
|
std::variant<DefaultCharExpr, Label, Star> u;
|
|
};
|
|
|
|
// R1214 id-variable -> scalar-int-variable
|
|
WRAPPER_CLASS(IdVariable, ScalarIntVariable);
|
|
|
|
// R1213 io-control-spec ->
|
|
// [UNIT =] io-unit | [FMT =] format | [NML =] namelist-group-name |
|
|
// ADVANCE = scalar-default-char-expr |
|
|
// ASYNCHRONOUS = scalar-default-char-constant-expr |
|
|
// BLANK = scalar-default-char-expr |
|
|
// DECIMAL = scalar-default-char-expr |
|
|
// DELIM = scalar-default-char-expr | END = label | EOR = label |
|
|
// ERR = label | ID = id-variable | IOMSG = iomsg-variable |
|
|
// IOSTAT = scalar-int-variable | PAD = scalar-default-char-expr |
|
|
// POS = scalar-int-expr | REC = scalar-int-expr |
|
|
// ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr |
|
|
// SIZE = scalar-int-variable
|
|
WRAPPER_CLASS(EndLabel, Label);
|
|
WRAPPER_CLASS(EorLabel, Label);
|
|
struct IoControlSpec {
|
|
UNION_CLASS_BOILERPLATE(IoControlSpec);
|
|
struct CharExpr {
|
|
ENUM_CLASS(Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign)
|
|
TUPLE_CLASS_BOILERPLATE(CharExpr);
|
|
std::tuple<Kind, ScalarDefaultCharExpr> t;
|
|
};
|
|
WRAPPER_CLASS(Asynchronous, ScalarDefaultCharConstantExpr);
|
|
WRAPPER_CLASS(Pos, ScalarIntExpr);
|
|
WRAPPER_CLASS(Rec, ScalarIntExpr);
|
|
WRAPPER_CLASS(Size, ScalarIntVariable);
|
|
std::variant<IoUnit, Format, Name, CharExpr, Asynchronous, EndLabel, EorLabel,
|
|
ErrLabel, IdVariable, MsgVariable, StatVariable, Pos, Rec, Size>
|
|
u;
|
|
};
|
|
|
|
// R1216 input-item -> variable | io-implied-do
|
|
struct InputItem {
|
|
UNION_CLASS_BOILERPLATE(InputItem);
|
|
std::variant<Variable, common::Indirection<InputImpliedDo>> u;
|
|
};
|
|
|
|
// R1210 read-stmt ->
|
|
// READ ( io-control-spec-list ) [input-item-list] |
|
|
// READ format [, input-item-list]
|
|
struct ReadStmt {
|
|
BOILERPLATE(ReadStmt);
|
|
ReadStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
|
|
std::list<IoControlSpec> &&cs, std::list<InputItem> &&its)
|
|
: iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
|
|
items(std::move(its)) {}
|
|
std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
|
|
// followed by untagged format/namelist
|
|
std::optional<Format> format; // if second in controls without FMT=/NML=, or
|
|
// no (io-control-spec-list); might be
|
|
// an untagged namelist group name
|
|
std::list<IoControlSpec> controls;
|
|
std::list<InputItem> items;
|
|
};
|
|
|
|
// R1217 output-item -> expr | io-implied-do
|
|
struct OutputItem {
|
|
UNION_CLASS_BOILERPLATE(OutputItem);
|
|
std::variant<Expr, common::Indirection<OutputImpliedDo>> u;
|
|
};
|
|
|
|
// R1211 write-stmt -> WRITE ( io-control-spec-list ) [output-item-list]
|
|
struct WriteStmt {
|
|
BOILERPLATE(WriteStmt);
|
|
WriteStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
|
|
std::list<IoControlSpec> &&cs, std::list<OutputItem> &&its)
|
|
: iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
|
|
items(std::move(its)) {}
|
|
std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
|
|
// followed by untagged format/namelist
|
|
std::optional<Format> format; // if second in controls without FMT=/NML=;
|
|
// might be an untagged namelist group, too
|
|
std::list<IoControlSpec> controls;
|
|
std::list<OutputItem> items;
|
|
};
|
|
|
|
// R1212 print-stmt PRINT format [, output-item-list]
|
|
struct PrintStmt {
|
|
TUPLE_CLASS_BOILERPLATE(PrintStmt);
|
|
std::tuple<Format, std::list<OutputItem>> t;
|
|
};
|
|
|
|
// R1220 io-implied-do-control ->
|
|
// do-variable = scalar-int-expr , scalar-int-expr [, scalar-int-expr]
|
|
using IoImpliedDoControl = LoopBounds<DoVariable, ScalarIntExpr>;
|
|
|
|
// R1218 io-implied-do -> ( io-implied-do-object-list , io-implied-do-control )
|
|
// R1219 io-implied-do-object -> input-item | output-item
|
|
struct InputImpliedDo {
|
|
TUPLE_CLASS_BOILERPLATE(InputImpliedDo);
|
|
std::tuple<std::list<InputItem>, IoImpliedDoControl> t;
|
|
};
|
|
|
|
struct OutputImpliedDo {
|
|
TUPLE_CLASS_BOILERPLATE(OutputImpliedDo);
|
|
std::tuple<std::list<OutputItem>, IoImpliedDoControl> t;
|
|
};
|
|
|
|
// R1223 wait-spec ->
|
|
// [UNIT =] file-unit-number | END = label | EOR = label | ERR = label |
|
|
// ID = scalar-int-expr | IOMSG = iomsg-variable |
|
|
// IOSTAT = scalar-int-variable
|
|
WRAPPER_CLASS(IdExpr, ScalarIntExpr);
|
|
struct WaitSpec {
|
|
UNION_CLASS_BOILERPLATE(WaitSpec);
|
|
std::variant<FileUnitNumber, EndLabel, EorLabel, ErrLabel, IdExpr,
|
|
MsgVariable, StatVariable>
|
|
u;
|
|
};
|
|
|
|
// R1222 wait-stmt -> WAIT ( wait-spec-list )
|
|
WRAPPER_CLASS(WaitStmt, std::list<WaitSpec>);
|
|
|
|
// R1227 position-spec ->
|
|
// [UNIT =] file-unit-number | IOMSG = iomsg-variable |
|
|
// IOSTAT = scalar-int-variable | ERR = label
|
|
// R1229 flush-spec ->
|
|
// [UNIT =] file-unit-number | IOSTAT = scalar-int-variable |
|
|
// IOMSG = iomsg-variable | ERR = label
|
|
struct PositionOrFlushSpec {
|
|
UNION_CLASS_BOILERPLATE(PositionOrFlushSpec);
|
|
std::variant<FileUnitNumber, MsgVariable, StatVariable, ErrLabel> u;
|
|
};
|
|
|
|
// R1224 backspace-stmt ->
|
|
// BACKSPACE file-unit-number | BACKSPACE ( position-spec-list )
|
|
WRAPPER_CLASS(BackspaceStmt, std::list<PositionOrFlushSpec>);
|
|
|
|
// R1225 endfile-stmt ->
|
|
// ENDFILE file-unit-number | ENDFILE ( position-spec-list )
|
|
WRAPPER_CLASS(EndfileStmt, std::list<PositionOrFlushSpec>);
|
|
|
|
// R1226 rewind-stmt -> REWIND file-unit-number | REWIND ( position-spec-list )
|
|
WRAPPER_CLASS(RewindStmt, std::list<PositionOrFlushSpec>);
|
|
|
|
// R1228 flush-stmt -> FLUSH file-unit-number | FLUSH ( flush-spec-list )
|
|
WRAPPER_CLASS(FlushStmt, std::list<PositionOrFlushSpec>);
|
|
|
|
// R1231 inquire-spec ->
|
|
// [UNIT =] file-unit-number | FILE = file-name-expr |
|
|
// ACCESS = scalar-default-char-variable |
|
|
// ACTION = scalar-default-char-variable |
|
|
// ASYNCHRONOUS = scalar-default-char-variable |
|
|
// BLANK = scalar-default-char-variable |
|
|
// DECIMAL = scalar-default-char-variable |
|
|
// DELIM = scalar-default-char-variable |
|
|
// DIRECT = scalar-default-char-variable |
|
|
// ENCODING = scalar-default-char-variable |
|
|
// ERR = label | EXIST = scalar-logical-variable |
|
|
// FORM = scalar-default-char-variable |
|
|
// FORMATTED = scalar-default-char-variable |
|
|
// ID = scalar-int-expr | IOMSG = iomsg-variable |
|
|
// IOSTAT = scalar-int-variable |
|
|
// NAME = scalar-default-char-variable |
|
|
// NAMED = scalar-logical-variable |
|
|
// NEXTREC = scalar-int-variable | NUMBER = scalar-int-variable |
|
|
// OPENED = scalar-logical-variable |
|
|
// PAD = scalar-default-char-variable |
|
|
// PENDING = scalar-logical-variable | POS = scalar-int-variable |
|
|
// POSITION = scalar-default-char-variable |
|
|
// READ = scalar-default-char-variable |
|
|
// READWRITE = scalar-default-char-variable |
|
|
// RECL = scalar-int-variable | ROUND = scalar-default-char-variable |
|
|
// SEQUENTIAL = scalar-default-char-variable |
|
|
// SIGN = scalar-default-char-variable |
|
|
// SIZE = scalar-int-variable |
|
|
// STREAM = scalar-default-char-variable |
|
|
// STATUS = scalar-default-char-variable |
|
|
// UNFORMATTED = scalar-default-char-variable |
|
|
// WRITE = scalar-default-char-variable
|
|
// @ | CONVERT = scalar-default-char-variable
|
|
// | DISPOSE = scalar-default-char-variable
|
|
struct InquireSpec {
|
|
UNION_CLASS_BOILERPLATE(InquireSpec);
|
|
struct CharVar {
|
|
ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
|
|
Direct, Encoding, Form, Formatted, Iomsg, Name, Pad, Position, Read,
|
|
Readwrite, Round, Sequential, Sign, Stream, Status, Unformatted, Write,
|
|
/* extensions: */ Convert, Dispose)
|
|
TUPLE_CLASS_BOILERPLATE(CharVar);
|
|
std::tuple<Kind, ScalarDefaultCharVariable> t;
|
|
};
|
|
struct IntVar {
|
|
ENUM_CLASS(Kind, Iostat, Nextrec, Number, Pos, Recl, Size)
|
|
TUPLE_CLASS_BOILERPLATE(IntVar);
|
|
std::tuple<Kind, ScalarIntVariable> t;
|
|
};
|
|
struct LogVar {
|
|
ENUM_CLASS(Kind, Exist, Named, Opened, Pending)
|
|
TUPLE_CLASS_BOILERPLATE(LogVar);
|
|
std::tuple<Kind, Scalar<Logical<Variable>>> t;
|
|
};
|
|
std::variant<FileUnitNumber, FileNameExpr, CharVar, IntVar, LogVar, IdExpr,
|
|
ErrLabel>
|
|
u;
|
|
};
|
|
|
|
// R1230 inquire-stmt ->
|
|
// INQUIRE ( inquire-spec-list ) |
|
|
// INQUIRE ( IOLENGTH = scalar-int-variable ) output-item-list
|
|
struct InquireStmt {
|
|
UNION_CLASS_BOILERPLATE(InquireStmt);
|
|
struct Iolength {
|
|
TUPLE_CLASS_BOILERPLATE(Iolength);
|
|
std::tuple<ScalarIntVariable, std::list<OutputItem>> t;
|
|
};
|
|
std::variant<std::list<InquireSpec>, Iolength> u;
|
|
};
|
|
|
|
// R1301 format-stmt -> FORMAT format-specification
|
|
WRAPPER_CLASS(FormatStmt, format::FormatSpecification);
|
|
|
|
// R1402 program-stmt -> PROGRAM program-name
|
|
WRAPPER_CLASS(ProgramStmt, Name);
|
|
|
|
// R1403 end-program-stmt -> END [PROGRAM [program-name]]
|
|
WRAPPER_CLASS(EndProgramStmt, std::optional<Name>);
|
|
|
|
// R1401 main-program ->
|
|
// [program-stmt] [specification-part] [execution-part]
|
|
// [internal-subprogram-part] end-program-stmt
|
|
struct MainProgram {
|
|
TUPLE_CLASS_BOILERPLATE(MainProgram);
|
|
std::tuple<std::optional<Statement<ProgramStmt>>, SpecificationPart,
|
|
ExecutionPart, std::optional<InternalSubprogramPart>,
|
|
Statement<EndProgramStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1405 module-stmt -> MODULE module-name
|
|
WRAPPER_CLASS(ModuleStmt, Name);
|
|
|
|
// R1408 module-subprogram ->
|
|
// function-subprogram | subroutine-subprogram |
|
|
// separate-module-subprogram
|
|
struct ModuleSubprogram {
|
|
UNION_CLASS_BOILERPLATE(ModuleSubprogram);
|
|
std::variant<common::Indirection<FunctionSubprogram>,
|
|
common::Indirection<SubroutineSubprogram>,
|
|
common::Indirection<SeparateModuleSubprogram>>
|
|
u;
|
|
};
|
|
|
|
// R1407 module-subprogram-part -> contains-stmt [module-subprogram]...
|
|
struct ModuleSubprogramPart {
|
|
TUPLE_CLASS_BOILERPLATE(ModuleSubprogramPart);
|
|
std::tuple<Statement<ContainsStmt>, std::list<ModuleSubprogram>> t;
|
|
};
|
|
|
|
// R1406 end-module-stmt -> END [MODULE [module-name]]
|
|
WRAPPER_CLASS(EndModuleStmt, std::optional<Name>);
|
|
|
|
// R1404 module ->
|
|
// module-stmt [specification-part] [module-subprogram-part]
|
|
// end-module-stmt
|
|
struct Module {
|
|
TUPLE_CLASS_BOILERPLATE(Module);
|
|
std::tuple<Statement<ModuleStmt>, SpecificationPart,
|
|
std::optional<ModuleSubprogramPart>, Statement<EndModuleStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1411 rename ->
|
|
// local-name => use-name |
|
|
// OPERATOR ( local-defined-operator ) =>
|
|
// OPERATOR ( use-defined-operator )
|
|
struct Rename {
|
|
UNION_CLASS_BOILERPLATE(Rename);
|
|
struct Names {
|
|
TUPLE_CLASS_BOILERPLATE(Names);
|
|
std::tuple<Name, Name> t;
|
|
};
|
|
struct Operators {
|
|
TUPLE_CLASS_BOILERPLATE(Operators);
|
|
std::tuple<DefinedOpName, DefinedOpName> t;
|
|
};
|
|
std::variant<Names, Operators> u;
|
|
};
|
|
|
|
// R1418 parent-identifier -> ancestor-module-name [: parent-submodule-name]
|
|
struct ParentIdentifier {
|
|
TUPLE_CLASS_BOILERPLATE(ParentIdentifier);
|
|
std::tuple<Name, std::optional<Name>> t;
|
|
};
|
|
|
|
// R1417 submodule-stmt -> SUBMODULE ( parent-identifier ) submodule-name
|
|
struct SubmoduleStmt {
|
|
TUPLE_CLASS_BOILERPLATE(SubmoduleStmt);
|
|
std::tuple<ParentIdentifier, Name> t;
|
|
};
|
|
|
|
// R1419 end-submodule-stmt -> END [SUBMODULE [submodule-name]]
|
|
WRAPPER_CLASS(EndSubmoduleStmt, std::optional<Name>);
|
|
|
|
// R1416 submodule ->
|
|
// submodule-stmt [specification-part] [module-subprogram-part]
|
|
// end-submodule-stmt
|
|
struct Submodule {
|
|
TUPLE_CLASS_BOILERPLATE(Submodule);
|
|
std::tuple<Statement<SubmoduleStmt>, SpecificationPart,
|
|
std::optional<ModuleSubprogramPart>, Statement<EndSubmoduleStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1421 block-data-stmt -> BLOCK DATA [block-data-name]
|
|
WRAPPER_CLASS(BlockDataStmt, std::optional<Name>);
|
|
|
|
// R1422 end-block-data-stmt -> END [BLOCK DATA [block-data-name]]
|
|
WRAPPER_CLASS(EndBlockDataStmt, std::optional<Name>);
|
|
|
|
// R1420 block-data -> block-data-stmt [specification-part] end-block-data-stmt
|
|
struct BlockData {
|
|
TUPLE_CLASS_BOILERPLATE(BlockData);
|
|
std::tuple<Statement<BlockDataStmt>, SpecificationPart,
|
|
Statement<EndBlockDataStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1508 generic-spec ->
|
|
// generic-name | OPERATOR ( defined-operator ) |
|
|
// ASSIGNMENT ( = ) | defined-io-generic-spec
|
|
// R1509 defined-io-generic-spec ->
|
|
// READ ( FORMATTED ) | READ ( UNFORMATTED ) |
|
|
// WRITE ( FORMATTED ) | WRITE ( UNFORMATTED )
|
|
struct GenericSpec {
|
|
UNION_CLASS_BOILERPLATE(GenericSpec);
|
|
EMPTY_CLASS(Assignment);
|
|
EMPTY_CLASS(ReadFormatted);
|
|
EMPTY_CLASS(ReadUnformatted);
|
|
EMPTY_CLASS(WriteFormatted);
|
|
EMPTY_CLASS(WriteUnformatted);
|
|
CharBlock source;
|
|
std::variant<Name, DefinedOperator, Assignment, ReadFormatted,
|
|
ReadUnformatted, WriteFormatted, WriteUnformatted>
|
|
u;
|
|
};
|
|
|
|
// R1510 generic-stmt ->
|
|
// GENERIC [, access-spec] :: generic-spec => specific-procedure-list
|
|
struct GenericStmt {
|
|
TUPLE_CLASS_BOILERPLATE(GenericStmt);
|
|
std::tuple<std::optional<AccessSpec>, GenericSpec, std::list<Name>> t;
|
|
};
|
|
|
|
// R1503 interface-stmt -> INTERFACE [generic-spec] | ABSTRACT INTERFACE
|
|
struct InterfaceStmt {
|
|
UNION_CLASS_BOILERPLATE(InterfaceStmt);
|
|
std::variant<std::optional<GenericSpec>, Abstract> u;
|
|
};
|
|
|
|
// R1412 only -> generic-spec | only-use-name | rename
|
|
// R1413 only-use-name -> use-name
|
|
struct Only {
|
|
UNION_CLASS_BOILERPLATE(Only);
|
|
std::variant<common::Indirection<GenericSpec>, Name, Rename> u;
|
|
};
|
|
|
|
// R1409 use-stmt ->
|
|
// USE [[, module-nature] ::] module-name [, rename-list] |
|
|
// USE [[, module-nature] ::] module-name , ONLY : [only-list]
|
|
// R1410 module-nature -> INTRINSIC | NON_INTRINSIC
|
|
struct UseStmt {
|
|
BOILERPLATE(UseStmt);
|
|
ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic) // R1410
|
|
template<typename A>
|
|
UseStmt(std::optional<ModuleNature> &&nat, Name &&n, std::list<A> &&x)
|
|
: nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {}
|
|
std::optional<ModuleNature> nature;
|
|
Name moduleName;
|
|
std::variant<std::list<Rename>, std::list<Only>> u;
|
|
};
|
|
|
|
// R1514 proc-attr-spec ->
|
|
// access-spec | proc-language-binding-spec | INTENT ( intent-spec ) |
|
|
// OPTIONAL | POINTER | PROTECTED | SAVE
|
|
struct ProcAttrSpec {
|
|
UNION_CLASS_BOILERPLATE(ProcAttrSpec);
|
|
std::variant<AccessSpec, LanguageBindingSpec, IntentSpec, Optional, Pointer,
|
|
Protected, Save>
|
|
u;
|
|
};
|
|
|
|
// R1512 procedure-declaration-stmt ->
|
|
// PROCEDURE ( [proc-interface] ) [[, proc-attr-spec]... ::]
|
|
// proc-decl-list
|
|
struct ProcedureDeclarationStmt {
|
|
TUPLE_CLASS_BOILERPLATE(ProcedureDeclarationStmt);
|
|
std::tuple<std::optional<ProcInterface>, std::list<ProcAttrSpec>,
|
|
std::list<ProcDecl>>
|
|
t;
|
|
};
|
|
|
|
// R1527 prefix-spec ->
|
|
// declaration-type-spec | ELEMENTAL | IMPURE | MODULE |
|
|
// NON_RECURSIVE | PURE | RECURSIVE
|
|
struct PrefixSpec {
|
|
UNION_CLASS_BOILERPLATE(PrefixSpec);
|
|
EMPTY_CLASS(Elemental);
|
|
EMPTY_CLASS(Impure);
|
|
EMPTY_CLASS(Module);
|
|
EMPTY_CLASS(Non_Recursive);
|
|
EMPTY_CLASS(Pure);
|
|
EMPTY_CLASS(Recursive);
|
|
std::variant<DeclarationTypeSpec, Elemental, Impure, Module, Non_Recursive,
|
|
Pure, Recursive>
|
|
u;
|
|
};
|
|
|
|
// R1532 suffix ->
|
|
// proc-language-binding-spec [RESULT ( result-name )] |
|
|
// RESULT ( result-name ) [proc-language-binding-spec]
|
|
struct Suffix {
|
|
BOILERPLATE(Suffix);
|
|
Suffix(LanguageBindingSpec &&lbs, std::optional<Name> &&rn)
|
|
: binding(std::move(lbs)), resultName(std::move(rn)) {}
|
|
Suffix(Name &&rn, std::optional<LanguageBindingSpec> &&lbs)
|
|
: binding(std::move(lbs)), resultName(std::move(rn)) {}
|
|
std::optional<LanguageBindingSpec> binding;
|
|
std::optional<Name> resultName;
|
|
};
|
|
|
|
// R1530 function-stmt ->
|
|
// [prefix] FUNCTION function-name ( [dummy-arg-name-list] ) [suffix]
|
|
// R1526 prefix -> prefix-spec [prefix-spec]...
|
|
// R1531 dummy-arg-name -> name
|
|
struct FunctionStmt {
|
|
TUPLE_CLASS_BOILERPLATE(FunctionStmt);
|
|
std::tuple<std::list<PrefixSpec>, Name, std::list<Name>,
|
|
std::optional<Suffix>>
|
|
t;
|
|
};
|
|
|
|
// R1533 end-function-stmt -> END [FUNCTION [function-name]]
|
|
WRAPPER_CLASS(EndFunctionStmt, std::optional<Name>);
|
|
|
|
// R1536 dummy-arg -> dummy-arg-name | *
|
|
struct DummyArg {
|
|
UNION_CLASS_BOILERPLATE(DummyArg);
|
|
std::variant<Name, Star> u;
|
|
};
|
|
|
|
// R1535 subroutine-stmt ->
|
|
// [prefix] SUBROUTINE subroutine-name [( [dummy-arg-list] )
|
|
// [proc-language-binding-spec]]
|
|
struct SubroutineStmt {
|
|
TUPLE_CLASS_BOILERPLATE(SubroutineStmt);
|
|
std::tuple<std::list<PrefixSpec>, Name, std::list<DummyArg>,
|
|
std::optional<LanguageBindingSpec>>
|
|
t;
|
|
};
|
|
|
|
// R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]]
|
|
WRAPPER_CLASS(EndSubroutineStmt, std::optional<Name>);
|
|
|
|
// R1505 interface-body ->
|
|
// function-stmt [specification-part] end-function-stmt |
|
|
// subroutine-stmt [specification-part] end-subroutine-stmt
|
|
struct InterfaceBody {
|
|
UNION_CLASS_BOILERPLATE(InterfaceBody);
|
|
struct Function {
|
|
TUPLE_CLASS_BOILERPLATE(Function);
|
|
std::tuple<Statement<FunctionStmt>, common::Indirection<SpecificationPart>,
|
|
Statement<EndFunctionStmt>>
|
|
t;
|
|
};
|
|
struct Subroutine {
|
|
TUPLE_CLASS_BOILERPLATE(Subroutine);
|
|
std::tuple<Statement<SubroutineStmt>,
|
|
common::Indirection<SpecificationPart>, Statement<EndSubroutineStmt>>
|
|
t;
|
|
};
|
|
std::variant<Function, Subroutine> u;
|
|
};
|
|
|
|
// R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list
|
|
struct ProcedureStmt {
|
|
ENUM_CLASS(Kind, ModuleProcedure, Procedure)
|
|
TUPLE_CLASS_BOILERPLATE(ProcedureStmt);
|
|
std::tuple<Kind, std::list<Name>> t;
|
|
};
|
|
|
|
// R1502 interface-specification -> interface-body | procedure-stmt
|
|
struct InterfaceSpecification {
|
|
UNION_CLASS_BOILERPLATE(InterfaceSpecification);
|
|
std::variant<InterfaceBody, Statement<ProcedureStmt>> u;
|
|
};
|
|
|
|
// R1504 end-interface-stmt -> END INTERFACE [generic-spec]
|
|
WRAPPER_CLASS(EndInterfaceStmt, std::optional<GenericSpec>);
|
|
|
|
// R1501 interface-block ->
|
|
// interface-stmt [interface-specification]... end-interface-stmt
|
|
struct InterfaceBlock {
|
|
TUPLE_CLASS_BOILERPLATE(InterfaceBlock);
|
|
std::tuple<Statement<InterfaceStmt>, std::list<InterfaceSpecification>,
|
|
Statement<EndInterfaceStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1511 external-stmt -> EXTERNAL [::] external-name-list
|
|
WRAPPER_CLASS(ExternalStmt, std::list<Name>);
|
|
|
|
// R1519 intrinsic-stmt -> INTRINSIC [::] intrinsic-procedure-name-list
|
|
WRAPPER_CLASS(IntrinsicStmt, std::list<Name>);
|
|
|
|
// R1522 procedure-designator ->
|
|
// procedure-name | proc-component-ref | data-ref % binding-name
|
|
struct ProcedureDesignator {
|
|
UNION_CLASS_BOILERPLATE(ProcedureDesignator);
|
|
std::variant<Name, ProcComponentRef> u;
|
|
};
|
|
|
|
// R1525 alt-return-spec -> * label
|
|
WRAPPER_CLASS(AltReturnSpec, Label);
|
|
|
|
// R1524 actual-arg ->
|
|
// expr | variable | procedure-name | proc-component-ref |
|
|
// alt-return-spec
|
|
struct ActualArg {
|
|
WRAPPER_CLASS(PercentRef, Variable); // %REF(v) extension
|
|
WRAPPER_CLASS(PercentVal, Expr); // %VAL(x) extension
|
|
UNION_CLASS_BOILERPLATE(ActualArg);
|
|
ActualArg(Expr &&x) : u{common::Indirection<Expr>(std::move(x))} {}
|
|
std::variant<common::Indirection<Expr>, AltReturnSpec, PercentRef, PercentVal>
|
|
u;
|
|
};
|
|
|
|
// R1523 actual-arg-spec -> [keyword =] actual-arg
|
|
struct ActualArgSpec {
|
|
TUPLE_CLASS_BOILERPLATE(ActualArgSpec);
|
|
std::tuple<std::optional<Keyword>, ActualArg> t;
|
|
};
|
|
|
|
// R1520 function-reference -> procedure-designator ( [actual-arg-spec-list] )
|
|
struct Call {
|
|
TUPLE_CLASS_BOILERPLATE(Call);
|
|
CharBlock source;
|
|
std::tuple<ProcedureDesignator, std::list<ActualArgSpec>> t;
|
|
};
|
|
|
|
struct FunctionReference {
|
|
WRAPPER_CLASS_BOILERPLATE(FunctionReference, Call);
|
|
Designator ConvertToArrayElementRef();
|
|
StructureConstructor ConvertToStructureConstructor(
|
|
const semantics::DerivedTypeSpec &);
|
|
};
|
|
|
|
// R1521 call-stmt -> CALL procedure-designator [( [actual-arg-spec-list] )]
|
|
WRAPPER_CLASS(CallStmt, Call);
|
|
|
|
// R1529 function-subprogram ->
|
|
// function-stmt [specification-part] [execution-part]
|
|
// [internal-subprogram-part] end-function-stmt
|
|
struct FunctionSubprogram {
|
|
TUPLE_CLASS_BOILERPLATE(FunctionSubprogram);
|
|
std::tuple<Statement<FunctionStmt>, SpecificationPart, ExecutionPart,
|
|
std::optional<InternalSubprogramPart>, Statement<EndFunctionStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1534 subroutine-subprogram ->
|
|
// subroutine-stmt [specification-part] [execution-part]
|
|
// [internal-subprogram-part] end-subroutine-stmt
|
|
struct SubroutineSubprogram {
|
|
TUPLE_CLASS_BOILERPLATE(SubroutineSubprogram);
|
|
std::tuple<Statement<SubroutineStmt>, SpecificationPart, ExecutionPart,
|
|
std::optional<InternalSubprogramPart>, Statement<EndSubroutineStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1539 mp-subprogram-stmt -> MODULE PROCEDURE procedure-name
|
|
WRAPPER_CLASS(MpSubprogramStmt, Name);
|
|
|
|
// R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]]
|
|
WRAPPER_CLASS(EndMpSubprogramStmt, std::optional<Name>);
|
|
|
|
// R1538 separate-module-subprogram ->
|
|
// mp-subprogram-stmt [specification-part] [execution-part]
|
|
// [internal-subprogram-part] end-mp-subprogram-stmt
|
|
struct SeparateModuleSubprogram {
|
|
TUPLE_CLASS_BOILERPLATE(SeparateModuleSubprogram);
|
|
std::tuple<Statement<MpSubprogramStmt>, SpecificationPart, ExecutionPart,
|
|
std::optional<InternalSubprogramPart>, Statement<EndMpSubprogramStmt>>
|
|
t;
|
|
};
|
|
|
|
// R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]]
|
|
struct EntryStmt {
|
|
TUPLE_CLASS_BOILERPLATE(EntryStmt);
|
|
std::tuple<Name, std::list<DummyArg>, std::optional<Suffix>> t;
|
|
};
|
|
|
|
// R1542 return-stmt -> RETURN [scalar-int-expr]
|
|
WRAPPER_CLASS(ReturnStmt, std::optional<ScalarIntExpr>);
|
|
|
|
// R1544 stmt-function-stmt ->
|
|
// function-name ( [dummy-arg-name-list] ) = scalar-expr
|
|
struct StmtFunctionStmt {
|
|
TUPLE_CLASS_BOILERPLATE(StmtFunctionStmt);
|
|
std::tuple<Name, std::list<Name>, Scalar<Expr>> t;
|
|
Statement<ActionStmt> ConvertToAssignment();
|
|
};
|
|
|
|
// Compiler directives
|
|
// !DIR$ IGNORE_TKR [ [(tkr...)] name ]...
|
|
// !DIR$ name...
|
|
struct CompilerDirective {
|
|
UNION_CLASS_BOILERPLATE(CompilerDirective);
|
|
struct IgnoreTKR {
|
|
TUPLE_CLASS_BOILERPLATE(IgnoreTKR);
|
|
std::tuple<std::list<const char *>, Name> t;
|
|
};
|
|
CharBlock source;
|
|
std::variant<std::list<IgnoreTKR>, std::list<Name>> u;
|
|
};
|
|
|
|
// Legacy extensions
|
|
struct BasedPointer {
|
|
TUPLE_CLASS_BOILERPLATE(BasedPointer);
|
|
std::tuple<ObjectName, ObjectName, std::optional<ArraySpec>> t;
|
|
};
|
|
WRAPPER_CLASS(BasedPointerStmt, std::list<BasedPointer>);
|
|
|
|
struct Union;
|
|
struct StructureDef;
|
|
|
|
struct StructureField {
|
|
UNION_CLASS_BOILERPLATE(StructureField);
|
|
std::variant<Statement<DataComponentDefStmt>,
|
|
common::Indirection<StructureDef>, common::Indirection<Union>>
|
|
u;
|
|
};
|
|
|
|
struct Map {
|
|
EMPTY_CLASS(MapStmt);
|
|
EMPTY_CLASS(EndMapStmt);
|
|
TUPLE_CLASS_BOILERPLATE(Map);
|
|
std::tuple<Statement<MapStmt>, std::list<StructureField>,
|
|
Statement<EndMapStmt>>
|
|
t;
|
|
};
|
|
|
|
struct Union {
|
|
EMPTY_CLASS(UnionStmt);
|
|
EMPTY_CLASS(EndUnionStmt);
|
|
TUPLE_CLASS_BOILERPLATE(Union);
|
|
std::tuple<Statement<UnionStmt>, std::list<Map>, Statement<EndUnionStmt>> t;
|
|
};
|
|
|
|
struct StructureStmt {
|
|
TUPLE_CLASS_BOILERPLATE(StructureStmt);
|
|
std::tuple<Name, bool /*slashes*/, std::list<EntityDecl>> t;
|
|
};
|
|
|
|
struct StructureDef {
|
|
EMPTY_CLASS(EndStructureStmt);
|
|
TUPLE_CLASS_BOILERPLATE(StructureDef);
|
|
std::tuple<Statement<StructureStmt>, std::list<StructureField>,
|
|
Statement<EndStructureStmt>>
|
|
t;
|
|
};
|
|
|
|
// Old style PARAMETER statement without parentheses.
|
|
// Types are determined entirely from the right-hand sides, not the names.
|
|
WRAPPER_CLASS(OldParameterStmt, std::list<NamedConstantDef>);
|
|
|
|
// Deprecations
|
|
struct ArithmeticIfStmt {
|
|
TUPLE_CLASS_BOILERPLATE(ArithmeticIfStmt);
|
|
std::tuple<Expr, Label, Label, Label> t;
|
|
};
|
|
|
|
struct AssignStmt {
|
|
TUPLE_CLASS_BOILERPLATE(AssignStmt);
|
|
std::tuple<Label, Name> t;
|
|
};
|
|
|
|
struct AssignedGotoStmt {
|
|
TUPLE_CLASS_BOILERPLATE(AssignedGotoStmt);
|
|
std::tuple<Name, std::list<Label>> t;
|
|
};
|
|
|
|
WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
|
|
|
|
// PROC_BIND(CLOSE | MASTER | SPREAD)
|
|
struct OmpProcBindClause {
|
|
ENUM_CLASS(Type, Close, Master, Spread)
|
|
WRAPPER_CLASS_BOILERPLATE(OmpProcBindClause, Type);
|
|
};
|
|
|
|
// DEFAULT(PRIVATE | FIRSTPRIVATE | SHARED | NOND)
|
|
struct OmpDefaultClause {
|
|
ENUM_CLASS(Type, Private, Firstprivate, Shared, None)
|
|
WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, Type);
|
|
};
|
|
|
|
// variable-name | / common-block / | array-sections
|
|
struct OmpObject {
|
|
TUPLE_CLASS_BOILERPLATE(OmpObject);
|
|
ENUM_CLASS(Kind, Object, Common)
|
|
std::tuple<Kind, Designator> t;
|
|
};
|
|
|
|
WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
|
|
|
|
// map-type ->(TO | FROM | TOFROM | ALLOC | RELEASE | DELETE)
|
|
struct OmpMapType {
|
|
TUPLE_CLASS_BOILERPLATE(OmpMapType);
|
|
EMPTY_CLASS(Always);
|
|
ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete)
|
|
std::tuple<std::optional<Always>, Type> t;
|
|
};
|
|
|
|
// MAP ( map-type : list)
|
|
struct OmpMapClause {
|
|
TUPLE_CLASS_BOILERPLATE(OmpMapClause);
|
|
std::tuple<std::optional<OmpMapType>, OmpObjectList> t;
|
|
};
|
|
|
|
// schedule-modifier-type -> MONOTONIC | NONMONOTONIC | SIMD
|
|
struct OmpScheduleModifierType {
|
|
ENUM_CLASS(ModType, Monotonic, Nonmonotonic, Simd)
|
|
WRAPPER_CLASS_BOILERPLATE(OmpScheduleModifierType, ModType);
|
|
};
|
|
|
|
struct OmpScheduleModifier {
|
|
TUPLE_CLASS_BOILERPLATE(OmpScheduleModifier);
|
|
WRAPPER_CLASS(Modifier1, OmpScheduleModifierType);
|
|
WRAPPER_CLASS(Modifier2, OmpScheduleModifierType);
|
|
std::tuple<Modifier1, std::optional<Modifier2>> t;
|
|
};
|
|
|
|
// SCHEDULE([schedule-modifier [,schedule-modifier]] schedule-type [,
|
|
// chunksize])
|
|
struct OmpScheduleClause {
|
|
TUPLE_CLASS_BOILERPLATE(OmpScheduleClause);
|
|
ENUM_CLASS(ScheduleType, Static, Dynamic, Guided, Auto, Runtime)
|
|
std::tuple<std::optional<OmpScheduleModifier>, ScheduleType,
|
|
std::optional<ScalarIntExpr>>
|
|
t;
|
|
};
|
|
|
|
// IF(DirectiveNameModifier: scalar-logical-expr)
|
|
struct OmpIfClause {
|
|
TUPLE_CLASS_BOILERPLATE(OmpIfClause);
|
|
ENUM_CLASS(DirectiveNameModifier, Parallel, Target, TargetEnterData,
|
|
TargetExitData, TargetData, TargetUpdate, Taskloop, Task)
|
|
std::tuple<std::optional<DirectiveNameModifier>, ScalarLogicalExpr> t;
|
|
};
|
|
|
|
// ALIGNED(list, scalar-int-constant-expr)
|
|
struct OmpAlignedClause {
|
|
TUPLE_CLASS_BOILERPLATE(OmpAlignedClause);
|
|
std::tuple<std::list<Name>, std::optional<ScalarIntConstantExpr>> t;
|
|
};
|
|
|
|
// linear-modifier -> REF | VAL | UVAL
|
|
struct OmpLinearModifier {
|
|
ENUM_CLASS(Type, Ref, Val, Uval)
|
|
WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type);
|
|
};
|
|
|
|
// LINEAR((linear-modifier(list) | (list)) [: linear-step])
|
|
struct OmpLinearClause {
|
|
UNION_CLASS_BOILERPLATE(OmpLinearClause);
|
|
struct WithModifier {
|
|
BOILERPLATE(WithModifier);
|
|
WithModifier(OmpLinearModifier &&m, std::list<Name> &&n,
|
|
std::optional<ScalarIntConstantExpr> &&s)
|
|
: modifier(std::move(m)), names(std::move(n)), step(std::move(s)) {}
|
|
OmpLinearModifier modifier;
|
|
std::list<Name> names;
|
|
std::optional<ScalarIntConstantExpr> step;
|
|
};
|
|
struct WithoutModifier {
|
|
BOILERPLATE(WithoutModifier);
|
|
WithoutModifier(
|
|
std::list<Name> &&n, std::optional<ScalarIntConstantExpr> &&s)
|
|
: names(std::move(n)), step(std::move(s)) {}
|
|
std::list<Name> names;
|
|
std::optional<ScalarIntConstantExpr> step;
|
|
};
|
|
std::variant<WithModifier, WithoutModifier> u;
|
|
};
|
|
|
|
// reduction-identifier -> Add, Subtract, Multiply, .and., .or., .eqv., .neqv.,
|
|
// min, max, iand, ior, ieor
|
|
struct OmpReductionOperator {
|
|
UNION_CLASS_BOILERPLATE(OmpReductionOperator);
|
|
std::variant<common::Indirection<DefinedOperator>, ProcedureDesignator> u;
|
|
};
|
|
|
|
// REDUCTION(reduction-identifier: list)
|
|
struct OmpReductionClause {
|
|
TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
|
|
std::tuple<OmpReductionOperator, std::list<Designator>> t;
|
|
};
|
|
|
|
// depend-vec-length -> +/- non-negative-constant
|
|
struct OmpDependSinkVecLength {
|
|
TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength);
|
|
std::tuple<common::Indirection<DefinedOperator>, ScalarIntConstantExpr> t;
|
|
};
|
|
|
|
// depend-vec -> iterator_variable [+/- depend-vec-length]
|
|
struct OmpDependSinkVec {
|
|
TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec);
|
|
std::tuple<Name, std::optional<OmpDependSinkVecLength>> t;
|
|
};
|
|
|
|
struct OmpDependenceType {
|
|
ENUM_CLASS(Type, In, Out, Inout, Source, Sink)
|
|
WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
|
|
};
|
|
|
|
// DEPEND(SOURCE | SINK: vec | DEPEND((IN | OUT | INOUT) : list)
|
|
struct OmpDependClause {
|
|
UNION_CLASS_BOILERPLATE(OmpDependClause);
|
|
EMPTY_CLASS(Source);
|
|
WRAPPER_CLASS(Sink, std::list<OmpDependSinkVec>);
|
|
struct InOut {
|
|
TUPLE_CLASS_BOILERPLATE(InOut);
|
|
std::tuple<OmpDependenceType, std::list<Designator>> t;
|
|
};
|
|
std::variant<Source, Sink, InOut> u;
|
|
};
|
|
|
|
// NOWAIT
|
|
EMPTY_CLASS(OmpNowait);
|
|
|
|
// OpenMP Clauses
|
|
struct OmpClause {
|
|
UNION_CLASS_BOILERPLATE(OmpClause);
|
|
EMPTY_CLASS(Defaultmap);
|
|
EMPTY_CLASS(Inbranch);
|
|
EMPTY_CLASS(Mergeable);
|
|
EMPTY_CLASS(Nogroup);
|
|
EMPTY_CLASS(Notinbranch);
|
|
EMPTY_CLASS(Untied);
|
|
WRAPPER_CLASS(Collapse, ScalarIntConstantExpr);
|
|
WRAPPER_CLASS(Copyin, OmpObjectList);
|
|
WRAPPER_CLASS(Copyprivate, OmpObjectList);
|
|
WRAPPER_CLASS(Device, ScalarIntExpr);
|
|
WRAPPER_CLASS(DistSchedule, ScalarIntExpr);
|
|
WRAPPER_CLASS(Final, ScalarIntExpr);
|
|
WRAPPER_CLASS(Firstprivate, OmpObjectList);
|
|
WRAPPER_CLASS(From, std::list<Designator>);
|
|
WRAPPER_CLASS(Grainsize, ScalarIntExpr);
|
|
WRAPPER_CLASS(Lastprivate, OmpObjectList);
|
|
WRAPPER_CLASS(NumTasks, ScalarIntExpr);
|
|
WRAPPER_CLASS(NumTeams, ScalarIntExpr);
|
|
WRAPPER_CLASS(NumThreads, ScalarIntExpr);
|
|
WRAPPER_CLASS(Ordered, std::optional<ScalarIntConstantExpr>);
|
|
WRAPPER_CLASS(Priority, ScalarIntExpr);
|
|
WRAPPER_CLASS(Private, OmpObjectList);
|
|
WRAPPER_CLASS(Safelen, ScalarIntConstantExpr);
|
|
WRAPPER_CLASS(Shared, OmpObjectList);
|
|
WRAPPER_CLASS(Simdlen, ScalarIntConstantExpr);
|
|
WRAPPER_CLASS(ThreadLimit, ScalarIntExpr);
|
|
WRAPPER_CLASS(To, std::list<Designator>);
|
|
WRAPPER_CLASS(Uniform, std::list<Name>);
|
|
WRAPPER_CLASS(UseDevicePtr, std::list<Name>);
|
|
std::variant<Defaultmap, Inbranch, Mergeable, Nogroup, Notinbranch, OmpNowait,
|
|
Untied, Collapse, Copyin, Copyprivate, Device, DistSchedule, Final,
|
|
Firstprivate, From, Grainsize, Lastprivate, NumTasks, NumTeams,
|
|
NumThreads, Ordered, Priority, Private, Safelen, Shared, Simdlen,
|
|
ThreadLimit, To, Uniform, UseDevicePtr, OmpAlignedClause,
|
|
OmpDefaultClause, OmpDependClause, OmpIfClause, OmpLinearClause,
|
|
OmpMapClause, OmpProcBindClause, OmpReductionClause, OmpScheduleClause>
|
|
u;
|
|
};
|
|
|
|
WRAPPER_CLASS(OmpClauseList, std::list<OmpClause>);
|
|
|
|
// SECTIONS, PARALLEL SECTIONS
|
|
WRAPPER_CLASS(OmpEndSections, std::optional<OmpNowait>);
|
|
WRAPPER_CLASS(OmpEndParallelSections, std::optional<OmpNowait>);
|
|
EMPTY_CLASS(OmpSection);
|
|
|
|
struct OpenMPSectionsConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
|
|
std::tuple<OmpClauseList, Block, OmpEndSections> t;
|
|
};
|
|
|
|
struct OpenMPParallelSectionsConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPParallelSectionsConstruct);
|
|
std::tuple<OmpClauseList, Block, OmpEndParallelSections> t;
|
|
};
|
|
|
|
// WORKSHARE
|
|
EMPTY_CLASS(OmpEndWorkshare);
|
|
struct OpenMPWorkshareConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPWorkshareConstruct);
|
|
std::tuple<Block, std::optional<OmpNowait>> t;
|
|
};
|
|
|
|
// SINGLE
|
|
WRAPPER_CLASS(OmpEndSingle, OmpClauseList);
|
|
struct OpenMPSingleConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPSingleConstruct);
|
|
std::tuple<OmpClauseList, Block, OmpEndSingle> t;
|
|
};
|
|
|
|
// OpenMP directive enclosing block
|
|
struct OmpBlockDirective {
|
|
UNION_CLASS_BOILERPLATE(OmpBlockDirective);
|
|
EMPTY_CLASS(Master);
|
|
EMPTY_CLASS(Ordered);
|
|
EMPTY_CLASS(ParallelWorkshare);
|
|
EMPTY_CLASS(Parallel);
|
|
EMPTY_CLASS(TargetData);
|
|
EMPTY_CLASS(TargetParallel);
|
|
EMPTY_CLASS(TargetTeams);
|
|
EMPTY_CLASS(Target);
|
|
EMPTY_CLASS(Taskgroup);
|
|
EMPTY_CLASS(Task);
|
|
EMPTY_CLASS(Teams);
|
|
std::variant<Master, Ordered, ParallelWorkshare, Parallel, TargetData,
|
|
TargetParallel, TargetTeams, Target, Taskgroup, Task, Teams>
|
|
u;
|
|
};
|
|
|
|
struct OmpDeclareTargetMapType {
|
|
ENUM_CLASS(Type, Link, To)
|
|
WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetMapType, Type);
|
|
};
|
|
|
|
struct OpenMPDeclareTargetConstruct {
|
|
UNION_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct);
|
|
struct WithClause {
|
|
BOILERPLATE(WithClause);
|
|
WithClause(OmpDeclareTargetMapType &&m, OmpObjectList &&n)
|
|
: maptype(std::move(m)), names(std::move(n)) {}
|
|
OmpDeclareTargetMapType maptype;
|
|
OmpObjectList names;
|
|
};
|
|
struct WithExtendedList {
|
|
BOILERPLATE(WithExtendedList);
|
|
WithExtendedList(OmpObjectList &&n) : names(std::move(n)) {}
|
|
OmpObjectList names;
|
|
};
|
|
EMPTY_CLASS(Implicit);
|
|
std::variant<WithClause, WithExtendedList, Implicit> u;
|
|
};
|
|
|
|
struct OmpReductionCombiner {
|
|
UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
|
|
WRAPPER_CLASS(FunctionCombiner, Call);
|
|
std::variant<AssignmentStmt, FunctionCombiner> u;
|
|
};
|
|
|
|
WRAPPER_CLASS(OmpReductionInitializerClause, common::Indirection<Expr>);
|
|
|
|
struct OpenMPDeclareReductionConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
|
|
std::tuple<OmpReductionOperator, std::list<DeclarationTypeSpec>,
|
|
OmpReductionCombiner, std::optional<OmpReductionInitializerClause>>
|
|
t;
|
|
};
|
|
|
|
struct OpenMPDeclareSimdConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareSimdConstruct);
|
|
std::tuple<std::optional<Name>, OmpClauseList> t;
|
|
};
|
|
|
|
struct OpenMPDeclarativeConstruct {
|
|
UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct);
|
|
WRAPPER_CLASS(Threadprivate, OmpObjectList);
|
|
std::variant<OpenMPDeclareReductionConstruct, OpenMPDeclareSimdConstruct,
|
|
OpenMPDeclareTargetConstruct, Threadprivate>
|
|
u;
|
|
};
|
|
|
|
// CRITICAL [Name] <block> END CRITICAL [Name]
|
|
WRAPPER_CLASS(OmpEndCritical, std::optional<Name>);
|
|
struct OpenMPCriticalConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct);
|
|
WRAPPER_CLASS(Hint, ConstantExpr);
|
|
std::tuple<std::optional<Name>, std::optional<Hint>, Block, OmpEndCritical> t;
|
|
};
|
|
|
|
// END ATOMIC
|
|
EMPTY_CLASS(OmpEndAtomic);
|
|
|
|
// ATOMIC READ
|
|
struct OmpAtomicRead {
|
|
TUPLE_CLASS_BOILERPLATE(OmpAtomicRead);
|
|
EMPTY_CLASS(SeqCst1);
|
|
EMPTY_CLASS(SeqCst2);
|
|
std::tuple<std::optional<SeqCst1>, std::optional<SeqCst2>,
|
|
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
|
|
t;
|
|
};
|
|
|
|
// ATOMIC WRITE
|
|
struct OmpAtomicWrite {
|
|
TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite);
|
|
EMPTY_CLASS(SeqCst1);
|
|
EMPTY_CLASS(SeqCst2);
|
|
std::tuple<std::optional<SeqCst1>, std::optional<SeqCst2>,
|
|
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
|
|
t;
|
|
};
|
|
|
|
// ATOMIC UPDATE
|
|
struct OmpAtomicUpdate {
|
|
TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate);
|
|
EMPTY_CLASS(SeqCst1);
|
|
EMPTY_CLASS(SeqCst2);
|
|
std::tuple<std::optional<SeqCst1>, std::optional<SeqCst2>,
|
|
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
|
|
t;
|
|
};
|
|
|
|
// ATOMIC CAPTURE
|
|
struct OmpAtomicCapture {
|
|
TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture);
|
|
EMPTY_CLASS(SeqCst1);
|
|
EMPTY_CLASS(SeqCst2);
|
|
WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
|
|
WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
|
|
std::tuple<std::optional<SeqCst1>, std::optional<SeqCst2>, Stmt1, Stmt2,
|
|
OmpEndAtomic>
|
|
t;
|
|
};
|
|
|
|
// ATOMIC
|
|
struct OmpAtomic {
|
|
TUPLE_CLASS_BOILERPLATE(OmpAtomic);
|
|
EMPTY_CLASS(SeqCst);
|
|
std::tuple<std::optional<SeqCst>, Statement<AssignmentStmt>,
|
|
std::optional<OmpEndAtomic>>
|
|
t;
|
|
};
|
|
|
|
struct OpenMPAtomicConstruct {
|
|
UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
|
|
std::variant<OmpAtomicRead, OmpAtomicWrite, OmpAtomicCapture, OmpAtomicUpdate,
|
|
OmpAtomic>
|
|
u;
|
|
};
|
|
|
|
struct OmpLoopDirective {
|
|
UNION_CLASS_BOILERPLATE(OmpLoopDirective);
|
|
EMPTY_CLASS(DistributeParallelDoSimd);
|
|
EMPTY_CLASS(DistributeParallelDo);
|
|
EMPTY_CLASS(DistributeSimd);
|
|
EMPTY_CLASS(Distribute);
|
|
EMPTY_CLASS(ParallelDoSimd);
|
|
EMPTY_CLASS(ParallelDo);
|
|
EMPTY_CLASS(Do);
|
|
EMPTY_CLASS(DoSimd);
|
|
EMPTY_CLASS(Simd);
|
|
EMPTY_CLASS(TargetParallelDoSimd);
|
|
EMPTY_CLASS(TargetParallelDo);
|
|
EMPTY_CLASS(TargetTeamsDistributeParallelDoSimd);
|
|
EMPTY_CLASS(TargetTeamsDistributeParallelDo);
|
|
EMPTY_CLASS(TargetTeamsDistributeSimd);
|
|
EMPTY_CLASS(TargetTeamsDistribute);
|
|
EMPTY_CLASS(TargetSimd);
|
|
EMPTY_CLASS(TaskloopSimd);
|
|
EMPTY_CLASS(Taskloop);
|
|
EMPTY_CLASS(TeamsDistributeParallelDoSimd);
|
|
EMPTY_CLASS(TeamsDistributeParallelDo);
|
|
EMPTY_CLASS(TeamsDistributeSimd);
|
|
EMPTY_CLASS(TeamsDistribute);
|
|
std::variant<DistributeParallelDoSimd, DistributeParallelDo, DistributeSimd,
|
|
Distribute, ParallelDoSimd, ParallelDo, Do, DoSimd, Simd,
|
|
TargetParallelDoSimd, TargetParallelDo,
|
|
TargetTeamsDistributeParallelDoSimd, TargetTeamsDistributeParallelDo,
|
|
TargetTeamsDistributeSimd, TargetTeamsDistribute, TargetSimd,
|
|
TaskloopSimd, Taskloop, TeamsDistributeParallelDoSimd,
|
|
TeamsDistributeParallelDo, TeamsDistributeSimd, TeamsDistribute>
|
|
u;
|
|
};
|
|
|
|
// Cancel/Cancellation type
|
|
struct OmpCancelType {
|
|
ENUM_CLASS(Type, Parallel, Sections, Do, Taskgroup)
|
|
WRAPPER_CLASS_BOILERPLATE(OmpCancelType, Type);
|
|
};
|
|
|
|
// CANCELLATION POINT
|
|
WRAPPER_CLASS(OpenMPCancellationPointConstruct, OmpCancelType);
|
|
|
|
// CANCEL
|
|
struct OpenMPCancelConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct);
|
|
WRAPPER_CLASS(If, ScalarLogicalExpr);
|
|
std::tuple<OmpCancelType, std::optional<If>> t;
|
|
};
|
|
|
|
// FLUSH
|
|
WRAPPER_CLASS(OpenMPFlushConstruct, std::optional<OmpObjectList>);
|
|
|
|
// Standalone constructs
|
|
struct OmpStandaloneDirective {
|
|
UNION_CLASS_BOILERPLATE(OmpStandaloneDirective);
|
|
EMPTY_CLASS(TargetEnterData);
|
|
EMPTY_CLASS(TargetExitData);
|
|
EMPTY_CLASS(TargetUpdate);
|
|
std::variant<TargetEnterData, TargetExitData, TargetUpdate> u;
|
|
};
|
|
|
|
EMPTY_CLASS(OpenMPTaskyieldConstruct);
|
|
EMPTY_CLASS(OpenMPTaskwaitConstruct);
|
|
EMPTY_CLASS(OpenMPBarrierConstruct);
|
|
WRAPPER_CLASS(OmpEndBlockDirective, common::Indirection<OmpBlockDirective>);
|
|
|
|
// DO / DO SIMD
|
|
WRAPPER_CLASS(OmpEndDoSimd, std::optional<OmpNowait>);
|
|
WRAPPER_CLASS(OmpEndDo, std::optional<OmpNowait>);
|
|
struct OpenMPEndLoopDirective {
|
|
UNION_CLASS_BOILERPLATE(OpenMPEndLoopDirective);
|
|
std::variant<common::Indirection<OmpEndDoSimd>, common::Indirection<OmpEndDo>,
|
|
common::Indirection<OmpLoopDirective>>
|
|
u;
|
|
};
|
|
|
|
struct OpenMPBlockConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPBlockConstruct);
|
|
std::tuple<OmpBlockDirective, OmpClauseList, Block, OmpEndBlockDirective> t;
|
|
};
|
|
|
|
struct OpenMPLoopConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct);
|
|
std::tuple<OmpLoopDirective, OmpClauseList> t;
|
|
};
|
|
|
|
struct OpenMPStandaloneConstruct {
|
|
TUPLE_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
|
|
std::tuple<OmpStandaloneDirective, OmpClauseList> t;
|
|
};
|
|
|
|
struct OpenMPConstruct {
|
|
UNION_CLASS_BOILERPLATE(OpenMPConstruct);
|
|
std::variant<common::Indirection<OpenMPStandaloneConstruct>,
|
|
common::Indirection<OpenMPBarrierConstruct>,
|
|
common::Indirection<OpenMPTaskwaitConstruct>,
|
|
common::Indirection<OpenMPTaskyieldConstruct>,
|
|
common::Indirection<OpenMPSingleConstruct>,
|
|
common::Indirection<OpenMPSectionsConstruct>,
|
|
common::Indirection<OpenMPParallelSectionsConstruct>,
|
|
common::Indirection<OpenMPWorkshareConstruct>,
|
|
common::Indirection<OpenMPLoopConstruct>,
|
|
common::Indirection<OpenMPBlockConstruct>,
|
|
common::Indirection<OpenMPCancellationPointConstruct>,
|
|
common::Indirection<OpenMPCancelConstruct>,
|
|
common::Indirection<OpenMPFlushConstruct>,
|
|
common::Indirection<OpenMPAtomicConstruct>,
|
|
common::Indirection<OpenMPCriticalConstruct>, OmpSection>
|
|
u;
|
|
};
|
|
}
|
|
#endif // FORTRAN_PARSER_PARSE_TREE_H_
|