Adds support for conditional statements

This commit is contained in:
Tarik Eshaq 2020-08-14 11:47:44 -07:00
Родитель 2079e42d09
Коммит b1e9d62eba
3 изменённых файлов: 37 добавлений и 11 удалений

Просмотреть файл

@ -257,6 +257,18 @@ impl<'a> Evaluator<'a> {
.ok_or(EvaluationError::UnknownTransform(name))?;
f(&args_arr).map_err(|e| e.into())
}
Expression::Conditional {
left,
truthy,
falsy,
} => {
if self.eval_ast(*left, context)?.is_truthy() {
self.eval_ast(*truthy, context)
} else {
self.eval_ast(*falsy, context)
}
}
}
}
}
@ -463,10 +475,12 @@ mod tests {
}
#[test]
#[should_panic]
fn test_conditional_expression() {
assert_eq!(Evaluator::new().eval("'foo' ? 1 : 2").unwrap(), value!(1));
assert_eq!(Evaluator::new().eval("'' ? 1 : 2").unwrap(), value!(2));
assert_eq!(
Evaluator::new().eval("'foo' ? 1 : 2").unwrap(),
value!(1f64)
);
assert_eq!(Evaluator::new().eval("'' ? 1 : 2").unwrap(), value!(2f64));
}
#[test]

Просмотреть файл

@ -9,6 +9,8 @@ pub enum Expression {
Boolean(bool),
Array(Vec<Box<Expression>>),
Object(Vec<(String, Box<Expression>)>),
Identifier(String),
BinaryOperation {
operation: OpCode,
left: Box<Expression>,
@ -28,7 +30,11 @@ pub enum Expression {
index: Box<Expression>,
},
Identifier(String),
Conditional {
left: Box<Expression>,
truthy: Box<Expression>,
falsy: Box<Expression>,
},
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]

Просмотреть файл

@ -32,10 +32,16 @@ Expr40: Box<Expression> = {
};
Expr50: Box<Expression> = {
<subject: Expr50> "|" <name: Identifier> <args: Args?> => Box::new(Expression::Transform{name, subject, args}),
Expr60
<left: Expr50> "?" <truthy: Expr60> ":" <falsy: Expr60> => Box::new(Expression::Conditional {left, truthy, falsy}),
Expr60,
}
Expr60: Box<Expression> = {
<subject: Expr60> "|" <name: Identifier> <args: Args?> => Box::new(Expression::Transform{name, subject, args}),
Expr70
};
/// Expression for dereferencing.
/// Used for dereferencing object literals, array literals, and the context
/// There are two types of operations here:
@ -58,13 +64,13 @@ Expr50: Box<Expression> = {
/// `foo.bar[0] == {"baz": 1}`
/// `foo.bar[1].bobo[0] == 13`
/// `[1, 2, 3][1] == 2`
Expr60: Box<Expression> = {
<subject: Expr60> <index: Index> => Box::new(Expression::IndexOperation{subject, index}),
<subject: Expr60> "." <ident: Identifier> => Box::new(Expression::DotOperation{subject, ident}),
Expr70
Expr70: Box<Expression> = {
<subject: Expr70> <index: Index> => Box::new(Expression::IndexOperation{subject, index}),
<subject: Expr70> "." <ident: Identifier> => Box::new(Expression::DotOperation{subject, ident}),
Expr80
};
Expr70: Box<Expression> = {
Expr80: Box<Expression> = {
Number => Box::new(Expression::Number(<>)),
Boolean => Box::new(Expression::Boolean(<>)),
String => Box::new(Expression::String(<>)),