From 20364f03517adf696b414f9dc0f27282462da0d1 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Thu, 1 Mar 2018 13:23:31 -0800 Subject: [PATCH] [flang] Ensure that the parse tree visitation Walk template works on FORMAT. The classes that were segregated into format-specification.h have also been grouped into a new Fortran::format namespace. Code added to tools/f18/f18.cc to run a minimal visitor over the parse trees resulting from successful parses so that any future build problems with Walk() will be caught earlier. Rearrange Walk instances, keep format:: ones together. Original-commit: flang-compiler/f18@685ddb91ceb2217877a887eca14a63a4b725ea12 Reviewed-on: https://github.com/flang-compiler/f18/pull/22 --- flang/lib/parser/format-specification.h | 2 + flang/lib/parser/grammar.h | 163 +++++++++++++----------- flang/lib/parser/parse-tree-visitor.h | 84 ++++++------ flang/lib/parser/parse-tree.cc | 77 +++++------ flang/lib/parser/parse-tree.h | 5 +- flang/lib/parser/unparse.cc | 2 - flang/tools/f18/f18.cc | 33 +++-- 7 files changed, 202 insertions(+), 164 deletions(-) diff --git a/flang/lib/parser/format-specification.h b/flang/lib/parser/format-specification.h index 0404449e80d0..ea40df708961 100644 --- a/flang/lib/parser/format-specification.h +++ b/flang/lib/parser/format-specification.h @@ -17,6 +17,7 @@ #include namespace Fortran { +namespace format { // R1307 data-edit-desc (part 1 of 2) -> // I w [. m] | B w [. m] | O w [. m] | Z w [. m] | F w . d | @@ -129,5 +130,6 @@ struct FormatSpecification { : items(std::move(is)), unlimitedItems(std::move(us)) {} std::list items, unlimitedItems; }; +} // namespace format } // namespace Fortran #endif // FORTRAN_FORMAT_SPECIFICATION_H_ diff --git a/flang/lib/parser/grammar.h b/flang/lib/parser/grammar.h index a0b45fcfa08b..54d83853f26d 100644 --- a/flang/lib/parser/grammar.h +++ b/flang/lib/parser/grammar.h @@ -9,7 +9,6 @@ #include "basic-parsers.h" #include "characters.h" -#include "format-specification.h" #include "parse-tree.h" #include "token-parsers.h" #include "user-state.h" @@ -3060,7 +3059,7 @@ TYPE_CONTEXT_PARSER("INQUIRE statement"_en_US, // R1301 format-stmt -> FORMAT format-specification TYPE_CONTEXT_PARSER("FORMAT statement"_en_US, - "FORMAT" >> construct{}(Parser{})) + "FORMAT" >> construct{}(Parser{})) // R1321 char-string-edit-desc // N.B. C1313 disallows any kind parameter on the character literal. @@ -3069,7 +3068,7 @@ constexpr auto charStringEditDesc = spaces >> // R1303 format-items -> format-item [[,] format-item]... constexpr auto formatItems = - nonemptySeparated(Parser{}, maybe(","_tok)); + nonemptySeparated(Parser{}, maybe(","_tok)); // R1306 r -> digit-string static inline int castU64ToInt(std::uint64_t &&n) { @@ -3081,20 +3080,21 @@ constexpr auto repeat = spaces >> applyFunction(castU64ToInt, digitString); // R1304 format-item -> // [r] data-edit-desc | control-edit-desc | char-string-edit-desc | // [r] ( format-items ) -TYPE_PARSER(construct{}( - maybe(repeat), Parser{}) || - construct{}(maybe(repeat), Parser{}) || - construct{}(Parser{}) || - construct{}(charStringEditDesc) || - construct{}(maybe(repeat), parenthesized(formatItems))) +TYPE_PARSER(construct{}( + maybe(repeat), Parser{}) || + construct{}( + maybe(repeat), Parser{}) || + construct{}(Parser{}) || + construct{}(charStringEditDesc) || + construct{}(maybe(repeat), parenthesized(formatItems))) // R1302 format-specification -> // ( [format-items] ) | ( [format-items ,] unlimited-format-item ) // R1305 unlimited-format-item -> * ( format-items ) -TYPE_PARSER( - parenthesized(construct{}(defaulted(formatItems)) || - construct{}( - defaulted(formatItems / ","), "*" >> parenthesized(formatItems)))) +TYPE_PARSER(parenthesized( + construct{}(defaulted(formatItems)) || + construct{}( + defaulted(formatItems / ","), "*" >> parenthesized(formatItems)))) // R1308 w -> digit-string // R1309 m -> digit-string // R1310 d -> digit-string @@ -3111,54 +3111,54 @@ constexpr auto mandatoryDigits = "." >> construct>{}(width); // G w [. d [E e]] | L w | A [w] | D w . d | // DT [char-literal-constant] [( v-list )] // (part 1 of 2) -TYPE_PARSER(construct{}( - "I" >> pure(IntrinsicTypeDataEditDesc::Kind::I) || - "B" >> pure(IntrinsicTypeDataEditDesc::Kind::B) || - "O" >> pure(IntrinsicTypeDataEditDesc::Kind::O) || - "Z" >> pure(IntrinsicTypeDataEditDesc::Kind::Z), +TYPE_PARSER(construct{}( + "I" >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) || + "B" >> pure(format::IntrinsicTypeDataEditDesc::Kind::B) || + "O" >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) || + "Z" >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z), mandatoryWidth, maybe("." >> digits), noInt) || - construct{}( - "F" >> pure(IntrinsicTypeDataEditDesc::Kind::F) || - "D" >> pure(IntrinsicTypeDataEditDesc::Kind::D), + construct{}( + "F" >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) || + "D" >> pure(format::IntrinsicTypeDataEditDesc::Kind::D), mandatoryWidth, mandatoryDigits, noInt) || - construct{}( - "EN" >> pure(IntrinsicTypeDataEditDesc::Kind::EN) || - "ES" >> pure(IntrinsicTypeDataEditDesc::Kind::ES) || - "EX" >> pure(IntrinsicTypeDataEditDesc::Kind::EX) || - "E" >> pure(IntrinsicTypeDataEditDesc::Kind::E), + construct{}( + "EN" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) || + "ES" >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) || + "EX" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) || + "E" >> pure(format::IntrinsicTypeDataEditDesc::Kind::E), mandatoryWidth, mandatoryDigits, maybe("E" >> digits)) || - construct{}( - "G" >> pure(IntrinsicTypeDataEditDesc::Kind::G), mandatoryWidth, + construct{}( + "G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G), mandatoryWidth, mandatoryDigits, maybe("E" >> digits)) || - construct{}( - "G" >> pure(IntrinsicTypeDataEditDesc::Kind::G) || - "L" >> pure(IntrinsicTypeDataEditDesc::Kind::L), + construct{}( + "G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) || + "L" >> pure(format::IntrinsicTypeDataEditDesc::Kind::L), mandatoryWidth, noInt, noInt) || - construct{}( - "A" >> pure(IntrinsicTypeDataEditDesc::Kind::A), maybe(width), noInt, - noInt) || + construct{}( + "A" >> pure(format::IntrinsicTypeDataEditDesc::Kind::A), maybe(width), + noInt, noInt) || // PGI/Intel extension: omitting width (and all else that follows) - extension(construct{}( - "I" >> pure(IntrinsicTypeDataEditDesc::Kind::I) || + extension(construct{}( + "I" >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) || ("B"_tok / !letter /* don't occlude BN & BZ */) >> - pure(IntrinsicTypeDataEditDesc::Kind::B) || - "O" >> pure(IntrinsicTypeDataEditDesc::Kind::O) || - "Z" >> pure(IntrinsicTypeDataEditDesc::Kind::Z) || - "F" >> pure(IntrinsicTypeDataEditDesc::Kind::F) || + pure(format::IntrinsicTypeDataEditDesc::Kind::B) || + "O" >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) || + "Z" >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z) || + "F" >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) || ("D"_tok / !letter /* don't occlude DC & DP */) >> - pure(IntrinsicTypeDataEditDesc::Kind::D) || - "EN" >> pure(IntrinsicTypeDataEditDesc::Kind::EN) || - "ES" >> pure(IntrinsicTypeDataEditDesc::Kind::ES) || - "EX" >> pure(IntrinsicTypeDataEditDesc::Kind::EX) || - "E" >> pure(IntrinsicTypeDataEditDesc::Kind::E) || - "G" >> pure(IntrinsicTypeDataEditDesc::Kind::G) || - "L" >> pure(IntrinsicTypeDataEditDesc::Kind::L), + pure(format::IntrinsicTypeDataEditDesc::Kind::D) || + "EN" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) || + "ES" >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) || + "EX" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) || + "E" >> pure(format::IntrinsicTypeDataEditDesc::Kind::E) || + "G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) || + "L" >> pure(format::IntrinsicTypeDataEditDesc::Kind::L), noInt, noInt, noInt))) // R1307 data-edit-desc (part 2 of 2) // R1312 v -> [sign] digit-string TYPE_PARSER("DT" >> - construct{}( + construct{}( spaces >> defaulted(charLiteralConstantWithoutKind), defaulted(parenthesized(nonemptyList(spaces >> signedDigitString))))) @@ -3178,32 +3178,47 @@ constexpr auto scaleFactor = spaces >> // R1318 blank-interp-edit-desc -> BN | BZ // R1319 round-edit-desc -> RU | RD | RZ | RN | RC | RP // R1320 decimal-edit-desc -> DC | DP -TYPE_PARSER( - construct{}("TL" >> pure(ControlEditDesc::Kind::TL) || - "TR" >> pure(ControlEditDesc::Kind::TR) || - "T" >> pure(ControlEditDesc::Kind::T), - repeat) || - construct{}(repeat, - "X" >> pure(ControlEditDesc::Kind::X) || - "/" >> pure(ControlEditDesc::Kind::Slash)) || - construct{}("X" >> pure(ControlEditDesc::Kind::X) || - "/" >> pure(ControlEditDesc::Kind::Slash)) || - construct{}( - scaleFactor, "P" >> pure(ControlEditDesc::Kind::P)) || - ":" >> construct{}(pure(ControlEditDesc::Kind::Colon)) || - "SS" >> construct{}(pure(ControlEditDesc::Kind::SS)) || - "SP" >> construct{}(pure(ControlEditDesc::Kind::SP)) || - "S" >> construct{}(pure(ControlEditDesc::Kind::S)) || - "BN" >> construct{}(pure(ControlEditDesc::Kind::BN)) || - "BZ" >> construct{}(pure(ControlEditDesc::Kind::BZ)) || - "RU" >> construct{}(pure(ControlEditDesc::Kind::RU)) || - "RD" >> construct{}(pure(ControlEditDesc::Kind::RD)) || - "RZ" >> construct{}(pure(ControlEditDesc::Kind::RZ)) || - "RN" >> construct{}(pure(ControlEditDesc::Kind::RN)) || - "RC" >> construct{}(pure(ControlEditDesc::Kind::RC)) || - "RP" >> construct{}(pure(ControlEditDesc::Kind::RP)) || - "DC" >> construct{}(pure(ControlEditDesc::Kind::DC)) || - "DP" >> construct{}(pure(ControlEditDesc::Kind::DP))) +TYPE_PARSER(construct{}( + "TL" >> pure(format::ControlEditDesc::Kind::TL) || + "TR" >> pure(format::ControlEditDesc::Kind::TR) || + "T" >> pure(format::ControlEditDesc::Kind::T), + repeat) || + construct{}(repeat, + "X" >> pure(format::ControlEditDesc::Kind::X) || + "/" >> pure(format::ControlEditDesc::Kind::Slash)) || + construct{}( + "X" >> pure(format::ControlEditDesc::Kind::X) || + "/" >> pure(format::ControlEditDesc::Kind::Slash)) || + construct{}( + scaleFactor, "P" >> pure(format::ControlEditDesc::Kind::P)) || + ":" >> construct{}( + pure(format::ControlEditDesc::Kind::Colon)) || + "SS" >> construct{}( + pure(format::ControlEditDesc::Kind::SS)) || + "SP" >> construct{}( + pure(format::ControlEditDesc::Kind::SP)) || + "S" >> construct{}( + pure(format::ControlEditDesc::Kind::S)) || + "BN" >> construct{}( + pure(format::ControlEditDesc::Kind::BN)) || + "BZ" >> construct{}( + pure(format::ControlEditDesc::Kind::BZ)) || + "RU" >> construct{}( + pure(format::ControlEditDesc::Kind::RU)) || + "RD" >> construct{}( + pure(format::ControlEditDesc::Kind::RD)) || + "RZ" >> construct{}( + pure(format::ControlEditDesc::Kind::RZ)) || + "RN" >> construct{}( + pure(format::ControlEditDesc::Kind::RN)) || + "RC" >> construct{}( + pure(format::ControlEditDesc::Kind::RC)) || + "RP" >> construct{}( + pure(format::ControlEditDesc::Kind::RP)) || + "DC" >> construct{}( + pure(format::ControlEditDesc::Kind::DC)) || + "DP" >> construct{}( + pure(format::ControlEditDesc::Kind::DP))) // R1401 main-program -> // [program-stmt] [specification-part] [execution-part] diff --git a/flang/lib/parser/parse-tree-visitor.h b/flang/lib/parser/parse-tree-visitor.h index 24aac7099562..56d7af4d1300 100644 --- a/flang/lib/parser/parse-tree-visitor.h +++ b/flang/lib/parser/parse-tree-visitor.h @@ -1,7 +1,6 @@ #ifndef FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ #define FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ -#include "format-specification.h" #include "parse-tree.h" #include #include @@ -28,6 +27,12 @@ Walk(const A &x, V &visitor) { } } +template void Walk(const format::ControlEditDesc &, V &); +template void Walk(const format::DerivedTypeDataEditDesc &, V &); +template void Walk(const format::FormatItem &, V &); +template void Walk(const format::FormatSpecification &, V &); +template void Walk(const format::IntrinsicTypeDataEditDesc &, V &); + // Traversal of needed STL template classes (optional, list, tuple, variant) template void Walk(const std::optional &x, V &visitor) { @@ -173,44 +178,6 @@ template void Walk(const DeclarationTypeSpec::Type &x, V &visitor) { visitor.Post(x); } } -template void Walk(const Fortran::ControlEditDesc &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.kind, visitor); - visitor.Post(x); - } -} -template -void Walk(const Fortran::DerivedTypeDataEditDesc &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.type, visitor); - Walk(x.parameters, visitor); - visitor.Post(x); - } -} -template void Walk(const Fortran::FormatItem &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.repeatCount, visitor); - Walk(x.u, visitor); - visitor.Post(x); - } -} -template void Walk(const FormatSpecification &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.items, visitor); - Walk(x.unlimitedItems, visitor); - visitor.Post(x); - } -} -template -void Walk(const Fortran::IntrinsicTypeDataEditDesc &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.kind, visitor); - Walk(x.width, visitor); - Walk(x.digits, visitor); - Walk(x.exponentWidth, visitor); - visitor.Post(x); - } -} template void Walk(const ImportStmt &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.names, visitor); @@ -327,6 +294,45 @@ template void Walk(const WriteStmt &x, V &visitor) { visitor.Post(x); } } +template void Walk(const format::ControlEditDesc &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.kind, visitor); + visitor.Post(x); + } +} +template +void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.type, visitor); + Walk(x.parameters, visitor); + visitor.Post(x); + } +} +template void Walk(const format::FormatItem &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.repeatCount, visitor); + Walk(x.u, visitor); + visitor.Post(x); + } +} +template +void Walk(const format::FormatSpecification &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.items, visitor); + Walk(x.unlimitedItems, visitor); + visitor.Post(x); + } +} +template +void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.kind, visitor); + Walk(x.width, visitor); + Walk(x.digits, visitor); + Walk(x.exponentWidth, visitor); + visitor.Post(x); + } +} } // namespace parser } // namespace Fortran #endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ diff --git a/flang/lib/parser/parse-tree.cc b/flang/lib/parser/parse-tree.cc index aeefcce84eb3..3d17ac868377 100644 --- a/flang/lib/parser/parse-tree.cc +++ b/flang/lib/parser/parse-tree.cc @@ -306,7 +306,8 @@ std::ostream &operator<<(std::ostream &o, const Rename::Names &x) { // R1411 #undef TUPLE_FORMATTER // R1302 format-specification -std::ostream &operator<<(std::ostream &o, const FormatSpecification &x) { +std::ostream &operator<<( + std::ostream &o, const format::FormatSpecification &x) { return o << "(FormatSpecification " << x.items << ' ' << x.unlimitedItems << ')'; } @@ -821,22 +822,23 @@ std::ostream &operator<<(std::ostream &o, const CaseValueRange::Range &x) { } // R1307 data-edit-desc (part 1 of 2) -std::ostream &operator<<(std::ostream &o, const IntrinsicTypeDataEditDesc &x) { +std::ostream &operator<<( + std::ostream &o, const format::IntrinsicTypeDataEditDesc &x) { o << "(IntrinsicTypeDataEditDesc "; switch (x.kind) { - case IntrinsicTypeDataEditDesc::Kind::I: o << "I "; break; - case IntrinsicTypeDataEditDesc::Kind::B: o << "B "; break; - case IntrinsicTypeDataEditDesc::Kind::O: o << "O "; break; - case IntrinsicTypeDataEditDesc::Kind::Z: o << "Z "; break; - case IntrinsicTypeDataEditDesc::Kind::F: o << "F "; break; - case IntrinsicTypeDataEditDesc::Kind::E: o << "E "; break; - case IntrinsicTypeDataEditDesc::Kind::EN: o << "EN "; break; - case IntrinsicTypeDataEditDesc::Kind::ES: o << "ES "; break; - case IntrinsicTypeDataEditDesc::Kind::EX: o << "EX "; break; - case IntrinsicTypeDataEditDesc::Kind::G: o << "G "; break; - case IntrinsicTypeDataEditDesc::Kind::L: o << "L "; break; - case IntrinsicTypeDataEditDesc::Kind::A: o << "A "; break; - case IntrinsicTypeDataEditDesc::Kind::D: o << "D "; break; + case format::IntrinsicTypeDataEditDesc::Kind::I: o << "I "; break; + case format::IntrinsicTypeDataEditDesc::Kind::B: o << "B "; break; + case format::IntrinsicTypeDataEditDesc::Kind::O: o << "O "; break; + case format::IntrinsicTypeDataEditDesc::Kind::Z: o << "Z "; break; + case format::IntrinsicTypeDataEditDesc::Kind::F: o << "F "; break; + case format::IntrinsicTypeDataEditDesc::Kind::E: o << "E "; break; + case format::IntrinsicTypeDataEditDesc::Kind::EN: o << "EN "; break; + case format::IntrinsicTypeDataEditDesc::Kind::ES: o << "ES "; break; + case format::IntrinsicTypeDataEditDesc::Kind::EX: o << "EX "; break; + case format::IntrinsicTypeDataEditDesc::Kind::G: o << "G "; break; + case format::IntrinsicTypeDataEditDesc::Kind::L: o << "L "; break; + case format::IntrinsicTypeDataEditDesc::Kind::A: o << "A "; break; + case format::IntrinsicTypeDataEditDesc::Kind::D: o << "D "; break; default: CRASH_NO_CASE; } return o << x.width << ' ' << x.digits << ' ' << x.exponentWidth << ')'; @@ -855,41 +857,42 @@ std::ostream &operator<<(std::ostream &o, const WriteStmt &x) { } // R1307 data-edit-desc (part 2 of 2) -std::ostream &operator<<(std::ostream &o, const DerivedTypeDataEditDesc &x) { +std::ostream &operator<<( + std::ostream &o, const format::DerivedTypeDataEditDesc &x) { return o << "(DerivedTypeDataEditDesc " << x.type << ' ' << x.parameters << ')'; } // R1313 control-edit-desc -std::ostream &operator<<(std::ostream &o, const ControlEditDesc &x) { +std::ostream &operator<<(std::ostream &o, const format::ControlEditDesc &x) { o << "(ControlEditDesc "; switch (x.kind) { - case ControlEditDesc::Kind::T: o << "T "; break; - case ControlEditDesc::Kind::TL: o << "TL "; break; - case ControlEditDesc::Kind::TR: o << "TR "; break; - case ControlEditDesc::Kind::X: o << "X "; break; - case ControlEditDesc::Kind::Slash: o << "/ "; break; - case ControlEditDesc::Kind::Colon: o << ": "; break; - case ControlEditDesc::Kind::SS: o << "SS "; break; - case ControlEditDesc::Kind::SP: o << "SP "; break; - case ControlEditDesc::Kind::S: o << "S "; break; - case ControlEditDesc::Kind::P: o << "P "; break; - case ControlEditDesc::Kind::BN: o << "BN "; break; - case ControlEditDesc::Kind::BZ: o << "BZ "; break; - case ControlEditDesc::Kind::RU: o << "RU "; break; - case ControlEditDesc::Kind::RD: o << "RD "; break; - case ControlEditDesc::Kind::RN: o << "RN "; break; - case ControlEditDesc::Kind::RC: o << "RC "; break; - case ControlEditDesc::Kind::RP: o << "RP "; break; - case ControlEditDesc::Kind::DC: o << "DC "; break; - case ControlEditDesc::Kind::DP: o << "DP "; break; + case format::ControlEditDesc::Kind::T: o << "T "; break; + case format::ControlEditDesc::Kind::TL: o << "TL "; break; + case format::ControlEditDesc::Kind::TR: o << "TR "; break; + case format::ControlEditDesc::Kind::X: o << "X "; break; + case format::ControlEditDesc::Kind::Slash: o << "/ "; break; + case format::ControlEditDesc::Kind::Colon: o << ": "; break; + case format::ControlEditDesc::Kind::SS: o << "SS "; break; + case format::ControlEditDesc::Kind::SP: o << "SP "; break; + case format::ControlEditDesc::Kind::S: o << "S "; break; + case format::ControlEditDesc::Kind::P: o << "P "; break; + case format::ControlEditDesc::Kind::BN: o << "BN "; break; + case format::ControlEditDesc::Kind::BZ: o << "BZ "; break; + case format::ControlEditDesc::Kind::RU: o << "RU "; break; + case format::ControlEditDesc::Kind::RD: o << "RD "; break; + case format::ControlEditDesc::Kind::RN: o << "RN "; break; + case format::ControlEditDesc::Kind::RC: o << "RC "; break; + case format::ControlEditDesc::Kind::RP: o << "RP "; break; + case format::ControlEditDesc::Kind::DC: o << "DC "; break; + case format::ControlEditDesc::Kind::DP: o << "DP "; break; default: CRASH_NO_CASE; } return o << x.count << ')'; } // R1304 format-item -std::ostream &operator<<(std::ostream &o, const FormatItem &x) { +std::ostream &operator<<(std::ostream &o, const format::FormatItem &x) { o << "(FormatItem " << x.repeatCount; std::visit([&o](const auto &y) { o << y; }, x.u); return o << ')'; diff --git a/flang/lib/parser/parse-tree.h b/flang/lib/parser/parse-tree.h index 49b774e2523e..2db2226f7df9 100644 --- a/flang/lib/parser/parse-tree.h +++ b/flang/lib/parser/parse-tree.h @@ -7,7 +7,7 @@ // 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). +// (viz., format-specification.h). #include "format-specification.h" #include "idioms.h" @@ -118,7 +118,6 @@ struct WhereConstruct; // R1042 struct ForallConstruct; // R1050 struct InputImpliedDo; // R1218 struct OutputImpliedDo; // R1218 -struct FormatItems; // R1303 struct FunctionReference; // R1520 struct FunctionSubprogram; // R1529 struct SubroutineSubprogram; // R1534 @@ -2706,7 +2705,7 @@ struct InquireStmt { }; // R1301 format-stmt -> FORMAT format-specification -WRAPPER_CLASS(FormatStmt, FormatSpecification); +WRAPPER_CLASS(FormatStmt, format::FormatSpecification); // R1402 program-stmt -> PROGRAM program-name WRAPPER_CLASS(ProgramStmt, Name); diff --git a/flang/lib/parser/unparse.cc b/flang/lib/parser/unparse.cc index a0788fe30ae3..c25d35b18be1 100644 --- a/flang/lib/parser/unparse.cc +++ b/flang/lib/parser/unparse.cc @@ -1,6 +1,4 @@ #include "unparse.h" - -#include "format-specification.h" #include "idioms.h" #include "indirection.h" #include "parse-tree-visitor.h" diff --git a/flang/tools/f18/f18.cc b/flang/tools/f18/f18.cc index 89895b240f40..1f475f0f2ed2 100644 --- a/flang/tools/f18/f18.cc +++ b/flang/tools/f18/f18.cc @@ -4,6 +4,7 @@ #include "../../lib/parser/idioms.h" #include "../../lib/parser/message.h" #include "../../lib/parser/parse-tree.h" +#include "../../lib/parser/parse-tree-visitor.h" #include "../../lib/parser/preprocessor.h" #include "../../lib/parser/prescan.h" #include "../../lib/parser/provenance.h" @@ -22,9 +23,7 @@ #include #include -namespace { - -std::list argList(int argc, char *const argv[]) { +static std::list argList(int argc, char *const argv[]) { std::list result; for (int j = 0; j < argc; ++j) { result.emplace_back(argv[j]); @@ -32,14 +31,30 @@ std::list argList(int argc, char *const argv[]) { return result; } -} // namespace - namespace Fortran { namespace parser { constexpr auto grammar = program; } // namespace parser } // namespace Fortran using Fortran::parser::grammar; +using ParseTree = typename decltype(grammar)::resultType; + +struct MeasurementVisitor { + template bool Pre(const A &) { return true; } + template void Post(const A &) { + ++objects; + bytes += sizeof(A); + } + size_t objects{0}, bytes{0}; +}; + +void MeasureParseTree(const ParseTree &program) { + MeasurementVisitor visitor; + Fortran::parser::Walk(program, visitor); + std::cout << "Parse tree comprises " << visitor.objects + << " objects and occupies " << visitor.bytes + << " total bytes.\n"; +} int main(int argc, char *const argv[]) { @@ -135,7 +150,7 @@ int main(int argc, char *const argv[]) { .Prescan(range)}; messages.Emit(std::cerr); if (!prescanOk) { - return 1; + return EXIT_FAILURE; } columns = std::numeric_limits::max(); @@ -154,12 +169,12 @@ int main(int argc, char *const argv[]) { while (std::optional och{state.GetNextChar()}) { std::cout << *och; } - return 0; + return EXIT_SUCCESS; } - std::optional result{ - grammar.Parse(&state)}; + std::optional result{grammar.Parse(&state)}; if (result.has_value() && !state.anyErrorRecovery()) { + MeasureParseTree(*result); Unparse(std::cout, *result); return EXIT_SUCCESS; } else {