1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
use colored::*; use std::error::Error; use std::fmt; use std::fmt::{Display, Formatter}; #[macro_export] macro_rules! parse { ($str:expr) => { Parser::new($str.to_string(), None).parse() }; } pub type ParseResult<T> = Result<T, ParseError>; #[derive(Debug)] pub struct ParseError { index: usize, message: Option<String>, pub(crate) eof: bool, } impl Display for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { if let Some(message) = &self.message { write!( f, "{}", format!("Parse Error at index {}: {}", self.index, message).red() ) } else { write!( f, "{}", format!("Parse Error at index {}", self.index).red() ) } } } impl Error for ParseError {} impl ParseError { pub fn new(index: usize) -> Self { Self { index, message: None, eof: false, } } pub fn new_with_message(index: usize, message: &str) -> Self { Self { index, message: Some(message.to_string()), eof: false, } } pub fn eof(index: usize) -> Self { Self { index, message: Some("EOF".to_string()), eof: true, } } pub fn set_message(&mut self, message: &str) { self.message = Some(message.to_string()); } pub fn get_position(&self, content: &str) -> Option<(usize, usize)> { if content.len() <= self.index { return None; } let split_content = content.split_at(self.index); let line_number = split_content.0.matches("\n").count() as usize; let overshoot_position = self.index as isize - split_content.0.len() as isize; if let Some(line) = split_content.0.lines().last() { let inline_position = (line.len() as isize + overshoot_position) as usize; Some((line_number, inline_position)) } else { None } } }