好的,词法分析就结束了,我们开始语法分析吧。
首先为了简化问题,我们对C语言作出如下限制:
1. 没有switch语句
2. 不支持函数指针
3. 没有结构体、联合体
4. 以及一些其他的语句
预处理器将在第七篇中讲到。编译阶段将不会有预处理指令(#include等)。
我们要处理的语法将在下面列出。
文法
定义文法
首先我们定义一条文法是这样的:
NAME ::= SOME_THING
这表示我们定义了一条文法,代号是NAME
,可以匹配SOME_THING
,比如我们定义
D ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
表示我们定义八进制数位,可匹配0~7所有的数字,其中竖线|
表示或的意思,就是可接受0或1或2或3或…或7。
文法提取
定义文法可能有很多重复的地方,我们可以提取。
R ::= Ua | Ub | Uc | Ud | ... | Uz
提取成
R ::= U(a | b | c | ... | z)
下面的sizeof
的定义将采取这种方式:sizeof((TYPE | ID))
表示sizeof(TYPE) | sizeof(ID)
递归文法
我们要定义一种文法,可以匹配多次的,比如我们要匹配一个八进制整数,显然位数在理想情况下是可以无限长的,为了匹配这种文法,我们引入递归文法,比如定义八进制整数:
N ::= D | ND
表示接受一位8进制数,或者一位8进制数后面继续接8进制整数。那么匹配123
的时候就是:
N -> ND -> NDD -> DDD
首先N展开成ND,ND中的N再次展开成ND,最后N展开成D完成匹配。
必须要注意的是我们不能这样定义:N ::= ND
,这样就是死递归,停不下来了。
当然我们也可以定义 N::=D