如何修复LALR(1) Lark DSL语法,解析无括号&&连接的多赋值表达式?
解决LALR(1) Lark语法中
&&与赋值语句的解析冲突问题 问题根源
当前语法在解析(a == 2 && b == 3) ? (c = 12 && d = 13);时,错误尝试将其解析为(c = (12 && d) = 13),核心原因是表达式层级结构不符合需求:
- 原规则中
logical_and_expression仅接受equality_expression作为操作数,无法识别赋值表达式 - 赋值表达式的右递归规则会强制将
12 && d =13视为赋值右操作数,而12 && d并非合法的赋值左值,最终导致解析失败
修复方案
调整表达式层级,让赋值表达式可以作为逻辑与运算符的操作数,同时保持运算符优先级和语义的正确性。修改后的完整Lark语法如下:
?start: statement* ?statement: expression ";" ?expression : conditional_expression ?conditional_expression : logical_or_expression | logical_or_expression "?" expression (":" expression)? ?logical_or_expression : logical_and_expression | logical_or_expression "||" logical_and_expression ?logical_and_expression : assignment_expression | logical_and_expression "&&" assignment_expression ?assignment_expression : equality_expression | primary_expression assignment_op assignment_expression ?equality_expression : relational_expression | equality_expression equals_op relational_expression | equality_expression not_equals_op relational_expression ?relational_expression : additive_expression | relational_expression less_than_op additive_expression | relational_expression greater_than_op additive_expression | relational_expression less_than_eq_op additive_expression | relational_expression greater_than_eq_op additive_expression ?additive_expression : multiplicative_expression | additive_expression add_op multiplicative_expression | additive_expression sub_op multiplicative_expression ?multiplicative_expression : primary_expression | multiplicative_expression mul_op primary_expression | multiplicative_expression div_op primary_expression | multiplicative_expression mod_op primary_expression ?primary_expression : variable | variable "[" INT "]" -> array_accessor | ESCAPED_STRING | NUMBER | unary_op expression | invoke_expression | "(" expression ")" invoke_expression : ID ("." ID)* "(" argument_list? ")" argument_list : expression ("," expression)* unary_op : "-" -> negate_op | "!" -> invert_op assignment_op : "=" add_op : "+" sub_op : "-" mul_op : "*" div_op : "/" mod_op : "%" equals_op : "==" not_equals_op : "!=" greater_than_op : ">" greater_than_eq_op : ">=" less_than_op : "<" less_than_eq_op : "<=" ID : CNAME | CNAME "%%" CNAME ?variable : ID | ID "@" ID -> namelist_id | ID "@" ID "@" ID -> exptype_id | "$" ID -> environment_id %import common.WS %import common.ESCAPED_STRING %import common.CNAME %import common.INT %import common.NUMBER %import common.CPP_COMMENT %ignore WS %ignore CPP_COMMENT
关键修改说明
- 调整逻辑与表达式的操作数类型:将
logical_and_expression的基础规则从equality_expression改为assignment_expression,允许赋值表达式作为逻辑与的操作数,确保c=12 && d=13被解析为(c=12) && (d=13)。 - 重构表达式层级:将
expression的顶层改为conditional_expression,确保三元条件表达式可以包含赋值和逻辑表达式;同时将assignment_expression的基础规则改为equality_expression,避免层级混乱。 - 保留原有语义:所有原合法示例(如带括号的逻辑与、三元条件语句)仍可正常解析,不会破坏现有功能。
内容的提问来源于stack exchange,提问作者MerseyViking
相关产品推荐
相关产品推荐

