From 6be28381d6081dfb3a1dc9d1ec15062b67ba1ef9 Mon Sep 17 00:00:00 2001 From: Tolmachev Igor Date: Sat, 9 May 2026 19:04:27 +0300 Subject: Implement fmt::Display for Error Replaces the todo!() stub. InvalidFloatLiteral and InvalidIntegerLiteral now also take the original string. --- compiler/src/ast/error.rs | 33 +++++++++++++++++---------------- compiler/src/ast/parser.rs | 16 ++++++++++------ compiler/src/ast/tests.rs | 8 ++++---- 3 files changed, 31 insertions(+), 26 deletions(-) (limited to 'compiler/src') 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::{ #[derive(Clone, Debug, PartialEq, Eq)] pub enum Error { // Number - InvalidFloatLiteral(ParseFloatError), - InvalidIntegerLiteral(ParseIntError), + InvalidFloatLiteral(Rc, ParseFloatError), + InvalidIntegerLiteral(Rc, ParseIntError), // String UnclosedString(Rc), @@ -23,21 +23,22 @@ pub enum Error { RecursionLimit, } -impl From for Error { - fn from(value: ParseFloatError) -> Self { - Self::InvalidFloatLiteral(value) - } -} - -impl From for Error { - fn from(value: ParseIntError) -> Self { - Self::InvalidIntegerLiteral(value) - } -} - impl fmt::Display for Error { - fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { - todo!() + 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}") + } + Error::UnclosedString(string) => write!(f, "unclosed string {string:?}"), + Error::UnexpectedEscapeChar(ch) => write!(f, "unexpected escape char {ch:?}"), + Error::UnexpectedRightPar => write!(f, "unexpected right par"), + Error::UnclosedLeftPar => write!(f, "unclosed left par"), + Error::UnexpectedEof => write!(f, "unexpected eof"), + Error::RecursionLimit => write!(f, "recursion limit"), + } } } 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 { let is_float = number.bytes().any(|b| matches!(b, b'.' | b'e' | b'E')) || matches!(number, "inf" | "+inf" | "-inf" | "nan"); - let atom = if is_float { - Atom::Float(number.parse()?) + if is_float { + match number.parse() { + Ok(ok) => Ok(Atom::Float(ok)), + Err(err) => Err(Error::InvalidFloatLiteral(number.into(), err)), + } } else { - Atom::Integer(number.parse()?) - }; - - Ok(atom) + match number.parse() { + Ok(ok) => Ok(Atom::Integer(ok)), + Err(err) => Err(Error::InvalidIntegerLiteral(number.into(), err)), + } + } } fn parse_string(string: &str) -> Result { 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() { let error = number.parse::().unwrap_err(); assert_eq!( parse_err(tokens.clone()), - Error::InvalidIntegerLiteral(error), + Error::InvalidIntegerLiteral(number.into(), error), "input: {tokens:?}", ); } @@ -445,7 +445,7 @@ fn test_invalid_float() { let error = number.parse::().unwrap_err(); assert_eq!( parse_err(tokens.clone()), - Error::InvalidFloatLiteral(error), + Error::InvalidFloatLiteral(number.into(), error), "input: {tokens:?}", ); } @@ -639,7 +639,7 @@ fn test_error_span_invalid_float() { let err = parse_sp_err(tokens.clone()); assert!( - matches!(err.inner, Error::InvalidFloatLiteral(_)), + matches!(err.inner, Error::InvalidFloatLiteral(..)), "input: {tokens:?}, got: {:?}", err.inner, ); @@ -725,7 +725,7 @@ fn test_error_span_deep_nested() { let err = parse_sp_err(tokens.clone()); assert!( - matches!(err.inner, Error::InvalidIntegerLiteral(_)), + matches!(err.inner, Error::InvalidIntegerLiteral(..)), "input: {tokens:?}, got: {:?}", err.inner, ); -- cgit v1.3