AST抽象语法树(Abstract Syntax Tree)

抽象语法树(Abstract Syntax Tree)

webpackLint等不少的工具和库的核心都是经过Abstract Syntax Tree抽象语法树这个概念来实现对代码的检查、分析等操做的node

  • 经过了解抽象语法树这个概念,你也能够随手编写相似的工具

抽象语法树用途

  • 代码语法的检查、代码风格的检查、代码的格式化、代码的高亮、代码错误提示、代码自动补全等等
    • 如JSLint、JSHint对代码错误或风格的检查,发现一些潜在的错误
    • IDE的错误提示、格式化、高亮、自动补全等等
  • 代码混淆压缩
    • UglifyJS2等
  • 优化变动代码,改变代码结构使达到想要的结构
    • 代码打包工具webpack、rollup等等
    • CommonJS、AMD、CMD、UMD等代码规范之间的转化
    • CoffeeScript、TypeScript、JSX等转化为原生Javascript

抽象语法树定义

这些工具的原理都是经过JavaScript Parser把代码转化为一颗抽象语法树(AST),这颗树定义了代码的结构,经过操纵这颗树,咱们能够精准的定位到声明语句、赋值语句、运算语句等等,实现对代码的分析、优化、变动等操做webpack

在计算机科学中,抽象语法树(abstract syntax tree或者缩写为AST),或者语法树(syntax tree),是源代码的抽象语法结构的树状表现形式,这里特指编程语言的源代码。web

Javascript的语法是为了给开发者更好的编程而设计的,可是不适合程序的理解。因此须要转化为AST来使之更适合程序分析,浏览器编译器通常会把源码转化为AST来进行进一步的分析等其余操做。 JavaScript Parserexpress


  • JavaScript Parser,把js源码转化为抽象语法树的解析器。npm

  • 浏览器会把js源码经过解析器转为抽象语法树,再进一步转化为字节码或直接生成机器码。编程

  • 通常来讲每一个js引擎都会有本身的抽象语法树格式,Chrome的v8引擎,firefox的SpiderMonkey引擎等等,MDN提供了详细SpiderMonkey AST format的详细说明,算是业界的标准。浏览器

经常使用的JavaScript Parser

  • esprima
  • traceur
  • acorn
  • shift

4.2 esprima

接下来咱们将下面代码转换成AST,而后生成先的函数newAstbash

let code = 'function ast(){}'; //js代码便可(字符串形式)async

第一步:先安装 esprima estraverse escodegen

npm  i esprima estraverse escodegen -D
复制代码

把上面的源码转成AST编程语言

// 把源码转化为AST
let ast = esprima.parseModule(code);
console.log(ast);

复制代码

打印结果以下 Module { type: 'Program', body: [ FunctionDeclaration { type: 'FunctionDeclaration', id: [Object], params: [], body: [Object], generator: false, expression: false, async: false } ], sourceType: 'module' }

复制代码

接下来,遍历AST 并更新AST

let indent = 0;
function padding() {
  return " ".repeat(indent);
}

estraverse.traverse(ast, {
  enter(node) {
    //进入

    console.log(padding() + node.type + "进入");
    if (node.type === "FunctionDeclaration") {
      node.id.name = "newAst";
    }
    indent += 2;
  },
  leave(node) {
    //离开
    indent -= 2;
    console.log(padding() + node.type + "退出");
  },
});


复制代码
打印结果
Program进入
  FunctionDeclaration进入
    Identifier进入
    Identifier退出
    BlockStatement进入
    BlockStatement退出
  FunctionDeclaration退出
Program退出
复制代码

最后,把修改后的抽象语法从新生成源代码

//把修改事后的抽象语法树从新生成源代码
let result = escodegen.generate(ast);
console.log(result);
复制代码
打印后的结果
function newAst() {
}
复制代码
相关文章
相关标签/搜索