From 29a6c1a83c8d657095b15b0d89c6873a53473a50 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Tue, 24 Apr 2018 15:02:41 -0700 Subject: [PATCH] [flang] Allow construct("TOKEN"_tok)" with unvalued parser argument. Original-commit: flang-compiler/f18@19d2a4a849fcc14aa02083a2ade0211a15784526 Reviewed-on: https://github.com/flang-compiler/f18/pull/69 Tree-same-pre-rewrite: false --- flang/documentation/ParserCombinators.md | 5 +- flang/lib/parser/basic-parsers.h | 21 ++++++- flang/lib/parser/grammar.h | 98 ++++++++++++++++---------------- 3 files changed, 70 insertions(+), 54 deletions(-) diff --git a/flang/documentation/ParserCombinators.md b/flang/documentation/ParserCombinators.md index 2e52720..7158598 100644 --- a/flang/documentation/ParserCombinators.md +++ b/flang/documentation/ParserCombinators.md @@ -99,8 +99,9 @@ collect the values that they return. * `construct(p1, p2, ...)` matches zero or more parsers in succession, collecting their results and then passing them with move semantics to a constructor for the type T if they all succeed. -* `constructIf(p)` matches p and then returns the default-constructed `T{}`. - The value of p must be the vacant `Success{}` value. + If there is a single parser as the argument and it returns no usable + value but only success or failure (_e.g.,_ `"IF"_tok`), the default + nullary constructor of the type `T` is called. * `sourced(p)` matches p, and fills in its `source` data member with the locations of the cooked character stream that it consumed * `applyFunction(f, p1, p2, ...)` matches one or more parsers in succession, diff --git a/flang/lib/parser/basic-parsers.h b/flang/lib/parser/basic-parsers.h index 8054198..767367d 100644 --- a/flang/lib/parser/basic-parsers.h +++ b/flang/lib/parser/basic-parsers.h @@ -876,8 +876,9 @@ private: const PA parser_; }; -template -constexpr Construct01 constructIf(const PA &parser) { +// TODO pmk rm +template constexpr Construct01 +constructIf(const PA &parser) { return Construct01{parser}; } @@ -897,8 +898,22 @@ private: const PA parser_; }; +// With a single argument that is a parser with no usable value, +// construct(p) invokes T's default nullary constructor T(){}. +// With a single argument that is a parser with a usable value of +// type A, construct(p) invokes T's explicit constructor T(A &&). +template constexpr +typename std::enable_if, + Construct01>::type +construct(const PA &parser) { + return Construct01{parser}; +} + template -constexpr Construct1 construct(const PA &parser) { +constexpr +typename std::enable_if, + Construct1>::type +construct(const PA &parser) { return Construct1{parser}; } diff --git a/flang/lib/parser/grammar.h b/flang/lib/parser/grammar.h index 490fdd4..00be770 100644 --- a/flang/lib/parser/grammar.h +++ b/flang/lib/parser/grammar.h @@ -279,14 +279,14 @@ TYPE_PARSER(construct(indirect(Parser{})) || construct(indirect(Parser{})) || construct(indirect(Parser{})) || construct(indirect(Parser{})) || - construct(constructIf("CONTINUE"_tok)) || + construct(construct("CONTINUE"_tok)) || construct(indirect(Parser{})) || construct(indirect(Parser{})) || construct(indirect(Parser{})) || construct(indirect(Parser{})) || construct(indirect(Parser{})) || construct(indirect(Parser{})) || - construct(constructIf("FAIL IMAGE"_sptok)) || + construct(construct("FAIL IMAGE"_sptok)) || construct(indirect(Parser{})) || construct(indirect(Parser{})) || construct(indirect(Parser{})) || @@ -388,10 +388,10 @@ TYPE_PARSER(construct(Parser{}) || TYPE_PARSER(construct(name)) // R701 type-param-value -> scalar-int-expr | * | : -constexpr auto star = constructIf("*"_tok); +constexpr auto star = construct("*"_tok); TYPE_PARSER(construct(scalarIntExpr) || construct(star) || - construct(constructIf(":"_tok))) + construct(construct(":"_tok))) // R702 type-spec -> intrinsic-type-spec | derived-type-spec // N.B. This type-spec production is one of two instances in the Fortran @@ -574,7 +574,7 @@ TYPE_CONTEXT_PARSER("CHARACTER literal constant"_en_US, space >> charLiteralConstantWithoutKind) || construct( construct>( - construct(constructIf("NC"_tok))), + construct(construct("NC"_tok))), charLiteralConstantWithoutKind)) // deprecated: Hollerith literals @@ -616,9 +616,9 @@ TYPE_CONTEXT_PARSER("TYPE statement"_en_US, // R728 type-attr-spec -> // ABSTRACT | access-spec | BIND(C) | EXTENDS ( parent-type-name ) -TYPE_PARSER(construct(constructIf("ABSTRACT"_tok)) || +TYPE_PARSER(construct(construct("ABSTRACT"_tok)) || construct( - constructIf("BIND ( C )"_tok)) || + construct("BIND ( C )"_tok)) || construct( construct("EXTENDS" >> parenthesized(name))) || construct(accessSpec)) @@ -635,7 +635,7 @@ TYPE_PARSER(construct( recovery("END TYPE" >> maybe(name), endStmtErrorRecovery))) // R731 sequence-stmt -> SEQUENCE -TYPE_PARSER(constructIf("SEQUENCE"_tok)) +TYPE_PARSER(construct("SEQUENCE"_tok)) // R732 type-param-def-stmt -> // integer-type-spec , type-param-attr-spec :: type-param-decl-list @@ -668,9 +668,9 @@ TYPE_PARSER(construct(declarationTypeSpec, // access-spec | ALLOCATABLE | // CODIMENSION lbracket coarray-spec rbracket | // CONTIGUOUS | DIMENSION ( component-array-spec ) | POINTER -constexpr auto allocatable = constructIf("ALLOCATABLE"_tok); -constexpr auto contiguous = constructIf("CONTIGUOUS"_tok); -constexpr auto pointer = constructIf("POINTER"_tok); +constexpr auto allocatable = construct("ALLOCATABLE"_tok); +constexpr auto contiguous = construct("CONTIGUOUS"_tok); +constexpr auto pointer = construct("POINTER"_tok); TYPE_PARSER(construct(accessSpec) || construct(allocatable) || construct("CODIMENSION" >> coarraySpec) || @@ -704,7 +704,7 @@ TYPE_CONTEXT_PARSER("PROCEDURE component definition statement"_en_US, // R742 proc-component-attr-spec -> // access-spec | NOPASS | PASS [(arg-name)] | POINTER -constexpr auto noPass = constructIf("NOPASS"_tok); +constexpr auto noPass = construct("NOPASS"_tok); constexpr auto pass = construct("PASS" >> maybe(parenthesized(name))); TYPE_PARSER(construct(accessSpec) || construct(noPass) || @@ -727,7 +727,7 @@ TYPE_PARSER(construct("=>" >> nullInit) || // R745 private-components-stmt -> PRIVATE // R747 binding-private-stmt -> PRIVATE -TYPE_PARSER(constructIf("PRIVATE"_tok)) +TYPE_PARSER(construct("PRIVATE"_tok)) // R746 type-bound-procedure-part -> // contains-stmt [binding-private-stmt] [type-bound-proc-binding]... @@ -771,9 +771,9 @@ TYPE_CONTEXT_PARSER("type bound GENERIC statement"_en_US, // R752 bind-attr -> // access-spec | DEFERRED | NON_OVERRIDABLE | NOPASS | PASS [(arg-name)] TYPE_PARSER(construct(accessSpec) || - construct(constructIf("DEFERRED"_tok)) || + construct(construct("DEFERRED"_tok)) || construct( - constructIf("NON_OVERRIDABLE"_tok)) || + construct("NON_OVERRIDABLE"_tok)) || construct(noPass) || construct(pass)) // R753 final-procedure-stmt -> FINAL [::] final-subroutine-name-list @@ -816,7 +816,7 @@ TYPE_CONTEXT_PARSER("enum definition"_en_US, statement(Parser{}))) // R760 enum-def-stmt -> ENUM, BIND(C) -TYPE_PARSER(constructIf("ENUM , BIND ( C )"_tok)) +TYPE_PARSER(construct("ENUM , BIND ( C )"_tok)) // R761 enumerator-def-stmt -> ENUMERATOR [::] enumerator-list TYPE_CONTEXT_PARSER("ENUMERATOR statement"_en_US, @@ -896,25 +896,25 @@ TYPE_PARSER(construct(declarationTypeSpec, // DIMENSION ( array-spec ) | EXTERNAL | INTENT ( intent-spec ) | // INTRINSIC | language-binding-spec | OPTIONAL | PARAMETER | POINTER | // PROTECTED | SAVE | TARGET | VALUE | VOLATILE -constexpr auto optional = constructIf("OPTIONAL"_tok); -constexpr auto protectedAttr = constructIf("PROTECTED"_tok); -constexpr auto save = constructIf("SAVE"_tok); +constexpr auto optional = construct("OPTIONAL"_tok); +constexpr auto protectedAttr = construct("PROTECTED"_tok); +constexpr auto save = construct("SAVE"_tok); TYPE_PARSER(construct(accessSpec) || construct(allocatable) || - construct(constructIf("ASYNCHRONOUS"_tok)) || + construct(construct("ASYNCHRONOUS"_tok)) || construct("CODIMENSION" >> coarraySpec) || construct(contiguous) || construct("DIMENSION" >> arraySpec) || - construct(constructIf("EXTERNAL"_tok)) || + construct(construct("EXTERNAL"_tok)) || construct("INTENT" >> parenthesized(intentSpec)) || - construct(constructIf("INTRINSIC"_tok)) || + construct(construct("INTRINSIC"_tok)) || construct(languageBindingSpec) || construct(optional) || - construct(constructIf("PARAMETER"_tok)) || + construct(construct("PARAMETER"_tok)) || construct(pointer) || construct(protectedAttr) || construct(save) || - construct(constructIf("TARGET"_tok)) || - construct(constructIf("VALUE"_tok)) || - construct(constructIf("VOLATILE"_tok))) + construct(construct("TARGET"_tok)) || + construct(construct("VALUE"_tok)) || + construct(construct("VOLATILE"_tok))) // R804 object-name -> name constexpr auto objectName = name; @@ -928,7 +928,7 @@ TYPE_PARSER(construct(objectName, maybe(arraySpec), // R806 null-init -> function-reference // TODO: confirm in semantics that NULL still intrinsic in this scope -TYPE_PARSER(constructIf("NULL ( )"_tok) / !"("_tok) +TYPE_PARSER(construct("NULL ( )"_tok) / !"("_tok) // R807 access-spec -> PUBLIC | PRIVATE TYPE_PARSER(construct("PUBLIC" >> pure(AccessSpec::Kind::Public)) || @@ -1004,7 +1004,7 @@ TYPE_PARSER(construct( TYPE_PARSER(construct(nonemptyList(assumedImpliedSpec))) // R825 assumed-rank-spec -> .. -TYPE_PARSER(constructIf(".."_tok)) +TYPE_PARSER(construct(".."_tok)) // R826 intent-spec -> IN | OUT | INOUT TYPE_PARSER(construct("IN OUT" >> pure(IntentSpec::Intent::InOut) || @@ -2010,7 +2010,7 @@ TYPE_PARSER(construct(construct( construct(construct( "SHARED" >> parenthesized(nonemptyList(name)))) || construct( - constructIf("DEFAULT ( NONE )"_tok))) + construct("DEFAULT ( NONE )"_tok))) // R1123 loop-control -> // [,] do-variable = scalar-int-expr , scalar-int-expr @@ -2094,7 +2094,7 @@ TYPE_CONTEXT_PARSER("CASE statement"_en_US, TYPE_PARSER(construct("END SELECT" >> maybe(name))) // R1145 case-selector -> ( case-value-range-list ) | DEFAULT -constexpr auto defaultKeyword = constructIf("DEFAULT"_tok); +constexpr auto defaultKeyword = construct("DEFAULT"_tok); TYPE_PARSER(parenthesized(construct( nonemptyList(Parser{}))) || construct(defaultKeyword)) @@ -3012,7 +3012,7 @@ TYPE_PARSER(construct(Parser{}) || // R1503 interface-stmt -> INTERFACE [generic-spec] | ABSTRACT INTERFACE TYPE_PARSER(construct("INTERFACE" >> maybe(genericSpec)) || - construct(constructIf("ABSTRACT INTERFACE"_sptok))) + construct(construct("ABSTRACT INTERFACE"_sptok))) // R1504 end-interface-stmt -> END INTERFACE [generic-spec] TYPE_PARSER(construct("END INTERFACE" >> maybe(genericSpec))) @@ -3048,14 +3048,14 @@ TYPE_PARSER(construct("MODULE PROCEDURE"_sptok >> TYPE_PARSER(construct( "OPERATOR" >> parenthesized(Parser{})) || construct( - constructIf("ASSIGNMENT ( = )"_tok)) || + construct("ASSIGNMENT ( = )"_tok)) || construct( - constructIf("READ ( FORMATTED )"_tok)) || - construct(constructIf( + construct("READ ( FORMATTED )"_tok)) || + construct(construct( "READ ( UNFORMATTED )"_tok)) || construct( - constructIf("WRITE ( FORMATTED )"_tok)) || - construct(constructIf( + construct("WRITE ( FORMATTED )"_tok)) || + construct(construct( "WRITE ( UNFORMATTED )"_tok)) || construct(name)) @@ -3142,13 +3142,13 @@ TYPE_PARSER(construct(star >> label)) // NON_RECURSIVE | PURE | RECURSIVE TYPE_PARSER(construct(declarationTypeSpec) || construct( - constructIf("ELEMENTAL"_tok)) || - construct(constructIf("IMPURE"_tok)) || - construct(constructIf("MODULE"_tok)) || + construct("ELEMENTAL"_tok)) || + construct(construct("IMPURE"_tok)) || + construct(construct("MODULE"_tok)) || construct( - constructIf("NON_RECURSIVE"_tok)) || - construct(constructIf("PURE"_tok)) || - construct(constructIf("RECURSIVE"_tok))) + construct("NON_RECURSIVE"_tok)) || + construct(construct("PURE"_tok)) || + construct(construct("RECURSIVE"_tok))) // R1529 function-subprogram -> // function-stmt [specification-part] [execution-part] @@ -3235,7 +3235,7 @@ TYPE_CONTEXT_PARSER("RETURN statement"_en_US, construct("RETURN" >> maybe(scalarIntExpr))) // R1543 contains-stmt -> CONTAINS -TYPE_PARSER(constructIf("CONTAINS"_tok)) +TYPE_PARSER(construct("CONTAINS"_tok)) // R1544 stmt-function-stmt -> // function-name ( [dummy-arg-name-list] ) = scalar-expr @@ -3248,7 +3248,7 @@ TYPE_CONTEXT_PARSER("statement function definition"_en_US, // !DIR$ IGNORE_TKR [ [(tkr...)] name ]... constexpr auto beginDirective = skipEmptyLines >> space >> "!"_ch; constexpr auto endDirective = space >> endOfLine; -constexpr auto ivdep = constructIf("DIR$ IVDEP"_tok); +constexpr auto ivdep = construct("DIR$ IVDEP"_tok); constexpr auto ignore_tkr = "DIR$ IGNORE_TKR" >> optionalList(construct( defaulted(parenthesized(some("tkr"_ch))), name)); @@ -3273,17 +3273,17 @@ TYPE_CONTEXT_PARSER("STRUCTURE definition"_en_US, extension(construct(statement(Parser{}), many(Parser{}), statement( - constructIf("END STRUCTURE"_tok))))) + construct("END STRUCTURE"_tok))))) TYPE_CONTEXT_PARSER("UNION definition"_en_US, - construct(statement(constructIf("UNION"_tok)), + construct(statement(construct("UNION"_tok)), many(Parser{}), - statement(constructIf("END UNION"_tok)))) + statement(construct("END UNION"_tok)))) TYPE_CONTEXT_PARSER("MAP definition"_en_US, - construct(statement(constructIf("MAP"_tok)), + construct(statement(construct("MAP"_tok)), many(Parser{}), - statement(constructIf("END MAP"_tok)))) + statement(construct("END MAP"_tok)))) TYPE_CONTEXT_PARSER("arithmetic IF statement"_en_US, deprecated(construct( -- 2.7.4