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:
Sebastian Schmidt 2019-03-28 10:02:08 +01:00
parent 88ab1e1987
commit a7b5f602d5
4 changed files with 34 additions and 48 deletions

View File

@ -29,11 +29,6 @@ impl fmt::Display for EvalexprError {
},
ExpectedTuple { actual } => write!(f, "Expected a Value::Tuple, 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."),
PrecedenceViolation => write!(
f,

View File

@ -74,9 +74,6 @@ pub enum EvalexprError {
actual: Value,
},
/// The given expression is empty
EmptyExpression,
/// Tried to append a child to a leaf node.
/// Leaf nodes cannot have children.
AppendedToLeafNode,

View File

@ -21,12 +21,12 @@ pub trait Operator: Debug + Display {
/// True if this operator is a leaf, meaning it accepts no arguments.
// Make this a const fn once #57563 is resolved
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
fn argument_amount(&self) -> usize;
fn max_argument_amount(&self) -> usize;
/// Evaluates the operator with the given arguments and context.
fn eval(&self, arguments: &[Value], context: &dyn Context) -> EvalexprResult<Value>;
@ -119,13 +119,16 @@ impl Operator for RootNode {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
1
}
fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult<Value> {
expect_operator_argument_amount(arguments.len(), 1)?;
Ok(arguments[0].clone())
if let Some(first) = arguments.first() {
Ok(first.clone())
} else {
Ok(Value::Empty)
}
}
}
@ -138,7 +141,7 @@ impl Operator for Add {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -174,7 +177,7 @@ impl Operator for Sub {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -210,7 +213,7 @@ impl Operator for Neg {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
1
}
@ -240,7 +243,7 @@ impl Operator for Mul {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -276,7 +279,7 @@ impl Operator for Div {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -312,7 +315,7 @@ impl Operator for Mod {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -348,7 +351,7 @@ impl Operator for Exp {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -375,7 +378,7 @@ impl Operator for Eq {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -399,7 +402,7 @@ impl Operator for Neq {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -423,7 +426,7 @@ impl Operator for Gt {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -457,7 +460,7 @@ impl Operator for Lt {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -491,7 +494,7 @@ impl Operator for Geq {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -525,7 +528,7 @@ impl Operator for Leq {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -559,7 +562,7 @@ impl Operator for And {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -585,7 +588,7 @@ impl Operator for Or {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -611,7 +614,7 @@ impl Operator for Not {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
1
}
@ -636,7 +639,7 @@ impl Operator for Tuple {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
2
}
@ -673,7 +676,7 @@ impl Operator for Const {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
0
}
@ -693,7 +696,7 @@ impl Operator for VariableIdentifier {
true
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
0
}
@ -717,7 +720,7 @@ impl Operator for FunctionIdentifier {
false
}
fn argument_amount(&self) -> usize {
fn max_argument_amount(&self) -> usize {
1
}

View File

@ -264,8 +264,8 @@ impl Node {
&self.operator
}
fn has_correct_amount_of_children(&self) -> bool {
self.children().len() == self.operator().argument_amount()
fn has_enough_children(&self) -> bool {
self.children().len() == self.operator().max_argument_amount()
}
fn insert_back_prioritized(&mut self, node: Node, is_root_node: bool) -> EvalexprResult<()> {
@ -275,7 +275,7 @@ impl Node {
{
if self.operator().is_leaf() {
Err(EvalexprError::AppendedToLeafNode)
} else if self.has_correct_amount_of_children() {
} else if self.has_enough_children() {
if self.children.last().unwrap().operator().precedence()
< node.operator().precedence()
// Right-to-left chaining
@ -381,17 +381,8 @@ pub(crate) fn tokens_to_operator_tree(tokens: Vec<Token>) -> EvalexprResult<Node
if root.len() > 1 {
Err(EvalexprError::UnmatchedLBrace)
} else if let Some(mut root) = root.pop() {
if root.children().len() > 1 {
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 if let Some(root) = root.pop() {
Ok(root)
} else {
Err(EvalexprError::UnmatchedRBrace)
}