编译原理课程设计报告1

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

课程设计报告
设计题目:一个简单文法的编译器的设计与实现
班级:计算机1206班
组长学号:2012XXX
组长姓名:XXX
指导教师:XXX
设计时间:2014年12月
设计分工
组长学号及姓名:2012XXX XXX
分工:1)读取源文件进行词法分析
2)进行LL(1)分析生成分析表
3)设计顶层自动机将源程序分段
4)生成可执行的汇编程序
组员1学号及姓名:2012XXX XXX
分工:1)设计第二层自动机处理程序片段
2)生成中间语言四元式
3)源程序错误处理
组员2学号及姓名:2012XXX XXX
分工:1)设计第三层自动机处理复合表达式
2)设计带动作的LL(1) 文法
3)源程序错误处理
摘要
编译原理课程具有很强的理论性和实践性,是计算机专业的一门非常重要的专业基础课程,在系统软件中也是占有十分重要的地位。

本次课程设计我们是在Visual C++
的平台上应用了词法分析、语法分析、语义分析、中间语言生成以及目标语言生成的知识设计了一个简单的编译器前端。

其中设计了一个简单的有限自动机来扫描源程序即进行语法分析,并生成了关键字表、标志符表、界符表、常数表和Token串;设计了一个LL(1)文法和一个带动作的文法来实现语法分析,并生成了Select集和LL(1)分析表;采用了四元式序列的设计来生成中间语言;通过汇编语言设计来生成目标语言。

最后为了使该编译器更加完善,我们设计了简单的的错误检查机制,能够对源程序进行比较全面的错误检查同时也能够指出错误出现的大致位置,增强了该编译器的健壮性。

关键字:编译器,前端,有限自动机,LL(1)文法,汇编语言,错误处理
目录
摘要 (3)
1、概述 (5)
2、课程设计任务及要求 (5)
2.1设计任务 (5)
2.2设计要求 (6)
3、算法与数据结构 (6)
3.1词法分析器的算法 (6)
3.2 语法分析器的算法 (12)
3.2.1 LL(1)文法设计算法 (12)
3.2.2递归下降子程序设计算法 (19)
3.3中间语言生成器算法 (20)
3.4处理复合表达式算法 (24)
3.5目标语言生成器算法 (30)
3.6数据结构 (39)
4、程序设计与实现 (39)
4.1编译程序设计与实现 (39)
4.2程序实验结果 (39)
4.2.1待测源程序 (39)
4.2.2词法分析结果 (40)
4.2.3语法分析结果 (41)
4.2.4中间语言生成结果 (42)
4.2.5目标语言生成结果 (43)
4.2.6程序错误处理结果 (44)
5、参考文献 (44)
1、概述
本次课程设计的编译程序主要包括了词法分析器、语法分析器、中间代码生成器和目标代码生成器四部分,编译程序的输出结果包括了词法分析后的关键字表、界符表、标识符表和Token串,语法分析后的Select集和LL(1)分析表;中间代码生成器产生的四元式序列。

最后除了完成设计所要求的内容之外,我们还做了一些扩展例如:设计了目标代码生成器来生成可执行的汇编程序;还设计了错误检查机制来查找源程序的错误并指出错误产生的大致位置。

词法分析是编译程序的第一步操作,它的任务是:从左至右扫描源程序的字符串,按照一定的词法规则识别出一个个正确的字符,并转换成该字符相对应的Token码,最终生成一个完整的Token串以供语法分析使用。

由此可知,词法分析是整个编译程序的基础,而执行词法分析的一系列操作的就是词法分析器。

语法分析是编译程序的第二步操作也是编译程序的核心部分,其主要任务是:分
析语法内容,确定语法结构同时生成Select集和LL(1)分析表。

中间代码和目标代码的生成是对源程序的进一步操作,其任务是:根据词法分析产生的Token串和语法分析确定的语法结构来生成中间语言——四元式和目标语言——汇编语言程序。

2、课程设计任务及要求
2.1设计任务
一个简单文法的编译器前端的设计与实现
●定义一个简单程序设计语言文法(包括变量说明语句、算术运算表达式、赋值语句;
扩展包括逻辑运算表达式、If语句、While语句等);
●扫描器设计实现;
●语法分析器设计实现;
●中间代码设计;
●中间代码生成器设计实现。

