replace thiserror with quick_error
This commit is contained in:
28
Cargo.lock
generated
28
Cargo.lock
generated
@@ -404,6 +404,12 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-error"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.37"
|
version = "1.0.37"
|
||||||
@@ -565,8 +571,8 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
|
"quick-error",
|
||||||
"rust_decimal",
|
"rust_decimal",
|
||||||
"thiserror",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -603,26 +609,6 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "2.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "2.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.87",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
|
|||||||
@@ -3,13 +3,10 @@ name = "stationlang"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
panic = "unwind"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "^4.5", features = ["derive"] }
|
clap = { version = "^4.5", features = ["derive"] }
|
||||||
|
quick-error = "2.0.1"
|
||||||
rust_decimal = "1.36.0"
|
rust_decimal = "1.36.0"
|
||||||
thiserror = { version = "^2.0" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = { version = "^1.0", features = ["backtrace"] }
|
anyhow = { version = "^1.0", features = ["backtrace"] }
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly"
|
channel = "stable"
|
||||||
components = ["rustfmt", "clippy"]
|
components = ["rustfmt", "clippy"]
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::parser::tree_node::*;
|
use crate::parser::tree_node::*;
|
||||||
use crate::parser::Parser as ASTParser;
|
use crate::parser::Parser as ASTParser;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -9,14 +7,21 @@ use std::io::Write;
|
|||||||
/// Represents the return keyword. Used as a variable name for the register.
|
/// Represents the return keyword. Used as a variable name for the register.
|
||||||
const RETURN: &'static str = "ret";
|
const RETURN: &'static str = "ret";
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
quick_error! {
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum CompileError {
|
pub enum CompileError {
|
||||||
#[error(transparent)]
|
ParseError(err: crate::parser::ParseError) {
|
||||||
ParseError(#[from] crate::parser::ParseError),
|
from()
|
||||||
#[error("A fatal error has occurred with the compiler. Scope could not be found.")]
|
display("Parse error: {}", err)
|
||||||
ScopeError,
|
}
|
||||||
#[error(transparent)]
|
ScopeError {
|
||||||
WriteError(#[from] std::io::Error),
|
display("A fatal error has occurred with the compiler. Scope could not be found.")
|
||||||
|
}
|
||||||
|
WriteError(err: std::io::Error) {
|
||||||
|
from()
|
||||||
|
display("Write error: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Compiler<'a> {
|
pub struct Compiler<'a> {
|
||||||
|
|||||||
31
src/main.rs
31
src/main.rs
@@ -1,4 +1,5 @@
|
|||||||
#![feature(error_generic_member_access)]
|
#[macro_use]
|
||||||
|
extern crate quick_error;
|
||||||
|
|
||||||
mod compiler;
|
mod compiler;
|
||||||
mod parser;
|
mod parser;
|
||||||
@@ -21,16 +22,26 @@ macro_rules! boxed {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
quick_error! {
|
||||||
|
#[derive(Debug)]
|
||||||
enum StationlangError {
|
enum StationlangError {
|
||||||
#[error(transparent)]
|
TokenizerError(err: TokenizerError) {
|
||||||
TokenizerError(#[from] TokenizerError),
|
from()
|
||||||
#[error(transparent)]
|
display("Tokenizer error: {}", err)
|
||||||
ParserError(#[from] parser::ParseError),
|
}
|
||||||
#[error(transparent)]
|
ParserError(err: parser::ParseError) {
|
||||||
CompileError(#[from] compiler::CompileError),
|
from()
|
||||||
#[error(transparent)]
|
display("Parser error: {}", err)
|
||||||
IoError(#[from] std::io::Error),
|
}
|
||||||
|
CompileError(err: compiler::CompileError) {
|
||||||
|
from()
|
||||||
|
display("Compile error: {}", err)
|
||||||
|
}
|
||||||
|
IoError(err: std::io::Error) {
|
||||||
|
from()
|
||||||
|
display("IO error: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
|||||||
@@ -8,31 +8,33 @@ use crate::{
|
|||||||
Tokenizer, TokenizerBuffer, TokenizerError,
|
Tokenizer, TokenizerBuffer, TokenizerError,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::io::SeekFrom;
|
||||||
backtrace::{self, Backtrace},
|
|
||||||
io::SeekFrom,
|
|
||||||
};
|
|
||||||
use thiserror::Error;
|
|
||||||
use tree_node::*;
|
use tree_node::*;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
quick_error! {
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
#[error(transparent)]
|
TokenizerError(err: TokenizerError) {
|
||||||
TokenizerError(#[from] TokenizerError),
|
from()
|
||||||
#[error("Unexpected token\n\nLine: {0}, Column: {1}\nToken: {2}\n", token.line, token.column, token.token_type)]
|
display("Tokenizer Error: {}", err)
|
||||||
UnexpectedToken {
|
source(err)
|
||||||
token: Token,
|
}
|
||||||
#[backtrace]
|
UnexpectedToken(token: Token) {
|
||||||
backtrace: std::backtrace::Backtrace,
|
display("Unexpected token: {:?}", token)
|
||||||
},
|
}
|
||||||
#[error("Duplicated Identifer\n\nLine: {0}, Column: {1}\nToken: {2}\n", token.line, token.column, token.token_type)]
|
DuplicateIdentifier(token: Token) {
|
||||||
DuplicateIdentifier { token: Token },
|
display("Duplicate identifier: {:?}", token)
|
||||||
#[error("Invalid Syntax\n\nLine: {0}, Column: {1}\nReason: {reason}", token.line, token.column)]
|
}
|
||||||
InvalidSyntax { token: Token, reason: String },
|
InvalidSyntax(token: Token, reason: String) {
|
||||||
#[error("This keyword is not yet implemented\n\nLine: {0}, Column: {1}\nToken: {2}\n", token.line, token.column, token.token_type)]
|
display("Invalid syntax: {:?}, Reason: {}", token, reason)
|
||||||
UnsupportedKeyword { token: Token },
|
}
|
||||||
#[error("Unexpected EOF")]
|
UnsupportedKeyword(token: Token) {
|
||||||
UnexpectedEOF,
|
display("Unsupported keyword: {:?}", token)
|
||||||
|
}
|
||||||
|
UnexpectedEOF {
|
||||||
|
display("Unexpected EOF")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! self_matches_peek {
|
macro_rules! self_matches_peek {
|
||||||
@@ -57,22 +59,14 @@ macro_rules! extract_token_data {
|
|||||||
($token:ident, $pattern:pat, $extraction:expr) => {
|
($token:ident, $pattern:pat, $extraction:expr) => {
|
||||||
match $token.token_type {
|
match $token.token_type {
|
||||||
$pattern => $extraction,
|
$pattern => $extraction,
|
||||||
_ => {
|
_ => return Err(ParseError::UnexpectedToken($token.clone())),
|
||||||
return Err(ParseError::UnexpectedToken {
|
|
||||||
token: $token.clone(),
|
|
||||||
backtrace: std::backtrace::Backtrace::capture(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($token:expr, $pattern:pat, $extraction:expr) => {
|
($token:expr, $pattern:pat, $extraction:expr) => {
|
||||||
match $token.token_type {
|
match $token.token_type {
|
||||||
$pattern => $extraction,
|
$pattern => $extraction,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken($token.clone()));
|
||||||
token: $token.clone(),
|
|
||||||
backtrace: std::backtrace::Backtrace::capture(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -180,9 +174,7 @@ impl Parser {
|
|||||||
Keyword::Else
|
Keyword::Else
|
||||||
) =>
|
) =>
|
||||||
{
|
{
|
||||||
return Err(ParseError::UnsupportedKeyword {
|
return Err(ParseError::UnsupportedKeyword(current_token.clone()))
|
||||||
token: current_token.clone(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// match declarations with a `let` keyword
|
// match declarations with a `let` keyword
|
||||||
@@ -218,10 +210,7 @@ impl Parser {
|
|||||||
TokenType::Symbol(Symbol::LParen) => Expression::PriorityExpression(self.priority()?),
|
TokenType::Symbol(Symbol::LParen) => Expression::PriorityExpression(self.priority()?),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: std::backtrace::Backtrace::capture(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -265,10 +254,7 @@ impl Parser {
|
|||||||
{
|
{
|
||||||
self.invocation().map(Expression::InvocationExpression)
|
self.invocation().map(Expression::InvocationExpression)
|
||||||
}
|
}
|
||||||
_ => Err(ParseError::UnexpectedToken {
|
_ => Err(ParseError::UnexpectedToken(current_token.clone())),
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: std::backtrace::Backtrace::capture(),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,10 +267,7 @@ impl Parser {
|
|||||||
|
|
||||||
let current_token = token_from_option!(self.get_next()?).clone();
|
let current_token = token_from_option!(self.get_next()?).clone();
|
||||||
if !token_matches!(current_token, TokenType::Symbol(Symbol::Assign)) {
|
if !token_matches!(current_token, TokenType::Symbol(Symbol::Assign)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
self.assign_next()?;
|
self.assign_next()?;
|
||||||
|
|
||||||
@@ -313,10 +296,7 @@ impl Parser {
|
|||||||
| Expression::Negation(_) // -1 + 2
|
| Expression::Negation(_) // -1 + 2
|
||||||
=> {}
|
=> {}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ParseError::InvalidSyntax {
|
return Err(ParseError::InvalidSyntax(current_token.clone(), String::from("Invalid expression for binary operation")))
|
||||||
token: current_token.clone(),
|
|
||||||
reason: "Invalid expression for binary operation".to_owned(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,10 +318,10 @@ impl Parser {
|
|||||||
|
|
||||||
// validate the vectors and make sure operators.len() == expressions.len() - 1
|
// validate the vectors and make sure operators.len() == expressions.len() - 1
|
||||||
if operators.len() != expressions.len() - 1 {
|
if operators.len() != expressions.len() - 1 {
|
||||||
return Err(ParseError::InvalidSyntax {
|
return Err(ParseError::InvalidSyntax(
|
||||||
token: current_token.clone(),
|
current_token.clone(),
|
||||||
reason: "Invalid number of operators".to_owned(),
|
String::from("Invalid number of operators"),
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every time we find a valid operator, we pop 2 off the expressions and add one back.
|
// Every time we find a valid operator, we pop 2 off the expressions and add one back.
|
||||||
@@ -437,10 +417,10 @@ impl Parser {
|
|||||||
|
|
||||||
// Ensure there is only one expression left in the expressions vector, and no operators left
|
// Ensure there is only one expression left in the expressions vector, and no operators left
|
||||||
if expressions.len() != 1 || !operators.is_empty() {
|
if expressions.len() != 1 || !operators.is_empty() {
|
||||||
return Err(ParseError::InvalidSyntax {
|
return Err(ParseError::InvalidSyntax(
|
||||||
token: current_token.clone(),
|
current_token.clone(),
|
||||||
reason: "Invalid number of operators".to_owned(),
|
String::from("Invalid number of operators"),
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edge case. If the current token is a semi-colon, RParen, we need to set current token to the previous token
|
// Edge case. If the current token is a semi-colon, RParen, we need to set current token to the previous token
|
||||||
@@ -461,10 +441,7 @@ impl Parser {
|
|||||||
fn priority(&mut self) -> Result<Box<Expression>, ParseError> {
|
fn priority(&mut self) -> Result<Box<Expression>, ParseError> {
|
||||||
let current_token = token_from_option!(self.current_token);
|
let current_token = token_from_option!(self.current_token);
|
||||||
if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) {
|
if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: std::backtrace::Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assign_next()?;
|
self.assign_next()?;
|
||||||
@@ -472,10 +449,7 @@ impl Parser {
|
|||||||
|
|
||||||
let current_token = token_from_option!(self.get_next()?);
|
let current_token = token_from_option!(self.get_next()?);
|
||||||
if !token_matches!(current_token, TokenType::Symbol(Symbol::RParen)) {
|
if !token_matches!(current_token, TokenType::Symbol(Symbol::RParen)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: std::backtrace::Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(boxed!(expression))
|
Ok(boxed!(expression))
|
||||||
@@ -491,10 +465,7 @@ impl Parser {
|
|||||||
// Ensure the next token is a left parenthesis
|
// Ensure the next token is a left parenthesis
|
||||||
let current_token = token_from_option!(self.get_next()?);
|
let current_token = token_from_option!(self.get_next()?);
|
||||||
if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) {
|
if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: std::backtrace::Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut arguments = Vec::<Expression>::new();
|
let mut arguments = Vec::<Expression>::new();
|
||||||
@@ -508,10 +479,10 @@ impl Parser {
|
|||||||
let expression = self.expression()?.ok_or(ParseError::UnexpectedEOF)?;
|
let expression = self.expression()?.ok_or(ParseError::UnexpectedEOF)?;
|
||||||
|
|
||||||
if let Expression::BlockExpression(_) = expression {
|
if let Expression::BlockExpression(_) = expression {
|
||||||
return Err(ParseError::InvalidSyntax {
|
return Err(ParseError::InvalidSyntax(
|
||||||
token: current_token,
|
current_token,
|
||||||
reason: "Block expressions are not allowed in function invocations".to_owned(),
|
String::from("Block expressions are not allowed in function invocations"),
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments.push(expression);
|
arguments.push(expression);
|
||||||
@@ -520,10 +491,9 @@ impl Parser {
|
|||||||
if !self_matches_peek!(self, TokenType::Symbol(Symbol::Comma))
|
if !self_matches_peek!(self, TokenType::Symbol(Symbol::Comma))
|
||||||
&& !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen))
|
&& !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen))
|
||||||
{
|
{
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(
|
||||||
token: token_from_option!(self.get_next()?).clone(),
|
token_from_option!(self.get_next()?).clone(),
|
||||||
backtrace: backtrace::Backtrace::capture(),
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// edge case: if the next token is not a right parenthesis, increment the current token
|
// edge case: if the next token is not a right parenthesis, increment the current token
|
||||||
@@ -547,10 +517,7 @@ impl Parser {
|
|||||||
|
|
||||||
// sanity check: make sure the current token is a left brace
|
// sanity check: make sure the current token is a left brace
|
||||||
if !token_matches!(current_token, TokenType::Symbol(Symbol::LBrace)) {
|
if !token_matches!(current_token, TokenType::Symbol(Symbol::LBrace)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: backtrace::Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while !self_matches_peek!(
|
while !self_matches_peek!(
|
||||||
@@ -580,10 +547,7 @@ impl Parser {
|
|||||||
fn declaration(&mut self) -> Result<Expression, ParseError> {
|
fn declaration(&mut self) -> Result<Expression, ParseError> {
|
||||||
let current_token = token_from_option!(self.current_token);
|
let current_token = token_from_option!(self.current_token);
|
||||||
if !self_matches_current!(self, TokenType::Keyword(Keyword::Let)) {
|
if !self_matches_current!(self, TokenType::Keyword(Keyword::Let)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: backtrace::Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
let identifier = extract_token_data!(
|
let identifier = extract_token_data!(
|
||||||
token_from_option!(self.get_next()?),
|
token_from_option!(self.get_next()?),
|
||||||
@@ -594,10 +558,7 @@ impl Parser {
|
|||||||
let current_token = token_from_option!(self.get_next()?).clone();
|
let current_token = token_from_option!(self.get_next()?).clone();
|
||||||
|
|
||||||
if !token_matches!(current_token, TokenType::Symbol(Symbol::Assign)) {
|
if !token_matches!(current_token, TokenType::Symbol(Symbol::Assign)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token,
|
|
||||||
backtrace: backtrace::Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assign_next()?;
|
self.assign_next()?;
|
||||||
@@ -606,10 +567,7 @@ impl Parser {
|
|||||||
// make sure the next token is a semi-colon
|
// make sure the next token is a semi-colon
|
||||||
let current_token = token_from_option!(self.get_next()?);
|
let current_token = token_from_option!(self.get_next()?);
|
||||||
if !token_matches!(current_token, TokenType::Symbol(Symbol::Semicolon)) {
|
if !token_matches!(current_token, TokenType::Symbol(Symbol::Semicolon)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: backtrace::Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Expression::DeclarationExpression(
|
Ok(Expression::DeclarationExpression(
|
||||||
@@ -623,12 +581,7 @@ impl Parser {
|
|||||||
let literal = match current_token.token_type {
|
let literal = match current_token.token_type {
|
||||||
TokenType::Number(ref num) => Literal::Number(num.clone()),
|
TokenType::Number(ref num) => Literal::Number(num.clone()),
|
||||||
TokenType::String(ref string) => Literal::String(string.clone()),
|
TokenType::String(ref string) => Literal::String(string.clone()),
|
||||||
_ => {
|
_ => return Err(ParseError::UnexpectedToken(current_token.clone())),
|
||||||
return Err(ParseError::UnexpectedToken {
|
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: backtrace::Backtrace::capture(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(literal)
|
Ok(literal)
|
||||||
@@ -638,10 +591,7 @@ impl Parser {
|
|||||||
let current_token = token_from_option!(self.current_token);
|
let current_token = token_from_option!(self.current_token);
|
||||||
// Sanify check that the current token is a `fn` keyword
|
// Sanify check that the current token is a `fn` keyword
|
||||||
if !self_matches_current!(self, TokenType::Keyword(Keyword::Fn)) {
|
if !self_matches_current!(self, TokenType::Keyword(Keyword::Fn)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let fn_ident = extract_token_data!(
|
let fn_ident = extract_token_data!(
|
||||||
@@ -653,10 +603,7 @@ impl Parser {
|
|||||||
// make sure next token is a left parenthesis
|
// make sure next token is a left parenthesis
|
||||||
let current_token = token_from_option!(self.get_next()?);
|
let current_token = token_from_option!(self.get_next()?);
|
||||||
if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) {
|
if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: Backtrace::capture(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut arguments = Vec::<String>::new();
|
let mut arguments = Vec::<String>::new();
|
||||||
@@ -672,9 +619,7 @@ impl Parser {
|
|||||||
extract_token_data!(current_token, TokenType::Identifier(ref id), id.clone());
|
extract_token_data!(current_token, TokenType::Identifier(ref id), id.clone());
|
||||||
|
|
||||||
if arguments.contains(&argument) {
|
if arguments.contains(&argument) {
|
||||||
return Err(ParseError::DuplicateIdentifier {
|
return Err(ParseError::DuplicateIdentifier(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments.push(argument);
|
arguments.push(argument);
|
||||||
@@ -683,10 +628,9 @@ impl Parser {
|
|||||||
if !self_matches_peek!(self, TokenType::Symbol(Symbol::Comma))
|
if !self_matches_peek!(self, TokenType::Symbol(Symbol::Comma))
|
||||||
&& !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen))
|
&& !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen))
|
||||||
{
|
{
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(
|
||||||
token: token_from_option!(self.get_next()?).clone(),
|
token_from_option!(self.get_next()?).clone(),
|
||||||
backtrace: Backtrace::capture(),
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// edge case: if the next token is not a right parenthesis, increment the current token
|
// edge case: if the next token is not a right parenthesis, increment the current token
|
||||||
@@ -701,10 +645,7 @@ impl Parser {
|
|||||||
// make sure the next token is a left brace
|
// make sure the next token is a left brace
|
||||||
let current_token = token_from_option!(self.get_next()?);
|
let current_token = token_from_option!(self.get_next()?);
|
||||||
if !token_matches!(current_token, TokenType::Symbol(Symbol::LBrace)) {
|
if !token_matches!(current_token, TokenType::Symbol(Symbol::LBrace)) {
|
||||||
return Err(ParseError::UnexpectedToken {
|
return Err(ParseError::UnexpectedToken(current_token.clone()));
|
||||||
token: current_token.clone(),
|
|
||||||
backtrace: Backtrace::capture(),
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(FunctionExpression {
|
Ok(FunctionExpression {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
pub mod token;
|
pub mod token;
|
||||||
|
|
||||||
|
use crate::boxed;
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
@@ -7,23 +8,31 @@ use std::{
|
|||||||
io::{BufReader, Cursor, Read, Seek, SeekFrom},
|
io::{BufReader, Cursor, Read, Seek, SeekFrom},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
|
||||||
use token::{Keyword, Number, Symbol, Token, TokenType};
|
use token::{Keyword, Number, Symbol, Token, TokenType};
|
||||||
|
|
||||||
use crate::boxed;
|
quick_error! {
|
||||||
|
#[derive(Debug)]
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum TokenizerError {
|
pub enum TokenizerError {
|
||||||
#[error("IO Error: {0}")]
|
IOError(err: std::io::Error) {
|
||||||
IOError(#[from] std::io::Error),
|
from()
|
||||||
#[error("Number Parse Error \"{0}\"\nLine: {1}, Column: {2}")]
|
display("IO Error: {}", err)
|
||||||
NumberParseError(std::num::ParseIntError, usize, usize),
|
source(err)
|
||||||
#[error("Decimal Parse Error \"{0}\"\nLine: {1}, Column: {2}")]
|
}
|
||||||
DecimalParseError(rust_decimal::Error, usize, usize),
|
NumberParseError(err: std::num::ParseIntError, line: usize, column: usize) {
|
||||||
#[error("Unknown Symbol \"{0}\"\nLine: {1}, Column: {2}")]
|
display("Number Parse Error: {}\nLine: {}, Column: {}", err, line, column)
|
||||||
UnknownSymbolError(char, usize, usize),
|
source(err)
|
||||||
#[error("Unknown Keyword or Identifier \"{0}\"\nLine: {1}, Column: {2}")]
|
}
|
||||||
UnknownKeywordOrIdentifierError(String, usize, usize),
|
DecimalParseError(err: rust_decimal::Error, line: usize, column: usize) {
|
||||||
|
display("Decimal Parse Error: {}\nLine: {}, Column: {}", err, line, column)
|
||||||
|
source(err)
|
||||||
|
}
|
||||||
|
UnknownSymbolError(char: char, line: usize, column: usize) {
|
||||||
|
display("Unknown Symbol: {}\nLine: {}, Column: {}", char, line, column)
|
||||||
|
}
|
||||||
|
UnknownKeywordOrIdentifierError(val: String, line: usize, column: usize) {
|
||||||
|
display("Unknown Keyword or Identifier: {}\nLine: {}, Column: {}", val, line, column)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Tokenize: Read + Seek {}
|
pub trait Tokenize: Read + Seek {}
|
||||||
|
|||||||
Reference in New Issue
Block a user