所以,我正在使用flex / bison编写一种语言,并且我在实现标识符方面遇到了困难,特别是在知道何时查看作业或参考时, 例如:
1)A = 1 + 2
2)B + C(其中B和C已被指定值)
示例一,我可以通过将一个ID令牌从flex返回到bison,并遵循一个识别1 + 2是整数表达式的语法,将A放入符号表并设置其值来解决问题。
第二个例子和第三个例子对我来说比较困难,因为:经过我的词法分析器后,在ex.2中返回到野牛的是“ID PLUS ID” - >我有一个语法,可识别数值的算术表达式,如INT PLUS INT(可产生INT)或DOUBLE MINUS INT(可产生DOUBLE)。如果我有“ID PLUS ID”,我怎么知道返回值的类型是什么?
这是我到目前为止最好的想法:当标记化时,每次ID出现时,我都会搜索其值并输入符号表并将ID标记与其各自的信息一起切换出来;例如:在标记化时,我遇到了B,它有一个与它匹配的正则表达式作为ID。我查看我的符号表,看到它的值为51.2并且是双倍的。因此,我没有返回ID,而是将B值设置为bison,而是返回值为51.2的DOUBLE
我有两种不同的解决方案相互矛盾。原因如下:如果我想为ID分配一个值,我会对我的编译器说A = 5.在这种情况下,如果我使用我之前描述的解决方案,那么在所有内容被标记化之后我会得到什么是,INT ASGN INT,或STRING ASGN INT等......所以,在这种情况下,我会使用前一种解决方案,而不是后者。
我的问题是:我使用什么样的逻辑设备来帮助我的编译器知道要使用哪种解决方案?
注意:我认为没有必要发布源代码来描述我的难题,但是如果有人能够有效地使用它作为参考来帮助我理解他们对这个主题的意见。
谢谢。
答案 0 :(得分:1)
如果可能,请重新设计您的语言,以便明确无误。这就是为什么即使是Javascript也有var
。
否则您将需要通过语义规则消除歧义,例如首次使用标识符是其声明。我不知道你的案例有什么问题(2):只需生成适当的代码。如果尚未使用B
和C
,那么使用这样的值读取应该是非法的,但是如果进入 Nth,则涉及控制流分析准确度,因此您可能更愿意假设初始值为零。
在任何情况下,您都可以看到它从根本上说是语言设计问题,而不是编码问题。
答案 1 :(得分:1)
通常的方法是使用yacc / bison规则:
expr: ID { $$ = lookupId($1); }
其中lookupId
函数在符号表中查找符号并返回其类型和值(如果您正在编写编译器而不是严格的解释器,则返回类型和存储位置)。然后,您的其他expr
规则不需要关心它们的操作数是来自常量,符号还是其他表达式:
expr: expr '+' expr { $$ = DoAddition($1, $3); }
函数DoAddition
获取其两个操作数的类型和值(或位置),并添加它们,生成结果,或生成代码以在运行时执行添加。