[flang] Resolve some TODOs in the grammar.

Original-commit: flang-compiler/f18@6ef9e2388b
Reviewed-on: https://github.com/flang-compiler/f18/pull/39
This commit is contained in:
peter klausler 2018-04-03 14:14:39 -07:00
parent 828cff6dbb
commit 382edf056b
5 changed files with 65 additions and 37 deletions

View File

@ -124,7 +124,7 @@ last (_pace_ the standard C library conventions for `memcpy()` & al.).
explicitly, it should contains either a `default:;` at its end or a explicitly, it should contains either a `default:;` at its end or a
`default:` label that obviously crashes. `default:` label that obviously crashes.
#### Classes #### Classes
1. Define only POD structures with `struct`. 1. Define POD structures with `struct`.
1. Don't use `this->` in (non-static) member functions. 1. Don't use `this->` in (non-static) member functions.
1. Define accessor and mutator member functions (implicitly) inline in the 1. Define accessor and mutator member functions (implicitly) inline in the
class, after constructors and assignments. Don't needlessly define class, after constructors and assignments. Don't needlessly define

View File

@ -178,13 +178,15 @@ as function calls. The semantic analysis phase of the compiler performs
local rewrites of the parse tree once it can be disambiguated by symbols local rewrites of the parse tree once it can be disambiguated by symbols
and types. and types.
Formally speaking, this parser is based on recursive descent with localized Formally speaking, this parser is based on recursive descent with
backtracking. It is not generated as a table or code from a specification localized backtracking (specifically, it will not backtrack into a
of the Fortran grammar; rather, it _is_ the grammar, as declaratively successful reduction to try its other alternatives). It is not generated
respecified in C++ constant expressions using a small collection of basic as a table or code from a specification of the Fortran grammar; rather, it
token recognition objects and a library of "parser combinator" template _is_ the grammar, as declaratively respecified in C++ constant expressions
functions that compose them to form more complicated recognizers and using a small collection of basic token recognition objects and a library
their correspondences to the construction of parse tree values. of "parser combinator" template functions that compose them to form more
complicated recognizers and their correspondences to the construction
of parse tree values.
Unparsing Unparsing
--------- ---------

View File

