High-Level Definitions
这一部分包含了C(-)*语言中所有的高层(全局变量以及函数定义)语法。
语法单元Program是初始语法单元,代表整个程序。
每一个Program可以产生一个ExtDefList,这里ExtDefList代表零个或多个ExtDef。
每一个ExtDef就代表着一个全局变量的定义、一个结构体的定义或者一个函数的
定义。其中,
ExtDef→SpecifierExtDecList SEMI这条产生式代表对全局变量的定义,例如int
global1, global2;其中Specifier代表类型,ExtDecList为零个或者多个对一个
变量的定义VarDec。
ExtDef→Specifier SEMI这条产生式专门为结构体的定义而准备,例如struct
{…};当然这条产生式会允许出现“int;”这样没有意义的语句,但实际上在标准
C中这样的语句是合法的。
ExtDef→SpecifierFunDecCompSt这条产生式代表函数定义:Specifier是返回类
型,FunDec是函数头,CompSt代表函数体。
Specifiers
这一部分产生式主要与变量的类型有关。
Specifier是类型描述符,它有两种取值:一种(Specifier→TYPE)是直接变成基
本类型int或float,而另一种(Specifier→StructSpecifier)是变成结构体类型
对于结构体类型来说,
StructSpecifier→STRUCT OptTag LC DefListRC:这是定义结构体的基本格式,
例如struct Complex { int real, image;}。其中OptTag可有可无,因此也可以这
样写:struct {int real, image;}。
StructSpecifier→STRUCT Tag:如果之前已经定义过了某个结构体,比如struct
Complex {…},那么之后就可以直接使用该结构体定义变量,例如struct
Complex a, b;,而不需要重新定义这个结构体。
Declarators
这一部分产生式主要与变量和函数的定义有关。
VarDec代表了对一个变量的定义。一个变量可以直接是一个标识符(例如int a
中的a),也可以是一个标识符后面跟若干个方括号括起来的数字(如int a[10][2]
中的a[10][2],这种情况下a是一个数组)。
FunDec代表了对一个函数头的定义。它包括一个代表函数名的标识符以及由圆
括号括起来的一个形参列表,该列表由VarList表示(也可能为空)。VarList可以
包括若干个ParamDec,其中每一个ParamDec都是对一个形参的定义,该定义由
类型描述符Specifier和变量定义VarDec组成。一个完整的函数头的例子为:foo(int
x, float y[10])
Statements
这一部分产生式主要与语句有关。
CompSt代表了一个由一对花括号括起来的语句块。语句块内部先是一系列变量
的定义DefList,然后是一系列的语句StmtList。可以发现,对CompSt的这种定义
是不允许在程序的任何位置定义变量的,必须在每一个语句块的开头才能定义。
StmtList就是零个或多个Stmt的组合。每一个Stmt都代表一条语句,这条语句可
以是一个在末尾添了分号的表达式(Exp SEMI),可以是另一个语句块(CompSt),
可以是一条返回语句(RETURN Exp SEMI),可以是一条if-then语句(IF LP Exp RP
Stmt),可以是一条if-then-else语句(IF LP ExpRP Stmt ELSE Stmt),也可以是一
条while语句(WHILE LP Test RP Stmt)
Local Definitions
这一部分产生式主要与局部变量的定义有关。
DefList这个语法单元前面曾出现在CompSt以及StructSpecifier产生式的右边,说
白了它就是一串像int a; float b,c; int d[10];这样的变量定义。一个DefList可以由零
个或者多个Def组成。
每一个Def就是一条定义,它包括一个类型描述符Speicifier以及一个DecList,例
如inta,b,c; 由于DecList中的每一个Dec又可以变成VarDec ASSIGNOP Exp,这说明
我们是允许对局部变量在定义时进行初始化的,例如int a = 5;
Expressions
这一部分产生式主要与表达式有关。
表达式可以演化出的形式多种多样,但总体上看不外乎下面几种:
包含二元运算符的表达式包括赋值表达式(Exp ASSIGNOP Exp)、逻辑与(Exp
AND Exp)、逻辑或(Exp OR Exp)、关系表达式(ExpRELOP Exp)以及四则
运算表达式(ExpPLUS Exp等)。
包含一元运算符的表达式包括括号表达式(LP Exp RP)、取负(MINUSExp)
以及逻辑非(NOT Exp)。
不包含运算符但又比较特殊的表达式包括函数调用表达式(带参数的IDLP
Args RP以及不带参数的ID LP RP)、数组访问表达式(Exp LB Exp RB)以及结
构体访问表达式(Exp DOT ID)。
最基本的表达式包括整数常量(INT)、浮点数常量(FLOAT)以及普通变量
(ID)。
语法单元Args代表实参列表,每一个实参都可以变成一个表达式Exp。
由于表达式中可以包含各种各样的运算符,为了消除潜在的二义性问题,我们
需要对这些运算符规定优先级(precedence)以及结合性(associativity)。