[flang] Fix tokenization of signed-int-literal-constant, allow internal space.
Original-commit: flang-compiler/f18@afa6425b48 Reviewed-on: https://github.com/flang-compiler/f18/pull/90 Tree-same-pre-rewrite: false
This commit is contained in:
parent
51e63799fd
commit
454f909cbc
2 changed files with 54 additions and 44 deletions
|
@ -481,8 +481,8 @@ TYPE_PARSER(construct<KindSelector>(
|
|||
construct<KindSelector::StarSize>("*" >> digitString / spaceCheck))))
|
||||
|
||||
// R707 signed-int-literal-constant -> [sign] int-literal-constant
|
||||
TYPE_PARSER(space >> sourced(construct<SignedIntLiteralConstant>(
|
||||
signedDigitString, maybe(underscore >> kindParam))))
|
||||
TYPE_PARSER(sourced(construct<SignedIntLiteralConstant>(
|
||||
SignedIntLiteralConstantWithoutKind{}, maybe(underscore >> kindParam))))
|
||||
|
||||
// R708 int-literal-constant -> digit-string [_ kind-param]
|
||||
// The negated look-ahead for a trailing underscore prevents misrecognition
|
||||
|
@ -495,9 +495,11 @@ TYPE_PARSER(construct<KindParam>(digitString) ||
|
|||
construct<KindParam>(scalar(integer(constant(name)))))
|
||||
|
||||
// R712 sign -> + | -
|
||||
// Not a complete token.
|
||||
constexpr auto sign = "+"_ch >> pure(Sign::Positive) ||
|
||||
"-"_ch >> pure(Sign::Negative);
|
||||
// N.B. A sign constitutes a whole token, so a space is allowed in free form
|
||||
// after the sign and before a real-literal-constant or
|
||||
// complex-literal-constant. A sign is not a unary operator in these contexts.
|
||||
constexpr auto sign = "+"_tok >> pure(Sign::Positive) ||
|
||||
"-"_tok >> pure(Sign::Negative);
|
||||
|
||||
// R713 signed-real-literal-constant -> [sign] real-literal-constant
|
||||
constexpr auto signedRealLiteralConstant = space >>
|
||||
|
@ -512,7 +514,7 @@ constexpr auto signedRealLiteralConstant = space >>
|
|||
// R717 exponent -> signed-digit-string
|
||||
// N.B. Preceding space is not skipped.
|
||||
constexpr auto exponentPart =
|
||||
("ed"_ch || extension("q"_ch)) >> signedDigitString;
|
||||
("ed"_ch || extension("q"_ch)) >> SignedDigitString{};
|
||||
|
||||
TYPE_CONTEXT_PARSER("REAL literal constant"_en_US,
|
||||
construct<RealLiteralConstant>(
|
||||
|
@ -532,7 +534,7 @@ TYPE_CONTEXT_PARSER("COMPLEX literal constant"_en_US,
|
|||
|
||||
// PGI/Intel extension: signed complex literal constant
|
||||
TYPE_PARSER(construct<SignedComplexLiteralConstant>(
|
||||
space >> sign, Parser<ComplexLiteralConstant>{}))
|
||||
sign, Parser<ComplexLiteralConstant>{}))
|
||||
|
||||
// R719 real-part ->
|
||||
// signed-int-literal-constant | signed-real-literal-constant |
|
||||
|
|
|
@ -446,9 +446,47 @@ constexpr struct SkipDigitString {
|
|||
}
|
||||
} skipDigitString;
|
||||
|
||||
// R707 signed-int-literal-constant -> [sign] int-literal-constant
|
||||
// N.B. Spaces are consumed before and after the sign, since the sign
|
||||
// and the int-literal-constant are distinct tokens. Does not
|
||||
// handle a trailing kind parameter.
|
||||
static inline constexpr std::optional<std::int64_t> SignedInteger(
|
||||
const std::optional<std::uint64_t> &x, Location at, bool negate,
|
||||
ParseState &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(at, "overflow in signed decimal literal"_err_en_US);
|
||||
}
|
||||
std::int64_t value = *x;
|
||||
return {negate ? -value : value};
|
||||
}
|
||||
|
||||
struct SignedIntLiteralConstantWithoutKind {
|
||||
using resultType = std::int64_t;
|
||||
static std::optional<std::int64_t> Parse(ParseState &state) {
|
||||
Location at{state.GetLocation()};
|
||||
static constexpr auto minus = attempt("-"_tok);
|
||||
static constexpr auto plus = maybe("+"_tok);
|
||||
bool negate{false};
|
||||
if (minus.Parse(state)) {
|
||||
negate = true;
|
||||
} else if (!plus.Parse(state)) {
|
||||
return {};
|
||||
}
|
||||
return SignedInteger(digitString.Parse(state), at, negate, state);
|
||||
}
|
||||
};
|
||||
|
||||
// R710 signed-digit-string -> [sign] digit-string
|
||||
// N.B. Not a complete token -- no space is skipped.
|
||||
constexpr struct SignedDigitString {
|
||||
// Used only in the exponent parts of real literal constants.
|
||||
struct SignedDigitString {
|
||||
using resultType = std::int64_t;
|
||||
static std::optional<std::int64_t> Parse(ParseState &state) {
|
||||
std::optional<const char *> sign{state.PeekAtNextChar()};
|
||||
|
@ -459,21 +497,9 @@ constexpr struct SignedDigitString {
|
|||
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};
|
||||
return SignedInteger(digitString.Parse(state), *sign, negate, state);
|
||||
}
|
||||
} signedDigitString;
|
||||
};
|
||||
|
||||
// Variants of the above for use in FORMAT specifications, where spaces
|
||||
// must be ignored.
|
||||
|
@ -510,15 +536,8 @@ struct PositiveDigitStringIgnoreSpaces {
|
|||
using resultType = std::int64_t;
|
||||
static std::optional<std::int64_t> Parse(ParseState &state) {
|
||||
Location at{state.GetLocation()};
|
||||
std::optional<std::uint64_t> x{DigitStringIgnoreSpaces{}.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};
|
||||
return SignedInteger(
|
||||
DigitStringIgnoreSpaces{}.Parse(state), at, false /*positive*/, state);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -531,19 +550,8 @@ struct SignedDigitStringIgnoreSpaces {
|
|||
negate = **sign == '-';
|
||||
}
|
||||
Location at{state.GetLocation()};
|
||||
std::optional<std::uint64_t> x{DigitStringIgnoreSpaces{}.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(at, "overflow in signed decimal literal"_err_en_US);
|
||||
}
|
||||
std::int64_t value = *x;
|
||||
return {negate ? -value : value};
|
||||
return SignedInteger(
|
||||
DigitStringIgnoreSpaces{}.Parse(state), at, negate, state);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue