@@ -10,9 +10,8 @@
10//! or := and ("or" and)*
10//! or := and ("or" and)*
11//! and := not ("and" not)*
11//! and := not ("and" not)*
12//! not := "not" not | compare
12//! not := "not" not | compare
13−//! compare := concat (("==" | "!=" | "<" | ">" | "<=" | ">=" | "contains"
13+//! compare := sum (("==" | "!=" | "<" | ">" | "<=" | ">=" | "contains"
14−//! | "starts-with" | "ends-with") concat)?
14+//! | "starts-with" | "ends-with") sum)?
15−//! concat := sum ("~" sum)*
16//! sum := product (("+" | "-") product)*
15//! sum := product (("+" | "-") product)*
17//! product := unary (("*" | "/" | "%") unary)*
16//! product := unary (("*" | "/" | "%") unary)*
18//! unary := "-" unary | primary
17//! unary := "-" unary | primary
@@ -112,7 +111,7 @@ impl fmt::Display for Token {
115−const OPERATORS: &[&str] = &["==", "!=", "<=", ">=", "<", ">", "+", "-", "*", "/", "%", "~"];
114+const OPERATORS: &[&str] = &["==", "!=", "<=", ">=", "<", ">", "+", "-", "*", "/", "%"];
117fn tokenize(src: &str) -> Result<Vec<Token>, String> {
116fn tokenize(src: &str) -> Result<Vec<Token>, String> {
118 let chars: Vec<char> = src.chars().collect();
117 let chars: Vec<char> = src.chars().collect();
@@ -249,7 +248,7 @@ impl Parser<'_> {
251 fn compare(&mut self) -> Result<Value, String> {
250 fn compare(&mut self) -> Result<Value, String> {
252− let left = self.concat()?;
251+ let left = self.sum()?;
253 let op = if let Some(op) = self.eat_op(&["==", "!=", "<=", ">=", "<", ">"]) {
252 let op = if let Some(op) = self.eat_op(&["==", "!=", "<=", ">=", "<", ">"]) {
255 } else if self.eat_word("contains") {
254 } else if self.eat_word("contains") {
@@ -261,7 +260,7 @@ impl Parser<'_> {
262 return Ok(left);
261 return Ok(left);
264− let right = self.concat()?;
263+ let right = self.sum()?;
265 let numbers = left.as_num().zip(right.as_num());
264 let numbers = left.as_num().zip(right.as_num());
266 let (l, r) = (left.to_string(), right.to_string());
265 let (l, r) = (left.to_string(), right.to_string());
267 Ok(Value::Bool(match (op, numbers) {
266 Ok(Value::Bool(match (op, numbers) {
@@ -284,15 +283,6 @@ impl Parser<'_> {
287− fn concat(&mut self) -> Result<Value, String> {
288− let mut left = self.sum()?;
289− while self.eat_op(&["~"]).is_some() {
290− let right = self.sum()?;
291− left = Value::Str(format!("{}{}", left, right));
296 fn sum(&mut self) -> Result<Value, String> {
286 fn sum(&mut self) -> Result<Value, String> {
297 let mut left = self.product()?;
287 let mut left = self.product()?;
298 while let Some(op) = self.eat_op(&["+", "-"]) {
288 while let Some(op) = self.eat_op(&["+", "-"]) {
@@ -566,7 +556,6 @@ mod tests {
568 fn strings_and_if() {
558 fn strings_and_if() {
569− assert_eq!(ev("\"Hello \" ~ $name").to_string(), "Hello World");
570 assert_eq!(ev("\"Hi $name!\"").to_string(), "Hi World!");
559 assert_eq!(ev("\"Hi $name!\"").to_string(), "Hi World!");
571 assert_eq!(ev("if($count > 2, big, small)").to_string(), "big");
560 assert_eq!(ev("if($count > 2, big, small)").to_string(), "big");
572 assert_eq!(ev("$missing").to_string(), "");
561 assert_eq!(ev("$missing").to_string(), "");