Abstract Syntax Code

本贴最后更新于 1332 天前,其中的信息可能已经事过境迁

抽象语法树 AST

将代码进行词法分析语法分析后变成树结构以便于生成中间代码的环节

图片.png
如图所示,该树为 2*3+7

词法分析

比如一段代码

const a = 5;

经过词法分析

[{value: 'const', type: 'keyword'}, {value: 'a', type: 'identifier'}, ...]

语法分析

词法分析的输出是语法分析的输入,将词法分析的结果转化为树

{
   type: "VariableDeclarator", 
   id: {
       type: "Identifier",
       name: "a"
   },
   ...
}

当生成树的时候,解析器会删除一些没必要的标识 tokens(比如:不完整的括号),因此 AST 不是 100% 与源码匹配的。

与源代码互相匹配的叫做 具体语法树

关于研究用途拆解包

recast 包可以在 nodejs 中拆解 code 输出词法语法分析后的结果,并且可以进行 inspect 操作等等

拿到抽象语法树之后

Go 语言的编译器会对语法树中定义和使用的类型进行检查

  1. 常量、类型和函数名及类型;
  2. 变量的赋值和初始化;
  3. 函数和闭包的主体;
  4. 哈希键值对的类型;
  5. 导入函数体;
  6. 外部的声明;

检查过程中展开内建函数

比如 go 中的 make() 转为具体的 make 类型 makeslice makechan

中间代码生成

检查/展开内建函数后生成中间代码 compileFunctions

图片.png

将函数 放入编译队列 Queue 等待编译 后端 携程消费

编译

1.编译入口在 [src/cmd/compile/internal/gc/main.go]

2.先获取命令行传入的参数并更新编译选项和配置

3.运行 parseFiles 函数对输入的所有文件进行词法与语法分析得到文件对应的抽象语法树

  1. 检查常量、类型和函数的类型;
  2. 处理变量的赋值;
  3. 对函数的主体进行类型检查;
  4. 决定如何捕获变量;
  5. 检查内联函数的类型;
  6. 进行逃逸分析;
  7. 将闭包的主体转换成引用的捕获变量;
  8. 编译顶层函数;
  9. 检查外部依赖的声明;

最后生成中间代码 main 最后根据 机器类型生成对应的机器码

感谢

内容部分来自:
draveness

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...