gpt4 book ai didi

java - 如何有效区分ANTLR4规则中的不同标记?

转载 作者:行者123 更新时间:2023-11-30 06:04:15 25 4
gpt4 key购买 nike

我有一个简单的语法规则:

expr    : expr (EQUALS | NOT_EQUALS) expr
| literal;
literal : ...; // omitted here

词法分析器识别 EQUALSNOT_EQUALS:

EQUALS     : '=';
NOT_EQUALS : '!=';

在我的代码中,我想区分等于不等于情况。我想知道如何有效地做到这一点。目前,我按如下方式实现访问者:

public Expression visitExpr(ExprContext ctx) {
if (ctx.EQUALS() != null) {
return EqualsExpression.construct(ctx.expr());
} else if (ctx.NOT_EQUALS() != null) {
return NotEqualsExpression.construct(ctx.expr());
} else if (ctx.literal() != null) {
return LiteralExpression.construct(ctx.literal());
}
throw new IllegalStateException();
}

我不确定这是否非常有效,因为 EQUALS()/NOT_EQUALS() 调用 getToken(),它基本上是循环的通过所有的 child 。这已经完成了多次,所以我不确定这是否明智。另外,我调用了literal()两次。关于后者,我知道我可以缓存在本地变量中,但是如果要考虑多个子规则,这将很快以相当难看的代码结束。

有没有办法更有效地做到这一点?基于某种 token 标识符或分支标识符的 switch/case 语句会更理想吗?

旁注

我可以将 expr 规则拆分为多个规则,如下所示:

expr         : expr_eq | expr_not_eq | expr_literal
expr_eq : expr EQUALS expr
expr_not_eq : expr NOT_EQUALS expr
expr_literal : literal

现在,访问者将单独访问每个可能的分支:

public Expression visitExprEx(ExprEqContext ctx) {
return EqualsExpression.construct(ctx.expr());
}

public Expression visitExprNotEq(ExprNotEqContext ctx) {
return NotEqualsExpression.construct(ctx.expr());
}

public Expression visitExprLiteral(ExprLiteralContext ctx) {
return LiteralExpression.construct(ctx.literal());
}

但是查看 Github 上的 G4 语法 ( https://github.com/antlr/grammars-v4 ),很少有人这样做。所以我不确定这是否是前进的方向。

最佳答案

永远不要仅通过查看代码来猜测性能。测量一下!

子列表非常短,这意味着 getToken在找到 EQUALS 之前只执行 1-2 次循环或NOT_EQUALS 。代码的其他部分可能需要比查找更多的时间。

但是,如果您想获得每一项性能,请避免使用方便的方法并手动执行操作,因为您可以根据您对语法的了解来优化访问。在这种特殊情况下,您的 expr 规则只能有 1 或 3 个子规则。查看第一个变体,它可以获得一个 literal规则子节点或 expr规则子节点,内部 alt 的 token 子节点和另一个 expr规则子节点。您所要做的就是检查:

if (ctx.getChildCount() > 1 && ((TerminalNode)ctx.getChild(1)).getSymbol().getType() == YourParser.EQUALS)

关于java - 如何有效区分ANTLR4规则中的不同标记?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51692873/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com