初次接触AST——抽象语法树

AST——抽象语法树


AST——抽象语法树,是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。

先看一段代码:

// An highlighted block
var foo = 'bar';

转换成语法树的JSON格式是什么:

// An highlighted block
{
  "type": "Program",
  "body": [ // 这个就是解析出来的语法体,所有的js代码都被解析到这里面
    {
      "type": "VariableDeclaration", // 这个是一个var类型,具体作用,在后面有使用。请往后看
      "declarations": [ // 描述一下当前数据,由什么组成
        {
          "type": "VariableDeclarator",
          "id": {
            "type": "Identifier",  // 标识符,就是咱们所说的变量
            "name": "foo" // 这个就是变量名称
          },
          "init": {
            "type": "Literal",
            "value": "bar",
            "raw": "'bar'"
          }
        }
      ],
      "kind": "var"
    }
  ],
  "sourceType": "script"
}

上面的代码就是一个简单的var变量赋值的一个语句,通过espeima转换成为AST树的话。就变成咱们常见的JSON形式的数据!那么AST它的用处只有这些吗?它要怎么为我们服务呢?我们且往下看

如何使用AST让我们去实现代码的变更呢?

三个步骤:

  • 解析我们的语法(js)=> 形成对应的语法树
  • 遍历语法树 => 对语法树进行操作
  • 输出新的文件 => 变更后的文件

esprima

esprima 是比较常用的一个转换工具,并且会有对应的在线转换的功能,它主要替我们把对应的js代码转换成AST语法树。那我们如何使用它呢?

// 先进行安装esprima
let esprima = require('esprima')
let code = `function ast() {}`// 需要转换的数据
const tree =  esprima.parseScript(code) //返回出来的就是AST的树

上面的代码就是将js的文本代码直接转换成AST树,看起来是不是很简单。咱们现在获取到对应的AST树,那么我们该如何使用呢?

estraverse

estraverse 是将语法树进行变更,咱们可以在这里做咱们自己想要做的事情。下一步,咱们将通过esprima转换得到的语法树进行变更一下,将函数的名称修改一下。

let esprima = require('esprima')
let code = `function ast() {}`// 需要转换的数据
const tree =  esprima.parseScript(code) //返回出来的就是AST的树
let estraverse = require('estraverse')
estraverse.traverse(tree, {
  // node 是每一个节点,一般都是含有type的都是一个节点
  enter(node) {
    // 进入
    if (node.type === 'Identifier') {
      node.name = 'zsl'
    }
  },
  leave(node) {
    // 完成,并离开得到修改后的数据
  }
})

estraverse有一个方法就是traverse,该方法的代码如下:

estraverse.traverse(option\[Object], Object\[Function, ...])
option 是需要变更的语法树,后面的是一些对象,对象里面都是一些函数,最主要的函数就是 enter ()leave ()函数,如果只是操作的话,一般都是在输入函数里面进行操作进行

上面就已经将咱们的语法树已经做过处理了,可是这还是对应的语法树而不是我们所认识的js代码文本啊,不急,且往下看。

escodegen

escodegen 是AST转换js的最后一步,也是我们得到最后结果的一步。上代码:

let esprima = require('esprima')
let code = `function ast() {}`// 需要转换的数据
const tree =  esprima.parseScript(code) //返回出来的就是AST的树
let estraverse = require('estraverse')
estraverse.traverse(tree, {
  // node 是每一个节点,一般都是含有type的都是一个节点
  enter(node) {
    // 进入
    if (node.type === 'Identifier') {
      node.name = 'zsl'
    }
  },
  leave(node) {
    // 完成,并离开得到修改后的数据
  }
})
// 将对应的语法树重新输出为对应的数据
let escodegen = require('escodegen')
let code1 = escodegen.generate(tree)
console.log(code1)
// function zsl() {}

这一步就是将对应的AST树重新转换成咱们知道的js代码。

其实,这只是一个小小的demo,但是从一个小小的demo我们可以知道,咱们使用的某些插件,其实都是按照这个逻辑过来的,我们在项目打包的时候,引用的一些loader文件,之所以配置他们,其实就是为了让一些之前的语法或者新的语言的方法,统统转换成html,js,css等这些文件。

下一步,着手写一下babel与AST的之间的关系,然后,写成自己的插件。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值