编译系统透视:图解编译原理
上QQ阅读APP看书,第一时间看更新

3.2 语法分析思路

前面的词法分析已经详细讲解了如何从C语言源程序文件的连续字符串中识别出一个个独立、按序排列的符号(token)串,语法分析就要从这个符号串中识别出符合C语言语法的语句。识别的方法是:以C语言语法为模板,将符号串按序逐个匹配,如果能匹配成功,就可以确定匹配成功的符号串是一条符合C语言语法的句子,同时也就确定了这条语句的语法属性(如函数声明语句)及句子的各个语法成分(如返回值类型、函数名、参数列表)。如果与所有语法类型的模板都无法匹配,说明这个符号串有语法错误。

下面我们仍以前面提供的源程序为例介绍语法分析。语法分析以句为处理单位,根据C语言语法规则,源程序中首先出现的是全局语句,下面列举了几种全局语句:

·外部变量声明语句,如extern int a;

·全局变量声明及初始化语句,如int a=10;

·函数声明语句,如int fun(int a,int b);

·函数定义语句,如int fun(int a,int b){…}

这几种全局语句的句型如图3-2所示。

图3-2 以模板形式展现的语法规则

一条实际的语句只能属于一种具体的句型,下面我们从第一条语句开始分析,通过遍历词法获得结果,分析它究竟属于哪种句型。第一个符号是“int”,情景如图3-3所示。

图3-3 “int”和模板匹配的情景

从图3-3中对句型的展示可知,外部变量声明语句的第一个符号必须是“extern”,“int”不满足这一条件,因此当前句不可能是外部变量声明语句。其他几种句型的开头是数据类型,“int”满足条件,因此当前句可能是其他几种句型的任意一种,还需向后遍历才能最终确定具体句型,情景如图3-4所示。

图3-4 “fun”和模板匹配的情景

下一个符号是标识符“fun”。在剩下三种句型中,类型后跟着的分别是变量名、函数名、函数名,标识符“fun”都满足条件,所以仍然无法断定当前句型,还需继续向后遍历词法分析结果,情景如图3-5所示。

图3-5 “(”和模板匹配的情景

下一个符号是“(”,显然与全局变量定义中的“=”不匹配了,于是排除这种可能。剩余两种句型仍然符合,还需向后遍历,均出现了“(参数声明表)”,向后遍历到“int”、“a”、“int”、“b”、“)”时,都满足这两种句型的条件,无法确定当前句型究竟是函数声明还是函数定义,这部分遍历的情景如图3-6所示。

图3-6 一直到“;”之前的符号和模板匹配的情景

再继续向后遍历,出现符号“;”,情景如图3-7所示。

图3-7 “;”和模板匹配的情景

此时函数声明和函数定义的句型出现差异,函数声明应出现“;”,函数定义应出现“{”,由此可知当前语句型应为函数声明语句。

至此,在全局语句的四种句型中,我们根据词法分析的结果,逐个词进行匹配,最终排除了三种不符合的句型,确定了当前语句的句型。可见,确定句型的过程是一个根据可能语句句型的全集不断进行匹配,不断排除错误可能的过程。