// R1005 add-operand -> [add-operand mult-op] mult-operand
// R1008 mult-op -> * | /
// The left recursion in the grammar is implemented iteratively.
-constexpr struct AddOperand {
+struct AddOperand {
using resultType = Expr;
constexpr AddOperand() {}
static inline std::optional<Expr> Parse(ParseState &state) {
}
return result;
}
-} addOperand;
+};
+constexpr AddOperand addOperand;
// R1006 level-2-expr -> [[level-2-expr] add-op] add-operand
// R1009 add-op -> + | -
// by means of a missing first operand; e.g., 2*-3 is valid in C but not
// standard Fortran. We accept unary + and - to appear before any primary
// as an extension.
-constexpr struct Level2Expr {
+struct Level2Expr {
using resultType = Expr;
constexpr Level2Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
}
return result;
}
-} level2Expr;
+};
+constexpr Level2Expr level2Expr;
// R1010 level-3-expr -> [level-3-expr concat-op] level-2-expr
// R1011 concat-op -> //
// Concatenation (//) is left-associative for parsing performance, although
// one would never notice if it were right-associated.
-constexpr struct Level3Expr {
+struct Level3Expr {
using resultType = Expr;
constexpr Level3Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
}
return result;
}
-} level3Expr;
+};
+constexpr Level3Expr level3Expr;
// R1012 level-4-expr -> [level-3-expr rel-op] level-3-expr
// R1013 rel-op ->
// .EQ. | .NE. | .LT. | .LE. | .GT. | .GE. |
// == | /= | < | <= | > | >= @ | <>
// N.B. relations are not recursive (i.e., LOGICAL is not ordered)
-constexpr struct Level4Expr {
+struct Level4Expr {
using resultType = Expr;
constexpr Level4Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
}
return result;
}
-} level4Expr;
+};
+constexpr Level4Expr level4Expr;
// R1014 and-operand -> [not-op] level-4-expr
// R1018 not-op -> .NOT.
// N.B. Fortran's .NOT. binds less tightly than its comparison operators do.
// PGI/Intel extension: accept multiple .NOT. operators
-constexpr struct AndOperand {
+struct AndOperand {
using resultType = Expr;
constexpr AndOperand() {}
static inline std::optional<Expr> Parse(ParseState &);
-} andOperand;
+};
+constexpr AndOperand andOperand;
// Match a logical operator or, optionally, its abbreviation.
inline constexpr auto logicalOp(const char *op, const char *abbrev) {
// R1015 or-operand -> [or-operand and-op] and-operand
// R1019 and-op -> .AND.
// .AND. is left-associative
-constexpr struct OrOperand {
+struct OrOperand {
using resultType = Expr;
constexpr OrOperand() {}
static inline std::optional<Expr> Parse(ParseState &state) {
}
return result;
}
-} orOperand;
+};
+constexpr OrOperand orOperand;
// R1016 equiv-operand -> [equiv-operand or-op] or-operand
// R1020 or-op -> .OR.
// .OR. is left-associative
-constexpr struct EquivOperand {
+struct EquivOperand {
using resultType = Expr;
constexpr EquivOperand() {}
static inline std::optional<Expr> Parse(ParseState &state) {
}
return result;
}
-} equivOperand;
+};
+constexpr EquivOperand equivOperand;
// R1017 level-5-expr -> [level-5-expr equiv-op] equiv-operand
// R1021 equiv-op -> .EQV. | .NEQV.
// Logical equivalence is left-associative.
// Extension: .XOR. as synonym for .NEQV.
-constexpr struct Level5Expr {
+struct Level5Expr {
using resultType = Expr;
constexpr Level5Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
}
return result;
}
-} level5Expr;
+};
+constexpr Level5Expr level5Expr;
// R1022 expr -> [expr defined-binary-op] level-5-expr
// Defined binary operators associate leftwards.
constexpr auto digit{"0123456789"_ch};
// Skips over optional spaces. Always succeeds.
-constexpr struct Space {
+struct Space {
using resultType = Success;
constexpr Space() {}
static std::optional<Success> Parse(ParseState &state) {
}
return {Success{}};
}
-} space;
+};
+constexpr Space space;
// Skips a space that in free form requires a warning if it precedes a
// character that could begin an identifier or keyword. Always succeeds.
}
}
-constexpr struct SpaceCheck {
+struct SpaceCheck {
using resultType = Success;
constexpr SpaceCheck() {}
static std::optional<Success> Parse(ParseState &state) {
}
return {Success{}};
}
-} spaceCheck;
+};
+constexpr SpaceCheck spaceCheck;
// Matches a token string. Spaces in the token string denote where
// spaces may appear in the source; they can be made mandatory for
// R711 digit-string -> digit [digit]...
// N.B. not a token -- no space is skipped
-constexpr struct DigitString {
+struct DigitString {
using resultType = CharBlock;
static std::optional<resultType> Parse(ParseState &state) {
if (std::optional<const char *> ch1{state.PeekAtNextChar()}) {
}
return std::nullopt;
}
-} digitString;
+};
+constexpr DigitString digitString;
struct SignedIntLiteralConstantWithoutKind {
using resultType = CharBlock;
}
};
-constexpr struct DigitString64 {
+struct DigitString64 {
using resultType = std::uint64_t;
static std::optional<std::uint64_t> Parse(ParseState &state) {
std::optional<const char *> firstDigit{digit.Parse(state)};
}
return {value};
}
-} digitString64;
+};
+constexpr DigitString64 digitString64;
// R707 signed-int-literal-constant -> [sign] int-literal-constant
// N.B. Spaces are consumed before and after the sign, since the sign
}
};
-constexpr struct ConsumedAllInputParser {
+struct ConsumedAllInputParser {
using resultType = Success;
constexpr ConsumedAllInputParser() {}
static inline std::optional<Success> Parse(ParseState &state) {
}
return std::nullopt;
}
-} consumedAllInput;
+};
+constexpr ConsumedAllInputParser consumedAllInput;
template <char goal> struct SkipPast {
using resultType = Success;
// the ones that specify the source form) that might appear before the
// next statement. Skip over empty statements (bare semicolons) when
// not in strict standard conformance mode. Always succeeds.
-constexpr struct SkipStuffBeforeStatement {
+struct SkipStuffBeforeStatement {
using resultType = Success;
static std::optional<Success> Parse(ParseState &state) {
if (UserState * ustate{state.userState()}) {
}
return {Success{}};
}
-} skipStuffBeforeStatement;
+};
+constexpr SkipStuffBeforeStatement skipStuffBeforeStatement;
// R602 underscore -> _
constexpr auto underscore{"_"_ch};