ANTLR 4 只支持直接左递归。你在这里所做的是隐藏了一个动作后的左递归。
最简单的解决方案是为您的语法实现一个侦听器,并将println
语句添加到您的enterAlpha
.
这是没有动作的语法代码:
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
。这种情况可以(并且可能应该)通过几种方式来解决,以提高代码的清晰度。以下提示可以单独使用或组合使用。
something
选项 1:为andotherthing
关键字添加显式词法分析器规则。
alpha
: alpha Something
| Otherthing
;
Something : 'something';
Otherthing : 'otherthing';
通过在规则中引用Something
和,ANTLR 将生成访问器方法,为您提供对为解析树中的标记创建的实例的直接访问。Otherthing
alpha
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");
}