编译原理课设.docx

上传人:b****5 文档编号:7478503 上传时间:2023-01-24 格式:DOCX 页数:35 大小:275.33KB
下载 相关 举报
编译原理课设.docx_第1页
第1页 / 共35页
编译原理课设.docx_第2页
第2页 / 共35页
编译原理课设.docx_第3页
第3页 / 共35页
编译原理课设.docx_第4页
第4页 / 共35页
编译原理课设.docx_第5页
第5页 / 共35页
点击查看更多>>
下载资源
资源描述

编译原理课设.docx

《编译原理课设.docx》由会员分享,可在线阅读,更多相关《编译原理课设.docx(35页珍藏版)》请在冰豆网上搜索。

编译原理课设.docx

编译原理课设

 

编译技术课程设计

 

班级

学号

姓名

指导老师

2015年6月

 

一、目的

<<编译技术>>是理论与实践并重的课程,而其课程设计要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。

从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。

二、题目

题目1表达式的小型编译器

三、要求

1.词法分析

产生语言的单词序列

2.语法分析

能识别由加+乘*括号()操作数(变量或常数)所组成的算术表达式,其文法如下:

E→E+T|T

T→T*F|F

F→(E)|i

使用的分析方法可以是:

递归下降分析法或LR分析法。

3.代码生成

产生上述算术表达式的中间代码

4.错误处理

给出错误信息

输入:

算术表达式

输出:

符号表,常数表。

归下降分析法:

递归调用过程/LR分析法:

语义栈和符号栈

四元式序列

四、实验环境

1.开发环境:

VisualStudio2013

2.程序语言:

C++

 

五、系统实现

1.词法分析

(1)单词符号表

 

 

(2)状态转换图

(3)数据结构

(4)函数说明

voidgetonechar()/*从输入的算数表达式中读取一个字符*/

voidconcatenation()/*将token中的字符串与character中的字符并作为token中新的字符串*/

boolletter()/*判断character中的字符是否为字母的布尔函数,是则返回true,否侧返回false*/

booldigit()/*判断character中的字符是否为数字的布尔函数,是则返回true,否侧返回false*/

voidretract()/*扫描指针回退一个字符,同时将character置为空白*/

intreserve()/*将token中的字符查找保留字数组,若是保留字就返回它的种别编码,否则返回0*/

voidbuildlist1()/*将标识符登录到符号表中(value2[])*/

voidbuildlist2()/*将常数登录到常数表中(value1[])*/

voidresolve()/*词法分析的主要函数,每次识别一个单词,将种别编码放入cf[]中,填入对应的value1[]和value[]*/

voidcffx()/*词法分析,读入输入的算数表达式,循环执行resolve(),直到所有单词识别完毕*/

2.语法分析

(1)分析方法说明

本程序采用LR分析法,存在4种动作:

①移进:

使(s,a)的下一个状态s’=ACTION[s,a]和输入符号a进栈,下一输入符号变成现行输入符号.

②规约:

指用某一产生式A→β进行规约,假若β的长度为γ,则规约动作是去掉栈顶的γ个栈,即是状态Sm-γ变成栈顶状态,然后使(Sm-γ,A)的下一状态s’=GOTO[Sm-γ,A]和文法符号A进栈.规约的动作不改变现行输入符号,执行规约的动作意味着呈现于栈顶的符号串Xm-γ+1…Xm是一个相对于A的句柄.

③接受:

宣布分析成功,停止分析器工作.

④报错:

报告发现源程序含有错误,调用错误处理程序.

 

(2)文法

(3)数据结构

#include/*引入c++标准库*/

stackstatus;/*状态栈*/

stacksign;/*符号栈*/

(4)函数说明

VoidinitYffx()/*语法分析初始化,状态栈放0,符号栈放#,语义栈放_*/

VoidshowLR()/*遍历状态栈,符号栈,语义栈,并显示出来*/

VoidyffxSolve()/*查action二维数组,进行移进,规约处理*/

Voidyyfx()/*循环执行yffxSolve(),直到分析成功或出现错误*/

VoidshowBlm()/*显示变量名表*/

VoidshowCsb()/*显示常数表*/

3.中间代码

(1)属性文法

①移进时:

如果输入的是终结符,语义栈就移进”_”,如果是非终结符,则语义栈移进对应的常数或变量名.

②规约时:

如果规约对应的文法是(4)E→i时语义栈不变,

对应其他文法时,先pop出栈顶3个元素,

再如果是(3)E→(E)文法时,语义栈push刚才出栈的第二个元素,

如果是

(1)E→E+E文法时,判断刚才出栈的第一个和第三个元素是否是常数,是则push两个常数的和,否则push临时变量Tn;

如果是

(1)E→E*E文法时,判断刚才出栈的第一个和第三个元素是否是常数,是则push两个常数的积,否则push临时变量Tn;

(2)数据结构

#include/*引入c++标准库*/

stackyuyi;/*语义栈*/

stringv1,v2,v3,v4;/*分别表示四元式的参数1,参数2,参数3,参数4*/

