From 4412cb03c475f7d4fce2ed474a7efe9f1d947c1d Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 20 Apr 2018 15:19:20 -0700 Subject: [PATCH] [flang] More clean-up. Original-commit: flang-compiler/f18@96dda922867e50f6f33a4ebe4d0fbc8e25141c5b Reviewed-on: https://github.com/flang-compiler/f18/pull/66 Tree-same-pre-rewrite: false --- flang/lib/parser/grammar.h | 134 ++++++--------------------------------- flang/lib/parser/parse-tree.h | 1 - flang/lib/parser/stmt-parser.h | 61 ++++++++++++++++++ flang/lib/parser/token-parsers.h | 24 ++++++- flang/lib/parser/type-parsers.h | 1 + flang/lib/parser/user-state.cc | 48 ++++++++++++++ flang/lib/parser/user-state.h | 13 ++++ 7 files changed, 166 insertions(+), 116 deletions(-) create mode 100644 flang/lib/parser/stmt-parser.h create mode 100644 flang/lib/parser/user-state.cc diff --git a/flang/lib/parser/grammar.h b/flang/lib/parser/grammar.h index 217664e..6d0be78 100644 --- a/flang/lib/parser/grammar.h +++ b/flang/lib/parser/grammar.h @@ -11,6 +11,7 @@ #include "characters.h" #include "debug-parser.h" #include "parse-tree.h" +#include "stmt-parser.h" #include "token-parsers.h" #include "type-parsers.h" #include "user-state.h" @@ -32,53 +33,6 @@ namespace parser { // on the definitions of symbols. The "Rxxx" numbers that appear in // comments refer to these numbered requirements in the Fortran standard. -// R711 digit-string -> digit [digit]... -// N.B. not a token -- no space is skipped -constexpr DigitString digitString; - -// statement(p) parses Statement

for some statement type P that is the -// result type of the argument parser p, while also handling labels and -// end-of-statement markers. - -// R611 label -> digit [digit]... -constexpr auto label = space >> digitString / spaceCheck; - -template -using statementConstructor = construct>; - -template inline constexpr auto unterminatedStatement(const PA &p) { - return skipEmptyLines >> - sourced(statementConstructor{}(maybe(label), space >> p)); -} - -constexpr auto endOfLine = "\n"_ch / skipEmptyLines || - fail("expected end of line"_err_en_US); - -constexpr auto endOfStmt = space >> - (";"_ch / skipMany(";"_tok) / maybe(endOfLine) || endOfLine); - -template inline constexpr auto statement(const PA &p) { - return unterminatedStatement(p) / endOfStmt; -} - -constexpr auto ignoredStatementPrefix = skipEmptyLines >> maybe(label) >> - maybe(name / ":") >> space; - -// Error recovery within statements: skip to the end of the line, -// but not over an END or CONTAINS statement. -constexpr auto errorRecovery = construct{}; -constexpr auto skipToEndOfLine = SkipTo<'\n'>{} >> errorRecovery; -constexpr auto stmtErrorRecovery = - !"END"_tok >> !"CONTAINS"_tok >> skipToEndOfLine; - -// Error recovery across statements: skip the line, unless it looks -// like it might end the containing construct. -constexpr auto errorRecoveryStart = ignoredStatementPrefix; -constexpr auto skipBadLine = SkipPast<'\n'>{} >> errorRecovery; -constexpr auto executionPartErrorRecovery = errorRecoveryStart >> !"END"_tok >> - !"CONTAINS"_tok >> !"ELSE"_tok >> !"CASE"_tok >> !"TYPE IS"_tok >> - !"CLASS"_tok >> !"RANK"_tok >> skipBadLine; - // R507 declaration-construct -> // specification-construct | data-stmt | format-stmt | // entry-stmt | stmt-function-stmt @@ -373,37 +327,8 @@ TYPE_PARSER(construct{}(indirect(Parser{})) || // END DO statements appear only at the ends of do-constructs that begin // with a nonlabel-do-stmt, so care must be taken to recognize this case and // essentially treat them like CONTINUE statements. -struct CapturedLabelDoStmt { - static constexpr auto parser = statement(indirect(Parser{})); - using resultType = Statement>; - static std::optional Parse(ParseState &state) { - auto result = parser.Parse(state); - if (result) { - if (auto ustate = state.userState()) { - ustate->NewDoLabel(std::get

