AST描述

  在计算机科学中,抽象语法树(AST)或语法树是用编程语言编写的源代码的抽象语法结构的树表示。树的每个节点表示在源代码中出现的构造。语法是“抽象的”,因为它不代表真实语法中出现的每个细节,而只是结构,内容相关的细节。例如,分组括号 在树结构中是隐式的,并且可以通过具有三个分支的单个节点来表示类似于if-condition-then表达式的句法结构。

  这将抽象语法树与传统上指定的解析树区分开来,这些语法树通常由解析器在源代码转换和编译过程中构建。一旦构建,通过后续处理(例如,上下文分析)将附加信息添加到AST 。

  抽象语法树也用于程序分析和程序转换系统。

  参考:[维基百科](https://en.wikipedia.org/wiki/Abstract_syntax_tree)

解析器Parser

  JavaScript Parser是把js源码转化为抽象语法树的解析器,一般分为词法分析、语法分析及代码生成或执行。

词法分析

  词法分析阶段会把字符串形式的代码转换为令牌(Tokens)流。可将令牌看作是一个扁平的语法片段数组。

var answer = 6 * 7;

//Tokens
[
{
"type": "Keyword",
"value": "var",
"range": [
34,
37
],
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 3
}
}
},
{
"type": "Identifier",
"value": "answer",
"range": [
38,
44
],
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 10
}
}
},
{
"type": "Punctuator",
"value": "=",
"range": [
45,
46
],
"loc": {
"start": {
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 12
}
}
},
{
"type": "Numeric",
"value": "6",
"range": [
47,
48
],
"loc": {
"start": {
"line": 2,
"column": 13
},
"end": {
"line": 2,
"column": 14
}
}
},
{
"type": "Punctuator",
"value": "*",
"range": [
49,
50
],
"loc": {
"start": {
"line": 2,
"column": 15
},
"end": {
"line": 2,
"column": 16
}
}
},
{
"type": "Numeric",
"value": "7",
"range": [
51,
52
],
"loc": {
"start": {
"line": 2,
"column": 17
},
"end": {
"line": 2,
"column": 18
}
}
},
{
"type": "Punctuator",
"value": ";",
"range": [
52,
53
],
"loc": {
"start": {
"line": 2,
"column": 18
},
"end": {
"line": 2,
"column": 19
}
}
}
]

  

语法分析  

  语法分析阶段会把一个令牌流转换成抽象语法树(AST)的形式,这个阶段会使用令牌中的信息把它们转换成一个AST的树结构。

// Life, Universe, and Everything
var answer = 6 * 7;
// Syntax
{
"type": "Program",
"body": [
{
"type": "VariableDeclaration",
"declarations": [
{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "answer",
"range": [
38,
44
],
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 10
}
}
},
"init": {
"type": "BinaryExpression",
"operator": "*",
"left": {
"type": "Literal",
"value": 6,
"raw": "6",
"range": [
47,
48
],
"loc": {
"start": {
"line": 2,
"column": 13
},
"end": {
"line": 2,
"column": 14
}
}
},
"right": {
"type": "Literal",
"value": 7,
"raw": "7",
"range": [
51,
52
],
"loc": {
"start": {
"line": 2,
"column": 17
},
"end": {
"line": 2,
"column": 18
}
}
},
"range": [
47,
52
],
"loc": {
"start": {
"line": 2,
"column": 13
},
"end": {
"line": 2,
"column": 18
}
}
},
"range": [
38,
52
],
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 18
}
}
}
],
"kind": "var",
"range": [
34,
53
],
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 19
}
},
"leadingComments": [
{
"type": "Line",
"value": " Life, Universe, and Everything",
"range": [
0,
33
],
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 33
}
}
}
]
}
],
"sourceType": "script",
"range": [
34,
53
],
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 19
}
}
}

常见的AST node类型

  AST树每一层结构也被叫做节点(Node)。一个AST可以由单一的节点或是成百上千个节点够成,通过组合在一起来描述静态分析的程序语法(静态分析是在不需要执行代码的前提下对代码进行分析的处理过程 (执行代码的同时进行代码分析即是动态分析)。 静态分析的目的是多种多样的, 它可用于语法检查,编译,代码高亮,代码转换,优化,压缩等等场景。)。

 Node types:https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API#Node_objects

babel AST node types:https://github.com/babel/babylon/blob/master/ast/spec.md

使用esprima生成抽象语法树流程

  以上生成的AST树可视化工具:[esprima](http://esprima.org/demo/parse.html#)生成,通过[esprima](https://github.com/jquery/esprima)将源码生成抽象语法树,并通过[estraverse](https://github.com/estools/estraverse)遍历并更新AST,最后通过[escodegen](https://github.com/estools/escodegen)将AST重新生成源码。

常用的JavaScript Parser

  [Acorn](https://github.com/acornjs/acorn),[Esprima](https://github.com/jquery/esprima),[UglifyJS2](https://github.com/mishoo/UglifyJS2),[Babel(https://github.com/babel/babel)等

总结

  最后,根据对抽象语法树的大概了解做了个demo级的将命名函数转换为exports函数的npm包:https://www.npmjs.com/package/fn2export,欢迎使用~~~

最新文章

  1. [LeetCode] House Robber 打家劫舍
  2. 总结:JSP几种提交表单方法
  3. THINKPHP之连接数据库(全局配置)
  4. HTTP的长连接和短连接——Node上的测试
  5. 第三章 EnumUtil根据值获取枚举对象
  6. Java学习随笔1:Java是值传递还是引用传递?
  7. Windows Internals学习笔记(三)Procdump的使用
  8. MySql插入记录时判断
  9. 解决:子元素设置margin-top,父元素也受影响的问题
  10. [置顶] 读取pdf并且在web页面中显示
  11. Extjs打开window窗口自动加载html网页
  12. 改造百度UMeditor(UEditor-min)富文本编辑器的图片上传功能
  13. Asp.net开发常用的51个非常实用的代码
  14. 在当前光标处按指定属性显示字符 - BOIS中断
  15. Struts(二十三):使用声名式验证
  16. less &进行选择判断css的样式
  17. 如何通过stat获取目录或文件的权限的数字形式
  18. python爬虫之Cookie
  19. Windows 安装服务 的两种方式
  20. Parallel.ForEach 多线程 声明失败 "未将对象引用设置到对象的实例"

热门文章

  1. cdnbest的proxy里api用法案例:
  2. DB2在dbvisualizer 客户端执行begi/end 语句块
  3. python note 02 格式化与判断、字符串转换
  4. [leetcode]70. Climbing Stairs爬楼梯
  5. centos free详解
  6. 新版本wireshark tshark使用
  7. 20175316盛茂淞 2018-2019-2 《Java程序设计》第2周学习总结
  8. OpenCV-可视化界面Image Watch
  9. ABP框架系列之十三:(Authorization-授权)
  10. Docker基础-使用Dockerfile创建镜像