1. 程式人生 > >五分鐘瞭解抽象語法樹(AST)babel是如何轉換的?

五分鐘瞭解抽象語法樹(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的轉換過程就是構建和修改抽象語法樹的過程