抽象語法樹

什么是AST

在計(jì)算機(jī)科學(xué)中,抽象語法樹(Abstract Syntax Tree,AST),或簡稱語法樹(Syntax tree),是源代碼語法結(jié)構(gòu)的一種抽象表示。它以樹狀的形式表現(xiàn)編程語言的語法結(jié)構(gòu)。

AST 的功能十分強(qiáng)大。大名鼎鼎的webpack babel等前端工具都是借助AST來實(shí)現(xiàn)的。

AST在日常業(yè)務(wù)中也許很難涉及到。事實(shí)上,在javascript世界中,我們可以認(rèn)為抽象語法樹(AST)是最底層。 再往下,就是關(guān)于轉(zhuǎn)換和編譯的“黑魔法”領(lǐng)域了。

AST的結(jié)構(gòu)

說了這么多,我們來結(jié)合實(shí)例來看一下AST它到底長什么樣子。

現(xiàn)在我們拆解一個(gè)簡單的 add 函數(shù)

function add(a, b) {
    return a + b
}
  • 首先,我們拿到的這個(gè)語法塊,是一個(gè)函數(shù)聲明FunctionDeclaration,接著拆解,它分為三塊:
    • id 就是它的名字,add
    • params 兩個(gè)參數(shù),a和b
    • body 大括號里的內(nèi)容

我們繼續(xù)拆分,add 沒法繼續(xù)拆下去了,他是一個(gè)最基礎(chǔ)的標(biāo)記,就像是名字一樣

{
    name: 'add'
    type: 'identifier'
    ...
}

params 繼續(xù)炒粉,其實(shí)就是兩個(gè)identifier組成的數(shù)組,之后也沒辦法再拆分了。

[
    {
        name: 'a'
        type: 'identifier'
        ...
    },
    {
        name: 'b'
        type: 'identifier'
        ...
    }
]

接下來,我們拆分 body

body 其實(shí)是一個(gè)塊狀域BlockStatement,打開BlockStatement,里面是一個(gè)ReturnStatement

繼續(xù)打開ReturnStatement,里面是一個(gè)二項(xiàng)式BinaryExpression,用來表示 a + b

繼續(xù)打開BinaryExpression,它成了三部分,left,operator,right

  • operator : +
  • left : a
  • right: b

到這里,我們把一個(gè)簡單的add函數(shù)拆解完畢,它的全部構(gòu)成為

{
  "type": "Program",
  "start": 0,
  "end": 39,
  "body": [
    {
      "type": "FunctionDeclaration",
      "start": 0,
      "end": 39,
      "id": {
        "type": "Identifier",
        "start": 9,
        "end": 12,
        "name": "add"
      },
      "expression": false,
      "generator": false,
      "params": [
        {
          "type": "Identifier",
          "start": 13,
          "end": 14,
          "name": "a"
        },
        {
          "type": "Identifier",
          "start": 16,
          "end": 17,
          "name": "b"
        }
      ],
      "body": {
        "type": "BlockStatement",
        "start": 19,
        "end": 39,
        "body": [
          {
            "type": "ReturnStatement",
            "start": 25,
            "end": 37,
            "argument": {
              "type": "BinaryExpression",
              "start": 32,
              "end": 37,
              "left": {
                "type": "Identifier",
                "start": 32,
                "end": 33,
                "name": "a"
              },
              "operator": "+",
              "right": {
                "type": "Identifier",
                "start": 36,
                "end": 37,
                "name": "b"
              }
            }
          }
        ]
      }
    }
  ]
}

看到這里,可能是要倒吸一口涼氣。

我靠,轉(zhuǎn)換一個(gè)add函數(shù)就這么費(fèi)勁,出來這么一大坨,那我們成百上千行的代碼要何從下手?

送我們的螺絲刀

不要著急,AST 縱然很復(fù)雜,但是現(xiàn)在不需要我們重復(fù)造輪子。關(guān)于AST的解析、操作、轉(zhuǎn)換已經(jīng)有很多成熟的庫幫我們封裝好了。

Babel就為我們封裝好了一系列的工具。

另外,可以通過AST explorer來進(jìn)行直觀的樹形結(jié)構(gòu)轉(zhuǎn)換。

接下來,讓我們使用AST技術(shù)來實(shí)現(xiàn)一個(gè)自動為代碼增加try-catch的babel插件!

查看下文

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容