当前位置: 首页 > 知识库问答 >
问题:

如何有效地区分ANTLR4中规则中的不同令牌?

太叔京
2023-03-14
expr    : expr (EQUALS | NOT_EQUALS) expr
        | literal;
literal : ...; // omitted here
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(),它基本上循环所有子级。这样做了多次,所以我不确定这是否明智。另外,我调用literal()两次。关于后者,我知道我可以缓存在一个局部变量中,但如果需要考虑多个子规则,这将很快导致相当丑陋的代码。

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

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());
}

共有1个答案

汪信鸥
2023-03-14

不要仅仅从代码中猜测性能。量一下!

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

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

if (ctx.getChildCount() > 1 && ((TerminalNode)ctx.getChild(1)).getSymbol().getType() == YourParser.EQUALS)
 类似资料:
  • 我有这样的语法: 问题是,我不能在polygonType、pointList规则(除了POLYGON_分隔符,我需要使用逗号)和boolOperator规则(使用逗号)中同时使用逗号标记不同的规则。换句话说,如果我们将POLYGON_分隔符改为逗号,并用这样的值测试这样的语法 我们将得到一个错误 如果有人能帮我理解这个问题,我会很高兴的。 另外,如果我们不改变当前语法,测试的值是

  • 可能在内部使用的代码将在规则之后被取消,如下所示: ANTLR4就是这样做事的吗?

  • 我对是否允许以下情况感到困惑: UPDATE:我知道当我在for循环中提供正确的声明类型时,它就会工作。问题是如果我不这样做会发生什么?

  • 现在生成的匹配器捕获“~”为未知,但为输入“~”创建3个“~”未知令牌,而不是单个“~”令牌。我应该做什么来告诉lexer为未知的连续字符生成单词令牌。我还试过“未知:.;”和“未知:.+;”没有结果。 编辑:在当前的antlr版本中。+?现在捕获剩余的单词,所以这个问题似乎已经解决了。

  • 这是我的语法文件的一部分: 段落规则应该“标记”我岛语法中的所有段落,因为我想围绕生成的段落元素生成p块。从技术上讲,所有不同的段落元素都可以识别。 问题是,不同的规则会导致侦听器中的段落调用不同。由于规则不同,这是完全合乎逻辑的,但这使得在侦听器中处理树非常困难。同一段落的两个不同条目(例如)可以在图1中找到。 输入文本为: 只有一个段落,但如果我处理树,输出的HTML将包含两个段落。 有没有办

  • 从ANTLR4开始。发现lexer规则可以是递归的https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md#recursive-莱克瑟规则。使用递归词法规则而不是递归解析器规则的用例是什么?在使用lexer递归规则时,你不会丢失所有信息吗?