modify number_token to produce partial lexing results (#2986)

This commit is contained in:
Mark Thom
2025-07-05 00:58:28 -07:00
parent 8e01eea440
commit ce56b5ed6b
2 changed files with 144 additions and 210 deletions

View File

@@ -911,27 +911,16 @@ impl MachineState {
use crate::parser::lexer::*; use crate::parser::lexer::*;
let nx = self.store(self.deref(self.registers[2])); let nx = self.store(self.deref(self.registers[2]));
let add_dot = !string.ends_with('.') || string.ends_with("'."); let iter = std::io::Cursor::new(string);
let cursor = std::io::Cursor::new(string);
let iter = std::io::Read::chain(cursor, {
let mut dot_buf: [u8; '.'.len_utf8()] = [0u8];
if add_dot && !string.ends_with('\'') {
'.'.encode_utf8(&mut dot_buf);
}
std::io::Cursor::new(dot_buf)
});
let mut lexer = Lexer::new(CharReader::new(iter), self); let mut lexer = Lexer::new(CharReader::new(iter), self);
let mut tokens = vec![]; let mut tokens = vec![];
match lexer.next_token() { match lexer.next_number_token() {
Ok(token @ Token::Literal(Literal::Atom(atom!("-")) | Literal::Char('-'))) => { Ok(token @ Token::Literal(Literal::Atom(atom!("-")) | Literal::Char('-'))) => {
tokens.push(token); tokens.push(token);
if let Ok(token) = lexer.next_token() { if let Ok(token) = lexer.next_number_token() {
tokens.push(token); tokens.push(token);
} }
} }

View File

@@ -1,3 +1,5 @@
use crate::arena::F64Ptr;
use crate::arena::TypedArenaPtr;
use crate::atom_table::*; use crate::atom_table::*;
pub use crate::machine::machine_state::*; pub use crate::machine::machine_state::*;
use crate::parser::ast::*; use crate::parser::ast::*;
@@ -49,6 +51,55 @@ impl Token {
} }
} }
#[derive(Debug)]
enum Number {
BigInt(TypedArenaPtr<Integer>),
Fixnum(Fixnum),
Float(F64Ptr),
}
impl Number {
#[inline]
fn to_literal(self) -> Literal {
match self {
Number::BigInt(ibig) => Literal::Integer(ibig),
Number::Fixnum(fixnum) => Literal::Fixnum(fixnum),
Number::Float(f) => Literal::Float(f.as_offset()),
}
}
}
#[derive(Debug)]
enum NumberToken {
Number(Number),
Partial(String),
}
impl NumberToken {
#[inline]
fn to_token(self) -> Option<Token> {
match self {
NumberToken::Number(number) => Some(Token::Literal(number.to_literal())),
NumberToken::Partial(_) => None,
}
}
}
macro_rules! try_nt {
($token:expr, $e: expr) => {{
match $e {
Ok(c) => c,
Err(e) => {
return if e.is_unexpected_eof() {
Ok(NumberToken::Partial($token))
} else {
Err(e)
}
}
}
}};
}
pub struct Lexer<'a, R> { pub struct Lexer<'a, R> {
pub(crate) reader: R, pub(crate) reader: R,
pub(crate) machine_st: &'a mut MachineState, pub(crate) machine_st: &'a mut MachineState,
@@ -443,7 +494,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
fn hexadecimal_constant(&mut self, start: char) -> Result<Token, ParserError> { fn hexadecimal_constant(&mut self, start: char) -> Result<NumberToken, ParserError> {
self.skip_char(start); self.skip_char(start);
let mut c = self.lookahead_char()?; let mut c = self.lookahead_char()?;
@@ -454,31 +505,21 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if hexadecimal_digit_char!(c) { if hexadecimal_digit_char!(c) {
self.skip_char(c); self.skip_char(c);
token.push(c); token.push(c);
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
} else { } else {
break; break;
} }
} }
i64::from_str_radix(&token, 16) self.parse_integer_by_radix(&token, 16)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(NumberToken::Number)
.or_else(|_| {
Integer::from_str_radix(&token, 16)
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else { } else {
self.return_char(start); self.return_char(start);
Err(ParserError::ParseBigInt(self.line_num, self.col_num)) Err(ParserError::ParseBigInt(self.line_num, self.col_num))
} }
} }
fn octal_constant(&mut self, start: char) -> Result<Token, ParserError> { fn octal_constant(&mut self, start: char) -> Result<NumberToken, ParserError> {
self.skip_char(start); self.skip_char(start);
let mut c = self.lookahead_char()?; let mut c = self.lookahead_char()?;
@@ -489,31 +530,21 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if octal_digit_char!(c) { if octal_digit_char!(c) {
self.skip_char(c); self.skip_char(c);
token.push(c); token.push(c);
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
} else { } else {
break; break;
} }
} }
i64::from_str_radix(&token, 8) self.parse_integer_by_radix(&token, 8)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(NumberToken::Number)
.or_else(|_| {
Integer::from_str_radix(&token, 8)
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else { } else {
self.return_char(start); self.return_char(start);
Err(ParserError::ParseBigInt(self.line_num, self.col_num)) Err(ParserError::ParseBigInt(self.line_num, self.col_num))
} }
} }
fn binary_constant(&mut self, start: char) -> Result<Token, ParserError> { fn binary_constant(&mut self, start: char) -> Result<NumberToken, ParserError> {
self.skip_char(start); self.skip_char(start);
let mut c = self.lookahead_char()?; let mut c = self.lookahead_char()?;
@@ -524,24 +555,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if binary_digit_char!(c) { if binary_digit_char!(c) {
self.skip_char(c); self.skip_char(c);
token.push(c); token.push(c);
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
} else { } else {
break; break;
} }
} }
i64::from_str_radix(&token, 2) self.parse_integer_by_radix(&token, 2)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(NumberToken::Number)
.or_else(|_| {
Integer::from_str_radix(&token, 2)
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else { } else {
self.return_char(start); self.return_char(start);
Err(ParserError::ParseBigInt(self.line_num, self.col_num)) Err(ParserError::ParseBigInt(self.line_num, self.col_num))
@@ -634,15 +655,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
fn vacate_with_float(&mut self, mut token: String) -> Result<Token, ParserError> { fn vacate_with_float(&mut self, mut token: String) -> Result<Number, ParserError> {
self.return_char(token.pop().unwrap()); self.return_char(token.pop().unwrap());
let n = parse_float_lossy(&token)?; let n = parse_float_lossy(&token)?;
Ok(Number::Float(float_alloc!(n, self.machine_st.arena)))
Ok(Token::Literal(Literal::from(float_alloc!(
n,
self.machine_st.arena
))))
} }
fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> { fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> {
@@ -663,17 +679,43 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
pub fn number_token(&mut self, leading_c: char) -> Result<Token, ParserError> { fn parse_integer_by_radix(
&mut self,
token: &String,
radix: u32,
) -> Result<Number, ParserError> {
i64::from_str_radix(&token, radix)
.map(|n| {
Fixnum::build_with_checked(n)
.map(Number::Fixnum)
.unwrap_or_else(|_| {
Number::BigInt(arena_alloc!(Integer::from(n), &mut self.machine_st.arena))
})
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| Number::BigInt(arena_alloc!(n, &mut self.machine_st.arena)))
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
}
#[inline]
fn parse_integer(&mut self, token: &String) -> Result<Number, ParserError> {
self.parse_integer_by_radix(token, 10)
}
fn number_token(&mut self, leading_c: char) -> Result<NumberToken, ParserError> {
let mut token = String::with_capacity(16); let mut token = String::with_capacity(16);
self.skip_char(leading_c); self.skip_char(leading_c);
token.push(leading_c); token.push(leading_c);
let mut c = self.skip_underscore_in_number()?; let mut c = try_nt!(token, self.skip_underscore_in_number());
while decimal_digit_char!(c) { while decimal_digit_char!(c) {
token.push(c); token.push(c);
self.skip_char(c); self.skip_char(c);
c = self.skip_underscore_in_number()?; c = try_nt!(token, self.skip_underscore_in_number());
} }
if decimal_point_char!(c) { if decimal_point_char!(c) {
@@ -681,31 +723,17 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if self.reader.peek_char().is_none() { if self.reader.peek_char().is_none() {
self.return_char('.'); self.return_char('.');
self.parse_integer(&token).map(NumberToken::Number)
token
.parse::<i64>()
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else if decimal_digit_char!(self.lookahead_char()?) { } else if decimal_digit_char!(self.lookahead_char()?) {
token.push('.'); token.push('.');
token.push(self.read_char()?); token.push(self.read_char()?);
let mut c = self.lookahead_char()?; let mut c = try_nt!(token, self.lookahead_char());
while decimal_digit_char!(c) { while decimal_digit_char!(c) {
token.push(c); token.push(c);
self.skip_char(c); self.skip_char(c);
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
} }
if exponent_char!(c) { if exponent_char!(c) {
@@ -713,12 +741,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token.push(c); token.push(c);
let c = match self.lookahead_char() { let c = match self.lookahead_char() {
Err(_) => return self.vacate_with_float(token), Err(_) => return self.vacate_with_float(token).map(NumberToken::Number),
Ok(c) => c, Ok(c) => c,
}; };
if !sign_char!(c) && !decimal_digit_char!(c) { if !sign_char!(c) && !decimal_digit_char!(c) {
return self.vacate_with_float(token); return self.vacate_with_float(token).map(NumberToken::Number);
} }
if sign_char!(c) { if sign_char!(c) {
@@ -728,14 +756,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
let c = match self.lookahead_char() { let c = match self.lookahead_char() {
Err(_) => { Err(_) => {
self.return_char(token.pop().unwrap()); self.return_char(token.pop().unwrap());
return self.vacate_with_float(token); return self.vacate_with_float(token).map(NumberToken::Number);
} }
Ok(c) => c, Ok(c) => c,
}; };
if !decimal_digit_char!(c) { if !decimal_digit_char!(c) {
self.return_char(token.pop().unwrap()); self.return_char(token.pop().unwrap());
return self.vacate_with_float(token); return self.vacate_with_float(token).map(NumberToken::Number);
} }
} }
@@ -746,7 +774,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token.push(c); token.push(c);
loop { loop {
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
if decimal_digit_char!(c) { if decimal_digit_char!(c) {
self.skip_char(c); self.skip_char(c);
@@ -757,60 +785,29 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
let n = parse_float_lossy(&token)?; let n = parse_float_lossy(&token)?;
Ok(Token::Literal(Literal::from(float_alloc!( Ok(NumberToken::Number(Number::Float(float_alloc!(
n, n,
self.machine_st.arena self.machine_st.arena
)))) ))))
} else { } else {
return self.vacate_with_float(token); return self.vacate_with_float(token).map(NumberToken::Number);
} }
} else { } else {
let n = parse_float_lossy(&token)?; let n = parse_float_lossy(&token)?;
Ok(Token::Literal(Literal::from(float_alloc!( Ok(NumberToken::Number(Number::Float(float_alloc!(
n, n,
self.machine_st.arena self.machine_st.arena
)))) ))))
} }
} else { } else {
self.return_char('.'); self.return_char('.');
self.parse_integer(&token).map(NumberToken::Number)
token
.parse::<i64>()
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} }
} else if token.starts_with('0') && token.len() == 1 { } else if token.starts_with('0') && token.len() == 1 {
if c == 'x' { if c == 'x' {
self.hexadecimal_constant(c).or_else(|e| { self.hexadecimal_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e { if let ParserError::ParseBigInt(..) = e {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| {
ParserError::ParseBigInt(self.line_num, self.col_num)
})
})
} else { } else {
Err(e) Err(e)
} }
@@ -818,24 +815,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} else if c == 'o' { } else if c == 'o' {
self.octal_constant(c).or_else(|e| { self.octal_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e { if let ParserError::ParseBigInt(..) = e {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| {
ParserError::ParseBigInt(self.line_num, self.col_num)
})
})
} else { } else {
Err(e) Err(e)
} }
@@ -843,24 +823,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} else if c == 'b' { } else if c == 'b' {
self.binary_constant(c).or_else(|e| { self.binary_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e { if let ParserError::ParseBigInt(..) = e {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| {
ParserError::ParseBigInt(self.line_num, self.col_num)
})
})
} else { } else {
Err(e) Err(e)
} }
@@ -877,14 +840,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
self.skip_char(c); self.skip_char(c);
self.return_char('\''); self.return_char('\'');
return Ok(Token::Literal(Literal::Fixnum(Fixnum::build_with(0)))); return Ok(NumberToken::Number(Number::Fixnum(Fixnum::build_with(0))));
} else { } else {
self.return_char('\\'); self.return_char('\\');
} }
} }
self.get_single_quoted_char() self.get_single_quoted_char()
.map(|c| Token::Literal(Literal::Fixnum(Fixnum::build_with(c as i64)))) .map(|c| NumberToken::Number(Number::Fixnum(Fixnum::build_with(c as i64))))
.or_else(|err| { .or_else(|err| {
match err { match err {
ParserError::UnexpectedChar('\'', ..) => {} ParserError::UnexpectedChar('\'', ..) => {}
@@ -892,57 +855,13 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
self.return_char(c); self.return_char(c);
self.parse_integer(&token).map(NumberToken::Number)
token
.parse::<i64>()
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| {
ParserError::ParseBigInt(self.line_num, self.col_num)
})
})
}) })
} else { } else {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} }
} else { } else {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} }
} }
@@ -1001,6 +920,29 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
pub fn next_number_token(&mut self) -> Result<Token, ParserError> {
self.scan_for_layout()?;
let c = self.lookahead_char()?;
if !decimal_digit_char!(c) {
return self.name_token(c);
}
match self.number_token(c) {
Ok(NumberToken::Partial(token_string)) => match self.parse_integer(&token_string) {
Ok(n) => Ok(Token::Literal(n.to_literal())),
Err(_) => {
let n = parse_float_lossy(&token_string)?;
Ok(Token::Literal(Literal::Float(
float_alloc!(n, self.machine_st.arena).as_offset(),
)))
}
},
Ok(NumberToken::Number(n)) => return Ok(Token::Literal(n.to_literal())),
Err(e) => return Err(e),
}
}
pub fn next_token(&mut self) -> Result<Token, ParserError> { pub fn next_token(&mut self) -> Result<Token, ParserError> {
let layout_inserted = self.scan_for_layout()?; let layout_inserted = self.scan_for_layout()?;
let cr = self.lookahead_char(); let cr = self.lookahead_char();
@@ -1053,7 +995,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
if decimal_digit_char!(c) { if decimal_digit_char!(c) {
return self.number_token(c); return self.number_token(c).and_then(|nt| match nt.to_token() {
Some(token) => Ok(token),
None => Err(ParserError::unexpected_eof()),
});
} }
if c == ']' { if c == ']' {