@ -91,10 +91,10 @@ struct ControlEditDesc {
ControlEditDesc(ControlEditDesc &&) = default; ControlEditDesc(ControlEditDesc &&) = default;
ControlEditDesc &operator=(ControlEditDesc &&) = default; ControlEditDesc &operator=(ControlEditDesc &&) = default;
explicit ControlEditDesc(Kind k) : kind{k} {} explicit ControlEditDesc(Kind k) : kind{k} {}
ControlEditDesc(Kind k, int ct) : kind{k}, count{ct} {} ControlEditDesc(Kind k, std::int64_t ct) : kind{k}, count{ct} {}
ControlEditDesc(int ct, Kind k) : kind{k}, count{ct} {} ControlEditDesc(std::int64_t ct, Kind k) : kind{k}, count{ct} {}
Kind kind; Kind kind;
int count{1}; // r, k, or n std::int64_t count{1}; // r, k, or n
}; };
// R1304 format-item -> // R1304 format-item ->
@ -107,10 +107,10 @@ struct FormatItem {
FormatItem(FormatItem &&) = default; FormatItem(FormatItem &&) = default;
FormatItem &operator=(FormatItem &&) = default; FormatItem &operator=(FormatItem &&) = default;
template<typename A> template<typename A>
FormatItem(std::optional<int> &&r, A &&x) FormatItem(std::optional<std::uint64_t> &&r, A &&x)
: repeatCount{std::move(r)}, u{std::move(x)} {} : repeatCount{std::move(r)}, u{std::move(x)} {}
template<typename A> explicit FormatItem(A &&x) : u{std::move(x)} {} template<typename A> explicit FormatItem(A &&x) : u{std::move(x)} {}
std::optional<int> repeatCount; std::optional<std::uint64_t> repeatCount;
std::variant<IntrinsicTypeDataEditDesc, DerivedTypeDataEditDesc, std::variant<IntrinsicTypeDataEditDesc, DerivedTypeDataEditDesc,
ControlEditDesc, std::string, std::list<FormatItem>> ControlEditDesc, std::string, std::list<FormatItem>>
u; u;

View File

@ -159,7 +159,7 @@ template<typename PA> inline constexpr auto indirect(const PA &p) {
// R711 digit-string -> digit [digit]... // R711 digit-string -> digit [digit]...
// N.B. not a token -- no space is skipped // N.B. not a token -- no space is skipped
constexpr auto digitString = DigitString{}; constexpr DigitString digitString;
// statement(p) parses Statement<P> for some statement type P that is the // statement(p) parses Statement<P> for some statement type P that is the
// result type of the argument parser p, while also handling labels and // result type of the argument parser p, while also handling labels and
@ -707,17 +707,7 @@ TYPE_PARSER(construct<KindSelector>{}(
// R710 signed-digit-string -> [sign] digit-string // R710 signed-digit-string -> [sign] digit-string
// N.B. Not a complete token -- no space is skipped. // N.B. Not a complete token -- no space is skipped.
static inline std::int64_t negate(std::uint64_t &&n) { constexpr SignedDigitString signedDigitString;
return -n; // TODO: check for overflow
}
static inline std::int64_t castToSigned(std::uint64_t &&n) {
return n; // TODO: check for overflow
}
constexpr auto signedDigitString = "-"_ch >>
applyFunction(negate, digitString) ||
maybe("+"_ch) >> applyFunction(castToSigned, digitString);
// R707 signed-int-literal-constant -> [sign] int-literal-constant // R707 signed-int-literal-constant -> [sign] int-literal-constant
TYPE_PARSER(space >> sourced(construct<SignedIntLiteralConstant>{}( TYPE_PARSER(space >> sourced(construct<SignedIntLiteralConstant>{}(
@ -3081,11 +3071,7 @@ constexpr auto formatItems =
nonemptySeparated(space >> Parser<format::FormatItem>{}, maybe(","_tok)); nonemptySeparated(space >> Parser<format::FormatItem>{}, maybe(","_tok));
// R1306 r -> digit-string // R1306 r -> digit-string
static inline int castU64ToInt(std::uint64_t &&n) { constexpr auto repeat = space >> digitString;
return n; // TODO: check for overflow
}
constexpr auto repeat = space >> applyFunction(castU64ToInt, digitString);
// R1304 format-item -> // R1304 format-item ->
// [r] data-edit-desc | control-edit-desc | char-string-edit-desc | // [r] data-edit-desc | control-edit-desc | char-string-edit-desc |
@ -3177,11 +3163,8 @@ TYPE_PARSER("D"_ch >> "T"_ch >>
defaulted(parenthesized(nonemptyList(space >> signedDigitString))))) defaulted(parenthesized(nonemptyList(space >> signedDigitString)))))
// R1314 k -> [sign] digit-string // R1314 k -> [sign] digit-string
static inline int castS64ToInt(std::int64_t &&n) { constexpr auto count = space >> DigitStringAsPositive{};
return n; // TODO: check for overflow constexpr auto scaleFactor = count;
}
constexpr auto scaleFactor = space >>
applyFunction(castS64ToInt, signedDigitString);
// R1313 control-edit-desc -> // R1313 control-edit-desc ->
// position-edit-desc | [r] / | : | sign-edit-desc | k P | // position-edit-desc | [r] / | : | sign-edit-desc | k P |
@ -3196,8 +3179,8 @@ TYPE_PARSER(construct<format::ControlEditDesc>{}("T"_ch >>
("L"_ch >> pure(format::ControlEditDesc::Kind::TL) || ("L"_ch >> pure(format::ControlEditDesc::Kind::TL) ||
"R"_ch >> pure(format::ControlEditDesc::Kind::TR) || "R"_ch >> pure(format::ControlEditDesc::Kind::TR) ||
pure(format::ControlEditDesc::Kind::T)), pure(format::ControlEditDesc::Kind::T)),
repeat) || count) ||
construct<format::ControlEditDesc>{}(repeat, construct<format::ControlEditDesc>{}(count,
"X"_ch >> pure(format::ControlEditDesc::Kind::X) || "X"_ch >> pure(format::ControlEditDesc::Kind::X) ||
"/"_ch >> pure(format::ControlEditDesc::Kind::Slash)) || "/"_ch >> pure(format::ControlEditDesc::Kind::Slash)) ||
construct<format::ControlEditDesc>{}( construct<format::ControlEditDesc>{}(

View File

@ -457,6 +457,49 @@ constexpr struct SkipDigitString {
} }
} skipDigitString; } skipDigitString;
struct DigitStringAsPositive {
using resultType = std::int64_t;
static std::optional<std::int64_t> Parse(ParseState *state) {
Location at{state->GetLocation()};
std::optional<std::uint64_t> x{DigitString{}.Parse(state)};
if (!x.has_value()) {
return {};
}
if (*x > std::numeric_limits<std::int64_t>::max()) {
state->Say(at, "overflow in positive decimal literal"_err_en_US);
}
std::int64_t value = *x;
return {value};
}
};
struct SignedDigitString {
using resultType = std::int64_t;
static std::optional<std::int64_t> Parse(ParseState *state) {
std::optional<const char *> sign{state->PeekAtNextChar()};
if (!sign.has_value()) {
return {};
}
bool negate{**sign == '-'};
if (negate || **sign == '+') {
state->UncheckedAdvance();
}
std::optional<std::uint64_t> x{DigitString{}.Parse(state)};
if (!x.has_value()) {
return {};
}
std::uint64_t limit{std::numeric_limits<std::int64_t>::max()};
if (negate) {
limit = -(limit + 1);
}
if (*x > limit) {
state->Say(*sign, "overflow in signed decimal literal"_err_en_US);
}
std::int64_t value = *x;
return {negate ? -value : value};
}
};
// Legacy feature: Hollerith literal constants // Legacy feature: Hollerith literal constants
struct HollerithLiteral { struct HollerithLiteral {
using resultType = std::string; using resultType = std::string;