我写了一个编译器

主要观点:作者拥有计算机科学学位,曾学习编译器课程,上周末完成了从无到有编写编译器的尝试。以 Go 语言编写了将 BASIC 代码转换为 Go 代码的编译器toybasic,并在 GitHub 上开源。

关键信息:

  • 选择编写简单的toybasic编译器,受小时候学习的 BASIC 语言影响,基于 TinyBASIC 进行修改,去除了INPUT语句。
  • 编译器有三个阶段:词法分析器将源代码字符序列转换为有意义的标记序列;语法分析器根据标记构建语法树并检查语法正确性;编译器遍历语法树生成等效的 Go 代码。
  • 词法分析器使用nex工具,通过确定性有限自动机(DFA)对语言进行标记化,配置文件指定正则表达式来捕获关键字和标识符。
  • 语法分析器使用 Go 内置的goyacc,按照特定语法定义语言的语法,生成解析树,并通过opr函数定义节点类型和形状。
  • 每个节点类型都有Generate函数,知道如何将该节点转换为 Go 代码,并调用子节点的Generate函数。
  • 展示了一个简单的example/hello.bas程序及其输出,验证了编译器的功能。

重要细节:

  • lexyacc自 1975 年起就开始帮助解决 C 语言中的问题,goyacc是 Go 语言默认工具中的yacc变体。
  • 语法定义中通过特殊语法指定语言的语法规则,并为每个相关符号提供 Go 代码片段来生成解析树。
  • 定义了一个重要的属性表来指定树中每个节点需要填充的属性。
  • 展示了PrintOp节点类型的示例代码,知道如何将其转换为 Go 代码中的fmt.Println语句。
  • 编写了一个使用toybasic中所有构造的 BASIC 程序来测试编译器,还验证了自己小时候写的第一个 BASIC 程序仍能正常工作。
阅读 12
0 条评论