From d91d983c742c922fa39f09c4679c6886267444fa Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 23 Sep 2020 22:48:28 +0800 Subject: [PATCH] Enable dots on numbers to parse as method calls. --- src/token.rs | 33 +++++++++++++++++++++++++++++++-- tests/number_literals.rs | 12 +++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/token.rs b/src/token.rs index ad0ef340..6245310a 100644 --- a/src/token.rs +++ b/src/token.rs @@ -731,6 +731,7 @@ pub struct TokenizeState { /// /// This trait is volatile and may change. pub trait InputStream { + fn unread(&mut self, ch: char); /// Get the next character fn get_next(&mut self) -> Option; /// Peek the next character @@ -1014,8 +1015,21 @@ fn get_next_token_inner( } #[cfg(not(feature = "no_float"))] '.' => { - result.push(next_char); - eat_next(stream, pos); + stream.get_next().unwrap(); + + // Check if followed by digits (or _) + match stream.peek_next().unwrap_or('\0') { + '0'..='9' | '_' => { + result.push(next_char); + pos.advance() + } + _ => { + // Not a floating-point number + stream.unread(next_char); + break; + } + } + while let Some(next_char_in_float) = stream.peek_next() { match next_char_in_float { '0'..='9' | '_' => { @@ -1499,6 +1513,8 @@ fn is_id_continue(x: char) -> bool { /// A type that implements the `InputStream` trait. /// Multiple character streams are jointed together to form one single stream. pub struct MultiInputsStream<'a> { + /// Buffered character, if any. + buf: Option, /// The input character streams. streams: StaticVec>>, /// The current stream index. @@ -1506,8 +1522,16 @@ pub struct MultiInputsStream<'a> { } impl InputStream for MultiInputsStream<'_> { + /// Buffer a character. + fn unread(&mut self, ch: char) { + self.buf = Some(ch); + } /// Get the next character fn get_next(&mut self) -> Option { + if let Some(ch) = self.buf.take() { + return Some(ch); + } + loop { if self.index >= self.streams.len() { // No more streams @@ -1523,6 +1547,10 @@ impl InputStream for MultiInputsStream<'_> { } /// Peek the next character fn peek_next(&mut self) -> Option { + if let Some(ch) = self.buf { + return Some(ch); + } + loop { if self.index >= self.streams.len() { // No more streams @@ -1673,6 +1701,7 @@ pub fn lex<'a, 'e>( }, pos: Position::new(1, 0), stream: MultiInputsStream { + buf: None, streams: input.iter().map(|s| s.chars().peekable()).collect(), index: 0, }, diff --git a/tests/number_literals.rs b/tests/number_literals.rs index ce19b52d..2e7b6b01 100644 --- a/tests/number_literals.rs +++ b/tests/number_literals.rs @@ -4,7 +4,17 @@ use rhai::{Engine, EvalAltResult, INT}; fn test_number_literal() -> Result<(), Box> { let engine = Engine::new(); - assert_eq!(engine.eval::("65")?, 65); + assert_eq!(engine.eval::("42")?, 42); + + #[cfg(not(feature = "no_object"))] + assert_eq!( + engine.eval::("42.type_of()")?, + if cfg!(feature = "only_i32") { + "i32" + } else { + "i64" + } + ); Ok(()) }