diff --git a/cli/src/template.pest b/cli/src/template.pest index b40f71a6a..89e24cc17 100644 --- a/cli/src/template.pest +++ b/cli/src/template.pest @@ -71,14 +71,10 @@ expression = { ~ (whitespace* ~ infix_ops ~ whitespace* ~ (prefix_ops ~ whitespace*)* ~ term)* } -// Use 'term' instead of 'expression' to disallow 'x || y ++ z'. It can be -// parsed, but the precedence isn't obvious. -concat = _{ - term ~ (whitespace* ~ concat_op ~ whitespace* ~ term)+ +template = { + expression ~ (whitespace* ~ concat_op ~ whitespace* ~ expression)* } -template = { concat | expression } - program = _{ SOI ~ whitespace* ~ template? ~ whitespace* ~ EOI } function_alias_declaration = { diff --git a/cli/src/template_parser.rs b/cli/src/template_parser.rs index 8c42717a0..60347b985 100644 --- a/cli/src/template_parser.rs +++ b/cli/src/template_parser.rs @@ -52,7 +52,6 @@ impl Rule { Rule::primary => None, Rule::term => None, Rule::expression => None, - Rule::concat => None, Rule::template => None, Rule::program => None, Rule::function_alias_declaration => None, @@ -476,7 +475,6 @@ fn parse_template_node(pair: Pair) -> TemplateParseResult let mut nodes: Vec<_> = inner .filter_map(|pair| match pair.as_rule() { Rule::concat_op => None, - Rule::term => Some(parse_term_node(pair)), Rule::expression => Some(parse_expression_node(pair)), r => panic!("unexpected template item rule {r:?}"), }) @@ -1070,11 +1068,16 @@ mod tests { parse_normalized("x || (y && (z.h()))").unwrap(), ); - // Top-level expression is allowed, but not in concatenation - assert!(parse_template(r"x && y").is_ok()); - assert!(parse_template(r"f(x && y)").is_ok()); - assert!(parse_template(r"x && y ++ z").is_err()); - assert!(parse_template(r"(x && y) ++ z").is_ok()); + // Logical operator bounds more tightly than concatenation. This might + // not be so intuitive, but should be harmless. + assert_eq!( + parse_normalized(r"x && y ++ z").unwrap(), + parse_normalized(r"(x && y) ++ z").unwrap(), + ); + assert_eq!( + parse_normalized(r"x ++ y || z").unwrap(), + parse_normalized(r"x ++ (y || z)").unwrap(), + ); // Expression span assert_eq!(parse_template(" ! x ").unwrap().span.as_str(), "! x");