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,
|
|
|
|
Token,
|
|
|
|
Constant
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum PreToken {
|
|
|
|
PreQuantity(LineLocation, String),
|
|
|
|
PreWord(LineLocation, String),
|
|
|
|
PreOperator(LineLocation, String),
|
|
|
|
|
|
|
|
PreGroupStart(LineLocation),
|
|
|
|
PreGroupEnd(LineLocation),
|
|
|
|
PreGroup(LineLocation, VecDeque<PreToken>),
|
|
|
|
|
|
|
|
Container(Token)
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PreToken {
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn get_line_location(&self) -> &LineLocation {
|
|
|
|
match self {
|
|
|
|
PreToken::PreQuantity(l, _)
|
|
|
|
| PreToken::PreWord(l, _)
|
|
|
|
| PreToken::PreOperator(l, _)
|
|
|
|
| PreToken::PreGroupStart(l)
|
|
|
|
| PreToken::PreGroupEnd(l)
|
|
|
|
| PreToken::PreGroup(l, _)
|
|
|
|
=> l,
|
|
|
|
|
|
|
|
_ => panic!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn get_mut_line_location(&mut self) -> &mut LineLocation {
|
|
|
|
match self {
|
|
|
|
PreToken::PreQuantity(l, _)
|
|
|
|
| PreToken::PreWord(l, _)
|
|
|
|
| PreToken::PreOperator(l, _)
|
|
|
|
| PreToken::PreGroupStart(l)
|
|
|
|
| PreToken::PreGroupEnd(l)
|
|
|
|
| PreToken::PreGroup(l, _)
|
|
|
|
=> l,
|
|
|
|
|
|
|
|
_ => panic!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
2023-06-14 16:15:51 -07:00
|
|
|
pub fn to_token(self, context: &Context) -> Result<Token, (LineLocation, ParserError)>{
|
2023-06-11 13:53:45 -07:00
|
|
|
match self {
|
|
|
|
PreToken::PreQuantity(l, mut s) => {
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
if r.is_none() {
|
|
|
|
return Err((l, ParserError::BadNumber))
|
|
|
|
}
|
|
|
|
return Ok(Token::Quantity(r.unwrap()));
|
|
|
|
},
|
|
|
|
|
|
|
|
PreToken::PreWord(l, s) => {
|
|
|
|
|
2023-06-14 16:15:51 -07:00
|
|
|
let c = Constant::from_string(&s);
|
|
|
|
if c.is_some() { return Ok(Token::Constant(c.unwrap())); }
|
2023-06-11 13:53:45 -07:00
|
|
|
|
|
|
|
let c = Unit::from_string(&s);
|
|
|
|
if c.is_some() { return Ok(Token::Quantity(c.unwrap())); }
|
|
|
|
|
2023-06-14 16:15:51 -07:00
|
|
|
let c = context.get_variable(&s);
|
|
|
|
if c.is_some() { return Ok(Token::Variable(s)); }
|
2023-06-14 14:04:32 -07:00
|
|
|
|
2023-06-11 13:53:45 -07:00
|
|
|
return Err((l, ParserError::Undefined(s)));
|
|
|
|
}
|
|
|
|
|
|
|
|
PreToken::Container(v) => { return Ok(v); }
|
|
|
|
|
|
|
|
PreToken::PreOperator(_,_)
|
|
|
|
| PreToken::PreGroupStart(_)
|
|
|
|
| PreToken::PreGroupEnd(_)
|
|
|
|
| PreToken::PreGroup(_, _)
|
|
|
|
=> panic!()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|