乐趣区

关于javascript:AST-Abstract-Syntax-Tree

AST (Abstract Syntax Tree)

题目 内容
AST AST 定义,应用形式,原理
AST AST 例子
AST AST 利用

AST 定义

  • AST(Abstract Syntax Tree)形象语法树,简称 AST,它是源代码 (也就是说它不仅仅是利用于 JavaScript,同时还利用于其余语言,例如: Python,Rust 等) 语法结构的一种形象示意。
  • 它以树状的模式体现编程语言的语法结构,树上的每个节点都示意源码中的一种构造
  • 语法【形象】: 指的是这里的语法并不会示意出实在语法中呈现的每个细节。

AST 应用形式

  • 咱们常见的词法分析器以及语法解析器(它能够将 JavaScript 源码转换成 AST),比方上面实例中的 esprima,当然还有其余的,例如: acorn、shift、traceur 等

用处

  • AST 形象语法树的用处是十分宽泛的,比方:
  • vscode、atom、sublime 中的 代码高亮 代码格式化 谬误提醒 代码主动补全
  • eslintprettier对代码谬误或者格调的查看;
  • babel转译 ES6ES5
  • 所以说如果你想优化 JavaScript 的编译和运行速度,AST 的理解是必不可少的。

AST 原理

编译流程

  • JavaScript 执行的过程首先是读取 JavaScript 文件中的 字符流 ,其次通过 词法分析器生成 token,之后再通过 语法分析器 (Parser) 生成 AST 树 ,最初转换为 机器码 执行。
var name = "jackdan";
  • 第一步就先读取下面的字符流'var name ="jackdan"'
  • 第二步分词: 将 'var name ="jackdan"' 整个代码字符串宰割成最小的语法单元数组;如下:
[{ type: 'Keyword', value: 'var'},
  {type: 'Identifier', value: 'name'},
  {type: 'Punctuator', value: '='},
  {type: 'String', value: '"jackdan"'}
]
  • 第三步语法分析: 在分词的根底上建设剖析语法单元之间的关系;如下:
- Program
  type: "Program"
  - body: [
    - VariableDeclaration {
      type: "VariableDeclaration"
      - declarations: [
        - VariableDeclarator {
          type: "VariableDeclarator"
          - id: Identifier {
            type: "Identifier"
            name: "name"
          }
          - init: Literal {
            type: "Literal"
            value: "jackdan"
            raw: "jackdan"
          }
        }
      ]
      kind: "var"
    }
  ]
  • 咱们重点梳理一下原理中的 词法剖析 语法分析,接触过这两者的应该不会太过于生疏。

词法剖析

  • 词法剖析:同时也称为扫描 (scanner),简略来说就是调用
    next() 办法,一个一个字母的来读取字符 ,而后与定义好的JavaScript 要害字符 做比拟,生成对应的 Token。Token 是一个 不可分割的最小单元。例如:
var name = "jackdan";
// 先读取 v,而后持续读取 a, 最初读取 r 组成一个 var
// var 这三个字符就辨认为 JavaScript 中的关键字,作为一个整体,语义上就不能再被合成了,因而咱们也视为一个 Token
  • 从下面的代码实例中不难得出,词法分析器里,每个 关键字是一个 Token,每个 标识符是一个 Token,每个 操作符是一个 Token,每个 标点符号也都是一个 Token。除此之外,还会 过滤掉程序中的正文和空白字符(换行符、空格、制表符等)。
  • 最终,咱们看到整个代码都被宰割进了一个 tokens 列表(或者说一维数组)。
[{ type: 'Keyword', value: 'var'},
  {type: 'Identifier', value: 'name'},
  {type: 'Punctuator', value: '='},
  {type: 'String', value: '"jackdan"'}
]

语法分析

  • 语法分析就是将 词法剖析的 tokns 列表转化成有语法含意的形象语法树结构 。同时去 验证语法(高亮、主动补全等),语法如果有错的话,抛出语法错误。
- Program
  type: "Program"
  - body: [
    - VariableDeclaration {
      type: "VariableDeclaration"
      - declarations: [
        - VariableDeclarator {
          type: "VariableDeclarator"
          - id: Identifier {
            type: "Identifier"
            name: "name"
          }
          - init: Literal {
            type: "Literal"
            value: "jackdan"
            raw: "jackdan"
          }
        }
      ]
      kind: "var"
    }
  ]

AST 实例

// 源代码
var name = "jackdan";
// AST 形象语法树
/**
 * 
 *      +-----------+
 *      | assign(=) |
 *      +-----------+
 *      /            \
 *     /              \
 * +----+        +---------+
 * |name|        |"jackdan"|
 * +----+        +---------+
 * 
*/
// 运行输入的构造代码
- Program
  type: "Program"
  - body: [
    - VariableDeclaration {
      type: "VariableDeclaration"
      - declarations: [
        - VariableDeclarator {
          type: "VariableDeclarator"
          - id: Identifier {
            type: "Identifier"
            name: "name"
          }
          - init: Literal {
            type: "Literal"
            value: "jackdan"
            raw: "jackdan"
          }
        }
      ]
      kind: "var"
    }
  ]
> var esprima = require('esprima');
> var program = 'var name ="jackdan"';

> esprima.tokenize(program);
[{ type: 'Keyword', value: 'var'},
  {type: 'Identifier', value: 'name'},
  {type: 'Punctuator', value: '='},
  {type: 'String', value: '"jackdan"'}
]

> esprima.parse(program);
Script {
  type: 'Program',
  body: [
    VariableDeclaration {
      type: 'VariableDeclaration',
      declarations: [Array],
      kind: 'var'
    }
  ],
  sourceType: 'script'
}

Thinking in JackDan

退出移动版