使用ANTLR 4解决类Java表达式的解析歧义问题
针对(something) -x的解析歧义问题,要让解析器优先选择带转换的一元表达式而非二元减法表达式,核心是调整语法规则的优先级层次,确保转换表达式(CastExpression)和一元表达式(UnaryExpression)的优先级高于加减二元表达式(AdditiveExpression)。以下是具体实现方案,无需消除直接左递归:
修改后的语法规则
expression : additiveExpression ; additiveExpression : unaryCastExpression ( (Plus | Minus) unaryCastExpression )* | unaryCastExpression ; unaryCastExpression : LeftParen expr = expression RightParen # ParenthesizedExpression | id = Identifier # IdentifierExpression | op = (Minus | BitwiseNot) expr = unaryCastExpression # UnaryExpression | < assoc = right > LeftParen type = Identifier RightParen expr = unaryCastExpression # CastExpression ;
规则说明
分层设计优先级:
- 最高优先级:
unaryCastExpression,包含括号表达式、标识符、一元运算符表达式、类型转换表达式。 - 较低优先级:
additiveExpression,仅允许将unaryCastExpression作为操作数进行加减运算。
这样解析器会优先尝试匹配高优先级的类型转换+一元表达式组合,而非将(something)作为二元减法的左操作数。
- 最高优先级:
保留直接左递归:
additiveExpression使用了ANTLR4支持的直接左递归写法(( (Plus | Minus) unaryCastExpression )*),无需手动消除左递归,同时保证加减运算的左结合性。右结合的转换表达式:
保留原规则中< assoc = right >修饰的CastExpression,确保连续转换(如(A)(B)x)能正确解析为(A)((B)x)。
效果验证
修改后,(something) -x会被优先解析为:
CastExpression(type=something, expr=UnaryExpression(op=Minus, expr=IdentifierExpression(id=x)))
而非原来的:
AdditiveExpression(left=ParenthesizedExpression(expr=IdentifierExpression(id=something)), op=Minus, right=UnaryExpression(op=Minus, expr=IdentifierExpression(id=x)))
内容的提问来源于stack exchange,提问作者Llama Boy

