我刚刚完成了对C Minus递归下降解析器的编码,如果可以解析输入文本文件,则简单地打印“ ACCEPT”,否则就打印“ REJECT”。对于语法中的每个规则,我都有一个仅返回true或false的函数。 以下是语法分析中必须执行的一些检查:
基本上,我的问题是,执行此操作的明智方法是什么?
我现在根本没有符号表,但是我听到同学说我可以简单地对函数本身进行某些检查。例如,要不允许浮点数作为数组索引,只需在我的代码中找到带有方括号的函数,然后在其中添加一些“检查”,如果浮点数位于两个方括号之间,则会返回错误。
答案 0 :(得分:3)
您的检查清单不是语法检查中的“语法”分析。
如果仅将完全有效的程序解释为语言实例,则它们是“语法”检查。
大多数编译器社区将这种检查称为“语义”(有效性)检查。
通常,此类检查是关于是否根据语言规则将运算符应用于操作数(例如,““ operator []只能用于数组类型”。)
要执行此操作,您必须知道每个运算符(例如“ []”)的操作数类型。为此,人们通常构建符号表,将标识符映射到标识符的类型,并将源代码区域映射到在那些区域中有效的标识符集(“范围”)。使用此信息,您可以检查应用于符号的运算符是否有意义。
现在会出现复杂情况:某些运算符适用于表达式,例如,其他运算符组成,例如:foo(x)[17]
,我打算表示“ foo
是该函数会返回一个数组,因此现在您必须将类型信息与每个表达式相关联。
最简单的方法是将类型信息与树中的每个节点相关联。 您将需要阅读有关符号表的信息,如何通过遍历树来构建树,然后如何遍历树来对每个节点进行类型标记(标识符很简单:类型就是symobl表所表示的类型)。标识符是)。通常,您可以进行自下而上的树遍历,首先标记叶节点,然后检查其上方的操作员节点的有效性,并在通过有效性检查后计算操作员节点的类型,然后继续此过程以将树节点标记为分析器爬上树。
[对于某些语言,自下而上的扫描无效;您可以反复上下传递信息。艾达(Ada)为此而出名]。
此过程的正式表征称为“属性评估”。参见https://en.wikipedia.org/wiki/Attribute_grammar。您无需成为正式的想法实施者,就可以手工完成自下而上的案例。
那是聪明的方法。可能有其他方法,但是很难想象,也很难使工作“正确”。