ANTLR PL/SQL语法无法检测缺失分号,求解决方案
解决PL/SQL语法解析中语句末尾缺失分号的检测问题
首先要明确:你使用的PlSqlLexer.g4仅负责词法分析(将代码拆分为Token单元),而语句结构合法性(包括末尾分号是否存在)的校验,是由配套的PlSqlParser.g4中的语法规则定义的。官方默认语法可能允许部分场景省略分号,要解决你的问题,可从以下方向入手:
1. 修改语法规则强制校验分号
找到PlSqlParser.g4中的顶级语句入口(比如sql_script或unit这类规则),调整规则要求所有独立SQL语句必须以分号结尾。
比如原规则可能类似:
sql_script : (sql_statement (SEMI | NEWLINE)*)* EOF;
可修改为强制要求分号:
sql_script : (sql_statement SEMI (NEWLINE)*)* EOF;
修改后,任何顶级SQL语句末尾未加都会触发语法错误。
2. 明确独立语句与PL/SQL块的边界
针对你示例中SELECT语句后紧跟匿名块的场景,需在语法规则中明确:
- 所有独立DML/查询语句必须以分号闭合
- PL/SQL块(
BEGIN...END)可以用/作为结束标记,但前提是前面的语句已正确闭合
这样就能避免解析器将未闭合的SELECT语句误认为是匿名块的一部分。
3. 自定义错误监听(可选)
如果不想修改官方语法文件,可在解析代码中添加自定义ANTLRErrorListener,针对性检测缺失分号的场景:
- 当解析器遇到意外的
BEGINToken时,检查前一个语句是否未以分号结尾 - 输出自定义错误提示,比如「语句末尾缺失分号」
验证效果
针对你提供的测试代码:
Select * From d where d.DISCOUNTNAME = '2023' BEGIN Insert into DISCOUNT_MAIN_PARAM Values ('9922'); IF SQL%ROWCOUNT = 1 THEN COMMIT; ELSE ROLLBACK; END IF; END; / Select * From d where d.DISCOUNTNAME = '2023';
修改语法规则后,解析器会在第一行末尾触发语法错误,提前拦截问题。
内容的提问来源于stack exchange,提问作者Cyrille MODIANO
相关产品推荐
相关产品推荐

