这样,图8.9中的第(3)条产生式及其有关语义描述如图8.10。
图 8.10 类型转换的语义处理
  产生式 语义动作
  E→E1*E2 {E.place∶=newtemp;
if E1.type=int AND E2.type=int then
begin emit(E.place,′∶=′,E1.place,′*i′, E2.place);
      E.type∶=int
end
else if E1.type=real AND E2.type=real then
begin emit (E.place,′∶=′,E1.place,′*r′,E2.place);
      E.type∶=real
end
else if E1.type=int/* and E2.type=real */ then
begin t∶=newtemp;
   emit(t,′∶=′,′itr′,E1.place);
   emit(E.place,′∶=′,t,′*r′,E2.place);
   E.type∶=real
end
else /*E1·type=real and E2.type=int*/
begin t∶=newtemp;
   emit(t,′∶=′;′itr′,E2.place);
   emit(E.place,′∶=′,E1.place,′*r′,t);
   E.type∶=real
end;
  图8.9中的例子里,与非终结符E相联的语义值有E.place,还有E.type。语义值的设计是与语义处理的描述相关的。大家回顾一下PL/0编译程序中对赋值语句的语义处理,其中对赋值语句左部的标识符,检查它的种类(kind),若不是变量名,则指出错误,若是变量名,才生成赋值运算的代码。对右部表达式中作为运算对象的标识符,检查其是否变量名或常量名,是,生成相应代码,不是(即是过程名),则指出错误。这一点若用语义规则描述的话,还应增加一语义值,与非终结符相联,比如用E.kind表示。
  赋值语句中会含有复杂数据类型,如数组元素、记录(结构)的引用。这种情况的翻译工作要复杂些,我们将在后面给予专门讨论。