diff --git a/dust-lang/src/dust_error.rs b/dust-lang/src/dust_error.rs index 907d08e..3df6b76 100644 --- a/dust-lang/src/dust_error.rs +++ b/dust-lang/src/dust_error.rs @@ -146,17 +146,63 @@ impl<'src> DustError<'src> { ); report.push_str(&renderer.render(message).to_string()); - report.push('\n'); + report.push_str("\n\n"); } DustError::Analysis { analysis_errors, source, - } => todo!(), + } => { + for error in analysis_errors { + let position = error.position(); + let label = error.to_string(); + let message = + Level::Warning + .title("Analysis error") + .snippet(Snippet::source(source).fold(true).annotation( + Level::Warning.span(position.0..position.1).label(&label), + )) + .footer( + Level::Warning + .title("This error was found without running the program."), + ); + + report.push_str(&renderer.render(message).to_string()); + report.push_str("\n\n"); + } + } DustError::Parse { parse_error, source, - } => todo!(), - DustError::Lex { lex_error, source } => todo!(), + } => { + if let ParseError::Lex(lex_error) = parse_error { + let lex_error_report = DustError::lex(lex_error.clone(), source).report(); + + report.push_str(&lex_error_report); + + return report; + } + + let position = parse_error.position(); + let label = parse_error.to_string(); + let message = Level::Error.title("Parse error").snippet( + Snippet::source(source) + .fold(true) + .annotation(Level::Error.span(position.0..position.1).label(&label)), + ); + + report.push_str(&renderer.render(message).to_string()); + } + DustError::Lex { lex_error, source } => { + let position = lex_error.position(); + let label = lex_error.to_string(); + let message = Level::Error.title("Lex error").snippet( + Snippet::source(source) + .fold(true) + .annotation(Level::Error.span(position.0..position.1).label(&label)), + ); + + report.push_str(&renderer.render(message).to_string()); + } } report diff --git a/dust-lang/src/lexer.rs b/dust-lang/src/lexer.rs index 5a68a61..bb9dbf7 100644 --- a/dust-lang/src/lexer.rs +++ b/dust-lang/src/lexer.rs @@ -297,8 +297,6 @@ impl<'src> Lexer<'src> { (Token::Colon, (self.position - 1, self.position)) } _ => { - self.position += 1; - return Err(LexError::UnexpectedCharacter { actual: c, position: self.position, @@ -497,8 +495,8 @@ pub enum LexError { impl LexError { pub fn position(&self) -> Span { match self { - Self::ExpectedCharacter { position, .. } => (*position, *position + 1), - Self::UnexpectedCharacter { position, .. } => (*position, *position + 1), + Self::ExpectedCharacter { position, .. } => (*position, *position), + Self::UnexpectedCharacter { position, .. } => (*position, *position), Self::UnexpectedEndOfFile { position } => (*position, *position), } } @@ -508,19 +506,13 @@ impl Display for LexError { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { Self::ExpectedCharacter { - expected, - actual, - position, - } => write!( - f, - "Expected character '{}' at {:?}, found '{}'", - expected, position, actual - ), - Self::UnexpectedCharacter { actual, position } => { - write!(f, "Unexpected character at {:?}: '{}'", position, actual) + expected, actual, .. + } => write!(f, "Expected character '{expected}', found '{actual}'"), + Self::UnexpectedCharacter { actual, .. } => { + write!(f, "Unexpected character '{actual}'") } - Self::UnexpectedEndOfFile { position } => { - write!(f, "Unexpected end of file at {:?}", position) + Self::UnexpectedEndOfFile { .. } => { + write!(f, "Unexpected end of file") } } }