20364f0351
The classes that were segregated into format-specification.h have also been grouped into a new Fortran::format namespace. Code added to tools/f18/f18.cc to run a minimal visitor over the parse trees resulting from successful parses so that any future build problems with Walk() will be caught earlier. Rearrange Walk instances, keep format:: ones together. Original-commit: flang-compiler/f18@685ddb91ce Reviewed-on: https://github.com/flang-compiler/f18/pull/22
135 lines
4.7 KiB
C++
135 lines
4.7 KiB
C++
#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 <cinttypes>
|
|
#include <list>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <variant>
|
|
|
|
namespace Fortran {
|
|
namespace format {
|
|
|
|
// 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<int> &&w,
|
|
std::optional<int> &&d, std::optional<int> &&e)
|
|
: kind{k}, width{std::move(w)}, digits{std::move(d)}, exponentWidth{
|
|
std::move(e)} {}
|
|
Kind kind;
|
|
std::optional<int> width; // w
|
|
std::optional<int> digits; // m or d
|
|
std::optional<int> 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<std::int64_t> &&p)
|
|
: type{std::move(t)}, parameters{std::move(p)} {}
|
|
std::string type;
|
|
std::list<std::int64_t> 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<typename A>
|
|
FormatItem(std::optional<int> &&r, A &&x)
|
|
: repeatCount{std::move(r)}, u{std::move(x)} {}
|
|
template<typename A> explicit FormatItem(A &&x) : u{std::move(x)} {}
|
|
std::optional<int> repeatCount;
|
|
std::variant<IntrinsicTypeDataEditDesc, DerivedTypeDataEditDesc,
|
|
ControlEditDesc, std::string, std::list<FormatItem>>
|
|
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<FormatItem> &&is)
|
|
: items(std::move(is)) {}
|
|
FormatSpecification(std::list<FormatItem> &&is, std::list<FormatItem> &&us)
|
|
: items(std::move(is)), unlimitedItems(std::move(us)) {}
|
|
std::list<FormatItem> items, unlimitedItems;
|
|
};
|
|
} // namespace format
|
|
} // namespace Fortran
|
|
#endif // FORTRAN_FORMAT_SPECIFICATION_H_
|