use structure::xflow::XFlowValue;
use runtime::xfstate::XFState;
#![arguments(context: &XFState)]
pub expression -> XFlowValue
= boolean_expression
/ arithmetic_expression
/ variable
/ atom
/ parenthesized<expression>
// Arithmetic
pub arithmetic_expression -> XFlowValue
= e:arithmetic_test { XFlowValue::Integer(e) }
arithmetic_test -> i64
= #infix<integer> {
#L x plus y { x + y }
x minus y { x - y }
#L x times y { x * y }
x division y { x / y }
#R x power y { x.pow(y as u32) }
}
/ integer
// Boolean
pub boolean_expression -> XFlowValue
= e:boolean_test { XFlowValue::Boolean(e) }
boolean_test -> bool
= l:integer eq r:integer { l == r }
/ l:integer ne r:integer { l != r }
/ l:integer gt r:integer { l > r }
/ l:integer lt r:integer { l < r }
/ l:integer gte r:integer { l >= r }
/ l:integer lte r:integer { l <= r }
/ boolean_infix
boolean_infix -> bool
= #infix<boolean> {
#L l eq r { l == r }
l ne r { l != r }
#R l and r { l && r }
l or r { l || r }
}
/ not
/ parenthesized<boolean_test>
/ boolean
parenthesized<foo>
= "(" s:foo ")" { s }
// Operators
plus -> ()
= _ "+" _
minus -> ()
= _ "-" _
times -> ()
= _ "*" _
division -> ()
= _ "/" _
power -> ()
= _ "^" _
eq -> ()
= _ "==" _
ne -> ()
= _ "!=" _
gt -> ()
= _ ">" _
lt -> ()
= _ "<" _
gte -> ()
= _ ">=" _
lte -> ()
= _ "<=" _
and -> ()
= _ "&&" _
or -> ()
= _ "||" _
not -> bool
= "!" l:boolean { !l }
/ "!" l:parenthesized<boolean> { !l }
// Primitives
boolean -> bool
= "true" { true }
/ "false" { false }
/ boolean_variable
/ parenthesized<boolean_test>
/ parenthesized<boolean>
integer -> i64
= n:$([0-9]+) { n.parse().unwrap() }
/ integer_variable
/ parenthesized<integer>
/ parenthesized<arithmetic_test>
variable -> XFlowValue
= i:integer_variable { XFlowValue::Integer(i) }
/ b:boolean_variable { XFlowValue::Boolean(b) }
boolean_variable -> bool
= "$" s:$([A-Za-z]+) {?
match context.get(s) {
Some(val) => {
match val.value {
XFlowValue::Boolean(b) => Ok(b),
_ => Err("Incorrect Value Found (Boolean)")
}
}
None => Err("Value not found in local state (Boolean)")
}
}
integer_variable -> i64
= "$" s:$([A-Za-z]+) {?
match context.get(s) {
Some(val) => {
match val.value {
XFlowValue::Integer(i) => Ok(i),
_ => Err("Incorrect Value Found")
}
}
None => Err("Value not found in local state")
}
}
space -> ()
= " "
/ newline
newline -> ()
= "\n"
/ "\r"
/ "\r\n"
_ -> ()
= space*
atom -> XFlowValue
= i:integer { XFlowValue::Integer(i) }
/ b:boolean { XFlowValue::Boolean(b) }
//
// Supporting utilities
//
pub variable_names -> Vec<&'input str>
= var_name*
/ !var_name { Vec::<&'input str>::new() }
var_name -> &'input str
= non_var_start* "$" s:$([A-Za-z]+) non_var_start* { s }
non_var_start -> ()
= $([^$]) {}