//===-- lib/Parser/io-parsers.cpp -----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Per-type parsers for I/O statements and FORMAT #include "basic-parsers.h" #include "expr-parsers.h" #include "misc-parsers.h" #include "stmt-parser.h" #include "token-parsers.h" #include "type-parser-implementation.h" #include "flang/Parser/characters.h" #include "flang/Parser/parse-tree.h" namespace Fortran::parser { // R1201 io-unit -> file-unit-number | * | internal-file-variable // R1203 internal-file-variable -> char-variable // R905 char-variable -> variable // "char-variable" is attempted first since it's not type constrained but // syntactically ambiguous with "file-unit-number", which is constrained. TYPE_PARSER(construct(variable / lookAhead(space / ",);\n"_ch)) || construct(fileUnitNumber) || construct(star)) // R1202 file-unit-number -> scalar-int-expr TYPE_PARSER(construct(scalarIntExpr / !"="_tok)) // R1204 open-stmt -> OPEN ( connect-spec-list ) TYPE_CONTEXT_PARSER("OPEN statement"_en_US, construct( "OPEN (" >> nonemptyList("expected connection specifications"_err_en_US, Parser{}) / ")")) // R1206 file-name-expr -> scalar-default-char-expr constexpr auto fileNameExpr{scalarDefaultCharExpr}; // R1205 connect-spec -> // [UNIT =] file-unit-number | ACCESS = scalar-default-char-expr | // ACTION = scalar-default-char-expr | // ASYNCHRONOUS = scalar-default-char-expr | // BLANK = scalar-default-char-expr | // DECIMAL = scalar-default-char-expr | // DELIM = scalar-default-char-expr | // ENCODING = scalar-default-char-expr | ERR = label | // FILE = file-name-expr | FORM = scalar-default-char-expr | // IOMSG = iomsg-variable | IOSTAT = scalar-int-variable | // NEWUNIT = scalar-int-variable | PAD = scalar-default-char-expr | // POSITION = scalar-default-char-expr | RECL = scalar-int-expr | // ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr | // STATUS = scalar-default-char-expr // @ | CARRIAGECONTROL = scalar-default-char-variable // | CONVERT = scalar-default-char-variable // | DISPOSE = scalar-default-char-variable constexpr auto statusExpr{construct(scalarDefaultCharExpr)}; constexpr auto errLabel{construct(label)}; TYPE_PARSER(first(construct(maybe("UNIT ="_tok) >> fileUnitNumber), construct(construct( "ACCESS =" >> pure(ConnectSpec::CharExpr::Kind::Access), scalarDefaultCharExpr)), construct(construct( "ACTION =" >> pure(ConnectSpec::CharExpr::Kind::Action), scalarDefaultCharExpr)), construct(construct( "ASYNCHRONOUS =" >> pure(ConnectSpec::CharExpr::Kind::Asynchronous), scalarDefaultCharExpr)), construct(construct( "BLANK =" >> pure(ConnectSpec::CharExpr::Kind::Blank), scalarDefaultCharExpr)), construct(construct( "DECIMAL =" >> pure(ConnectSpec::CharExpr::Kind::Decimal), scalarDefaultCharExpr)), construct(construct( "DELIM =" >> pure(ConnectSpec::CharExpr::Kind::Delim), scalarDefaultCharExpr)), construct(construct( "ENCODING =" >> pure(ConnectSpec::CharExpr::Kind::Encoding), scalarDefaultCharExpr)), construct("ERR =" >> errLabel), construct("FILE =" >> fileNameExpr), extension( "nonstandard usage: NAME= in place of FILE="_port_en_US, construct("NAME =" >> fileNameExpr)), construct(construct( "FORM =" >> pure(ConnectSpec::CharExpr::Kind::Form), scalarDefaultCharExpr)), construct("IOMSG =" >> msgVariable), construct("IOSTAT =" >> statVariable), construct(construct( "NEWUNIT =" >> scalar(integer(variable)))), construct(construct( "PAD =" >> pure(ConnectSpec::CharExpr::Kind::Pad), scalarDefaultCharExpr)), construct(construct( "POSITION =" >> pure(ConnectSpec::CharExpr::Kind::Position), scalarDefaultCharExpr)), construct( construct("RECL =" >> scalarIntExpr)), construct(construct( "ROUND =" >> pure(ConnectSpec::CharExpr::Kind::Round), scalarDefaultCharExpr)), construct(construct( "SIGN =" >> pure(ConnectSpec::CharExpr::Kind::Sign), scalarDefaultCharExpr)), construct("STATUS =" >> statusExpr), extension( "nonstandard usage: CARRIAGECONTROL="_port_en_US, construct( construct("CARRIAGECONTROL =" >> pure(ConnectSpec::CharExpr::Kind::Carriagecontrol), scalarDefaultCharExpr))), extension( "nonstandard usage: CONVERT="_port_en_US, construct(construct( "CONVERT =" >> pure(ConnectSpec::CharExpr::Kind::Convert), scalarDefaultCharExpr))), extension( "nonstandard usage: DISPOSE="_port_en_US, construct(construct( "DISPOSE =" >> pure(ConnectSpec::CharExpr::Kind::Dispose), scalarDefaultCharExpr))))) // R1209 close-spec -> // [UNIT =] file-unit-number | IOSTAT = scalar-int-variable | // IOMSG = iomsg-variable | ERR = label | // STATUS = scalar-default-char-expr constexpr auto closeSpec{first( construct(maybe("UNIT ="_tok) >> fileUnitNumber), construct("IOSTAT =" >> statVariable), construct("IOMSG =" >> msgVariable), construct("ERR =" >> errLabel), construct("STATUS =" >> statusExpr))}; // R1208 close-stmt -> CLOSE ( close-spec-list ) TYPE_CONTEXT_PARSER("CLOSE statement"_en_US, construct("CLOSE" >> parenthesized(nonemptyList(closeSpec)))) // R1210 read-stmt -> // READ ( io-control-spec-list ) [input-item-list] | // READ format [, input-item-list] // The ambiguous READ(CVAR) is parsed as if CVAR were the unit. // As Fortran doesn't have internal unformatted I/O, it should // be parsed as if (CVAR) were a format; this is corrected by // rewriting in semantics when we know that CVAR is character. constexpr auto inputItemList{ extension( "nonstandard usage: leading comma in input item list"_port_en_US, some("," >> inputItem)) || // legacy extension: leading comma optionalList(inputItem)}; TYPE_CONTEXT_PARSER("READ statement"_en_US, construct("READ (" >> construct>(maybe("UNIT ="_tok) >> ioUnit), "," >> construct>(format), defaulted("," >> nonemptyList(ioControlSpec)) / ")", inputItemList) || construct( "READ (" >> construct>(ioUnit), construct>(), defaulted("," >> nonemptyList(ioControlSpec)) / ")", inputItemList) || construct("READ" >> construct>(), construct>(), parenthesized(nonemptyList(ioControlSpec)), inputItemList) || construct("READ" >> construct>(), construct>(format), construct>(), many("," >> inputItem))) // R1214 id-variable -> scalar-int-variable constexpr auto idVariable{construct(scalarIntVariable)}; // R1213 io-control-spec -> // [UNIT =] io-unit | [FMT =] format | [NML =] namelist-group-name | // ADVANCE = scalar-default-char-expr | // ASYNCHRONOUS = scalar-default-char-constant-expr | // BLANK = scalar-default-char-expr | // DECIMAL = scalar-default-char-expr | // DELIM = scalar-default-char-expr | END = label | EOR = label | // ERR = label | ID = id-variable | IOMSG = iomsg-variable | // IOSTAT = scalar-int-variable | PAD = scalar-default-char-expr | // POS = scalar-int-expr | REC = scalar-int-expr | // ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr | // SIZE = scalar-int-variable constexpr auto endLabel{construct(label)}; constexpr auto eorLabel{construct(label)}; TYPE_PARSER(first(construct("UNIT =" >> ioUnit), construct("FMT =" >> format), construct("NML =" >> name), construct( "ADVANCE =" >> construct( pure(IoControlSpec::CharExpr::Kind::Advance), scalarDefaultCharExpr)), construct(construct( "ASYNCHRONOUS =" >> scalarDefaultCharConstantExpr)), construct("BLANK =" >> construct( pure(IoControlSpec::CharExpr::Kind::Blank), scalarDefaultCharExpr)), construct( "DECIMAL =" >> construct( pure(IoControlSpec::CharExpr::Kind::Decimal), scalarDefaultCharExpr)), construct("DELIM =" >> construct( pure(IoControlSpec::CharExpr::Kind::Delim), scalarDefaultCharExpr)), construct("END =" >> endLabel), construct("EOR =" >> eorLabel), construct("ERR =" >> errLabel), construct("ID =" >> idVariable), construct("IOMSG = " >> msgVariable), construct("IOSTAT = " >> statVariable), construct("PAD =" >> construct( pure(IoControlSpec::CharExpr::Kind::Pad), scalarDefaultCharExpr)), construct( "POS =" >> construct(scalarIntExpr)), construct( "REC =" >> construct(scalarIntExpr)), construct("ROUND =" >> construct( pure(IoControlSpec::CharExpr::Kind::Round), scalarDefaultCharExpr)), construct("SIGN =" >> construct( pure(IoControlSpec::CharExpr::Kind::Sign), scalarDefaultCharExpr)), construct( "SIZE =" >> construct(scalarIntVariable)))) // R1211 write-stmt -> WRITE ( io-control-spec-list ) [output-item-list] constexpr auto outputItemList{ extension( "nonstandard usage: leading comma in output item list"_port_en_US, some("," >> outputItem)) || // legacy: allow leading comma optionalList(outputItem)}; TYPE_CONTEXT_PARSER("WRITE statement"_en_US, construct("WRITE (" >> construct>(maybe("UNIT ="_tok) >> ioUnit), "," >> construct>(format), defaulted("," >> nonemptyList(ioControlSpec)) / ")", outputItemList) || construct( "WRITE (" >> construct>(ioUnit), construct>(), defaulted("," >> nonemptyList(ioControlSpec)) / ")", outputItemList) || construct("WRITE" >> construct>(), construct>(), parenthesized(nonemptyList(ioControlSpec)), outputItemList)) // R1212 print-stmt PRINT format [, output-item-list] TYPE_CONTEXT_PARSER("PRINT statement"_en_US, construct( "PRINT" >> format, defaulted("," >> nonemptyList(outputItem)))) // R1215 format -> default-char-expr | label | * // deprecated(ASSIGN): | scalar-int-name TYPE_PARSER(construct(label / !"_."_ch) || construct(expr / !"="_tok) || construct(star)) // R1216 input-item -> variable | io-implied-do TYPE_PARSER(construct(variable) || construct(indirect(inputImpliedDo))) // R1217 output-item -> expr | io-implied-do TYPE_PARSER(construct(expr) || construct(indirect(outputImpliedDo))) // R1220 io-implied-do-control -> // do-variable = scalar-int-expr , scalar-int-expr [, scalar-int-expr] constexpr auto ioImpliedDoControl{loopBounds(scalarIntExpr)}; // R1218 io-implied-do -> ( io-implied-do-object-list , io-implied-do-control ) // R1219 io-implied-do-object -> input-item | output-item TYPE_CONTEXT_PARSER("input implied DO"_en_US, parenthesized( construct(nonemptyList(inputItem / lookAhead(","_tok)), "," >> ioImpliedDoControl))) TYPE_CONTEXT_PARSER("output implied DO"_en_US, parenthesized(construct( nonemptyList(outputItem / lookAhead(","_tok)), "," >> ioImpliedDoControl))) // R1222 wait-stmt -> WAIT ( wait-spec-list ) TYPE_CONTEXT_PARSER("WAIT statement"_en_US, "WAIT" >> parenthesized(construct(nonemptyList(Parser{})))) // R1223 wait-spec -> // [UNIT =] file-unit-number | END = label | EOR = label | ERR = label | // ID = scalar-int-expr | IOMSG = iomsg-variable | // IOSTAT = scalar-int-variable constexpr auto idExpr{construct(scalarIntExpr)}; TYPE_PARSER(first(construct(maybe("UNIT ="_tok) >> fileUnitNumber), construct("END =" >> endLabel), construct("EOR =" >> eorLabel), construct("ERR =" >> errLabel), construct("ID =" >> idExpr), construct("IOMSG =" >> msgVariable), construct("IOSTAT =" >> statVariable))) constexpr auto bareUnitNumberAsList{ applyFunction(singletonList, construct(fileUnitNumber))}; constexpr auto positionOrFlushSpecList{ parenthesized(nonemptyList(positionOrFlushSpec)) || bareUnitNumberAsList}; // R1224 backspace-stmt -> // BACKSPACE file-unit-number | BACKSPACE ( position-spec-list ) TYPE_CONTEXT_PARSER("BACKSPACE statement"_en_US, construct("BACKSPACE" >> positionOrFlushSpecList)) // R1225 endfile-stmt -> // ENDFILE file-unit-number | ENDFILE ( position-spec-list ) TYPE_CONTEXT_PARSER("ENDFILE statement"_en_US, construct("END FILE" >> positionOrFlushSpecList)) // R1226 rewind-stmt -> REWIND file-unit-number | REWIND ( position-spec-list ) TYPE_CONTEXT_PARSER("REWIND statement"_en_US, construct("REWIND" >> positionOrFlushSpecList)) // R1227 position-spec -> // [UNIT =] file-unit-number | IOMSG = iomsg-variable | // IOSTAT = scalar-int-variable | ERR = label // R1229 flush-spec -> // [UNIT =] file-unit-number | IOSTAT = scalar-int-variable | // IOMSG = iomsg-variable | ERR = label TYPE_PARSER( construct(maybe("UNIT ="_tok) >> fileUnitNumber) || construct("IOMSG =" >> msgVariable) || construct("IOSTAT =" >> statVariable) || construct("ERR =" >> errLabel)) // R1228 flush-stmt -> FLUSH file-unit-number | FLUSH ( flush-spec-list ) TYPE_CONTEXT_PARSER("FLUSH statement"_en_US, construct("FLUSH" >> positionOrFlushSpecList)) // R1231 inquire-spec -> // [UNIT =] file-unit-number | FILE = file-name-expr | // ACCESS = scalar-default-char-variable | // ACTION = scalar-default-char-variable | // ASYNCHRONOUS = scalar-default-char-variable | // BLANK = scalar-default-char-variable | // DECIMAL = scalar-default-char-variable | // DELIM = scalar-default-char-variable | // ENCODING = scalar-default-char-variable | // ERR = label | EXIST = scalar-logical-variable | // FORM = scalar-default-char-variable | // FORMATTED = scalar-default-char-variable | // ID = scalar-int-expr | IOMSG = iomsg-variable | // IOSTAT = scalar-int-variable | // NAME = scalar-default-char-variable | // NAMED = scalar-logical-variable | // NEXTREC = scalar-int-variable | NUMBER = scalar-int-variable | // OPENED = scalar-logical-variable | // PAD = scalar-default-char-variable | // PENDING = scalar-logical-variable | POS = scalar-int-variable | // POSITION = scalar-default-char-variable | // READ = scalar-default-char-variable | // READWRITE = scalar-default-char-variable | // RECL = scalar-int-variable | ROUND = scalar-default-char-variable | // SEQUENTIAL = scalar-default-char-variable | // SIGN = scalar-default-char-variable | // SIZE = scalar-int-variable | // STREAM = scalar-default-char-variable | // STATUS = scalar-default-char-variable | // WRITE = scalar-default-char-variable // @ | CARRIAGECONTROL = scalar-default-char-variable // | CONVERT = scalar-default-char-variable // | DISPOSE = scalar-default-char-variable TYPE_PARSER(first(construct(maybe("UNIT ="_tok) >> fileUnitNumber), construct("FILE =" >> fileNameExpr), construct( "ACCESS =" >> construct( pure(InquireSpec::CharVar::Kind::Access), scalarDefaultCharVariable)), construct( "ACTION =" >> construct( pure(InquireSpec::CharVar::Kind::Action), scalarDefaultCharVariable)), construct( "ASYNCHRONOUS =" >> construct( pure(InquireSpec::CharVar::Kind::Asynchronous), scalarDefaultCharVariable)), construct("BLANK =" >> construct(pure(InquireSpec::CharVar::Kind::Blank), scalarDefaultCharVariable)), construct( "DECIMAL =" >> construct( pure(InquireSpec::CharVar::Kind::Decimal), scalarDefaultCharVariable)), construct("DELIM =" >> construct(pure(InquireSpec::CharVar::Kind::Delim), scalarDefaultCharVariable)), construct( "DIRECT =" >> construct( pure(InquireSpec::CharVar::Kind::Direct), scalarDefaultCharVariable)), construct( "ENCODING =" >> construct( pure(InquireSpec::CharVar::Kind::Encoding), scalarDefaultCharVariable)), construct("ERR =" >> errLabel), construct("EXIST =" >> construct( pure(InquireSpec::LogVar::Kind::Exist), scalarLogicalVariable)), construct("FORM =" >> construct( pure(InquireSpec::CharVar::Kind::Form), scalarDefaultCharVariable)), construct( "FORMATTED =" >> construct( pure(InquireSpec::CharVar::Kind::Formatted), scalarDefaultCharVariable)), construct("ID =" >> idExpr), construct("IOMSG =" >> construct(pure(InquireSpec::CharVar::Kind::Iomsg), scalarDefaultCharVariable)), construct("IOSTAT =" >> construct(pure(InquireSpec::IntVar::Kind::Iostat), scalar(integer(variable)))), construct("NAME =" >> construct( pure(InquireSpec::CharVar::Kind::Name), scalarDefaultCharVariable)), construct("NAMED =" >> construct( pure(InquireSpec::LogVar::Kind::Named), scalarLogicalVariable)), construct("NEXTREC =" >> construct(pure(InquireSpec::IntVar::Kind::Nextrec), scalar(integer(variable)))), construct("NUMBER =" >> construct(pure(InquireSpec::IntVar::Kind::Number), scalar(integer(variable)))), construct("OPENED =" >> construct( pure(InquireSpec::LogVar::Kind::Opened), scalarLogicalVariable)), construct("PAD =" >> construct( pure(InquireSpec::CharVar::Kind::Pad), scalarDefaultCharVariable)), construct("PENDING =" >> construct( pure(InquireSpec::LogVar::Kind::Pending), scalarLogicalVariable)), construct("POS =" >> construct( pure(InquireSpec::IntVar::Kind::Pos), scalar(integer(variable)))), construct( "POSITION =" >> construct( pure(InquireSpec::CharVar::Kind::Position), scalarDefaultCharVariable)), construct("READ =" >> construct( pure(InquireSpec::CharVar::Kind::Read), scalarDefaultCharVariable)), construct( "READWRITE =" >> construct( pure(InquireSpec::CharVar::Kind::Readwrite), scalarDefaultCharVariable)), construct("RECL =" >> construct( pure(InquireSpec::IntVar::Kind::Recl), scalar(integer(variable)))), construct("ROUND =" >> construct(pure(InquireSpec::CharVar::Kind::Round), scalarDefaultCharVariable)), construct( "SEQUENTIAL =" >> construct( pure(InquireSpec::CharVar::Kind::Sequential), scalarDefaultCharVariable)), construct("SIGN =" >> construct( pure(InquireSpec::CharVar::Kind::Sign), scalarDefaultCharVariable)), construct("SIZE =" >> construct( pure(InquireSpec::IntVar::Kind::Size), scalar(integer(variable)))), construct( "STREAM =" >> construct( pure(InquireSpec::CharVar::Kind::Stream), scalarDefaultCharVariable)), construct( "STATUS =" >> construct( pure(InquireSpec::CharVar::Kind::Status), scalarDefaultCharVariable)), construct( "UNFORMATTED =" >> construct( pure(InquireSpec::CharVar::Kind::Unformatted), scalarDefaultCharVariable)), construct("WRITE =" >> construct(pure(InquireSpec::CharVar::Kind::Write), scalarDefaultCharVariable)), extension( "nonstandard usage: CARRIAGECONTROL="_port_en_US, construct("CARRIAGECONTROL =" >> construct( pure(InquireSpec::CharVar::Kind::Carriagecontrol), scalarDefaultCharVariable))), extension( "nonstandard usage: CONVERT="_port_en_US, construct( "CONVERT =" >> construct( pure(InquireSpec::CharVar::Kind::Convert), scalarDefaultCharVariable))), extension( "nonstandard usage: DISPOSE="_port_en_US, construct( "DISPOSE =" >> construct( pure(InquireSpec::CharVar::Kind::Dispose), scalarDefaultCharVariable))))) // R1230 inquire-stmt -> // INQUIRE ( inquire-spec-list ) | // INQUIRE ( IOLENGTH = scalar-int-variable ) output-item-list TYPE_CONTEXT_PARSER("INQUIRE statement"_en_US, "INQUIRE" >> (construct( parenthesized(nonemptyList(Parser{}))) || construct(construct( parenthesized("IOLENGTH =" >> scalar(integer(variable))), nonemptyList(outputItem))))) // R1301 format-stmt -> FORMAT format-specification // 13.2.1 allows spaces to appear "at any point" within a format specification // without effect, except of course within a character string edit descriptor. TYPE_CONTEXT_PARSER("FORMAT statement"_en_US, construct("FORMAT" >> Parser{})) // R1321 char-string-edit-desc // N.B. C1313 disallows any kind parameter on the character literal. constexpr auto charStringEditDesc{ space >> (charLiteralConstantWithoutKind || rawHollerithLiteral)}; // R1303 format-items -> format-item [[,] format-item]... constexpr auto formatItems{ nonemptySeparated(space >> Parser{}, maybe(","_tok))}; // R1306 r -> digit-string constexpr DigitStringIgnoreSpaces repeat; // 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))) // R1302 format-specification -> // ( [format-items] ) | ( [format-items ,] unlimited-format-item ) // R1305 unlimited-format-item -> * ( format-items ) // minor extension: the comma is optional before the unlimited-format-item TYPE_PARSER(parenthesized(construct( defaulted(formatItems / maybe(","_tok)), "*" >> parenthesized(formatItems)) || construct(defaulted(formatItems)))) // R1308 w -> digit-string // R1309 m -> digit-string // R1310 d -> digit-string // R1311 e -> digit-string constexpr auto width{repeat}; constexpr auto mandatoryWidth{construct>(width)}; constexpr auto digits{repeat}; 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] | // 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(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), 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)) || construct( "G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G), mandatoryWidth, mandatoryDigits, maybe("E " >> digits)) || construct( "G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) || "L " >> pure(format::IntrinsicTypeDataEditDesc::Kind::L), mandatoryWidth, noInt, noInt) || construct( "A " >> pure(format::IntrinsicTypeDataEditDesc::Kind::A), maybe(width), noInt, noInt) || // PGI/Intel extension: omitting width (and all else that follows) // Parse them just to get them to the I/O checker in semantics; // they are not supported by the runtime. extension(construct< format::IntrinsicTypeDataEditDesc>( "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 */) >> pure(format::IntrinsicTypeDataEditDesc::Kind::D) || "E " >> ("N " >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) || "S " >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) || "X " >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) || 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 constexpr SignedDigitStringIgnoreSpaces scaleFactor; TYPE_PARSER(construct( "D T" >> defaulted(charLiteralConstantWithoutKind), defaulted(parenthesized(nonemptyList(scaleFactor))))) // R1314 k -> [sign] digit-string constexpr PositiveDigitStringIgnoreSpaces count; // R1313 control-edit-desc -> // position-edit-desc | [r] / | : | sign-edit-desc | k P | // blank-interp-edit-desc | round-edit-desc | decimal-edit-desc | // @ \ | $ // R1315 position-edit-desc -> T n | TL n | TR n | n X // R1316 n -> digit-string // R1317 sign-edit-desc -> SS | SP | S // 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( "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) || "/" >> 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)) || "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( pure(format::ControlEditDesc::Kind::Dollar)) || "\\" >> construct( pure(format::ControlEditDesc::Kind::Backslash)))) } // namespace Fortran::parser