1 // Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef FORTRAN_PARSER_FORMAT_SPECIFICATION_H_ 16 #define FORTRAN_PARSER_FORMAT_SPECIFICATION_H_ 17 18 // Represent parses of Fortran format specifications from FORMAT statements 19 // and character literals in formatted I/O statements at compilation time 20 // as well as from character variables and expressions at run time. 21 // From requirement productions R1302-R1321 of the Fortran 2018 draft 22 // standard (q.v.), extended with Hollerith. These structures have been 23 // isolated so that they may be used in the run-time without introducing 24 // dependences on other parts of the compiler's source code. 25 // TODO: support Q formatting extension? 26 27 #include <cinttypes> 28 #include <list> 29 #include <optional> 30 #include <string> 31 #include <variant> 32 33 namespace Fortran::format { 34 35 // R1307 data-edit-desc (part 1 of 2) -> 36 // I w [. m] | B w [. m] | O w [. m] | Z w [. m] | F w . d | 37 // E w . d [E e] | EN w . d [E e] | ES w . d [E e] | EX w . d [E e] | 38 // G w [. d [E e]] | L w | A [w] | D w . d 39 // R1308 w -> digit-string 40 // R1309 m -> digit-string 41 // R1310 d -> digit-string 42 // R1311 e -> digit-string 43 struct IntrinsicTypeDataEditDesc { 44 enum class Kind { I, B, O, Z, F, E, EN, ES, EX, G, L, A, D }; 45 IntrinsicTypeDataEditDesc() = delete; 46 IntrinsicTypeDataEditDesc(IntrinsicTypeDataEditDesc &&) = default; 47 IntrinsicTypeDataEditDesc &operator=(IntrinsicTypeDataEditDesc &&) = default; IntrinsicTypeDataEditDescIntrinsicTypeDataEditDesc48 IntrinsicTypeDataEditDesc(Kind &&k, std::optional<int> &&w, 49 std::optional<int> &&d, std::optional<int> &&e) 50 : kind{k}, width{std::move(w)}, digits{std::move(d)}, exponentWidth{ 51 std::move(e)} {} 52 Kind kind; 53 std::optional<int> width; // w 54 std::optional<int> digits; // m or d 55 std::optional<int> exponentWidth; // e 56 }; 57 58 // R1307 data-edit-desc (part 2 of 2) -> 59 // DT [char-literal-constant] [( v-list )] 60 // R1312 v -> [sign] digit-string 61 struct DerivedTypeDataEditDesc { 62 DerivedTypeDataEditDesc() = delete; 63 DerivedTypeDataEditDesc(DerivedTypeDataEditDesc &&) = default; 64 DerivedTypeDataEditDesc &operator=(DerivedTypeDataEditDesc &&) = default; DerivedTypeDataEditDescDerivedTypeDataEditDesc65 DerivedTypeDataEditDesc(std::string &&t, std::list<std::int64_t> &&p) 66 : type{std::move(t)}, parameters{std::move(p)} {} 67 std::string type; 68 std::list<std::int64_t> parameters; 69 }; 70 71 // R1313 control-edit-desc -> 72 // position-edit-desc | [r] / | : | sign-edit-desc | k P | 73 // blank-interp-edit-desc | round-edit-desc | decimal-edit-desc | 74 // @ \ | $ 75 // R1315 position-edit-desc -> T n | TL n | TR n | n X 76 // R1316 n -> digit-string 77 // R1317 sign-edit-desc -> SS | SP | S 78 // R1318 blank-interp-edit-desc -> BN | BZ 79 // R1319 round-edit-desc -> RU | RD | RZ | RN | RC | RP 80 // R1320 decimal-edit-desc -> DC | DP 81 struct ControlEditDesc { 82 enum class Kind { 83 T, 84 TL, 85 TR, 86 X, 87 Slash, 88 Colon, 89 SS, 90 SP, 91 S, 92 P, 93 BN, 94 BZ, 95 RU, 96 RD, 97 RZ, 98 RN, 99 RC, 100 RP, 101 DC, 102 DP, 103 Dollar, // extension: inhibit newline on output 104 Backslash, // ditto, but only on terminals 105 }; 106 ControlEditDesc() = delete; 107 ControlEditDesc(ControlEditDesc &&) = default; 108 ControlEditDesc &operator=(ControlEditDesc &&) = default; ControlEditDescControlEditDesc109 explicit ControlEditDesc(Kind k) : kind{k} {} ControlEditDescControlEditDesc110 ControlEditDesc(Kind k, std::int64_t ct) : kind{k}, count{ct} {} ControlEditDescControlEditDesc111 ControlEditDesc(std::int64_t ct, Kind k) : kind{k}, count{ct} {} 112 Kind kind; 113 std::int64_t count{1}; // r, k, or n 114 }; 115 116 // R1304 format-item -> 117 // [r] data-edit-desc | control-edit-desc | char-string-edit-desc | 118 // [r] ( format-items ) 119 // R1306 r -> digit-string 120 // R1321 char-string-edit-desc 121 struct FormatItem { 122 FormatItem() = delete; 123 FormatItem(FormatItem &&) = default; 124 FormatItem &operator=(FormatItem &&) = default; 125 template<typename A, typename = common::NoLvalue<A>> FormatItemFormatItem126 FormatItem(std::optional<std::uint64_t> &&r, A &&x) 127 : repeatCount{std::move(r)}, u{std::move(x)} {} 128 template<typename A, typename = common::NoLvalue<A>> FormatItemFormatItem129 explicit FormatItem(A &&x) : u{std::move(x)} {} 130 std::optional<std::uint64_t> repeatCount; 131 std::variant<IntrinsicTypeDataEditDesc, DerivedTypeDataEditDesc, 132 ControlEditDesc, std::string, std::list<FormatItem>> 133 u; 134 }; 135 136 // R1302 format-specification -> 137 // ( [format-items] ) | ( [format-items ,] unlimited-format-item ) 138 // R1303 format-items -> format-item [[,] format-item]... 139 // R1305 unlimited-format-item -> * ( format-items ) 140 struct FormatSpecification { 141 FormatSpecification() = delete; 142 FormatSpecification(FormatSpecification &&) = default; 143 FormatSpecification &operator=(FormatSpecification &&) = default; FormatSpecificationFormatSpecification144 explicit FormatSpecification(std::list<FormatItem> &&is) 145 : items(std::move(is)) {} FormatSpecificationFormatSpecification146 FormatSpecification(std::list<FormatItem> &&is, std::list<FormatItem> &&us) 147 : items(std::move(is)), unlimitedItems(std::move(us)) {} 148 std::list<FormatItem> items, unlimitedItems; 149 }; 150 } 151 #endif // FORTRAN_PARSER_FORMAT_SPECIFICATION_H_ 152