From 843242e692280d604b74324ba26ead6158223439 Mon Sep 17 00:00:00 2001 From: Tolmachev Igor Date: Sun, 10 May 2026 12:54:41 +0300 Subject: Remove Float from parser Dropped to make the language simpler. --- compiler/src/ast/error.rs | 10 +---- compiler/src/ast/models.rs | 1 - compiler/src/ast/parser.rs | 19 ++------- compiler/src/ast/tests.rs | 96 +--------------------------------------------- compiler/src/lex/lexer.rs | 6 +-- compiler/src/lex/tests.rs | 8 ---- 6 files changed, 7 insertions(+), 133 deletions(-) (limited to 'compiler') diff --git a/compiler/src/ast/error.rs b/compiler/src/ast/error.rs index 8117513..38b3916 100644 --- a/compiler/src/ast/error.rs +++ b/compiler/src/ast/error.rs @@ -1,13 +1,8 @@ -use std::{ - error, fmt, - num::{ParseFloatError, ParseIntError}, - rc::Rc, -}; +use std::{error, fmt, num::ParseIntError, rc::Rc}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum Error { // Number - InvalidFloatLiteral(Rc, ParseFloatError), InvalidIntegerLiteral(Rc, ParseIntError), // String @@ -26,9 +21,6 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Error::InvalidFloatLiteral(number, err) => { - write!(f, "invalid float literal {number}: {err}") - } Error::InvalidIntegerLiteral(number, err) => { write!(f, "invalid integer literal {number}: {err}") } diff --git a/compiler/src/ast/models.rs b/compiler/src/ast/models.rs index db9728d..2a8c5ae 100644 --- a/compiler/src/ast/models.rs +++ b/compiler/src/ast/models.rs @@ -4,7 +4,6 @@ use crate::span::Spanned; #[derive(Clone, Debug, PartialEq)] pub enum Atom { - Float(f64), Integer(i64), String(Rc), Symbol(Rc), diff --git a/compiler/src/ast/parser.rs b/compiler/src/ast/parser.rs index bb4e0ce..c0ad917 100644 --- a/compiler/src/ast/parser.rs +++ b/compiler/src/ast/parser.rs @@ -9,19 +9,9 @@ use crate::{ pub(super) const MAX_DEPTH: usize = 256; // TODO: make it a compile flag fn parse_number(number: &str) -> Result { - let is_float = number.bytes().any(|b| matches!(b, b'.' | b'e' | b'E')) - || matches!(number, "inf" | "+inf" | "-inf" | "nan"); - - if is_float { - match number.parse() { - Ok(ok) => Ok(Atom::Float(ok)), - Err(err) => Err(Error::InvalidFloatLiteral(number.into(), err)), - } - } else { - match number.parse() { - Ok(ok) => Ok(Atom::Integer(ok)), - Err(err) => Err(Error::InvalidIntegerLiteral(number.into(), err)), - } + match number.parse() { + Ok(ok) => Ok(Atom::Integer(ok)), + Err(err) => Err(Error::InvalidIntegerLiteral(number.into(), err)), } } @@ -59,9 +49,6 @@ fn parse_symbol(symbol: &str) -> Atom { "true" => Atom::Bool(true), "false" => Atom::Bool(false), "nil" => Atom::Nil, - "inf" | "+inf" => Atom::Float(f64::INFINITY), - "-inf" => Atom::Float(f64::NEG_INFINITY), - "nan" => Atom::Float(f64::NAN), _ => Atom::Symbol(symbol.into()), } } diff --git a/compiler/src/ast/tests.rs b/compiler/src/ast/tests.rs index 505b075..44789cb 100644 --- a/compiler/src/ast/tests.rs +++ b/compiler/src/ast/tests.rs @@ -8,7 +8,6 @@ use crate::{ #[derive(Debug, PartialEq)] enum E { - Flt(f64), Int(i64), Str(&'static str), Sym(&'static str), @@ -21,7 +20,6 @@ impl From for E { fn from(expr: Expr) -> Self { match expr { Expr::Atom(atom) => match atom { - Atom::Float(f) => Flt(f), Atom::Integer(i) => Int(i), Atom::String(s) => Str(Box::leak(s.into())), Atom::Symbol(s) => Sym(Box::leak(s.into())), @@ -68,48 +66,12 @@ fn test_integers() { } } -#[test] -fn test_floats() { - let cases = vec![ - (vec![Number("2.71")], vec![Flt(2.71)]), - (vec![Number("-2.5")], vec![Flt(-2.5)]), - (vec![Number("+0.0")], vec![Flt(0.0)]), - (vec![Number(".5")], vec![Flt(0.5)]), - (vec![Number("-.5")], vec![Flt(-0.5)]), - (vec![Number("+.5")], vec![Flt(0.5)]), - (vec![Number("1e10")], vec![Flt(1e10)]), - (vec![Number("1E10")], vec![Flt(1e10)]), - (vec![Number("1.5e-3")], vec![Flt(1.5e-3)]), - (vec![Number("-1.5E+3")], vec![Flt(-1.5e3)]), - (vec![Number("inf")], vec![Flt(f64::INFINITY)]), - (vec![Number("-inf")], vec![Flt(f64::NEG_INFINITY)]), - (vec![Number("1e9999")], vec![Flt(f64::INFINITY)]), - (vec![Number("-1e9999")], vec![Flt(f64::NEG_INFINITY)]), - ]; - for (tokens, ast) in cases { - assert_eq!(parse(tokens.clone()), ast, "input: {tokens:?}"); - } -} - -#[test] -fn test_float_nan() { - let tokens = vec![Number("nan")]; - let expr = &parse(tokens.clone())[0]; - assert!( - matches!(expr, Flt(f) if f.is_nan()), - "input: {tokens:?}, got: {expr:?}" - ); -} - #[test] fn test_keywords() { let cases = vec![ (vec![Symbol("true")], vec![Bool(true)]), (vec![Symbol("false")], vec![Bool(false)]), (vec![Symbol("nil")], vec![Nil]), - (vec![Symbol("inf")], vec![Flt(f64::INFINITY)]), - (vec![Symbol("+inf")], vec![Flt(f64::INFINITY)]), - (vec![Symbol("-inf")], vec![Flt(f64::NEG_INFINITY)]), (vec![LeftPar, RightPar], vec![Nil]), ]; for (tokens, ast) in cases { @@ -117,16 +79,6 @@ fn test_keywords() { } } -#[test] -fn test_keyword_nan() { - let tokens = vec![Symbol("nan")]; - let expr = &parse(tokens.clone())[0]; - assert!( - matches!(expr, Flt(f) if f.is_nan()), - "input: {tokens:?}, got: {expr:?}" - ); -} - #[test] fn test_keywords_case_sensitive() { let cases = vec![ @@ -241,7 +193,7 @@ fn test_lists() { vec![ LeftPar, Number("1"), - Number("2.5"), + Number("-1"), String("s"), Symbol("foo"), Symbol("true"), @@ -250,7 +202,7 @@ fn test_lists() { ], vec![List(vec![ Int(1), - Flt(2.5), + Int(-1), Str("s"), Sym("foo"), Bool(true), @@ -350,36 +302,6 @@ fn test_invalid_integer() { } } -#[test] -fn test_invalid_float() { - let cases = vec![ - "12somE0txt", - "12som.0txt", - "12.3txt", - "1.2.3", - "1.2.3.4", - ".", - "+.", - "-.", - "1e", - "1e+", - "1e-", - "1.e", - ".e5", - "1ee5", - "1e1.5", - ]; - for number in cases { - let tokens = vec![Number(number)]; - let error = number.parse::().unwrap_err(); - assert_eq!( - parse_err(tokens.clone()), - Error::InvalidFloatLiteral(number.into(), error), - "input: {tokens:?}", - ); - } -} - #[test] fn test_unclosed_string() { let cases = vec![ @@ -504,20 +426,6 @@ fn test_error_span_invalid_integer() { assert_eq!(err.span, s, "input: {tokens:?}"); } -#[test] -fn test_error_span_invalid_float() { - let s = sp((1, 0, 0), (1, 5, 5)); - let tokens = vec![tsp(Number("1.2.3"), s)]; - let err = parse_sp_err(tokens.clone()); - - assert!( - matches!(err.inner, Error::InvalidFloatLiteral(..)), - "input: {tokens:?}, got: {:?}", - err.inner, - ); - assert_eq!(err.span, s, "input: {tokens:?}"); -} - #[test] fn test_error_span_unclosed_left_par() { let lp = sp((1, 0, 0), (1, 1, 1)); diff --git a/compiler/src/lex/lexer.rs b/compiler/src/lex/lexer.rs index 6efbca0..5e45b20 100644 --- a/compiler/src/lex/lexer.rs +++ b/compiler/src/lex/lexer.rs @@ -131,12 +131,8 @@ impl<'a> Iterator for Lexer<'a> { // Number ch if ch.is_ascii_digit() - || ch == '.' && self.peek_nth(1).is_some_and(|ch| ch.is_ascii_digit()) || matches!(ch, '+' | '-') - && self.peek_nth(1).is_some_and(|ch| ch.is_ascii_digit()) - || matches!(ch, '+' | '-') - && self.peek_nth(1).is_some_and(|ch| ch == '.') - && self.peek_nth(2).is_some_and(|ch| ch.is_ascii_digit()) => + && self.peek_nth(1).is_some_and(|ch| ch.is_ascii_digit()) => { Token::Number(self.next_atom()) } diff --git a/compiler/src/lex/tests.rs b/compiler/src/lex/tests.rs index d0ed658..0672dfa 100644 --- a/compiler/src/lex/tests.rs +++ b/compiler/src/lex/tests.rs @@ -42,16 +42,8 @@ fn test_numbers() { let cases = vec![ ("0", vec![Number("0")]), ("42", vec![Number("42")]), - ("3.14", vec![Number("3.14")]), ("-7", vec![Number("-7")]), ("+5", vec![Number("+5")]), - ("-0.5", vec![Number("-0.5")]), - ("1e10", vec![Number("1e10")]), - ("1.5e-3", vec![Number("1.5e-3")]), - (".5", vec![Number(".5")]), - ("-.5", vec![Number("-.5")]), - ("+.5", vec![Number("+.5")]), - ("-.0", vec![Number("-.0")]), ]; for (code, tokens) in cases { assert_eq!(tokenize(code), tokens); -- cgit v1.3