博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
编译原理——中间代码生成
阅读量:6152 次
发布时间:2019-06-21

本文共 15917 字,大约阅读时间需要 53 分钟。

预备知识

源语言->中间代码->目标语言

中间代码(Intermediate Representation或者IR):复杂性介于源程序语言和机器语言的一种表示形式。

编译程序锁使用的中间代码有多种形式。常见的有逆波兰记号,三元式。四元式。和树形表示。四元式是一种普遍採用的中间代码形式,非常相似于三地址指令,有时把这类中间表示称为“三地址代码”,这样的表示能够看作是一种虚拟三地址机的通用汇编码,每条”指令“包括操作符和三个地址,两个是为运算对象的,一个是为结果的。
基本表达式的翻译模式:
(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->ID

emit($1);printf("=");emit($3);

step1:输出ID;

step2:输出=
step3:输出E2.place

4)i+1;E->E1+E2。newtemp,建立一个暂时变量,E.place=E1.place+E2.place,

$$>t=newtemp();//创建暂时变量emit($$);//输出创建E.placeprintf("=");//输出=emit($1);//输出E1.placeprintf("+");//输出+emit($3);//输出E2.place

也就是说,在语法树的叶子结点存在两种place,一种是ID,即变量名,一种是整数或者浮点数。这两种place值都和暂时变量无关,不须要建立暂时变量的操作。

place的值相应到四元式中:
1)常数
2)源程序中变量名ID
3)为生成四元式而建立的暂时变量名。

方法一:变量名採用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为暂时变量编号。

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。

代码更改:

因为用union导致了内存的错乱(详细什么原因,过后还须要研究),因此将union去掉,4种类型都设置为语法树结点的成员。这样一来可能浪费了空间,可是能保证代码的正确性。

一、【实验目的】

通过在词法分析。语法分析和语义分析程序的基础上,将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,程序的编译说明

(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

2,实验分析

(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为暂时变量编号。

3,实验代码

(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
#include
# include
#include "gramtree_v1.h"%}%union{struct ast* a;double d;}/*declare tokens*/%token
INTEGER FLOAT%token
TYPE STRUCT RETURN IF ELSE WHILE ID SPACE SEMI COMMA ASSIGNOP RELOP PLUSMINUS STAR DIV AND OR DOT NOT LP RP LB RB LC RC AERROR%token
EOL%type
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.cint 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=t0t1=x-y          /*相应z=x-y;*/    z=t1t2=x*y          /*相应z=x*y;*/    z=t2t3=x/y          /*相应z=x/y;*/        z=t3t4=x&&y     /*相应z=x&&y;*/   z=t4t5=x||y         /*相应z=x||y;*/   z=t5t6=x+y          /*相应z=x+y-1.0-2.0/y;*/  t7=t6-1.000000t8=2.000000/yt9=t7-t8z=t9t10=x*2.500000      /*相应z=x*2.5+x*y-x/2.0;*/    t11=x*yt12=t10+t11t13=x/2.000000t14=t12-t13z=t14t15=y+x             /*相应z=x||y+x&&y;*/  t16=t15&&yt17=x||t16z=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,可是这仅仅是针对于本次实验仅仅对基本表达式进行翻译的设计,假设提升实验难度,要求对语句等进行翻译。这样的设计多半是行不通的,须要再寻求一种更强大更健壮的设计。

转载地址:http://quwfa.baihongyu.com/

你可能感兴趣的文章
淘宝的几个架构图
查看>>
Android扩展 - 拍照篇(Camera)
查看>>
数据加密插件
查看>>
linux后台运行程序
查看>>
win7 vs2012/2013 编译boost 1.55
查看>>
Tar打包、压缩与解压缩到指定目录的方法
查看>>
配置spring上下文
查看>>
Python异步IO --- 轻松管理10k+并发连接
查看>>
Oracle中drop user和drop user cascade的区别
查看>>
登记申请汇总
查看>>
Android Jni调用浅述
查看>>
CodeCombat森林关卡Python代码
查看>>
第一个应用程序HelloWorld
查看>>
(二)Spring Boot 起步入门(翻译自Spring Boot官方教程文档)1.5.9.RELEASE
查看>>
Java并发编程73道面试题及答案
查看>>
企业级负载平衡简介(转)
查看>>
ICCV2017 论文浏览记录
查看>>
科技巨头的交通争夺战
查看>>
Shell基础之-正则表达式
查看>>
JavaScript异步之Generator、async、await
查看>>