标题：布尔表达式
概述
n布尔表达式是布尔运算量和逻辑运算符按一定语法规则组成的式子。　　n逻辑运算符通常有∧、∨、﹃三种（在某些语言中，还有≡（等价）及→（蕴含）等等）；
n逻辑运算对象可以是逻辑值（True 或False）、布尔变量、关系表达式以及由括号括起来的布尔表达式。
n不论是布尔变量还是布尔表达式，都只能取逻辑值True或False。在计算机内通常用1（或非零整数）表示真值（True），用0表示假值(False)。
n关系表达式是形如E1 Rop E2的式子，其中E1和E2为简单算术表达式，Rop 为关系运算符（<, >, =, <=, >=, <> ）。若E1和E2之值使该关系式成立，则此关系表达式之值为True ，否则为False 。
布尔表达式的语义及作用
布尔表达式的语义在于指明计算一个逻辑值的规则.
布尔表达式在程序设计语言中有两个基本的作用：
一是在某些控制语句中作为实现控制转移的条件；
另一个则是用于计算逻辑值本身。
约定:各类运算符的优先顺序（由高至低）如下：
⒈括号
⒉算术运算符       *(乘法)   / （除法） +（加法） -（减法） %（模）（返回一个除法的整数余数，例如：12%5=2，这里是因为12除以5的余数是2）
⒊关系运算符       <（小于）、<=（小于等于）、=（等于）、>（）大于、>=（大于等于）、<>（不等于）
⒋逻辑运算符       ┒  ∧   ∨
3. 布尔表达式的等价解释-求值角度
为了方便起见，下面我们仅讨论由文法
E→ E∧E | E∨E | ┑E | (E) |  I  |  i  Rop i  (5.1)
可采用类似算术表达式的方式来进行。例如，对于布尔表达式A∨B∧C，可翻译为：
(∧,        B,    C,    T1 )
(∨,        A,    T1,  T2 )
布尔表达式的等价解释-过程角度
对于一个布尔表达式而言，我们的目的仅仅是为了判定它的真假值。因此，有时只需计算它的一个子表达式，便能确定整个布尔表达式的真假值。例如，对于A∨B，只要知道A为真，则无论B取何值，表达式的结果一定为真。
可见，对于三种常见逻辑运算，可作如下等价的解释：
A∧B      —(A) ? B : 0         (5.2)
A∨B      —(A) ? 1 : B         (5.3)
﹃A          (A) ? 0 : 1          (5.4)
布尔表达式的出口
对于布尔表达式A∨（B∧（┑C∨D）)，其等价的表述是
A ？1 ：（B ？（（C ？0 ：1）？  1 ：D ）：0  ）
显然，采用此种结构可产生更为有效的中间代码。这里需假定原布尔表达式的计算过程中不含有任何的副作用。
在上式的计算中，根据A、B、C、D的取值不同，计算的结果以及运算的终止点亦不同。例如，当A=1（真）时，结果为1且终止于左边第一个‘1’处。
这样终止的点我们称为该布尔表达式的出口，同时，把使布尔表达式取值为真的出口称为真出口，反之称为假出口。
对一个布尔表达式而言，它至少有一个真出口和一个假出口（当然可以有多个）。在用于控制流程的布尔表达式E的计算中，这些出口分别指出当E值为真和假时，控制所应转向的目标（即某一四元式的序号）。
控制语句中的布尔表达式
if E then S1 else S2或while E do S
布尔表达式真假值的确定
一个布尔表达式E的真假值的确定，是在语法翻译过程中，根据(5.2)-(5.4)等价解释式逐步进行的。
例如，对于布尔表达式       E = E(1)∨E(2)
若E(1)为真，则E必为真，故E(1)的真出口必是E的真出口(之一);
若E(1)为假，则E的真假值取决于E(2)的真假值，此时，需对E(2)进行计算，由此可见，E(1)的假出口应为E(2)对应的四元式的序号(E(2)的入口)，同时,E(2)的真、假出口也是E的真、假出口。
类似地，可确定E(1)∧E(2)、﹃E及更复杂的表达式的真、假出口。
条件语句的翻译结果
在设计布尔表达式翻译算法（即编写语义动作）时，可定义和使用如下三类四元式：
(jnz, A1, ,p)—当A1为真(非零)时，转向第p四元式；
(jrop,A1,A2,p)当关系A1 rop A2成立时，转向第p四元式；
(j, , ,p)无条件转向第p四元式
例如，对于条件语句
if A∨B<C then S1 else S2
经翻译后，可得四元式序列：
(1)            (jnz, A, -, 5)
(2)          (j, - ,- , 3)
(3)          (j<, B, C, 5)
(4)          (j, -, -, p+1)
(5)          S1相应的四元式序列
(p)          (j, -, -, q)
(p+1)   S2相应的四元式序列
(q)   …
其中，表达式A的真出口为5（也是整个表达式的真出口），假出口为3（即表达式B<C的第一四元式）；B<C的真、假出口也分别是整个表达式的真、假出口。
拉链与回填
在自底向上的语法制导翻译时（或者说，在S-属性翻译文法中), 在产生一个(无)条件转移四元式时, 它所要转向的那个四元式有时尚未产生，故无法立即产生一个完全的控制转移四元式。
例如，在上例中，在产生第一个四元式时，由于语句S1的中间代码尚未产生，即A的真出口确切位置并不知道，故此时只能产生一个空缺转移目标的四元式    (jnz,A,-,0),
并将此四元式的序号(即1)作为语义信息存起来，待开始翻译S1时，再将S1的第一四元式的序号(即5)回填这个不完全的四元式。
另外，在翻译过程中，常常会出现若干转移四元式转向同一目标，但此目标的具体位置又尚未确定的情况，此时我们可将这些四元式用拉链的办法将它们链接起来，用一指针指向链头，在确定了目标四元式的位置之后，再回填这个链。
n对于一个布尔表达式E来说，它应有两条链：真出口链(称为T链，记作TC)和假出口链(称为F链，记作FC)。它们就是非终结符Expr的两个属性Expr  . TC及Expr .  FC。
n例如，对于上述if语句中的布尔式E=A∨B<C，在翻译过程中形成的T链和F链如右图所示。
n其中，每条链都是利用四元式中的Result域连接的，Result >0时,它给出本链的后继四元式的序号，Result =0时表示本四元式是链尾结点。
文法的“拆分”
n为便于实现布尔表达式的语法制导翻译，我们先改写文法，以便能在翻译过程中的适当时机获得所需的语义属性值。例如，可将文法(5.1)改写为：
qExpr®Expr^ Expr | Expr∨ Expr | ﹃ Expr|
iden |iden Rop iden | ( Expr )
Expr^ ® Expr ∧
Expr∨® Expr ∨                  (5.7)
n将文法进行“拆分”的目的:
1.在翻译完运算符∧（∨）左侧的表达式后，能够及时获取其语义属性TC及FC
2.完成用下一四元式序号（即运算符右侧表达式的第一四元式之序号）回填前一表达式的相应真（假）链TC（FC），
3.将其另一链FC（TC）作为产生式左部符号的综合属性FC（TC）传播之。
语义变量及辅助语义函数
1.NXQ—全局变量，用于指示所要产生的下一四元式的序号；
2.GEN（…）—其意义同前,每次调用,NXQ++；
3.  int Merge(int p1,int p2)—将链首“指针”分别为p1和p2的两条链合并为一条，并返回新链的链首“指针”（此处的“指针”实际上是四元式的序号，应为整型值）我们假定四元式是以一结构形式表示（存储）的：
struct _Quadruple{
int Op, arg1, arg2, Result;
} QuadrupleList[]; 
4.void BackPatch(int p,int t)—用四元式序号t回填以p为首的链，将链中每个四元式的Result域改写为t的值。
函数Merge( )及BackPatch( )的程序见书
翻译布尔表达式的属性文法
1.Expr→iden { $$.TC= NXQ;  $$.FC= NXQ+1;             GEN(jnz, Entry($1), 0, 0);  GEN(j,0,0,0); }
| iden rop iden { $$.TC= NXQ;  $$.FC= NXQ+1;
GEN(jrop, Entry($1), Entry($3), 0);
GEN(j, 0, 0, 0); }
|  ‘(’ Expr  ‘)’ { $$.TC= $2 . TC;   $$.FC= $2.FC; }
| ‘﹃’ Expr    { $$.TC= $2.FC;   $$.FC= $2 . TC; }
| Expr^   Expr  
{ $$.TC= $2 . TC;  $$.FC=Merge($1.FC,$2.FC); }
| Expr∨  Expr 
{ $$.FC= $2.FC;  $$.TC=Merge($ 1 . TC,$2 . TC); }
| Expr^→ Expr ‘∧’ 
{ BackPatch($ 1 . TC,NXQ);  $$.FC= $1.FC; }
| Expr∨→ Expr ‘∨’ 
{BackPatch($1.FC,NXQ);  $$.TC= $ 1 . TC; }