ホームページ  >  記事  >  バックエンド開発  >  Pythonで単純な四則演算の構文ツリーの可視化を実現する方法

Pythonで単純な四則演算の構文ツリーの可視化を実現する方法

WBOY
WBOY転載
2023-05-10 12:46:061315ブラウズ

簡単な四則演算構文ツリーの視覚化

試してみたい場合は、この Python 視覚化ライブラリをインストールする必要があります。

Pythonで単純な四則演算の構文ツリーの可視化を実現する方法

AST の解析

Python の ast ライブラリには、受信したコンテンツを AST に解析できる解析メソッドがあります。次に、ast.dump を使用してエクスポートし、印刷します。
注: indent このパラメータは Python 3.9 以降でのみ使用できます。バージョンがそれより前の場合は削除できますが、これは最終的な出力形式にのみ影響します。

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)

実行結果:
ここには 2 つのものが出力され、1 つは AST のダンプ、もう 1 つは AST の JSON 表現 (オブジェクトの JSON 表現ではなく、論理構造の JSON 表現) です。

Pythonで単純な四則演算の構文ツリーの可視化を実現する方法

表示のレンダリング

出力された JSON 文字列をファイルにコピーし、data.json という名前を付けます。コンソールに直接出力するのはとても面白いと思います、結果を直接見るのが好きです。
次のコマンドを実行します: pytm-cli -d TB -i data.json -odemo.html
ブラウザで demo.html を開いて効果を確認します。 。

Pythonで単純な四則演算の構文ツリーの可視化を実現する方法

主流の走査手法

上記の走査手法は理解するのは簡単ですが、拡張するのは困難です。 AST は通常、Visitor パターン を介して走査され、ast ライブラリにはいくつかの走査メソッドも提供されます。
JSON を生成するためにトラバースするだけで済み、AST 自体を変更する必要がないため、次の 2 つのタイプのみを確認します。明らかに最初のものは使用できず、その理由は青でマークされています。実際に気にする必要があるのは JSON の生成だけであるため、コンテキストを気にしないのであれば、それ自体が物語っています。したがって、以下では ast.NodeVisitor を選択します。使い方も非常に簡単で、このクラスを継承し、ノードごとに異なる処理ロジックを記述するだけです(これにより、異なるノードのロジックが分離され、コードの結合が軽減されます)。

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 ノードも追加されます。

Pythonで単純な四則演算の構文ツリーの可視化を実現する方法

以上がPythonで単純な四則演算の構文ツリーの可視化を実現する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。