●目标代码生成器设计实现
2.2设计要求
●给出一个源程序文件,作为编译器前端的输入
●输出相关编译阶段的运行结果
●词法分析阶段:
●生成Token序列;
●生成关键字表、界符表、符号表系统。

●中间代码生成阶段:
●生成四元式序列;
●生成符号表系统。

3、算法与数据结构
3.1词法分析器的算法
1)一个简单有限自动机(扫描器)的设计:
2)一个简单词法分析器设计:
算法实现如下:
Void main(){ //词法分析部分代码char p[10];
string TOKEN;
string Source;
string temp;
FILE* fp;
fp=fopen("D:\\MySourceFile.txt","r");
if(!fp) Source="Cannot open file";
else
{
int i;
char c;
while(!feof(fp))
{
c=fgetc(fp);
Source+=c;
}
fclose(fp);
for(i=0;i<Source.size();i++)
{
if(Source[i]==13||Source[i]==9||Source[i]==10||Source[i]==-1)
{
Source.replace(i,1," ");
}
}
}
Source+='#';
cout<<"处理后源程序\n"<<Source<<endl<<endl;
initKTPT();
int i,j;
for(i=0;i<Source.size();i++)
{
switch(kindofchar(Source[i]))
{
case 'e':
{
cout<<"\n非法字符!,位置:"<<i<<"错误代码"<<Source[i]<<endl<<endl;
for(int k=0;k<=i;k++) cout<<Source[k];
exit(0);
}
case 's':break;
case 'd':
{
temp+=Source[i];
for(j=1;Source[i+j]=='.'||kindofchar(Source[i+j])=='d';j++)
temp+=Source[i+j];
i=i+j-1;
if(inCT(temp)==-1)
{
temp="N "+temp;
CT.push_back(temp);
}
TOKEN+="<CT,";
itoa(inCT(temp),p,10);
TOKEN+=p;
TOKEN+=">";
temp="";
break;
}
case 'w':
{
temp+=Source[i];
for(j=1;kindofchar(Source[i+j])=='w'||kindofchar(Source[i+j])=='d'||Source[i+j]== '_';j++) temp+=Source[i+j];
i=i+j-1;
if(inKT(temp)!=-1)
{
TOKEN+="<KT,";
itoa(inKT(temp),p,10);
TOKEN+=p;
TOKEN+=">";
temp="";
break;
}
if(inIT(temp)==-1) IT.push_back(temp);
TOKEN+="<IT,";
itoa(inIT(temp),p,10);
TOKEN+=p;
TOKEN+=">";
temp="";
break;
}
case 'f':
{
temp+=Source[i];
if(kindofchar(Source[i+1])=='f'&&inPT(temp+Source[i+1])>=0)
{
temp+=Source[i+1];
i++;
}
TOKEN+="<PT,";
itoa(inPT(temp),p,10);
TOKEN+=p;
TOKEN+=">";
temp="";
break;
}
case '\"':
{
i++;
for(j=0;Source[i+j]!='\"'&&(i+j)<(Source.size()-1);j++)
{
if(Source[i+j]=='\\'&&Source[i+j+1]=='\"')
{
temp+='\"';
j++;
}
if(Source[i+j]=='\\'&&Source[i+j+1]=='\'')
{
temp+='\'';
j++;
}
if(Source[i+j]=='\\'&&Source[i+j+1]=='\\')
{
temp+='\\';
j++;
}
if(Source[i+j]=='\\'&&Source[i+j+1]=='\0')
{
temp+='\0';
j++;
}
else temp+=Source[i+j];
}
if((i+j)>=(Source.size()-1))
{
cout<<"未找到可匹配的双引号,位置:"<<i<<endl;
for(int k=0;k<=i;k++) cout<<Source[k];
exit(0);
}
i=i+j;
if(inCT(temp)==-1)
{
temp="S "+temp;
CT.push_back(temp);
}
TOKEN+="<CT,";
itoa(inCT(temp),p,10);
TOKEN+=p;
TOKEN+=">";
temp="";
break;
}
case '\'':
{
if((i+3)<(Source.size()-1)&&Source[i+1]=='\\'&&Source[i+3]=='\'')
{
switch(Source[i+2])
{
case '\\':temp+='\\';break;
case '\'':temp+='\'';break;
case '\"':temp+='\"';break;
case '0':temp+="\\0";break;
default:cout<<"错误的单引号使用(转义错误),位置:"<<i<<endl;for(int k=0;k<=i;k++) cout<<Source[k];exit(0);
}
i+=3;
}
else
{
if((i+2)>=(Source.size()-1))
{
cout<<"错误的单引号使用(越界),位置:"<<i<<endl;
for(int k=0;k<=i;k++) cout<<Source[k];
exit(0);
}
temp+=Source[i+1];
i+=2;
}
if(inCT(temp)==-1)
{
temp="C "+temp;
CT.push_back(temp);
}
TOKEN+="<CT,";
itoa(inCT(temp),p,10);
TOKEN+=p;
TOKEN+=">";
temp="";
break;
}
case '#':break;
default:break;
}
}
3.2语法分析器的算法
首先介绍一下整个课程设计中我们使用到的一些文法。

C--文件-> void main ( ) C<--程序体
C -> { Y<--语句--> }
Y -> S<--声明语句--> ; I<--语句后继-->| Z<--赋值语句--> ; I| V<--条件语句-->N<--if后继-->{B} I| W<--循环语句--> I
I->Y | 空
S ->类型 标识符 声明后继 类型 -> int|float|char
声明后继 -> ,标识符 声明后继 | 空 Z -> 标识符 = 表达式 V -> if ( E )C N->else C | 空
W -> while ( 表达式 )程序体 E -> 详见rull.txt 源文件。

语法分析主要是对LL(1)文法和递归下降子程序的设计,其算法设计如下: 3.2.1 LL(1)文法的设计 1)算法原理如下:
● 利用一个分析表,登记如何选择产生式的知识; ● 利用一个分析栈,记录分析过程;
● 此分析法要求文法必须满足 LL(1)文法形式。

