kangyana / daily-question

When your heart is set on something, you get closer to your goal with each passing day.
https://www.webpack.top
MIT License
3 stars 0 forks source link

【Q104】什么是 AST,及其应用 #104

Open kangyana opened 1 year ago

kangyana commented 1 year ago

1. 什么是 AST

AST 是 Abstract Syntax Tree 的简称,是前端工程化绕不过的一个名词。 它涉及到工程化诸多环节的应用,比如:

而在语言转换的过程中,实质上就是对其 AST 的操作,核心步骤就是 AST 三步走:

Alt

以下是一段代码:

const a = 4;

转换为 AST:

{
  "type": "Program",
  "start": 0,
  "end": 11,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 11,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 6,
          "end": 11,
          "id": {
            "type": "Identifier",
            "start": 6,
            "end": 7,
            "name": "a"
          },
          "init": {
            "type": "Literal",
            "start": 10,
            "end": 11,
            "value": 4,
            "raw": "4"
          }
        }
      ],
      "kind": "const"
    }
  ],
  "sourceType": "module"
}

不同的语言拥有不同的解析器,比如 Javascript 的解析器和 CSS 的解析器就完全不同。

对相同的语言,也存在诸多的解析器,也就会生成多种 AST,如 babelespree

AST Explorer (opens new window)中,列举了诸多语言的解析器(Parser),及转化器(Transformer)。

Alt

kangyana commented 1 year ago

2. AST 的生成

AST 的生成这一步骤被称为 解析(Parser),而该步骤也有两个阶段:

词法分析(Lexical Analysis)

词法分析用以将代码转化为 Token 流,维护一个关于 Token 的数组。

Alt

// Code
a = 3

// 转换为 Token
[
  { type: { ... }, value: "a", start: 0, end: 1, loc: { ... } },
  { type: { ... }, value: "=", start: 2, end: 3, loc: { ... } },
  { type: { ... }, value: "3", start: 4, end: 5, loc: { ... } },
  ...
]

词法分析后的 Token 流也有诸多应用,如:

语法分析 (Syntactic Analysis)

语法分析将 Token 流转化为结构化的 AST,方便操作:

{
  "type": "Program",
  "start": 0,
  "end": 5,
  "body": [
    {
      "type": "ExpressionStatement",
      "start": 0,
      "end": 5,
      "expression": {
        "type": "AssignmentExpression",
        "start": 0,
        "end": 5,
        "operator": "=",
        "left": {
          "type": "Identifier",
          "start": 0,
          "end": 1,
          "name": "a"
        },
        "right": {
          "type": "Literal",
          "start": 4,
          "end": 5,
          "value": 3,
          "raw": "3"
        }
      }
    }
  ],
  "sourceType": "module"
}

3. 实践

可通过自己写一个解析器,将语言 (DSL) 解析为 AST 进行练手,以下两个示例是不错的选择:

或可参考一个最简编译器的实现 the super tiny compiler