Jika anda ingin mencubanya, anda perlu memasang pustaka visualisasi python ini.
Python's ast library mempunyai kaedah parse yang boleh menghuraikan kandungan masuk ke dalam AST. Kemudian kami menggunakan ast.dump
untuk mengeksport dan mencetaknya.
Nota: indent
Parameter ini hanya tersedia selepas Python 3.9 Jika versi lebih awal, anda boleh mengalih keluarnya hanya akan menjejaskan format output akhir.
Baiklah, semudah itu. Kami telah melakukannya kerana perpustakaan ini sangat berkuasa, tetapi ia hanya digunakan sedikit di sini. Sebenarnya, struktur asas sudah boleh dilihat di sini, tetapi tujuan saya adalah untuk menghasilkan perwakilan JSON bagi pokok ini. Saya ingin menggunakan perpustakaan lukisan Python di atas untuk melukisnya Input yang disokongnya ialah JSON, dan formatnya ialah:
{ "name": "A", "children": [ "name": "B", "children": [] ] }
""" Python's AST 利用 Python 的 ast 模块来解析表达式(简单的二元运算), 然后通过遍历语法树来生成 JSON 表示,再使用 PYthon 的库来 将其可视化。这个程序的目的是为了验证自己写的简易解析器是否正确。 """ import ast import json # 操作类型和操作符映射的字典 OPERATORS = { ast.Add: "+", ast.Sub: "-", ast.Mult: "*", ast.Div: "/" } def generate(tree: ast.Module): """ generate expression AST's representation of JSON """ if not tree: raise Exception("Emtpy AST tree!") if tree.__class__ == ast.Module: print(json.dumps({ "name": "Expr", "children": [DFS(tree.body[0].value)] # type: ignore }, indent=4)) def DFS(node): """ DFS AST """ if not node: return {} if node.__class__ == ast.BinOp: return { "name": "BinOp", "children": [ { "name": "left", "children": [ DFS(node.left) ] }, DFS(node.op), { "name": "left", "children": [ DFS(node.right) ] } ] } if node.__class__ == ast.Constant: return { "name": "NUMBER", "children": [ { "name": str(node.value) # Python 的绘图库,必须是字符串才能正常显示 } ] } if node.__class__ in [ast.Add, ast.Sub, ast.Mult, ast.Div]: return { "name": "Op", "children": [ { "name": OPERATORS[node.__class__] } ] } # 这里我只处理 加减乘除和数字类型的运行 raise Exception("There is not support extra type.") if __name__ == "__main__": ast_tree = ast.parse("1+2+3+4+5") print(ast.dump(ast_tree, indent=4)) generate(ast_tree)
Hasil berjalan:
Saya akan keluarkan dua perkara di sini, satu ialah pembuangan AST; yang satu lagi ialah perwakilan JSON bagi AST (perwakilan JSON bagi struktur logik, bukan perwakilan JSON bagi objek).
Salin rentetan JSON yang dicetak ke dalam fail dan namakannya data.json
. Saya rasa agak menarik untuk output terus ke konsol Saya suka melihat hasilnya secara langsung.
Laksanakan arahan berikut: pytm-cli -d TB -i data.json -o demo.html
Buka demo.html
dalam penyemak imbas untuk melihat kesannya.
Walaupun kaedah traversal di atas mudah difahami, ia sukar untuk dikembangkan. AST biasanya dilalui melalui corak Pelawat, dan perpustakaan ast juga menyediakan beberapa kaedah traversal.
Oleh kerana di sini kita hanya perlu merentasi untuk menjana JSON dan tidak perlu mengubah suai AST itu sendiri, jadi kita hanya melihat dua jenis berikut. Jelas sekali yang pertama tidak boleh digunakan, dan sebabnya telah ditandakan dengan warna biru. Ia bercakap untuk dirinya sendiri jika anda tidak mengambil berat tentang konteks, kerana menjana JSON sebenarnya adalah semua yang anda perlu ambil berat. Jadi, saya pilih ast.NodeVisitor
di bawah. Menggunakannya juga sangat mudah. Hanya warisi kelas ini dan kemudian tulis logik pemprosesan yang berbeza untuk nod yang berbeza (ini memisahkan logik nod yang berbeza dan mengurangkan gandingan kod).
""" Python's AST 利用 Python 的 ast 模块来解析表达式(简单的二元运算), 然后通过遍历语法树来生成 JSON 表示,再使用 PYthon 的库来 将其可视化。这个程序的目的是为了验证自己写的简易解析器是否正确。 """ import ast import json # 操作类型和操作符映射的字典 OPERATORS = { ast.Add: "+", ast.Sub: "-", ast.Mult: "*", ast.Div: "/" } class JSONVisitor(ast.NodeVisitor): """ JSON visitor: Traversal AST and generate JSON representation """ def visit_Module(self, node): module = { "name": "Module", "children": [] } for sub_node in node.body: module["children"].append(self.visit(sub_node)) return module def visit_Expr(self, node): return { "name": "Expr", "children": [ self.visit(node.value) ] } def visit_BinOp(self, node): return { "name": "BinOp", "children": [ { "name": "left", "children": [ self.visit(node.left) ] }, self.visit(node.op), { "name": "right", "children": [ self.visit(node.right) ] } ] } def visit_Constant(self, node): return { "name": "NUMBER", "children": [{ "name": str(node.value) # # Python 的绘图库,必须是字符串才能正常显示 }] } def visit_Add(self, node): return self.__visit(node) def visit_Sub(self, node): return self.__visit(node) def visit_Mult(self, node): return self.__visit(node) def visit_Div(self, node): return self.__visit(node) def __visit(self, node): return { "name": "Op", "children": [{ "name": OPERATORS[node.__class__] }] } if __name__ == "__main__": ast_tree = ast.parse("1+2+3+4+5") visitor = JSONVisitor() json_str = visitor.visit(ast_tree) print(json.dumps(json_str, indent=4))
Versi kasar sebelumnya bermula terus daripada Expr
Untuk versi yang lebih elegan ini, saya meletakkan nod Module
Juga ditambah .
Atas ialah kandungan terperinci Bagaimana untuk melaksanakan visualisasi pokok sintaks operasi empat aritmetik mudah dalam python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!