Indicate the number of float tokens in the first token

This commit is contained in:
Jonas Schievink 2022-05-05 16:06:44 +02:00
parent 34dc8e9383
commit 2fe38d3b63
16 changed files with 194 additions and 44 deletions

View file

@ -39,6 +39,7 @@ mod generic_params;
mod types;
use crate::{
grammar::expressions::FLOAT_LITERAL_FIRST,
parser::{CompletedMarker, Marker, Parser},
SyntaxKind::{self, *},
TokenSet, T,
@ -318,9 +319,15 @@ fn name_ref(p: &mut Parser) {
}
fn name_ref_or_index(p: &mut Parser) {
assert!(p.at(IDENT) || p.at(INT_NUMBER) || p.at(FLOAT_NUMBER_PART));
assert!(
p.at(IDENT) || p.at(INT_NUMBER) || p.at(FLOAT_NUMBER_PART) || p.at_ts(FLOAT_LITERAL_FIRST)
);
let m = p.start();
p.bump_any();
if p.at_ts(FLOAT_LITERAL_FIRST) {
p.bump_remap(FLOAT_NUMBER_PART);
} else {
p.bump_any();
}
m.complete(p, NAME_REF);
}

View file

@ -3,7 +3,7 @@ mod atom;
use super::*;
pub(crate) use self::atom::{block_expr, match_arm_list};
pub(super) use self::atom::{float_literal, literal, LITERAL_FIRST};
pub(super) use self::atom::{float_literal, literal, FLOAT_LITERAL_FIRST, LITERAL_FIRST};
#[derive(PartialEq, Eq)]
pub(super) enum Semicolon {
@ -452,6 +452,9 @@ fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
// fn foo() {
// x.foo();
// y.bar::<T>(1, 2,);
//
// 0e0.sin();
// 0e0f32.sin();
// }
fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
@ -477,7 +480,7 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
assert!(p.at(T![.]));
let m = lhs.precede(p);
p.bump(T![.]);
if p.at(IDENT) || p.at(INT_NUMBER) || p.at(FLOAT_NUMBER_PART) {
if p.at(IDENT) || p.at(INT_NUMBER) || p.at(FLOAT_NUMBER_PART) || p.at_ts(FLOAT_LITERAL_FIRST) {
name_ref_or_index(p);
} else {
p.error("expected field name or number");

View file

@ -17,19 +17,24 @@ pub(crate) const LITERAL_FIRST: TokenSet = TokenSet::new(&[
T![true],
T![false],
INT_NUMBER,
FLOAT_NUMBER_PART,
FLOAT_NUMBER_START_0,
FLOAT_NUMBER_START_1,
FLOAT_NUMBER_START_2,
BYTE,
CHAR,
STRING,
BYTE_STRING,
]);
pub(crate) const FLOAT_LITERAL_FIRST: TokenSet =
TokenSet::new(&[FLOAT_NUMBER_START_0, FLOAT_NUMBER_START_1, FLOAT_NUMBER_START_2]);
pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
if !p.at_ts(LITERAL_FIRST) {
return None;
}
let m = p.start();
if p.at(FLOAT_NUMBER_PART) {
if p.at_ts(FLOAT_LITERAL_FIRST) {
float_literal(p);
} else {
// Everything else is just one token.
@ -38,15 +43,30 @@ pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
Some(m.complete(p, LITERAL))
}
// test float_literal
// fn f() {
// 0.0;
// 1.;
// 0e0;
// 0e0f32;
// 1.23f64;
// }
pub(crate) fn float_literal(p: &mut Parser) {
// Floats can be up to 3 tokens: 2 `FLOAT_NUMBER_PART`s separated by 1 `DOT`
// Floats can be up to 3 tokens. The first token indicates how many there are.
// We remap the first token to `FLOAT_NUMBER_PART` so that no subsequent code has to deal with
// this awful, awful hack.
let f = p.start();
p.bump(FLOAT_NUMBER_PART);
if p.at(DOT) {
if p.at(FLOAT_NUMBER_START_0) {
p.bump_remap(FLOAT_NUMBER_PART);
} else if p.at(FLOAT_NUMBER_START_1) {
p.bump_remap(FLOAT_NUMBER_PART);
p.bump(DOT);
if p.at(FLOAT_NUMBER_PART) {
p.bump(FLOAT_NUMBER_PART);
}
} else if p.at(FLOAT_NUMBER_START_2) {
p.bump_remap(FLOAT_NUMBER_PART);
p.bump(DOT);
p.bump(FLOAT_NUMBER_PART);
} else {
unreachable!();
}
f.complete(p, FLOAT_LITERAL);
}

View file

@ -457,7 +457,7 @@ pub(crate) fn token_tree(p: &mut Parser) {
return;
}
T![')'] | T![']'] => p.err_and_bump("unmatched brace"),
FLOAT_NUMBER_PART => {
FLOAT_NUMBER_START_0 | FLOAT_NUMBER_START_1 | FLOAT_NUMBER_START_2 => {
float_literal(p);
}
_ => p.bump_any(),

View file

@ -240,11 +240,16 @@ impl<'a> Converter<'a> {
// In order to correctly parse nested tuple accesses like `tup.0.0`, where the `0.0`
// is lexed as a float, we split floats that contain a `.` into 3 tokens.
// To ensure that later stages can always reconstruct the token correctly, the first
// token in the sequence indicates the number of following tokens that are part of
// the float literal.
if let Some((before, after)) = token_text.split_once('.') {
let err = if err.is_empty() { None } else { Some(err) };
if !before.is_empty() {
self.push(FLOAT_NUMBER_PART, before.len(), None);
}
assert!(!before.is_empty());
let tok =
if after.is_empty() { FLOAT_NUMBER_START_1 } else { FLOAT_NUMBER_START_2 };
self.push(tok, before.len(), None);
self.push(DOT, 1, None);
if !after.is_empty() {
self.push(FLOAT_NUMBER_PART, after.len(), err);
@ -252,7 +257,7 @@ impl<'a> Converter<'a> {
return;
}
FLOAT_NUMBER_PART
FLOAT_NUMBER_START_0
}
rustc_lexer::LiteralKind::Char { terminated } => {
if !terminated {

File diff suppressed because one or more lines are too long