🧌
AST について調べてみた
AST(Abstract Syntax Tree) とは
- プログラムの文法構造を木構造で表したもの
- ソースコード:人間が読みやすいもの
- AST:コンピュータが読みやすいもの
下記は簡単な Python のソースコードを AST を用いて表現した例です.
AST 変換
Python には AST ライブラリが用意されているため,AST を簡単に生成することができます.
まず,print('Hello, World!')
というコードを AST に変換してみます.
import ast
code = "print('Hello, World!')"
parsed_src = ast.parse(code)
print(ast.dump(parsed_src, indent=4))
アウトプットは以下のようになります.
Module(
body=[
Expr(
value=Call(
func=Name(id='print', ctx=Load()),
args=[
Constant(value='Hello, World!')],
keywords=[]))],
type_ignores=[])
各ノードの説明は以下の通りです.
- Module: プログラム全体が一つのモジュールとして扱われる
- body: 実行される文(statement)が配列として格納される
- Expr: 式(expression)を表すノード
-
Call: 関数呼び出しを表現(
print()
の部分) -
func: 呼び出される関数名(
print
) - Name: 変数名や関数名を表すノード
- ctx=Load(): 値を読み込むコンテキストを示す(値を取得して使用)
- args: 関数の引数を配列として管理
-
Constant: 文字列や数値などのリテラル値(
'Hello, World!'
) - keywords: 名前付き引数(今回は空の配列)
- type_ignores: 型チェックの無視指定(今回は空の配列)
AST 変換 ~ 関数 ~
次に簡単な Python 関数を AST に変換してみます.
import ast
code = """
def add(a, b):
return a + b
"""
parsed_src = ast.parse(code)
print(ast.dump(parsed_src, indent=4))
アウトプットは以下のようになります.
Module(
body=[
FunctionDef(
name='add',
args=arguments(
posonlyargs=[],
args=[
arg(arg='a'),
arg(arg='b')],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=[
Return(
value=BinOp(
left=Name(id='a', ctx=Load()),
op=Add(),
right=Name(id='b', ctx=Load())))],
decorator_list=[],
type_params=[])],
type_ignores=[])
この結果からわかることは以下の通りです.
- Module ノードがプログラム全体を表す
-
FunctionDef ノードで
add
関数が定義されている-
args に引数
a
,b
が含まれる -
body に Return ノードが 1 つだけあり,戻り値として BinOp(Add) で
a + b
を計算している
-
args に引数
- 装飾子(decorator_list)や型パラメータ(type_params)は無く,シンプルな関数定義である
- type_ignores が空なので型無視指示も無い
AST 視覚化
先ほどご紹介した add
関数を視覚化すると以下のようになります.
ちなみに,こちらから簡単に作成可能です.使用時は,parser
を python
に変更することを忘れないようにしてください.
まとめ
- プログラムの文法構造を木構造で表したもの
- Python の AST ライブラリを用いて,AST を生成することができる
参考文献
Discussion