ANTLR4监听器如何生成上下文错误并终止语法树遍历?
在ANTLR监听器中抛出致命错误并终止语法树遍历的方案
你需要在语义检查阶段(监听器中)检测一元操作符与操作数的类型不匹配问题,并立即中断语法树遍历、终止处理,以下是符合需求的具体实现方案:
核心思路
ANTLR的监听器允许抛出自定义异常来中断遍历流程,无需修改语法文件嵌入业务代码。通过定义语义异常类,在类型检查失败时抛出异常,再在遍历启动处捕获并终止程序即可。
实现步骤
1. 定义自定义语义异常类
创建一个继承自RuntimeException的异常类,用于携带错误信息和位置:
public class SemanticErrorException extends RuntimeException { public SemanticErrorException(String message, int line, int column) { super(String.format("语义错误 [%d:%d]: %s", line, column, message)); } }
2. 修改监听器的类型检查逻辑
在exitUnaryOperation方法中添加类型校验,当操作符与操作数类型不匹配时抛出异常:
@Override public void exitUnaryOperation(PolicyParser.UnaryOperationContext ctx) { String op = ctx.operator.getText(); Operator operator; switch (op) { case "+": operator = Operator.PLUS; break; case "-": operator = Operator.MINUS; break; case "!": operator = Operator.NOT; break; default: operator = null; } Expression operand = values.get(ctx.operand); // 校验一元操作符与操作数的类型匹配性 if (operator == Operator.PLUS || operator == Operator.MINUS) { // 加减操作仅支持数值类型(需根据你的Expression体系调整类型判断) if (!(operand instanceof NumericExpression)) { throw new SemanticErrorException( "一元加减操作仅支持数值类型,当前操作数类型为" + operand.getType(), ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine() ); } } else if (operator == Operator.NOT) { // 逻辑非操作仅支持布尔类型 if (!(operand instanceof BooleanExpression)) { throw new SemanticErrorException( "逻辑非操作仅支持布尔类型,当前操作数类型为" + operand.getType(), ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine() ); } } values.put(ctx, new UnaryOperation(operator, operand)); }
3. 在遍历启动代码中捕获异常并终止
启动语法树遍历的地方捕获自定义异常,输出错误后终止程序:
// 假设已完成解析得到语法树 PolicyParser parser = ...; ParseTree tree = parser.program(); // 初始化监听器和遍历器 YourCustomListener listener = new YourCustomListener(); ParseTreeWalker walker = new ParseTreeWalker(); try { walker.walk(listener, tree); // 无错误时执行后续逻辑 } catch (SemanticErrorException e) { System.err.println(e.getMessage()); System.exit(1); // 立即终止程序 }
方案优势
- 完全在监听器代码中处理语义检查,不需要修改ANTLR语法文件,避免嵌入特定语言代码
- 异常抛出后会立即中断
ParseTreeWalker的遍历流程,符合你"终止输入处理"的需求 - 异常携带行号和列号信息,能精准定位错误位置,提升调试体验
内容的提问来源于stack exchange,提问作者John Arrowwood
相关产品推荐
相关产品推荐

