#ifndef FORTRAN_FORMAT_SPECIFICATION_H_ #define FORTRAN_FORMAT_SPECIFICATION_H_ // Represent parses of Fortran format specifications from FORMAT statements // and character literals in formatted I/O statements at compilation time // as well as from character variables and expressions at run time. // From requirement productions R1302-R1321 of the Fortran 2018 draft // standard (q.v.), extended with Hollerith. These structures have been // isolated so that they may be used in the run-time without introducing // dependences on other parts of the compiler's source code. // TODO: support Q formatting extension? #include #include #include #include #include namespace Fortran { // R1307 data-edit-desc (part 1 of 2) -> // 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 // R1308 w -> digit-string // R1309 m -> digit-string // R1310 d -> digit-string // R1311 e -> digit-string struct IntrinsicTypeDataEditDesc { enum class Kind { I, B, O, Z, F, E, EN, ES, EX, G, L, A, D }; IntrinsicTypeDataEditDesc() = delete; IntrinsicTypeDataEditDesc(IntrinsicTypeDataEditDesc &&) = default; IntrinsicTypeDataEditDesc &operator=(IntrinsicTypeDataEditDesc &&) = default; IntrinsicTypeDataEditDesc(Kind &&k, std::optional &&w, std::optional &&d, std::optional &&e) : kind{k}, width{std::move(w)}, digits{std::move(d)}, exponentWidth{ std::move(e)} {} Kind kind; std::optional width; // w std::optional digits; // m or d std::optional exponentWidth; // e }; // R1307 data-edit-desc (part 2 of 2) -> // DT [char-literal-constant] [( v-list )] // R1312 v -> [sign] digit-string struct DerivedTypeDataEditDesc { DerivedTypeDataEditDesc() = delete; DerivedTypeDataEditDesc(DerivedTypeDataEditDesc &&) = default; DerivedTypeDataEditDesc &operator=(DerivedTypeDataEditDesc &&) = default; DerivedTypeDataEditDesc(std::string &&t, std::list &&p) : type{std::move(t)}, parameters{std::move(p)} {} std::string type; std::list parameters; }; // 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 struct ControlEditDesc { enum class Kind { T, TL, TR, X, Slash, Colon, SS, SP, S, P, BN, BZ, RU, RD, RZ, RN, RC, RP, DC, DP }; ControlEditDesc() = delete; ControlEditDesc(ControlEditDesc &&) = default; ControlEditDesc &operator=(ControlEditDesc &&) = default; explicit ControlEditDesc(Kind k) : kind{k} {} ControlEditDesc(Kind k, int ct) : kind{k}, count{ct} {} ControlEditDesc(int ct, Kind k) : kind{k}, count{ct} {} Kind kind; int count{1}; // r, k, or n }; // R1304 format-item -> // [r] data-edit-desc | control-edit-desc | char-string-edit-desc | // [r] ( format-items ) // R1306 r -> digit-string // R1321 char-string-edit-desc struct FormatItem { FormatItem() = delete; FormatItem(FormatItem &&) = default; FormatItem &operator=(FormatItem &&) = default; template FormatItem(std::optional &&r, A &&x) : repeatCount{std::move(r)}, u{std::move(x)} {} template explicit FormatItem(A &&x) : u{std::move(x)} {} std::optional repeatCount; std::variant> u; }; // R1302 format-specification -> // ( [format-items] ) | ( [format-items ,] unlimited-format-item ) // R1303 format-items -> format-item [[,] format-item]... // R1305 unlimited-format-item -> * ( format-items ) struct FormatSpecification { FormatSpecification() = delete; FormatSpecification(FormatSpecification &&) = default; FormatSpecification &operator=(FormatSpecification &&) = default; explicit FormatSpecification(std::list &&is) : items(std::move(is)) {} FormatSpecification(std::list &&is, std::list &&us) : items(std::move(is)), unlimitedItems(std::move(us)) {} std::list items, unlimitedItems; }; } // namespace Fortran #endif // FORTRAN_FORMAT_SPECIFICATION_H_