Action 不能在左递归替换中使用任何{}语句
我正在使用Java目标。我有以下简单语法:Action 不能在左递归替换中使用任何{}语句,action,antlr4,left-recursion,Action,Antlr4,Left Recursion,我正在使用Java目标。我有以下简单语法: grammmar example; alpha : alpha 'something' | 'otherthing' ; 现在,我想让解析器在输入规则alpha时,为某物打印Hello-World,为另一物打印Hello-World。因此,我想用以下方式修改我的语法: grammmar example; alpha : {System.out.pr
grammmar example;
alpha :
alpha 'something'
| 'otherthing' ;
现在,我想让解析器在输入规则alpha时,为某物打印Hello-World
,为另一物打印Hello-World
。因此,我想用以下方式修改我的语法:
grammmar example;
alpha :
{System.out.println("Hello World for something");}
alpha 'something'
| {System.out.println("Hello World for otherthing");}
'otherthing' ;
但这会导致解析器抛出错误,即规则项是相互左递归的。此错误是由于在左递归备选方案中使用任何{…}语句造成的
由于这似乎是一个bug/在ANTLR4中可以改进,我还有什么其他选择呢?ANTLR4只支持直接左递归。您在这里所做的是在一个操作之后隐藏左递归
最简单的解决方案是为语法实现一个侦听器,并在enterAlpha
的实现中添加println
语句
以下是不带操作的语法代码:
alpha
: alpha 'something'
| 'otherthing'
;
下面是带有操作代码的侦听器方法:
@Override
public void enterAlpha(AlphaContext ctx) {
if (ctx.alpha() != null) {
System.out.println("Hello World for something");
} else {
System.out.println("Hello World for otherthing");
}
}
该代码中使用的条件可能看起来很奇怪,但由于语法的编写方式,没有其他方法可以在代码中确定在alpha
中采用了哪种替代方法。这种情况可以(也可能应该)通过几种方法来解决,以提高代码的清晰度。以下提示可单独使用或组合使用
选项1:为something
和otherthing
关键字添加显式词法规则。
通过引用alpha
规则中的Something
和Otherthing
,ANTLR将在AlphaContext
中生成访问器方法,以便您直接访问为解析树中的标记创建的TerminalNode
实例
@Override
public void enterAlpha(AlphaContext ctx) {
if (ctx.Something() != null) {
System.out.println("Hello World for something");
} else if (ctx.Otherthing() != null) {
System.out.println("Hello World for otherthing");
} else {
assert ctx.exception != null; // only reachable if a parse error occurred
}
}
选项2:标记alpha
规则的外部备选方案。
这将导致ANTLR为每个备选方案生成单独的上下文类,这也允许您单独实现侦听器/访问者功能
alpha
: alpha 'something' # mySomething
| 'otherthing' # myOtherthing
;
侦听器现在可能如下所示:
@Override
public void enterMySomething(MySomethingContext ctx) {
System.out.println("Hello World for something");
}
@Override
public void enterMyOtherthing(MyOtherthingContext ctx) {
System.out.println("Hello World for otherthing");
}
@Override
public void enterMySomething(MySomethingContext ctx) {
System.out.println("Hello World for something");
}
@Override
public void enterMyOtherthing(MyOtherthingContext ctx) {
System.out.println("Hello World for otherthing");
}