2)算法设计如下: (1)
(2)
(3)
算法实现如下: void maketable()//////////////////////////////////////////需要参数指明所需文法 { //打开文件
//switch()///////////////////////////////////////根据参数选择文法 FILE* fp=fopen("D:/rull.txt","r"); if(fp==NULL) {
cout<<"打开文件失败"<<endl; getchar(); exit(0); }
重复执行 ①、②、③ ,直到栈中只剩 # 为止:
① 若 栈顶符=A 且 当前符 w=a 且 有产生式: A a , 则 POP,PUSH(a )R ;
② 若 栈顶符=a 且 当前符为a ; 则 pop,NEXT(w); ③ 否则,错误处理! ;当前符 w= # 结束: 栈 # # Z 开始: 栈 ; NEXT(w)
//读取文件
string source="";
char readchar;
do
{
readchar=fgetc(fp);
source+=readchar;
}
while(readchar!=EOF);
fclose(fp);
//cout<<"----source流----"<<endl<<source<<endl;//检查//从source流中提取有效数据
Vs=source[3];
Vn+=Vs;
int i,j,k,l;
string ps="";
for(i=8;source[i]!=';';i++) Vn+=source[i];
i+=4;
for(;source[i]!=';';i++) Vt+=source[i];
i++;
while(source[i]!=';')
{
for(;source[i]!=' '&&source[i]!=';';i++)
{
ps+=source[i];
}
QRULL.push_back(ps);
ps="";
if(source[i]==' ') i++;
}
//拆分或符号
string ps2="";
int flag;
for(i=0;i<QRULL.size();i++)
{
flag=0;
for(j=0;j<QRULL[i].length();j++)
{
if(QRULL[i][j]=='|')
{
flag=1;
break;
}
}
if(flag==0) continue;
ps2+=QRULL[i][0];
ps2+="->";
for(j=0;QRULL[i][j]!='|';j++) ps+=QRULL[i][j];
for(j++;j<QRULL[i].length();j++) ps2+=QRULL[i][j];
QRULL[i]=ps;
QRULL.push_back(ps2);
ps="";
ps2="";
}
cout<<"----有效四元产生式表----"<<endl;//检查
for(i=0;i<QRULL.size();i++)//检查
{
cout<<QRULL[i]<<' ';//检查
}
cout<<endl;//检查
//从四元产生式转化为普通产生式
ps="";
for(i=0;i<QRULL.size();i++)
{
k=0;ps="";
for(j=0;j<QRULL[i].size();j++)
{
if(QRULL[i][j]!='{') ps+=QRULL[i][j];
else j+=2;
}
RULL.push_back(ps);
}
cout<<"----有效普通产生式表----"<<endl;//检查
for(i=0;i<RULL.size();i++)//检查
{
cout<<RULL[i]<<' ';//检查
}
cout<<endl;//检查
//检测直接左递归
flag=0;
for(i=0;i<RULL.size();i++)
{
if(RULL[i][0]==RULL[i][3]) flag=1;
}
if(flag==1)
{
system("cls");
system("color CF");
cout<<"检测到直接左递归文法,系统已停止运行,请改正产生式。

"<<endl;
getchar();
exit(0);
}
//产生SELECT表
Vt+='#';
MAXITERATE=RULL.size()*RULL.size();
vector<string> SELECT;
SELECT=Select();
cout<<"----SELECT集----"<<endl<<"SELECT"<<endl;//检查
for(i=0;i<SELECT.size();i++)//检查
{
cout<<SELECT[i]<<endl;//检查
}
SelectTable=new int*[Vn.size()];
int* intp;
for(i=0;i<Vn.size();i++)
{
intp=new int[Vt.size()];
SelectTable[i]=intp;
}
for(i=0;i<Vn.size();i++)
{
for(j=0;j<Vt.size();j++) SelectTable[i][j]=-1;
}
for(k=0;k<SELECT.size();k++)
{
for(l=2;l<SELECT[k].length();l++)
{
i=inVn(SELECT[k][0]);
j=inVt(SELECT[k][l]);
SelectTable[i][j]=k;
}
}
cout<<"----SelectTable----"<<endl<<" ";//检测
for(i=0;i<Vt.size();i++) cout<<Vt[i]<<' ';//检测
cout<<endl;//检测
for(i=0;i<Vn.size();i++)//检测
{
cout<<Vn[i]<<' ';//检测
for(j=0;j<Vt.size();j++) cout<<SelectTable[i][j]<<' ';//检测cout<<endl;//检测
}
//进行选择集相交检测
if(check()==0)
{
system("cls");
system("color CF");
cout<<"选择集相交,该文法不是LL1文法,请修改产生式"<<endl;
getchar();
exit(0);
}
}
vector<string> Select()
{
int i;
vector<string> SELECT;
string ps="";
for(i=0;i<RULL.size();i++)
{
ps=RULL[i][0];
ps+=" ";
ps+=first(RULL[i]);
SELECT.push_back(ps);
//迭代器清零
counter=0;
}
return SELECT;
}
string first(string rull)
{//cout<<"迭代次数"<<counter<<endl;//检测
counter++;
if(counter>MAXITERATE)
{
system("cls");
system("color CF");
cout<<"生成选择集时迭代次数过高,疑似出现递归死循环,系统已停止运行,请检查是否有语法错误"<<endl;
cout<<"迭代次数上限暂设为产生式数量的平方。

过多的迭代会损害设备,若没有语法错误,请简化语法树"<<endl;
getchar();
exit(0);
}
int i,j;
string pp;
string res="";
if(inVt(rull[3])>=0) res=rull[3];
else if(inVn(rull[3])>=0)
{
for(i=0;i<RULL.size();i++)
{
pp=rull;
if(RULL[i][0]==pp[3])
{
pp=pp[0];
pp+="->";
for(j=3;j<RULL[i].size();j++) pp+=RULL[i][j];
for(j=4;j<rull.size();j++) pp+=rull[j];
res+=first(pp);
}
}
}
else if(rull[3]=='0') res+=follow(rull);
else
{
system("cls");
system("color CF");
cout<<"产生式关键位置检测到非法字符,系统已停止运行。

"<<endl;
getchar();
exit(0);
}
return res;
}
string follow(string rull)
{//cout<<"迭代次数"<<counter<<endl;//检测
counter++;
if(counter>MAXITERATE)
{
system("cls");
system("color CF");
cout<<"生成选择集时迭代次数过高,疑似出现递归死循环,系统已终止运行,请检查是否有语法错误"<<endl;
cout<<"迭代次数上限暂设为产生式数量的平方。

过多的迭代会损害设备,若没有语法错误,请简化语法树"<<endl;
getchar();
exit(0);
}
vector<string> p;
string res;
string pp="";
string t="";
int i,site,j;
if(rull[0]==Vs) res+='#';
for(i=0;i<RULL.size();i++)
{
pp="";
for(j=3;j<RULL[i].length();j++) pp+=RULL[i][j];
pp+='0';
site=pp.find(rull[0],0);
while(site<pp.size())
{
t+="->";
pp=t;
site++;
}
}
return res;
}
3.2.2递归下降子程序的设计
●设计原理如下:
对每一个非终结符,构造一个子程序,用以识别该非终结符所定义的符号串。

