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

如何在AssignVariableBlock父上下文中获取匹配分支?附语法示例

如何在ANTLR的enterAssignVariableBlock中区分assign的不同分支?

问题描述

我定义了如下ANTLR语法规则:

simpleAssign: name = ID '=' value = (STRING | BOOLEAN | INTEGER | DOUBLE );
simpleReference: name = ID '=' value = ID;
listAssign: name = ID '=' value = listString #listStringAssign;
assign: simpleAssign #simpleVariableAssign | listAssign #listOfVariableAssign | simpleReference #referenceToVariable ;
assignVariableBlock: assign + #assignVariabels;

我希望在重写的enterAssignVariableBlock方法中,获取每个assign匹配的分支(simpleVariableAssign、listOfVariableAssign或referenceToVariable),代码框架如下:

@Override 
public void enterAssignVariableBlock(StudyParser.AssignVariableBlockContext ctx) {
    // switch matched alternative (simpleVariableAssign | listOfVariableAssign | referenceToVariable ) do
}

请问该如何实现?

解决方案

ANTLR会为语法中每个带#label的分支生成对应的上下文子类,同时在父上下文类(这里是AssignContext)中提供了便捷的判断和类型转换方法。你可以通过以下两种方式区分不同分支:

方法1:使用ANTLR生成的isXXX()和asXXX()方法

遍历assignVariableBlock下的所有assign上下文,通过isXXX()判断分支类型,再用asXXX()转换为具体的上下文类,从而获取分支内的详细信息:

@Override 
public void enterAssignVariableBlock(StudyParser.AssignVariableBlockContext ctx) {
    // 遍历所有assign节点
    for (StudyParser.AssignContext assignCtx : ctx.assign()) {
        if (assignCtx.isSimpleVariableAssign()) {
            // 处理简单变量赋值分支
            StudyParser.SimpleVariableAssignContext simpleCtx = assignCtx.asSimpleVariableAssign();
            String varName = simpleCtx.name.getText();
            String value = simpleCtx.value.getText();
            System.out.println("简单赋值:" + varName + " = " + value);
        } else if (assignCtx.isListOfVariableAssign()) {
            // 处理列表赋值分支
            StudyParser.ListOfVariableAssignContext listCtx = assignCtx.asListOfVariableAssign();
            String varName = listCtx.name.getText();
            String listValue = listCtx.value.getText();
            System.out.println("列表赋值:" + varName + " = " + listValue);
        } else if (assignCtx.isReferenceToVariable()) {
            // 处理引用赋值分支
            StudyParser.ReferenceToVariableContext refCtx = assignCtx.asReferenceToVariable();
            String varName = refCtx.name.getText();
            String refName = refCtx.value.getText();
            System.out.println("引用赋值:" + varName + " = " + refName);
        }
    }
}

方法2:通过instanceof判断上下文子类

你也可以直接遍历assignVariableBlock的子节点,用instanceof判断每个节点对应的具体上下文子类:

@Override 
public void enterAssignVariableBlock(StudyParser.AssignVariableBlockContext ctx) {
    for (ParseTree child : ctx.children) {
        if (child instanceof StudyParser.SimpleVariableAssignContext) {
            StudyParser.SimpleVariableAssignContext simpleCtx = (StudyParser.SimpleVariableAssignContext) child;
            // 简单赋值分支逻辑
        } else if (child instanceof StudyParser.ListOfVariableAssignContext) {
            StudyParser.ListOfVariableAssignContext listCtx = (StudyParser.ListOfVariableAssignContext) child;
            // 列表赋值分支逻辑
        } else if (child instanceof StudyParser.ReferenceToVariableContext) {
            StudyParser.ReferenceToVariableContext refCtx = (StudyParser.ReferenceToVariableContext) child;
            // 引用赋值分支逻辑
        }
    }
}

原理说明

当你在ANTLR语法中使用#label为分支命名时,ANTLR的代码生成器会:

  • 为每个带标签的分支创建一个单独的上下文子类(比如SimpleVariableAssignContext继承自AssignContext)
  • 在父上下文类(AssignContext)中生成isXXX()方法用于判断当前节点属于哪个分支
  • 生成asXXX()方法用于安全地将父上下文转换为具体的子上下文类型

这样你就可以轻松区分不同的赋值分支,并获取每个分支内的语法元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:57:31