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), 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,

View File

@ -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,

View File

@ -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
} }

View File

@ -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)
} }