Do not require expressions to have content
* Make parser return implicit toplevel node * Make `RootNode` return `Value::Empty` if it has no arguments instead of failing Relates to #28
This commit is contained in:
parent
88ab1e1987
commit
a7b5f602d5
@ -29,11 +29,6 @@ impl fmt::Display for EvalexprError {
|
|||||||
},
|
},
|
||||||
ExpectedTuple { actual } => write!(f, "Expected a Value::Tuple, but got {:?}.", actual),
|
ExpectedTuple { actual } => write!(f, "Expected a Value::Tuple, but got {:?}.", actual),
|
||||||
ExpectedEmpty { actual } => write!(f, "Expected a Value::Empty, but got {:?}.", actual),
|
ExpectedEmpty { actual } => write!(f, "Expected a Value::Empty, but got {:?}.", actual),
|
||||||
EmptyExpression => write!(
|
|
||||||
f,
|
|
||||||
"Got an empty expression that cannot be parsed into a node tree, because it \
|
|
||||||
returns nothing."
|
|
||||||
),
|
|
||||||
AppendedToLeafNode => write!(f, "Tried to append a node to a leaf node."),
|
AppendedToLeafNode => write!(f, "Tried to append a node to a leaf node."),
|
||||||
PrecedenceViolation => write!(
|
PrecedenceViolation => write!(
|
||||||
f,
|
f,
|
||||||
|
@ -74,9 +74,6 @@ pub enum EvalexprError {
|
|||||||
actual: Value,
|
actual: Value,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The given expression is empty
|
|
||||||
EmptyExpression,
|
|
||||||
|
|
||||||
/// Tried to append a child to a leaf node.
|
/// Tried to append a child to a leaf node.
|
||||||
/// Leaf nodes cannot have children.
|
/// Leaf nodes cannot have children.
|
||||||
AppendedToLeafNode,
|
AppendedToLeafNode,
|
||||||
|
@ -21,12 +21,12 @@ pub trait Operator: Debug + Display {
|
|||||||
/// True if this operator is a leaf, meaning it accepts no arguments.
|
/// True if this operator is a leaf, meaning it accepts no arguments.
|
||||||
// Make this a const fn once #57563 is resolved
|
// Make this a const fn once #57563 is resolved
|
||||||
fn is_leaf(&self) -> bool {
|
fn is_leaf(&self) -> bool {
|
||||||
self.argument_amount() == 0
|
self.max_argument_amount() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the amount of arguments required by this operator.
|
/// Returns the maximum amount of arguments required by this operator.
|
||||||
// Make this a const fn once #57563 is resolved
|
// Make this a const fn once #57563 is resolved
|
||||||
fn argument_amount(&self) -> usize;
|
fn max_argument_amount(&self) -> usize;
|
||||||
|
|
||||||
/// Evaluates the operator with the given arguments and context.
|
/// Evaluates the operator with the given arguments and context.
|
||||||
fn eval(&self, arguments: &[Value], context: &dyn Context) -> EvalexprResult<Value>;
|
fn eval(&self, arguments: &[Value], context: &dyn Context) -> EvalexprResult<Value>;
|
||||||
@ -119,13 +119,16 @@ impl Operator for RootNode {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult<Value> {
|
fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult<Value> {
|
||||||
expect_operator_argument_amount(arguments.len(), 1)?;
|
if let Some(first) = arguments.first() {
|
||||||
Ok(arguments[0].clone())
|
Ok(first.clone())
|
||||||
|
} else {
|
||||||
|
Ok(Value::Empty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +141,7 @@ impl Operator for Add {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +177,7 @@ impl Operator for Sub {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +213,7 @@ impl Operator for Neg {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +243,7 @@ impl Operator for Mul {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +279,7 @@ impl Operator for Div {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +315,7 @@ impl Operator for Mod {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +351,7 @@ impl Operator for Exp {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,7 +378,7 @@ impl Operator for Eq {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,7 +402,7 @@ impl Operator for Neq {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,7 +426,7 @@ impl Operator for Gt {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +460,7 @@ impl Operator for Lt {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,7 +494,7 @@ impl Operator for Geq {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,7 +528,7 @@ impl Operator for Leq {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +562,7 @@ impl Operator for And {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,7 +588,7 @@ impl Operator for Or {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,7 +614,7 @@ impl Operator for Not {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,7 +639,7 @@ impl Operator for Tuple {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -673,7 +676,7 @@ impl Operator for Const {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,7 +696,7 @@ impl Operator for VariableIdentifier {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -717,7 +720,7 @@ impl Operator for FunctionIdentifier {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn argument_amount(&self) -> usize {
|
fn max_argument_amount(&self) -> usize {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,8 +264,8 @@ impl Node {
|
|||||||
&self.operator
|
&self.operator
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_correct_amount_of_children(&self) -> bool {
|
fn has_enough_children(&self) -> bool {
|
||||||
self.children().len() == self.operator().argument_amount()
|
self.children().len() == self.operator().max_argument_amount()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_back_prioritized(&mut self, node: Node, is_root_node: bool) -> EvalexprResult<()> {
|
fn insert_back_prioritized(&mut self, node: Node, is_root_node: bool) -> EvalexprResult<()> {
|
||||||
@ -275,7 +275,7 @@ impl Node {
|
|||||||
{
|
{
|
||||||
if self.operator().is_leaf() {
|
if self.operator().is_leaf() {
|
||||||
Err(EvalexprError::AppendedToLeafNode)
|
Err(EvalexprError::AppendedToLeafNode)
|
||||||
} else if self.has_correct_amount_of_children() {
|
} else if self.has_enough_children() {
|
||||||
if self.children.last().unwrap().operator().precedence()
|
if self.children.last().unwrap().operator().precedence()
|
||||||
< node.operator().precedence()
|
< node.operator().precedence()
|
||||||
// Right-to-left chaining
|
// Right-to-left chaining
|
||||||
@ -381,17 +381,8 @@ pub(crate) fn tokens_to_operator_tree(tokens: Vec<Token>) -> EvalexprResult<Node
|
|||||||
|
|
||||||
if root.len() > 1 {
|
if root.len() > 1 {
|
||||||
Err(EvalexprError::UnmatchedLBrace)
|
Err(EvalexprError::UnmatchedLBrace)
|
||||||
} else if let Some(mut root) = root.pop() {
|
} else if let Some(root) = root.pop() {
|
||||||
if root.children().len() > 1 {
|
Ok(root)
|
||||||
Err(EvalexprError::wrong_operator_argument_amount(
|
|
||||||
root.children().len(),
|
|
||||||
1,
|
|
||||||
))
|
|
||||||
} else if let Some(child) = root.children.pop() {
|
|
||||||
Ok(child)
|
|
||||||
} else {
|
|
||||||
Err(EvalexprError::EmptyExpression)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Err(EvalexprError::UnmatchedRBrace)
|
Err(EvalexprError::UnmatchedRBrace)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user