More refactoring
This commit is contained in:
parent
51e5c0b80d
commit
b7f6705d62
7 changed files with 122 additions and 56 deletions
|
@ -12,8 +12,10 @@ pub enum ASTParsingError {
|
|||
}
|
||||
|
||||
impl std::fmt::Display for ASTParsingError {
|
||||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
todo!()
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match *self {
|
||||
Self::UnmatchedBrace => write!(f, "Unmatched brace"),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl std::error::Error for ASTParsingError {}
|
||||
|
|
34
src/error.rs
34
src/error.rs
|
@ -37,3 +37,37 @@ impl<'a> From<&'a OwnedLocation> for Location<'a> {
|
|||
pub trait ErrorWithLocation: Error {
|
||||
fn get_location(&self) -> Location;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ErrorLocationWrapper<T: Error> {
|
||||
inner: T,
|
||||
location: OwnedLocation,
|
||||
}
|
||||
|
||||
impl<T: Error> ErrorLocationWrapper<T> {
|
||||
pub fn new(inner: T, location: OwnedLocation) -> Self {
|
||||
Self { inner, location }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: std::error::Error> ErrorWithLocation for ErrorLocationWrapper<T> {
|
||||
fn get_location(&self) -> Location {
|
||||
(&self.location).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Error> std::fmt::Display for ErrorLocationWrapper<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"An error occured: {} \n On line: {}, col: {}",
|
||||
self.inner, self.location.line, self.location.col
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Error> Error for ErrorLocationWrapper<T> {
|
||||
fn cause(&self) -> Option<&dyn Error> {
|
||||
Some(&self.inner)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use super::types;
|
||||
use crate::ast::astnode::{self, UnaryOperator};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RuntimeError;
|
||||
|
||||
impl Display for RuntimeError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "A runtime error occured")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for RuntimeError {}
|
||||
|
||||
pub trait Interpret {
|
||||
fn interpret(&self) -> Result<types::Value, RuntimeError>;
|
||||
}
|
||||
|
|
|
@ -2,29 +2,7 @@ use crate::error::{ErrorWithLocation, Location, OwnedLocation};
|
|||
use core::fmt;
|
||||
use std::error::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LexingError {
|
||||
pub location: OwnedLocation,
|
||||
pub kind: LexingErrorKind,
|
||||
}
|
||||
|
||||
impl fmt::Display for LexingError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Error: {}", self.kind)
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorWithLocation for LexingError {
|
||||
fn get_location<'a>(&'a self) -> Location<'a> {
|
||||
(&self.location).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for LexingError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
Some(&self.kind)
|
||||
}
|
||||
}
|
||||
pub type LexingError = crate::error::ErrorLocationWrapper<LexingErrorKind>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LexingErrorKind {
|
||||
|
|
|
@ -68,6 +68,10 @@ impl<'a, 'b> Lexer<'a, 'b> {
|
|||
self.get_token(token_type)
|
||||
}
|
||||
|
||||
fn get_error(&self, error: LexingErrorKind) -> LexingError {
|
||||
LexingError::new(error, self.source_iter.get_location(self.file).into())
|
||||
}
|
||||
|
||||
fn scan_token(&mut self) -> Option<Result<Token<'b>, LexingError>> {
|
||||
Some(Ok(match self.source_iter.next()? {
|
||||
'(' => self.get_token(token::TokenType::LeftParen),
|
||||
|
@ -103,11 +107,8 @@ impl<'a, 'b> Lexer<'a, 'b> {
|
|||
),
|
||||
'"' => {
|
||||
let mut string = String::new();
|
||||
let unmatched_char_error = Some(Err(LexingError {
|
||||
kind: LexingErrorKind::UnmatchedQuote,
|
||||
location: self.source_iter.get_location(self.file).into(),
|
||||
}));
|
||||
|
||||
let unmatched_char_error =
|
||||
Some(Err(self.get_error(LexingErrorKind::UnmatchedQuote)));
|
||||
loop {
|
||||
let next_char = self.source_iter.next();
|
||||
match next_char {
|
||||
|
@ -156,12 +157,7 @@ impl<'a, 'b> Lexer<'a, 'b> {
|
|||
}
|
||||
// Ignore whitespace
|
||||
' ' | '\r' | '\t' | '\n' => return None,
|
||||
c => {
|
||||
return Some(Err(LexingError {
|
||||
location: self.source_iter.get_location(self.file).into(),
|
||||
kind: LexingErrorKind::UnexpectedCharacter(c),
|
||||
}))
|
||||
}
|
||||
c => return Some(Err(self.get_error(LexingErrorKind::UnexpectedCharacter(c)))),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
62
src/lib.rs
Normal file
62
src/lib.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
pub mod ast;
|
||||
pub mod error;
|
||||
pub mod interpreter;
|
||||
pub mod lexer;
|
||||
|
||||
use interpreter::ast_walker::Interpret;
|
||||
use interpreter::types::Value;
|
||||
use lexer::Lexer;
|
||||
|
||||
pub fn run(code: &str) -> Result<Value, run::Error> {
|
||||
let mut lexer = Lexer::new(code, None);
|
||||
let tokens = lexer.scan_tokens()?;
|
||||
|
||||
let mut parser = crate::ast::parser::Parser::new(tokens.into_iter());
|
||||
let expressions = parser.scan_expressions()?;
|
||||
|
||||
Ok(expressions[0].interpret()?)
|
||||
}
|
||||
|
||||
mod run {
|
||||
use std::fmt::Display;
|
||||
|
||||
use super::ast;
|
||||
use super::interpreter::ast_walker::RuntimeError;
|
||||
use super::lexer;
|
||||
use from_variants::FromVariants;
|
||||
|
||||
#[derive(Debug, FromVariants)]
|
||||
pub enum Error {
|
||||
Lexing(Vec<lexer::LexingError>),
|
||||
ASTParsing(Vec<ast::parser::ASTParsingError>),
|
||||
Runtime(RuntimeError),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let error_kind = match *self {
|
||||
Error::Lexing(_) => "lexing",
|
||||
Error::ASTParsing(_) => "ast generation",
|
||||
Error::Runtime(_) => "runtime",
|
||||
};
|
||||
write!(f, "Errors occured during {error_kind}\n")?;
|
||||
match *self {
|
||||
Error::Lexing(ref errors) => {
|
||||
for error in errors {
|
||||
write!(f, "{error} \n")?;
|
||||
}
|
||||
}
|
||||
Error::ASTParsing(ref errors) => {
|
||||
for error in errors {
|
||||
write!(f, "{error} \n")?;
|
||||
}
|
||||
}
|
||||
Error::Runtime(ref error) => write!(f, "{error} \n")?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
}
|
25
src/main.rs
25
src/main.rs
|
@ -1,10 +1,4 @@
|
|||
mod ast;
|
||||
mod error;
|
||||
mod interpreter;
|
||||
mod lexer;
|
||||
|
||||
use interpreter::ast_walker::Interpret;
|
||||
use lexer::Lexer;
|
||||
use crftng_intrprtrs::run;
|
||||
use std::{fs, io, path};
|
||||
use tracing::Level;
|
||||
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
||||
|
@ -27,7 +21,10 @@ fn run_repl() {
|
|||
|
||||
let line = line_buf.trim();
|
||||
if !line.is_empty() {
|
||||
run(line).unwrap();
|
||||
match run(line) {
|
||||
Ok(v) => println!("{:?}", v),
|
||||
Err(e) => println!("{}", e),
|
||||
}
|
||||
line_buf.clear();
|
||||
}
|
||||
}
|
||||
|
@ -36,18 +33,6 @@ fn run_repl() {
|
|||
}
|
||||
}
|
||||
|
||||
fn run(code: &str) -> Result<(), Vec<lexer::LexingError>> {
|
||||
let mut lexer = Lexer::new(code, None);
|
||||
let tokens = lexer.scan_tokens()?;
|
||||
println!("{:?}", tokens);
|
||||
let mut parser = crate::ast::parser::Parser::new(tokens.into_iter());
|
||||
let expressions = parser.scan_expressions().unwrap();
|
||||
println!("{:?}", expressions);
|
||||
println!("{:?}", expressions[0].interpret());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
dotenv::dotenv().ok();
|
||||
color_eyre::install().expect("Failed to install color-eyre");
|
||||
|
|
Loading…
Reference in a new issue