for some statement type P that is the +// result type of the argument parser p, while also handling labels and +// end-of-statement markers. + +// R611 label -> digit [digit]... +constexpr auto label = space >> digitString / spaceCheck; + +template +using statementConstructor = construct>; + +template inline constexpr auto unterminatedStatement(const PA &p) { + return skipEmptyLines >> + sourced(statementConstructor{}(maybe(label), space >> p)); +} + +constexpr auto endOfLine = "\n"_ch / skipEmptyLines || + fail("expected end of line"_err_en_US); + +constexpr auto endOfStmt = space >> + (";"_ch / skipMany(";"_tok) / maybe(endOfLine) || endOfLine); + +template inline constexpr auto statement(const PA &p) { + return unterminatedStatement(p) / endOfStmt; +} + +constexpr auto ignoredStatementPrefix = skipEmptyLines >> maybe(label) >> + maybe(name / ":") >> space; + +// Error recovery within statements: skip to the end of the line, +// but not over an END or CONTAINS statement. +constexpr auto errorRecovery = construct{}; +constexpr auto skipToEndOfLine = SkipTo<'\n'>{} >> errorRecovery; +constexpr auto stmtErrorRecovery = + !"END"_tok >> !"CONTAINS"_tok >> skipToEndOfLine; + +// Error recovery across statements: skip the line, unless it looks +// like it might end the containing construct. +constexpr auto errorRecoveryStart = ignoredStatementPrefix; +constexpr auto skipBadLine = SkipPast<'\n'>{} >> errorRecovery; +constexpr auto executionPartErrorRecovery = errorRecoveryStart >> !"END"_tok >> + !"CONTAINS"_tok >> !"ELSE"_tok >> !"CASE"_tok >> !"TYPE IS"_tok >> + !"CLASS"_tok >> !"RANK"_tok >> skipBadLine; + +} // namespace parser +} // namespace Fortran +#endif // FORTRAN_PARSER_STMT_PARSER_H_ diff --git a/flang/lib/parser/token-parsers.h b/flang/lib/parser/token-parsers.h index 8637eb2..3042762 100644 --- a/flang/lib/parser/token-parsers.h +++ b/flang/lib/parser/token-parsers.h @@ -8,7 +8,9 @@ #include "char-set.h" #include "characters.h" #include "idioms.h" +#include "instrumented-parser.h" #include "provenance.h" +#include "type-parsers.h" #include #include #include @@ -523,10 +525,10 @@ struct HollerithLiteral { } }; -struct ConsumedAllInputParser { +constexpr struct ConsumedAllInputParser { using resultType = Success; constexpr ConsumedAllInputParser() {} - static std::optional Parse(ParseState &state) { + static inline std::optional Parse(ParseState &state) { if (state.IsAtEnd()) { return {Success{}}; } @@ -615,6 +617,24 @@ constexpr struct FormDirectivesAndEmptyLines { return {Success{}}; } } skipEmptyLines; + +// R602 underscore -> _ +constexpr auto underscore = "_"_ch; + +// R516 keyword -> name +// R601 alphanumeric-character -> letter | digit | underscore +// R603 name -> letter [alphanumeric-character]... +// N.B. Don't accept an underscore if it is immediately followed by a +// quotation mark, so that kindParameter_"character literal" is parsed properly. +// PGI and ifort accept '$' in identifiers, even as the initial character. +// Cray and gfortran accept '$', but not as the first character. +// Cray accepts '@' as well. +constexpr auto otherIdChar = underscore / !"'\""_ch || extension("$@"_ch); +constexpr auto nonDigitIdChar = letter || otherIdChar; +constexpr auto rawName = nonDigitIdChar >> many(nonDigitIdChar || digit); +TYPE_PARSER(space >> sourced(attempt(rawName) >> construct{})) +constexpr auto keyword = construct{}(name); + } // namespace parser } // namespace Fortran #endif // FORTRAN_PARSER_TOKEN_PARSERS_H_ diff --git a/flang/lib/parser/type-parsers.h b/flang/lib/parser/type-parsers.h index 128c0d2..d9ec348 100644 --- a/flang/lib/parser/type-parsers.h +++ b/flang/lib/parser/type-parsers.h @@ -2,6 +2,7 @@ #define FORTRAN_PARSER_TYPE_PARSERS_H_ #include "basic-parsers.h" +#include "instrumented-parser.h" #include "parse-tree.h" #include diff --git a/flang/lib/parser/user-state.cc b/flang/lib/parser/user-state.cc new file mode 100644 index 0000000..236ff4c --- /dev/null +++ b/flang/lib/parser/user-state.cc @@ -0,0 +1,48 @@ +#include "user-state.h" +#include "basic-parsers.h" +#include "grammar.h" +#include "parse-state.h" +#include "stmt-parser.h" +#include "type-parsers.h" +#include + +namespace Fortran { +namespace parser { + +std::optional StartNewSubprogram::Parse(ParseState &state) { + if (auto ustate = state.userState()) { + ustate->NewSubprogram(); + } + return {Success{}}; +} + +std::optional CapturedLabelDoStmt::Parse( + ParseState &state) { + static constexpr auto parser = statement(indirect(Parser{})); + auto result = parser.Parse(state); + if (result) { + if (auto ustate = state.userState()) { + ustate->NewDoLabel(std::get