From 4e9d846fbd51cec9e8d931c4aa3f399668ac316e Mon Sep 17 00:00:00 2001 From: Mel Date: Sun, 21 Nov 2021 19:44:47 +0100 Subject: Basic errors for parsing. --- src/error.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/error.rs (limited to 'src/error.rs') diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..7493681 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,80 @@ +use crate::{interpret::walker::WalkerError, lex::token::Location, parse::parser::ParserError}; +use colored::Colorize; +use std::fmt::Display; +pub struct RHError { + pub at: ErrorLocation, + pub kind: RHErrorKind, +} + +impl RHError { + pub fn hydrate_source<'s>(self, source: &'s str) -> RHErrorWithSource<'s> { + RHErrorWithSource { + error: self, + source, + } + } +} + +pub enum RHErrorKind { + Parse(ParserError), + Run(WalkerError), +} + +pub enum ErrorLocation { + Specific(Location), + Eof, +} + +pub struct RHErrorWithSource<'source> { + error: RHError, + source: &'source str, +} + +impl Display for RHErrorWithSource<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let (error_title, error_string) = match &self.error.kind { + RHErrorKind::Parse(parser_error) => ( + "Encountered error during parsing", + format!("{}", parser_error), + ), + RHErrorKind::Run(walker_error) => { + ("Encountered runtime error", format!("{}", walker_error)) + } + }; + + let weird_source_error_msg = + "Found error but could not get it's location in source, how does this even happen?"; + + let (line_number, line_column, source_line) = match self.error.at { + ErrorLocation::Specific(location) => ( + location.row, + location.col, + self.source + .lines() + .nth(location.row) + .expect(weird_source_error_msg), + ), + ErrorLocation::Eof => { + let lines = self.source.lines(); + let (line_count, _) = lines.size_hint(); + let last_line = lines.last().expect(weird_source_error_msg); + + (line_count, last_line.len(), last_line) + } + }; + + let arrow_pad_len = line_column + 3 + line_number.to_string().len(); + + writeln!(f, "{} {}:\n", " Error ".on_red(), error_title)?; + writeln!( + f, + "{}{}", + format!("{} | ", line_number).dimmed(), + source_line + )?; + writeln!(f, "{}{}", " ".repeat(arrow_pad_len), "^".red())?; + writeln!(f, "{}", error_string)?; + + Ok(()) + } +} -- cgit 1.4.1