#include "expr-parsers.h"
#include "basic-parsers.h"
#include "misc-parsers.h"
#include "stmt-parser.h"
#include "token-parsers.h"
#include "type-parser-implementation.h"
#include "flang/Parser/characters.h"
#include "flang/Parser/parse-tree.h"
namespace Fortran::parser {
TYPE_PARSER(construct<BOZLiteralConstant>(BOZLiteral{}))
TYPE_CONTEXT_PARSER("array constructor"_en_US,
construct<ArrayConstructor>(
"(/" >> Parser<AcSpec>{} / "/)" || bracketed(Parser<AcSpec>{})))
TYPE_PARSER(construct<AcSpec>(maybe(typeSpec / "::"),
nonemptyList("expected array constructor values"_err_en_US,
Parser<AcValue>{})) ||
construct<AcSpec>(typeSpec / "::"))
TYPE_PARSER(
extension<LanguageFeature::TripletInArrayConstructor>(
"nonstandard usage: triplet in array constructor"_port_en_US,
construct<AcValue>(construct<AcValue::Triplet>(scalarIntExpr,
":" >> scalarIntExpr, maybe(":" >> scalarIntExpr)))) ||
construct<AcValue>(indirect(expr)) ||
construct<AcValue>(indirect(Parser<AcImpliedDo>{})))
TYPE_PARSER(parenthesized(
construct<AcImpliedDo>(nonemptyList(Parser<AcValue>{} / lookAhead(","_tok)),
"," >> Parser<AcImpliedDoControl>{})))
TYPE_PARSER(construct<AcImpliedDoControl>(
maybe(integerTypeSpec / "::"), loopBounds(scalarIntExpr)))
constexpr auto primary{instrumented("primary"_en_US,
first(construct<Expr>(indirect(Parser<CharLiteralConstantSubstring>{})),
construct<Expr>(literalConstant),
construct<Expr>(construct<Expr::Parentheses>("(" >>
expr / !","_tok / recovery(")"_tok, SkipPastNested<'(', ')'>{}))),
construct<Expr>(indirect(functionReference) / !"("_tok / !"%"_tok),
construct<Expr>(designator / !"("_tok / !"%"_tok),
construct<Expr>(indirect(Parser<SubstringInquiry>{})),
construct<Expr>(Parser<StructureConstructor>{}),
construct<Expr>(Parser<ArrayConstructor>{}),
construct<Expr>(parenthesized(
construct<Expr::ComplexConstructor>(expr, "," >> expr))),
extension<LanguageFeature::PercentLOC>(
"nonstandard usage: %LOC"_port_en_US,
construct<Expr>("%LOC" >> parenthesized(construct<Expr::PercentLoc>(
indirect(variable)))))))};
constexpr auto level1Expr{sourced(
primary ||
construct<Expr>(construct<Expr::DefinedUnary>(definedOpName, primary)))};
struct MultOperand {
using resultType = Expr;
constexpr MultOperand() {}
static inline std::optional<Expr> Parse(ParseState &);
};
static constexpr auto standardMultOperand{sourced(MultOperand{})};
static constexpr auto multOperand{standardMultOperand ||
extension<LanguageFeature::SignedMultOperand>(
"nonstandard usage: signed mult-operand"_port_en_US,
construct<Expr>(
construct<Expr::UnaryPlus>("+" >> standardMultOperand))) ||
extension<LanguageFeature::SignedMultOperand>(
"nonstandard usage: signed mult-operand"_port_en_US,
construct<Expr>(construct<Expr::Negate>("-" >> standardMultOperand)))};
inline std::optional<Expr> MultOperand::Parse(ParseState &state) {
std::optional<Expr> result{level1Expr.Parse(state)};
if (result) {
static constexpr auto op{attempt("**"_tok)};
if (op.Parse(state)) {
std::function<Expr(Expr &&)> power{[&result](Expr &&right) {
return Expr{Expr::Power(std::move(result).value(), std::move(right))};
}};
return applyLambda(power, multOperand).Parse(state);
}
}
return result;
}
struct AddOperand {
using resultType = Expr;
constexpr AddOperand() {}
static inline std::optional<Expr> Parse(ParseState &state) {
std::optional<Expr> result{multOperand.Parse(state)};
if (result) {
auto source{result->source};
std::function<Expr(Expr &&)> multiply{[&result](Expr &&right) {
return Expr{
Expr::Multiply(std::move(result).value(), std::move(right))};
}};
std::function<Expr(Expr &&)> divide{[&result](Expr &&right) {
return Expr{Expr::Divide(std::move(result).value(), std::move(right))};
}};
auto more{attempt(sourced("*" >> applyLambda(multiply, multOperand) ||
"/" >> applyLambda(divide, multOperand)))};
while (std::optional<Expr> next{more.Parse(state)}) {
result = std::move(next);
result->source.ExtendToCover(source);
}
}
return result;
}
};
constexpr AddOperand addOperand;
struct Level2Expr {
using resultType = Expr;
constexpr Level2Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
static constexpr auto unary{
sourced(
construct<Expr>(construct<Expr::UnaryPlus>("+" >> addOperand)) ||
construct<Expr>(construct<Expr::Negate>("-" >> addOperand))) ||
addOperand};
std::optional<Expr> result{unary.Parse(state)};
if (result) {
auto source{result->source};
std::function<Expr(Expr &&)> add{[&result](Expr &&right) {
return Expr{Expr::Add(std::move(result).value(), std::move(right))};
}};
std::function<Expr(Expr &&)> subtract{[&result](Expr &&right) {
return Expr{
Expr::Subtract(std::move(result).value(), std::move(right))};
}};
auto more{attempt(sourced("+" >> applyLambda(add, addOperand) ||
"-" >> applyLambda(subtract, addOperand)))};
while (std::optional<Expr> next{more.Parse(state)}) {
result = std::move(next);
result->source.ExtendToCover(source);
}
}
return result;
}
};
constexpr Level2Expr level2Expr;
struct Level3Expr {
using resultType = Expr;
constexpr Level3Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
std::optional<Expr> result{level2Expr.Parse(state)};
if (result) {
auto source{result->source};
std::function<Expr(Expr &&)> concat{[&result](Expr &&right) {
return Expr{Expr::Concat(std::move(result).value(), std::move(right))};
}};
auto more{attempt(sourced("//" >> applyLambda(concat, level2Expr)))};
while (std::optional<Expr> next{more.Parse(state)}) {
result = std::move(next);
result->source.ExtendToCover(source);
}
}
return result;
}
};
constexpr Level3Expr level3Expr;
struct Level4Expr {
using resultType = Expr;
constexpr Level4Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
std::optional<Expr> result{level3Expr.Parse(state)};
if (result) {
auto source{result->source};
std::function<Expr(Expr &&)> lt{[&result](Expr &&right) {
return Expr{Expr::LT(std::move(result).value(), std::move(right))};
}};
std::function<Expr(Expr &&)> le{[&result](Expr &&right) {
return Expr{Expr::LE(std::move(result).value(), std::move(right))};
}};
std::function<Expr(Expr &&)> eq{[&result](Expr &&right) {
return Expr{Expr::EQ(std::move(result).value(), std::move(right))};
}};
std::function<Expr(Expr &&)> ne{[&result](Expr &&right) {
return Expr{Expr::NE(std::move(result).value(), std::move(right))};
}};
std::function<Expr(Expr &&)> ge{[&result](Expr &&right) {
return Expr{Expr::GE(std::move(result).value(), std::move(right))};
}};
std::function<Expr(Expr &&)> gt{[&result](Expr &&right) {
return Expr{Expr::GT(std::move(result).value(), std::move(right))};
}};
auto more{attempt(
sourced((".LT."_tok || "<"_tok) >> applyLambda(lt, level3Expr) ||
(".LE."_tok || "<="_tok) >> applyLambda(le, level3Expr) ||
(".EQ."_tok || "=="_tok) >> applyLambda(eq, level3Expr) ||
(".NE."_tok || "/="_tok ||
extension<LanguageFeature::AlternativeNE>(
"nonstandard usage: <> for /= or .NE."_port_en_US,
"<>"_tok )) >>
applyLambda(ne, level3Expr) ||
(".GE."_tok || ">="_tok) >> applyLambda(ge, level3Expr) ||
(".GT."_tok || ">"_tok) >> applyLambda(gt, level3Expr)))};
if (std::optional<Expr> next{more.Parse(state)}) {
next->source.ExtendToCover(source);
return next;
}
}
return result;
}
};
constexpr Level4Expr level4Expr;
struct AndOperand {
using resultType = Expr;
constexpr AndOperand() {}
static inline std::optional<Expr> Parse(ParseState &);
};
constexpr AndOperand andOperand;
inline constexpr auto logicalOp(const char *op, const char *abbrev) {
return TokenStringMatch{op} ||
extension<LanguageFeature::LogicalAbbreviations>(
"nonstandard usage: abbreviated LOGICAL operator"_port_en_US,
TokenStringMatch{abbrev});
}
inline std::optional<Expr> AndOperand::Parse(ParseState &state) {
static constexpr auto notOp{attempt(logicalOp(".NOT.", ".N.") >> andOperand)};
if (std::optional<Expr> negation{notOp.Parse(state)}) {
return Expr{Expr::NOT{std::move(*negation)}};
} else {
return level4Expr.Parse(state);
}
}
struct OrOperand {
using resultType = Expr;
constexpr OrOperand() {}
static inline std::optional<Expr> Parse(ParseState &state) {
static constexpr auto operand{sourced(andOperand)};
std::optional<Expr> result{operand.Parse(state)};
if (result) {
auto source{result->source};
std::function<Expr(Expr &&)> logicalAnd{[&result](Expr &&right) {
return Expr{Expr::AND(std::move(result).value(), std::move(right))};
}};
auto more{attempt(sourced(
logicalOp(".AND.", ".A.") >> applyLambda(logicalAnd, andOperand)))};
while (std::optional<Expr> next{more.Parse(state)}) {
result = std::move(next);
result->source.ExtendToCover(source);
}
}
return result;
}
};
constexpr OrOperand orOperand;
struct EquivOperand {
using resultType = Expr;
constexpr EquivOperand() {}
static inline std::optional<Expr> Parse(ParseState &state) {
std::optional<Expr> result{orOperand.Parse(state)};
if (result) {
auto source{result->source};
std::function<Expr(Expr &&)> logicalOr{[&result](Expr &&right) {
return Expr{Expr::OR(std::move(result).value(), std::move(right))};
}};
auto more{attempt(sourced(
logicalOp(".OR.", ".O.") >> applyLambda(logicalOr, orOperand)))};
while (std::optional<Expr> next{more.Parse(state)}) {
result = std::move(next);
result->source.ExtendToCover(source);
}
}
return result;
}
};
constexpr EquivOperand equivOperand;
struct Level5Expr {
using resultType = Expr;
constexpr Level5Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
std::optional<Expr> result{equivOperand.Parse(state)};
if (result) {
auto source{result->source};
std::function<Expr(Expr &&)> eqv{[&result](Expr &&right) {
return Expr{Expr::EQV(std::move(result).value(), std::move(right))};
}};
std::function<Expr(Expr &&)> neqv{[&result](Expr &&right) {
return Expr{Expr::NEQV(std::move(result).value(), std::move(right))};
}};
auto more{attempt(sourced(".EQV." >> applyLambda(eqv, equivOperand) ||
(".NEQV."_tok ||
extension<LanguageFeature::XOROperator>(
"nonstandard usage: .XOR./.X. spelling of .NEQV."_port_en_US,
logicalOp(".XOR.", ".X."))) >>
applyLambda(neqv, equivOperand)))};
while (std::optional<Expr> next{more.Parse(state)}) {
result = std::move(next);
result->source.ExtendToCover(source);
}
}
return result;
}
};
constexpr Level5Expr level5Expr;
template <> std::optional<Expr> Parser<Expr>::Parse(ParseState &state) {
std::optional<Expr> result{level5Expr.Parse(state)};
if (result) {
auto source{result->source};
std::function<Expr(DefinedOpName &&, Expr &&)> defBinOp{
[&result](DefinedOpName &&op, Expr &&right) {
return Expr{Expr::DefinedBinary(
std::move(op), std::move(result).value(), std::move(right))};
}};
auto more{attempt(
sourced(applyLambda<Expr>(defBinOp, definedOpName, level5Expr)))};
while (std::optional<Expr> next{more.Parse(state)}) {
result = std::move(next);
result->source.ExtendToCover(source);
}
}
return result;
}
constexpr auto definedOpNameChar{letter ||
extension<LanguageFeature::PunctuationInNames>(
"nonstandard usage: non-alphabetic character in defined operator"_port_en_US,
"$@"_ch)};
TYPE_PARSER(
space >> construct<DefinedOpName>(sourced("."_ch >>
some(definedOpNameChar) >> construct<Name>() / "."_ch)))
TYPE_PARSER(construct<SpecificationExpr>(scalarIntExpr))
TYPE_CONTEXT_PARSER("assignment statement"_en_US,
construct<AssignmentStmt>(variable / "=", expr))
TYPE_CONTEXT_PARSER("pointer assignment statement"_en_US,
construct<PointerAssignmentStmt>(dataRef,
parenthesized(nonemptyList(Parser<BoundsRemapping>{})), "=>" >> expr) ||
construct<PointerAssignmentStmt>(dataRef,
defaulted(parenthesized(nonemptyList(Parser<BoundsSpec>{}))),
"=>" >> expr))
TYPE_PARSER(construct<BoundsSpec>(boundExpr / ":"))
TYPE_PARSER(construct<BoundsRemapping>(boundExpr / ":", boundExpr))
TYPE_PARSER(construct<ProcComponentRef>(structureComponent))
TYPE_CONTEXT_PARSER("WHERE statement"_en_US,
construct<WhereStmt>("WHERE" >> parenthesized(logicalExpr), assignmentStmt))
TYPE_CONTEXT_PARSER("WHERE construct"_en_US,
construct<WhereConstruct>(statement(Parser<WhereConstructStmt>{}),
many(whereBodyConstruct),
many(construct<WhereConstruct::MaskedElsewhere>(
statement(Parser<MaskedElsewhereStmt>{}),
many(whereBodyConstruct))),
maybe(construct<WhereConstruct::Elsewhere>(
statement(Parser<ElsewhereStmt>{}), many(whereBodyConstruct))),
statement(Parser<EndWhereStmt>{})))
TYPE_CONTEXT_PARSER("WHERE construct statement"_en_US,
construct<WhereConstructStmt>(
maybe(name / ":"), "WHERE" >> parenthesized(logicalExpr)))
TYPE_PARSER(construct<WhereBodyConstruct>(statement(assignmentStmt)) ||
construct<WhereBodyConstruct>(statement(whereStmt)) ||
construct<WhereBodyConstruct>(indirect(whereConstruct)))
TYPE_CONTEXT_PARSER("masked ELSEWHERE statement"_en_US,
construct<MaskedElsewhereStmt>(
"ELSE WHERE" >> parenthesized(logicalExpr), maybe(name)))
TYPE_CONTEXT_PARSER("ELSEWHERE statement"_en_US,
construct<ElsewhereStmt>("ELSE WHERE" >> maybe(name)))
TYPE_CONTEXT_PARSER("END WHERE statement"_en_US,
construct<EndWhereStmt>(recovery(
"END WHERE" >> maybe(name), namedConstructEndStmtErrorRecovery)))
TYPE_CONTEXT_PARSER("FORALL construct"_en_US,
construct<ForallConstruct>(statement(Parser<ForallConstructStmt>{}),
many(Parser<ForallBodyConstruct>{}),
statement(Parser<EndForallStmt>{})))
TYPE_CONTEXT_PARSER("FORALL construct statement"_en_US,
construct<ForallConstructStmt>(
maybe(name / ":"), "FORALL" >> indirect(concurrentHeader)))
TYPE_PARSER(construct<ForallBodyConstruct>(statement(forallAssignmentStmt)) ||
construct<ForallBodyConstruct>(statement(whereStmt)) ||
construct<ForallBodyConstruct>(whereConstruct) ||
construct<ForallBodyConstruct>(indirect(forallConstruct)) ||
construct<ForallBodyConstruct>(statement(forallStmt)))
TYPE_PARSER(construct<ForallAssignmentStmt>(assignmentStmt) ||
construct<ForallAssignmentStmt>(pointerAssignmentStmt))
TYPE_CONTEXT_PARSER("END FORALL statement"_en_US,
construct<EndForallStmt>(recovery(
"END FORALL" >> maybe(name), namedConstructEndStmtErrorRecovery)))
TYPE_CONTEXT_PARSER("FORALL statement"_en_US,
construct<ForallStmt>("FORALL" >> indirect(concurrentHeader),
unlabeledStatement(forallAssignmentStmt)))
}