format code.
This commit is contained in:
parent
3729348632
commit
3c19414593
@ -20,7 +20,7 @@ impl BuiltIn {
|
||||
#[derive(PartialEq)]
|
||||
enum Compare {
|
||||
Min,
|
||||
Max
|
||||
Max,
|
||||
}
|
||||
|
||||
fn create_min_fuction() -> Function {
|
||||
@ -36,7 +36,8 @@ fn compare(compare: Compare) -> Function {
|
||||
max_args: None,
|
||||
min_args: Some(1),
|
||||
compiled: Box::new(move |values| {
|
||||
let mut prev: Result<Value, Error> = Err(Error::Custom("can't find min value.".to_owned()));
|
||||
let mut prev: Result<Value, Error> = Err(Error::Custom("can't find min value."
|
||||
.to_owned()));
|
||||
|
||||
for value in values {
|
||||
match value {
|
||||
@ -56,7 +57,7 @@ fn compare(compare: Compare) -> Function {
|
||||
prev = Ok(value);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
if prev.is_ok() {
|
||||
if compare == Compare::Min {
|
||||
@ -75,7 +76,7 @@ fn compare(compare: Compare) -> Function {
|
||||
}
|
||||
}
|
||||
prev
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,18 +85,18 @@ fn create_is_empty_fuction() -> Function {
|
||||
Function {
|
||||
max_args: Some(1),
|
||||
min_args: Some(1),
|
||||
compiled: Box::new(|values|{
|
||||
compiled: Box::new(|values| {
|
||||
match *values.first().unwrap() {
|
||||
Value::String(ref string) => Ok(Value::Bool(string.is_empty())),
|
||||
Value::Array(ref array) => Ok(Value::Bool(array.is_empty())),
|
||||
Value::Object(ref object) => Ok(Value::Bool(object.is_empty())),
|
||||
Value::Null => Ok(Value::Bool(true)),
|
||||
_ => Ok(Value::Bool(false))
|
||||
_ => Ok(Value::Bool(false)),
|
||||
}
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_array_function() -> Function {
|
||||
Function::new(|values|Ok(to_value(values)))
|
||||
Function::new(|values| Ok(to_value(values)))
|
||||
}
|
||||
|
@ -15,15 +15,12 @@ pub struct Expression {
|
||||
pub raw: String,
|
||||
pub pos: Vec<usize>,
|
||||
pub operators: Vec<Operator>,
|
||||
pub node: Option<Node>
|
||||
pub node: Option<Node>,
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn new<T: Into<String>>(raw: T) -> Result<Expression, Error> {
|
||||
let mut expr = Expression {
|
||||
raw: raw.into(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut expr = Expression { raw: raw.into(), ..Default::default() };
|
||||
|
||||
expr.parse_pos()?;
|
||||
expr.parse_operators()?;
|
||||
@ -36,19 +33,19 @@ impl Expression {
|
||||
|
||||
for (index, cur) in self.raw.chars().enumerate() {
|
||||
match cur {
|
||||
'(' | ')' | '+' | '-' | '*' | '/' | ',' | ' ' | '!' | '=' |
|
||||
'>' | '<' | '\'' | '[' | ']' | '%' | '&' | '|' => {
|
||||
if ! found_quote {
|
||||
'(' | ')' | '+' | '-' | '*' | '/' | ',' | ' ' | '!' | '=' | '>' | '<' | '\'' |
|
||||
'[' | ']' | '%' | '&' | '|' => {
|
||||
if !found_quote {
|
||||
self.pos.push(index);
|
||||
self.pos.push(index + 1);
|
||||
}
|
||||
},
|
||||
}
|
||||
'"' => {
|
||||
found_quote = ! found_quote;
|
||||
found_quote = !found_quote;
|
||||
self.pos.push(index);
|
||||
self.pos.push(index + 1);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,8 +87,8 @@ impl Expression {
|
||||
prev.clear();
|
||||
continue;
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
if quote.is_some() {
|
||||
@ -147,11 +144,11 @@ impl Expression {
|
||||
operators.push(Operator::Function("array".to_owned()));
|
||||
operators.push(operator);
|
||||
continue;
|
||||
},
|
||||
}
|
||||
Operator::LeftParenthesis => {
|
||||
parenthesis += 1;
|
||||
|
||||
if ! operators.is_empty() {
|
||||
if !operators.is_empty() {
|
||||
let prev_operator = operators.pop().unwrap();
|
||||
if prev_operator.is_identifier() {
|
||||
operators.push(Operator::Function(prev_operator.get_identifier()));
|
||||
@ -161,11 +158,11 @@ impl Expression {
|
||||
operators.push(prev_operator);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Operator::RightParenthesis => parenthesis -= 1,
|
||||
Operator::RightSquareBracket => square_brackets -= 1,
|
||||
Operator::WhiteSpace => continue,
|
||||
_ => ()
|
||||
_ => (),
|
||||
}
|
||||
|
||||
prev = raw;
|
||||
@ -185,17 +182,24 @@ impl Expression {
|
||||
|
||||
for operator in &self.operators {
|
||||
match *operator {
|
||||
Operator::Add(priority) | Operator::Sub(priority) |
|
||||
Operator::Mul(priority) | Operator::Div(priority) |
|
||||
Operator::Not(priority) | Operator::Eq(priority) |
|
||||
Operator::Ne(priority) | Operator::Gt(priority) |
|
||||
Operator::Lt(priority) | Operator::Ge(priority) |
|
||||
Operator::And(priority) | Operator::Or(priority) |
|
||||
Operator::Le(priority) | Operator::Rem(priority) => {
|
||||
if ! parsing_nodes.is_empty() {
|
||||
Operator::Add(priority) |
|
||||
Operator::Sub(priority) |
|
||||
Operator::Mul(priority) |
|
||||
Operator::Div(priority) |
|
||||
Operator::Not(priority) |
|
||||
Operator::Eq(priority) |
|
||||
Operator::Ne(priority) |
|
||||
Operator::Gt(priority) |
|
||||
Operator::Lt(priority) |
|
||||
Operator::Ge(priority) |
|
||||
Operator::And(priority) |
|
||||
Operator::Or(priority) |
|
||||
Operator::Le(priority) |
|
||||
Operator::Rem(priority) => {
|
||||
if !parsing_nodes.is_empty() {
|
||||
let prev = parsing_nodes.pop().unwrap();
|
||||
if prev.is_value_or_enough() {
|
||||
if prev.operator.get_priority() < priority && ! prev.closed {
|
||||
if prev.operator.get_priority() < priority && !prev.closed {
|
||||
parsing_nodes.extend_from_slice(&rob_to(prev, operator.to_node()));
|
||||
} else {
|
||||
parsing_nodes.push(operator.children_to_node(vec![prev]));
|
||||
@ -211,12 +215,18 @@ impl Expression {
|
||||
} else {
|
||||
return Err(Error::StartWithNonValueOperator);
|
||||
}
|
||||
},
|
||||
Operator::Function(_) | Operator::LeftParenthesis | Operator::LeftSquareBracket => parsing_nodes.push(operator.to_node()),
|
||||
}
|
||||
Operator::Function(_) |
|
||||
Operator::LeftParenthesis |
|
||||
Operator::LeftSquareBracket => parsing_nodes.push(operator.to_node()),
|
||||
Operator::Comma => close_comma(&mut parsing_nodes)?,
|
||||
Operator::RightParenthesis | Operator::RightSquareBracket => close_bracket(&mut parsing_nodes, operator.get_left())?,
|
||||
Operator::Value(_) | Operator::Identifier(_) => append_child_to_last_node(&mut parsing_nodes, operator)?,
|
||||
_ => ()
|
||||
Operator::RightParenthesis |
|
||||
Operator::RightSquareBracket => {
|
||||
close_bracket(&mut parsing_nodes, operator.get_left())?
|
||||
}
|
||||
Operator::Value(_) |
|
||||
Operator::Identifier(_) => append_child_to_last_node(&mut parsing_nodes, operator)?,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,21 +240,75 @@ impl Expression {
|
||||
Box::new(move |contexts, buildin, functions| -> Result<Value, Error> {
|
||||
return exec_node(&node, contexts, buildin, functions);
|
||||
|
||||
fn exec_node(node: &Node, contexts: ContextsRef, buildin: &Functions, functions: &Functions) -> Result<Value, Error> {
|
||||
fn exec_node(node: &Node,
|
||||
contexts: ContextsRef,
|
||||
buildin: &Functions,
|
||||
functions: &Functions)
|
||||
-> Result<Value, Error> {
|
||||
match node.operator {
|
||||
Operator::Add(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.add(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Mul(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.mul(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Sub(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.sub(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Div(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.div(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Rem(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.rem(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Eq(_) => Math::eq(&exec_node(&node.get_first_child(), contexts, buildin, functions)?, &exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Ne(_) => Math::ne(&exec_node(&node.get_first_child(), contexts, buildin, functions)?, &exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Gt(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.gt(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Lt(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.lt(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Ge(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.ge(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Le(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.le(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::And(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.and(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Or(_) => exec_node(&node.get_first_child(), contexts, buildin, functions)?.or(&exec_node(&node.get_last_child(), contexts, buildin, functions)?),
|
||||
Operator::Add(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.add(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Mul(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.mul(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Sub(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.sub(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Div(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.div(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Rem(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.rem(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Eq(_) => {
|
||||
Math::eq(&exec_node(&node.get_first_child(), contexts, buildin, functions)?,
|
||||
&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Ne(_) => {
|
||||
Math::ne(&exec_node(&node.get_first_child(), contexts, buildin, functions)?,
|
||||
&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Gt(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.gt(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Lt(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.lt(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Ge(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.ge(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Le(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.le(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::And(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.and(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Or(_) => {
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)
|
||||
?
|
||||
.or(&exec_node(&node.get_last_child(), contexts, buildin, functions)?)
|
||||
}
|
||||
Operator::Function(ref ident) => {
|
||||
let function_option = if functions.contains_key(ident) {
|
||||
functions.get(ident)
|
||||
@ -263,16 +327,17 @@ impl Expression {
|
||||
} else {
|
||||
Err(Error::FunctionNotExists(ident.to_owned()))
|
||||
}
|
||||
},
|
||||
}
|
||||
Operator::Value(ref value) => Ok(value.clone()),
|
||||
Operator::Not(_) => {
|
||||
let value = exec_node(&node.get_first_child(), contexts, buildin, functions)?;
|
||||
let value =
|
||||
exec_node(&node.get_first_child(), contexts, buildin, functions)?;
|
||||
match value {
|
||||
Value::Bool(boolean) => Ok(Value::Bool(!boolean)),
|
||||
Value::Null => Ok(Value::Bool(true)),
|
||||
_ => Err(Error::NotBoolean(value))
|
||||
_ => Err(Error::NotBoolean(value)),
|
||||
}
|
||||
}
|
||||
},
|
||||
Operator::Identifier(ref ident) => {
|
||||
let number = parse_number(ident);
|
||||
if number.is_some() {
|
||||
@ -282,18 +347,20 @@ impl Expression {
|
||||
} else {
|
||||
match find(contexts, ident) {
|
||||
Some(value) => Ok(value),
|
||||
None => Ok(Value::Null)
|
||||
None => Ok(Value::Null),
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => Err(Error::CanNotExec(node.operator.clone()))
|
||||
}
|
||||
_ => Err(Error::CanNotExec(node.operator.clone())),
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn append_child_to_last_node(parsing_nodes: &mut Vec<Node>, operator: &Operator) -> Result<(), Error> {
|
||||
fn append_child_to_last_node(parsing_nodes: &mut Vec<Node>,
|
||||
operator: &Operator)
|
||||
-> Result<(), Error> {
|
||||
let mut node = operator.to_node();
|
||||
node.closed = true;
|
||||
|
||||
@ -316,7 +383,7 @@ fn append_child_to_last_node(parsing_nodes: &mut Vec<Node>, operator: &Operator)
|
||||
|
||||
fn get_final_node(mut parsing_nodes: Vec<Node>) -> Result<Node, Error> {
|
||||
if parsing_nodes.is_empty() {
|
||||
return Err(Error::NoFinalNode)
|
||||
return Err(Error::NoFinalNode);
|
||||
}
|
||||
|
||||
while parsing_nodes.len() != 1 {
|
||||
@ -343,7 +410,7 @@ fn close_bracket(parsing_nodes: &mut Vec<Node>, bracket: Operator) -> Result<(),
|
||||
return Err(Error::BracketNotWithFunction);
|
||||
}
|
||||
} else if prev.operator == bracket {
|
||||
if ! current.closed {
|
||||
if !current.closed {
|
||||
current.closed = true;
|
||||
}
|
||||
|
||||
@ -361,13 +428,13 @@ fn close_bracket(parsing_nodes: &mut Vec<Node>, bracket: Operator) -> Result<(),
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
if ! prev.closed {
|
||||
if !prev.closed {
|
||||
prev.add_child(current);
|
||||
if prev.is_enough() {
|
||||
prev.closed = true;
|
||||
}
|
||||
|
||||
if ! parsing_nodes.is_empty() {
|
||||
if !parsing_nodes.is_empty() {
|
||||
parsing_nodes.push(prev);
|
||||
} else {
|
||||
return Err(Error::StartWithNonValueOperator);
|
||||
@ -410,13 +477,13 @@ fn close_comma(parsing_nodes: &mut Vec<Node>) -> Result<(), Error> {
|
||||
return Err(Error::CommaNotWithFunction);
|
||||
}
|
||||
} else {
|
||||
if ! prev.closed {
|
||||
if !prev.closed {
|
||||
prev.add_child(current);
|
||||
if prev.is_enough() {
|
||||
prev.closed = true;
|
||||
}
|
||||
|
||||
if ! parsing_nodes.is_empty() {
|
||||
if !parsing_nodes.is_empty() {
|
||||
parsing_nodes.push(prev);
|
||||
} else {
|
||||
return Err(Error::StartWithNonValueOperator);
|
||||
@ -440,7 +507,7 @@ fn find(contexts: ContextsRef, key: &str) -> Option<Value> {
|
||||
let value = get(context, key);
|
||||
match value {
|
||||
Some(_) => return value,
|
||||
None => continue
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,10 +521,10 @@ fn get(context: &Context, key: &str) -> Option<Value> {
|
||||
|
||||
if context_value_option.is_none() {
|
||||
None
|
||||
} else if ! keys.is_empty() {
|
||||
} else if !keys.is_empty() {
|
||||
match context_value_option.unwrap().search(&keys.join(".")) {
|
||||
Some(value) => Some(value.clone()),
|
||||
None => None
|
||||
None => None,
|
||||
}
|
||||
} else {
|
||||
Some(context_value_option.unwrap().clone())
|
||||
|
@ -11,22 +11,27 @@ pub struct Function {
|
||||
/// Minimum number of arguments.
|
||||
pub min_args: Option<usize>,
|
||||
/// Accept values and return a result which contains a value.
|
||||
pub compiled: Box<Fn(Vec<Value>) -> Result<Value, Error> + Sync + Send>
|
||||
pub compiled: Box<Fn(Vec<Value>) -> Result<Value, Error> + Sync + Send>,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
/// Create a function with a closure.
|
||||
pub fn new<F>(closure: F) -> Function where F: 'static + Fn(Vec<Value>) -> Result<Value, Error> + Sync + Send {
|
||||
pub fn new<F>(closure: F) -> Function
|
||||
where F: 'static + Fn(Vec<Value>) -> Result<Value, Error> + Sync + Send
|
||||
{
|
||||
Function {
|
||||
max_args: None,
|
||||
min_args: None,
|
||||
compiled: Box::new(closure)
|
||||
compiled: Box::new(closure),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Function {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Function {{ max_args: {:?}, min_args: {:?} }}", self.max_args, self.min_args)
|
||||
write!(f,
|
||||
"Function {{ max_args: {:?}, min_args: {:?} }}",
|
||||
self.max_args,
|
||||
self.min_args)
|
||||
}
|
||||
}
|
||||
|
53
src/lib.rs
53
src/lib.rs
@ -117,7 +117,10 @@ pub fn eval_with_functions(expr: &str, functions: &Functions) -> Result<Value, E
|
||||
}
|
||||
|
||||
/// Evaluates the value of an expression with the given context and functions.
|
||||
pub fn eval_with_context_and_functions(expr: &str, context: &Context, functions: &Functions) -> Result<Value, Error> {
|
||||
pub fn eval_with_context_and_functions(expr: &str,
|
||||
context: &Context,
|
||||
functions: &Functions)
|
||||
-> Result<Value, Error> {
|
||||
let mut contexts = Contexts::new();
|
||||
contexts.push(context.clone());
|
||||
eval_with_contexts_and_functions(expr, &contexts, functions)
|
||||
@ -125,7 +128,10 @@ pub fn eval_with_context_and_functions(expr: &str, context: &Context, functions:
|
||||
|
||||
/// Evaluates the value of an expression with the given contexts and functions.<br>
|
||||
/// The value of the last context is searched first.
|
||||
pub fn eval_with_contexts_and_functions(expr: &str, contexts: ContextsRef, functions: &Functions) -> Result<Value, Error> {
|
||||
pub fn eval_with_contexts_and_functions(expr: &str,
|
||||
contexts: ContextsRef,
|
||||
functions: &Functions)
|
||||
-> Result<Value, Error> {
|
||||
Expression::new(expr)?.compile()(contexts, &BuiltIn::new(), functions)
|
||||
}
|
||||
|
||||
@ -194,7 +200,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_min_brackets() {
|
||||
assert_eq!(eval("(min(30, 5, 245, 20) * 10 + (5 + 5) * 5)"), Ok(to_value(100)));
|
||||
assert_eq!(eval("(min(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
|
||||
Ok(to_value(100)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -209,7 +216,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_max_brackets() {
|
||||
assert_eq!(eval("(max(30, 5, 245, 20) * 10 + (5 + 5) * 5)"), Ok(to_value(2500)));
|
||||
assert_eq!(eval("(max(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
|
||||
Ok(to_value(2500)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -301,12 +309,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_single_and_double_quote() {
|
||||
assert_eq!(eval(r#"' """" ' + ' """" '"#), Ok(to_value(r#" """" """" "#)));
|
||||
assert_eq!(eval(r#"' """" ' + ' """" '"#),
|
||||
Ok(to_value(r#" """" """" "#)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_and_single_quote() {
|
||||
assert_eq!(eval(r#"" '''' " + " '''' ""#), Ok(to_value(r#" '''' '''' "#)));
|
||||
assert_eq!(eval(r#"" '''' " + " '''' ""#),
|
||||
Ok(to_value(r#" '''' '''' "#)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -398,7 +408,8 @@ mod tests {
|
||||
fn test_buildin_is_empty() {
|
||||
let mut context = Context::new();
|
||||
context.insert("array".to_owned(), to_value(Vec::<String>::new()));
|
||||
assert_eq!(eval_with_context("is_empty(array)", &context), Ok(to_value(true)));
|
||||
assert_eq!(eval_with_context("is_empty(array)", &context),
|
||||
Ok(to_value(true)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -411,8 +422,10 @@ mod tests {
|
||||
#[test]
|
||||
fn test_custom_function() {
|
||||
let mut functions = Functions::new();
|
||||
functions.insert("output".to_owned(), Function::new(|_|Ok(to_value("This is custom function's output"))));
|
||||
assert_eq!(eval_with_functions("output()", &functions), Ok(to_value("This is custom function's output")));
|
||||
functions.insert("output".to_owned(),
|
||||
Function::new(|_| Ok(to_value("This is custom function's output"))));
|
||||
assert_eq!(eval_with_functions("output()", &functions),
|
||||
Ok(to_value("This is custom function's output")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -421,7 +434,7 @@ mod tests {
|
||||
raw: "+ + 5".to_owned(),
|
||||
pos: Vec::new(),
|
||||
operators: Vec::new(),
|
||||
node: None
|
||||
node: None,
|
||||
};
|
||||
|
||||
expr.parse_pos().unwrap();
|
||||
@ -432,10 +445,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_error_duplicate_operator() {
|
||||
let mut expr = Expression {
|
||||
raw: "5 + + 5".to_owned(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut expr = Expression { raw: "5 + + 5".to_owned(), ..Default::default() };
|
||||
|
||||
expr.parse_pos().unwrap();
|
||||
expr.parse_operators().unwrap();
|
||||
@ -445,10 +455,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_error_duplicate_value() {
|
||||
let mut expr = Expression {
|
||||
raw: "2 + 6 5".to_owned(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut expr = Expression { raw: "2 + 6 5".to_owned(), ..Default::default() };
|
||||
|
||||
expr.parse_pos().unwrap();
|
||||
expr.parse_operators().unwrap();
|
||||
@ -458,10 +465,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_error_unpaired_brackets() {
|
||||
let mut expr = Expression {
|
||||
raw: "(2 + 3)) * 5".to_owned(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut expr = Expression { raw: "(2 + 3)) * 5".to_owned(), ..Default::default() };
|
||||
|
||||
expr.parse_pos().unwrap();
|
||||
|
||||
@ -470,10 +474,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_error_comma() {
|
||||
let mut expr = Expression {
|
||||
raw: ", 2 + 5".to_owned(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut expr = Expression { raw: ", 2 + 5".to_owned(), ..Default::default() };
|
||||
|
||||
expr.parse_pos().unwrap();
|
||||
expr.parse_operators().unwrap();
|
||||
|
@ -165,7 +165,7 @@ impl Type for Value {
|
||||
Value::F64(f) => f,
|
||||
Value::I64(f) => f as f64,
|
||||
Value::U64(f) => f as f64,
|
||||
_ => panic!("not a number")
|
||||
_ => panic!("not a number"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ use Function;
|
||||
pub struct Node {
|
||||
pub operator: Operator,
|
||||
pub children: Vec<Node>,
|
||||
pub closed: bool
|
||||
pub closed: bool,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
@ -16,7 +16,7 @@ impl Node {
|
||||
Node {
|
||||
operator: operator,
|
||||
children: Vec::new(),
|
||||
closed: false
|
||||
closed: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,11 +51,7 @@ impl Node {
|
||||
if self.operator.is_value_or_ident() {
|
||||
true
|
||||
} else if self.operator.can_have_child() {
|
||||
if self.closed {
|
||||
true
|
||||
} else {
|
||||
self.is_enough()
|
||||
}
|
||||
if self.closed { true } else { self.is_enough() }
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -63,8 +59,8 @@ impl Node {
|
||||
|
||||
pub fn is_unclosed_function(&self) -> bool {
|
||||
match self.operator {
|
||||
Operator::Function(_) => ! self.closed,
|
||||
_ => false
|
||||
Operator::Function(_) => !self.closed,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,65 +31,68 @@ pub enum Operator {
|
||||
Comma,
|
||||
Function(String),
|
||||
Identifier(String),
|
||||
Value(Value)
|
||||
Value(Value),
|
||||
}
|
||||
|
||||
impl Operator {
|
||||
pub fn is_identifier(&self) -> bool {
|
||||
match *self {
|
||||
Operator::Identifier(_) => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_at_beginning(&self) -> bool {
|
||||
match *self {
|
||||
Operator::Not(_) | Operator::Function(_) | Operator::LeftParenthesis => true,
|
||||
_ => false
|
||||
Operator::Not(_) |
|
||||
Operator::Function(_) |
|
||||
Operator::LeftParenthesis => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_max_args(&self) -> Option<usize> {
|
||||
match *self {
|
||||
Operator::Add(_) | Operator::Sub(_) |
|
||||
Operator::Mul(_) | Operator::Div(_) |
|
||||
Operator::Eq(_) | Operator::Ne(_) |
|
||||
Operator::Gt(_) | Operator::Lt(_) |
|
||||
Operator::Ge(_) | Operator::Le(_) |
|
||||
Operator::And(_) | Operator::Or(_) |
|
||||
Operator::Rem(_)=> Some(2),
|
||||
Operator::Add(_) | Operator::Sub(_) | Operator::Mul(_) | Operator::Div(_) |
|
||||
Operator::Eq(_) | Operator::Ne(_) | Operator::Gt(_) | Operator::Lt(_) |
|
||||
Operator::Ge(_) | Operator::Le(_) | Operator::And(_) | Operator::Or(_) |
|
||||
Operator::Rem(_) => Some(2),
|
||||
Operator::Not(_) => Some(1),
|
||||
Operator::Function(_) => None,
|
||||
_ => Some(0)
|
||||
_ => Some(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_min_args(&self) -> Option<usize> {
|
||||
match *self {
|
||||
Operator::Add(_) | Operator::Sub(_) |
|
||||
Operator::Mul(_) | Operator::Div(_) |
|
||||
Operator::Eq(_) | Operator::Ne(_) |
|
||||
Operator::Gt(_) | Operator::Lt(_) |
|
||||
Operator::Ge(_) | Operator::Le(_) |
|
||||
Operator::And(_) | Operator::Or(_) |
|
||||
Operator::Add(_) | Operator::Sub(_) | Operator::Mul(_) | Operator::Div(_) |
|
||||
Operator::Eq(_) | Operator::Ne(_) | Operator::Gt(_) | Operator::Lt(_) |
|
||||
Operator::Ge(_) | Operator::Le(_) | Operator::And(_) | Operator::Or(_) |
|
||||
Operator::Rem(_) => Some(2),
|
||||
Operator::Not(_) => Some(1),
|
||||
Operator::Function(_) => None,
|
||||
_ => Some(0)
|
||||
_ => Some(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_priority(&self) -> u8 {
|
||||
match *self {
|
||||
Operator::Add(priority) | Operator::Sub(priority) |
|
||||
Operator::Div(priority) | Operator::Mul(priority) |
|
||||
Operator::Eq(priority) | Operator::Ne(priority) |
|
||||
Operator::Gt(priority) | Operator::Lt(priority) |
|
||||
Operator::Ge(priority) | Operator::Le(priority) |
|
||||
Operator::And(priority) | Operator::Or(priority) |
|
||||
Operator::Add(priority) |
|
||||
Operator::Sub(priority) |
|
||||
Operator::Div(priority) |
|
||||
Operator::Mul(priority) |
|
||||
Operator::Eq(priority) |
|
||||
Operator::Ne(priority) |
|
||||
Operator::Gt(priority) |
|
||||
Operator::Lt(priority) |
|
||||
Operator::Ge(priority) |
|
||||
Operator::Le(priority) |
|
||||
Operator::And(priority) |
|
||||
Operator::Or(priority) |
|
||||
Operator::Rem(priority) => priority,
|
||||
Operator::Value(_) | Operator::Identifier(_) => 0,
|
||||
_ => 99
|
||||
Operator::Value(_) |
|
||||
Operator::Identifier(_) => 0,
|
||||
_ => 99,
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,34 +103,43 @@ impl Operator {
|
||||
pub fn is_not(&self) -> bool {
|
||||
match *self {
|
||||
Operator::Not(_) => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_value_or_ident(&self) -> bool {
|
||||
match *self {
|
||||
Operator::Value(_) | Operator::Identifier(_) => true,
|
||||
_ => false
|
||||
Operator::Value(_) |
|
||||
Operator::Identifier(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_have_child(&self) -> bool {
|
||||
match *self {
|
||||
Operator::Function(_) | Operator::Add(_) |
|
||||
Operator::Sub(_) | Operator::Div(_) |
|
||||
Operator::Mul(_) | Operator::Rem(_) |
|
||||
Operator::Eq(_) | Operator::Ne(_) |
|
||||
Operator::Gt(_) | Operator::Lt(_) |
|
||||
Operator::And(_) | Operator::Or(_) |
|
||||
Operator::Ge(_) | Operator::Le(_) => true,
|
||||
_ => false
|
||||
Operator::Function(_) |
|
||||
Operator::Add(_) |
|
||||
Operator::Sub(_) |
|
||||
Operator::Div(_) |
|
||||
Operator::Mul(_) |
|
||||
Operator::Rem(_) |
|
||||
Operator::Eq(_) |
|
||||
Operator::Ne(_) |
|
||||
Operator::Gt(_) |
|
||||
Operator::Lt(_) |
|
||||
Operator::And(_) |
|
||||
Operator::Or(_) |
|
||||
Operator::Ge(_) |
|
||||
Operator::Le(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_left(&self) -> bool {
|
||||
match *self {
|
||||
Operator::LeftParenthesis | Operator::LeftSquareBracket => true,
|
||||
_ => false
|
||||
Operator::LeftParenthesis |
|
||||
Operator::LeftSquareBracket => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +147,7 @@ impl Operator {
|
||||
match *self {
|
||||
Operator::RightParenthesis => Operator::LeftParenthesis,
|
||||
Operator::RightSquareBracket => Operator::LeftSquareBracket,
|
||||
_ => panic!("not bracket")
|
||||
_ => panic!("not bracket"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +164,7 @@ impl Operator {
|
||||
pub fn get_identifier(&self) -> String {
|
||||
match *self {
|
||||
Operator::Identifier(ref ident) => ident.to_owned(),
|
||||
_ => panic!("not identifier")
|
||||
_ => panic!("not identifier"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -186,7 +198,7 @@ impl FromStr for Operator {
|
||||
"<=" => Ok(Operator::Le(6)),
|
||||
"&&" => Ok(Operator::And(4)),
|
||||
"||" => Ok(Operator::Or(2)),
|
||||
_ => Ok(Operator::Identifier(raw.to_owned()))
|
||||
_ => Ok(Operator::Identifier(raw.to_owned())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user