不会学的AST

小白总结的译文,出自《AST for JavaScript developers》

为什么要谈AST

如果你查看目前任何主流的项目中的 devDependencies,会发现这些年不计其数的插件诞生。我们归纳一下有:javascript转译、代码压缩、css预处理器、elint、pretiier 等。有很多js模块不会在生产环境用到,但是它们在开发过程中充当着重要的角色。所有的上述工具,不管怎样,都建立在了AST这个巨人的肩膀上。

AST与Devs.png

什么是AST

官方定义: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.

AST转化案例.png

这很简化,只是大体思想。实际上,真正AST每个节点会有更多的信息。从纯文本中,我们将得到树形结构的数据。每个条目和树中的节点一一对应。

如何生成AST

那怎么从纯文本中得到AST呢?我们知道当下的编译器都做了这件事情。

编译器生成AST.png

幸运的是,我们无需贯穿编译器的所有知识点,最后将高级语言转译为二进制代码。只需要关注词法分析和语法分析,这两步是从代码中生成AST的关键所在。

  • 词法分析
    也叫做扫描Scanner。它读取我们的代码,然后把它们按照预定的规则合并成一个个的标识tokens。同时,它会移除空白符、注释 等。最后,整个代码将被分割进一个tokens列表(或者说一维数组)。
词法分析.png

当词法分析源代码时,它会一个一个字母地读取代码,所以很形象地称之为扫描-scans;当它遇到空格,操作符,或者特殊符号时,会认为一个话已经完成了。

  • 语法分析
    即解析器。它会将词法分析出来的数组转化成树形的表达形式。同时验证语法,语法如果有错的话,抛出语法错误。
语法分析.png

当生成树时,解析器会删除一些没必要的标识tokens(比如不完整的括号),因此AST不是100%与源码匹配的,但已经能让我们知道如何处理了。说个题外话,解析器100%覆盖所有代码结构生成树叫做CST(具体语法树)

  • 生成AST结构
抽象语法树结构.png

玩转AST

astexplorer 是一个很棒的网站,可以在线玩转AST,其中包含了很多第三方AST库。除了JS,还有很多其他语言的AST库。

  • babylon
    babylon是一个很棒的第三方库,它被用在大名鼎鼎的babel中,一直支持最新的JS特性,不用担心以后JS又出新版导致代码大规模重构。
  • babel

Babel is not a ‘tool for having ES6 support’. Well, it is, but it is far not only what it is about.

经常把beble和支持es6/7/8联系起来,但它仅仅是一组插件中的一个。我们也可以使用它来压缩代码、react相关语法转译(如jsx)、flow插件 等。
babel是一个Javascript编译器。宏观来说,它分3个阶段运行代码:解析parsing --> 转译transforming --> 生成generation。我们可以给babel一些Javascript代码,它修改代码,然后生成新的代码返回。

babel是怎样修改代码的呢?没错!它创建了AST,遍历树,修改tokens,最后从AST中生成新的代码。

范例

babel的工作过程.png

babel使用babylon --> 首先解析代码成AST,然后遍历AST,再反转所有的变量名,最后生成代码!
正如我们看到的,第一步(解析)和第三步(生成)看起来非常常规,我们每次都会做这两步。所以,babel接管处理了它们。最后,我们最为关心的,那就是AST转译这一步了。

当我们开发babel-plugin时,只需要描述转化AST的节点visitors就可以了

babel-plugin.png

将它加入babel插件列表中,设置webpackbabel-loader配置 或者 .babelrc中的plugins即可。

  • JScodeshift
    比如你想要替换掉所有老掉牙的匿名函数,把它们变成Lambda表达式(箭头函数)。
匿名函数替换为箭头函数.png

这时候jscodeshift就登场了,jscodeshift是一个跑codemods的工具,codemods是一段描述AST要转化成什么样的代码,思想和babel的插件如出一辙。

some code.png

所以,如果你想创建自动把你的代码从旧的框架迁移到新的框架,这就是一种很nice的方式

比如 react 16prop-types 重构

reactupdate.png

有很多不同的codemodes已经创建了:
https://github.com/facebook/jscodeshift
https://github.com/reactjs/react-codemod

  • Prettier
格式化代码.png

Prettier 格式化我们的代码,调整长句,整理空格,括号等。所以它将代码作为输入,修改后的代码作为输出。听起来很熟悉对吧!

prettier工作过程.png

思路还是一样。首先,将代码生成AST。之后依然是处理AST,最后生成代码。但是,中间过程其实并不像它看起来那么简单。

你可能感兴趣的:(不会学的AST)