0前言
闲来无事,在屋里多看了一眼《编译原理》(2V),有练练手的冲动——采用LR(1)技术,写了一个C语言的语法归约器!之所以用LR(1)是因为gcc,ucc,tcc和lcc跟商量好似的,清一色的用的LL归约技术,书上也是讲的跟天花一样漂亮,那么就说明它已经十分成熟了,如果再使用LL技术实在是炸不出价值来,源码一抓一大把,看看就够了,重写必要性不大!另外,书中的LR技术讲的项集又是大的没谱,工作量太大;如果使用工具yacc生成,又不知道它咋搞的猫腻,所以就没有踩它们的脚印,自己整套方法high起来^!^!至于后期要不要增加编译的其他部分,再说。现在用它来拉拉风!顺便解释下C语言真正机密——归约!
1、C语言C99文法树
C99文法树图,这是C99标准文法,画成图了,方便查阅,便于理解。其中实线是归约方向,虚线箭头不是归约指向,是箭头指向的产生式中此非终结符的产生式,实线箭头相连两头构成一个产生式!(注:图较大,显示太小,请自行右键图片另存为下载该图片查阅或者干脆查看C99文法,都中)
值得提醒一点的是,单纯从文法上讲,它不是树,更准确的说是图,但为了方便理解,中间交织的内容就没有连接,从而看上去还像一颗树
a、表达式(注,为了便于理解运算符优先级,这部分化成了圈)
b、声明,定义,初始化,抽象类型部分(注,图中有opt的,则表示前面的非终结符可选)
c、语句部分(注,图中有opt的,则表示前面的非终结符可选,鉴于图片大小分布,没有展开)
d、外部定义
e、合成总图(几部分的连接不是绝对的对应,比如expression在多处出现,我只是简单链接一条示意了一下,不要钻牛尖哦)
2、实例探究
如果你没有C语言基础,请按照下面步骤执行,一移动鼠标到浏览器的X,二点击关闭,over,(*^__^*) !如果你是初学者,可能会有点好处;前提是下文你得看得懂!如果你是个码农,可能你会看到之前你没有看到的C的另一层面!如果你是个高级工程师且懂得编译,那么你也按照上面两步走或者高手ALT-F4即可!
阅读说明:(对读懂很重要)
0-仅归约过程,无符号表处理,因此不检查ID的冲突和不对typedef的类型归约
1-归约过程输出的是归约栈的整个栈当前状态
1-归约过程输出的是归约栈的整个栈当前状态
2-连续的栈输出,表示curr的多次归约
3-栈顶非终结符是从上步归约而来
3-栈顶非终结符是从上步归约而来
比如:
declaration-specifiers direct-declarator
declaration-specifiers declarator
declaration-specifiers declarator
其中declarator是从direct-declarator归约而来
再比如:
declaration-list type-specifier declaration-specifiers
declaration-list declaration-specifiers
declaration-list declaration-specifiers
其中declaration-specifiers是由type-specifier declaration-specifiers 归约而来,等等
4-curr输出当前归约的终结符,next是预取下一个要归约的终结符
5-如果curr输出是ID,STR,CONSTANT,则它的真实值是前面的next输出.比如下面的curr: ID, next ; 那么这个ID就是右上vali
6-要结合上面的文法图或者C99标准来解读
7-任何无语法错误的源程序都要归约成一棵树!根结点就是translation-unit
4-curr输出当前归约的终结符,next是预取下一个要归约的终结符
5-如果curr输出是ID,STR,CONSTANT,则它的真实值是前面的next输出.比如下面的curr: ID, next ; 那么这个ID就是右上vali
6-要结合上面的文法图或者C99标准来解读
7-任何无语法错误的源程序都要归约成一棵树!根结点就是translation-unit
话说千言万语不如一个好例子。当然不可能在这里穷举所有相关语法的实例,而只在常用重点上举几个例子!看看 C语言是怎么被解析的!
2.1、基本全局变量
示例代码
int vali;
char valc;
short vals;
long vall;
unsigned int valui;
signed int valsi;
/*其余float double double float
unsigned char, signed char, unsigned short, signed short
unsigned long, signed long都一样的归约过程,不多余举例*/
归约树
curr: int next: vali
type-specifier
declaration-specifiers
curr: ID next: ;
declaration-specifiers direct-declarator
declaration-specifiers declarator
declaration-specifiers init-declarator
declaration-specifiers init-declarator-list
curr: ; next: char
declaration
declaration-list
//归约char valc;
curr: char next: valc
declaration-list type-specifier
declaration-list declaration-specifiers
curr: ID next: ;
declaration-list declaration-specifiers direct-declarator
declaration-list declaration-specifiers declarator
declaration-list declaration-specifiers init-declarator
declaration-list declaration-specifiers init-declarator-list
curr: ; next: short
declaration-list declaration
declaration-list
//归约short vals;
curr: short next: vals
declaration-list type-specifier
declaration-list declaration-specifiers
curr: ID next: ;
declaration-list declaration-specifiers direct-declarator
declaration-list declaration-specifiers declarator
declaration-list declaration-specifiers init-declarator
declaration-list declaration-specifiers init-declarator-list
curr: ; next: long
declaration-list declaration
declaration-list
//归约long vall;
curr: long next: vall
declaration-list type-specifier
declaration-list declaration-specifiers
curr: ID next: ;
declaration-list declaration-specifiers direct-declarator
declaration-list declaration-specifiers declarator
declaration-list declaration-specifiers init-declarator
declaration-list declaration-specifiers init-declarator-list
curr: ; next: unsigned
declaration-list declaration
declaration-list
//归约unsigned int valui;
curr: unsigned next: int
declaration-list type-specifier
curr: int next: valui
declaration-list type-specifier type-specifier
declaration-list type-specifier declaration-specifiers
declaration-list declaration-specifiers
curr: ID next: ;
declaration-list declaration-specifiers direct-declarator
declaration-list declaration-specifiers declarator
declaration-list declaration-specifiers init-declarator
declaration-list declaration-specifiers init-declarator-list
curr: ; next: signed
declaration-list declaration
declaration-list
//归约signed int valsi;
curr: signed next: int
declaration-list type-specifier
curr: int next: valsi
declaration-list type-specifier type-specifier
declaration-list type-specifier declaration-specifiers
declaration-list declaration-specifiers
curr: ID next: ;
declaration-list declaration-specifiers direct-declarator
declaration-list declaration-specifiers declarator
declaration-list declaration-specifiers init-declarator
declaration-list declaration-specifiers init-declarator-list
curr: ; next: NULL
declaration-list declaration
declaration-list
translation-unit //完成
提示
int vali;归约过程为例子
int->type-specifier->declaration-specifiers(1)
ID->direct-declarator->declarator->init-declarator->init-declarator-list (2)
(1)和(2)->declaration.
由于下面还有变量的定义,因此
declaration->declaration-list
上面其他变量的归约过程基本一样,不多解释!
从语法来讲,void, char, short, int, long, float, double, unsigned, signed,可以任意组合N长的类型说明符,比如long long long long int unsigned char short,这8个当成一个类型也是能正确归约的。当然它没有意义!有没有意义这是类型检测的工作,属于后话,先不说!
2.2、结构联合枚举类型声明和定义
示例代码
struct AA;
union BB;
enum CC;
struct girl {
int ga, gb, gc;
};
struct boy {
struct girl bl;
};
struct woman {
union inner {
struct girl gg;
struct boy bb;
}sex;
};
union type{
int vali;
char ch;
long vall;
};
enum tag{
FIRST,
FOLLOW,
LAST,
TEST
};
归约树
curr: struct next: AA
curr: ID next: ;
struct-specifier
type-specifier
declaration-specifiers
curr: ; next: union
declaration
declaration-list
//归约union BB;
curr: union next: BB
curr: ID next: ;
declaration-list union-specifier
declaration-list type-specifier
declaration-list declaration-specifiers
curr: ; next: enum
declaration-list declaration
declaration-list
//归约enum CC;
curr: enum next: CC
curr: ID next: ;
declaration-list enum-specifier
declaration-list type-specifier
declaration-list declaration-specifiers
curr: ; next: struct
declaration-list declaration
declaration-list
/*归约struct girl {
int ga, gb, gc;
};*/
curr: struct next: girl
curr: ID next: {
curr: { next: int
curr: int next: ga
declaration-list struct ID { type-specifier
declaration-list struct ID { specifier-qualifier-list
curr: ID next: ,
declaration-list struct ID { specifier-qualifier-list direct-declarator
declaration-list struct ID { specifier-qualifier-list declarator
declaration-list struct ID { specifier-qualifier-list struct-declarator-list
curr: , next: gb
curr: ID next: ,
declaration-list struct ID { specifier-qualifier-list struct-declarator-list , direct-declarator
declaration-list struct ID { specifier-qualifier-list struct-declarator-list , declarator
declaration-list struct ID { specifier-qualifier-list struct-declarator-list
curr: , next: gc
curr: ID next: ;
declaration-list struct ID { specifier-qualifier-list struct-declarator-list , direct-declarator
declaration-list struct ID { specifier-qualifier-list struct-declarator-list , declarator
declaration-list struct ID { specifier-qualifier-list struct-declarator-list
curr: ; next: }
declaration-list struct ID { struct-declaration
declaration-list struct ID { struct-declaration-list
curr: } next: ;
declaration-list struct-specifier
declaration-list type-specifier
declaration-list declaration-specifiers
curr: ; next: struct
declaration-list declaration
declaration-list
/*归约struct boy {
struct girl bl;
};*/
curr: struct next: boy
curr: ID next: {
curr: { next: struct
curr: struct next: girl
curr: bl next: ID
declaration-list struct ID { struct-specifier
declaration-list struct ID { type-specifier
declaration-list struct ID { specifier-qualifier-list
curr: ID next: ;
declaration-list struct ID { specifier-qualifier-list direct-declarator
declaration-list struct ID { specifier-qualifier-list declarator
declaration-list struct ID { specifier-qualifier-list struct-declarator-list
curr: ; next: }
declaration-list struct ID { struct-declaration
declaration-list struct ID { struct-declaration-list
curr: } next: ;
declaration-list struct-specifier
declaration-list type-specifier
declaration-list declaration-specifiers
curr: ; next: struct
declaration-list declaration
declaration-list
/*归约struct woman {
union inner {
struct girl gg;
struct boy bb;
}sex;
};*/
curr: struct next: woman
curr: ID next: {
curr: { next: union
curr: union next: inner
curr: ID next: {
curr: { next: struct
curr: struct next: girl
curr: gg next: ID
declaration-list struct ID { union ID { struct-specifier
declaration-list struct ID { union ID { type-specifier
declaration-list struct ID { union ID { specifier-qualifier-list
curr: ID next: ;
declaration-list struct ID { union ID { specifier-qualifier-list direct-declarator
declaration-list struct ID { union ID { specifier-qualifier-list declarator
declaration-list struct ID { union ID { specifier-qualifier-list struct-declarator-list
curr: ; next: struct
declaration-list struct ID { union ID { struct-declaration
declaration-list struct ID { union ID { struct-declaration-list
curr: struct next: boy
curr: bb next: ID
declaration-list struct ID { union ID { struct-declaration-list struct-specifier
declaration-list struct ID { union ID { struct-declaration-list type-specifier
declaration-list struct ID { union ID { struct-declaration-list specifier-qualifier-list
curr: ID next: ;
declaration-list struct ID { union ID { struct-declaration-list specifier-qualifier-list direct-declarator
declaration-list struct ID { union ID { struct-declaration-list specifier-qualifier-list declarator
declaration-list struct ID { union ID { struct-declaration-list specifier-qualifier-list struct-declarator-list
curr: ; next: }
declaration-list struct ID { union ID { struct-declaration-list struct-declaration
declaration-list struct ID { union ID { struct-declaration-list
curr: } next: sex
declaration-list struct ID { union-specifier
declaration-list struct ID { type-specifier
declaration-list struct ID { specifier-qualifier-list
curr: ID next: ;
declaration-list struct ID { specifier-qualifier-list direct-declarator
declaration-list struct ID { specifier-qualifier-list declarator
declaration-list struct ID { specifier-qualifier-list struct-declarator-list
curr: ; next: }
declaration-list struct ID { struct-declaration
declaration-list struct ID { struct-declaration-list
curr: } next: ;
declaration-list struct-specifier
declaration-list type-specifier
declaration-list declaration-specifiers
curr: ; next: union
declaration-list declaration
declaration-list
/*归约union type{
int vali;
char ch;
long vall;
};*/
curr: union next: type
curr: ID next: {
curr: { next: int
curr: int next: vali
declaration-list union ID { type-specifier
declaration-list union ID { specifier-qualifier-list
curr: ID next: ;
declaration-list union ID { specifier-qualifier-list direct-declarator
declaration-list union ID { specifier-qualifier-list declarator
declaration-list union ID { specifier-qualifier-list struct-declarator-list
curr: ; next: char
declaration-list union ID { struct-declaration
declaration-list union ID { struct-declaration-list
curr: char next: ch
declaration-list union ID { struct-declaration-list type-specifier
declaration-list union ID { struct-declaration-list specifier-qualifier-list
curr: ID next: ;
declaration-list union ID { struct-declaration-list specifier-qualifier-list direct-de