1、概要
前三篇博文(0,1,2)主要讨论是声明和定义的相关语法归约。从这篇文字开始,将开始进行有效的计算,涉及表达式和语句。
首先,表达式和语句这两个概念是不同的,表达式是没有分号(;)的,而表达式+;构成语句。但这不是语句的全部,语句还可以是跳转,迭代,标签语句等等(见图片C语句文法图)!打个比喻来说吧——就是蛋和鸡的关系!当然不是那个悖论,而是表达式是蛋,孵化是分号,鸡是语句。蛋孵化成鸡。鸡肚子里可以有蛋!嘎嘎!二者区别必须明白。不能混为一谈!
在C语言中,如果单纯就表达式计算而言,表达式就是一个人,而分号;好似一张毕业证,有它你就是正规的劳动人员,哪怕你什么都不干什么都不会(比如单个分号;)而没它,你就是没户口的黑孩,不能参与计算劳动,编译器抱怨的不得了,就是不让你上岗运行!
其次,说到表达式,运算符的优先级问题就不得不提一提了。C中的优先级是由表达式文法决定的!当初学C的时候都是死记硬背的,那时候觉得这个优先级是C它爹里奇严格要求,每次运算的时候都要检测后面的优先级,看它是不是比当前运算符优先级高。而且一直觉得编译器也是这样做的。而事实上不是,广义上讲是严格要求,因为它已经写入了文法,归约顺序是固定的,就像法律条文一样,是严格约束的;但是从狭义上而论。这个优先级是很自然的事情,不需要摇头晃脑的背,也不用比较优先级高低来实现,而是语法归约过程很自然的东西。一级一级的归约,一级一级的蹦哒,到了哪个阶段,那个阶段归约,优先级自然就隐含在里面了!它们的归约顺序决定了它们优先级!
通过表达式对归约过程的理解,把它画成一个顺时钟的表圈更直观!如上图所示!(图片较大,另存为下载可正常查阅)
在中心处写了一段:运算符的结合只能从高到低而不能逆向进行(归约箭头方向决定了),较低运算符优先结合的方法是使用()在零点方向。()是相当复位运算符,使得较低运算符能够回到最高优先级处改变运算符结合顺序!这样较低运算符能够先运算之后再和较高运算符结合;注意归约过程不会跳跃!(下文示例可以得知这一点)即向‘上游’运算符结合,必须顺时钟走一圈,并且使用了(),否则达到零点前expression处就归约停止!
举个简单例子帮助理解这一段话:a+1<<8和a+(1<<8)
a+1<<8归约过程
a是id->primary-expr->postfix-expr->unary-expr->cast-expr->mul-expre->additive-expr(暂停)
+
1是constant->primary-expr->postfix-expr->unary-expr->cast-expr->mul-expr(暂停)
然后additive-expr+mul-expr->additive-expr->shift-expr
<<
8是constant->primary-expr->postfix-expr->unary-expr->cast-expr->mul-expr->additive-expre(暂停)
shift-expr<<additive-expr->shift-expr->relational-expr->equality-expr->...->expr(暂停)
a+(1<<8)归约过程
a是id->primary-expr->postfix-expr->unary-expr->cast-expr->mul-expr->additive-expr(暂停)
+
(
1是constant->primary-expr->postfix-expr->unary-expr->cast-expr->mul-expr->additive-expr->shift-expr(暂停)
<<
8是constant->primary-expr->postfix-expr->unary-expr->cast-expr->mul-expr->additive-expr(暂停)
shift-expr<<additive-expr->shift-expr->relational-expr->equality-expr->...->expr(暂停)
)
(expr)->primary-expr->postfix-expr->unary-expr->cast-expr->mul-expr
additive-expr+mul-expr->additive-expr->shift-expr->...->expr
注意区分它们的不同!或许你会问如何知道到什么时候需要暂停,什么时候继续归约?答案就在非终结符的follow基上!什么是follow集以及first基,请参与《编译原理》第4章语法分析部分!这里就不重述了!
在这里你只需要知道:当下一个运算符是当前非终结符要归约到的非终结符的follow基时,则继续归约,否则暂停。比如上面这个例子1的归约shift-expression的follow基包含<<,那么additive-expression就需要归约到shift-expression,再往下,relational-expression的follow基不包含<<,所以shift-expression就到此暂停,不能再归约下去!而等待其他部分(<< 和additive-expression)到来,再一起归约!
如果上文看不懂,不要紧,在下面的示例中会给出很多组合范例,可以多看几个就理解了,当然你要结合C99文法或者上图来理解!
最后,为了更好描述原理,这里要相对前面的声明定义而言做些调整!单个示例进行提示!表达式示例分两大类,基本常用和高级复合!在此文将给出基本常用表达式归约。下一篇给出复合表达式归约。
输出依旧老风格,整个归约栈,其实是一颗树,只不过是栈的形式描述的。每次归约都是从孩子到父亲的建树过程,因为这是LR(1),自底向上!(LL正好相反,自顶向下)整个归约纳入一个函数当中,每次栈的输出开头“declaration-specifiers declarator { block-item-list“它属于函数归约的部分,压在栈中而已,可以忽略不看,重点在表达式的归约上!另外,表达式之间过度部分如下,也可以忽略不看!
declaration-specifiers declarator { expression-statement
declaration-specifiers declarator { statement
declaration-specifiers declarator { block-item
declaration-specifiers declarator { block-item-list
2、表达式归约
2.1、基本表达式
示例代码
void basic_exp()
{
left = a[i];
left = i++;
left = i--;
left = fun(i);
left = girl.age;
left = girl->wight;
left = ++i;
left = --i;
left = *a;
left = &a;
left = !a;
left = ~a;
left = +a;
left = -a;
left = sizeof(int);
left = (int *)a;
left = a * b;
left = a / b;
left = a % b;
left = a + b;
left = a - b;
left = a << 1;
left = b >> 1;
left = a > b;
left = a < b;
left = a <= b;
left = a >= b;
left = a != b;
left = a == b;
left = a & b;
left = a ^ b;
left = a | b;
left = a && b;
left = a || b;
left = a > b ? a : b;
left = a = 1;
left = a >>= 1;
left = a, b;
left = (a + b) * c;
}
归约过程
{
curr: void next: basic_exp
type-specifier
declaration-specifiers
curr: ID next: (
declaration-specifiers direct-declarator
curr: ( next: )
curr: ) next: {
declaration-specifiers direct-declarator
declaration-specifiers declarator
curr: { next: left
left = a[i];
curr: ID next: =
declaration-specifiers declarator { primary-expression
declaration-specifiers declarator { postfix-expression
declaration-specifiers declarator { unary-expression
curr: = next: a
declaration-specifiers declarator { unary-expression assignment-operator
curr: ID next: [
declaration-specifiers declarator { unary-expression assignment-operator primary-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression
curr: [ next: i
curr: ID next: ]
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ primary-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ postfix-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ unary-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ cast-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ multiplicative-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ additive-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ shift-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ relational-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ equality-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ AND-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ exclusive-OR-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ inclusive-OR-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ logical-AND-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ logical-OR-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ conditional-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ assignment-expression
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression [ expression
curr: ] next: ;
declaration-specifiers declarator { unary-expression assignment-operator postfix-expression
declaration-specifiers declarator { unary-expression assignment-operator unary-expression
declaration-specifiers declarator { unary-expression assignment-operator cast-expression
declaration-specifiers declarator { unary-expression assignment-operator multiplicative-expression
declaration-specifiers declarator { unary-expression assignment-operator additive-expression
declaration-specifiers declarator { unary-expression assignment-operator shift-expression
declaration-specifiers declarator { unary-expression assignment-operator relational-expression
declaration-specifiers declarator { unary-expression assignment-operator equality-expression
declaration-specifiers declarator { unary-expression assignment-operator AND-expression
declaration-specifiers declarator { unary-expression assignment-operator exclusive-OR-expression
declaration-specifiers declarator { unary-expression assignment-operator inclusive-OR-expression
declaration-specifiers declarator { unary-expression assignment-operator logical-AND-expression
declaration-specifiers declarator { unary-expression assignment-operator logical-OR-expression
declaration-specifiers declarator { unary-expression assignment-operator conditional-expression
declaration-specifiers declarator { unary-expression assignment-operator assignment-expression
declaration-specifiers declarator { assignment-expression
declaration-specifiers declarator { expression
curr: ; next: left
declaration-specifiers declarator { expression-statement
declaration-specifiers declarator { statement
declaration-specifiers declarator { block-item
declaration-specifiers declarator { block-item-list
left = i--;
curr: ID next: =
declaration-specifiers declarator { block-item-list primary-expression
declaration-specifiers declarator { block-item-list postfix-expression
declaration-specifiers declarator { block-item-list unary-expression
curr: = next: i
declaration-specifiers declarator { block-item-list unary-expression assignment-operator
curr: ID next: --
declaration-specifiers declarator { block-item-list unary-expression assignment-operator primary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression
curr: -- next: ;
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator unary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator cast-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator multiplicative-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator additive-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator shift-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator relational-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator equality-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator exclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator inclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator conditional-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator assignment-expression
declaration-specifiers declarator { block-item-list assignment-expression
declaration-specifiers declarator { block-item-list expression
curr: ; next: left
declaration-specifiers declarator { block-item-list expression-statement
declaration-specifiers declarator { block-item-list statement
declaration-specifiers declarator { block-item-list block-item
declaration-specifiers declarator { block-item-list
left = fun(i);
curr: ID next: =
declaration-specifiers declarator { block-item-list primary-expression
declaration-specifiers declarator { block-item-list postfix-expression
declaration-specifiers declarator { block-item-list unary-expression
curr: = next: fun
declaration-specifiers declarator { block-item-list unary-expression assignment-operator
curr: ID next: (
declaration-specifiers declarator { block-item-list unary-expression assignment-operator primary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression
curr: ( next: i
curr: ID next: )
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( primary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( postfix-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( unary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( cast-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( multiplicative-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( additive-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( shift-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( relational-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( equality-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( exclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( inclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( logical-AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( logical-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( conditional-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( assignment-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression ( argument-expression-list
curr: ) next: ;
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator unary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator cast-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator multiplicative-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator additive-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator shift-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator relational-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator equality-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator exclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator inclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator conditional-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator assignment-expression
declaration-specifiers declarator { block-item-list assignment-expression
declaration-specifiers declarator { block-item-list expression
curr: ; next: left
declaration-specifiers declarator { block-item-list expression-statement
declaration-specifiers declarator { block-item-list statement
declaration-specifiers declarator { block-item-list block-item
declaration-specifiers declarator { block-item-list
curr: ID next: =
declaration-specifiers declarator { block-item-list primary-expression
declaration-specifiers declarator { block-item-list postfix-expression
declaration-specifiers declarator { block-item-list unary-expression
curr: = next: girl
declaration-specifiers declarator { block-item-list unary-expression assignment-operator
curr: ID next: .
declaration-specifiers declarator { block-item-list unary-expression assignment-operator primary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression
curr: . next: age
curr: ID next: ;
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator unary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator cast-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator multiplicative-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator additive-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator shift-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator relational-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator equality-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator exclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator inclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator conditional-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator assignment-expression
declaration-specifiers declarator { block-item-list assignment-expression
declaration-specifiers declarator { block-item-list expression
curr: ; next: left
declaration-specifiers declarator { block-item-list expression-statement
declaration-specifiers declarator { block-item-list statement
declaration-specifiers declarator { block-item-list block-item
declaration-specifiers declarator { block-item-list
left = girl->wight;
curr: ID next: =
declaration-specifiers declarator { block-item-list primary-expression
declaration-specifiers declarator { block-item-list postfix-expression
declaration-specifiers declarator { block-item-list unary-expression
curr: = next: girl
declaration-specifiers declarator { block-item-list unary-expression assignment-operator
curr: ID next: ->
declaration-specifiers declarator { block-item-list unary-expression assignment-operator primary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression
curr: -> next: wight
curr: ID next: ;
declaration-specifiers declarator { block-item-list unary-expression assignment-operator postfix-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator unary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator cast-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator multiplicative-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator additive-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator shift-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator relational-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator equality-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator exclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator inclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator conditional-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator assignment-expression
declaration-specifiers declarator { block-item-list assignment-expression
declaration-specifiers declarator { block-item-list expression
curr: ; next: left
declaration-specifiers declarator { block-item-list expression-statement
declaration-specifiers declarator { block-item-list statement
declaration-specifiers declarator { block-item-list block-item
declaration-specifiers declarator { block-item-list
left = ++i;
curr: ID next: =
declaration-specifiers declarator { block-item-list primary-expression
declaration-specifiers declarator { block-item-list postfix-expression
declaration-specifiers declarator { block-item-list unary-expression
curr: = next: ++
declaration-specifiers declarator { block-item-list unary-expression assignment-operator
curr: ++ next: i
curr: ID next: ;
declaration-specifiers declarator { block-item-list unary-expression assignment-operator ++ primary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator ++ postfix-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator ++ unary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator unary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator cast-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator multiplicative-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator additive-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator shift-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator relational-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator equality-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator exclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator inclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator conditional-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator assignment-expression
declaration-specifiers declarator { block-item-list assignment-expression
declaration-specifiers declarator { block-item-list expression
curr: ; next: left
declaration-specifiers declarator { block-item-list expression-statement
declaration-specifiers declarator { block-item-list statement
declaration-specifiers declarator { block-item-list block-item
declaration-specifiers declarator { block-item-list
left = --i;
curr: ID next: =
declaration-specifiers declarator { block-item-list primary-expression
declaration-specifiers declarator { block-item-list postfix-expression
declaration-specifiers declarator { block-item-list unary-expression
curr: = next: --
declaration-specifiers declarator { block-item-list unary-expression assignment-operator
curr: -- next: i
curr: ID next: ;
declaration-specifiers declarator { block-item-list unary-expression assignment-operator -- primary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator -- postfix-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator -- unary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator unary-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator cast-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator multiplicative-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator additive-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator shift-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator relational-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator equality-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator exclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator inclusive-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-AND-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator logical-OR-expression
declaration-specifiers declarator { block-item-list unary-expression assignment-operator conditional-expression
declaration-specifiers declarator { block-item-list unary-expression