抽象語法樹(AST)

 

AST描述

  在計算機科學中,抽象語法樹(AST)或語法樹是用編程語言編寫的源代碼的抽象語法結構的樹表示。樹的每一個節點表示在源代碼中出現的構造。語法是「抽象的」,由於它不表明真實語法中出現的每一個細節,而只是結構,內容相關的細節。例如,分組括號 在樹結構中是隱式的,而且能夠經過具備三個分支的單個節點來表示相似於if-condition-then表達式的句法結構。javascript

  這將抽象語法樹與傳統上指定的解析樹區分開來,這些語法樹一般由解析器在源代碼轉換和編譯過程當中構建。一旦構建,經過後續處理(例如,上下文分析)將附加信息添加到AST 。html

  抽象語法樹也用於程序分析和程序轉換系統。java

  參考:[維基百科](https://en.wikipedia.org/wiki/Abstract_syntax_tree)node

解析器Parser

  JavaScript Parser是把js源碼轉化爲抽象語法樹的解析器,通常分爲詞法分析、語法分析及代碼生成或執行。jquery

詞法分析

  詞法分析階段會把字符串形式的代碼轉換爲令牌(Tokens)流。可將令牌看做是一個扁平的語法片斷數組。git

var answer = 6 * 7;

//Tokens
[
    {
        "type": "Keyword",
        "value": "var",
        "range": [
            34,
            37
        ],
        "loc": {
            "start": {
                "line": 2,
                "column": 0
            },
            "end": {
                "line": 2,
                "column": 3
            }
        }
    },
    {
        "type": "Identifier",
        "value": "answer",
        "range": [
            38,
            44
        ],
        "loc": {
            "start": {
                "line": 2,
                "column": 4
            },
            "end": {
                "line": 2,
                "column": 10
            }
        }
    },
    {
        "type": "Punctuator",
        "value": "=",
        "range": [
            45,
            46
        ],
        "loc": {
            "start": {
                "line": 2,
                "column": 11
            },
            "end": {
                "line": 2,
                "column": 12
            }
        }
    },
    {
        "type": "Numeric",
        "value": "6",
        "range": [
            47,
            48
        ],
        "loc": {
            "start": {
                "line": 2,
                "column": 13
            },
            "end": {
                "line": 2,
                "column": 14
            }
        }
    },
    {
        "type": "Punctuator",
        "value": "*",
        "range": [
            49,
            50
        ],
        "loc": {
            "start": {
                "line": 2,
                "column": 15
            },
            "end": {
                "line": 2,
                "column": 16
            }
        }
    },
    {
        "type": "Numeric",
        "value": "7",
        "range": [
            51,
            52
        ],
        "loc": {
            "start": {
                "line": 2,
                "column": 17
            },
            "end": {
                "line": 2,
                "column": 18
            }
        }
    },
    {
        "type": "Punctuator",
        "value": ";",
        "range": [
            52,
            53
        ],
        "loc": {
            "start": {
                "line": 2,
                "column": 18
            },
            "end": {
                "line": 2,
                "column": 19
            }
        }
    }
]

  

語法分析  

  語法分析階段會把一個令牌流轉換成抽象語法樹(AST)的形式,這個階段會使用令牌中的信息把它們轉換成一個AST的樹結構。github

// Life, Universe, and Everything
var answer = 6 * 7;
// Syntax
{
    "type": "Program",
    "body": [
        {
            "type": "VariableDeclaration",
            "declarations": [
                {
                    "type": "VariableDeclarator",
                    "id": {
                        "type": "Identifier",
                        "name": "answer",
                        "range": [
                            38,
                            44
                        ],
                        "loc": {
                            "start": {
                                "line": 2,
                                "column": 4
                            },
                            "end": {
                                "line": 2,
                                "column": 10
                            }
                        }
                    },
                    "init": {
                        "type": "BinaryExpression",
                        "operator": "*",
                        "left": {
                            "type": "Literal",
                            "value": 6,
                            "raw": "6",
                            "range": [
                                47,
                                48
                            ],
                            "loc": {
                                "start": {
                                    "line": 2,
                                    "column": 13
                                },
                                "end": {
                                    "line": 2,
                                    "column": 14
                                }
                            }
                        },
                        "right": {
                            "type": "Literal",
                            "value": 7,
                            "raw": "7",
                            "range": [
                                51,
                                52
                            ],
                            "loc": {
                                "start": {
                                    "line": 2,
                                    "column": 17
                                },
                                "end": {
                                    "line": 2,
                                    "column": 18
                                }
                            }
                        },
                        "range": [
                            47,
                            52
                        ],
                        "loc": {
                            "start": {
                                "line": 2,
                                "column": 13
                            },
                            "end": {
                                "line": 2,
                                "column": 18
                            }
                        }
                    },
                    "range": [
                        38,
                        52
                    ],
                    "loc": {
                        "start": {
                            "line": 2,
                            "column": 4
                        },
                        "end": {
                            "line": 2,
                            "column": 18
                        }
                    }
                }
            ],
            "kind": "var",
            "range": [
                34,
                53
            ],
            "loc": {
                "start": {
                    "line": 2,
                    "column": 0
                },
                "end": {
                    "line": 2,
                    "column": 19
                }
            },
            "leadingComments": [
                {
                    "type": "Line",
                    "value": " Life, Universe, and Everything",
                    "range": [
                        0,
                        33
                    ],
                    "loc": {
                        "start": {
                            "line": 1,
                            "column": 0
                        },
                        "end": {
                            "line": 1,
                            "column": 33
                        }
                    }
                }
            ]
        }
    ],
    "sourceType": "script",
    "range": [
        34,
        53
    ],
    "loc": {
        "start": {
            "line": 2,
            "column": 0
        },
        "end": {
            "line": 2,
            "column": 19
        }
    }
}
View Code

常見的AST node類型

  AST樹每一層結構也被叫作節點(Node)。一個AST能夠由單一的節點或是成百上千個節點夠成,經過組合在一塊兒來描述靜態分析的程序語法(靜態分析是在不須要執行代碼的前提下對代碼進行分析的處理過程 (執行代碼的同時進行代碼分析便是動態分析)。 靜態分析的目的是多種多樣的, 它可用於語法檢查,編譯,代碼高亮,代碼轉換,優化,壓縮等等場景。)。npm

 Node types:https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API#Node_objects
編程

babel AST node types:https://github.com/babel/babylon/blob/master/ast/spec.md
 

使用esprima生成抽象語法樹流程

  以上生成的AST樹可視化工具:[esprima](http://esprima.org/demo/parse.html#)生成,經過[esprima](https://github.com/jquery/esprima)將源碼生成抽象語法樹,並經過[estraverse](https://github.com/estools/estraverse)遍歷並更新AST,最後經過[escodegen](https://github.com/estools/escodegen)將AST從新生成源碼。數組

經常使用的JavaScript Parser

  [Acorn](https://github.com/acornjs/acorn),[Esprima](https://github.com/jquery/esprima),[UglifyJS2](https://github.com/mishoo/UglifyJS2),[Babel(https://github.com/babel/babel)等

總結

  最後,根據對抽象語法樹的大概瞭解作了個demo級的將命名函數轉換爲exports函數的npm包:https://www.npmjs.com/package/fn2export,歡迎使用~~~

相關文章
相關標籤/搜索