框架中部分实现的解释
虽然现有的语义检查只是针对decaf的基本语法的,但是了解一下其中比较tricky的实现也是有必要的,因为新语法有可能需要修改和拓展原有的语义检查。
SymbolPass::var_def
这个函数处理了类的字段,函数参数和局部变量的定义。
TypeCk::cur_var_def
当当前语句是一条VarDef
时,会将self.cur_var_def
设置成这条语句。目前,它存在的唯一意义是用于帮助拒绝这样的代码:
对此我们的编译器会汇报一个"undeclared variable"的错误。
但是,因为全局就只有这一个self.cur_var_def
,容易发现假如VarDef
的右端项中也有VarDef
时,这个方法可能不能奏效。基础的框架中不可能有这样的情形,但是在引入lambda表达式之后,这样的情形是可能存在的,例如:
为了在新语法中解决这个问题,我个人推荐的方案是:
在
VarDef
中额外维护一个finish_loc
,表示这条语句的结束位置提示:按照现在的实现,在lalr1的lalr(1)模式下,语法动作中你可以访问变量
lexer
,它包含了当前的行号和列号信息如果你不想维护pa1b的结果的话,可以不维护,只要保证编译通过即可
修改
ScopeStack::lookup_before
,使用上面定义的finish_loc
来过滤符号删除
cur_var_def
及其相关操作,因为它已经没用了
并非要求一定要这么实现,如果你觉得有更简单优雅的方法(我也的确觉得这个不太优雅),可以随意发挥。
符号表的输出
java/scala版的实验框架中保存了很多无用的信息,这些信息在我看来就是纯粹为输出服务的。我不想在我的框架中保存这些信息,例如Scope
就是最简化的定义:
信息已经不能再简化了。与之相反,java版的框架中的LocalScope
中保存了所有嵌套在它里面的作用域:
我读过完整的代码了,这个就是只用来输出的。我不喜欢这样的设计,这不符合"Don't pay for whay you don't use."的原则。在我的设计中,为了在输出时找出所有嵌套在它里面的作用域,我会遍历一遍所有的语句。
大家可以按照自己喜欢的方式实现新特性的符号表的输出,不过因为我目前的设计,我相信实现起来一定是会比其它版本难度要大一些的,希望大家理解。
Last updated