nilang 0.4.1

A scripting language interpreter for Advent of Code
Documentation
pub use super::lexer::LexError;
pub use crate::spanned::{Spanned, retrieve_span_snippet};

#[derive(PartialEq, Debug)]
pub struct ParseError {
    items: Vec<Spanned<ParseErrorItem>>,
    path: Option<String>,
}

#[derive(PartialEq, Debug)]
pub enum ParseErrorItem {
    LexError(LexError),
    Expected { msg: String, found: String },
    DuplicateArgs,
}

impl ParseError {
    pub fn new(items: Vec<Spanned<ParseErrorItem>>, path: Option<String>) -> Self {
        Self {
            items,
            path
        }
    }

    pub fn set_path(&mut self, path: Option<&String>) {
        self.path = path.cloned();
    }

    pub fn render(&self) -> String {
        let mut result = String::new();

        if let Some(path) = self.path.as_ref() {
            for spanned_err in self.items.iter() {
                result.push_str(&format!("{}\n", spanned_err.item.render()));
                if let Ok(span_snippet) = retrieve_span_snippet(path, spanned_err.span) {
                    let line = span_snippet.line;
                    let source = format!(" {} | {}\n", line, span_snippet.source_line.trim());
                    result.push_str(&source);
                } else {
                    result.push_str("  EOF\n");
                }
            }

            result.push_str(&format!("parser error: Failed to parse \"{}\" due to the previous {} errors.", path, self.items.len()));
        } else {
            for spanned_err in self.items.iter() {
                result.push_str(&format!("{}\n", spanned_err.item.render()));
            }
            result.push_str(&format!("parser error: Failed to parse due to the previous {} errors.", self.items.len()));
        }

        result
    }

}

impl ParseErrorItem {
    fn render(&self) -> String {
        match self {
            ParseErrorItem::LexError(err) => format!("lexical error: {}", err.render()),
            ParseErrorItem::Expected { msg, found } => format!("parser error: {msg}, found {found}"),
            ParseErrorItem::DuplicateArgs => String::from("parser error: Function arguments cannot duplicate names"),
        }
    }
}