Maison  >  Article  >  développement back-end  >  Comment réaliser la visualisation de l'arbre syntaxique de quatre opérations arithmétiques simples en python

Comment réaliser la visualisation de l'arbre syntaxique de quatre opérations arithmétiques simples en python

WBOY
WBOYavant
2023-05-10 12:46:061228parcourir

Visualisation simple de l'arbre syntaxique de quatre opérations arithmétiques

Si vous voulez l'essayer, vous devez installer cette bibliothèque de visualisation Python.

Comment réaliser la visualisation de larbre syntaxique de quatre opérations arithmétiques simples en python

Parsing AST

La bibliothèque ast de Python dispose d'une méthode d'analyse qui peut analyser le contenu entrant dans un AST. Nous l'exportons ensuite en utilisant ast.dump et l'imprimons.
Remarque : indent Ce paramètre n'est disponible qu'après Python 3.9. Si la version est antérieure, vous pouvez le supprimer, ce qui n'affectera que le format de sortie final. ast.dump 将其导出并打印。
注意:indent 这个参数是 Python 3.9 以后才有的,如果版本低的话,可以去掉,只会影响最后输出的格式。

Comment réaliser la visualisation de larbre syntaxique de quatre opérations arithmétiques simples en python

好了,就是这么简单。我们已经做到了,因为这个库的功能很强大,但是这里只是用到一点点而已。其实这里已经可以看出基本的结构了,不过我的目的是生成这棵树的 JSON 表示。我想要使用上面的 Python 绘图库把它绘制出来,它所支持的输入是 JSON,并且它的格式为:

{
	"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)

运行结果:
我这里会输出两个东西,一个是 AST 的 dump;另一个是 AST 的 JSON 表示(逻辑结构的 JSON 表示,不是对象的 JSON 表示)。

Comment réaliser la visualisation de larbre syntaxique de quatre opérations arithmétiques simples en python

渲染显示

把打印出来的 JSON 字符串复制进文件,命名为 data.json。我感觉直接输出到控制台蛮有意思的,我喜欢直接看到它的结果。
执行如下命令:pytm-cli -d TB -i data.json -o demo.html
在浏览器打开 demo.html 即可看到效果了。

Comment réaliser la visualisation de larbre syntaxique de quatre opérations arithmétiques simples en python

主流的遍历方法

上面这种遍历方法虽然便于理解,但是难以扩展。AST 通常是通过 访问者模式 进行遍历的,而且 ast 库也提供了几种遍历方法。
因为这里只需要遍历来生成 JSON,并不需要修改AST本身,所以我们只看下面这两种即可。显然第一种是不能用的,原因已经用蓝色标记出来了。它自己说了如果你不关心上下文,因为生成 JSON 实际上是需要关注这个的。所以,我选择下面的 ast.NodeVisitor。使用它也很简单,继承这个类,然后对不同的节点写不同的处理逻辑就行了(这样把不同节点的逻辑分开了,降低了代码的耦合性)。

Comment réaliser la visualisation de larbre syntaxique de quatre opérations arithmétiques simples en python

完整代码

"""
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))

前面那个粗糙版本是直接从 Expr 开始的,这个优雅点的版本,我就把 Module

Comment visualiser l'arbre syntaxique des quatre opérations arithmétiques simples en Python

Comment réaliser la visualisation de larbre syntaxique de quatre opérations arithmétiques simples en pythonBien Oui, c'est aussi simple que cela. Nous l'avons fait parce que cette bibliothèque est très puissante, mais elle n'est que peu utilisée ici. En fait, la structure de base est déjà visible ici, mais mon objectif est de générer une représentation JSON de cet arbre. Je souhaite utiliser la bibliothèque de dessins Python ci-dessus pour le dessiner. L'entrée qu'elle prend en charge est JSON et son format est :

rrreee🎜Méthode de traversée approximative🎜rrreee🎜Exécuter les résultats :
Je vais en afficher deux. Il y a deux choses, l'un est un dump d'AST ; l'autre est une représentation JSON d'AST (une représentation JSON d'une structure logique, pas une représentation JSON d'un objet). 🎜🎜Comment visualiser l'arbre syntaxique des quatre opérations arithmétiques simples en python🎜 🎜Affichage de rendu 🎜🎜Copiez la chaîne JSON imprimée dans le fichier et nommez-la data.json. Je trouve assez intéressant de sortir directement sur la console. J'aime voir les résultats directement.
Exécutez la commande suivante : pytm-cli -d TB -i data.json -o demo.html
Ouvrez demo.html dans le navigateur , c'est-à-dire que vous pouvez voir l'effet. 🎜🎜Comment visualiser l'arbre syntaxique des quatre opérations arithmétiques simples en Python🎜 🎜Mainstream La méthode de traversée🎜🎜Bien que la méthode de traversée ci-dessus soit facile à comprendre, elle est difficile à développer. AST est généralement parcouru via le modèle de visiteur, et la bibliothèque ast fournit également plusieurs méthodes de parcours.
Parce qu'ici, nous n'avons besoin que de parcourir pour générer du JSON et n'avons pas besoin de modifier l'AST lui-même, nous examinons donc uniquement les deux types suivants. Évidemment, le premier ne peut pas être utilisé, et la raison a été indiquée en bleu. Cela parle de lui-même si vous ne vous souciez pas du contexte, car générer du JSON est en fait tout ce dont vous devez vous soucier. Donc, je choisis ast.NodeVisitor ci-dessous. Son utilisation est également très simple. Il suffit d'hériter de cette classe, puis d'écrire une logique de traitement différente pour différents nœuds (cela sépare la logique des différents nœuds et réduit le couplage du code). 🎜🎜Comment visualiser l'arbre syntaxique des quatre opérations arithmétiques simples en Python🎜 🎜Complete La version précédente approximative du code 🎜rrreee🎜 démarrait directement à partir de Expr. Pour cette version plus élégante, j'ai également ajouté le nœud Module. 🎜🎜🎜🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer