aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTolmachev Igor <me@igorek.dev>2026-05-09 19:04:27 +0300
committerTolmachev Igor <me@igorek.dev>2026-05-09 19:04:46 +0300
commit6be28381d6081dfb3a1dc9d1ec15062b67ba1ef9 (patch)
tree1bf89581879ce76f27d69881a6afa4e72e30bf61
parent6c5c627dd441b0e7ac52cfd05e1923584dd213ae (diff)
downloadcrisp-6be28381d6081dfb3a1dc9d1ec15062b67ba1ef9.tar.gz
crisp-6be28381d6081dfb3a1dc9d1ec15062b67ba1ef9.zip
Implement fmt::Display for Error
Replaces the todo!() stub. InvalidFloatLiteral and InvalidIntegerLiteral now also take the original string.
-rw-r--r--compiler/src/ast/error.rs33
-rw-r--r--compiler/src/ast/parser.rs16
-rw-r--r--compiler/src/ast/tests.rs8
3 files changed, 31 insertions, 26 deletions
diff --git a/compiler/src/ast/error.rs b/compiler/src/ast/error.rs
index c3283f4..8117513 100644
--- a/compiler/src/ast/error.rs
+++ b/compiler/src/ast/error.rs
@@ -7,8 +7,8 @@ use std::{
7#[derive(Clone, Debug, PartialEq, Eq)] 7#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum Error { 8pub enum Error {
9 // Number 9 // Number
10 InvalidFloatLiteral(ParseFloatError), 10 InvalidFloatLiteral(Rc<str>, ParseFloatError),
11 InvalidIntegerLiteral(ParseIntError), 11 InvalidIntegerLiteral(Rc<str>, ParseIntError),
12 12
13 // String 13 // String
14 UnclosedString(Rc<str>), 14 UnclosedString(Rc<str>),
@@ -23,21 +23,22 @@ pub enum Error {
23 RecursionLimit, 23 RecursionLimit,
24} 24}
25 25
26impl From<ParseFloatError> for Error {
27 fn from(value: ParseFloatError) -> Self {
28 Self::InvalidFloatLiteral(value)
29 }
30}
31
32impl From<ParseIntError> for Error {
33 fn from(value: ParseIntError) -> Self {
34 Self::InvalidIntegerLiteral(value)
35 }
36}
37
38impl fmt::Display for Error { 26impl fmt::Display for Error {
39 fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { 27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40 todo!() 28 match self {
29 Error::InvalidFloatLiteral(number, err) => {
30 write!(f, "invalid float literal {number}: {err}")
31 }
32 Error::InvalidIntegerLiteral(number, err) => {
33 write!(f, "invalid integer literal {number}: {err}")
34 }
35 Error::UnclosedString(string) => write!(f, "unclosed string {string:?}"),
36 Error::UnexpectedEscapeChar(ch) => write!(f, "unexpected escape char {ch:?}"),
37 Error::UnexpectedRightPar => write!(f, "unexpected right par"),
38 Error::UnclosedLeftPar => write!(f, "unclosed left par"),
39 Error::UnexpectedEof => write!(f, "unexpected eof"),
40 Error::RecursionLimit => write!(f, "recursion limit"),
41 }
41 } 42 }
42} 43}
43 44
diff --git a/compiler/src/ast/parser.rs b/compiler/src/ast/parser.rs
index 83e48b8..263e5b7 100644
--- a/compiler/src/ast/parser.rs
+++ b/compiler/src/ast/parser.rs
@@ -12,13 +12,17 @@ fn parse_number(number: &str) -> Result<Atom, Error> {
12 let is_float = number.bytes().any(|b| matches!(b, b'.' | b'e' | b'E')) 12 let is_float = number.bytes().any(|b| matches!(b, b'.' | b'e' | b'E'))
13 || matches!(number, "inf" | "+inf" | "-inf" | "nan"); 13 || matches!(number, "inf" | "+inf" | "-inf" | "nan");
14 14
15 let atom = if is_float { 15 if is_float {
16 Atom::Float(number.parse()?) 16 match number.parse() {
17 Ok(ok) => Ok(Atom::Float(ok)),
18 Err(err) => Err(Error::InvalidFloatLiteral(number.into(), err)),
19 }
17 } else { 20 } else {
18 Atom::Integer(number.parse()?) 21 match number.parse() {
19 }; 22 Ok(ok) => Ok(Atom::Integer(ok)),
20 23 Err(err) => Err(Error::InvalidIntegerLiteral(number.into(), err)),
21 Ok(atom) 24 }
25 }
22} 26}
23 27
24fn parse_string(string: &str) -> Result<Atom, Error> { 28fn parse_string(string: &str) -> Result<Atom, Error> {
diff --git a/compiler/src/ast/tests.rs b/compiler/src/ast/tests.rs
index 708e788..c6d8c38 100644
--- a/compiler/src/ast/tests.rs
+++ b/compiler/src/ast/tests.rs
@@ -415,7 +415,7 @@ fn test_invalid_integer() {
415 let error = number.parse::<i64>().unwrap_err(); 415 let error = number.parse::<i64>().unwrap_err();
416 assert_eq!( 416 assert_eq!(
417 parse_err(tokens.clone()), 417 parse_err(tokens.clone()),
418 Error::InvalidIntegerLiteral(error), 418 Error::InvalidIntegerLiteral(number.into(), error),
419 "input: {tokens:?}", 419 "input: {tokens:?}",
420 ); 420 );
421 } 421 }
@@ -445,7 +445,7 @@ fn test_invalid_float() {
445 let error = number.parse::<f64>().unwrap_err(); 445 let error = number.parse::<f64>().unwrap_err();
446 assert_eq!( 446 assert_eq!(
447 parse_err(tokens.clone()), 447 parse_err(tokens.clone()),
448 Error::InvalidFloatLiteral(error), 448 Error::InvalidFloatLiteral(number.into(), error),
449 "input: {tokens:?}", 449 "input: {tokens:?}",
450 ); 450 );
451 } 451 }
@@ -639,7 +639,7 @@ fn test_error_span_invalid_float() {
639 let err = parse_sp_err(tokens.clone()); 639 let err = parse_sp_err(tokens.clone());
640 640
641 assert!( 641 assert!(
642 matches!(err.inner, Error::InvalidFloatLiteral(_)), 642 matches!(err.inner, Error::InvalidFloatLiteral(..)),
643 "input: {tokens:?}, got: {:?}", 643 "input: {tokens:?}, got: {:?}",
644 err.inner, 644 err.inner,
645 ); 645 );
@@ -725,7 +725,7 @@ fn test_error_span_deep_nested() {
725 let err = parse_sp_err(tokens.clone()); 725 let err = parse_sp_err(tokens.clone());
726 726
727 assert!( 727 assert!(
728 matches!(err.inner, Error::InvalidIntegerLiteral(_)), 728 matches!(err.inner, Error::InvalidIntegerLiteral(..)),
729 "input: {tokens:?}, got: {:?}", 729 "input: {tokens:?}, got: {:?}",
730 err.inner, 730 err.inner,
731 ); 731 );