五分鐘瞭解抽象語法樹(AST)babel是如何轉換的?
抽象語法樹
什麼是抽象語法樹?
It is a hierarchical program representation that presents source code structure according to the grammar of a programming language, each AST node corresponds to an item of a source code.
抽象語法樹是原始碼語法結構的一種抽象表示。它以樹狀的形式表現程式語言的語法結構,樹上的每個節點都表示原始碼中的一種結構
看不懂沒關係,抽象語法樹有很多章節,我們不需要逐一瞭解
這篇文章會幫你建立起,抽象語法樹的印象
我們只需要把目光聚焦於詞法分析(Lexical Analysis)和語法分析(Syntax Analysis)上,這兩步在轉換抽象語法樹過程中扮演著極其重要的角色。
詞法分析 Lexical Analysis
也叫scanner(掃描器),它讀取我們的source code中你的每一個字元,轉換成token(詞法令牌), 最後,我的原始碼可能會被轉換成 list of tokens
input => const a = 5; output => [{type: 'keyword', value: 'const', ...}, {type: 'identifier', value: 'a', ...}, {type: 'value', value: '5', ...}, ...]
語法分析 Syntax Analysis
也叫parser(解析器),將詞法分析器解析出的list of token,轉換成tree representation
input => [{type: 'keyword', value: 'const', ...}, {type: 'identifier', value: 'a', ...}, {type: 'value', value: '5', ...}, ...] output => [{type: 'VariableDeclarator', declarations: {kind: 'const', type: 'Identifier', name: 'a'}, init: {type: 'Literal', value: '5'}, ...}]
最終,經過詞法分析和語法分析,我們的程式碼被轉換成了一個樹形節點
所有的樹形節點組合起來,就形成了concrete syntax tree(混合語法樹),該樹雖然和程式碼並不是100%匹配,但卻包含了足夠的資訊使解析器能夠正確的處理程式碼
Babel
babel是一個js編譯器,他解析高版本es語法程式碼,生成向後相容的低版本js程式碼。
how it works ?
在高層次上,babel解析分為三步
parser => transform => generate
我們將使用虛擬碼
分析每一步的輸入輸出目標
step 1: parser
import * as BabelParser from '***@babel/parser*';
const code = ` const a = 5 `;
const ast = BabelParser.parse(code);
首先,parser輸入原始碼,輸出抽象語法樹ast
step 2: transform
import traverse from '***@babel/traverse***';
const new_ast = traverse(ast, {
enter(path) {
if (path.node.type === 'Identifier') {
// do something transformal
}
...
}
});
然後, 結合babel preset,plugin,轉換上述ast,生成新的ast
step3: generate
import generate from '***@babel/generator***';
const newCode = generate(new_ast);
最後,根據新的語法樹ast,生成編譯後新的程式碼
總結起來就是:
parser: source_code => ast
traverse: ast => new_ast
generate: new_ast => target_code
實際上,babel的轉換過程就是構建和修改抽象語法樹的過程