mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 10:41:03 +01:00
Add support for octal numbers (#6909)
This implements the leads decision made in #6821, proposal #6910. The proposal is pending, but I figured it's relatively safe to just do given the decision. Assisted-by: Google Antigravity with Gemini --------- Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
This commit is contained in:
co-authored by
Chandler Carruth
parent
c5761d2d16
commit
613a139bef
@@ -54,7 +54,7 @@ CARBON_DIAGNOSTIC_KIND(ErrorReadingFile)
|
||||
// Lexer diagnostics
|
||||
// ============================================================================
|
||||
|
||||
CARBON_DIAGNOSTIC_KIND(BinaryRealLiteral)
|
||||
CARBON_DIAGNOSTIC_KIND(InvalidRealLiteralRadix)
|
||||
CARBON_DIAGNOSTIC_KIND(ContentBeforeStringTerminator)
|
||||
CARBON_DIAGNOSTIC_KIND(DecimalEscapeSequence)
|
||||
CARBON_DIAGNOSTIC_KIND(DumpSemIRRangeMissingEnd)
|
||||
|
||||
@@ -159,6 +159,8 @@ NumericLiteral::Parser::Parser(Diagnostics::Emitter<const char*>& emitter,
|
||||
radix_ = Radix::Hexadecimal;
|
||||
} else if (int_part_.consume_front("0b")) {
|
||||
radix_ = Radix::Binary;
|
||||
} else if (int_part_.consume_front("0o")) {
|
||||
radix_ = Radix::Octal;
|
||||
}
|
||||
|
||||
fract_part_ = literal.text_.substr(
|
||||
@@ -190,16 +192,28 @@ static auto ParseBinary(llvm::StringRef digits) -> llvm::APInt {
|
||||
return value;
|
||||
}
|
||||
|
||||
// Parses a hexadecimal integer literal.
|
||||
static auto ParseHexadecimal(llvm::StringRef digits) -> llvm::APInt {
|
||||
llvm::APInt value(std::max<int>(IntStore::MinAPWidth, digits.size() * 4), 0);
|
||||
int cursor = digits.size() * 4 - 1;
|
||||
// Parses an octal or hexadecimal integer literal.
|
||||
template <NumericLiteral::Radix Radix>
|
||||
requires(Radix == NumericLiteral::Radix::Hexadecimal ||
|
||||
Radix == NumericLiteral::Radix::Octal)
|
||||
static auto ParseOctalOrHexadecimal(llvm::StringRef digits) -> llvm::APInt {
|
||||
constexpr int BitsPerDigit =
|
||||
Radix == NumericLiteral::Radix::Hexadecimal ? 4 : 3;
|
||||
llvm::APInt value(
|
||||
std::max<int>(IntStore::MinAPWidth, digits.size() * BitsPerDigit), 0);
|
||||
int cursor = digits.size() * BitsPerDigit - 1;
|
||||
for (char c : digits) {
|
||||
uint8_t digit = c <= '9' ? (c - '0') : (c - 'A' + 10);
|
||||
if (digit & 0x8) {
|
||||
value.setBit(cursor);
|
||||
uint8_t digit;
|
||||
if constexpr (Radix == NumericLiteral::Radix::Octal) {
|
||||
digit = c - '0';
|
||||
} else {
|
||||
digit = c <= '9' ? (c - '0') : (c - 'A' + 10);
|
||||
|
||||
if (digit & 0x8) {
|
||||
value.setBit(cursor);
|
||||
}
|
||||
--cursor;
|
||||
}
|
||||
--cursor;
|
||||
if (digit & 0x4) {
|
||||
value.setBit(cursor);
|
||||
}
|
||||
@@ -289,10 +303,13 @@ static auto ParseInt(llvm::StringRef digits, NumericLiteral::Radix radix,
|
||||
switch (radix) {
|
||||
case NumericLiteral::Radix::Binary:
|
||||
return ParseBinary(digits);
|
||||
case NumericLiteral::Radix::Octal:
|
||||
return ParseOctalOrHexadecimal<NumericLiteral::Radix::Octal>(digits);
|
||||
case NumericLiteral::Radix::Decimal:
|
||||
return ParseDecimal(digits);
|
||||
case NumericLiteral::Radix::Hexadecimal:
|
||||
return ParseHexadecimal(digits);
|
||||
return ParseOctalOrHexadecimal<NumericLiteral::Radix::Hexadecimal>(
|
||||
digits);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +343,8 @@ auto NumericLiteral::Parser::GetExponent() -> llvm::APInt {
|
||||
int excess_exponent = fract_part_.size();
|
||||
if (radix_ == Radix::Hexadecimal) {
|
||||
excess_exponent *= 4;
|
||||
} else if (radix_ == Radix::Octal) {
|
||||
excess_exponent *= 3;
|
||||
}
|
||||
exponent -= excess_exponent;
|
||||
if (exponent_is_negative_ && !exponent.isNegative()) {
|
||||
@@ -347,22 +366,9 @@ auto NumericLiteral::Parser::CheckDigitSequence(llvm::StringRef text,
|
||||
bool allow_digit_separators)
|
||||
-> CheckDigitSequenceResult {
|
||||
std::bitset<256> valid_digits;
|
||||
switch (radix) {
|
||||
case Radix::Binary:
|
||||
for (char c : "01") {
|
||||
valid_digits[static_cast<unsigned char>(c)] = true;
|
||||
}
|
||||
break;
|
||||
case Radix::Decimal:
|
||||
for (char c : "0123456789") {
|
||||
valid_digits[static_cast<unsigned char>(c)] = true;
|
||||
}
|
||||
break;
|
||||
case Radix::Hexadecimal:
|
||||
for (char c : "0123456789ABCDEF") {
|
||||
valid_digits[static_cast<unsigned char>(c)] = true;
|
||||
}
|
||||
break;
|
||||
static constexpr llvm::StringLiteral Digits = "0123456789ABCDEF";
|
||||
for (char c : Digits.take_front(static_cast<int>(radix))) {
|
||||
valid_digits[static_cast<unsigned char>(c)] = true;
|
||||
}
|
||||
|
||||
int num_digit_separators = 0;
|
||||
@@ -386,11 +392,11 @@ auto NumericLiteral::Parser::CheckDigitSequence(llvm::StringRef text,
|
||||
continue;
|
||||
}
|
||||
|
||||
CARBON_DIAGNOSTIC(
|
||||
InvalidDigit, Error,
|
||||
"invalid digit '{0}' in {1:=2:binary|=10:decimal|=16:hexadecimal} "
|
||||
"numeric literal",
|
||||
char, Diagnostics::IntAsSelect);
|
||||
CARBON_DIAGNOSTIC(InvalidDigit, Error,
|
||||
"invalid digit '{0}' in "
|
||||
"{1:=2:binary|=8:octal|=10:decimal|=16:hexadecimal} "
|
||||
"numeric literal",
|
||||
char, Diagnostics::IntAsSelect);
|
||||
emitter_.Emit(text.begin() + i, InvalidDigit, c, static_cast<int>(radix));
|
||||
return {.ok = false};
|
||||
}
|
||||
@@ -435,12 +441,14 @@ auto NumericLiteral::Parser::CheckFractionalPart() -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (radix_ == Radix::Binary) {
|
||||
CARBON_DIAGNOSTIC(BinaryRealLiteral, Error,
|
||||
"binary real number literals are not supported");
|
||||
if (radix_ == Radix::Binary || radix_ == Radix::Octal) {
|
||||
CARBON_DIAGNOSTIC(
|
||||
InvalidRealLiteralRadix, Error,
|
||||
"{0:=2:binary|=8:octal} real number literals are not supported",
|
||||
Diagnostics::IntAsSelect);
|
||||
emitter_.Emit(literal_.text_.begin() + literal_.radix_point_,
|
||||
BinaryRealLiteral);
|
||||
// Carry on and parse the binary real literal anyway.
|
||||
InvalidRealLiteralRadix, static_cast<int>(radix_));
|
||||
// Carry on and parse the real literal anyway.
|
||||
}
|
||||
|
||||
// We need to remove a '.' from the mantissa.
|
||||
|
||||
@@ -17,7 +17,12 @@ namespace Carbon::Lex {
|
||||
// A numeric literal token that has been extracted from a source buffer.
|
||||
class NumericLiteral {
|
||||
public:
|
||||
enum class Radix : int8_t { Binary = 2, Decimal = 10, Hexadecimal = 16 };
|
||||
enum class Radix : int8_t {
|
||||
Binary = 2,
|
||||
Octal = 8,
|
||||
Decimal = 10,
|
||||
Hexadecimal = 16
|
||||
};
|
||||
|
||||
// Value of an integer literal.
|
||||
struct IntValue {
|
||||
|
||||
@@ -15,14 +15,17 @@ namespace {
|
||||
|
||||
// Returns an integer literal string with `prefix` followed by `num_digits`
|
||||
// entries from `digits` (repeating `digits` as necessary).
|
||||
static auto MakeIntString(llvm::StringLiteral prefix,
|
||||
llvm::StringLiteral digits, size_t num_digits)
|
||||
static auto MakeIntString(llvm::StringLiteral prefix, int radix, int num_digits)
|
||||
-> std::string {
|
||||
// Digits are reversed so that we can take `radix` digits from the end, and
|
||||
// never have 0 be the first digit.
|
||||
static constexpr llvm::StringLiteral Digits = "FEDCBA9876543210";
|
||||
|
||||
std::string s;
|
||||
s.reserve(prefix.size() + num_digits);
|
||||
s.append(prefix);
|
||||
for (size_t i = 0; i < num_digits; i += digits.size()) {
|
||||
s.append(digits.take_front(std::min(digits.size(), num_digits - i)));
|
||||
for (int i = 0; i < num_digits; i += radix) {
|
||||
s.append(Digits.take_back(std::min(radix, num_digits - i)));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -40,7 +43,7 @@ static void BM_Lex_Int(benchmark::State& state) {
|
||||
}
|
||||
|
||||
static void BM_Lex_IntDecimalN(benchmark::State& state) {
|
||||
std::string s = MakeIntString("", "1234567890", state.range(0));
|
||||
std::string s = MakeIntString("", 10, state.range(0));
|
||||
for (auto _ : state) {
|
||||
CARBON_CHECK(NumericLiteral::Lex(s, true));
|
||||
}
|
||||
@@ -65,7 +68,7 @@ static void BM_ComputeValue_Int(benchmark::State& state) {
|
||||
}
|
||||
|
||||
static void BM_ComputeValue_IntDecimalN(benchmark::State& state) {
|
||||
std::string s = MakeIntString("", "1234567890", state.range(0));
|
||||
std::string s = MakeIntString("", 10, state.range(0));
|
||||
auto val = NumericLiteral::Lex(s, true);
|
||||
auto& emitter = Diagnostics::NullEmitter<const char*>();
|
||||
CARBON_CHECK(val);
|
||||
@@ -75,7 +78,17 @@ static void BM_ComputeValue_IntDecimalN(benchmark::State& state) {
|
||||
}
|
||||
|
||||
static void BM_ComputeValue_IntBinaryN(benchmark::State& state) {
|
||||
std::string s = MakeIntString("0b", "10", state.range(0));
|
||||
std::string s = MakeIntString("0b", 2, state.range(0));
|
||||
auto val = NumericLiteral::Lex(s, true);
|
||||
auto& emitter = Diagnostics::NullEmitter<const char*>();
|
||||
CARBON_CHECK(val);
|
||||
for (auto _ : state) {
|
||||
val->ComputeValue(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static void BM_ComputeValue_IntOctalN(benchmark::State& state) {
|
||||
std::string s = MakeIntString("0o", 8, state.range(0));
|
||||
auto val = NumericLiteral::Lex(s, true);
|
||||
auto& emitter = Diagnostics::NullEmitter<const char*>();
|
||||
CARBON_CHECK(val);
|
||||
@@ -86,7 +99,7 @@ static void BM_ComputeValue_IntBinaryN(benchmark::State& state) {
|
||||
|
||||
static void BM_ComputeValue_IntHexN(benchmark::State& state) {
|
||||
// 0 is in the middle so that it isn't truncated in parse.
|
||||
std::string s = MakeIntString("0x", "1234567890ABCDEF", state.range(0));
|
||||
std::string s = MakeIntString("0x", 16, state.range(0));
|
||||
auto val = NumericLiteral::Lex(s, true);
|
||||
auto& emitter = Diagnostics::NullEmitter<const char*>();
|
||||
CARBON_CHECK(val);
|
||||
@@ -102,6 +115,7 @@ BENCHMARK(BM_ComputeValue_Float);
|
||||
BENCHMARK(BM_ComputeValue_Int);
|
||||
BENCHMARK(BM_ComputeValue_IntDecimalN)->RangeMultiplier(10)->Range(1, 10000);
|
||||
BENCHMARK(BM_ComputeValue_IntBinaryN)->RangeMultiplier(10)->Range(1, 10000);
|
||||
BENCHMARK(BM_ComputeValue_IntOctalN)->RangeMultiplier(10)->Range(1, 10000);
|
||||
BENCHMARK(BM_ComputeValue_IntHexN)->RangeMultiplier(10)->Range(1, 10000);
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -95,6 +95,7 @@ TEST_F(NumericLiteralTest, HandlesIntLiteral) {
|
||||
{.token = "12", .value = 12, .radix = 10},
|
||||
{.token = "0x12_3ABC", .value = 0x12'3ABC, .radix = 16},
|
||||
{.token = "0b10_10_11", .value = 0b10'10'11, .radix = 2},
|
||||
{.token = "0o12_345", .value = 012345, .radix = 8},
|
||||
{.token = "1_234_567", .value = 1'234'567, .radix = 10},
|
||||
};
|
||||
for (bool can_form_real_literal : {false, true}) {
|
||||
@@ -122,6 +123,10 @@ TEST_F(NumericLiteralTest, ValidatesBaseSpecifier) {
|
||||
// Binary integer literals.
|
||||
"0b10110100101001010",
|
||||
"0b0000000",
|
||||
|
||||
// Octal integer literals.
|
||||
"0o01234567",
|
||||
"0o0000000",
|
||||
};
|
||||
for (llvm::StringLiteral literal : valid) {
|
||||
error_tracker.Reset();
|
||||
@@ -130,10 +135,9 @@ TEST_F(NumericLiteralTest, ValidatesBaseSpecifier) {
|
||||
}
|
||||
|
||||
llvm::StringLiteral invalid[] = {
|
||||
"00", "0X123", "0o123", "0B1",
|
||||
"007", "123L", "123456789A", "0x",
|
||||
"0b", "0x123abc", "0b011101201001", "0b10A",
|
||||
"0x_", "0b_",
|
||||
"00", "0X123", "0O123", "0B1", "007", "123L",
|
||||
"123456789A", "0x", "0b", "0o", "0x123abc", "0b011101201001",
|
||||
"0b10A", "0x_", "0b_", "0o_", "0o1238", "0o12A",
|
||||
};
|
||||
for (llvm::StringLiteral literal : invalid) {
|
||||
error_tracker.Reset();
|
||||
@@ -162,6 +166,10 @@ TEST_F(NumericLiteralTest, ValidatesIntDigitSeparators) {
|
||||
// Binary literals.
|
||||
"0b1_0_1_0_1_0",
|
||||
"0b111_0000",
|
||||
|
||||
// Octal literals.
|
||||
"0o1_234",
|
||||
"0o12_34",
|
||||
};
|
||||
for (llvm::StringLiteral literal : valid) {
|
||||
error_tracker.Reset();
|
||||
@@ -184,6 +192,11 @@ TEST_F(NumericLiteralTest, ValidatesIntDigitSeparators) {
|
||||
"0b1__01",
|
||||
"0b1011_",
|
||||
"0b1_01_01_",
|
||||
|
||||
// Octal literals.
|
||||
"0o_1234",
|
||||
"0o123_",
|
||||
"0o1_2__34",
|
||||
};
|
||||
for (llvm::StringLiteral literal : invalid) {
|
||||
error_tracker.Reset();
|
||||
@@ -275,6 +288,14 @@ TEST_F(NumericLiteralTest, HandlesRealLiteral) {
|
||||
.exponent = -2,
|
||||
.radix = 2,
|
||||
.int_value = 0b101101},
|
||||
|
||||
// Octal real literals. These are invalid, but we accept them for error
|
||||
// recovery.
|
||||
{.token = "0o12_34.56",
|
||||
.mantissa = 0123456,
|
||||
.exponent = -6,
|
||||
.radix = 8,
|
||||
.int_value = 01234},
|
||||
};
|
||||
// Check we get the right real value.
|
||||
for (Testcase testcase : testcases) {
|
||||
@@ -284,7 +305,8 @@ TEST_F(NumericLiteralTest, HandlesRealLiteral) {
|
||||
.mantissa = IsUnsignedInt(testcase.mantissa),
|
||||
.exponent = IsSignedInt(testcase.exponent)}))
|
||||
<< testcase.token;
|
||||
EXPECT_EQ(error_tracker.seen_error(), testcase.radix == 2)
|
||||
EXPECT_EQ(error_tracker.seen_error(),
|
||||
testcase.radix == 2 || testcase.radix == 8)
|
||||
<< testcase.token;
|
||||
}
|
||||
// If we are required to stop at the `.` character, check we get the right int
|
||||
@@ -319,6 +341,8 @@ TEST_F(NumericLiteralTest, ValidatesRealLiterals) {
|
||||
"0b.0",
|
||||
"0x_.0",
|
||||
"0b_.0",
|
||||
"0o.0",
|
||||
"0o_.0",
|
||||
|
||||
// No digits in fractional part.
|
||||
"0.e",
|
||||
|
||||
+52
-37
@@ -18,7 +18,7 @@ fn F() {
|
||||
// CHECK:STDOUT: - { index: 2, kind: "Identifier", line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: "F", identifier: 0, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 3, kind: "OpenParen", line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: "(", closing_token: 4 }
|
||||
// CHECK:STDOUT: - { index: 4, kind: "CloseParen", line: {{ *}}[[@LINE-4]], column: 6, indent: 1, spelling: ")", opening_token: 3 }
|
||||
// CHECK:STDOUT: - { index: 5, kind: "OpenCurlyBrace", line: {{ *}}[[@LINE-5]], column: 8, indent: 1, spelling: "{", closing_token: 58, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 5, kind: "OpenCurlyBrace", line: {{ *}}[[@LINE-5]], column: 8, indent: 1, spelling: "{", closing_token: 60, has_leading_space: true }
|
||||
// 8 and 9 trigger special behavior in APInt when mishandling signed versus
|
||||
// unsigned, so we pay extra attention to those.
|
||||
var ints: array(i32, 6) = (
|
||||
@@ -32,7 +32,7 @@ fn F() {
|
||||
// CHECK:STDOUT: - { index: 13, kind: "IntLiteral", line: {{ *}}[[@LINE-8]], column: 24, indent: 3, spelling: "6", value: "6", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 14, kind: "CloseParen", line: {{ *}}[[@LINE-9]], column: 25, indent: 3, spelling: ")", opening_token: 10 }
|
||||
// CHECK:STDOUT: - { index: 15, kind: "Equal", line: {{ *}}[[@LINE-10]], column: 27, indent: 3, spelling: "=", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 16, kind: "OpenParen", line: {{ *}}[[@LINE-11]], column: 29, indent: 3, spelling: "(", closing_token: 29, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 16, kind: "OpenParen", line: {{ *}}[[@LINE-11]], column: 29, indent: 3, spelling: "(", closing_token: 31, has_leading_space: true }
|
||||
8,
|
||||
// CHECK:STDOUT: - { index: 17, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "8", value: "8", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 18, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 6, indent: 5, spelling: "," }
|
||||
@@ -45,66 +45,81 @@ fn F() {
|
||||
0b1000,
|
||||
// CHECK:STDOUT: - { index: 23, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "0b1000", value: "8", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 24, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: "," }
|
||||
0o10,
|
||||
// CHECK:STDOUT: - { index: 25, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "0o10", value: "8", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 26, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 9, indent: 5, spelling: "," }
|
||||
39999999999999999993,
|
||||
// CHECK:STDOUT: - { index: 25, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "39999999999999999993", value: "39999999999999999993", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 26, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 25, indent: 5, spelling: "," }
|
||||
// CHECK:STDOUT: - { index: 27, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "39999999999999999993", value: "39999999999999999993", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 28, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 25, indent: 5, spelling: "," }
|
||||
12345678901234567890123456789012345678901234567890123456789,
|
||||
// CHECK:STDOUT: - { index: 27, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "12345678901234567890123456789012345678901234567890123456789", value: "12345678901234567890123456789012345678901234567890123456789", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 28, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 64, indent: 5, spelling: "," }
|
||||
// CHECK:STDOUT: - { index: 29, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "12345678901234567890123456789012345678901234567890123456789", value: "12345678901234567890123456789012345678901234567890123456789", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 30, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 64, indent: 5, spelling: "," }
|
||||
);
|
||||
// CHECK:STDOUT: - { index: 29, kind: "CloseParen", line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: ")", opening_token: 16, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 30, kind: "Semi", line: {{ *}}[[@LINE-2]], column: 4, indent: 3, spelling: ";" }
|
||||
// CHECK:STDOUT: - { index: 31, kind: "CloseParen", line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: ")", opening_token: 16, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 32, kind: "Semi", line: {{ *}}[[@LINE-2]], column: 4, indent: 3, spelling: ";" }
|
||||
var floats: array(f64, 7) = (
|
||||
// CHECK:STDOUT: - { index: 31, kind: "Var", line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: "var", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 32, kind: "Identifier", line: {{ *}}[[@LINE-2]], column: 7, indent: 3, spelling: "floats", identifier: 2, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 33, kind: "Colon", line: {{ *}}[[@LINE-3]], column: 13, indent: 3, spelling: ":" }
|
||||
// CHECK:STDOUT: - { index: 34, kind: "Array", line: {{ *}}[[@LINE-4]], column: 15, indent: 3, spelling: "array", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 35, kind: "OpenParen", line: {{ *}}[[@LINE-5]], column: 20, indent: 3, spelling: "(", closing_token: 39 }
|
||||
// CHECK:STDOUT: - { index: 36, kind: "FloatTypeLiteral", line: {{ *}}[[@LINE-6]], column: 21, indent: 3, spelling: "f64" }
|
||||
// CHECK:STDOUT: - { index: 37, kind: "Comma", line: {{ *}}[[@LINE-7]], column: 24, indent: 3, spelling: "," }
|
||||
// CHECK:STDOUT: - { index: 38, kind: "IntLiteral", line: {{ *}}[[@LINE-8]], column: 26, indent: 3, spelling: "7", value: "7", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 39, kind: "CloseParen", line: {{ *}}[[@LINE-9]], column: 27, indent: 3, spelling: ")", opening_token: 35 }
|
||||
// CHECK:STDOUT: - { index: 40, kind: "Equal", line: {{ *}}[[@LINE-10]], column: 29, indent: 3, spelling: "=", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 41, kind: "OpenParen", line: {{ *}}[[@LINE-11]], column: 31, indent: 3, spelling: "(", closing_token: 56, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 33, kind: "Var", line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: "var", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 34, kind: "Identifier", line: {{ *}}[[@LINE-2]], column: 7, indent: 3, spelling: "floats", identifier: 2, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 35, kind: "Colon", line: {{ *}}[[@LINE-3]], column: 13, indent: 3, spelling: ":" }
|
||||
// CHECK:STDOUT: - { index: 36, kind: "Array", line: {{ *}}[[@LINE-4]], column: 15, indent: 3, spelling: "array", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 37, kind: "OpenParen", line: {{ *}}[[@LINE-5]], column: 20, indent: 3, spelling: "(", closing_token: 41 }
|
||||
// CHECK:STDOUT: - { index: 38, kind: "FloatTypeLiteral", line: {{ *}}[[@LINE-6]], column: 21, indent: 3, spelling: "f64" }
|
||||
// CHECK:STDOUT: - { index: 39, kind: "Comma", line: {{ *}}[[@LINE-7]], column: 24, indent: 3, spelling: "," }
|
||||
// CHECK:STDOUT: - { index: 40, kind: "IntLiteral", line: {{ *}}[[@LINE-8]], column: 26, indent: 3, spelling: "7", value: "7", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 41, kind: "CloseParen", line: {{ *}}[[@LINE-9]], column: 27, indent: 3, spelling: ")", opening_token: 37 }
|
||||
// CHECK:STDOUT: - { index: 42, kind: "Equal", line: {{ *}}[[@LINE-10]], column: 29, indent: 3, spelling: "=", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 43, kind: "OpenParen", line: {{ *}}[[@LINE-11]], column: 31, indent: 3, spelling: "(", closing_token: 58, has_leading_space: true }
|
||||
0.9,
|
||||
// CHECK:STDOUT: - { index: 42, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "0.9", value: "9*10^-1", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 43, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 8, indent: 5, spelling: "," }
|
||||
8.0,
|
||||
// CHECK:STDOUT: - { index: 44, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "8.0", value: "80*10^-1", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 44, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "0.9", value: "9*10^-1", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 45, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 8, indent: 5, spelling: "," }
|
||||
8.0,
|
||||
// CHECK:STDOUT: - { index: 46, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "8.0", value: "80*10^-1", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 47, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 8, indent: 5, spelling: "," }
|
||||
80.0,
|
||||
// CHECK:STDOUT: - { index: 46, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "80.0", value: "800*10^-1", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 47, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 9, indent: 5, spelling: "," }
|
||||
// CHECK:STDOUT: - { index: 48, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "80.0", value: "800*10^-1", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 49, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 9, indent: 5, spelling: "," }
|
||||
1.0e7,
|
||||
// CHECK:STDOUT: - { index: 48, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "1.0e7", value: "10*10^6", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 49, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: "," }
|
||||
1.0e8,
|
||||
// CHECK:STDOUT: - { index: 50, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "1.0e8", value: "10*10^7", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 50, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "1.0e7", value: "10*10^6", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 51, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: "," }
|
||||
1.0e8,
|
||||
// CHECK:STDOUT: - { index: 52, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "1.0e8", value: "10*10^7", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 53, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: "," }
|
||||
1.0e-8,
|
||||
// CHECK:STDOUT: - { index: 52, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "1.0e-8", value: "10*10^-9", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 53, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: "," }
|
||||
// CHECK:STDOUT: - { index: 54, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "1.0e-8", value: "10*10^-9", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 55, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: "," }
|
||||
39999999999999999993.0e39999999999999999993,
|
||||
// CHECK:STDOUT: - { index: 54, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "39999999999999999993.0e39999999999999999993", value: "399999999999999999930*10^39999999999999999992", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 55, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 48, indent: 5, spelling: "," }
|
||||
// CHECK:STDOUT: - { index: 56, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: "39999999999999999993.0e39999999999999999993", value: "399999999999999999930*10^39999999999999999992", has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 57, kind: "Comma", line: {{ *}}[[@LINE-2]], column: 48, indent: 5, spelling: "," }
|
||||
);
|
||||
// CHECK:STDOUT: - { index: 56, kind: "CloseParen", line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: ")", opening_token: 41, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 57, kind: "Semi", line: {{ *}}[[@LINE-2]], column: 4, indent: 3, spelling: ";" }
|
||||
// CHECK:STDOUT: - { index: 58, kind: "CloseParen", line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: ")", opening_token: 43, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 59, kind: "Semi", line: {{ *}}[[@LINE-2]], column: 4, indent: 3, spelling: ";" }
|
||||
}
|
||||
// CHECK:STDOUT: - { index: 58, kind: "CloseCurlyBrace", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "}", opening_token: 5, has_leading_space: true }
|
||||
// CHECK:STDOUT: - { index: 60, kind: "CloseCurlyBrace", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "}", opening_token: 5, has_leading_space: true }
|
||||
|
||||
|
||||
// --- fail_binary_real.carbon
|
||||
// CHECK:STDOUT: - filename: fail_binary_real.carbon
|
||||
// CHECK:STDOUT: tokens:
|
||||
|
||||
// CHECK:STDERR: fail_binary_real.carbon:[[@LINE+4]]:4: error: binary real number literals are not supported [BinaryRealLiteral]
|
||||
// CHECK:STDERR: fail_binary_real.carbon:[[@LINE+4]]:4: error: binary real number literals are not supported [InvalidRealLiteralRadix]
|
||||
// CHECK:STDERR: 0b1.0
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
0b1.0
|
||||
// CHECK:STDOUT: - { index: 1, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "0b1.0", value: "2*2^-1", has_leading_space: true }
|
||||
|
||||
// --- fail_octal_real.carbon
|
||||
// CHECK:STDOUT: - filename: fail_octal_real.carbon
|
||||
// CHECK:STDOUT: tokens:
|
||||
|
||||
// CHECK:STDERR: fail_octal_real.carbon:[[@LINE+4]]:4: error: octal real number literals are not supported [InvalidRealLiteralRadix]
|
||||
// CHECK:STDERR: 0o1.0
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
0o1.0
|
||||
// CHECK:STDOUT: - { index: 1, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "0o1.0", value: "8*2^-3", has_leading_space: true }
|
||||
|
||||
|
||||
// --- fail_wrong_real_exponent.carbon
|
||||
// CHECK:STDOUT: - filename: fail_wrong_real_exponent.carbon
|
||||
// CHECK:STDOUT: tokens:
|
||||
|
||||
Reference in New Issue
Block a user