python - antlr4 python 3 从 plsql 语法打印或转储令牌
问题描述
我在 Python 中使用 antlr4 来阅读以下语法:
https://github.com/antlr/grammars-v4/tree/master/plsql
文件grants.sql只有“开始从双重选择'bob';结束;”
像树一样打印 lisp 的简单代码
from antlr4 import *
from PlSqlLexer import PlSqlLexer
from PlSqlParser import PlSqlParser
from PlSqlParserListener import PlSqlParserListener
input = FileStream('grants.sql')
lexer = PlSqlLexer(input)
stream = CommonTokenStream(lexer)
parser = PlSqlParser(stream)
tree = parser.sql_script()
print ("Tree " + tree.toStringTree(recog=parser));
因此输出为:
树 (sql_script (unit_statement (anonymous_block BEGIN (seq_of_statements (statement (sql_statement (data_manipulation_language_statements (select_statement (subquery (subquery_basic_elements (query_block SELECT (selected_element (select_list_elements (expressions (logical_expression (multiset_expression (relational_expression)) concatenation (model_expression (unary_expression (atom (常量 (quoted_string 'bob')))))))))))) (from_clause FROM (table_ref_list (table_ref (table_ref_aux (table_ref_aux_internal (dml_table_expression_clause (tableview_name (identifier (id_expression (regular_id DUAL)))))))) ))))))))) ;) 结尾 ;)) )
我希望能够拥有列出上述内容的python代码,而不是在类似lisp的语句中,而是列出所有规则和标记..即
- .sql_script
- ..unit_statement
- ...匿名块
- ....开始
等等等等
有人可以提供执行此操作的 python 代码或给我一些提示。感激不尽。
解决方案
这是一个开始:
from antlr4 import *
from antlr4.tree.Tree import TerminalNodeImpl
from PlSqlLexer import PlSqlLexer
from PlSqlParser import PlSqlParser
# Generate the lexer nad parser like this:
#
# java -jar antlr-4.7.1-complete.jar -Dlanguage=Python3 *.g4
#
def main():
lexer = PlSqlLexer(InputStream("SELECT * FROM TABLE_NAME"))
parser = PlSqlParser(CommonTokenStream(lexer))
tree = parser.sql_script()
traverse(tree, parser.ruleNames)
def traverse(tree, rule_names, indent = 0):
if tree.getText() == "<EOF>":
return
elif isinstance(tree, TerminalNodeImpl):
print("{0}TOKEN='{1}'".format(" " * indent, tree.getText()))
else:
print("{0}{1}".format(" " * indent, rule_names[tree.getRuleIndex()]))
for child in tree.children:
traverse(child, rule_names, indent + 1)
if __name__ == '__main__':
main()
打印:
sql_script
unit_statement
data_manipulation_language_statements
select_statement
subquery
subquery_basic_elements
query_block
TOKEN='SELECT'
TOKEN='*'
from_clause
TOKEN='FROM'
table_ref_list
table_ref
table_ref_aux
table_ref_aux_internal
dml_table_expression_clause
tableview_name
identifier
id_expression
regular_id
TOKEN='TABLE_NAME'
请注意,为了使词法分析器和解析器正常工作,我添加了以下 Python 类:
# PlSqlBaseLexer.py
from antlr4 import *
class PlSqlBaseLexer(Lexer):
def IsNewlineAtPos(self, pos):
la = self._input.LA(pos)
return la == -1 or la == '\n'
和:
# PlSqlBaseParser.py
from antlr4 import *
class PlSqlBaseParser(Parser):
_isVersion10 = False
_isVersion12 = True
def isVersion10(self):
return self._isVersion10
def isVersion12(self):
return self._isVersion12
def setVersion10(self, value):
self._isVersion10 = value
def setVersion12(self, value):
self._isVersion12 = value
我将其放在与生成的 Python 类相同的文件夹中。我还需要from PlSqlBaseLexer import PlSqlBaseLexer
生成PlSqlLexer.py
类中的导入语句,并修复PlSqlParser.py
from from ./PlSqlBaseParser import PlSqlBaseParser
to中的导入语句from PlSqlBaseParser import PlSqlBaseParser
。
请注意,运行演示相当慢。除非您有硬性要求在 Python 中执行此操作,否则我建议使用(非常!)更快的 Java 或 C# 目标。
推荐阅读
- scala - 模拟 BlazeClientBuilder[IO] 以返回模拟客户端 [IO]
- r - 通过 Shiny 应用程序从表数据库 SQL Server 更新数据
- html - 如何在没有模板文件的情况下使用 Ozimov Spring Boot 电子邮件工具发送 HTML 电子邮件?
- c# - 来自服务器端的数据源上的分页网格视图
- elasticsearch - 如何监控 ElasticSearch 上的搜索查询?我想知道我的用户在搜索什么
- python - Python elementtree在为非根节点插入子元素时从循环中获取重复元素
- angular - + 运算符意外连接
- php - Laravel 获取一组数组
- c# - 如何在表格下方创建公式(小计)
- python - pyfpdf write_html 内联 CSS 样式属性在 fpdf python 中不起作用