如何在ANTLR 4生成的解析树中剔除COMMA等非重要冗余节点?
ANTLR4解析树剔除无关标点节点解决方案
你可以通过两种方式实现需求,优先推荐调整解析树处理代码,无需修改已验证正常的语法文件。
方案1:调整解析树处理代码(推荐)
ANTLR4生成的解析树包含规则节点和终端节点,你只需要在遍历节点时过滤掉不需要的标点类终端节点即可,完全不需要修改现有语法。
实现逻辑:
- 先定义需要忽略的Token类型集合
- 遍历解析树时,遇到属于忽略集合的终端节点直接跳过处理即可
示例代码:
import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.antlr.v4.runtime.tree.TerminalNode; // 定义需要忽略的标点Token集合 Set<Integer> ignoredTokenTypes = new HashSet<>(Arrays.asList( IrohAsmParser.COMMA, IrohAsmParser.OPENBRACKETS, IrohAsmParser.CLOSEDBRACKETS, IrohAsmParser.OPENCURL, IrohAsmParser.CLOSECURL, IrohAsmParser.EQUALS, IrohAsmParser.AT )); // 自定义Visitor/Listener重写visitTerminal方法 @Override public void visitTerminal(TerminalNode node) { if (ignoredTokenTypes.contains(node.getSymbol().getType())) { // 直接跳过不需要的节点,不做处理 return; } // 其他需要保留的终端节点处理逻辑 } // 也可以在处理具体规则时直接跳过对应位置的节点,比如处理instruction规则: @Override public Object visitInstruction(IrohAsmParser.InstructionContext ctx) { String mnemonic = ctx.MNEMONIC().getText(); // 直接取两个操作数,自动跳过中间的COMMA节点 IrohAsmParser.FirstoperandContext firstOp = ctx.firstoperand(); IrohAsmParser.SecondoperandContext secondOp = ctx.secondoperand(); // 你的业务处理逻辑 return super.visitInstruction(ctx); }
这种方式的优势:
- 不改动已验证正确的语法,不会引入语法校验的风险
- 灵活度高,后续需要新增/移除忽略的节点直接修改集合即可
方案2:修改语法文件(可选)
ANTLR3中提供的!后缀自动排除节点的特性在ANTLR4中已经被移除,语法层面没有原生的剔除节点能力,若一定要通过语法实现干净的解析树,你可以自定义规则包装不需要的符号,但是会增加语法复杂度,不推荐使用。
注意:千万不要直接给COMMA这类分隔符加
-> skip配置,否则词法分析阶段会直接丢弃该符号,语法校验阶段无法匹配instruction规则,会直接报错。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

