2023-06-11 13:53:45 -07:00
|
|
|
use std::collections::VecDeque;
|
|
|
|
use crate::quantity::Unit;
|
|
|
|
use crate::quantity::Quantity;
|
2023-06-14 16:15:51 -07:00
|
|
|
use crate::context::Context;
|
2023-06-11 13:53:45 -07:00
|
|
|
|
|
|
|
use super::{
|
|
|
|
LineLocation,
|
|
|
|
ParserError,
|
2023-06-16 12:58:06 -07:00
|
|
|
Expression,
|
2023-06-11 13:53:45 -07:00
|
|
|
Constant
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2023-06-16 12:58:06 -07:00
|
|
|
pub enum Token {
|
2023-06-17 19:08:05 -07:00
|
|
|
Quantity(LineLocation, String),
|
|
|
|
Word(LineLocation, String),
|
|
|
|
Operator(LineLocation, String),
|
2023-06-11 13:53:45 -07:00
|
|
|
|
2023-06-17 19:08:05 -07:00
|
|
|
GroupStart(LineLocation),
|
|
|
|
GroupEnd(LineLocation),
|
|
|
|
Group(LineLocation, VecDeque<Token>),
|
2023-06-11 13:53:45 -07:00
|
|
|
|
2023-06-17 19:08:05 -07:00
|
|
|
// Never parsed from input, used to build a tree.
|
2023-06-16 12:58:06 -07:00
|
|
|
Container(Expression)
|
2023-06-11 13:53:45 -07:00
|
|
|
}
|
|
|
|
|
2023-06-16 12:58:06 -07:00
|
|
|
impl Token {
|
2023-06-11 13:53:45 -07:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn get_line_location(&self) -> &LineLocation {
|
|
|
|
match self {
|
2023-06-17 19:08:05 -07:00
|
|
|
Token::Quantity(l, _)
|
|
|
|
| Token::Word(l, _)
|
|
|
|
| Token::Operator(l, _)
|
|
|
|
| Token::GroupStart(l)
|
|
|
|
| Token::GroupEnd(l)
|
|
|
|
| Token::Group(l, _)
|
2023-06-11 13:53:45 -07:00
|
|
|
=> l,
|
|
|
|
|
2023-06-17 19:08:05 -07:00
|
|
|
Token::Container(_) => panic!("Containers do not have a linelocation.")
|
2023-06-11 13:53:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn get_mut_line_location(&mut self) -> &mut LineLocation {
|
|
|
|
match self {
|
2023-06-17 19:08:05 -07:00
|
|
|
Token::Quantity(l, _)
|
|
|
|
| Token::Word(l, _)
|
|
|
|
| Token::Operator(l, _)
|
|
|
|
| Token::GroupStart(l)
|
|
|
|
| Token::GroupEnd(l)
|
|
|
|
| Token::Group(l, _)
|
2023-06-11 13:53:45 -07:00
|
|
|
=> l,
|
|
|
|
|
2023-06-17 19:08:05 -07:00
|
|
|
Token::Container(_) => panic!("Containers do not have a linelocation.")
|
2023-06-11 13:53:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
2023-06-16 12:58:06 -07:00
|
|
|
pub fn to_expression(self, context: &Context) -> Result<Expression, (LineLocation, ParserError)>{
|
2023-06-11 13:53:45 -07:00
|
|
|
match self {
|
2023-06-17 19:08:05 -07:00
|
|
|
Token::Quantity(l, mut s) => {
|
2023-06-11 13:53:45 -07:00
|
|
|
|
|
|
|
// The length check here ensures that
|
|
|
|
// `.` is not parsed as `0.`
|
|
|
|
// That should be a syntax error.
|
|
|
|
if s.len() != 1 && &s[0..1] == "." {
|
|
|
|
s.insert(0, '0');
|
|
|
|
}
|
|
|
|
|
|
|
|
let r = Quantity::new_rational_from_string(&s);
|
2023-06-14 20:18:28 -07:00
|
|
|
|
2023-06-11 13:53:45 -07:00
|
|
|
if r.is_none() {
|
|
|
|
return Err((l, ParserError::BadNumber))
|
|
|
|
}
|
2023-06-14 20:18:28 -07:00
|
|
|
|
2023-06-16 12:58:06 -07:00
|
|
|
return Ok(Expression::Quantity(r.unwrap()));
|
2023-06-11 13:53:45 -07:00
|
|
|
},
|
|
|
|
|
2023-06-17 19:08:05 -07:00
|
|
|
Token::Word(_l, s) => {
|
2023-06-11 13:53:45 -07:00
|
|
|
|
2023-06-14 16:15:51 -07:00
|
|
|
let c = Constant::from_string(&s);
|
2023-06-16 12:58:06 -07:00
|
|
|
if c.is_some() { return Ok(Expression::Constant(c.unwrap())); }
|
2023-06-11 13:53:45 -07:00
|
|
|
|
|
|
|
let c = Unit::from_string(&s);
|
2023-06-16 12:58:06 -07:00
|
|
|
if c.is_some() { return Ok(Expression::Quantity(c.unwrap())); }
|
2023-06-11 13:53:45 -07:00
|
|
|
|
2023-06-14 16:15:51 -07:00
|
|
|
let c = context.get_variable(&s);
|
2023-06-16 12:58:06 -07:00
|
|
|
if c.is_some() { return Ok(Expression::Variable(s)); }
|
|
|
|
return Ok(Expression::Variable(s));
|
2023-06-11 13:53:45 -07:00
|
|
|
}
|
|
|
|
|
2023-06-16 12:58:06 -07:00
|
|
|
Token::Container(v) => { return Ok(v); }
|
2023-06-11 13:53:45 -07:00
|
|
|
|
2023-06-17 19:08:05 -07:00
|
|
|
Token::Operator(_,_)
|
|
|
|
| Token::GroupStart(_)
|
|
|
|
| Token::GroupEnd(_)
|
|
|
|
| Token::Group(_, _)
|
2023-06-11 13:53:45 -07:00
|
|
|
=> panic!()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|