每个子程序以产生式左部非终结符命名,以产生式右部构造子程序内容。

●构造算法如下:
⑴扩展文法:
增设一个产生式,作为主程序:Z`->Z ,
⑵入出口约定:
子程序入口时,其首符号已经读来!
子程序出口时,其后继符应该读来!
⑶子程序内容设计:
遇终结符,判定之,确认后读下一单词;
遇非终结符,调用之,返回后不读下一单词;
遇空串(e) ,直接出口;
●程序流程图如下:
3.3中间语言生成器算法
中间语言生成主要是对四元式序列的设计,其算法设计如下:
1)赋值语句的四元式设计
设有赋值语句:v = E ,则有v = E =>quat(E),q(:= res(E) _ v ) 算法实现如下:
void Z(int end){ //赋值语句四元式生成
int i;string str;
if(VTOKEN[tokenp+3].compare("<PT,21>")!=0)
{
tokenp+=2;
LL1(end-1);
str=VTOKEN[tokenp+1];
str+=SEM.top();
SEM.pop();
str+="<0,0>";
str+=VTOKEN[tokenp];
QT.push_back(str);
}
else
{
str=VTOKEN[tokenp+1];
str+=VTOKEN[tokenp+2];
str+="<0,0>";
str+=VTOKEN[tokenp];
QT.push_back(str);
}
cout<<"验证赋值语句并产生四元式"<<endl;
}
2)条件语句的四元式设计
文法:S -> if(E)S1 [ else S2 ]
语义结构:四元式结构:
else {cout<<"源代码错误-ERRO:02/if 当前TOKEN:"<<tokenp<<endl; getchar();exit(0); } do
{
if(VTOKEN[p].compare("<PT,0>")==0)f+=1;
else if(VTOKEN[p].compare("<PT,1>")==0)f-=1;
p++;
}while(f!=0);
if((p-1-tokenp)==1)
{cout<<"源代码错误-ERRO:02/if括号当前TOKEN:"<<tokenp<<endl; getchar();exit(0); }
if((p-1-tokenp)==2){
string tt;
tt=VTOKEN[tokenp+1];
str="<KT,3>";
str+=tt;
str+="<0,0>";
str+="<0,0>";
QT.push_back(str);
tokenp+=3;
}
else{
tokenp++;
LL1(p-2);
tokenp=p;
str="<KT,3>";
str+=SEM.top();
str+="<0,0>";
str+="<0,0>";
str+="<0,0>";
QT.push_back(str);
tokenp++;
C(end);
cout<<"验证else语句并产生四元式"<<endl;
}
3)循环语句的四元式设计
文法:S -> while(E)S
语义结构:四元式结构:
算法实现如下:
void W(int end){ //循环语句四元式生成
string str;
int p,f=0;
str="<KT,7>";
str+="<0,0>";
str+="<0,0>";
str+="<0,0>";
QT.push_back(str);
tokenp++;
p=tokenp;
do
{if(VTOKEN[p].compare("<PT,0>")==0)f+=1;
else if(VTOKEN[p].compare("<PT,1>")==0)f-=1;
p++;
}while(f!=0);
if((p-1-tokenp)==1)
{cout<<"源代码错误-ERRO:02/while括号当前TOKEN:"<<tokenp<<endl; getchar();exit(0); }
if((p-1-tokenp)==2){
string tt;
tt=VTOKEN[tokenp+1];
str="<KT,8>";
str+=tt;
str+="<0,0>";
str+="<0,0>";
QT.push_back(str);
tokenp+=3;
}
else{
tokenp++;LL1(p-2);
str="<KT,8>";
str+=SEM.top();
SEM.pop();
str+="<0,0>";
str+="<0,0>";
QT.push_back(str);
}
tokenp=p;
C(end);
str="<KT,10>";
str+="<0,0>";
str+="<0,0>";
str+="<0,0>";
QT.push_back(str);
cout<<"验证了循环语句并产生四元式"<<endl;
}
3.4处理复合表达式的算法
1)表达式四元式设计
Vn XTYFMNQSAB;
Vt jcibpk();
E->TX
X->jT{G}X|0
T->FY
Y->cF{G}Y|0
F->MN
N->bM{G}N|0
M->SQ
Q->pS{G}Q|0
S->AB
B->kA{G}B|0
A->i{P}|(E);
四元式结构:q:(ω o1 o2 t )/*算符,对象1,对象2,结果*/ 算法实现如下:
void GEQ(string a)///////运算符a,计数器qtp
{
char p[10];
ele num;
="t";
num.val="0";
int i=0;
string str;
string left;//左操作数
string right;//右操作数
string t;
if(pare("<PT,5>")==0||pare("<PT,22>")==0)
{
SEM.push("<0,0>");
}
right=SEM.top();
SEM.pop();
left=SEM.top();
SEM.pop();
if(left[1]=='C')
{
str=translate(left);
for(i=0;i<sizeof(str);i++)
{
if(str[i]=='.')
{
ITf.push_back(num);
t+="<ITf,";
itoa(ITf.size()-1,p,10);
t+=p;
t+=">";
break;
}
else continue;
}
ITi.push_back(num);
t+="<ITi,";
itoa(ITi.size()-1,p,10);
t+=p;
t+=">";
}
else
{
int flag=0;
str=translate(left);
for(i=0;i<ITi.size();i++)
{
if(pare(ITi[i].name)==0)
{
flag=1;
break;
}
else continue;
}
for(i=0;i<ITf.size()&&flag==0;i++)
{
if(pare(ITf[i].name)==0)
{
flag=2;
break;
}
else continue;
}
for(i=0;i<ITc.size()&&flag==0;i++)
{
if(pare(ITc[i].name)==0)
{
break;
}
else continue;
}
switch(flag)
{
case 0:{cout<<"使用了未声明的变量-ERRO:02 当前TOKEN:"<<tokenp<<endl;exit(0);}/////////////////////////////////////////未声明的变量case
1:{ITi.push_back(num);t+="<ITi,";itoa(ITi.size()-1,p,10);t+=p;t+=">";break;}
case
2:{ITf.push_back(num);t+="<ITf,";itoa(ITf.size()-1,p,10);t+=p;t+=">";break;}
case
3:{ITc.push_back(num);t+="<ITc,";itoa(ITc.size()-1,p,10);t+=p;t+=">";break;} }
}
if(right[1]=='I'&&right[3]==','){
int flag=0;
str=translate(right);
for(i=0;i<ITi.size();i++)
{
if(pare(ITi[i].name)==0)
{
flag=1;
break;
}
else continue;
}
for(i=0;i<ITf.size()&&flag==0;i++)
{
if(pare(ITf[i].name)==0)
{
flag=2;
break;
}
else continue;
}
for(i=0;i<ITc.size()&&flag==0;i++)
{
if(pare(ITc[i].name)==0)
{
flag=3;
break;
}
else continue;
if(flag==0){cout<<"使用了未声明的变量-ERRO:02 当前TOKEN:"<<tokenp<<endl;exit(0);}
}
a+=left;
a+=right;
a+=t;
QT.push_back(a);
SEM.push(t);
}
2)带语义动作的LL (1)自动机
E 入栈
err
算法实现如下:
(1)将token 翻译成非终结符
if(tokenp==end+1)w='#';
else
{
str=VTOKEN[tokenp];/////////////////////////需要查表,但是还没做啊哈哈哈 if(str[1]=='C'||str[1]=='I'){
w='i'; ///////////////////////////我有特别的赋值技巧
}
else{
if(pare("<PT,17>")==0){w='j';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,18>")==0){w='j';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,14>")==0){w='c';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,11>")==0){w='c';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,12>")==0){w='c';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
else
if(pare("<PT,15>")==0){w='c';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,16>")==0){w='c';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,6>")==0){w='b';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,7>")==0){w='b';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,8>")==0){w='p';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,9>")==0){w='p';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,10>")==0){w='p';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,5>")==0){w='k';if(last!=tokenp){SGN.push(str);last=tokenp;}} else
if(pare("<PT,22>")==0){w='k';if(last!=tokenp){SGN.push(str);last=tokenp;}} else if(pare("<PT,0>")==0){w='(';}
else if(pare("<PT,1>")==0){w=')';}
else{cout<<"源代码错误-ERRO:03"<<endl;getchar();exit(0);} }//else
}//else
(2)判断是否执行动作
while(s=='{'){
anal.pop();//弹出{
p=anal.top();
anal.pop();//弹出动作符号
anal.pop();//弹出}
s=anal.top();//接收常规栈顶
switch(p)
{
case 'P':{SEM.push(VTOKEN[tokenp-1]);break;}//当前字段压入语义栈
case 'G':{GEQ(SGN.top());break;}//调取表达式四元式生成函数
}
}//while
(3)用LL(1)方法匹配表达式文法
if(w=='#'&&s=='#') {cout<<"验证了表达式语句并生成了四元式"<<endl;return 1;} if(s==w)
{
anal.pop();
tokenp++;
}
else
{
if(m==-1) return 0;
else
{
n=inVt(w);
if(n==-1) return 0;
l=SelectTable[m][n];
if(l==-1) return 0;
anal.pop();
if(QRULL[l][3]=='0') continue;
else
{
for(j=QRULL[l].size()-1;j>=3;j--) anal.push(QRULL[l][j]);
}
}
}
3.5目标语言生成器算法
首先将符号表中的内容翻译为汇编代码的数据段,之后读取四元式生成程序段。

由于生成的四元式的操作码都在最左边,故可以采用类似LL(1)的算法,读取操作数并按照其语义,生成相应的汇编代码。

其中涉及到条件和循环等程序跳转的地方,采用了标号栈技术来实现各程序段标号的正确排序。

算法实现如下:
void WriteAsm()
{
int aa,bb;
string cc;
for(aa=0;aa<CT.size();aa++){
cc="";
for(bb=2;bb<CT[bb].length();bb++){
cc+=CT[aa][bb];
}
CT[aa]=cc;
}
vector<string> flags(0);//跳转标志栈
int flagcounter=0;//标志计数器
string tflag1,tflag2,tflag3;
int i,j;
char p[10];
string dseg1;dseg1="";
string dseg2;dseg2="";
string theasm;
theasm="DSEG SEGMENT\n";
for(i=0;i<ITi.size();i++){
if(ITi[i].name[0]=='t'){
dseg1=ITi[i].name+'i';
itoa(i,p,10);
dseg1+=p;
dseg2=ITi[i].val;
}
else{
dseg1=ITi[i].name;
dseg2=ITi[i].val;
}
theasm+=dseg1+' ';
theasm+="DW ";
theasm+=dseg2+'\n';
dseg1="";dseg2="";
}
} theasm+=dseg1+' ';
theasm+="DD ";
theasm+=dseg2+'\n';
dseg1="";dseg2="";
}
}
if(ITc.size()!=0){
for(i=0;i<ITc.size();i++){
if(ITc[i].name[0]=='t'){
dseg1=ITc[i].name+'c';
itoa(i,p,10);
dseg1+=p;
dseg2=ITc[i].val;
}
else{
dseg1=ITc[i].name;
dseg2=ITc[i].val;
}
theasm+=dseg1+' ';
theasm+="DB ";
theasm+=dseg2+'\n';
dseg1="";dseg2="";
}
}
theasm+="DSEG ENDS\nCSEG SEGMENT\nASSUME CS:CSEG,DS:DSEG\nstart:MOV AX,DSEG\nMOV DS,AX\n";
op=FindTable(op);
if(pare("+")==0){
aim=FindTable(aim);
theasm+="MOV AX,"+src1+"\n"+"MOV BX,"+src2+"\n"+"ADD AX,BX\n"+"MOV AX,"+aim+"\n";
}
else if(pare("-")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
theasm+="MOV AX,"+src1+"\n"+"MOV BX,"+src2+"\n"+"SUB AX,BX\n"+"MOV AX,"+aim+"\n";
}
else if(pare("~")==0){
src1=FindTable(src1);
aim=FindTable(aim);
theasm+="MOV AX,"+src1+"\n"+"MOV BX,0\n"+"SUB BX,AX\n"+"MOV BX,"+aim+"\n";
}
else if(pare("*")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
theasm+="MOV AX,"+src1+"\n"+"MOV BX,"+src2+"\n"+"MUL BX\n"+"MOV AX,"+aim+"\n";
}
else if(pare("/")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
theasm+="MOV AX,"+src1+"\n"+"MOV DX,0000H\n"+"MOV BX,"+src2+"\n"+"DIV BX\n"+"MOV AX,"+aim+"\n";
}
else if(pare("%")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
theasm+="MOV AX,"+src1+"\n"+"MOV DX,0000H\n"+"MOV BX,"+src2+"\n"+"DIV BX\n"+"MOV DX,"+aim+"\n";
}
else if(pare("=")==0){
src1=FindTable(src1);
aim=FindTable(aim);
theasm+="MOV "+aim+","+src1+"\n";
}
else if(pare("==")==0){
src1=FindTable(src1);
theasm+="CMP "+src1+","+src2+"\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JNE flag";
theasm+=p;
theasm+="\n";
tflag1="flag";
tflag1+=p;
theasm+="MOV "+aim+",1\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JMP flag";
theasm+=p;
theasm+="\n";
tflag2="flag";
tflag2+=p;
theasm+=tflag1+":MOV "+aim+",0\n"+tflag2+":"; }
else if(pare("!=")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
theasm+="CMP "+src1+","+src2+"\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JNE flag";
theasm+=p;
theasm+="\n";
tflag1="flag";
tflag1+=p;
theasm+="MOV "+aim+",0\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JMP flag";
theasm+=p;
theasm+="\n";
tflag2="flag";
tflag2+=p;
theasm+=tflag1+":MOV "+aim+",1\n"+tflag2+":"; }
else if(pare(">")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JLE flag";
theasm+=p;
theasm+="\n";
tflag1="flag";
tflag1+=p;
theasm+="MOV "+aim+",1\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JMP flag";
theasm+=p;
theasm+="\n";
tflag2="flag";
tflag2+=p;
theasm+=tflag1+":MOV "+aim+",0\n"+tflag2+":"; }
else if(pare("<")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
theasm+="CMP "+src1+","+src2+"\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JNL flag";
theasm+=p;
theasm+="\n";
tflag1="flag";
tflag1+=p;
theasm+="MOV "+aim+",1\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JMP flag";
theasm+=p;
theasm+="\n";
tflag2="flag";
tflag2+=p;
theasm+=tflag1+":MOV "+aim+",0\n"+tflag2+":"; }
else if(pare(">=")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
theasm+="CMP "+src1+","+src2+"\n";
itoa(flagcounter,p,10);
theasm+="JL flag";
theasm+=p;
theasm+="\n";
tflag1="flag";
tflag1+=p;
theasm+="MOV "+aim+",1\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JMP flag";
theasm+=p;
theasm+="\n";
tflag2="flag";
tflag2+=p;
theasm+=tflag1+":MOV "+aim+",0\n"+tflag2+":";
}
else if(pare("<=")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
theasm+="CMP "+src1+","+src2+"\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JG flag";
theasm+=p;
theasm+="\n";
tflag1="flag";
tflag1+=p;
theasm+="MOV "+aim+",1\n";
itoa(flagcounter,p,10);
flagcounter++;
theasm+="JMP flag";
theasm+=p;
theasm+="\n";
tflag2="flag";
tflag2+=p;
theasm+=tflag1+":MOV "+aim+",0\n"+tflag2+":";
}
else if(pare("&&")==0){
src1=FindTable(src1);
src2=FindTable(src2);
aim=FindTable(aim);
theasm+="MOV AX,"+src1+"\n"+"MOV BX,"+src2+"\n"+"AND AX,BX\n"+"MOV AX,"+aim+"\n";
}
else if(pare("||")==0){。

相关文档
最新文档