diff --git a/flang/docs/ParserCombinators.md b/flang/docs/ParserCombinators.md --- a/flang/docs/ParserCombinators.md +++ b/flang/docs/ParserCombinators.md @@ -155,7 +155,10 @@ * `"..."_tok` match the content of the string, skipping spaces before and after. Internal spaces are optional matches. The `_tok` suffix is optional when the parser appears before the combinator `>>` or after - the combinator `/`. + the combinator `/`. If the quoted string ends in a character that + could appear in an identifier, a missing space will be diagnosed in + free form source in pedantic mode if the next character could also + be part of an identifier -- add a trailing blank to avoid this. * `"..."_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 diff --git a/flang/lib/Parser/io-parsers.cpp b/flang/lib/Parser/io-parsers.cpp --- a/flang/lib/Parser/io-parsers.cpp +++ b/flang/lib/Parser/io-parsers.cpp @@ -569,6 +569,11 @@ constexpr auto noInt{construct>()}; constexpr auto mandatoryDigits{construct>("." >> width)}; +// The extra trailing spaces in the following quoted edit descriptor token +// parsers are intentional: they inhibit any spurious warnings about missing +// spaces in pedantic mode that would otherwise be emitted if the edit +// descriptor were followed by a character that could appear in an identifier. + // R1307 data-edit-desc -> // I w [. m] | B w [. m] | O w [. m] | Z w [. m] | F w . d | // E w . d [E e] | EN w . d [E e] | ES w . d [E e] | EX w . d [E e] | @@ -576,59 +581,60 @@ // DT [char-literal-constant] [( v-list )] // (part 1 of 2) 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), + "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(format::IntrinsicTypeDataEditDesc::Kind::F) || - "D" >> pure(format::IntrinsicTypeDataEditDesc::Kind::D), + "F " >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) || + "D " >> pure(format::IntrinsicTypeDataEditDesc::Kind::D), mandatoryWidth, mandatoryDigits, noInt) || construct( - "E" >> ("N" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) || - "S" >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) || - "X" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) || - pure(format::IntrinsicTypeDataEditDesc::Kind::E)), - mandatoryWidth, mandatoryDigits, maybe("E" >> digits)) || + "E " >> ("N " >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) || + "S " >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) || + "X " >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) || + pure(format::IntrinsicTypeDataEditDesc::Kind::E)), + mandatoryWidth, mandatoryDigits, maybe("E " >> digits)) || construct( - "G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G), mandatoryWidth, - mandatoryDigits, maybe("E" >> digits)) || + "G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G), + mandatoryWidth, mandatoryDigits, maybe("E " >> digits)) || construct( - "G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) || - "L" >> pure(format::IntrinsicTypeDataEditDesc::Kind::L), + "G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) || + "L " >> pure(format::IntrinsicTypeDataEditDesc::Kind::L), mandatoryWidth, noInt, noInt) || construct( - "A" >> pure(format::IntrinsicTypeDataEditDesc::Kind::A), maybe(width), + "A " >> pure(format::IntrinsicTypeDataEditDesc::Kind::A), maybe(width), noInt, noInt) || // PGI/Intel extension: omitting width (and all else that follows) extension( "nonstandard usage: abbreviated edit descriptor"_port_en_US, construct( - "I" >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) || - ("B"_tok / !letter /* don't occlude BN & BZ */) >> + "I " >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) || + ("B "_tok / !letter /* don't occlude BN & BZ */) >> 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 DT, DC, & DP */) >> + "O " >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) || + "Z " >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z) || + "F " >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) || + ("D "_tok / !letter /* don't occlude DT, DC, & DP */) >> pure(format::IntrinsicTypeDataEditDesc::Kind::D) || - "E" >> - ("N" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) || - "S" >> + "E " >> + ("N " >> + pure(format::IntrinsicTypeDataEditDesc::Kind::EN) || + "S " >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) || - "X" >> + "X " >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) || pure(format::IntrinsicTypeDataEditDesc::Kind::E)) || - "G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) || - "L" >> pure(format::IntrinsicTypeDataEditDesc::Kind::L), + "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 constexpr SignedDigitStringIgnoreSpaces scaleFactor; TYPE_PARSER(construct( - "D" >> "T"_tok >> defaulted(charLiteralConstantWithoutKind), + "D T" >> defaulted(charLiteralConstantWithoutKind), defaulted(parenthesized(nonemptyList(scaleFactor))))) // R1314 k -> [sign] digit-string @@ -645,46 +651,46 @@ // R1319 round-edit-desc -> RU | RD | RZ | RN | RC | RP // R1320 decimal-edit-desc -> DC | DP TYPE_PARSER(construct( - "T" >> ("L" >> pure(format::ControlEditDesc::Kind::TL) || - "R" >> pure(format::ControlEditDesc::Kind::TR) || - pure(format::ControlEditDesc::Kind::T)), + "T L " >> pure(format::ControlEditDesc::Kind::TL) || + "T R " >> pure(format::ControlEditDesc::Kind::TR) || + "T " >> pure(format::ControlEditDesc::Kind::T), count) || construct(count, - "X" >> pure(format::ControlEditDesc::Kind::X) || + "X " >> pure(format::ControlEditDesc::Kind::X) || "/" >> pure(format::ControlEditDesc::Kind::Slash)) || construct( - "X" >> pure(format::ControlEditDesc::Kind::X) || + "X " >> pure(format::ControlEditDesc::Kind::X) || "/" >> pure(format::ControlEditDesc::Kind::Slash)) || construct( - scaleFactor, "P" >> pure(format::ControlEditDesc::Kind::P)) || + scaleFactor, "P " >> pure(format::ControlEditDesc::Kind::P)) || construct( ":" >> pure(format::ControlEditDesc::Kind::Colon)) || - "S" >> ("S" >> construct( - pure(format::ControlEditDesc::Kind::SS)) || - "P" >> construct( - pure(format::ControlEditDesc::Kind::SP)) || - construct( - pure(format::ControlEditDesc::Kind::S))) || - "B" >> ("N" >> construct( - pure(format::ControlEditDesc::Kind::BN)) || - "Z" >> construct( - pure(format::ControlEditDesc::Kind::BZ))) || - "R" >> ("U" >> construct( - pure(format::ControlEditDesc::Kind::RU)) || - "D" >> construct( - pure(format::ControlEditDesc::Kind::RD)) || - "Z" >> construct( - pure(format::ControlEditDesc::Kind::RZ)) || - "N" >> construct( - pure(format::ControlEditDesc::Kind::RN)) || - "C" >> construct( - pure(format::ControlEditDesc::Kind::RC)) || - "P" >> construct( - pure(format::ControlEditDesc::Kind::RP))) || - "D" >> ("C" >> construct( - pure(format::ControlEditDesc::Kind::DC)) || - "P" >> construct( - pure(format::ControlEditDesc::Kind::DP))) || + "S " >> ("S " >> construct( + pure(format::ControlEditDesc::Kind::SS)) || + "P " >> construct( + pure(format::ControlEditDesc::Kind::SP)) || + construct( + pure(format::ControlEditDesc::Kind::S))) || + "B " >> ("N " >> construct( + pure(format::ControlEditDesc::Kind::BN)) || + "Z " >> construct( + pure(format::ControlEditDesc::Kind::BZ))) || + "R " >> ("U " >> construct( + pure(format::ControlEditDesc::Kind::RU)) || + "D " >> construct( + pure(format::ControlEditDesc::Kind::RD)) || + "Z " >> construct( + pure(format::ControlEditDesc::Kind::RZ)) || + "N " >> construct( + pure(format::ControlEditDesc::Kind::RN)) || + "C " >> construct( + pure(format::ControlEditDesc::Kind::RC)) || + "P " >> construct( + pure(format::ControlEditDesc::Kind::RP))) || + "D " >> ("C " >> construct( + pure(format::ControlEditDesc::Kind::DC)) || + "P " >> construct( + pure(format::ControlEditDesc::Kind::DP))) || extension( "nonstandard usage: $ and \\ control edit descriptors"_port_en_US, "$" >> construct(