[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
`default:` label that obviously crashes.
#### 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. Define accessor and mutator member functions (implicitly) inline in the
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
and types.
Formally speaking, this parser is based on recursive descent with localized
backtracking. It is not generated as a table or code from a specification
of the Fortran grammar; rather, it _is_ the grammar, as declaratively
respecified in C++ constant expressions using a small collection of basic
token recognition objects and a library of "parser combinator" template
functions that compose them to form more complicated recognizers and
their correspondences to the construction of parse tree values.
Formally speaking, this parser is based on recursive descent with
localized backtracking (specifically, it will not backtrack into a
successful reduction to try its other alternatives). It is not generated
as a table or code from a specification of the Fortran grammar; rather, it
_is_ the grammar, as declaratively respecified in C++ constant expressions
using a small collection of basic token recognition objects and a library
of "parser combinator" template functions that compose them to form more
complicated recognizers and their correspondences to the construction
of parse tree values.
Unparsing
---------

View File

@ -91,10 +91,10 @@ struct ControlEditDesc {
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} {}
ControlEditDesc(Kind k, std::int64_t ct) : kind{k}, count{ct} {}
ControlEditDesc(std::int64_t ct, Kind k) : kind{k}, count{ct} {}
Kind kind;
int count{1}; // r, k, or n
std::int64_t count{1}; // r, k, or n
};
// R1304 format-item ->
@ -107,10 +107,10 @@ struct FormatItem {
FormatItem(FormatItem &&) = default;
FormatItem &operator=(FormatItem &&) = default;
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)} {}
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,
ControlEditDesc, std::string, std::list<FormatItem>>
u;

View File

@ -159,7 +159,7 @@ template<typename PA> inline constexpr auto indirect(const PA &p) {
// R711 digit-string -> digit [digit]...
// 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
// 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
// N.B. Not a complete token -- no space is skipped.
static inline std::int64_t negate(std::uint64_t &&n) {
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);
constexpr SignedDigitString signedDigitString;
// R707 signed-int-literal-constant -> [sign] int-literal-constant
TYPE_PARSER(space >> sourced(construct<SignedIntLiteralConstant>{}(
@ -3081,11 +3071,7 @@ constexpr auto formatItems =
nonemptySeparated(space >> Parser<format::FormatItem>{}, maybe(","_tok));
// R1306 r -> digit-string
static inline int castU64ToInt(std::uint64_t &&n) {
return n; // TODO: check for overflow
}
constexpr auto repeat = space >> applyFunction(castU64ToInt, digitString);
constexpr auto repeat = space >> digitString;
// R1304 format-item ->
// [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)))))
// R1314 k -> [sign] digit-string
static inline int castS64ToInt(std::int64_t &&n) {
return n; // TODO: check for overflow
}
constexpr auto scaleFactor = space >>
applyFunction(castS64ToInt, signedDigitString);
constexpr auto count = space >> DigitStringAsPositive{};
constexpr auto scaleFactor = count;
// R1313 control-edit-desc ->
// 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) ||
"R"_ch >> pure(format::ControlEditDesc::Kind::TR) ||
pure(format::ControlEditDesc::Kind::T)),
repeat) ||
construct<format::ControlEditDesc>{}(repeat,
count) ||
construct<format::ControlEditDesc>{}(count,
"X"_ch >> pure(format::ControlEditDesc::Kind::X) ||
"/"_ch >> pure(format::ControlEditDesc::Kind::Slash)) ||
construct<format::ControlEditDesc>{}(

View File

@ -457,6 +457,49 @@ constexpr struct 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
struct HollerithLiteral {
using resultType = std::string;