(3)函数说明

语义栈和四元式的产生是在语法分析一起的,在yffxSolve().

voidyffxSolve()

{

stacktempYuyiPush;

showLR();

inti=-1;

if(cf[m]==6||cf[m]==7){

i=0;

}

if(cf[m]==8){

i=1;

}

if(cf[m]==10){

i=2;

}

if(cf[m]==14){

i=3;

}

if(cf[m]==15){

i=4;

}

if(cf[m]==16){

i=5;

}

if(i==-1){

cout<<"输入了错误的种别编码"<

m++;

return;

}

if(action[status.top()][i]>0)

{

if(action[status.top()][i]>100)

{

if(action[status.top()][i]==1000)

{

cout<<"acc"<

system("pause");

exit(0);

}

/*规约*/

//cout<<"gy"<

ints=action[status.top()][i]-100;

for(intj=0;j

{

if(s!

=4)

{

tempYuyiPush.push(yuyi.top());

yuyi.pop();

}

status.pop();

sign.pop();

}

status.push(action[status.top()][6]);

sign.push('E');

if(s==4)

{

}

else{

v2=tempYuyiPush.top();

tempYuyiPush.pop();

stringv2plus5=tempYuyiPush.top();

tempYuyiPush.pop();

v3=tempYuyiPush.top();

tempYuyiPush.pop();

if(isdigit(v2)&&isdigit(v3))

{

if(s==1)

{

v4=intToStr(strToInt(v2)+strToInt(v3));

}

if(s==2)

{

v4=intToStr(strToInt(v2)*strToInt(v3));

}

yuyi.push(v4);

}

else{

if(v2=="_"&&isdigit(v2plus5)&&v2=="_")

{

v4=v2plus5;

yuyi.push(v4);

}

else{

stringtempNum=intToStr(yuyiNum);

stringtempS="T"+tempNum;

yuyiNum++;

yuyi.push(tempS);

v4=tempS;

}

}

if(s==1)

{

v1="+";

}

if(s==2)

{

v1="*";

}

}

}

else

{

/*移近*/

//cout<<"yj"<

status.push(action[status.top()][i]);

sign.push(inputSign[i]);

if(cf[m]==6||cf[m]==7)

{

if(cf[m]==6)

{

yuyi.push(value2[m]);

}

else{

stringtempVal=intToStr(value1[m]);

yuyi.push(tempVal);

}

}

else{

yuyi.push("_");

}

m++;

}

}

else

{

interr=action[status.top()][i];

cout<<"第"<

system("pause");

exit(0);

}

lrNum++;

}

(4)流程图

4.错误处理

(1)数据结构

stringshowErr[12]=

{

{"FOUNDERROR:

+前缺少变量或常量"},/*0,e1*/

{"FOUNDERROR:

*前缺少变量或常量"},/*1,e2*/

{"FOUNDERROR:

)前缺少对应("},/*2,e3*/

{"FOUNDERROR:

连续的变量或常量,缺少+/*"},/*3,e4*/

{"FOUNDERROR:

(前缺少+/*"},/*4,e5*/

{"FOUNDERROR:

(后缺少常量或变量"},/*5,e6*/

{"FOUNDERROR:

()内无表达式"},/*6,e7*/

{"FOUNDERROR:

+后缺少变量或常量"},/*7,e8*/

{"FOUNDERROR:

*后缺少变量或常量"},/*8,e9*/

{"FOUNDERROR:

算数表达式为空"},/*9,e10*/

{"FOUNDERROR:

缺少对应)"},/*10,e11*/

{"FOUNDERROR:

语法分析错误"}/*11,e12*/

};

(2)函数说明

yffxSolve()中,查action数组时,遇到e时输出错误位置和错误信息,跳过此单词,继续进行语法分析.

六、程序运行结果

1.连乘

2.连加

3.加乘混合

4.带括号

5.常数

6.错误的算术表达式

1)缺少操作符

2)缺少操作数

3)不完整的()

七、总结

通过课程设计更加深入地理解了LR分析法对算数表达式处理的过程,熟悉了编译的四个阶段:

词法分析,语法分析,语义分析和中间代码,以及错误处理.在运用c++编写程序时,也熟悉了c++标准库中stack的使用.

程序是一段一段写下来的,整个程序没有整体的规划,定义的变量又多又乱,造成许多变量需要不断的修改,而且不利于程序的理解.在对栈处理的时候,发现标准库定义的stack的函数太少,只有pop,push,empty,top,size,没有遍历,需要自己写.

程序需要不断修改才能完成.检查时发现:

显示错误处理时没有给出错误位置;当出现多个错误时,只能显示第一个错误.

完整代码:

#include

#include

#include

#include

#include

usingnamespacestd;

stringstr;/*源程序*/

charcharacter;/*源程序当前字符*/

intp=-1;/*源程序游标*/

stringtoken="";

stringblz[5]={"while","if","else","switch","case"};

intc;/*标示符种类编码*/

//intlength;/*输入源程序的长度*/

intstatue=0;/*判断词法分析完成*/

intcf[50];/*词法分析后的种类编码数组*/

intvalue1[50];/*cf对应常数*/

stringvalue2[50];/*cf对应变量名*/

intq=0;/*cf创建的游标*/

intm=0;/*cf语法分析的游标*/

stringblmb[50];/*变量名表*/

inta=0;/*变量名表的游标*/

stringcsb[50];/*常数表*/

intb=0;/*常数表的游标*/

staticintaction[10][7]=

{{3,-12,-11,2,-10,-3,1},

{-9,4,5,-8,-10,1000,-1},

{3,-7,-7,2,-6,-2,6},

{-9,104,104,-8,104,104,-1},

{3,-5,-5,2,-10,-5,7},

{3,-4,-4,2,-10,-4,8},

{-9,4,5,-9,9,-2,-1},

{-9,101,5,-9,101,101,-1},

{-9,102,102,-9,102,102,-1},

{-9,103,103,-9,103,103,-1}};

stackstatus;

stacksign;

stackyuyi;

intlrNum=0;/*分析表步骤号*/

charinputSign[7]={'i','+','*','(',')','#','E'};/*进栈符号*/

intgyLen[4]={3,3,3,1};

intyuyiNum=1;/*语义临时变量序号*/

stringv1,v2,v3,v4;

stringshowErr[12]=

{

"发现错误:

+前缺少变量或常量",/*0,e12*/

"发现错误:

*前缺少变量或常量",/*1,e11*/

"发现错误:

)前缺少对应(",/*2,e10*/

"发现错误:

连续的变量或常量,缺少+/*",/*3,e9*/

"发现错误:

(前缺少+/*",/*4,e8*/

"发现错误:

(后缺少常量或变量",/*5,e7*/

"发现错误:

()内无表达式",/*6,e6*/

"发现错误:

+后缺少变量或常量",/*7,e5*/

"发现错误:

*后缺少变量或常量",/*8,e4*/

"发现错误:

算数表达式为空",/*9,e3*/

"发现错误:

缺少对应)",/*10,e2*/

"发现错误:

语法分析错误"/*11,e1*/

};

voidgetonechar()

{

/*if(p>=length)

{

system("pause");

exit(0);

}*/

p++;

while(str[p]==''&&str[p+1]=='')

{

p++;

}

character=(char)str[p];

}

voidconcatenation()

{

token+=character;

}

boolletter()

{

if((character>='a'&&character<='z')||(character>='A'&&character<='Z'))

{

returntrue;

}

else

returnfalse;

}

booldigit()

{

if((character>='0'&&character<='9'))

{

returntrue;

}

else

returnfalse;

}

intreserve()

{

for(inti=0;i<5;i++)

{

if(token==blz[i])

{

returni+1;

}

}

return0;

}

voidretract()

{

p--;

}

/*变量名表*/

voidbuildlist1(stringtoken)

{

inti;

for(i=0;i

{

if(token==blmb[i])

{

break;

}

}

if(i==a)

{

blmb[a]=token;

a++;

}

value2[q]=token;

}

/*常数表*/

voidbuildlist2(stringtoken)

{

inti;

for(i=0;i

{

if(token==csb[i])

{

break;

}

}

if(i==b)

{

csb[b]=token;

b++;

}

stringstreamss;

ss<

intnum;

ss>>num;

value1[q]=num;

}

voidresolve()

{

token="";

getonechar();

switch(character)

{

case'a':

case'b':

case'c':

case'd':

case'e':

case'f':

case'g':

case'h':

case'i':

case'j':

case'k':

case'l':

case'm':

case'n':

case'o':

case'p':

case'q':

case'r':

case's':

case't':

case'u':

case'v':

case'w':

case'x':

case'y':

case'z':

while(letter()||digit())

{

concatenation();

getonechar();

}

retract();

c=reserve();

if(c==0)

{

buildlist1(token);

cout<<"(6,"<

cf[q]=6;

q++;

}

else

{

cout<<"("<

cf[q]=c;

q++;

}

break;

case'0':

case'1':

case'2':

case'3':

case'4':

case'5':

case'6':

case'7':

case'8':

case'9':

while(digit())

{

concatenation();

getonechar();

}

retract();

buildlist2(token);

cf[q]=7;

q++;

cout<<"(7,"<

break;

case'+':

cf[q]=8;

q++;

cout<<"(8,+)"<

break;

case'-':

cf[q]=9;

q++;

cout<<"(9,-)"<

break;

case'(':

cf[q]=14;

q++;

cout<<"(14,()"<

break;

case')':

cf[q]=15;

q++;

cout<<"(15,))"<

break;

case'*':

cf[q]=10;

q++;

cout<<"(10,*)"<

break;

case'<':

getonechar();

if(character=='=')

{

cf[q]=11;

q++;

cout<<"(11,LE)"<

}

else

{

retract();

cf[q]=11;

q++;

cout<<"(11,LT)"<

}

break;

case'=':

getonechar();

if(character==

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 英语考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1