我为ANTLR v4编写了一个带有C#目标的语法,该目标使用了一些左递归解析规则,每次我尝试解析一些应该使用这些规则的示例代码时,解析引擎选择了错误的规则。 / p>
解析规则:
expr
: expr COR term
| expr CAND term
| term
;
我正在尝试解析的代码:
...
print("Testing Program p00csx\n");
...
访问者使用解析引擎中的信息:
public override Int32 VisitExpr(CSXParser.ExprContext context)
{
if (context == null) return 0;
switch (context.altNum)
{
case 1: //expr COR term
VisitExpr(context.expr());
Console.Write(context.COR());
VisitTerm(context.term());
break;
case 2: //expr CAND term
VisitExpr(context.expr());
Console.Write(context.CAND());
VisitTerm(context.term());
break;
case 3: //term
VisitTerm(context.term());
break;
}
return 0;
}
在这个例子中,print()调用中的字符串文字应解析为'expr',它解析为'term'等,直到我们有'stringLit'。这是上例中的情况3。相反,解析器正在挑选案例1,甚至认为程序文本中没有COR('||')。
ANTLR网站说v4可以处理这些左递归表达式,这让我相信我一定做错了。我是ANTLR的新手,也许这个问题很简单,我忽略了。任何帮助将非常感激;我一直在阅读文档并运行调试器几天,然后尝试解决这个问题。
谢谢!
答案 0 :(得分:2)
出于以下原因,您应该避免使用ParserRuleContext.altNum
字段。
相反,请尝试以下任一方法:
首先检查context.expr()
是否返回null,以测试替代方案。如果是这样,那么你有一个term
。如果expr()
返回非null,则可以检查context.COR()
或context.CAND()
中的哪一个返回非null,以确定使用的实际运算符。
标记最外层的替代品,例如
expr
: expr COR term # orExpr
| expr CAND term # andExpr
| term # termExpr
;
答案 1 :(得分:-1)
我建议您删除左递归:
expr
scope
{
LogicOperator op;
}
: expr ((COR {expr.op = LogicOperator.Or;} | CAND {expr.op = LogicOperator.And;}) exp)*
| term
;
P.S。 我的ANTLR3 grammar有逻辑运算符和优先级