forked from OSchip/llvm-project
[flang] Preserve some minor changes that accumulated as I was implementing
an unparsing feature. Enum classes in parse tree node class types are now defined with a macro so that the names of the enumerations can be captured for formatting purposes. Add a TODO comment. Rebase to new master with parse tree traversal code. Original-commit: flang-compiler/f18@d6bfcfd526 Reviewed-on: https://github.com/flang-compiler/f18/pull/16
This commit is contained in:
parent
c36ac6b185
commit
03aecfc336
|
@ -894,8 +894,8 @@ TYPE_PARSER("SEQUENCE" >> construct<SequenceStmt>{})
|
|||
// integer-type-spec , type-param-attr-spec :: type-param-decl-list
|
||||
// R734 type-param-attr-spec -> KIND | LEN
|
||||
TYPE_PARSER(construct<TypeParamDefStmt>{}(integerTypeSpec / ",",
|
||||
"KIND" >> pure(TypeParamDefStmt::KindOrLength::Kind) ||
|
||||
"LEN" >> pure(TypeParamDefStmt::KindOrLength::Length),
|
||||
"KIND" >> pure(TypeParamDefStmt::KindOrLen::Kind) ||
|
||||
"LEN" >> pure(TypeParamDefStmt::KindOrLen::Len),
|
||||
"::" >> nonemptyList(Parser<TypeParamDecl>{})))
|
||||
|
||||
// R733 type-param-decl -> type-param-name [= scalar-int-constant-expr]
|
||||
|
@ -1138,6 +1138,8 @@ TYPE_PARSER(construct<TypeDeclarationStmt>{}(declarationTypeSpec,
|
|||
optionalBeforeColons(nonemptyList(Parser<AttrSpec>{})),
|
||||
nonemptyList(entityDecl)) ||
|
||||
// PGI-only extension: don't require the colons
|
||||
// TODO: The standard requires the colons if the entity
|
||||
// declarations contain initializers.
|
||||
extension(construct<TypeDeclarationStmt>{}(declarationTypeSpec,
|
||||
defaulted("," >> nonemptyList(Parser<AttrSpec>{})),
|
||||
"," >> nonemptyList(entityDecl))))
|
||||
|
@ -2663,6 +2665,7 @@ TYPE_PARSER(maybe("UNIT ="_tok) >> construct<ConnectSpec>{}(fileUnitNumber) ||
|
|||
"FORM =" >>
|
||||
construct<ConnectSpec>{}(construct<ConnectSpec::CharExpr>{}(
|
||||
pure(ConnectSpec::CharExpr::Kind::Form), scalarDefaultCharExpr)) ||
|
||||
"IOMSG =" >> construct<ConnectSpec>{}(msgVariable) ||
|
||||
"IOSTAT =" >> construct<ConnectSpec>{}(statVariable) ||
|
||||
"NEWUNIT =" >> construct<ConnectSpec>{}(construct<ConnectSpec::Newunit>{}(
|
||||
scalar(integer(variable)))) ||
|
||||
|
@ -3187,15 +3190,18 @@ TYPE_PARSER(
|
|||
// R1401 main-program ->
|
||||
// [program-stmt] [specification-part] [execution-part]
|
||||
// [internal-subprogram-part] end-program-stmt
|
||||
// R1402 program-stmt -> PROGRAM program-name
|
||||
TYPE_CONTEXT_PARSER("main program"_en_US,
|
||||
construct<MainProgram>{}(maybe(statement("PROGRAM" >> name)),
|
||||
construct<MainProgram>{}(maybe(statement(Parser<ProgramStmt>{})),
|
||||
specificationPart, executionPart, maybe(internalSubprogramPart),
|
||||
unterminatedStatement(endProgramStmt)))
|
||||
|
||||
// R1402 program-stmt -> PROGRAM program-name
|
||||
TYPE_CONTEXT_PARSER(
|
||||
"PROGRAM statement"_en_US, construct<ProgramStmt>{}("PROGRAM" >> name))
|
||||
|
||||
// R1403 end-program-stmt -> END [PROGRAM [program-name]]
|
||||
TYPE_CONTEXT_PARSER("END PROGRAM statement"_en_US,
|
||||
"END" >> construct<EndProgramStmt>{}(defaulted("PROGRAM" >> maybe(name))))
|
||||
construct<EndProgramStmt>{}("END" >> defaulted("PROGRAM" >> maybe(name))))
|
||||
|
||||
// R1404 module ->
|
||||
// module-stmt [specification-part] [module-subprogram-part]
|
||||
|
|
|
@ -31,8 +31,6 @@ public:
|
|||
: cooked_{that.cooked_}, p_{that.p_}, limit_{that.limit_},
|
||||
column_{that.column_}, messages_{*that.cooked_.allSources()},
|
||||
userState_{that.userState_}, inFixedForm_{that.inFixedForm_},
|
||||
enableBackslashEscapesInCharLiterals_{
|
||||
that.enableBackslashEscapesInCharLiterals_},
|
||||
strictConformance_{that.strictConformance_},
|
||||
warnOnNonstandardUsage_{that.warnOnNonstandardUsage_},
|
||||
warnOnDeprecatedUsage_{that.warnOnDeprecatedUsage_},
|
||||
|
@ -42,8 +40,6 @@ public:
|
|||
column_{that.column_}, messages_{std::move(that.messages_)},
|
||||
context_{std::move(that.context_)}, userState_{that.userState_},
|
||||
inFixedForm_{that.inFixedForm_},
|
||||
enableBackslashEscapesInCharLiterals_{
|
||||
that.enableBackslashEscapesInCharLiterals_},
|
||||
strictConformance_{that.strictConformance_},
|
||||
warnOnNonstandardUsage_{that.warnOnNonstandardUsage_},
|
||||
warnOnDeprecatedUsage_{that.warnOnDeprecatedUsage_},
|
||||
|
@ -83,14 +79,6 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool enableBackslashEscapesInCharLiterals() const {
|
||||
return enableBackslashEscapesInCharLiterals_;
|
||||
}
|
||||
ParseState &set_enableBackslashEscapesInCharLiterals(bool yes) {
|
||||
enableBackslashEscapesInCharLiterals_ = yes;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool strictConformance() const { return strictConformance_; }
|
||||
ParseState &set_strictConformance(bool yes) {
|
||||
strictConformance_ = yes;
|
||||
|
@ -179,7 +167,6 @@ private:
|
|||
UserState *userState_{nullptr};
|
||||
|
||||
bool inFixedForm_{false};
|
||||
bool enableBackslashEscapesInCharLiterals_{true};
|
||||
bool strictConformance_{false};
|
||||
bool warnOnNonstandardUsage_{false};
|
||||
bool warnOnDeprecatedUsage_{false};
|
||||
|
|
|
@ -382,12 +382,6 @@ template<typename V> void Walk(const Suffix &x, V &visitor) {
|
|||
visitor.Post(x);
|
||||
}
|
||||
}
|
||||
template<typename V> void Walk(const TypeAttrSpec::Extends &x, V &visitor) {
|
||||
if (visitor.Pre(x)) {
|
||||
Walk(x.name, visitor);
|
||||
visitor.Post(x);
|
||||
}
|
||||
}
|
||||
template<typename V>
|
||||
void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) {
|
||||
if (visitor.Pre(x)) {
|
||||
|
@ -1524,6 +1518,9 @@ template<typename V> void Walk(const PointerStmt &x, V &visitor) {
|
|||
template<typename V> void Walk(const Program &x, V &visitor) {
|
||||
WalkWrapperClass(x, visitor);
|
||||
}
|
||||
template<typename V> void Walk(const ProgramStmt &x, V &visitor) {
|
||||
WalkWrapperClass(x, visitor);
|
||||
}
|
||||
template<typename V> void Walk(const ProtectedStmt &x, V &visitor) {
|
||||
WalkWrapperClass(x, visitor);
|
||||
}
|
||||
|
@ -1551,6 +1548,9 @@ template<typename V> void Walk(const SyncMemoryStmt &x, V &visitor) {
|
|||
template<typename V> void Walk(const TargetStmt &x, V &visitor) {
|
||||
WalkWrapperClass(x, visitor);
|
||||
}
|
||||
template<typename V> void Walk(const TypeAttrSpec::Extends &x, V &visitor) {
|
||||
WalkWrapperClass(x, visitor);
|
||||
}
|
||||
template<typename V> void Walk(const TypeParamInquiry &x, V &visitor) {
|
||||
WalkWrapperClass(x, visitor);
|
||||
}
|
||||
|
|
|
@ -311,6 +311,29 @@ std::ostream &operator<<(std::ostream &o, const FormatSpecification &x) {
|
|||
<< ')';
|
||||
}
|
||||
|
||||
#define NESTED_ENUM_FORMATTER(T) \
|
||||
NESTED_ENUM_TO_STRING(T) \
|
||||
std::ostream &operator<<(std::ostream &o, const T &x) { \
|
||||
return o << ToString(x); \
|
||||
}
|
||||
|
||||
NESTED_ENUM_FORMATTER(DefinedOperator::IntrinsicOperator) // R608
|
||||
NESTED_ENUM_FORMATTER(TypeParamDefStmt::KindOrLen) // R734
|
||||
NESTED_ENUM_FORMATTER(AccessSpec::Kind) // R807
|
||||
NESTED_ENUM_FORMATTER(IntentSpec::Intent) // R826
|
||||
NESTED_ENUM_FORMATTER(ImplicitStmt::ImplicitNoneNameSpec) // R866
|
||||
NESTED_ENUM_FORMATTER(ImportStmt::Kind) // R867
|
||||
NESTED_ENUM_FORMATTER(StopStmt::Kind) // R1160, R1161
|
||||
NESTED_ENUM_FORMATTER(ConnectSpec::CharExpr::Kind) // R1205
|
||||
NESTED_ENUM_FORMATTER(IoControlSpec::CharExpr::Kind) // R1213
|
||||
NESTED_ENUM_FORMATTER(InquireSpec::CharVar::Kind) // R1231
|
||||
NESTED_ENUM_FORMATTER(InquireSpec::IntVar::Kind) // R1231
|
||||
NESTED_ENUM_FORMATTER(InquireSpec::LogVar::Kind) // R1231
|
||||
NESTED_ENUM_FORMATTER(UseStmt::ModuleNature) // R1410
|
||||
NESTED_ENUM_FORMATTER(ProcedureStmt::Kind) // R1506
|
||||
|
||||
#undef NESTED_ENUM_FORMATTER
|
||||
|
||||
// Wrapper class formatting
|
||||
#define WRAPPER_FORMATTER(TYPE) \
|
||||
std::ostream &operator<<(std::ostream &o, const TYPE &x) { \
|
||||
|
@ -327,6 +350,7 @@ WRAPPER_FORMATTER(IntegerTypeSpec) // R705
|
|||
WRAPPER_FORMATTER(KindSelector) // R706
|
||||
WRAPPER_FORMATTER(HollerithLiteralConstant) // extension
|
||||
WRAPPER_FORMATTER(LogicalLiteralConstant) // R725
|
||||
WRAPPER_FORMATTER(TypeAttrSpec::Extends) // R728
|
||||
WRAPPER_FORMATTER(EndTypeStmt) // R730
|
||||
WRAPPER_FORMATTER(Pass) // R742 & R752
|
||||
WRAPPER_FORMATTER(FinalProcedureStmt) // R753
|
||||
|
@ -334,12 +358,14 @@ WRAPPER_FORMATTER(ComponentDataSource) // R758
|
|||
WRAPPER_FORMATTER(EnumeratorDefStmt) // R761
|
||||
WRAPPER_FORMATTER(BOZLiteralConstant) // R764, R765, R766, R767
|
||||
WRAPPER_FORMATTER(ArrayConstructor) // R769
|
||||
WRAPPER_FORMATTER(AccessSpec) // R807
|
||||
WRAPPER_FORMATTER(LanguageBindingSpec) // R808 & R1528
|
||||
WRAPPER_FORMATTER(DeferredCoshapeSpecList) // R810
|
||||
WRAPPER_FORMATTER(AssumedShapeSpec) // R819
|
||||
WRAPPER_FORMATTER(DeferredShapeSpecList) // R820
|
||||
WRAPPER_FORMATTER(AssumedImpliedSpec) // R821
|
||||
WRAPPER_FORMATTER(ImpliedShapeSpec) // R823 & R824
|
||||
WRAPPER_FORMATTER(IntentSpec) // R826
|
||||
WRAPPER_FORMATTER(AllocatableStmt) // R829
|
||||
WRAPPER_FORMATTER(AsynchronousStmt) // R831
|
||||
WRAPPER_FORMATTER(CodimensionStmt) // R834
|
||||
|
@ -413,6 +439,7 @@ WRAPPER_FORMATTER(IdVariable) // R1214
|
|||
WRAPPER_FORMATTER(WaitStmt) // R1222
|
||||
WRAPPER_FORMATTER(IdExpr) // R1223 & R1231
|
||||
WRAPPER_FORMATTER(FormatStmt) // R1301
|
||||
WRAPPER_FORMATTER(ProgramStmt) // R1402
|
||||
WRAPPER_FORMATTER(EndProgramStmt) // R1403
|
||||
WRAPPER_FORMATTER(ModuleStmt) // R1405
|
||||
WRAPPER_FORMATTER(EndModuleStmt) // R1406
|
||||
|
@ -495,32 +522,6 @@ EMPTY_TYPE_FORMATTER(Map::EndMapStmt)
|
|||
|
||||
#undef EMPTY_TYPE_FORMATTER
|
||||
|
||||
// R609
|
||||
std::ostream &operator<<(
|
||||
std::ostream &o, DefinedOperator::IntrinsicOperator x) {
|
||||
switch (x) {
|
||||
case DefinedOperator::IntrinsicOperator::Power: return o << "Power";
|
||||
case DefinedOperator::IntrinsicOperator::Multiply: return o << "Multiply";
|
||||
case DefinedOperator::IntrinsicOperator::Divide: return o << "Divide";
|
||||
case DefinedOperator::IntrinsicOperator::Add: return o << "Add";
|
||||
case DefinedOperator::IntrinsicOperator::Subtract: return o << "Subtract";
|
||||
case DefinedOperator::IntrinsicOperator::Concat: return o << "Concat";
|
||||
case DefinedOperator::IntrinsicOperator::LT: return o << "LT";
|
||||
case DefinedOperator::IntrinsicOperator::LE: return o << "LE";
|
||||
case DefinedOperator::IntrinsicOperator::EQ: return o << "EQ";
|
||||
case DefinedOperator::IntrinsicOperator::NE: return o << "NE";
|
||||
case DefinedOperator::IntrinsicOperator::GE: return o << "GE";
|
||||
case DefinedOperator::IntrinsicOperator::GT: return o << "GT";
|
||||
case DefinedOperator::IntrinsicOperator::NOT: return o << "NOT";
|
||||
case DefinedOperator::IntrinsicOperator::AND: return o << "AND";
|
||||
case DefinedOperator::IntrinsicOperator::OR: return o << "OR";
|
||||
case DefinedOperator::IntrinsicOperator::EQV: return o << "EQV";
|
||||
case DefinedOperator::IntrinsicOperator::NEQV: return o << "NEQV";
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
// R703
|
||||
std::ostream &operator<<(std::ostream &o, const DeclarationTypeSpec::Type &x) {
|
||||
return o << "(DeclarationTypeSpec TYPE " << x.derived << ')';
|
||||
|
@ -602,22 +603,6 @@ std::ostream &operator<<(
|
|||
return o << "(LengthAndKind " << x.length << ' ' << x.kind << ')';
|
||||
}
|
||||
|
||||
// R728 type-attr-spec
|
||||
std::ostream &operator<<(std::ostream &o, const TypeAttrSpec::Extends &x) {
|
||||
return o << "(Extends " << x.name << ')';
|
||||
}
|
||||
|
||||
// R734 type-param-attr-spec
|
||||
std::ostream &operator<<(
|
||||
std::ostream &o, const TypeParamDefStmt::KindOrLength &x) {
|
||||
switch (x) {
|
||||
case TypeParamDefStmt::KindOrLength::Kind: o << "Kind"; break;
|
||||
case TypeParamDefStmt::KindOrLength::Length: o << "Length"; break;
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
// R749 type-bound-procedure-stmt
|
||||
std::ostream &operator<<(
|
||||
std::ostream &o, const TypeBoundProcedureStmt::WithoutInterface &x) {
|
||||
|
@ -636,27 +621,6 @@ std::ostream &operator<<(std::ostream &o, const AcSpec &x) {
|
|||
return o << "(AcSpec " << x.type << ' ' << x.values << ')';
|
||||
}
|
||||
|
||||
// R807 access-spec
|
||||
std::ostream &operator<<(std::ostream &o, const AccessSpec &x) {
|
||||
switch (x.v) {
|
||||
case AccessSpec::Kind::Public: return o << "(Public)";
|
||||
case AccessSpec::Kind::Private: return o << "(Private)";
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
// R826 intent-spec
|
||||
std::ostream &operator<<(std::ostream &o, const IntentSpec &x) {
|
||||
switch (x.v) {
|
||||
case IntentSpec::Intent::In: return o << "(Intent In)";
|
||||
case IntentSpec::Intent::Out: return o << "(Intent Out)";
|
||||
case IntentSpec::Intent::InOut: return o << "(Intent InOut)";
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
// R863 implicit-stmt
|
||||
std::ostream &operator<<(std::ostream &o, const ImplicitStmt &x) {
|
||||
o << "(ImplicitStmt ";
|
||||
|
@ -664,21 +628,10 @@ std::ostream &operator<<(std::ostream &o, const ImplicitStmt &x) {
|
|||
x.u)) {
|
||||
o << "NONE ";
|
||||
}
|
||||
std::visit([&o](auto &&y) { o << y; }, x.u);
|
||||
std::visit([&o](const auto &y) { o << y; }, x.u);
|
||||
return o << ')';
|
||||
}
|
||||
|
||||
// R866
|
||||
std::ostream &operator<<(
|
||||
std::ostream &o, ImplicitStmt::ImplicitNoneNameSpec x) {
|
||||
switch (x) {
|
||||
case ImplicitStmt::ImplicitNoneNameSpec::External: return o << "External";
|
||||
case ImplicitStmt::ImplicitNoneNameSpec::Type: return o << "Type";
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
// R867
|
||||
ImportStmt::ImportStmt(Kind &&k, std::list<Name> &&n)
|
||||
: kind{k}, names(std::move(n)) {
|
||||
|
@ -687,14 +640,10 @@ ImportStmt::ImportStmt(Kind &&k, std::list<Name> &&n)
|
|||
|
||||
std::ostream &operator<<(std::ostream &o, const ImportStmt &x) {
|
||||
o << "(ImportStmt ";
|
||||
switch (x.kind) {
|
||||
case ImportStmt::Kind::Default: return o << x.names << ')';
|
||||
case ImportStmt::Kind::Only: return o << "Only " << x.names << ')';
|
||||
case ImportStmt::Kind::None: return o << "None)";
|
||||
case ImportStmt::Kind::All: return o << "All)";
|
||||
default: CRASH_NO_CASE;
|
||||
if (x.kind != ImportStmt::Kind::Default) {
|
||||
o << x.kind;
|
||||
}
|
||||
return o;
|
||||
return o << x.names << ')';
|
||||
}
|
||||
|
||||
// R901 designator
|
||||
|
@ -871,95 +820,6 @@ std::ostream &operator<<(std::ostream &o, const CaseValueRange::Range &x) {
|
|||
return o << "(Range " << x.lower << ' ' << x.upper << ')';
|
||||
}
|
||||
|
||||
// R1205
|
||||
std::ostream &operator<<(std::ostream &o, const ConnectSpec::CharExpr::Kind x) {
|
||||
switch (x) {
|
||||
case ConnectSpec::CharExpr::Kind::Access: o << "Access"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Action: o << "Action"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Asynchronous: o << "Asynchronous"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Blank: o << "Blank"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Decimal: o << "Decimal"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Delim: o << "Delim"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Encoding: o << "Encoding"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Form: o << "Form"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Pad: o << "Pad"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Position: o << "Position"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Round: o << "Round"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Sign: o << "Sign"; break;
|
||||
case ConnectSpec::CharExpr::Kind::Dispose: o << "Dispose"; break;
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
// R1213
|
||||
std::ostream &operator<<(std::ostream &o, IoControlSpec::CharExpr::Kind x) {
|
||||
switch (x) {
|
||||
case IoControlSpec::CharExpr::Kind::Advance: o << "Advance"; break;
|
||||
case IoControlSpec::CharExpr::Kind::Blank: o << "Blank"; break;
|
||||
case IoControlSpec::CharExpr::Kind::Decimal: o << "Decimal"; break;
|
||||
case IoControlSpec::CharExpr::Kind::Delim: o << "Delim"; break;
|
||||
case IoControlSpec::CharExpr::Kind::Pad: o << "Pad"; break;
|
||||
case IoControlSpec::CharExpr::Kind::Round: o << "Round"; break;
|
||||
case IoControlSpec::CharExpr::Kind::Sign: o << "Sign"; break;
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
// R1231
|
||||
std::ostream &operator<<(std::ostream &o, const InquireSpec::CharVar::Kind x) {
|
||||
switch (x) {
|
||||
case InquireSpec::CharVar::Kind::Access: o << "Access"; break;
|
||||
case InquireSpec::CharVar::Kind::Action: o << "Action"; break;
|
||||
case InquireSpec::CharVar::Kind::Asynchronous: o << "Asynchronous"; break;
|
||||
case InquireSpec::CharVar::Kind::Blank: o << "Blank"; break;
|
||||
case InquireSpec::CharVar::Kind::Decimal: o << "Decimal"; break;
|
||||
case InquireSpec::CharVar::Kind::Delim: o << "Delim"; break;
|
||||
case InquireSpec::CharVar::Kind::Encoding: o << "Encoding"; break;
|
||||
case InquireSpec::CharVar::Kind::Form: o << "Form"; break;
|
||||
case InquireSpec::CharVar::Kind::Formatted: o << "Formatted"; break;
|
||||
case InquireSpec::CharVar::Kind::Iomsg: o << "Iomsg"; break;
|
||||
case InquireSpec::CharVar::Kind::Name: o << "Name"; break;
|
||||
case InquireSpec::CharVar::Kind::Pad: o << "Pad"; break;
|
||||
case InquireSpec::CharVar::Kind::Position: o << "Position"; break;
|
||||
case InquireSpec::CharVar::Kind::Read: o << "Read"; break;
|
||||
case InquireSpec::CharVar::Kind::Readwrite: o << "Readwrite"; break;
|
||||
case InquireSpec::CharVar::Kind::Round: o << "Round"; break;
|
||||
case InquireSpec::CharVar::Kind::Sequential: o << "Sequential"; break;
|
||||
case InquireSpec::CharVar::Kind::Sign: o << "Sign"; break;
|
||||
case InquireSpec::CharVar::Kind::Stream: o << "Stream"; break;
|
||||
case InquireSpec::CharVar::Kind::Status: o << "Status"; break;
|
||||
case InquireSpec::CharVar::Kind::Write: o << "Write"; break;
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, const InquireSpec::IntVar::Kind x) {
|
||||
switch (x) {
|
||||
case InquireSpec::IntVar::Kind::Iostat: o << "Iostat"; break;
|
||||
case InquireSpec::IntVar::Kind::Nextrec: o << "Nextrec"; break;
|
||||
case InquireSpec::IntVar::Kind::Number: o << "Number"; break;
|
||||
case InquireSpec::IntVar::Kind::Pos: o << "Pos"; break;
|
||||
case InquireSpec::IntVar::Kind::Recl: o << "Recl"; break;
|
||||
case InquireSpec::IntVar::Kind::Size: o << "Size"; break;
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, const InquireSpec::LogVar::Kind x) {
|
||||
switch (x) {
|
||||
case InquireSpec::LogVar::Kind::Exist: o << "Exist"; break;
|
||||
case InquireSpec::LogVar::Kind::Named: o << "Named"; break;
|
||||
case InquireSpec::LogVar::Kind::Opened: o << "Opened"; break;
|
||||
case InquireSpec::LogVar::Kind::Pending: o << "Pending"; break;
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
// R1307 data-edit-desc (part 1 of 2)
|
||||
std::ostream &operator<<(std::ostream &o, const IntrinsicTypeDataEditDesc &x) {
|
||||
o << "(IntrinsicTypeDataEditDesc ";
|
||||
|
@ -982,16 +842,6 @@ std::ostream &operator<<(std::ostream &o, const IntrinsicTypeDataEditDesc &x) {
|
|||
return o << x.width << ' ' << x.digits << ' ' << x.exponentWidth << ')';
|
||||
}
|
||||
|
||||
// R1160, R1161
|
||||
std::ostream &operator<<(std::ostream &o, StopStmt::Kind x) {
|
||||
switch (x) {
|
||||
case StopStmt::Kind::Stop: o << "Stop"; break;
|
||||
case StopStmt::Kind::ErrorStop: o << "ErrorStop"; break;
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
// R1210 read-stmt
|
||||
std::ostream &operator<<(std::ostream &o, const ReadStmt &x) {
|
||||
return o << "(ReadStmt " << x.iounit << ' ' << x.format << ' ' << x.controls
|
||||
|
@ -1045,19 +895,9 @@ std::ostream &operator<<(std::ostream &o, const FormatItem &x) {
|
|||
return o << ')';
|
||||
}
|
||||
|
||||
// R1409, R1410
|
||||
// R1409
|
||||
std::ostream &operator<<(std::ostream &o, const UseStmt &x) {
|
||||
o << "(UseStmt ";
|
||||
if (x.nature) {
|
||||
switch (*x.nature) {
|
||||
case UseStmt::ModuleNature::Intrinsic: o << "Intrinsic"; break;
|
||||
case UseStmt::ModuleNature::Non_Intrinsic: o << "Non_Intrinsic"; break;
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
} else {
|
||||
o << "()";
|
||||
}
|
||||
o << ' ' << x.moduleName << ' ';
|
||||
o << "(UseStmt " << x.nature << ' ' << x.moduleName << ' ';
|
||||
std::visit(
|
||||
visitors{
|
||||
[&o](const std::list<Rename> &y) -> void { o << "RENAME " << y; },
|
||||
|
@ -1068,15 +908,6 @@ std::ostream &operator<<(std::ostream &o, const UseStmt &x) {
|
|||
}
|
||||
|
||||
// R1506
|
||||
std::ostream &operator<<(std::ostream &o, const ProcedureStmt::Kind &x) {
|
||||
switch (x) {
|
||||
case ProcedureStmt::Kind::ModuleProcedure: return o << "ModuleProcedure";
|
||||
case ProcedureStmt::Kind::Procedure: return o << "Procedure";
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, const ProcedureStmt &x) {
|
||||
return o << "(ProcedureStmt " << std::get<0>(x.t) << ' ' << std::get<1>(x.t)
|
||||
<< ')';
|
||||
|
|
|
@ -82,6 +82,14 @@
|
|||
WRAPPER_CLASS_BOILERPLATE(classname, type); \
|
||||
}
|
||||
|
||||
// Enumeration types in classes can be defined with this macro,
|
||||
// which also captures the names of the enums for formatting.
|
||||
// Invocations an be followed by declarators and must be followed by
|
||||
// a semicolon.
|
||||
#define DEFINE_NESTED_ENUM_CLASS(ENUMTYPE, ...) \
|
||||
static constexpr const char *ENUMTYPE##AsString{#__VA_ARGS__}; \
|
||||
enum class ENUMTYPE { __VA_ARGS__ }
|
||||
|
||||
namespace Fortran {
|
||||
namespace parser {
|
||||
|
||||
|
@ -477,30 +485,16 @@ WRAPPER_CLASS(NamedConstant, Name);
|
|||
// The Name here is stored without the dots; e.g., FOO, not .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 { // R608 intrinsic-operator
|
||||
Power,
|
||||
Multiply,
|
||||
Divide,
|
||||
Add,
|
||||
Subtract,
|
||||
Concat,
|
||||
LT,
|
||||
LE,
|
||||
EQ,
|
||||
NE,
|
||||
GE,
|
||||
GT,
|
||||
NOT,
|
||||
AND,
|
||||
OR,
|
||||
EQV,
|
||||
NEQV
|
||||
};
|
||||
DEFINE_NESTED_ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add,
|
||||
Subtract, Concat, LT, LE, EQ, NE, GE, GT, NOT, AND, OR, EQV, NEQV);
|
||||
std::variant<DefinedOpName, IntrinsicOperator> u;
|
||||
};
|
||||
|
||||
|
@ -512,7 +506,7 @@ using ObjectName = Name;
|
|||
// IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL
|
||||
struct ImportStmt {
|
||||
BOILERPLATE(ImportStmt);
|
||||
enum class Kind { Default, Only, None, All } kind{Kind::Default};
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Default, Only, None, All) kind{Kind::Default};
|
||||
ImportStmt(Kind &&k) : kind{k} {}
|
||||
ImportStmt(std::list<Name> &&n) : names(std::move(n)) {}
|
||||
ImportStmt(Kind &&, std::list<Name> &&);
|
||||
|
@ -552,7 +546,7 @@ WRAPPER_CLASS(IntegerTypeSpec, std::optional<KindSelector>);
|
|||
// R723 char-length -> ( type-param-value ) | digit-string
|
||||
struct CharLength {
|
||||
UNION_CLASS_BOILERPLATE(CharLength);
|
||||
std::variant<TypeParamValue, int64_t> u;
|
||||
std::variant<TypeParamValue, std::int64_t> u;
|
||||
};
|
||||
|
||||
// R722 length-selector -> ( [LEN =] type-param-value ) | * char-length [,]
|
||||
|
@ -782,7 +776,7 @@ struct ConstantValue {
|
|||
|
||||
// R807 access-spec -> PUBLIC | PRIVATE
|
||||
struct AccessSpec {
|
||||
enum class Kind { Public, Private };
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Public, Private);
|
||||
WRAPPER_CLASS_BOILERPLATE(AccessSpec, Kind);
|
||||
};
|
||||
|
||||
|
@ -792,11 +786,7 @@ EMPTY_CLASS(Abstract);
|
|||
struct TypeAttrSpec {
|
||||
UNION_CLASS_BOILERPLATE(TypeAttrSpec);
|
||||
EMPTY_CLASS(BindC);
|
||||
struct Extends {
|
||||
BOILERPLATE(Extends);
|
||||
Extends(Name &&n) : name(std::move(n)) {}
|
||||
Name name;
|
||||
};
|
||||
WRAPPER_CLASS(Extends, Name);
|
||||
std::variant<Abstract, AccessSpec, BindC, Extends> u;
|
||||
};
|
||||
|
||||
|
@ -830,9 +820,9 @@ struct TypeParamDecl {
|
|||
// integer-type-spec , type-param-attr-spec :: type-param-decl-list
|
||||
// R734 type-param-attr-spec -> KIND | LEN
|
||||
struct TypeParamDefStmt {
|
||||
enum class KindOrLength { Kind, Length }; // R734
|
||||
DEFINE_NESTED_ENUM_CLASS(KindOrLen, Kind, Len); // R734
|
||||
TUPLE_CLASS_BOILERPLATE(TypeParamDefStmt);
|
||||
std::tuple<IntegerTypeSpec, KindOrLength, std::list<TypeParamDecl>> t;
|
||||
std::tuple<IntegerTypeSpec, KindOrLen, std::list<TypeParamDecl>> t;
|
||||
};
|
||||
|
||||
// R1028 specification-expr -> scalar-int-expr
|
||||
|
@ -1209,7 +1199,7 @@ struct ArraySpec {
|
|||
|
||||
// R826 intent-spec -> IN | OUT | INOUT
|
||||
struct IntentSpec {
|
||||
enum class Intent { In, Out, InOut };
|
||||
DEFINE_NESTED_ENUM_CLASS(Intent, In, Out, InOut);
|
||||
WRAPPER_CLASS_BOILERPLATE(IntentSpec, Intent);
|
||||
};
|
||||
|
||||
|
@ -1445,8 +1435,7 @@ struct ImplicitSpec {
|
|||
// R866 implicit-name-spec -> EXTERNAL | TYPE
|
||||
struct ImplicitStmt {
|
||||
UNION_CLASS_BOILERPLATE(ImplicitStmt);
|
||||
enum class ImplicitNoneNameSpec { External, Type }; // R866
|
||||
friend std::ostream &operator<<(std::ostream &, ImplicitNoneNameSpec);
|
||||
DEFINE_NESTED_ENUM_CLASS(ImplicitNoneNameSpec, External, Type); // R866
|
||||
std::variant<std::list<ImplicitSpec>, std::list<ImplicitNoneNameSpec>> u;
|
||||
};
|
||||
|
||||
|
@ -2332,7 +2321,7 @@ struct StopCode {
|
|||
// R1161 error-stop-stmt ->
|
||||
// ERROR STOP [stop-code] [, QUIET = scalar-logical-expr]
|
||||
struct StopStmt {
|
||||
enum class Kind { Stop, ErrorStop };
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Stop, ErrorStop);
|
||||
TUPLE_CLASS_BOILERPLATE(StopStmt);
|
||||
std::tuple<Kind, std::optional<StopCode>, std::optional<ScalarLogicalExpr>> t;
|
||||
};
|
||||
|
@ -2448,28 +2437,16 @@ 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,
|
||||
Dispose /*extension*/
|
||||
};
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal,
|
||||
Delim, Encoding, Form, Pad, Position, Round, Sign,
|
||||
Dispose /*extension*/);
|
||||
TUPLE_CLASS_BOILERPLATE(CharExpr);
|
||||
std::tuple<Kind, ScalarDefaultCharExpr> t;
|
||||
};
|
||||
WRAPPER_CLASS(Recl, ScalarIntExpr);
|
||||
WRAPPER_CLASS(Newunit, ScalarIntVariable);
|
||||
std::variant<FileUnitNumber, FileNameExpr, CharExpr, StatVariable, Recl,
|
||||
Newunit, ErrLabel, StatusExpr>
|
||||
std::variant<FileUnitNumber, FileNameExpr, CharExpr, MsgVariable,
|
||||
StatVariable, Recl, Newunit, ErrLabel, StatusExpr>
|
||||
u;
|
||||
};
|
||||
|
||||
|
@ -2517,7 +2494,8 @@ WRAPPER_CLASS(EorLabel, Label);
|
|||
struct IoControlSpec {
|
||||
UNION_CLASS_BOILERPLATE(IoControlSpec);
|
||||
struct CharExpr {
|
||||
enum class Kind { Advance, Blank, Decimal, Delim, Pad, Round, Sign };
|
||||
DEFINE_NESTED_ENUM_CLASS(
|
||||
Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign);
|
||||
TUPLE_CLASS_BOILERPLATE(CharExpr);
|
||||
std::tuple<Kind, ScalarDefaultCharExpr> t;
|
||||
};
|
||||
|
@ -2680,39 +2658,19 @@ struct FlushStmt {
|
|||
struct InquireSpec {
|
||||
UNION_CLASS_BOILERPLATE(InquireSpec);
|
||||
struct CharVar {
|
||||
enum class Kind {
|
||||
Access,
|
||||
Action,
|
||||
Asynchronous,
|
||||
Blank,
|
||||
Decimal,
|
||||
Delim,
|
||||
Encoding,
|
||||
Form,
|
||||
Formatted,
|
||||
Iomsg,
|
||||
Name,
|
||||
Pad,
|
||||
Position,
|
||||
Read,
|
||||
Readwrite,
|
||||
Round,
|
||||
Sequential,
|
||||
Sign,
|
||||
Stream,
|
||||
Status,
|
||||
Write
|
||||
};
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal,
|
||||
Delim, Encoding, Form, Formatted, Iomsg, Name, Pad, Position, Read,
|
||||
Readwrite, Round, Sequential, Sign, Stream, Status, Write);
|
||||
TUPLE_CLASS_BOILERPLATE(CharVar);
|
||||
std::tuple<Kind, ScalarDefaultCharVariable> t;
|
||||
};
|
||||
struct IntVar {
|
||||
enum class Kind { Iostat, Nextrec, Number, Pos, Recl, Size };
|
||||
DEFINE_NESTED_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 };
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Exist, Named, Opened, Pending);
|
||||
TUPLE_CLASS_BOILERPLATE(LogVar);
|
||||
std::tuple<Kind, Scalar<Logical<Variable>>> t;
|
||||
};
|
||||
|
@ -2736,17 +2694,20 @@ struct InquireStmt {
|
|||
// R1301 format-stmt -> FORMAT format-specification
|
||||
WRAPPER_CLASS(FormatStmt, 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
|
||||
// R1402 program-stmt -> PROGRAM program-name
|
||||
struct MainProgram {
|
||||
TUPLE_CLASS_BOILERPLATE(MainProgram);
|
||||
std::tuple<std::optional<Statement<Name>>, SpecificationPart, ExecutionPart,
|
||||
std::optional<InternalSubprogramPart>, Statement<EndProgramStmt>>
|
||||
std::tuple<std::optional<Statement<ProgramStmt>>, SpecificationPart,
|
||||
ExecutionPart, std::optional<InternalSubprogramPart>,
|
||||
Statement<EndProgramStmt>>
|
||||
t;
|
||||
};
|
||||
|
||||
|
@ -2882,7 +2843,7 @@ struct Only {
|
|||
// R1410 module-nature -> INTRINSIC | NON_INTRINSIC
|
||||
struct UseStmt {
|
||||
BOILERPLATE(UseStmt);
|
||||
enum class ModuleNature { Intrinsic, Non_Intrinsic }; // R1410
|
||||
DEFINE_NESTED_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)) {}
|
||||
|
@ -2995,7 +2956,7 @@ struct InterfaceBody {
|
|||
|
||||
// R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list
|
||||
struct ProcedureStmt {
|
||||
enum class Kind { ModuleProcedure, Procedure };
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, ModuleProcedure, Procedure);
|
||||
TUPLE_CLASS_BOILERPLATE(ProcedureStmt);
|
||||
std::tuple<Kind, std::list<Name>> t;
|
||||
};
|
||||
|
@ -3184,7 +3145,6 @@ struct AssignedGotoStmt {
|
|||
WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
|
||||
|
||||
// Formatting of template types
|
||||
// TODO move elsewhere?
|
||||
template<typename A>
|
||||
std::ostream &operator<<(std::ostream &o, const Statement<A> &x) {
|
||||
return o << "(Statement " << x.label << ' '
|
||||
|
@ -3222,6 +3182,20 @@ std::ostream &operator<<(std::ostream &o, const LoopBounds<A> &x) {
|
|||
return o << "(LoopBounds " << x.name << ' ' << x.lower << ' ' << x.upper
|
||||
<< ' ' << x.step << ')';
|
||||
}
|
||||
|
||||
// Formatting enumerations defined via DEFINE_NESTED_ENUM_CLASS
|
||||
#define NESTED_ENUM_TO_STRING(ENUMTYPE) \
|
||||
static std::string ToString(ENUMTYPE x) { \
|
||||
std::string str{ENUMTYPE##AsString}; \
|
||||
size_t start{0}; \
|
||||
for (int j{static_cast<int>(x)}; j-- > 0;) { \
|
||||
start = str.find(',', start) + 1; \
|
||||
} \
|
||||
while (str[start] == ' ') { \
|
||||
++start; \
|
||||
} \
|
||||
return str.substr(start, str.find(',', start)); \
|
||||
}
|
||||
} // namespace parser
|
||||
} // namespace Fortran
|
||||
#endif // FORTRAN_PARSER_PARSE_TREE_H_
|
||||
|
|
|
@ -68,8 +68,39 @@ TokenSequence Definition::Tokenize(const std::vector<std::string> &argNames,
|
|||
return result;
|
||||
}
|
||||
|
||||
static size_t AfterLastNonBlank(const TokenSequence &tokens) {
|
||||
for (size_t j{tokens.size()}; j > 0; --j) {
|
||||
if (!tokens[j - 1].IsBlank()) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static TokenSequence Stringify(
|
||||
const TokenSequence &tokens, AllSources *allSources) {
|
||||
TokenSequence result;
|
||||
Provenance quoteProvenance{allSources->CompilerInsertionProvenance('"')};
|
||||
result.PutNextTokenChar('"', quoteProvenance);
|
||||
for (size_t j{0}; j < tokens.size(); ++j) {
|
||||
const CharPointerWithLength &token{tokens[j]};
|
||||
size_t bytes{token.size()};
|
||||
for (size_t k{0}; k < bytes; ++k) {
|
||||
char ch{token[k]};
|
||||
Provenance from{tokens.GetTokenProvenance(j, k)};
|
||||
if (ch == '"' || ch == '\\') {
|
||||
result.PutNextTokenChar(ch, from);
|
||||
}
|
||||
result.PutNextTokenChar(ch, from);
|
||||
}
|
||||
}
|
||||
result.PutNextTokenChar('"', quoteProvenance);
|
||||
result.CloseToken();
|
||||
return result;
|
||||
}
|
||||
|
||||
TokenSequence Definition::Apply(
|
||||
const std::vector<TokenSequence> &args, const AllSources &allSources) {
|
||||
const std::vector<TokenSequence> &args, AllSources *allSources) {
|
||||
TokenSequence result;
|
||||
bool pasting{false};
|
||||
bool skipping{false};
|
||||
|
@ -93,35 +124,16 @@ TokenSequence Definition::Apply(
|
|||
if (index >= args.size()) {
|
||||
continue;
|
||||
}
|
||||
size_t afterLastNonBlank{result.size()};
|
||||
for (; afterLastNonBlank > 0; --afterLastNonBlank) {
|
||||
if (!result[afterLastNonBlank - 1].IsBlank()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
size_t argTokens{args[index].size()};
|
||||
size_t afterLastNonBlank{AfterLastNonBlank(result)};
|
||||
if (afterLastNonBlank > 0 &&
|
||||
result[afterLastNonBlank - 1].ToString() == "#") {
|
||||
// stringifying
|
||||
while (result.size() >= afterLastNonBlank) {
|
||||
result.pop_back();
|
||||
}
|
||||
Provenance quoteProvenance{allSources.CompilerInsertionProvenance('"')};
|
||||
result.PutNextTokenChar('"', quoteProvenance);
|
||||
for (size_t k{0}; k < argTokens; ++k) {
|
||||
const CharPointerWithLength &arg{args[index][k]};
|
||||
size_t argBytes{args[index][k].size()};
|
||||
for (size_t n{0}; n < argBytes; ++n) {
|
||||
char ch{arg[n]};
|
||||
Provenance from{args[index].GetTokenProvenance(k, n)};
|
||||
if (ch == '"' || ch == '\\') {
|
||||
result.PutNextTokenChar(ch, from);
|
||||
}
|
||||
result.PutNextTokenChar(ch, from);
|
||||
}
|
||||
}
|
||||
result.PutNextTokenChar('"', quoteProvenance);
|
||||
result.CloseToken();
|
||||
result.Put(Stringify(args[index], allSources));
|
||||
} else {
|
||||
size_t argTokens{args[index].size()};
|
||||
for (size_t k{0}; k < argTokens; ++k) {
|
||||
if (!pasting || !args[index][k].IsBlank()) {
|
||||
result.Put(args[index], k);
|
||||
|
@ -143,9 +155,10 @@ TokenSequence Definition::Apply(
|
|||
// Delete whitespace immediately following ## in the body.
|
||||
} else if (bytes == 11 && isVariadic_ &&
|
||||
token.ToString() == "__VA_ARGS__") {
|
||||
Provenance commaProvenance{allSources->CompilerInsertionProvenance(',')};
|
||||
for (size_t k{argumentCount_}; k < args.size(); ++k) {
|
||||
if (k > argumentCount_) {
|
||||
result.Put(","s, allSources.CompilerInsertionProvenance(','));
|
||||
result.Put(","s, commaProvenance);
|
||||
}
|
||||
result.Put(args[k]);
|
||||
}
|
||||
|
@ -205,7 +218,7 @@ bool Preprocessor::MacroReplacement(const TokenSequence &input,
|
|||
}
|
||||
}
|
||||
if (j == tokens) {
|
||||
return false; // nothing appeared that could be replaced
|
||||
return false; // contains nothing that would be replaced
|
||||
}
|
||||
result->Put(input, 0, j);
|
||||
for (; j < tokens; ++j) {
|
||||
|
@ -300,7 +313,7 @@ bool Preprocessor::MacroReplacement(const TokenSequence &input,
|
|||
}
|
||||
def.set_isDisabled(true);
|
||||
TokenSequence replaced{
|
||||
ReplaceMacros(def.Apply(args, *allSources_), prescanner)};
|
||||
ReplaceMacros(def.Apply(args, allSources_), prescanner)};
|
||||
def.set_isDisabled(false);
|
||||
if (!replaced.empty()) {
|
||||
ProvenanceRange from{def.replacement().GetProvenanceRange()};
|
||||
|
|
|
@ -37,8 +37,7 @@ public:
|
|||
|
||||
bool set_isDisabled(bool disable);
|
||||
|
||||
TokenSequence Apply(
|
||||
const std::vector<TokenSequence> &args, const AllSources &);
|
||||
TokenSequence Apply(const std::vector<TokenSequence> &args, AllSources *);
|
||||
|
||||
private:
|
||||
static TokenSequence Tokenize(const std::vector<std::string> &argNames,
|
||||
|
|
|
@ -161,8 +161,11 @@ void Prescanner::NextChar() {
|
|||
}
|
||||
}
|
||||
while (*at_ == '\n' || *at_ == '&') {
|
||||
if ((inFixedForm_ && !FixedFormContinuation()) ||
|
||||
(!inFixedForm_ && !FreeFormContinuation())) {
|
||||
if (inFixedForm_) {
|
||||
if (!FixedFormContinuation()) {
|
||||
return;
|
||||
}
|
||||
} else if (!FreeFormContinuation()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -220,9 +223,7 @@ bool Prescanner::NextToken(TokenSequence *tokens) {
|
|||
EmitCharAndAdvance(tokens, 'h');
|
||||
inCharLiteral_ = true;
|
||||
while (n-- > 0) {
|
||||
if (PadOutCharacterLiteral()) {
|
||||
tokens->PutNextTokenChar(' ', spaceProvenance_);
|
||||
} else {
|
||||
if (!PadOutCharacterLiteral(tokens)) {
|
||||
if (*at_ == '\n') {
|
||||
break; // TODO error
|
||||
}
|
||||
|
@ -306,20 +307,42 @@ bool Prescanner::ExponentAndKind(TokenSequence *tokens) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Prescanner::EmitQuotedCharacter(TokenSequence *tokens, char ch) {
|
||||
switch (ch) {
|
||||
case '\a': EmitEscapedChar(tokens, 'a'); break;
|
||||
case '\b': EmitEscapedChar(tokens, 'b'); break;
|
||||
case '\f': EmitEscapedChar(tokens, 'f'); break;
|
||||
case '\r': EmitEscapedChar(tokens, 'r'); break;
|
||||
case '\t': EmitEscapedChar(tokens, 't'); break;
|
||||
case '\v': EmitEscapedChar(tokens, 'v'); break;
|
||||
case '\\':
|
||||
if (!enableBackslashEscapesInCharLiterals_) {
|
||||
EmitInsertedChar(tokens, '\\');
|
||||
}
|
||||
EmitChar(tokens, '\\');
|
||||
break;
|
||||
default:
|
||||
if (ch < ' ') {
|
||||
// emit an octal escape sequence
|
||||
EmitInsertedChar(tokens, '\\');
|
||||
EmitInsertedChar(tokens, '0' + ((ch >> 6) & 3));
|
||||
EmitInsertedChar(tokens, '0' + ((ch >> 3) & 7));
|
||||
EmitInsertedChar(tokens, '0' + (ch & 7));
|
||||
} else {
|
||||
EmitChar(tokens, ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Prescanner::QuotedCharacterLiteral(TokenSequence *tokens) {
|
||||
char quote{*at_};
|
||||
inCharLiteral_ = true;
|
||||
do {
|
||||
EmitCharAndAdvance(tokens, *at_);
|
||||
while (PadOutCharacterLiteral()) {
|
||||
tokens->PutNextTokenChar(' ', spaceProvenance_);
|
||||
EmitQuotedCharacter(tokens, *at_);
|
||||
NextChar();
|
||||
while (PadOutCharacterLiteral(tokens)) {
|
||||
}
|
||||
if (*at_ == '\\' && enableBackslashEscapesInCharLiterals_) {
|
||||
EmitCharAndAdvance(tokens, '\\');
|
||||
while (PadOutCharacterLiteral()) {
|
||||
tokens->PutNextTokenChar(' ', spaceProvenance_);
|
||||
}
|
||||
} else if (*at_ == quote) {
|
||||
if (*at_ == quote) {
|
||||
// A doubled quote mark becomes a single instance of the quote character
|
||||
// in the literal later.
|
||||
EmitCharAndAdvance(tokens, quote);
|
||||
|
@ -334,9 +357,10 @@ void Prescanner::QuotedCharacterLiteral(TokenSequence *tokens) {
|
|||
inCharLiteral_ = false;
|
||||
}
|
||||
|
||||
bool Prescanner::PadOutCharacterLiteral() {
|
||||
bool Prescanner::PadOutCharacterLiteral(TokenSequence *tokens) {
|
||||
if (inFixedForm_ && !tabInCurrentLine_ && *at_ == '\n' &&
|
||||
column_ < fixedFormColumnLimit_) {
|
||||
tokens->PutNextTokenChar(' ', spaceProvenance_);
|
||||
++column_;
|
||||
return true;
|
||||
}
|
||||
|
@ -502,7 +526,7 @@ bool Prescanner::CommentLinesAndPreprocessorDirectives() {
|
|||
|
||||
const char *Prescanner::FixedFormContinuationLine() {
|
||||
const char *p{lineStart_};
|
||||
if (p >= limit_) {
|
||||
if (p >= limit_ || !inFixedForm_) {
|
||||
return nullptr;
|
||||
}
|
||||
tabInCurrentLine_ = false;
|
||||
|
@ -539,6 +563,9 @@ bool Prescanner::FixedFormContinuation() {
|
|||
}
|
||||
|
||||
bool Prescanner::FreeFormContinuation() {
|
||||
if (inFixedForm_) {
|
||||
return false;
|
||||
}
|
||||
while (*at_ == ' ' || *at_ == '\t') {
|
||||
++at_;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,17 @@ private:
|
|||
tokens->PutNextTokenChar(ch, GetCurrentProvenance());
|
||||
}
|
||||
|
||||
void EmitInsertedChar(TokenSequence *tokens, char ch) {
|
||||
Provenance provenance{
|
||||
cooked_->allSources()->CompilerInsertionProvenance(ch)};
|
||||
tokens->PutNextTokenChar(ch, provenance);
|
||||
}
|
||||
|
||||
void EmitEscapedChar(TokenSequence *tokens, char ch) {
|
||||
EmitInsertedChar(tokens, '\\');
|
||||
EmitChar(tokens, ch);
|
||||
}
|
||||
|
||||
char EmitCharAndAdvance(TokenSequence *tokens, char ch) {
|
||||
EmitChar(tokens, ch);
|
||||
NextChar();
|
||||
|
@ -86,8 +97,9 @@ private:
|
|||
void SkipSpaces();
|
||||
bool NextToken(TokenSequence *);
|
||||
bool ExponentAndKind(TokenSequence *);
|
||||
void EmitQuotedCharacter(TokenSequence *, char);
|
||||
void QuotedCharacterLiteral(TokenSequence *);
|
||||
bool PadOutCharacterLiteral();
|
||||
bool PadOutCharacterLiteral(TokenSequence *);
|
||||
bool CommentLines();
|
||||
bool CommentLinesAndPreprocessorDirectives();
|
||||
bool IsFixedFormCommentLine(const char *);
|
||||
|
@ -123,6 +135,8 @@ private:
|
|||
int delimiterNesting_{0};
|
||||
Provenance spaceProvenance_{
|
||||
cooked_->allSources()->CompilerInsertionProvenance(' ')};
|
||||
Provenance backslashProvenance_{
|
||||
cooked_->allSources()->CompilerInsertionProvenance('\\')};
|
||||
};
|
||||
} // namespace parser
|
||||
} // namespace Fortran
|
||||
|
|
|
@ -66,11 +66,6 @@ AllSources::AllSources() : range_{1, 1} {
|
|||
// so that provenance offset 0 remains reserved as an uninitialized
|
||||
// value.
|
||||
origin_.emplace_back(range_, std::string{'?'});
|
||||
|
||||
for (char ch : " ,\"01\n"s) {
|
||||
compilerInsertionProvenance_[ch] =
|
||||
AddCompilerInsertion(std::string{ch}).LocalOffsetToProvenance(0);
|
||||
}
|
||||
}
|
||||
|
||||
AllSources::~AllSources() {}
|
||||
|
@ -231,8 +226,15 @@ int AllSources::GetLineNumber(Provenance at) const {
|
|||
return source ? source->FindOffsetLineAndColumn(offset).first : 0;
|
||||
}
|
||||
|
||||
Provenance AllSources::CompilerInsertionProvenance(char ch) const {
|
||||
return compilerInsertionProvenance_.find(ch)->second;
|
||||
Provenance AllSources::CompilerInsertionProvenance(char ch) {
|
||||
auto iter = compilerInsertionProvenance_.find(ch);
|
||||
if (iter != compilerInsertionProvenance_.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
ProvenanceRange newCharRange{AddCompilerInsertion(std::string{ch})};
|
||||
Provenance newCharProvenance{newCharRange.LocalOffsetToProvenance(0)};
|
||||
compilerInsertionProvenance_.insert(std::make_pair(ch, newCharProvenance));
|
||||
return newCharProvenance;
|
||||
}
|
||||
|
||||
AllSources::Origin::Origin(ProvenanceRange r, const SourceFile &source)
|
||||
|
|
|
@ -176,7 +176,7 @@ public:
|
|||
ProvenanceRange GetContiguousRangeAround(ProvenanceRange) const;
|
||||
std::string GetPath(Provenance) const; // __FILE__
|
||||
int GetLineNumber(Provenance) const; // __LINE__
|
||||
Provenance CompilerInsertionProvenance(char ch) const;
|
||||
Provenance CompilerInsertionProvenance(char ch);
|
||||
void Dump(std::ostream &) const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -199,7 +199,7 @@ struct CharLiteralChar {
|
|||
state->PutMessage(at, "unclosed character constant"_en_US);
|
||||
return {};
|
||||
}
|
||||
if (ch != '\\' || !state->enableBackslashEscapesInCharLiterals()) {
|
||||
if (ch != '\\') {
|
||||
return {Result::Bare(ch)};
|
||||
}
|
||||
if (!(och = nextChar.Parse(state)).has_value()) {
|
||||
|
|
|
@ -165,11 +165,9 @@ public:
|
|||
Put("END MODULE");
|
||||
return true;
|
||||
}
|
||||
bool Pre(const MainProgram &x) {
|
||||
if (std::get<std::optional<Statement<Name>>>(x.t)) {
|
||||
Put("PROGRAM ");
|
||||
Indent();
|
||||
}
|
||||
bool Pre(const ProgramStmt &x) {
|
||||
Put("PROGRAM ");
|
||||
Indent();
|
||||
return true;
|
||||
}
|
||||
bool Pre(const EndProgramStmt &x) {
|
||||
|
|
|
@ -147,7 +147,6 @@ int main(int argc, char *const argv[]) {
|
|||
Fortran::parser::ParseState state{cooked};
|
||||
Fortran::parser::UserState ustate;
|
||||
state.set_inFixedForm(fixedForm)
|
||||
.set_enableBackslashEscapesInCharLiterals(backslashEscapes)
|
||||
.set_strictConformance(standard)
|
||||
.set_userState(&ustate);
|
||||
|
||||
|
|
|
@ -202,7 +202,7 @@ static void visitDerivedTypeDef(const DerivedTypeDef &dtd) {
|
|||
std::visit(
|
||||
visitors{
|
||||
[&](const TypeAttrSpec::Extends &extends) {
|
||||
builder.extends(extends.name);
|
||||
builder.extends(extends.v);
|
||||
},
|
||||
[&](const TypeAttrSpec::BindC &) {
|
||||
builder.attr(semantics::Attr::BIND_C);
|
||||
|
|
Loading…
Reference in New Issue