aboutsummaryrefslogtreecommitdiff
path: root/compiler/src
diff options
context:
space:
mode:
authorTolmachev Igor <me@igorek.dev>2026-05-10 12:54:41 +0300
committerTolmachev Igor <me@igorek.dev>2026-05-10 12:54:41 +0300
commit843242e692280d604b74324ba26ead6158223439 (patch)
treee5f2d362b1c728f900d8214bc415752336fa4a94 /compiler/src
parent1801afdbd0058cc9cc040b977de0d5652d65aab9 (diff)
downloadcrisp-843242e692280d604b74324ba26ead6158223439.tar.gz
crisp-843242e692280d604b74324ba26ead6158223439.zip
Remove Float from parser
Dropped to make the language simpler.
Diffstat (limited to 'compiler/src')
-rw-r--r--compiler/src/ast/error.rs10
-rw-r--r--compiler/src/ast/models.rs1
-rw-r--r--compiler/src/ast/parser.rs19
-rw-r--r--compiler/src/ast/tests.rs96
-rw-r--r--compiler/src/lex/lexer.rs6
-rw-r--r--compiler/src/lex/tests.rs8
6 files changed, 7 insertions, 133 deletions
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 @@
1use std::{ 1use std::{error, fmt, num::ParseIntError, rc::Rc};
2 error, fmt,
3 num::{ParseFloatError, ParseIntError},
4 rc::Rc,
5};
6 2
7#[derive(Clone, Debug, PartialEq, Eq)] 3#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum Error { 4pub enum Error {
9 // Number 5 // Number
10 InvalidFloatLiteral(Rc<str>, ParseFloatError),
11 InvalidIntegerLiteral(Rc<str>, ParseIntError), 6 InvalidIntegerLiteral(Rc<str>, ParseIntError),
12 7
13 // String 8 // String
@@ -26,9 +21,6 @@ pub enum Error {
26impl fmt::Display for Error { 21impl fmt::Display for Error {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28 match self { 23 match self {
29 Error::InvalidFloatLiteral(number, err) => {
30 write!(f, "invalid float literal {number}: {err}")
31 }
32 Error::InvalidIntegerLiteral(number, err) => { 24 Error::InvalidIntegerLiteral(number, err) => {
33 write!(f, "invalid integer literal {number}: {err}") 25 write!(f, "invalid integer literal {number}: {err}")
34 } 26 }
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;
4 4
5#[derive(Clone, Debug, PartialEq)] 5#[derive(Clone, Debug, PartialEq)]
6pub enum Atom { 6pub enum Atom {
7 Float(f64),
8 Integer(i64), 7 Integer(i64),
9 String(Rc<str>), 8 String(Rc<str>),
10 Symbol(Rc<str>), 9 Symbol(Rc<str>),
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::{
9pub(super) const MAX_DEPTH: usize = 256; // TODO: make it a compile flag 9pub(super) const MAX_DEPTH: usize = 256; // TODO: make it a compile flag
10 10
11fn parse_number(number: &str) -> Result<Atom, Error> { 11fn parse_number(number: &str) -> Result<Atom, Error> {
12 let is_float = number.bytes().any(|b| matches!(b, b'.' | b'e' | b'E')) 12 match number.parse() {
13 || matches!(number, "inf" | "+inf" | "-inf" | "nan"); 13 Ok(ok) => Ok(Atom::Integer(ok)),
14 14 Err(err) => Err(Error::InvalidIntegerLiteral(number.into(), err)),
15 if is_float {
16 match number.parse() {
17 Ok(ok) => Ok(Atom::Float(ok)),
18 Err(err) => Err(Error::InvalidFloatLiteral(number.into(), err)),
19 }
20 } else {
21 match number.parse() {
22 Ok(ok) => Ok(Atom::Integer(ok)),
23 Err(err) => Err(Error::InvalidIntegerLiteral(number.into(), err)),
24 }
25 } 15 }
26} 16}
27 17
@@ -59,9 +49,6 @@ fn parse_symbol(symbol: &str) -> Atom {
59 "true" => Atom::Bool(true), 49 "true" => Atom::Bool(true),
60 "false" => Atom::Bool(false), 50 "false" => Atom::Bool(false),
61 "nil" => Atom::Nil, 51 "nil" => Atom::Nil,
62 "inf" | "+inf" => Atom::Float(f64::INFINITY),
63 "-inf" => Atom::Float(f64::NEG_INFINITY),
64 "nan" => Atom::Float(f64::NAN),
65 _ => Atom::Symbol(symbol.into()), 52 _ => Atom::Symbol(symbol.into()),
66 } 53 }
67} 54}
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::{
8 8
9#[derive(Debug, PartialEq)] 9#[derive(Debug, PartialEq)]
10enum E { 10enum E {
11 Flt(f64),
12 Int(i64), 11 Int(i64),
13 Str(&'static str), 12 Str(&'static str),
14 Sym(&'static str), 13 Sym(&'static str),
@@ -21,7 +20,6 @@ impl From<Expr> for E {
21 fn from(expr: Expr) -> Self { 20 fn from(expr: Expr) -> Self {
22 match expr { 21 match expr {
23 Expr::Atom(atom) => match atom { 22 Expr::Atom(atom) => match atom {
24 Atom::Float(f) => Flt(f),
25 Atom::Integer(i) => Int(i), 23 Atom::Integer(i) => Int(i),
26 Atom::String(s) => Str(Box::leak(s.into())), 24 Atom::String(s) => Str(Box::leak(s.into())),
27 Atom::Symbol(s) => Sym(Box::leak(s.into())), 25 Atom::Symbol(s) => Sym(Box::leak(s.into())),
@@ -69,47 +67,11 @@ fn test_integers() {
69} 67}
70 68
71#[test] 69#[test]
72fn test_floats() {
73 let cases = vec![
74 (vec![Number("2.71")], vec![Flt(2.71)]),
75 (vec![Number("-2.5")], vec![Flt(-2.5)]),
76 (vec![Number("+0.0")], vec![Flt(0.0)]),
77 (vec![Number(".5")], vec![Flt(0.5)]),
78 (vec![Number("-.5")], vec![Flt(-0.5)]),
79 (vec![Number("+.5")], vec![Flt(0.5)]),
80 (vec![Number("1e10")], vec![Flt(1e10)]),
81 (vec![Number("1E10")], vec![Flt(1e10)]),
82 (vec![Number("1.5e-3")], vec![Flt(1.5e-3)]),
83 (vec![Number("-1.5E+3")], vec![Flt(-1.5e3)]),
84 (vec![Number("inf")], vec![Flt(f64::INFINITY)]),
85 (vec![Number("-inf")], vec![Flt(f64::NEG_INFINITY)]),
86 (vec![Number("1e9999")], vec![Flt(f64::INFINITY)]),
87 (vec![Number("-1e9999")], vec![Flt(f64::NEG_INFINITY)]),
88 ];
89 for (tokens, ast) in cases {
90 assert_eq!(parse(tokens.clone()), ast, "input: {tokens:?}");
91 }
92}
93
94#[test]
95fn test_float_nan() {
96 let tokens = vec![Number("nan")];
97 let expr = &parse(tokens.clone())[0];
98 assert!(
99 matches!(expr, Flt(f) if f.is_nan()),
100 "input: {tokens:?}, got: {expr:?}"
101 );
102}
103
104#[test]
105fn test_keywords() { 70fn test_keywords() {
106 let cases = vec![ 71 let cases = vec![
107 (vec![Symbol("true")], vec![Bool(true)]), 72 (vec![Symbol("true")], vec![Bool(true)]),
108 (vec![Symbol("false")], vec![Bool(false)]), 73 (vec![Symbol("false")], vec![Bool(false)]),
109 (vec![Symbol("nil")], vec![Nil]), 74 (vec![Symbol("nil")], vec![Nil]),
110 (vec![Symbol("inf")], vec![Flt(f64::INFINITY)]),
111 (vec![Symbol("+inf")], vec![Flt(f64::INFINITY)]),
112 (vec![Symbol("-inf")], vec![Flt(f64::NEG_INFINITY)]),
113 (vec![LeftPar, RightPar], vec![Nil]), 75 (vec![LeftPar, RightPar], vec![Nil]),
114 ]; 76 ];
115 for (tokens, ast) in cases { 77 for (tokens, ast) in cases {
@@ -118,16 +80,6 @@ fn test_keywords() {
118} 80}
119 81
120#[test] 82#[test]
121fn test_keyword_nan() {
122 let tokens = vec![Symbol("nan")];
123 let expr = &parse(tokens.clone())[0];
124 assert!(
125 matches!(expr, Flt(f) if f.is_nan()),
126 "input: {tokens:?}, got: {expr:?}"
127 );
128}
129
130#[test]
131fn test_keywords_case_sensitive() { 83fn test_keywords_case_sensitive() {
132 let cases = vec![ 84 let cases = vec![
133 (vec![Symbol("True")], vec![Sym("True")]), 85 (vec![Symbol("True")], vec![Sym("True")]),
@@ -241,7 +193,7 @@ fn test_lists() {
241 vec![ 193 vec![
242 LeftPar, 194 LeftPar,
243 Number("1"), 195 Number("1"),
244 Number("2.5"), 196 Number("-1"),
245 String("s"), 197 String("s"),
246 Symbol("foo"), 198 Symbol("foo"),
247 Symbol("true"), 199 Symbol("true"),
@@ -250,7 +202,7 @@ fn test_lists() {
250 ], 202 ],
251 vec![List(vec![ 203 vec![List(vec![
252 Int(1), 204 Int(1),
253 Flt(2.5), 205 Int(-1),
254 Str("s"), 206 Str("s"),
255 Sym("foo"), 207 Sym("foo"),
256 Bool(true), 208 Bool(true),
@@ -351,36 +303,6 @@ fn test_invalid_integer() {
351} 303}
352 304
353#[test] 305#[test]
354fn test_invalid_float() {
355 let cases = vec![
356 "12somE0txt",
357 "12som.0txt",
358 "12.3txt",
359 "1.2.3",
360 "1.2.3.4",
361 ".",
362 "+.",
363 "-.",
364 "1e",
365 "1e+",
366 "1e-",
367 "1.e",
368 ".e5",
369 "1ee5",
370 "1e1.5",
371 ];
372 for number in cases {
373 let tokens = vec![Number(number)];
374 let error = number.parse::<f64>().unwrap_err();
375 assert_eq!(
376 parse_err(tokens.clone()),
377 Error::InvalidFloatLiteral(number.into(), error),
378 "input: {tokens:?}",
379 );
380 }
381}
382
383#[test]
384fn test_unclosed_string() { 306fn test_unclosed_string() {
385 let cases = vec![ 307 let cases = vec![
386 ( 308 (
@@ -505,20 +427,6 @@ fn test_error_span_invalid_integer() {
505} 427}
506 428
507#[test] 429#[test]
508fn test_error_span_invalid_float() {
509 let s = sp((1, 0, 0), (1, 5, 5));
510 let tokens = vec![tsp(Number("1.2.3"), s)];
511 let err = parse_sp_err(tokens.clone());
512
513 assert!(
514 matches!(err.inner, Error::InvalidFloatLiteral(..)),
515 "input: {tokens:?}, got: {:?}",
516 err.inner,
517 );
518 assert_eq!(err.span, s, "input: {tokens:?}");
519}
520
521#[test]
522fn test_error_span_unclosed_left_par() { 430fn test_error_span_unclosed_left_par() {
523 let lp = sp((1, 0, 0), (1, 1, 1)); 431 let lp = sp((1, 0, 0), (1, 1, 1));
524 let tokens = vec![tsp(LeftPar, lp)]; 432 let tokens = vec![tsp(LeftPar, lp)];
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> {
131 131
132 // Number 132 // Number
133 ch if ch.is_ascii_digit() 133 ch if ch.is_ascii_digit()
134 || ch == '.' && self.peek_nth(1).is_some_and(|ch| ch.is_ascii_digit())
135 || matches!(ch, '+' | '-') 134 || matches!(ch, '+' | '-')
136 && self.peek_nth(1).is_some_and(|ch| ch.is_ascii_digit()) 135 && self.peek_nth(1).is_some_and(|ch| ch.is_ascii_digit()) =>
137 || matches!(ch, '+' | '-')
138 && self.peek_nth(1).is_some_and(|ch| ch == '.')
139 && self.peek_nth(2).is_some_and(|ch| ch.is_ascii_digit()) =>
140 { 136 {
141 Token::Number(self.next_atom()) 137 Token::Number(self.next_atom())
142 } 138 }
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() {
42 let cases = vec![ 42 let cases = vec![
43 ("0", vec![Number("0")]), 43 ("0", vec![Number("0")]),
44 ("42", vec![Number("42")]), 44 ("42", vec![Number("42")]),
45 ("3.14", vec![Number("3.14")]),
46 ("-7", vec![Number("-7")]), 45 ("-7", vec![Number("-7")]),
47 ("+5", vec![Number("+5")]), 46 ("+5", vec![Number("+5")]),
48 ("-0.5", vec![Number("-0.5")]),
49 ("1e10", vec![Number("1e10")]),
50 ("1.5e-3", vec![Number("1.5e-3")]),
51 (".5", vec![Number(".5")]),
52 ("-.5", vec![Number("-.5")]),
53 ("+.5", vec![Number("+.5")]),
54 ("-.0", vec![Number("-.0")]),
55 ]; 47 ];
56 for (code, tokens) in cases { 48 for (code, tokens) in cases {
57 assert_eq!(tokenize(code), tokens); 49 assert_eq!(tokenize(code), tokens);