Antlr4 Python解析PLSQL包时出现NameError问题求助
PLSQL语法解析报错:
NameError: name 'this' is not defined分析 问题场景
在Ubuntu 22.04中部署Python版Antlr4 PLSQL解析环境的步骤:
- 下载基础类与语法文件:
wget https://github.com/antlr/grammars-v4/blob/master/sql/plsql/Python3/PlSqlLexerBase.py wget https://github.com/antlr/grammars-v4/blob/master/sql/plsql/Python3/PlSqlParserBase.py wget https://github.com/antlr/grammars-v4/blob/master/sql/plsql/PlSqlLexer.g4 wget https://github.com/antlr/grammars-v4/blob/master/sql/plsql/PlSqlParser.g4
- 安装运行依赖:
pip3 install antlr4-python3-runtime==4.13.1
测试以下匿名PLSQL块时,解析可正常生成语法树:
DECLARE l_x NUMBER; BEGIN SELECT length(c1) INTO l_x FROM the_table WHERE c2 = 'X'; END;
但解析以下PLSQL包定义文件时触发错误:
CREATE OR REPLACE PACKAGE pa_tsheet AS -- PROCEDURE pr_new_tsheet_template ( p_act_id IN timesheets.act_id %TYPE, p_apd_id IN timesheets.apd_id %TYPE, p_weekend_yn IN VARCHAR2, p_job_desc IN timesheet_items.job_details %TYPE, p_job_rate IN timesheet_items.rate %TYPE, p_job_hours IN timesheet_items.hours %TYPE, p_tms_id IN OUT timesheets.id %TYPE ); -- END pa_tsheet; /
错误栈信息如下:
python3 ./runPLSQLFiles.py ../pa_tsheet.pkh 2>&1 Traceback (most recent call last): File "antlr_plsql/grammars/./runPLSQLFiles.py", line 33, in <module> main() File "antlr_plsql/grammars/./runPLSQLFiles.py", line 19, in main tree = parser.sql_script() File "antlr_plsql/grammars/PlSqlParser.py", line 15340, in sql_script self.unit_statement() File "antlr_plsql/grammars/PlSqlParser.py", line 16370, in unit_statement self.create_package() File "antlr_plsql/grammars/PlSqlParser.py", line 25046, in create_package self.consume() File ".local/lib/python3.10/site-packages/antlr4/Parser.py", line 348, in consume self.getInputStream().consume() File ".local/lib/python3.10/site-packages/antlr4/BufferedTokenStream.py", line 101, in consume self.index = self.adjustSeekIndex(self.index + 1) File ".local/lib/python3.10/site-packages/antlr4/CommonTokenStream.py", line 45, in adjustSeekIndex return self.nextTokenOnChannel(i, self.channel) File ".local/lib/python3.10/site-packages/antlr4/BufferedTokenStream.py", line 214, in nextTokenOnChannel self.sync(i) File ".local/lib/python3.10/site-packages/antlr4/BufferedTokenStream.py", line 112, in sync fetched = self.fetch(n) File ".local/lib/python3.10/site-packages/antlr4/BufferedTokenStream.py", line 124, in fetch t = self.tokenSource.nextToken() File ".local/lib/python3.10/site-packages/antlr4/Lexer.py", line 137, in nextToken ttype = self._interp.match(self._input, self._mode) File ".local/lib/python3.10/site-packages/antlr4/atn/LexerATNSimulator.py", line 104, in match return self.execATN(input, dfa.s0) File ".local/lib/python3.10/site-packages/antlr4/atn/LexerATNSimulator.py", line 173, in execATN target = self.computeTargetState(input, s, t) File ".local/lib/python3.10/site-packages/antlr4/atn/LexerATNSimulator.py", line 231, in computeTargetState self.getReachableConfigSet(input, s.configs, reach, t) File ".local/lib/python3.10/site-packages/antlr4/atn/LexerATNSimulator.py", line 280, in getReachableConfigSet if self.closure(input, config, reach, currentAltReachedAcceptState, True, treatEofAsEpsilon): File ".local/lib/python3.10/site-packages/antlr4/atn/LexerATNSimulator.py", line 359, in closure currentAltReachedAcceptState = self.closure(input, c, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon) File ".local/lib/python3.10/site-packages/antlr4/atn/LexerATNSimulator.py", line 357, in closure c = self.getEpsilonTarget(input, config, t, configs, speculative, treatEofAsEpsilon) File ".local/lib/python3.10/site-packages/antlr4/atn/LexerATNSimulator.py", line 396, in getEpsilonTarget if self.evaluatePredicate(input, t.ruleIndex, t.predIndex, speculative): File ".local/lib/python3.10/site-packages/antlr4/atn/LexerATNSimulator.py", line 465, in evaluatePredicate return self.recog.sempred(None, ruleIndex, predIndex) File "antlr_plsql/grammars/PlSqlLexer.py", line 16736, in sempred return pred(localctx, predIndex) File "antlr_plsql/grammars/PlSqlLexer.py", line 16747, in PROMPT_MESSAGE_sempred return this.IsNewlineAtPos(-4) NameError: name 'this' is not defined
错误原因分析
- 生成代码的语法兼容性问题:Antlr生成的
PlSqlLexer.py文件中,PROMPT_MESSAGE_sempred方法错误使用了Java风格的this关键字,而Python中应该用self指代当前实例。这是PLSQL语法定义中的语义谓词在生成Python代码时未完成语法适配导致的。 - 触发条件:包定义末尾的
/符号会触发Lexer中PROMPT_MESSAGE规则的语义检查,而该检查方法中的this未被替换为self,直接抛出NameError。匿名块没有结尾的/,因此不会触发该规则,解析正常。 - 根源:antlr/grammars-v4仓库中的PLSQL语法文件(
PlSqlLexer.g4)的语义谓词实现,针对Python代码生成的兼容性处理存在缺陷,未适配Python的实例引用语法。
内容的提问来源于stack exchange,提问作者Pro West
相关产品推荐
相关产品推荐

