参考:
AST简介
抽象语法树(abstract syntax tree,AST) 是源代码的抽象语法结构的树状表示,树上的每个节点都表示源代码中的一种结构,这所以说是抽象的,是因为抽象语法树并不会表示出真实语法出现的每一个细节,比如说,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。 抽象语法树并不依赖于源语言的语法,也就是说语法分析阶段所采用的上下文无文文法,因为在写文法时,经常会对文法进行等价的转换(消除左递归,回溯,二义性等),这样会给文法分析引入一些多余的成分,对后续阶段造成不利影响,甚至会使合个阶段变得混乱。因些,很多编译器经常要独立地构造语法分析树,为前端,后端建立一个清晰的接口。 抽象语法树在很多领域有广泛的应用,比如浏览器,智能编辑器,编译器。
实例
- 四则运算表达式
表达式: 1+3*(4-1)+2
- xml
<letter>
<address>
<city>ShiChuang</city>
</address>
<people>
<id>12478</id>
<name>Nosic</name>
</people>
</letter>
- 程序1
while b != 0
{
if a > b
a = a-b
else
b = b-a
}
return a
- 程序2
sum=0
for i in range(0,100)
sum=sum+i
end
使用JDT ASTView浏览抽象语法树
Eclipse JDT 提供了可以可视化AST的插件:JDT AstView,该插件可以在IDEA上使用。
如果下载失败,多半是因为DNS的原因,可以
- 从官网获取对应插件的下载链接+迅雷 或者
- 修改hosts文件,修改plugins.jetbrains.com/ 域名地址ip 详细自行百度
以下是ASTView的测试代码
package test;
import java.util.LinkedList;
import java.util.List;
public class ASTTest {
public static void main(String[] args) {
int n = 1;
List<Integer> list = new LinkedList<>();
for (int i = 0; i < 10; i++) {
n++;
list.add(i);
}
System.out.println(n + list.size());
}
}
在代码界面右键 Enable JDT AST View
点击右侧工具栏的 JDT AST,点击相应的AST节点,光标就会在相应的代码闪烁。使用该插件可以帮助快速感受一下AST。
根据Eclipse AST的定义,图中每一个节点对应一个节点名,每一个子节点也在其依附的父节点中扮演着一个角色(身份),并且叶子节点基本为名称、操作符和字面量。表1给出了图1中的for循环节点(ForStatement)的四个子节点的节点名和依附于父节点的角色。
图1 ForSatement的语法树结构
表1 各个子节点的节点名和角色
文本 -> 抽象语法树的过程
- 词法分析:文本 -> token列表
- 去除空格,对token分类,去除空格,然后对token分类,那些属于语法关键字,那些属于操作符,那些属于语句的截止位置,那些属于数据
- 语法分析:token列表 -> 语法二叉树
- 扫描token流,然后分析它的语法,这一步应该是分析一条以;结尾的语句具体的执行规则,然后使用逆波兰表达式组合,最后形成一个二叉树,二叉树从底部往上一步步合并
第一步:词法分析,也叫扫描scanner 它读取我们的代码,然后把它们按照预定的规则合并成一个个的标识 tokens。同时,它会移除空白符、注释等。最后,整个代码将被分割进一个 tokens 列表(或者说一维数组)。
const a = 5;
// 转换成
[{value: 'const', type: 'keyword'}, {value: 'a', type: 'identifier'}, ...]
当词法分析源代码的时候,它会一个一个字母地读取代码,所以很形象地称之为扫描 - scans。当它遇到空格、操作符,或者特殊符号的时候,它会认为一个话已经完成了。 第二步:语法分析,也称解析器 它会将词法分析出来的数组转换成树形的形式,同时,验证语法。语法如果有错的话,抛出语法错误。
[{value: 'const', type: 'keyword'}, {value: 'a', type: 'identifier'}, ...]
// 语法分析后的树形形式
{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "a"
},
...
}
当生成树的时候,解析器会删除一些没必要的标识 tokens(比如:不完整的括号),因此 AST 不是 100% 与源码匹配的。 解析器100%覆盖所有代码结构生成树叫做CST(具体语法树)。