源語言->中間代碼->目標語言
中間代碼(Intermediate Representation或者IR):複雜性介於源程序語言和機器語言的一種表示形式。css
編譯程序鎖使用的中間代碼有多種形式。常見的有逆波蘭記號,三元式。四元式。和樹形表示。四元式是一種廣泛採用的中間代碼形式,很是類似於三地址指令,有時把這類中間表示稱爲「三地址代碼」,這樣的表示可以看做是一種虛擬三地址機的通用匯編碼,每條」指令「包括操做符和三個地址,兩個是爲運算對象的,一個是爲結果的。
基本表達式的翻譯模式:
(1)
Exp:Exp ASSIGNOP Exp
|Exp AND Exp
|Exp OR Exp
|Exp PLUS Exp
|Exp MINUS Exp
|Exp STAR Exp
|Exp DIV Exp
|ID
|INTEGER
|FLOAT
;
分析:
(1)要給每一個語法樹結點添加一個place屬性,這個place屬性的值依據下面規則計算。
1)假設EXP->ID,不需要爲ID創建暫時變量,place的值就等於變量ID的名字;
2)假設EXP->INTEGER|FLOAT,即推出常數。不需要爲常數創建暫時變量,place的值就等於常數值。
3)E->E1=E2,E1->IDvim
emit($1);printf("=");emit($3);
step1:輸出ID;
step2:輸出=
step3:輸出E2.place數組
4)i+1;E->E1+E2。newtemp,創建一個暫時變量,E.place=E1.place+E2.place,markdown
$$>t=newtemp();//建立暫時變量
emit($$);//輸出建立E.place
printf("=");//輸出=
emit($1);//輸出E1.place
printf("+");//輸出+
emit($3);//輸出E2.place
也就是說,在語法樹的葉子結點存在兩種place,一種是ID,即變量名,一種是整數或者浮點數。這兩種place值都和暫時變量無關,不需要創建暫時變量的操做。
place的值相應到四元式中:
1)常數
2)源程序中變量名ID
3)爲生成四元式而創建的暫時變量名。ide
方法一:變量名採用t加上數字的形式。爲所有的暫時變量名建立一個符號表,記其在符號表中的位置,這個位置是一個在整數v。從0開始。輸出時,輸出’t’+v,就可以輸出t0,t1這樣的形式,而且有效地避免了變量名的反覆。
方法二:直接將place設置成整數類型,再設置一個標記數組used[],用了一個整數i。就在標記數組中將used[i]=-1,表示ti已經被用過了。這樣一來。建立一個暫時變量。至關於設置place的值,而後更改used[]數組的值。函數
place應該是一個Union,有3種可能值。
1)int i(相應INTEGER)
2)char* (相應變量名ID)
3)float (相應FLOAT)
4)int t;相應暫時變量編號
爲了能識別place的值是4種中哪種,再爲語法樹結點增添一個ptag,1爲int,2爲float。3爲char,4爲暫時變量編號。post
union
{
int i;
char* s;
float f;
}place;
int tag;//標誌位
int main()
{
place.s="ID";
tag=1;
if(tag==1)
printf("%s",place);
}
除了EXP->ID,EXP->常數,每一條基本表達式規則要有一個輸出四元式的操做,emit。flex
代碼更改:
由於用union致使了內存的錯亂(詳細什麼緣由,事後還需要研究),所以將union去掉,4種類型都設置爲語法樹結點的成員。這樣一來可能浪費了空間,但是能保證代碼的正確性。ui
經過在詞法分析。語法分析和語義分析程序的基礎上,將C—源碼翻譯成中間代碼。認識中間代碼的表示形式和生成中間代碼的原理和技巧。掌握對簡單賦值語句的翻譯過程。從而達到對編譯器的編譯原理有更深的理解。提升代碼能力和代碼修養。編碼
在詞法分析,語法分析和語義分析程序的基礎上。將C—源碼翻譯成中間代碼,中間代碼的表示採用四元式,本實驗中僅僅對基本表達式進行翻譯,即將下面規則翻譯成四元式:表達式賦值語句,兩個表達式的邏輯與,邏輯或,加。減,乘。除。
Exp:Exp ASSIGNOP Exp
|Exp AND Exp
|Exp OR Exp
|Exp PLUS Exp
|Exp MINUS Exp
|Exp STAR Exp
|Exp DIV Exp
|ID
|INTEGER
|FLOAT
;
(1)程序總共包括4個文件gramtree_v1.h gramtree_v1.c gramtree.l gramtree_v1.y
gramtree_v1.h gramtree_v1.c定義和實現了:
1)語法樹結構體,語法樹建立函數,語法樹遍歷函數
2)變量符號表結構體,變量符號表的創建函數,查找變量是否已定義的函數。查找變量類型的函數
3)函數符號表結構體,函數符號表的創建函數,查找函數是否已定義。查找函數類型,查找函數形參個數。
4)數組符號表,數組符號表的創建函數,查找數組是否已定義的函數,查找數組類型的函數
5)結構體符號表,結構體符號表的創建函數,查找結構體是否已定義的函數
6)關於生成中間表達式的2個函數:newtemp()和emit()。newtemp生成了一個暫時變量,emit將一個語法結點的place屬性輸出到屏幕。
(2)gramtree.l是flex詞法分析模塊
(3)gramtree_v1.y是bison語法分析模塊。
在bison文件裏。在相應的變量定義,函數定義,數組定義 ,結構體定義,變量調用,函數調用,數組調用。結構體調用相應的語法規則中,創建或者查詢相應的符號表。實現語義分析和特定錯誤的檢測 而後輸出錯誤類型和錯誤行號。
(4)編譯時使用Makefile文件:
1)編寫Makefile文件內容,運行:vim Makefile
(1)要給每一個語法樹結點添加一個place屬性,這個place屬性的值依據下面規則計算。
1)假設EXP->ID,不需要爲ID創建暫時變量。place的值就等於變量ID的名字。
2)假設EXP->INTEGER|FLOAT,即推出常數,不需要爲常數創建暫時變量。place的值就等於常數值。
3)對於規則E->E1=E2,(E1->ID), E->E1&&E2。E->E1||E2,E->E1+E2。E->E1-E2,E->E1*E2,E->E1/E2:
step1:生成一個暫時變量.
暫時變量的名字符合t加上一個數字的表示形式,E.place的值就等於生成的暫時變量;
step2:輸出E.place->輸出E1.place->輸出操做符->輸出E2.place。
這樣就完畢了一條四元式的生成和輸出。
(2)屬性place的設置
在語法樹的葉子結點存在兩種place,一種是ID。即變量名;還有一種是整數或者浮點數,這兩種place值都和暫時變量無關。不需要創建暫時變量的操做。
place的值相應到四元式中。有下面3種狀況:
1)常數
2)源程序中變量名ID
3)爲生成四元式而創建的暫時變量名。
生成暫時變量的方法
直接將place設置成整數類型。再設置一個標記數組used[],用了一個整數i。就在標記數組中將used[i]=-1,表示ti已經被用過了。這樣一來,建立一個暫時變量,至關於設置place的值,而後更改used[]數組的值。
因而place的數據類型有下面3種可能值。
1)int i(相應INTEGER)
2)char* (相應變量名ID)
3)float (相應FLOAT)
4)int t;相應暫時變量編號
爲了能識別place的值是4種中哪種,再爲語法樹結點增添一個ptag,1爲int,2爲float,3爲char,4爲暫時變量編號。
(1)在語法樹結點中添加下面5個成員:place的4種數據類型。和一個用以標誌類型的整型變量ptag。
struct ast
{
/*用於生成中間代碼的變量,place的4種類型,*/
int i;//Integer
float f;//FLOAT
char id[30];//變量名ID
int t;//暫時變量t編號
int ptag;//用以標誌place的類型1,2,3,4
}
(2)生成暫時變量的函數newtemp()和輸出E.place的函數emit()
/*關於中間代碼的實現函數:建立暫時變量&輸出四元式*/
int newtemp()//建立暫時變量
{
int i=0;
for(i=0; i<100; ++i)//在used[]中找到一個沒有被用過的編號
{
if(used[i]==0)
{
used[i]=i+1;
return i;//返回的編號就是t的編號
}
}
}
void emit(struct ast* tp)//輸出四元式
{
if(tp->ptag==1)//place的值是INTEGER
printf("%d",tp->i);
else if(tp->ptag==2)
printf("%2f",tp->f);//place的值是FLOAT
else if(tp->ptag==3)
printf("%s",tp->id);//place的值是ID變量名字
else//place的值是暫時變量編號
printf("t%d",tp->t);
}
(3)在基本表達式的語義規則中添加:
/*Expressions*/
Exp:Exp ASSIGNOP Exp /*E1->ID,不需要創建暫時變量*/
{
emit($1);//輸出E1.place
printf("=");//輸出‘=’
emit($3);//輸出E2.place
printf("\n");
}
|Exp AND Exp /*邏輯與運算:需要創建暫時變量*/
{
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("&&");//輸出‘&&’
emit($3);//輸出E2.place
printf("\n");
}
|Exp OR Exp /*邏輯或運算:需要創建暫時變量*/
{
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("||");//輸出‘||’
emit($3);//輸出E2.place
printf("\n");
}
|Exp PLUS Exp /*加法運算:需要創建暫時變量*/
{
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("+");//輸出‘+’
emit($3);//輸出E2.place
printf("\n");
}
|Exp MINUS Exp /*減法運算:需要創建暫時變量*/
{
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("-");//輸出‘-’
emit($3);//輸出E2.place
printf("\n");
}
|Exp STAR Exp /*乘法運算:需要創建暫時變量*/
{
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("*");//輸出‘*’
emit($3);//輸出E2.place
printf("\n");
}
|Exp DIV Exp /*除法運算:需要創建暫時變量*/
{
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("/");//輸出‘/’
emit($3);//輸出E2.place
printf("\n");
}
|ID /*E->ID,不需要創建暫時變量*/
{
strcpy($$->id,$1->content);//E.place=ID的名字
$$->ptag=3;//記錄E.place的類型爲3
}
|INTEGER /*E->INTEGER。不需要創建暫時變量*/
{
$$->i=$1->value;//E.place=value
$$->ptag=1;//記錄E.place的類型爲1
}
|FLOAT /*E->FLOAT。不需要創建暫時變量*/
{
$$->f=$1->value;//E.place=value
$$->ptag=2;//記錄E.place的類型爲2
}
/* *Name:gramtree_v1.y *Author:WangLin *Created on:2015-10-03 *Version3.0 *Function:bison語法分析&語義分析&基本表達式的中間代碼生成(四元式) */
%{
#include<unistd.h>
#include<stdio.h>
# include<string.h>
#include "gramtree_v1.h"
%}
%union{
struct ast* a;
double d;
}
/*declare tokens*/
%token <a> INTEGER FLOAT
%token <a> TYPE STRUCT RETURN IF ELSE WHILE ID SPACE SEMI COMMA ASSIGNOP RELOP PLUS
MINUS STAR DIV AND OR DOT NOT LP RP LB RB LC RC AERROR
%token <a> EOL
%type <a> Program ExtDefList ExtDef ExtDecList Specifire StructSpecifire
OptTag Tag VarDec FunDec VarList ParamDec Compst StmtList Stmt DefList Def DecList Dec Exp Args
/*priority*/
%right ASSIGNOP
%left OR
%left AND
%left RELOP
%left PLUS MINUS
%left STAR DIV
%right NOT
%left LP RP LB RB DOT
%%
Program:ExtDefList {$$=newast("Program",1,$1);}
;
ExtDefList:ExtDef ExtDefList {$$=newast("ExtDefList",2,$1,$2);}
| {$$=newast("ExtDefList",0,-1);}
;
ExtDef:Specifire ExtDecList SEMI
{
$$=newast("ExtDef",3,$1,$2,$3);
if(exitvar($2))
printf("Error type 3 at Line %d:Redefined Variable '%s'\n",yylineno,$2->content);
else newvar(2,$1,$2);
}
|Specifire SEMI {$$=newast("ExtDef",2,$1,$2);}
|Specifire FunDec Compst
{
$$=newast("ExtDef",3,$1,$2,$3);
newfunc(4,$1);
}
;
ExtDecList:VarDec {$$=newast("ExtDecList",1,$1);}
|VarDec COMMA ExtDecList {$$=newast("ExtDecList",3,$1,$2,$3);}
;
/*Specifire*/
Specifire:TYPE {$$=newast("Specifire",1,$1);}
|StructSpecifire {$$=newast("Specifire",1,$1);}
;
StructSpecifire:STRUCT OptTag LC DefList RC
{
$$=newast("StructSpecifire",5,$1,$2,$3,$4,$5);
if(exitstruc($2))
printf("Error type 16 at Line %d:Duplicated name '%s'\n",yylineno,$2->content);
else newstruc(1,$2);
}
|STRUCT Tag {
$$=newast("StructSpecifire",2,$1,$2);
if(!exitstruc($2))
printf("Error type 17 at Line %d:undefined structure '%s'\n",yylineno,$2->content);
}
;
OptTag:ID {$$=newast("OptTag",1,$1);}
|{$$=newast("OptTag",0,-1);}
;
Tag:ID {$$=newast("Tag",1,$1);}
;
/*Declarators*/
VarDec:ID {$$=newast("VarDec",1,$1);$$->tag=1;}
| VarDec LB INTEGER RB {$$=newast("VarDec",4,$1,$2,$3,$4);$$->content=$1->content;$$->tag=4;}
;
FunDec:ID LP VarList RP
{$$=newast("FunDec",4,$1,$2,$3,$4);$$->content=$1->content;
if(exitfunc($1))printf("Error type 4 at Line %d:Redefined Function '%s'\n",yylineno,$1->content);
else newfunc(2,$1);}
|ID LP RP
{$$=newast("FunDec",3,$1,$2,$3);$$->content=$1->content;
if(exitfunc($1))printf("Error type 4 at Line %d:Redefined Function '%s'\n",yylineno,$1->content);
else newfunc(2,$1);}
;
VarList:ParamDec COMMA VarList {$$=newast("VarList",3,$1,$2,$3);}
|ParamDec {$$=newast("VarList",1,$1);}
;
ParamDec:Specifire VarDec {$$=newast("ParamDec",2,$1,$2);newvar(2,$1,$2);newfunc(1);}
;
/*Statement*/
Compst:LC DefList StmtList RC {$$=newast("Compst",4,$1,$2,$3,$4);}
;
StmtList:Stmt StmtList{$$=newast("StmtList",2,$1,$2);}
| {$$=newast("StmtList",0,-1);}
;
Stmt:Exp SEMI {$$=newast("Stmt",2,$1,$2);}
|Compst {$$=newast("Stmt",1,$1);}
|RETURN Exp SEMI {$$=newast("Stmt",3,$1,$2,$3);
newfunc(3,$2);}
|IF LP Exp RP Stmt {$$=newast("Stmt",5,$1,$2,$3,$4,$5);}
|IF LP Exp RP Stmt ELSE Stmt {$$=newast("Stmt",7,$1,$2,$3,$4,$5,$6,$7);}
|WHILE LP Exp RP Stmt {$$=newast("Stmt",5,$1,$2,$3,$4,$5);}
;
/*Local Definitions*/
DefList:Def DefList{$$=newast("DefList",2,$1,$2);}
| {$$=newast("DefList",0,-1);}
;
Def:Specifire DecList SEMI {$$=newast("Def",3,$1,$2,$3);
if(exitvar($2)||exitarray($2)) printf("Error type 3 at Line %d:Redefined Variable '%s'\n",yylineno,$2->content);
else if($2->tag==4) newarray(2,$1,$2);
else newvar(2,$1,$2);}
;
DecList:Dec {$$=newast("DecList",1,$1);}
|Dec COMMA DecList {$$=newast("DecList",3,$1,$2,$3);$$->tag=$3->tag;}
;
Dec:VarDec {$$=newast("Dec",1,$1);}
|VarDec ASSIGNOP Exp {$$=newast("Dec",3,$1,$2,$3);$$->content=$1->content;}
;
/*Expressions*/
Exp:Exp ASSIGNOP Exp/*E1->ID,不需要創建暫時變量*/
{$$=newast("Exp",3,$1,$2,$3);
if($1->type!=NULL&&$3->type!=NULL&&strcmp($1->type,$3->type)){printf("Error type 5 at Line %d:Type mismatched for assignment.\n ",yylineno);}
if($1->tag==3)printf("Error type 6 at Line %d:the left-hand side of an assignment must be a variable.\n ",yylineno);
emit($1);//輸出E1.place
printf("=");//輸出‘=’
emit($3);//輸出E2.place
printf("\n");
}
|Exp AND Exp /*與運算:需要創建暫時變量*/
{$$=newast("Exp",3,$1,$2,$3);
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("&&");//輸出‘&&’
emit($3);//輸出E2.place
printf("\n");
}
|Exp OR Exp/*或運算:需要創建暫時變量*/
{$$=newast("Exp",3,$1,$2,$3);
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("||");//輸出‘||’
emit($3);//輸出E2.place
printf("\n");
}
|Exp RELOP Exp{$$=newast("Exp",3,$1,$2,$3);}
|Exp PLUS Exp/*加法運算:需要創建暫時變量*/
{$$=newast("Exp",3,$1,$2,$3);
if($1->type!=NULL&&$3->type!=NULL&&strcmp($1->type,$3->type)){printf("Error type 7 at Line %d:Type mismatched for operand.\n ",yylineno);}
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("+");//輸出‘+’
emit($3);//輸出E2.place
printf("\n");
}
|Exp MINUS Exp/*減法運算:需要創建暫時變量*/
{$$=newast("Exp",3,$1,$2,$3);
if($1->type!=NULL&&$3->type!=NULL&&strcmp($1->type,$3->type)){printf("Error type 7 at Line %d:Type mismatched for operand.\n ",yylineno);}
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("-");//輸出‘-’
emit($3);//輸出E2.place
printf("\n");
}
|Exp STAR Exp/*乘法運算:需要創建暫時變量*/
{$$=newast("Exp",3,$1,$2,$3);
if($1->type!=NULL&&$3->type!=NULL&&strcmp($1->type,$3->type)){printf("Error type 7 at Line %d:Type mismatched for operand.\n ",yylineno);}
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("*");//輸出‘*’
emit($3);//輸出E2.place
printf("\n");
}
|Exp DIV Exp/*除法運算:需要創建暫時變量*/
{$$=newast("Exp",3,$1,$2,$3);
if($1->type!=NULL&&$3->type!=NULL&&strcmp($1->type,$3->type)){printf("Error type 7 at Line %d:Type mismatched for operand.\n ",yylineno);}
$$->t=newtemp();//E.place等於新建立的暫時變量
emit($$);//輸出E.place
printf("=");//輸出‘=’
emit($1);//輸出E1.place
printf("/");//輸出‘/’
emit($3);//輸出E2.place
printf("\n");
}
|LP Exp RP{$$=newast("Exp",3,$1,$2,$3);}
|MINUS Exp {$$=newast("Exp",2,$1,$2);}
|NOT Exp {$$=newast("Exp",2,$1,$2);}
|ID LP Args RP {$$=newast("Exp",4,$1,$2,$3,$4);
if((!exitfunc($1))&&(exitvar($1)||exitarray($1)))printf("Error type 11 at Line %d:'%s'is not a function.\n ",yylineno,$1->content);
else if(!exitfunc($1)){printf("Error type 2 at Line %d:undefined Function %s\n ",yylineno,$1->content);}
else if(pnumfunc($1)!=rpnum)printf("Error type 9 at Line %d:parameters num mismatched for function: %s\n ",yylineno,$1->content);}
|ID LP RP {$$=newast("Exp",3,$1,$2,$3);}
|Exp LB Exp RB
{$$=newast("Exp",4,$1,$2,$3,$4);
if(strcmp($3->type,"int"))printf("Error type 12 at Line %d:%.1f is not a integer.\n",yylineno,$3->value);
if((!exitarray($1))&&(exitvar($1)||exitfunc($1)))printf("Error type 10 at Line %d:'%s'is not an array.\n ",yylineno,$1->content);
else if(!exitarray($1)){printf("Error type 2 at Line %d:undefined Array %s\n ",yylineno,$1->content);}}
|Exp DOT ID
{$$=newast("Exp",3,$1,$2,$3);if(!exitstruc($1))printf("Error type 13 at Line %d:Illegal use of '.'.\n",yylineno);}
|ID /*E->ID,不需要創建暫時變量*/
{$$=newast("Exp",1,$1);
if(!exitvar($1)&&!exitarray($1))
{printf("Error type 1 at Line %d:undefined variable %s\n ",yylineno,$1->content);}
else $$->type=typevar($1);
strcpy($$->id,$1->content);//E.place=ID的名字
$$->ptag=3;//記錄E.place的類型爲3
}
|INTEGER /*E->INTEGER。不需要創建暫時變量*/
{$$=newast("Exp",1,$1);$$->tag=3;$$->type="int";
$$->i=$1->value;//E.place=value
$$->ptag=1;//記錄E.place的類型爲1
}
|FLOAT/*E->FLOAT,不需要創建暫時變量*/
{$$=newast("Exp",1,$1);$$->tag=3;$$->type="float";$$->value=$1->value;
$$->f=$1->value;//E.place=value
$$->ptag=2;//記錄E.place的類型爲2
}
;
Args:Exp COMMA Args {$$=newast("Args",3,$1,$2,$3);rpnum+=1;}
|Exp {$$=newast("Args",1,$1);rpnum+=1;}
;
%%
1.輸入內容: test1.c的內容例如如下:
[root@localhost IR]# cat test1.c
int main()
{
float x;
float y;
float z;
x=1.5;
y=1.6;
z=x+y;
z=x-y;
z=x*y;
z=x/y;
z=x&&y;
z=x||y;
z=x+y-1.0-2.0/y;
z=x*2.5+x*y-x/2.0;
z=x||y+x&&y;
}
2.輸出內容:凝視和空行都是爲了直觀加上的,不是輸出的一部分。
[root@localhost IR]# cat test1.c|./a.out
x=1.500000 /*相應x=1.5;*/
y=1.600000 /*相應y=1.6;*/
t0=x+y /*相應z=x+y;*/
z=t0
t1=x-y /*相應z=x-y;*/
z=t1
t2=x*y /*相應z=x*y;*/
z=t2
t3=x/y /*相應z=x/y;*/
z=t3
t4=x&&y /*相應z=x&&y;*/
z=t4
t5=x||y /*相應z=x||y;*/
z=t5
t6=x+y /*相應z=x+y-1.0-2.0/y;*/
t7=t6-1.000000
t8=2.000000/y
t9=t7-t8
z=t9
t10=x*2.500000 /*相應z=x*2.5+x*y-x/2.0;*/
t11=x*y
t12=t10+t11
t13=x/2.000000
t14=t12-t13
z=t14
t15=y+x /*相應z=x||y+x&&y;*/
t16=t15&&y
t17=x||t16
z=t17
3.實驗結果分析:
1)從輸出結果可以看出,程序正確處理了E->ID,E->常數,E->E1操做符E2的各類狀況。E->ID時。輸出的E.place就是ID的名字。E->常數時輸出的E.place就是常數的值,如表達式x=1.5和y=1.6。E->E1操做符E2時。E.place是暫時變量名。
2)正確處理表達式中的優先級。
如 z=x*2.5+x*y-x/2.0;由於乘法和除法的優先級高於加法和減法。所以先對乘法和除法進行計算。最後算加和減。
對於表達式z=x||y+x&&y;由於加減的優先級高於邏輯與和邏輯或。所以程序先計算加和減。再計算邏輯與和邏輯或。
3)正確處理了暫時變量的編號。
1.place的設置—Union的捨棄
由於place的數據類型可能有4種,但這4種並不是同一時候出現的。一次僅僅是一種類型,這和Union(共同體)的思想剛好一致。所以一開始想把place應該是一個Union。
union
{
int i;//Integer
float f;//FLOAT
char id[30];//變量名ID
int t;//暫時變量t編號
}place;
但在實踐的過程當中,union致使了內存的錯亂(詳細什麼緣由。事後還需要研究),所以僅僅能將union捨棄掉,4種類型都直接設置爲語法樹結點的成員,這樣一來可能浪費了空間。但是能保證代碼的正確性。
2.暫時變量編號數組used[]的使用 used[]的使用是一個比較巧妙的設計,既不佔用空間,操做也很是easy,但是這僅僅是針對於本次實驗僅僅對基本表達式進行翻譯的設計,假設提高實驗難度,要求對語句等進行翻譯。這樣的設計多半是行不通的,需要再尋求一種更強大更健壯的設計。