Pinkman

导航

从头学习compiler系列6——句法分析

 
    句法分析,也就是语义分析。一段代码不但要符合语法的规则,也要符合语义。
    比如c语言中,a = 1; 这个语句没有语法问题,如果变量a在之前没有定义,那么就属于语义错误。又如 a = b; a是int型,b是结构体,那么也属于语义错误,类型不匹配。
    下面列举一些Cool语言需要检测的语义错误。
    1,重名。类之间是否有重名;类继承树里面的函数是否有重名;类继承树里面的成员变量是否有重名。
    2,继承。类继承树中每个类是否有定义;如果没有继承,那么默认继承Object类;继承树中是否有环。
    3,未声明。使用一个变量前是否有定义。
    4,类型不匹配。如比较、算术计算、if条件、loop条件、函数返回值等需要类型匹配。
 
    接下来简单介绍一些检测的解决方案。
    1,类重名、父类不存在、继承有环。遍历所有的类,判断名字是否有重复。然后按照继承关系建立一个树形结构,这一步可以检测到父类不存在问题,树形结构进一步方便继承有环的问题(算法参考欧拉路径)。
    2,函数、成员变量重定义。和类重名检测类似,不过不仅要进行类内部的检测,还需要判断和父类是否有重名。
    3,变量未声明。这就引入作用域的概念。类成员变量在类内部有效,我们就说此变量的作用域在类内部。同理let引入的变量在let内部有效。作用域以下用scope表示。
    顶层scope就是当前的类对象,在这个下面使用的变量从类成员变量里查找。没有找到,那么这个变量未声明。
    进入一个函数,也就是进入新的scope,挂在顶层scope内部。这个scope添加了新的变量——函数参数。这时候可以使用的变量,首先查找本scope,如果没有找到,再查找上一层scope,如果都没有,那么变量未声明。这样做是因为如果有两个或更多scope里有变量重名,那么优先使用内部scope。
    如果继续进入新的scope,处理方法同上。退出一个scope,当前scope就回到上一层。
    Cool语言有4种地方引入scope:类对象、函数参数、let表达式、case表达式。
    4,类型匹配问题。
    需要了解Cool语言类型推导,参考cool_manual.pdf 11.1节。



来自为知笔记(Wiz)



posted on 2013-09-28 20:39  Pinkman  阅读(955)  评论(0编辑  收藏  举报