xref: /llvm-project/flang/include/flang/Parser/format-specification.h (revision d4b4ded1867768ecb2c857ae9c2593764d7f3e41)
1 //===-- include/flang/Parser/format-specification.h -------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef FORTRAN_PARSER_FORMAT_SPECIFICATION_H_
10 #define FORTRAN_PARSER_FORMAT_SPECIFICATION_H_
11 
12 // Represent parses of Fortran format specifications from FORMAT statements
13 // and character literals in formatted I/O statements at compilation time
14 // as well as from character variables and expressions at run time.
15 // From requirement productions R1302-R1321 of the Fortran 2018 draft
16 // standard (q.v.), extended with Hollerith.  These structures have been
17 // isolated so that they may be used in the run-time without introducing
18 // dependences on other parts of the compiler's source code.
19 // TODO: support Q formatting extension?
20 
21 #include "flang/Common/idioms.h"
22 #include <cinttypes>
23 #include <list>
24 #include <optional>
25 #include <string>
26 #include <variant>
27 
28 namespace Fortran::format {
29 
30 // R1307 data-edit-desc (part 1 of 2) ->
31 //         I w [. m] | B w [. m] | O w [. m] | Z w [. m] | F w . d |
32 //         E w . d [E e] | EN w . d [E e] | ES w . d [E e] | EX w . d [E e] |
33 //         G w [. d [E e]] | L w | A [w] | D w . d
34 // R1308 w -> digit-string
35 // R1309 m -> digit-string
36 // R1310 d -> digit-string
37 // R1311 e -> digit-string
38 struct IntrinsicTypeDataEditDesc {
39   enum class Kind { I, B, O, Z, F, E, EN, ES, EX, G, L, A, D };
40   IntrinsicTypeDataEditDesc() = delete;
41   IntrinsicTypeDataEditDesc(IntrinsicTypeDataEditDesc &&) = default;
42   IntrinsicTypeDataEditDesc &operator=(IntrinsicTypeDataEditDesc &&) = default;
IntrinsicTypeDataEditDescIntrinsicTypeDataEditDesc43   IntrinsicTypeDataEditDesc(Kind &&k, std::optional<int> &&w,
44       std::optional<int> &&d, std::optional<int> &&e)
45       : kind{k}, width{std::move(w)}, digits{std::move(d)}, exponentWidth{
46                                                                 std::move(e)} {}
47   Kind kind;
48   std::optional<int> width; // w
49   std::optional<int> digits; // m or d
50   std::optional<int> exponentWidth; // e
51 };
52 
53 // R1307 data-edit-desc (part 2 of 2) ->
54 //         DT [char-literal-constant] [( v-list )]
55 // R1312 v -> [sign] digit-string
56 struct DerivedTypeDataEditDesc {
57   DerivedTypeDataEditDesc() = delete;
58   DerivedTypeDataEditDesc(DerivedTypeDataEditDesc &&) = default;
59   DerivedTypeDataEditDesc &operator=(DerivedTypeDataEditDesc &&) = default;
DerivedTypeDataEditDescDerivedTypeDataEditDesc60   DerivedTypeDataEditDesc(std::string &&t, std::list<std::int64_t> &&p)
61       : type{std::move(t)}, parameters{std::move(p)} {}
62   std::string type;
63   std::list<std::int64_t> parameters;
64 };
65 
66 // R1313 control-edit-desc ->
67 //         position-edit-desc | [r] / | : | sign-edit-desc | k P |
68 //         blank-interp-edit-desc | round-edit-desc | decimal-edit-desc |
69 //         @ \ | $
70 // R1315 position-edit-desc -> T n | TL n | TR n | n X
71 // R1316 n -> digit-string
72 // R1317 sign-edit-desc -> SS | SP | S
73 // R1318 blank-interp-edit-desc -> BN | BZ
74 // R1319 round-edit-desc -> RU | RD | RZ | RN | RC | RP
75 // R1320 decimal-edit-desc -> DC | DP
76 struct ControlEditDesc {
77   enum class Kind {
78     T,
79     TL,
80     TR,
81     X,
82     Slash,
83     Colon,
84     SS,
85     SP,
86     S,
87     P,
88     BN,
89     BZ,
90     RU,
91     RD,
92     RZ,
93     RN,
94     RC,
95     RP,
96     DC,
97     DP,
98     Dollar, // extension: inhibit newline on output
99     Backslash, // ditto, but only on terminals
100   };
101   ControlEditDesc() = delete;
102   ControlEditDesc(ControlEditDesc &&) = default;
103   ControlEditDesc &operator=(ControlEditDesc &&) = default;
ControlEditDescControlEditDesc104   explicit ControlEditDesc(Kind k) : kind{k} {}
ControlEditDescControlEditDesc105   ControlEditDesc(Kind k, std::int64_t ct) : kind{k}, count{ct} {}
ControlEditDescControlEditDesc106   ControlEditDesc(std::int64_t ct, Kind k) : kind{k}, count{ct} {}
107   Kind kind;
108   std::int64_t count{1}; // r, k, or n
109 };
110 
111 // R1304 format-item ->
112 //         [r] data-edit-desc | control-edit-desc | char-string-edit-desc |
113 //         [r] ( format-items )
114 // R1306 r -> digit-string
115 // R1321 char-string-edit-desc
116 struct FormatItem {
117   FormatItem() = delete;
118   FormatItem(FormatItem &&) = default;
119   FormatItem &operator=(FormatItem &&) = default;
120   template <typename A, typename = common::NoLvalue<A>>
FormatItemFormatItem121   FormatItem(std::optional<std::uint64_t> &&r, A &&x)
122       : repeatCount{std::move(r)}, u{std::move(x)} {}
123   template <typename A, typename = common::NoLvalue<A>>
FormatItemFormatItem124   explicit FormatItem(A &&x) : u{std::move(x)} {}
125   std::optional<std::uint64_t> repeatCount;
126   std::variant<IntrinsicTypeDataEditDesc, DerivedTypeDataEditDesc,
127       ControlEditDesc, std::string, std::list<FormatItem>>
128       u;
129 };
130 
131 // R1302 format-specification ->
132 //         ( [format-items] ) | ( [format-items ,] unlimited-format-item )
133 // R1303 format-items -> format-item [[,] format-item]...
134 // R1305 unlimited-format-item -> * ( format-items )
135 struct FormatSpecification {
136   FormatSpecification() = delete;
137   FormatSpecification(FormatSpecification &&) = default;
138   FormatSpecification &operator=(FormatSpecification &&) = default;
FormatSpecificationFormatSpecification139   explicit FormatSpecification(std::list<FormatItem> &&is)
140       : items(std::move(is)) {}
FormatSpecificationFormatSpecification141   FormatSpecification(std::list<FormatItem> &&is, std::list<FormatItem> &&us)
142       : items(std::move(is)), unlimitedItems(std::move(us)) {}
143   std::list<FormatItem> items, unlimitedItems;
144 };
145 } // namespace Fortran::format
146 #endif // FORTRAN_PARSER_FORMAT_SPECIFICATION_H_
147