daisy/src/parser/expression/expression.rs

142 lines
3.4 KiB
Rust
Raw Normal View History

2023-06-11 13:53:45 -07:00
use std::collections::VecDeque;
use crate::quantity::Quantity;
use super::Operator;
use super::Constant;
2023-07-28 15:01:36 -07:00
use super::super::LineLocation;
2023-06-11 13:53:45 -07:00
2023-06-16 12:58:06 -07:00
/// Expressions represent logical objects in an expession.
2023-06-11 13:53:45 -07:00
#[derive(Debug)]
#[derive(Clone)]
2023-06-16 12:58:06 -07:00
pub enum Expression {
2023-07-28 15:01:36 -07:00
Variable(LineLocation, String),
Quantity(LineLocation, Quantity),
Constant(LineLocation, Constant),
Operator(LineLocation, Operator, VecDeque<Expression>),
2023-06-11 13:53:45 -07:00
}
2023-06-16 12:58:06 -07:00
impl ToString for Expression {
2023-06-11 13:53:45 -07:00
fn to_string(&self) -> String {
match self {
2023-07-28 15:01:36 -07:00
Expression::Quantity(_, v) => v.to_string(),
Expression::Constant(_, c) => c.to_string(),
Expression::Variable(_, s) => s.clone(),
Expression::Operator(_, o,a) => o.print(a)
2023-06-11 13:53:45 -07:00
}
}
}
2023-06-16 12:58:06 -07:00
impl Expression {
// This is called only when this is the outermost Expression.
2023-06-11 13:53:45 -07:00
// This sometimes leads to different--usually more verbose--behavior.
pub fn to_string_outer(&self) -> String {
match self {
2023-07-28 15:01:36 -07:00
Expression::Quantity(_, v) => v.to_string_outer(),
Expression::Constant(_, c) => c.to_string(),
Expression::Variable(_, s) => s.clone(),
Expression::Operator(_, o,a) => o.print(a)
2023-06-11 13:53:45 -07:00
}
}
2023-06-14 20:18:28 -07:00
pub fn is_quantity(&self) -> bool {
match self {
2023-07-28 15:01:36 -07:00
Expression::Quantity(_,_) => true,
2023-06-14 20:18:28 -07:00
_ => false
}
}
2023-07-31 20:43:50 -07:00
// True if this is a power operator applied to a constant or variable
// and an integer.
// Examples: pi^2, x ^ 3
pub fn is_poly_power(&self) -> bool {
match self {
Expression::Operator(_, Operator::Power, a) => {
// Assuming len(a) = 2, which should be true in this case
assert!(a.len() == 2);
let base = &a[0];
let power = &a[1];
// Make sure base ks const or variable
match base {
Expression::Constant(_, _)
| Expression::Variable(_, _)
=> {},
_ => { return false; }
};
// Make sure power is an integer
match power {
Expression::Quantity(_, q) => {
return q.unitless() && q.fract().is_zero();
},
_ => { return false; }
}
},
_ => { return false; }
};
}
2023-06-11 13:53:45 -07:00
#[inline(always)]
2023-06-16 12:58:06 -07:00
pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Expression>> {
2023-06-11 13:53:45 -07:00
match self {
2023-07-28 15:01:36 -07:00
Expression::Operator(_, _, ref mut a) => Some(a),
2023-06-11 13:53:45 -07:00
_ => None
}
}
#[inline(always)]
2023-06-16 12:58:06 -07:00
pub fn get_args(&self) -> Option<&VecDeque<Expression>> {
2023-06-14 20:18:28 -07:00
match self {
2023-07-28 15:01:36 -07:00
Expression::Operator(_, _, ref a) => Some(a),
2023-06-14 20:18:28 -07:00
_ => None
}
}
2023-06-11 13:53:45 -07:00
2023-06-14 20:18:28 -07:00
#[inline(always)]
2023-06-16 12:58:06 -07:00
pub fn get_at_coords<'a, 'b, I>(&'a self, coords: I) -> Option<&'a Expression>
2023-06-14 20:18:28 -07:00
where I: IntoIterator<Item = &'b usize> + Sized {
let mut g = self;
for t in coords.into_iter() {
let args = g.get_args();
let Some(args) = args else { return None; };
g = &args[*t];
2023-06-11 13:53:45 -07:00
}
2023-06-14 20:18:28 -07:00
return Some(g);
}
2023-06-11 13:53:45 -07:00
2023-06-14 20:18:28 -07:00
#[inline(always)]
2023-06-16 12:58:06 -07:00
pub fn get_at_coords_mut<'a, 'b, I>(&'a mut self, coords: I) -> Option<&'a mut Expression>
2023-06-14 20:18:28 -07:00
where I: IntoIterator<Item = &'b usize> + Sized {
let mut g = self;
for t in coords.into_iter() {
let args = g.get_args_mut();
let Some(args) = args else { return None; };
g = &mut args[*t];
}
return Some(g);
2023-06-11 13:53:45 -07:00
}
2023-07-28 15:01:36 -07:00
pub fn get_linelocation(&self) -> LineLocation {
match self {
Expression::Quantity(l, _)
| Expression::Constant(l, _)
| Expression::Variable(l, _)
| Expression::Operator(l, _,_)
=> { l.clone() }
}
}
pub fn set_linelocation(&mut self, loc: &LineLocation) {
match self {
Expression::Quantity(l, _) => { *l = *loc },
Expression::Constant(l, _) => { *l = *loc },
Expression::Variable(l, _) => { *l = *loc },
Expression::Operator(l, _,_) => { *l = *loc },
}
}
2023-06-11 13:53:45 -07:00
}