diff --git a/prism/prism.c b/prism/prism.c index f0a4df7e6b..4bac4d8c76 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -6315,7 +6315,7 @@ pm_strspn_hexadecimal_number_validate(pm_parser_t *parser, const uint8_t *string } static pm_token_type_t -lex_optional_float_suffix(pm_parser_t *parser) { +lex_optional_float_suffix(pm_parser_t *parser, bool* seen_e) { pm_token_type_t type = PM_TOKEN_INTEGER; // Here we're going to attempt to parse the optional decimal portion of a @@ -6336,6 +6336,7 @@ lex_optional_float_suffix(pm_parser_t *parser) { // float. If it's not there, it's okay and we'll just continue on. if (match(parser, 'e') || match(parser, 'E')) { (void) (match(parser, '+') || match(parser, '-')); + *seen_e = true; if (pm_char_is_decimal_digit(*parser->current.end)) { parser->current.end++; @@ -6351,8 +6352,9 @@ lex_optional_float_suffix(pm_parser_t *parser) { } static pm_token_type_t -lex_numeric_prefix(pm_parser_t *parser) { +lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { pm_token_type_t type = PM_TOKEN_INTEGER; + *seen_e = false; if (peek_offset(parser, -1) == '0') { switch (*parser->current.end) { @@ -6423,14 +6425,14 @@ lex_numeric_prefix(pm_parser_t *parser) { // 0.xxx is a float case '.': { - type = lex_optional_float_suffix(parser); + type = lex_optional_float_suffix(parser, seen_e); break; } // 0exxx is a float case 'e': case 'E': { - type = lex_optional_float_suffix(parser); + type = lex_optional_float_suffix(parser, seen_e); break; } } @@ -6440,7 +6442,7 @@ lex_numeric_prefix(pm_parser_t *parser) { parser->current.end += pm_strspn_decimal_number_validate(parser, parser->current.end); // Afterward, we'll lex as far as we can into an optional float suffix. - type = lex_optional_float_suffix(parser); + type = lex_optional_float_suffix(parser, seen_e); } return type; @@ -6452,7 +6454,8 @@ lex_numeric(pm_parser_t *parser) { parser->integer_base = PM_INTEGER_BASE_FLAGS_DECIMAL; if (parser->current.end < parser->end) { - type = lex_numeric_prefix(parser); + bool seen_e = false; + type = lex_numeric_prefix(parser, &seen_e); const uint8_t *end = parser->current.end; pm_token_type_t suffix_type = type; @@ -6468,7 +6471,7 @@ lex_numeric(pm_parser_t *parser) { suffix_type = PM_TOKEN_INTEGER_IMAGINARY; } } else { - if (match(parser, 'r')) { + if (!seen_e && match(parser, 'r')) { suffix_type = PM_TOKEN_FLOAT_RATIONAL; if (match(parser, 'i')) { diff --git a/test/prism/fixtures/numbers.txt b/test/prism/fixtures/numbers.txt index 3c8bf07805..47f20dcb42 100644 --- a/test/prism/fixtures/numbers.txt +++ b/test/prism/fixtures/numbers.txt @@ -44,10 +44,14 @@ 1ri +1.2r + 1.2ri -1ri +-1.2r + -1.2ri 0o1r diff --git a/test/prism/snapshots/numbers.txt b/test/prism/snapshots/numbers.txt index ca31480f67..c27f2a6354 100644 --- a/test/prism/snapshots/numbers.txt +++ b/test/prism/snapshots/numbers.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(63,5)) +@ ProgramNode (location: (1,0)-(67,5)) ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(63,5)) - └── body: (length: 32) + @ StatementsNode (location: (1,0)-(67,5)) + └── body: (length: 34) ├── @ IntegerNode (location: (1,0)-(1,1)) │ └── flags: decimal ├── @ IntegerNode (location: (3,0)-(3,1)) @@ -56,47 +56,53 @@ │ └── numeric: │ @ IntegerNode (location: (45,0)-(45,1)) │ └── flags: decimal - ├── @ ImaginaryNode (location: (47,0)-(47,5)) + ├── @ RationalNode (location: (47,0)-(47,4)) │ └── numeric: - │ @ RationalNode (location: (47,0)-(47,4)) - │ └── numeric: - │ @ FloatNode (location: (47,0)-(47,3)) - ├── @ ImaginaryNode (location: (49,0)-(49,4)) + │ @ FloatNode (location: (47,0)-(47,3)) + ├── @ ImaginaryNode (location: (49,0)-(49,5)) │ └── numeric: - │ @ RationalNode (location: (49,0)-(49,3)) + │ @ RationalNode (location: (49,0)-(49,4)) │ └── numeric: - │ @ IntegerNode (location: (49,0)-(49,2)) + │ @ FloatNode (location: (49,0)-(49,3)) + ├── @ ImaginaryNode (location: (51,0)-(51,4)) + │ └── numeric: + │ @ RationalNode (location: (51,0)-(51,3)) + │ └── numeric: + │ @ IntegerNode (location: (51,0)-(51,2)) │ └── flags: decimal - ├── @ ImaginaryNode (location: (51,0)-(51,6)) + ├── @ RationalNode (location: (53,0)-(53,5)) │ └── numeric: - │ @ RationalNode (location: (51,0)-(51,5)) + │ @ FloatNode (location: (53,0)-(53,4)) + ├── @ ImaginaryNode (location: (55,0)-(55,6)) + │ └── numeric: + │ @ RationalNode (location: (55,0)-(55,5)) │ └── numeric: - │ @ FloatNode (location: (51,0)-(51,4)) - ├── @ RationalNode (location: (53,0)-(53,4)) + │ @ FloatNode (location: (55,0)-(55,4)) + ├── @ RationalNode (location: (57,0)-(57,4)) │ └── numeric: - │ @ IntegerNode (location: (53,0)-(53,3)) + │ @ IntegerNode (location: (57,0)-(57,3)) │ └── flags: octal - ├── @ ImaginaryNode (location: (55,0)-(55,4)) - │ └── numeric: - │ @ IntegerNode (location: (55,0)-(55,3)) - │ └── flags: octal - ├── @ ImaginaryNode (location: (57,0)-(57,5)) - │ └── numeric: - │ @ RationalNode (location: (57,0)-(57,4)) - │ └── numeric: - │ @ IntegerNode (location: (57,0)-(57,3)) - │ └── flags: octal - ├── @ RationalNode (location: (59,0)-(59,4)) + ├── @ ImaginaryNode (location: (59,0)-(59,4)) │ └── numeric: │ @ IntegerNode (location: (59,0)-(59,3)) - │ └── flags: decimal - ├── @ ImaginaryNode (location: (61,0)-(61,4)) + │ └── flags: octal + ├── @ ImaginaryNode (location: (61,0)-(61,5)) │ └── numeric: - │ @ IntegerNode (location: (61,0)-(61,3)) + │ @ RationalNode (location: (61,0)-(61,4)) + │ └── numeric: + │ @ IntegerNode (location: (61,0)-(61,3)) + │ └── flags: octal + ├── @ RationalNode (location: (63,0)-(63,4)) + │ └── numeric: + │ @ IntegerNode (location: (63,0)-(63,3)) │ └── flags: decimal - └── @ ImaginaryNode (location: (63,0)-(63,5)) + ├── @ ImaginaryNode (location: (65,0)-(65,4)) + │ └── numeric: + │ @ IntegerNode (location: (65,0)-(65,3)) + │ └── flags: decimal + └── @ ImaginaryNode (location: (67,0)-(67,5)) └── numeric: - @ RationalNode (location: (63,0)-(63,4)) + @ RationalNode (location: (67,0)-(67,4)) └── numeric: - @ IntegerNode (location: (63,0)-(63,3)) + @ IntegerNode (location: (67,0)-(67,3)) └── flags: binary