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

ANTLR4从4.6升级至4.9.2后Lexer对非法输入未抛出运行时异常

ANTLR 4.6升级到4.7+版本后,词法和语法解析的默认错误恢复策略做了优化,默认会尝试跳过无效字符/自动修复错误继续解析,原有只给Lexer加错误监听器的配置就会失效,按以下步骤修改即可:


第一步:补全语法规则并添加兜底词法错误规则

你当前提供的语法规则存在缺失,包括空白符处理、字符串、数字、标识符及符号的词法规则,simpleFilter用到的value也没有定义,需要先补全规则,同时在所有词法规则的末尾添加兜底错误规则,确保所有无法匹配的字符都会触发错误:

grammar Filter;

start
 : appfilter
 ; 

appfilter
 : LBRACE appfilter RBRACE
 | negate LBRACE appfilter RBRACE
 | appfilter logical appfilter
 | simpleFilter
 | complexFilter
 ; 

complexFilter
 : key LSQBRACE appfilter RSQBRACE
 | key LSQBRACE appfilter RSQBRACE DOT_SEPARATOR simpleFilter
 ; 

simpleFilter
 : key binary value
 | key unary
 ; 

key
 : PATH
 | ATTRIBUTE
 ;
// 补充value规则
value : STRING | NUMBER;

binary  : EQ; 
unary   : PR; 
logical : AND | OR; 
negate  : NOT;

// 原有词法规则
EQ      : 'eq' | 'EQ' | 'Eq' | 'eQ'; 
PR      : 'pr' | 'PR' | 'Pr' | 'pR'; 
NOT     : 'not'; 
AND     : 'and'; 
OR      : 'or';
LBRACE : '(';
RBRACE : ')';
LSQBRACE : '[';
RSQBRACE : ']';
DOT_SEPARATOR : '.';

// 新增必备词法规则,可根据业务需求调整
WS : [ \t\r\n]+ -> skip; // 跳过空白符
STRING : '"' (~["\\] | '\\' .)* '"';
NUMBER : [0-9]+;
PATH : [a-z]+ ('.' [a-z]+)*;
ATTRIBUTE : '@' [a-z]+;

// 兜底错误规则,必须放在所有词法规则最后,优先级最低,匹配所有未被前面规则匹配的字符
ERROR_TOKEN : . ;

第二步:统一配置Lexer和Parser的错误处理逻辑

默认ANTLR的Lexer和Parser都会自带一个仅打印日志的ConsoleErrorListener,你需要先移除默认监听器,再添加自定义的抛异常监听器,同时替换Parser的默认错误恢复策略,禁止自动修复错误:

// 1. 配置Lexer错误处理
lexer.removeErrorListeners(); // 移除默认的控制台打印监听器
lexer.addErrorListener(new BaseErrorListener()  {
    @Override
    public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
        throw new RuntimeException(String.format("词法错误,位置%d:%d,错误信息:%s", line, charPositionInLine, msg), e);
    }
});

CommonTokenStream tokens = new CommonTokenStream(lexer);
FilterParser parser = new FilterParser(tokens);

// 2. 配置Parser错误处理
parser.removeErrorListeners(); // 同样移除Parser的默认监听器
parser.addErrorListener(new BaseErrorListener() {
    @Override
    public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
        throw new RuntimeException(String.format("语法错误,位置%d:%d,错误信息:%s", line, charPositionInLine, msg), e);
    }
});
// 替换错误恢复策略,遇到错误直接终止,不尝试自动修复
parser.setErrorHandler(new BailErrorStrategy());

// 执行解析
parser.start();

修改完成后再测试输入title eq "Emplyee" 1234,会直接抛出对应的运行时异常,不会再被自动恢复跳过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 06:36:00