From 40c797d773c2542249ef792a87953307e270705a Mon Sep 17 00:00:00 2001 From: peter klausler Date: Thu, 11 Jul 2019 16:50:43 -0700 Subject: [PATCH] [flang] Add "..."_id token syntax for complete tokens with lookahead Original-commit: flang-compiler/f18@19695ccfa4f2db50fb65af3f4db1bb595ef2f568 Reviewed-on: https://github.com/flang-compiler/f18/pull/569 Tree-same-pre-rewrite: false --- flang/documentation/ParserCombinators.md | 2 + flang/lib/parser/openmp-grammar.h | 76 ++++++++++++++++---------------- flang/lib/parser/token-parsers.h | 41 ++++++++++------- 3 files changed, 66 insertions(+), 53 deletions(-) diff --git a/flang/documentation/ParserCombinators.md b/flang/documentation/ParserCombinators.md index 4f60ceb..c10db06 100644 --- a/flang/documentation/ParserCombinators.md +++ b/flang/documentation/ParserCombinators.md @@ -143,6 +143,8 @@ is built. All of the following parsers consume characters acquired from the combinator `/`. * `"..."_sptok` is a string match in which the spaces are required in free form source. +* `"..."_id` is a string match for a complete identifier (not a prefix of + a longer identifier or keyword). * `parenthesized(p)` is shorthand for `"(" >> p / ")"`. * `bracketed(p)` is shorthand for `"[" >> p / "]"`. * `nonEmptyList(p)` matches a comma-separated list of one or more diff --git a/flang/lib/parser/openmp-grammar.h b/flang/lib/parser/openmp-grammar.h index 86907ce..3fc6a58 100644 --- a/flang/lib/parser/openmp-grammar.h +++ b/flang/lib/parser/openmp-grammar.h @@ -44,28 +44,28 @@ constexpr auto endOmpLine = space >> endOfLine; // OpenMP Clauses // DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE ) TYPE_PARSER(construct( - "PRIVATE" >> pure(OmpDefaultClause::Type::Private) || - "FIRSTPRIVATE" >> pure(OmpDefaultClause::Type::Firstprivate) || - "SHARED" >> pure(OmpDefaultClause::Type::Shared) || - "NONE" >> pure(OmpDefaultClause::Type::None))) + "PRIVATE"_id >> pure(OmpDefaultClause::Type::Private) || + "FIRSTPRIVATE"_id >> pure(OmpDefaultClause::Type::Firstprivate) || + "SHARED"_id >> pure(OmpDefaultClause::Type::Shared) || + "NONE"_id >> pure(OmpDefaultClause::Type::None))) // PROC_BIND(CLOSE | MASTER | SPREAD) TYPE_PARSER(construct( - "CLOSE" >> pure(OmpProcBindClause::Type::Close) || - "MASTER" >> pure(OmpProcBindClause::Type::Master) || - "SPREAD" >> pure(OmpProcBindClause::Type::Spread))) + "CLOSE"_id >> pure(OmpProcBindClause::Type::Close) || + "MASTER"_id >> pure(OmpProcBindClause::Type::Master) || + "SPREAD"_id >> pure(OmpProcBindClause::Type::Spread))) // MAP ([ [map-type-modifier[,]] map-type : ] list) // map-type-modifier -> ALWAYS // map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE TYPE_PARSER(construct( - maybe("ALWAYS" >> construct() / maybe(","_tok)), - "TO" >> pure(OmpMapType::Type::To) / ":"_tok || - "FROM" >> pure(OmpMapType::Type::From) / ":"_tok || - "TOFROM" >> pure(OmpMapType::Type::Tofrom) / ":"_tok || - "ALLOC" >> pure(OmpMapType::Type::Alloc) / ":"_tok || - "RELEASE" >> pure(OmpMapType::Type::Release) / ":"_tok || - "DELETE" >> pure(OmpMapType::Type::Delete) / ":"_tok)) + maybe("ALWAYS"_id >> construct() / maybe(","_tok)), + "TO"_id >> pure(OmpMapType::Type::To) / ":"_tok || + "FROM"_id >> pure(OmpMapType::Type::From) / ":"_tok || + "TOFROM"_id >> pure(OmpMapType::Type::Tofrom) / ":"_tok || + "ALLOC"_id >> pure(OmpMapType::Type::Alloc) / ":"_tok || + "RELEASE"_id >> pure(OmpMapType::Type::Release) / ":"_tok || + "DELETE"_id >> pure(OmpMapType::Type::Delete) / ":"_tok)) TYPE_PARSER(construct( maybe(Parser{}), Parser{})) @@ -75,36 +75,36 @@ TYPE_PARSER(construct( // kind -> STATIC | DYNAMIC | GUIDED | AUTO | RUNTIME // chunk_size -> ScalarIntExpr TYPE_PARSER(construct( - "MONOTONIC" >> pure(OmpScheduleModifierType::ModType::Monotonic) || - "NONMONOTONIC" >> pure(OmpScheduleModifierType::ModType::Nonmonotonic) || - "SIMD" >> pure(OmpScheduleModifierType::ModType::Simd))) + "MONOTONIC"_id >> pure(OmpScheduleModifierType::ModType::Monotonic) || + "NONMONOTONIC"_id >> pure(OmpScheduleModifierType::ModType::Nonmonotonic) || + "SIMD"_id >> pure(OmpScheduleModifierType::ModType::Simd))) TYPE_PARSER(construct(Parser{}, maybe(","_tok >> Parser{}) / ":"_tok)) TYPE_PARSER(construct(maybe(Parser{}), - "STATIC" >> pure(OmpScheduleClause::ScheduleType::Static) || - "DYNAMIC" >> pure(OmpScheduleClause::ScheduleType::Dynamic) || - "GUIDED" >> pure(OmpScheduleClause::ScheduleType::Guided) || - "AUTO" >> pure(OmpScheduleClause::ScheduleType::Auto) || - "RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime), + "STATIC"_id >> pure(OmpScheduleClause::ScheduleType::Static) || + "DYNAMIC"_id >> pure(OmpScheduleClause::ScheduleType::Dynamic) || + "GUIDED"_id >> pure(OmpScheduleClause::ScheduleType::Guided) || + "AUTO"_id >> pure(OmpScheduleClause::ScheduleType::Auto) || + "RUNTIME"_id >> pure(OmpScheduleClause::ScheduleType::Runtime), maybe(","_tok >> scalarIntExpr))) // IF(directive-name-modifier: scalar-logical-expr) TYPE_PARSER(construct( maybe( - ("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) || - "TARGET ENTER DATA" >> + ("PARALLEL"_id >> pure(OmpIfClause::DirectiveNameModifier::Parallel) || + "TARGET ENTER DATA"_id >> pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) || - "TARGET EXIT DATA" >> + "TARGET EXIT DATA"_id >> pure(OmpIfClause::DirectiveNameModifier::TargetExitData) || - "TARGET DATA" >> + "TARGET DATA"_id >> pure(OmpIfClause::DirectiveNameModifier::TargetData) || - "TARGET UPDATE" >> + "TARGET UPDATE"_id >> pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) || - "TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) || - "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) || - "TASK" >> pure(OmpIfClause::DirectiveNameModifier::Task)) / + "TARGET"_id >> pure(OmpIfClause::DirectiveNameModifier::Target) || + "TASKLOOP"_id >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) || + "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task)) / ":"_tok), scalarLogicalExpr)) @@ -123,23 +123,23 @@ TYPE_PARSER( construct(name, maybe(Parser{}))) TYPE_PARSER(construct( - "INOUT" >> pure(OmpDependenceType::Type::Inout) || - "IN" >> pure(OmpDependenceType::Type::In) || - "OUT" >> pure(OmpDependenceType::Type::Out))) + "INOUT"_id >> pure(OmpDependenceType::Type::Inout) || + "IN"_id >> pure(OmpDependenceType::Type::In) || + "OUT"_id >> pure(OmpDependenceType::Type::Out))) TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US, construct(construct( - "SINK"_tok >> ":"_tok >> nonemptyList(Parser{}))) || + "SINK"_id_tok >> ":"_tok >> nonemptyList(Parser{}))) || construct( - construct("SOURCE"_tok)) || + construct("SOURCE"_id)) || construct(construct( Parser{}, ":"_tok >> nonemptyList(designator)))) // linear-modifier TYPE_PARSER( - construct("REF" >> pure(OmpLinearModifier::Type::Ref) || - "VAL" >> pure(OmpLinearModifier::Type::Val) || - "UVAL" >> pure(OmpLinearModifier::Type::Uval))) + construct("REF"_id >> pure(OmpLinearModifier::Type::Ref) || + "VAL"_id >> pure(OmpLinearModifier::Type::Val) || + "UVAL"_id >> pure(OmpLinearModifier::Type::Uval))) // LINEAR(list: linear-step) TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US, diff --git a/flang/lib/parser/token-parsers.h b/flang/lib/parser/token-parsers.h index 6269ad3..dd00443 100644 --- a/flang/lib/parser/token-parsers.h +++ b/flang/lib/parser/token-parsers.h @@ -119,21 +119,21 @@ constexpr struct SpaceCheck { // like "BIND ( C )"_tok and "SYNC ALL"_sptok. The _tok suffix is implied // when a string literal appears before the sequencing operator >> or // after the sequencing operator /. +template class TokenStringMatch { public: using resultType = Success; constexpr TokenStringMatch(const TokenStringMatch &) = default; - constexpr TokenStringMatch(const char *str, std::size_t n, bool mandatory) - : str_{str}, bytes_{n}, mandatoryFreeFormSpace_{mandatory} {} - constexpr TokenStringMatch(const char *str, bool mandatory) - : str_{str}, mandatoryFreeFormSpace_{mandatory} {} + constexpr TokenStringMatch(const char *str, std::size_t n) + : str_{str}, bytes_{n} {} + explicit constexpr TokenStringMatch(const char *str) : str_{str} {} std::optional Parse(ParseState &state) const { space.Parse(state); const char *start{state.GetLocation()}; const char *p{str_}; std::optional at; // initially empty for (std::size_t j{0}; j < bytes_ && *p != '\0'; ++j, ++p) { - const auto spaceSkipping{*p == ' '}; + bool spaceSkipping{*p == ' '}; if (spaceSkipping) { if (j + 1 == bytes_ || p[1] == ' ' || p[1] == '\0') { continue; // redundant; ignore @@ -151,7 +151,7 @@ public: if (!at.has_value()) { return std::nullopt; } - } else if (mandatoryFreeFormSpace_) { + } else if constexpr (MandatoryFreeFormSpace) { MissingSpace(state); } // 'at' remains full for next iteration @@ -162,6 +162,14 @@ public: return std::nullopt; } } + if constexpr (MustBeComplete) { + if (auto after{state.PeekAtNextChar()}) { + if (IsLegalInIdentifier(**after)) { + state.Say(start, MessageExpectedText{str_, bytes_}); + return std::nullopt; + } + } + } state.set_anyTokenMatched(); if (IsLegalInIdentifier(p[-1])) { return spaceCheck.Parse(state); @@ -173,29 +181,32 @@ public: private: const char *const str_; const std::size_t bytes_{std::string::npos}; - const bool mandatoryFreeFormSpace_; }; -constexpr TokenStringMatch operator""_tok(const char str[], std::size_t n) { - return TokenStringMatch{str, n, false}; +constexpr TokenStringMatch<> operator""_tok(const char str[], std::size_t n) { + return {str, n}; +} + +constexpr TokenStringMatch operator""_sptok(const char str[], std::size_t n) { + return {str, n}; } -constexpr TokenStringMatch operator""_sptok(const char str[], std::size_t n) { - return TokenStringMatch{str, n, true}; +constexpr TokenStringMatch operator""_id(const char str[], std::size_t n) { + return {str, n}; } template inline constexpr std::enable_if_t, - SequenceParser> + SequenceParser, PA>> operator>>(const char *str, const PA &p) { - return SequenceParser{TokenStringMatch{str, false}, p}; + return SequenceParser, PA>{TokenStringMatch<>{str}, p}; } template inline constexpr std::enable_if_t, - FollowParser> + FollowParser>> operator/(const PA &p, const char *str) { - return FollowParser{p, TokenStringMatch{str, false}}; + return FollowParser>{p, TokenStringMatch<>{str}}; } template inline constexpr auto parenthesized(const PA &p) { -- 2.7.4