diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 66d9bfb..9522a33 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -334,15 +334,30 @@ fn parse_string(tokens: &mut Tokens) -> ParseResult { } fn parse_number(tokens: &mut Tokens) -> ParseResult { - if let Some(LocatedToken { - token: Token::Number(number), - .. - }) = tokens.next_if(&Token::Number(0)) - { - Ok(Some(ast::Expr::Value(ast::Value::Int(number.into())))) - } else { - Ok(None) - } + tokens.one_of(vec![ + |t| { + if let Some(LocatedToken { + token: Token::Int(number), + .. + }) = t.next_if(&Token::Int(0)) + { + Ok(Some(ast::Expr::Value(ast::Value::Int(number.into())))) + } else { + Ok(None) + } + }, + |t| { + if let Some(LocatedToken { + token: Token::Float(number), + .. + }) = t.next_if(&Token::Float(0.0)) + { + Ok(Some(ast::Expr::Value(ast::Value::Float(number.into())))) + } else { + Ok(None) + } + }, + ]) } fn parse_identifier(tokens: &mut Tokens) -> ParseResult { @@ -441,7 +456,7 @@ mod tests { } #[test] fn if_then() { - let program = "if !(3 < 2) { \"Hello\" }".to_string(); + let program = "if !(3.23 < 2.34) { \"Hello\" }".to_string(); let result = parse(&mut scan(program), parse_expr); insta::assert_debug_snapshot!(result); } diff --git a/src/parser/scanner.rs b/src/parser/scanner.rs index 5c10a6f..7a7ee52 100644 --- a/src/parser/scanner.rs +++ b/src/parser/scanner.rs @@ -339,11 +339,37 @@ fn lex_number(scanner: &mut Scanner, start: Pos, c: &char) -> LocatedToken { break; } } - let i = str.parse::().unwrap(); - LocatedToken { - start, - end: scanner.cursor(), - token: Token::Number(i), + if let Some(ch) = scanner.peek() + && *ch == '.' + { + scanner.pop(); + str.push('.'); + + loop { + if let Some(ch) = scanner.peek() + && !ch.is_numeric() + { + break; + } + if let Some(ch) = scanner.pop() { + str.push(*ch); + } else { + break; + } + } + let i = str.parse::().unwrap(); + LocatedToken { + start, + end: scanner.cursor(), + token: Token::Float(i), + } + } else { + let i = str.parse::().unwrap(); + LocatedToken { + start, + end: scanner.cursor(), + token: Token::Int(i), + } } } diff --git a/src/parser/snapshots/ayin__parser__parser__tests__if_then.snap b/src/parser/snapshots/ayin__parser__parser__tests__if_then.snap index 5e3477d..35bb64a 100644 --- a/src/parser/snapshots/ayin__parser__parser__tests__if_then.snap +++ b/src/parser/snapshots/ayin__parser__parser__tests__if_then.snap @@ -7,16 +7,16 @@ Ok( condition: Not( Op { lhs: Value( - Int( - 3, + Float( + 3.23, ), ), op: Compare( Lt, ), rhs: Value( - Int( - 2, + Float( + 2.34, ), ), }, diff --git a/src/parser/snapshots/ayin__parser__scanner__tests__let_number.snap b/src/parser/snapshots/ayin__parser__scanner__tests__let_number.snap index 67e7848..812ed82 100644 --- a/src/parser/snapshots/ayin__parser__scanner__tests__let_number.snap +++ b/src/parser/snapshots/ayin__parser__scanner__tests__let_number.snap @@ -8,7 +8,7 @@ expression: result "x", ), Equals, - Number( + Int( 108, ), Semicolon, diff --git a/src/parser/snapshots/ayin__parser__scanner__tests__scaffolding.snap b/src/parser/snapshots/ayin__parser__scanner__tests__scaffolding.snap index 253c9ad..f20bbb7 100644 --- a/src/parser/snapshots/ayin__parser__scanner__tests__scaffolding.snap +++ b/src/parser/snapshots/ayin__parser__scanner__tests__scaffolding.snap @@ -28,7 +28,7 @@ expression: result "x", ), Colon, - Number( + Int( 10, ), Comma, @@ -36,7 +36,7 @@ expression: result "y", ), Colon, - Number( + Int( 20, ), CloseCurly, @@ -93,15 +93,15 @@ expression: result "clear", ), OpenParen, - Number( + Int( 0, ), Comma, - Number( + Int( 0, ), Comma, - Number( + Int( 0, ), CloseParen, diff --git a/src/parser/types.rs b/src/parser/types.rs index 390ae65..c835a2f 100644 --- a/src/parser/types.rs +++ b/src/parser/types.rs @@ -1,4 +1,4 @@ -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub struct LocatedToken { pub start: Pos, pub end: Pos, @@ -16,7 +16,7 @@ impl std::fmt::Display for Pos { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub enum Token { Let, Fn, @@ -38,7 +38,8 @@ pub enum Token { Equals, Not, Op(Op), - Number(i32), + Int(i32), + Float(f32), String(String), Identifier(String), Label(String), @@ -63,7 +64,7 @@ pub enum Op { BinOr, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub struct Tokens(pub Vec); impl From> for Tokens { @@ -88,7 +89,8 @@ impl Tokens { let t = self.0.pop_if(|t| match (t.token.clone(), token) { (a, b) if a == *b => true, (Token::Identifier(_), Token::Identifier(_)) => true, - (Token::Number(_), Token::Number(_)) => true, + (Token::Int(_), Token::Int(_)) => true, + (Token::Float(_), Token::Float(_)) => true, (Token::String(_), Token::String(_)) => true, (Token::Label(_), Token::Label(_)) => true, (Token::Op(_), Token::Op(_)) => true, @@ -176,7 +178,7 @@ impl Tokens { pub type Parser = fn(&mut Tokens) -> ParseResult; pub type ParseResult = Result, Error>; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub enum Error { UnexpectedToken { expected: Token,