如何在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
相关产品推荐
相关产品推荐

