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 {
|
impl std::fmt::Display for ASTParsingError {
|
||||||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
todo!()
|
match *self {
|
||||||
|
Self::UnmatchedBrace => write!(f, "Unmatched brace"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::error::Error for ASTParsingError {}
|
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 {
|
pub trait ErrorWithLocation: Error {
|
||||||
fn get_location(&self) -> Location;
|
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 super::types;
|
||||||
use crate::ast::astnode::{self, UnaryOperator};
|
use crate::ast::astnode::{self, UnaryOperator};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RuntimeError;
|
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 {
|
pub trait Interpret {
|
||||||
fn interpret(&self) -> Result<types::Value, RuntimeError>;
|
fn interpret(&self) -> Result<types::Value, RuntimeError>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,29 +2,7 @@ use crate::error::{ErrorWithLocation, Location, OwnedLocation};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
#[derive(Debug)]
|
pub type LexingError = crate::error::ErrorLocationWrapper<LexingErrorKind>;
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LexingErrorKind {
|
pub enum LexingErrorKind {
|
||||||
|
|
|
@ -68,6 +68,10 @@ impl<'a, 'b> Lexer<'a, 'b> {
|
||||||
self.get_token(token_type)
|
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>> {
|
fn scan_token(&mut self) -> Option<Result<Token<'b>, LexingError>> {
|
||||||
Some(Ok(match self.source_iter.next()? {
|
Some(Ok(match self.source_iter.next()? {
|
||||||
'(' => self.get_token(token::TokenType::LeftParen),
|
'(' => self.get_token(token::TokenType::LeftParen),
|
||||||
|
@ -103,11 +107,8 @@ impl<'a, 'b> Lexer<'a, 'b> {
|
||||||
),
|
),
|
||||||
'"' => {
|
'"' => {
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
let unmatched_char_error = Some(Err(LexingError {
|
let unmatched_char_error =
|
||||||
kind: LexingErrorKind::UnmatchedQuote,
|
Some(Err(self.get_error(LexingErrorKind::UnmatchedQuote)));
|
||||||
location: self.source_iter.get_location(self.file).into(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let next_char = self.source_iter.next();
|
let next_char = self.source_iter.next();
|
||||||
match next_char {
|
match next_char {
|
||||||
|
@ -156,12 +157,7 @@ impl<'a, 'b> Lexer<'a, 'b> {
|
||||||
}
|
}
|
||||||
// Ignore whitespace
|
// Ignore whitespace
|
||||||
' ' | '\r' | '\t' | '\n' => return None,
|
' ' | '\r' | '\t' | '\n' => return None,
|
||||||
c => {
|
c => return Some(Err(self.get_error(LexingErrorKind::UnexpectedCharacter(c)))),
|
||||||
return Some(Err(LexingError {
|
|
||||||
location: self.source_iter.get_location(self.file).into(),
|
|
||||||
kind: 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;
|
use crftng_intrprtrs::run;
|
||||||
mod error;
|
|
||||||
mod interpreter;
|
|
||||||
mod lexer;
|
|
||||||
|
|
||||||
use interpreter::ast_walker::Interpret;
|
|
||||||
use lexer::Lexer;
|
|
||||||
use std::{fs, io, path};
|
use std::{fs, io, path};
|
||||||
use tracing::Level;
|
use tracing::Level;
|
||||||
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
||||||
|
@ -27,7 +21,10 @@ fn run_repl() {
|
||||||
|
|
||||||
let line = line_buf.trim();
|
let line = line_buf.trim();
|
||||||
if !line.is_empty() {
|
if !line.is_empty() {
|
||||||
run(line).unwrap();
|
match run(line) {
|
||||||
|
Ok(v) => println!("{:?}", v),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
line_buf.clear();
|
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() {
|
fn main() {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
color_eyre::install().expect("Failed to install color-eyre");
|
color_eyre::install().expect("Failed to install color-eyre");
|
||||||
|
|
Loading…
Reference in a new issue