mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-18 18:38:05 +08:00
Move the math expression parser from Pest to Chumsky and add more features (#2685)
Rewrite the math-parser library using a chumsky-based lexer and parser, adding functions, comparisons, logic, and conditionals
This commit is contained in:
@@ -2,6 +2,7 @@ use crate::ast::{Literal, Node};
|
||||
use crate::constants::DEFAULT_FUNCTIONS;
|
||||
use crate::context::{EvalContext, FunctionProvider, ValueProvider};
|
||||
use crate::value::{Number, Value};
|
||||
use num_complex::Complex;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@@ -24,7 +25,7 @@ impl Node {
|
||||
},
|
||||
|
||||
Node::BinOp { lhs, op, rhs } => match (lhs.eval(context)?, rhs.eval(context)?) {
|
||||
(Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs.binary_op(*op, rhs))),
|
||||
(Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs.binary_op(*op, rhs).ok_or(EvalError::TypeError)?)),
|
||||
},
|
||||
Node::UnaryOp { expr, op } => match expr.eval(context)? {
|
||||
Value::Number(num) => Ok(Value::Number(num.unary_op(*op))),
|
||||
@@ -32,6 +33,7 @@ impl Node {
|
||||
Node::Var(name) => context.get_value(name).ok_or_else(|| EvalError::MissingValue(name.clone())),
|
||||
Node::FnCall { name, expr } => {
|
||||
let values = expr.iter().map(|expr| expr.eval(context)).collect::<Result<Vec<Value>, EvalError>>()?;
|
||||
|
||||
if let Some(function) = DEFAULT_FUNCTIONS.get(&name.as_str()) {
|
||||
function(&values).ok_or(EvalError::TypeError)
|
||||
} else if let Some(val) = context.run_function(name, &values) {
|
||||
@@ -40,6 +42,14 @@ impl Node {
|
||||
context.get_value(name).ok_or_else(|| EvalError::MissingFunction(name.to_string()))
|
||||
}
|
||||
}
|
||||
Node::Conditional { condition, if_block, else_block } => {
|
||||
let condition = match condition.eval(context)? {
|
||||
Value::Number(Number::Real(number)) => number != 0.,
|
||||
Value::Number(Number::Complex(number)) => number != Complex::ZERO,
|
||||
};
|
||||
|
||||
if condition { if_block.eval(context) } else { else_block.eval(context) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user