diff --git a/CS143体验报告.md b/CS143体验报告.md index a7247ca..cd1de4a 100644 --- a/CS143体验报告.md +++ b/CS143体验报告.md @@ -150,3 +150,36 @@ PA 2-5 正式写编译器。PA2 写词法分析器,首先读一遍 README 和 不过以上都是我的写法,我看 Github 上还有别的写法,有的有问题,有的写的不太好但是能过(就比如说用空规则),总之能用就行,我也不能保证我写的一定没问题,毕竟对于 bison 还不是很熟悉。 最后还有一个行号的问题,建议把所有的行号都设置成最后一个符号的行号,不过实际上可以不改。感觉需要改一下的是 `cool-parse.h` 那边,因为 `no_expr` 的行号设为0比较合理,我这里好像是会继承基类`tree_node` 的构造函数,把行号设置为当前的行号;但是其实应该写成0,我也不知道当年的编译器是咋做的。 + +### PA4 + +终于不用折腾老古董了,虽然但是这个 PA 的代码量有点大啊,而且要考虑的东西变多了,为啥越做越难了。 + +#### 写之前先读文档 + +需要读的 Manual:Typing rules,scoping rules。除了13节 operational semantics 之外,应该都要看完。 + +主要任务: +- 遍历所有的类、构建继承关系图、检查继承关系 +- 对于每一个类,先遍历一遍构建符号表,然后类型检查并在 AST 上做类型注解 + +需要修改的文件: +- `cool-tree.h` 扩展 AST 的定义; +- `semant.cc` `semant.h` 实现主要的逻辑:`semant()` 方法会被主程序外部调用,`ClassTable` 写了一点 starter code,构建继承关系用这个东西。 + +如何遍历: +- 看代码 `dump_with_types` + +继承关系构建:建个图然后检查环路。从 basic class 继承有限制(Int、String和Bool这三个都是不可继承、不可重定义的,其他的basic class 不能重新定义),同时不能继承一个不存在的类。 +推荐的分析过程:第一步先检查继承关系,第二步检查其他的语义条件。 + +作用域:`self` 自动引入,其他带需要考虑命名覆盖的问题。注意,class、method、attribute 这些的命名可以在定义前被使用,因此可能需要多趟处理。符号表在 support code 里面有定义,甚至有一个 `symtab_example.cc` 的样例程序。 + +类型检查:对于无法确定类型的表达式,赋一个 Object 然后尝试恢复。需要给出错误信息,不过正如课上讲的 cascading error 是可以接受的。 + +代码生成接口约束: +`For every expression node, its type field must be set to the Symbol naming the type inferred by your type checker. This Symbol must be the result of the add_string method of the idtable. The special expression no expr must be assigned the type No_type which is a predefined symbol in the project skeleton.` 所有表达式节点的 `type` 必须设置为 `Symbol`,具体的值由 type checker 决定。`no_expr` 赋值为预定义的 `Symbol` 变量 `No_type`。 + +错误输出:对于不存在继承相关错误的程序,需要报告所有的语义错误(不要求和参考实现完全一致)。这个作业里面需要手动调用报错方法 `ClassTable::semant_error(Class_)`,(前两个PA是工具自动生成的) + +调试:skeleton 提供了一个命令行开关 `-s`,对应全局变量 `semant_debug`,可以用来条件打开调试信息。 diff --git a/assignments/PA4/compare.sh b/assignments/PA4/compare.sh new file mode 100755 index 0000000..ba79252 --- /dev/null +++ b/assignments/PA4/compare.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -ex +make semant +./stdsemant $* > std.out 2>&1 || true +./mysemant $* > my.out 2>&1 || true +diff std.out my.out +rm std.out my.out \ No newline at end of file diff --git a/assignments/PA4/stdsemant b/assignments/PA4/stdsemant new file mode 100755 index 0000000..b2cd456 --- /dev/null +++ b/assignments/PA4/stdsemant @@ -0,0 +1,2 @@ +#!/bin/bash -f +../../bin/lexer $* | ../../bin/parser $* | ../../bin/semant $*