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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 05:27:23