You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Antlr4技术问询:获取匹配子规则的名称

解决ANTLR监听器中获取匹配子规则名称的问题

嘿,Dines!针对你在ANTLR监听器里想获取location规则匹配的子规则(比如location_A/location_B/location_C)名称的需求,这里有几个实用的方案,我给你详细说说:

方案1:通过规则索引+解析器的ruleNames数组获取

ANTLR生成的每个解析器规则上下文类(比如LocationContext)都继承自ParserRuleContext,其中包含getRuleIndex()方法,能拿到当前上下文对应的规则索引。而你的解析器类会自动生成一个ruleNames字符串数组,里面按顺序存储了所有规则的名称,索引和规则是一一对应的。

假设你的语法规则是这样的:

location : location_A | location_B | location_C;
location_A : 'A' ID;
location_B : 'B' NUM;
location_C : 'C' STRING;

那在监听器的exitLocation方法里可以这么写:

@Override
public void exitLocation(YourParser.LocationContext ctx) {
    // 因为location是选择分支规则,第一个子节点就是匹配的子规则上下文
    ParserRuleContext matchedSubCtx = (ParserRuleContext) ctx.getChild(0);
    // 获取子规则的索引
    int subRuleIndex = matchedSubCtx.getRuleIndex();
    // 从解析器的ruleNames数组中拿到子规则名称
    String subRuleName = YourParser.ruleNames[subRuleIndex];
    System.out.println("当前匹配的子规则:" + subRuleName);
}

这个方法的好处是不需要硬编码规则名称,适合规则较多的场景。

方案2:直接判断上下文类型(更直观)

ANTLR会为每个语法规则生成专属的上下文类,比如Location_AContext、Location_BContext,你可以通过解析器上下文提供的 getter 方法直接判断匹配的子规则:

@Override
public void exitLocation(YourParser.LocationContext ctx) {
    if (ctx.location_A() != null) {
        System.out.println("匹配的子规则:location_A");
    } else if (ctx.location_B() != null) {
        System.out.println("匹配的子规则:location_B");
    } else if (ctx.location_C() != null) {
        System.out.println("匹配的子规则:location_C");
    }
}

这种方式代码可读性更高,适合规则结构清晰、分支不多的场景,维护起来也更方便。

注意事项

  • 如果你的location规则不是简单的选择分支,而是包含嵌套、重复等结构,需要调整遍历子节点的逻辑,比如通过ctx.getChildren()遍历所有子节点,筛选出ParserRuleContext类型的节点(跳过令牌节点)。
  • 避免通过子节点文本反推规则名称,这种方式容易因为文本重复导致误判,可靠性很低。

希望这些方案能帮你顺利解决问题!

内容的提问来源于stack exchange,提问作者Elipson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:48:43