pub mod ast;
pub mod ast_walker;
pub mod lexer;
pub mod parse_state;
pub mod parser;
pub mod pointer;
use crate::compiler::parser::ast::{Span, DUMMY_SPAN};
use std::backtrace::Backtrace;
use std::error::Error;
use std::fmt;
use std::fmt::{Debug, Display};
#[derive(Debug, Clone)]
pub struct CompileError {
pub message: String,
pub span: Span,
pub stack: Vec<String>,
}
impl CompileError {
pub(crate) fn new(message: String, span: Span) -> CompileError {
let mut stack = vec![];
let bt = Backtrace::capture();
let frames_iter = bt.frames();
for (count, frame) in frames_iter.iter().enumerate() {
if count < 4 {
continue;
}
stack.push(format!("{:?}\n", frame));
if count > 6 {
break;
}
}
return CompileError {
message,
span,
stack,
};
}
}
impl Display for CompileError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.message)
}
}
impl From<std::io::Error> for CompileError {
fn from(err: std::io::Error) -> Self {
CompileError::new(err.to_string(), DUMMY_SPAN)
}
}
impl From<String> for CompileError {
fn from(incoming: String) -> Self {
CompileError::new(incoming, DUMMY_SPAN)
}
}
impl Error for CompileError {}
#[cfg(test)]
pub(crate) mod tests {
use crate::compiler::parser::lexer::TokenStream;
use crate::compiler::parser::parse_state::ParseState;
use crate::compiler::parser::parser::Parser;
use crate::compiler::parser::CompileError;
pub(crate) fn base_test(
program: &str,
should_compile_ok: bool,
) -> Result<ParseState, Vec<CompileError>> {
let tokens = TokenStream::from(program);
let mut parser = Parser::new(tokens);
let mut result = ParseState::default();
parser.parse(&mut result);
for err in result.errors.iter() {
println!("{}: {}", err.span, err.message);
}
assert_eq!(should_compile_ok, result.errors.is_empty());
if !result.errors.is_empty() && should_compile_ok {
Err(*result.errors)
} else {
Ok(result)
}
}
}