编译原理词法分析器语法分析器实验报告.docx
《编译原理词法分析器语法分析器实验报告.docx》由会员分享,可在线阅读,更多相关《编译原理词法分析器语法分析器实验报告.docx(20页珍藏版)》请在冰点文库上搜索。
编译原理词法分析器语法分析器实验报告
编译技术班级网络0802
学号52
姓名叶晨舟
指导老师朱玉全
2011年7月4日
一、目的
编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。
从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。
二、任务及要求
基本要求:
1.词法分析器产生下述小语言的单词序列
这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表:
单词符号
种别编码
助记符
内码值
DIM
IF
DO
STOP
END
标识符
常数(整)
=
+
*
**
,
(
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$DIM
$IF
$DO
$STOP
$END
$ID
$INT
$ASSIGN
$PLUS
$STAR
$POWER
$COMMA
$LPAR
$RPAR
-
-
-
-
-
-
内部字符串
标准二进形式
-
-
-
-
-
-
对于这个小语言,有几点重要的限制:
首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。
所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。
例如,下面的写法是绝对禁止的:
IF(5)=x
其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。
也就是说,对于关键字不专设对应的转换图。
但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。
当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。
再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。
例如,一个条件语句应写为
IFi>0i=1;
而绝对不要写成
IFi>0i=1;
因为对于后者,我们的分析器将无条件地将IFI看成一个标识符。
这个小语言的单词符号的状态转换图,如下图:
2.语法分析器能识别由加+减-乘*除/乘方^括号()操作数所组成的算术表达式,其文法如下:
E→E+T|E-T|T
T→T*F|T/F|F
F→P^F|P
p→(E)|i
使用的算法可以是:
预测分析法;递归下降分析法;算符优先分析法;LR分析法等。
3.中间代码生成器产生上述算术表达式的中间代码(四元式序列)
三、实现过程
给出各题目的详细算法描述,数据结构和函数说明,流程图。
1、词法分析器的流程图
2、语法分析器主程序图
3、中间代码生成器流程图:
四、源程序
词法分析器:
#include<>
#include<>
#include
usingnamespacestd;
typedefstructtable,S1)==0||strcmp(M[p][q].m,S2)==0);
printf("%15c-->%s\n",X,str0);;
getchar();
}
}
opt3:
printf("请输入要分析的字符串,且以#结束:
\n");
analyse(Vn,Vt);
printf("********************请选择***********************\n");
printf("1:
输入字符串\n");
printf("2:
输入新分析表\n");
printf("0:
退出\n");
printf("*************************************************\n");
opt4:
cin>>select;
switch(select)
{
case'1':
{gotoopt3;break;}
case'2':
{gotoopt2;}
case'0':
{break;}
default:
{printf("输入错误!
请重新选择:
");
gotoopt4;
break;}
}
return0;
}
运行结果:
语法分析器源程序:
#include<>
#include
usingnamespacestd;
charprog[100],token[10];
charch;
intsyn,p,m=0,n,row,sum=0;
char*rwtab[20]={"dim","if","do","stop","end","and","begin","bool","case","char",
"false","for","int","not","or","set","then","true","until","while"
};
voidscaner()
{
for(n=0;n<9;n++)token[n]=NULL;
ch=prog[p++];
while(ch=='')
{
ch=prog[p];
p++;
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
m=0;
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
token[m++]=ch;
ch=prog[p++];
}
token[m++]='\0';
p--;
syn=21;
for(n=0;n<20;n++)
{
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
}
elseif((ch>='0'&&ch<='9'))
{
{
sum=0;
while((ch>='0'&&ch<='9'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
}
p--;
syn=7+15;
if(sum>32767)
syn=-1;
}
elseswitch(ch)
{
case'=':
syn=8+15;token[0]=ch;break;
case'+':
syn=9+15;token[0]=ch;break;
case'*':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='*')
{
syn=11+15;
token[m++]=ch;
}
else
{
syn=10+15;
p--;
}
break;
case',':
syn=12+15;token[0]=ch;break;
case'(':
syn=13+15;token[0]=ch;break;
case')':
syn=14+15;token[0]=ch;break;
case'#':
syn=0;token[0]=ch;break;
case'<':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='>')
{
syn=17+15;
token[m++]=ch;
}
elseif(ch=='=')
{
syn=16+15;
token[m++]=ch;
}
else
{
syn=15+15;
p--;
}
break;
case'>':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=19+15;
token[m++]=ch;
}
else
{
syn=18+15;
p--;
}
break;
case':
':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=21+15;
token[m++]=ch;
}
else
{
syn=20+15;
p--;
}
break;
case'/':
syn=22+15;token[0]=ch;break;
case'-':
syn=23+15;token[0]=ch;break;
case';':
syn=24+15;token[0]=ch;break;
default:
syn=-1;break;
}
}
voidmain()
{
p=0;
row=1;
cout<cout<<"***************************小型词法分析器**********************************"<cout<<"请输入一段程序(以#结束):
";
do
{
(ch);
prog[p++]=ch;
}
while(ch!
='#');
p=0;
cout<cout<<"种别编码自身值"<do
{
scaner();
switch(syn)
{
case22:
cout<<"("<case-1:
cout<<"Errorinrow"<"<default:
cout<<"("<}
}
while(syn!
=0);
}
运行结果:
}
中间代码生成器源程序:
表达式生成四元式
递归子程序法
#include
#include
usingnamespacestd;
#defineDEFAULT_SIZE100
charEMachine(charw);<exit
(1);
}
}
voidstack:
:
push(conststring&item)<return;
}
top++;
stacka[top]=item;
}
stringstack:
:
pop(void)<exit
(1);
}
stringitem=stacka[top];
top--;
returnitem;
}
stringstack:
:
gettop(void)const<exit
(1);
}
returnstacka[top];
}
staticstackwordStack;//符号栈
staticintnoOfQuet=0;//静态四元式个数记录
staticintnoOfT=1;//静态状态个数记录
voidmain(){//主函数
charyesOrNo;//进行一个循环操作控制
do{
cout<<"请输入算术表达式:
"<noOfT=1;//每次结束询问
ZMachine();
cout<";
cin>>yesOrNo;//输入“Y”则继续
}while(yesOrNo=='y');//否则程序结束
}
boolZMachine(){//Z自动机
charw;
cin>>w;
w=EMachine(w);//调用E自动机
if(w=='#'){//遇到“#”则结束
returntrue;
}
else{
returnfalse;
}
}
charEMachine(charw){//E自动机
stringoperate,a,b,c;
stringstate[5];
w=TMachine(w);//调用T自动机
while(w=='+'||w=='-'){//是加或减符号
operate=w;
cin>>w;//读入下一字符
w=TMachine(w);//调用T自动机
b=();//字符栈弹出
a=();//两个操作字符
cout<<"(\""<c="t"+intToString(noOfT);//输出四元式
(c);//新状态压栈
noOfT++;//状态计数加一
}
returnw;
}
charTMachine(charw){
stringoperate,a,b,c;
stringstate[5];
w=FMachine(w);//调用F自动机
while(w=='*'||w=='/'){//是乘除号
operate=w;
cin>>w;//读取下一字符
w=FMachine(w);//调用F自动机
b=();//符号栈弹出
a=();//两个操作字符
cout<<"(\""<c="t"+intToString(noOfT);//输出四元式
(c);//新状态压栈
noOfT++;//状态计数加1
}
returnw;
}
charFMachine(charw){//F自动机
stringtheWord;
if(w>='a'&&w<='z'||w>='A'&&w<='Z'){
theWord=w;//当前字符是字母
(theWord);//则压栈
}
elseif(w=='('){//是左括号
cin>>w;//则读取下一字符
w=EMachine(w);//调用E自动机
if(w!
=')'){//不是右括号则输入有误,报错
cerr<<"theinputiswrong!
"<exit(0);
}
}
else{//否则有误,报错
cerr<<"theinputiswrong!
"<exit(0);
}
cin>>w;//读取下一字符
returnw;
}
stringintToString(inta){//整形变字符串形函数
stringd;
charb='0',c;
inti;
while(a!
=0){
i=a%10;
a=a/10;
c=(int)b+i;
d=c+d;
}
returnd;
}
//Y=a+b*(c+(-d)*(e+f))
//Y=(a+b*(c-d*e/f+g*(h-i*x*(j+k*(-l)*(j+k)))+w))
//H=(d+a-(c+b-q)*a)+c-(a+b*(c+d))
六、总结
通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把理论知识应用于实验中,也让我重新熟悉了C++语言的相关内容,加深了对C++语言知识的深化和用途的理解。
相信在以后的毕业设计以及读研自己做项目时可以有更大的提升。
|