mirror of
https://github.com/rm-dr/daisy
synced 2025-08-02 01:34:50 -07:00
Added formattedtext and better error class
This commit is contained in:
@ -1,14 +1,10 @@
|
||||
mod stage;
|
||||
|
||||
mod token;
|
||||
mod parsererror;
|
||||
mod expression;
|
||||
mod linelocation;
|
||||
|
||||
use self::{
|
||||
token::Token,
|
||||
parsererror::ParserError,
|
||||
};
|
||||
use self::token::Token;
|
||||
|
||||
pub use self::{
|
||||
expression::Expression,
|
||||
@ -19,11 +15,11 @@ pub use self::{
|
||||
};
|
||||
|
||||
use crate::context::Context;
|
||||
|
||||
use crate::errors::DaisyError;
|
||||
|
||||
pub fn parse(
|
||||
s: &String, context: &Context
|
||||
) -> Result<Expression, (LineLocation, ParserError)> {
|
||||
) -> Result<Expression, (LineLocation, DaisyError)> {
|
||||
|
||||
let expressions = stage::tokenize(s);
|
||||
let (_, expressions) = stage::find_subs(expressions);
|
||||
@ -33,7 +29,7 @@ pub fn parse(
|
||||
return Ok(g);
|
||||
}
|
||||
|
||||
pub fn parse_no_context(s: &String) -> Result<Expression, (LineLocation, ParserError)> {
|
||||
pub fn parse_no_context(s: &String) -> Result<Expression, (LineLocation, DaisyError)> {
|
||||
parse(s, &Context::new())
|
||||
}
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
/// Types of parser errors.
|
||||
/// If we cannot parse a string, one of these is returned.
|
||||
#[derive(Debug)]
|
||||
pub enum ParserError {
|
||||
//MissingCloseParen,
|
||||
ExtraCloseParen,
|
||||
EmptyGroup,
|
||||
Syntax,
|
||||
BadNumber
|
||||
}
|
||||
|
||||
impl ToString for ParserError {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
//ParserError::MissingCloseParen => {
|
||||
// String::from("This group is never closed")
|
||||
//},
|
||||
ParserError::ExtraCloseParen => {
|
||||
String::from("Extra close parenthesis")
|
||||
},
|
||||
ParserError::EmptyGroup => {
|
||||
String::from("Groups can't be empty")
|
||||
},
|
||||
ParserError::Syntax => {
|
||||
String::from("Syntax")
|
||||
},
|
||||
ParserError::BadNumber => {
|
||||
String::from("Invalid number")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,14 +3,15 @@ use std::collections::VecDeque;
|
||||
use super::super::{
|
||||
Token,
|
||||
LineLocation,
|
||||
ParserError,
|
||||
Operator
|
||||
};
|
||||
|
||||
use crate::errors::DaisyError;
|
||||
|
||||
|
||||
fn lookback_signs(
|
||||
g: &mut VecDeque<Token>
|
||||
) -> Result<(), (LineLocation, ParserError)> {
|
||||
) -> Result<(), (LineLocation, DaisyError)> {
|
||||
|
||||
// Convert `-` operators to `neg` operators
|
||||
// Delete `+`s that mean "positive" instead of "add"
|
||||
@ -99,7 +100,7 @@ fn lookback_signs(
|
||||
// Inserts implicit operators
|
||||
fn lookback(
|
||||
g: &mut VecDeque<Token>
|
||||
) -> Result<(), (LineLocation, ParserError)> {
|
||||
) -> Result<(), (LineLocation, DaisyError)> {
|
||||
|
||||
lookback_signs(g)?;
|
||||
|
||||
@ -178,7 +179,7 @@ fn lookback(
|
||||
// The following are syntax errors
|
||||
(Token::Quantity(la,_), Token::Quantity(lb,_))
|
||||
=> {
|
||||
return Err((*la + *lb, ParserError::Syntax));
|
||||
return Err((*la + *lb, DaisyError::Syntax));
|
||||
},
|
||||
_ => {g.insert(i-1, b); g.insert(i-1, a);}
|
||||
}
|
||||
@ -195,7 +196,7 @@ pub fn groupify(
|
||||
mut g: VecDeque<Token>
|
||||
) -> Result<
|
||||
Token,
|
||||
(LineLocation, ParserError)
|
||||
(LineLocation, DaisyError)
|
||||
> {
|
||||
|
||||
let last_linelocation: LineLocation = *g.back().unwrap().get_line_location();
|
||||
@ -220,8 +221,8 @@ pub fn groupify(
|
||||
Token::GroupEnd(l) => {
|
||||
let l = *l_now + l;
|
||||
|
||||
if i_level == 0 { return Err((l, ParserError::ExtraCloseParen)) }
|
||||
if v_now.len() == 0 { return Err((l, ParserError::EmptyGroup)) }
|
||||
if i_level == 0 { return Err((l, DaisyError::ExtraCloseParen)) }
|
||||
if v_now.len() == 0 { return Err((l, DaisyError::EmptyGroup)) }
|
||||
|
||||
i_level -= 1;
|
||||
|
||||
@ -243,7 +244,7 @@ pub fn groupify(
|
||||
// Error on missing parenthesis
|
||||
if levels.len() != 1 {
|
||||
let (l, _) = levels.pop().unwrap();
|
||||
return Err((l, ParserError::MissingCloseParen))
|
||||
return Err((l, DaisyError::MissingCloseParen))
|
||||
}
|
||||
*/
|
||||
|
||||
@ -252,7 +253,7 @@ pub fn groupify(
|
||||
let (l, mut v) = levels.pop().unwrap();
|
||||
let (_, v_now) = levels.last_mut().unwrap();
|
||||
|
||||
if v.len() == 0 { return Err((l, ParserError::EmptyGroup)) }
|
||||
if v.len() == 0 { return Err((l, DaisyError::EmptyGroup)) }
|
||||
lookback(&mut v)?;
|
||||
|
||||
v_now.push_back(Token::Group(l, v));
|
||||
|
@ -1,9 +1,9 @@
|
||||
use std::collections::VecDeque;
|
||||
use crate::context::Context;
|
||||
use crate::errors::DaisyError;
|
||||
|
||||
use super::super::{
|
||||
Token,
|
||||
ParserError,
|
||||
LineLocation,
|
||||
Expression,
|
||||
Operator
|
||||
@ -13,7 +13,7 @@ fn treeify_binary(
|
||||
i: usize,
|
||||
g_inner: &mut VecDeque<Token>,
|
||||
context: &Context
|
||||
) -> Result<bool, (LineLocation, ParserError)> {
|
||||
) -> Result<bool, (LineLocation, DaisyError)> {
|
||||
|
||||
let this: &Token = &g_inner[i];
|
||||
|
||||
@ -23,7 +23,7 @@ fn treeify_binary(
|
||||
Token::Operator(l, _) => l,
|
||||
_ => panic!()
|
||||
};
|
||||
return Err((*l, ParserError::Syntax)); // left argument is empty
|
||||
return Err((*l, DaisyError::Syntax)); // left argument is empty
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ fn treeify_binary(
|
||||
Token::Operator(l, _) => l,
|
||||
_ => panic!()
|
||||
};
|
||||
return Err((*l, ParserError::Syntax)); // Left argument is empty
|
||||
return Err((*l, DaisyError::Syntax)); // Left argument is empty
|
||||
}
|
||||
};
|
||||
|
||||
@ -47,7 +47,7 @@ fn treeify_binary(
|
||||
Token::Operator(l, _) => l,
|
||||
_ => panic!()
|
||||
};
|
||||
return Err((*l, ParserError::Syntax)); // right argument is empty
|
||||
return Err((*l, DaisyError::Syntax)); // right argument is empty
|
||||
}
|
||||
};
|
||||
|
||||
@ -57,7 +57,7 @@ fn treeify_binary(
|
||||
|
||||
if let Token::Operator(l, s) = left {
|
||||
let o = Operator::from_string(s);
|
||||
if o.is_none() { return Err((*l, ParserError::Syntax)); } // Bad string
|
||||
if o.is_none() { return Err((*l, DaisyError::Syntax)); } // Bad string
|
||||
let o = o.unwrap();
|
||||
|
||||
if {
|
||||
@ -67,13 +67,13 @@ fn treeify_binary(
|
||||
return Ok(false);
|
||||
} else {
|
||||
let tl = *this.get_line_location() + *l;
|
||||
return Err((tl, ParserError::Syntax)); // left argument isn't valid
|
||||
return Err((tl, DaisyError::Syntax)); // left argument isn't valid
|
||||
}
|
||||
}
|
||||
|
||||
if let Token::Operator(l, s) = right {
|
||||
let o = Operator::from_string(s);
|
||||
if o.is_none() { return Err((*l, ParserError::Syntax)); } // Bad string
|
||||
if o.is_none() { return Err((*l, DaisyError::Syntax)); } // Bad string
|
||||
let o = o.unwrap();
|
||||
|
||||
if {
|
||||
@ -83,7 +83,7 @@ fn treeify_binary(
|
||||
return Ok(false);
|
||||
} else {
|
||||
let tl = *this.get_line_location() + *l;
|
||||
return Err((tl, ParserError::Syntax)); // right argument isn't valid (two operators next to each other)
|
||||
return Err((tl, DaisyError::Syntax)); // right argument isn't valid (two operators next to each other)
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ fn treeify_binary(
|
||||
let this_op = {
|
||||
let Token::Operator(l, s) = this else {panic!()};
|
||||
let o = Operator::from_string(s);
|
||||
if o.is_none() { return Err((*l, ParserError::Syntax)); } // bad operator string
|
||||
if o.is_none() { return Err((*l, DaisyError::Syntax)); } // bad operator string
|
||||
o.unwrap()
|
||||
};
|
||||
|
||||
@ -100,14 +100,14 @@ fn treeify_binary(
|
||||
let left_op = if i > 1 {
|
||||
let Token::Operator(l, s) = &g_inner[i-2] else {panic!()};
|
||||
let o = Operator::from_string(s);
|
||||
if o.is_none() { return Err((*l, ParserError::Syntax)); } // Bad operator string
|
||||
if o.is_none() { return Err((*l, DaisyError::Syntax)); } // Bad operator string
|
||||
Some(o.unwrap())
|
||||
} else { None };
|
||||
|
||||
let right_op = if i < g_inner.len()-2 {
|
||||
let Token::Operator(l, s) = &g_inner[i+2] else {panic!()};
|
||||
let o = Operator::from_string(s);
|
||||
if o.is_none() { return Err((*l, ParserError::Syntax)); } // Bad operator string
|
||||
if o.is_none() { return Err((*l, DaisyError::Syntax)); } // Bad operator string
|
||||
Some(o.unwrap())
|
||||
} else { None };
|
||||
|
||||
@ -159,7 +159,7 @@ fn treeify_unary(
|
||||
g_inner: &mut VecDeque<Token>,
|
||||
left_associative: bool,
|
||||
context: &Context
|
||||
) -> Result<bool, (LineLocation, ParserError)> {
|
||||
) -> Result<bool, (LineLocation, DaisyError)> {
|
||||
|
||||
let this: &Token = &g_inner[i];
|
||||
let next: &Token;
|
||||
@ -172,7 +172,7 @@ fn treeify_unary(
|
||||
Token::Operator(l, _) => l,
|
||||
_ => panic!()
|
||||
};
|
||||
return Err((*l, ParserError::Syntax)); // argument is missing
|
||||
return Err((*l, DaisyError::Syntax)); // argument is missing
|
||||
}
|
||||
};
|
||||
} else {
|
||||
@ -184,7 +184,7 @@ fn treeify_unary(
|
||||
Token::Operator(l, _) => l,
|
||||
_ => panic!()
|
||||
};
|
||||
return Err((*l, ParserError::Syntax)); // argument is missing
|
||||
return Err((*l, DaisyError::Syntax)); // argument is missing
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -204,7 +204,7 @@ fn treeify_unary(
|
||||
// Previous operator is invalid
|
||||
return Err((
|
||||
*this.get_line_location(),
|
||||
ParserError::Syntax
|
||||
DaisyError::Syntax
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -212,14 +212,14 @@ fn treeify_unary(
|
||||
if let Token::Operator(l, _) = next {
|
||||
let tl = *this.get_line_location() + *l;
|
||||
// Argument is invalid
|
||||
return Err((tl, ParserError::Syntax));
|
||||
return Err((tl, DaisyError::Syntax));
|
||||
} else {
|
||||
|
||||
// This operator
|
||||
let this_op = {
|
||||
let Token::Operator(l, s) = this else {panic!()};
|
||||
let o = Operator::from_string(s);
|
||||
if o.is_none() { return Err((*l, ParserError::Syntax)); } // Bad string
|
||||
if o.is_none() { return Err((*l, DaisyError::Syntax)); } // Bad string
|
||||
o.unwrap()
|
||||
};
|
||||
|
||||
@ -228,14 +228,14 @@ fn treeify_unary(
|
||||
if i > 1 {
|
||||
let Token::Operator(l, s) = &g_inner[i-2] else {panic!()};
|
||||
let o = Operator::from_string(s);
|
||||
if o.is_none() { return Err((*l, ParserError::Syntax)); } // Bad string
|
||||
if o.is_none() { return Err((*l, DaisyError::Syntax)); } // Bad string
|
||||
Some(o.unwrap())
|
||||
} else { None }
|
||||
} else {
|
||||
if i < g_inner.len()-2 {
|
||||
let Token::Operator(l, s) = &g_inner[i+2] else {panic!()};
|
||||
let o = Operator::from_string(s);
|
||||
if o.is_none() { return Err((*l, ParserError::Syntax)); } // Bad string
|
||||
if o.is_none() { return Err((*l, DaisyError::Syntax)); } // Bad string
|
||||
Some(o.unwrap())
|
||||
} else { None }
|
||||
};
|
||||
@ -285,7 +285,7 @@ fn treeify_unary(
|
||||
pub fn treeify(
|
||||
mut g: Token,
|
||||
context: &Context
|
||||
) -> Result<Expression, (LineLocation, ParserError)> {
|
||||
) -> Result<Expression, (LineLocation, DaisyError)> {
|
||||
let (l, g_inner): (LineLocation, &mut VecDeque<Token>) = match g {
|
||||
Token::Group(l, ref mut x) => (l, x),
|
||||
_ => panic!()
|
||||
@ -293,7 +293,7 @@ pub fn treeify(
|
||||
|
||||
if g_inner.len() == 0 {
|
||||
// This shouldn't ever happen.
|
||||
return Err((l, ParserError::EmptyGroup));
|
||||
return Err((l, DaisyError::EmptyGroup));
|
||||
}
|
||||
|
||||
let mut left_associative = true;
|
||||
@ -315,7 +315,7 @@ pub fn treeify(
|
||||
let this_op = match &g_inner[i] {
|
||||
Token::Operator(l, s) => {
|
||||
let o = Operator::from_string(&s);
|
||||
if o.is_none() { return Err((*l, ParserError::Syntax)); }
|
||||
if o.is_none() { return Err((*l, DaisyError::Syntax)); }
|
||||
o.unwrap()
|
||||
},
|
||||
_ => {
|
||||
@ -356,7 +356,7 @@ pub fn treeify(
|
||||
return match g {
|
||||
// Catch edge cases
|
||||
Token::Operator(l, _) => {
|
||||
Err((l, ParserError::Syntax))
|
||||
Err((l, DaisyError::Syntax))
|
||||
},
|
||||
Token::Group(_,_) => {
|
||||
treeify(g, context)
|
||||
|
@ -2,10 +2,10 @@ use std::collections::VecDeque;
|
||||
use crate::quantity::Unit;
|
||||
use crate::quantity::Quantity;
|
||||
use crate::context::Context;
|
||||
use crate::errors::DaisyError;
|
||||
|
||||
use super::{
|
||||
LineLocation,
|
||||
ParserError,
|
||||
Expression,
|
||||
Constant
|
||||
};
|
||||
@ -57,7 +57,7 @@ impl Token {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_expression(self, context: &Context) -> Result<Expression, (LineLocation, ParserError)>{
|
||||
pub fn to_expression(self, context: &Context) -> Result<Expression, (LineLocation, DaisyError)>{
|
||||
match self {
|
||||
Token::Quantity(l, mut s) => {
|
||||
|
||||
@ -71,7 +71,7 @@ impl Token {
|
||||
let r = Quantity::new_rational_from_string(&s);
|
||||
|
||||
if r.is_none() {
|
||||
return Err((l, ParserError::BadNumber))
|
||||
return Err((l, DaisyError::BadNumber))
|
||||
}
|
||||
|
||||
return Ok(Expression::Quantity(l, r.unwrap()));
|
||||
|
Reference in New Issue
Block a user