什么是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插件!