抽象語法樹(Abstract Syntax Tree)

抽象語法樹(Abstract Syntax Tree)

webpackLint等不少的工具和庫的核心都是經過Abstract Syntax Tree抽象語法樹這個概念來實現對代碼的檢查、分析等操做的node

  • 經過了解抽象語法樹這個概念,你也能夠隨手編寫相似的工具

抽象語法樹用途

  • 代碼語法的檢查、代碼風格的檢查、代碼的格式化、代碼的高亮、代碼錯誤提示、代碼自動補全等等webpack

    • 如JSLint、JSHint對代碼錯誤或風格的檢查,發現一些潛在的錯誤
    • IDE的錯誤提示、格式化、高亮、自動補全等等
  • 代碼混淆壓縮web

    • UglifyJS2等
  • 優化變動代碼,改變代碼結構使達到想要的結構express

    • 代碼打包工具webpack、rollup等等
    • CommonJS、AMD、CMD、UMD等代碼規範之間的轉化
    • CoffeeScript、TypeScript、JSX等轉化爲原生Javascript

抽象語法樹定義

這些工具的原理都是經過JavaScript Parser把代碼轉化爲一顆抽象語法樹(AST),這顆樹定義了代碼的結構,經過操縱這顆樹,咱們能夠精準的定位到聲明語句、賦值語句、運算語句等等,實現對代碼的分析、優化、變動等操做npm

在計算機科學中,抽象語法樹(abstract syntax tree或者縮寫爲AST),或者語法樹(syntax tree),是源代碼的抽象語法結構的樹狀表現形式,這裏特指編程語言的源代碼。

Javascript的語法是爲了給開發者更好的編程而設計的,可是不適合程序的理解。因此須要轉化爲AST來使之更適合程序分析,瀏覽器編譯器通常會把源碼轉化爲AST來進行進一步的分析等其餘操做。
JavaScript Parser編程


  • JavaScript Parser,把js源碼轉化爲抽象語法樹的解析器。
  • 瀏覽器會把js源碼經過解析器轉爲抽象語法樹,再進一步轉化爲字節碼或直接生成機器碼。
  • 通常來講每一個js引擎都會有本身的抽象語法樹格式,Chrome的v8引擎,firefox的SpiderMonkey引擎等等,MDN提供了詳細SpiderMonkey AST format的詳細說明,算是業界的標準。

經常使用的JavaScript Parser

  • esprima
  • traceur
  • acorn
  • shift

4.2 esprima

接下來咱們將下面代碼轉換成AST,而後生成先的函數newAst瀏覽器

let code = 'function ast(){}'; //js代碼便可(字符串形式)async

第一步:先安裝 esprima estraverse escodegen

npm  i esprima estraverse escodegen -D

把上面的源碼轉成AST編程語言

// 把源碼轉化爲AST
let ast = esprima.parseModule(code);
console.log(ast);

打印結果以下
Module {
type: 'Program',
body:
[ FunctionDeclaration {ide

type: 'FunctionDeclaration',
   id: [Object],
   params: [],
   body: [Object],
   generator: false,
   expression: false,
   async: false } ],

sourceType: 'module' }

接下來,遍歷AST 並更新AST

let indent = 0;
function padding() {
  return " ".repeat(indent);
}

estraverse.traverse(ast, {
  enter(node) {
    //進入

    console.log(padding() + node.type + "進入");
    if (node.type === "FunctionDeclaration") {
      node.id.name = "newAst";
    }
    indent += 2;
  },
  leave(node) {
    //離開
    indent -= 2;
    console.log(padding() + node.type + "退出");
  },
});
打印結果
Program進入
  FunctionDeclaration進入
    Identifier進入
    Identifier退出
    BlockStatement進入
    BlockStatement退出
  FunctionDeclaration退出
Program退出

最後,把修改後的抽象語法從新生成源代碼

//把修改事後的抽象語法樹從新生成源代碼
let result = escodegen.generate(ast);
console.log(result);
打印後的結果
function newAst() {
}
相關文章
相關標籤/搜索