ANTLR4(C#目标语言)动作中使用问号报错的问题排查
ANTLR 4 C#动作中
?.运算符引发报错的原因与解决办法 我在使用ANTLR 4生成C#代码时遇到一个问题——按照《The Definitive ANTLR 4 Reference》中的说明,动作代码块{...}里可以写任意有效的目标语言语句,但在引用可选规则exprList的属性时使用C#的空值运算符?.却触发了ANTLR的语法错误,而非C#编译错误。
以下代码可正常运行:
| ID '(' exprList? ')' { $result = creator.CreateFunctionCall( $ID, null, $exprList.result ); }
但为处理可选的exprList添加?.后,ANTLR报错:
| ID '(' exprList? ')' { $result = creator.CreateFunctionCall( $ID, null, $exprList?.result ); }
报错信息:
Error ANT02 error(67): Expr.g4:4:156: missing attribute access on rule reference exprList in $exprList
这不是ANTLR的问题,而是ANTLR的语法解析逻辑导致的歧义:ANTLR会优先将动作代码中的$exprList?识别为规则引用的可选修饰符(和语法规则里的exprList?语法一致),而非把?.当成C#的空值运算符。
解决这个歧义有两种可行方案:
方案一:用括号包裹规则引用
通过括号明确标记完整的规则属性引用,让ANTLR不会将?和$exprList绑定:| ID '(' exprList? ')' { $result = creator.CreateFunctionCall( $ID, null, ($exprList)?.result ); }这样C#编译器就能正确识别
?.运算符。方案二:先赋值给局部变量
先将exprList的属性值赋值给局部变量,再使用?.,这种方式更直观,也能彻底避免语法歧义:| ID '(' exprList? ')' { var exprResult = $exprList?.result; $result = creator.CreateFunctionCall( $ID, null, exprResult ); }
内容的提问来源于stack exchange,提问作者MadsN
相关产品推荐
相关产品推荐

