实验1词法分析实验报告.docx
《实验1词法分析实验报告.docx》由会员分享,可在线阅读,更多相关《实验1词法分析实验报告.docx(25页珍藏版)》请在冰豆网上搜索。
![实验1词法分析实验报告.docx](https://file1.bdocx.com/fileroot1/2022-11/26/988a258c-d0c1-4386-b263-0edd73bf0c67/988a258c-d0c1-4386-b263-0edd73bf0c671.gif)
实验1词法分析实验报告
软件学院
《编译原理》实验报告
题目:
词法、语法分析
专业:
软件工程
班级:
rB软件W101
学号:
201007104141
学生姓名:
田博
指导教师:
陆筱霞
日期:
2013-6-21
实验词法分析实验报告
一:
实验目的
调
试并完成一个词法分析程序,加深对词法分析原理的理解。
二:
实验要求
1、待分析的简单语言的词法
(1)关键字:
beginifthenwhiledoend
所有关键字都是小写。
(2)运算符和界符:
:
=+–*/<<=<>>>==;()#
(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:
ID=letter(letter|digit)*
NUM=digitdigit*
(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。
2、各种单词符号对应的别码
单词符号
种别码
单词符号
种别码
begin
1
:
17
if
2
:
=
18
then
3
>
20
while
4
<>
21
do
5
<=
22
end
6
<
23
letter(letter|digit)*
10
>=
24
digitdigit*
11
=
25
*
13
;
26
/
14
(
27
+
15
)
28
-
16
#
0
3、词法分析程序的输入
所给文法的源程序字符串。
输出:
二元组(syn,token或sum)构成的序列。
其中:
syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
三:
代码
#include#include#includecharprog[80],token[8];charch;intsyn,p,m=0,n,row,sum=0;char*rwtab[6]={"begin","if","then","while","do","end"};
voidscaner(){
for(n=0;n<8;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=10;
for(n=0;n<6;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=11;
if(sum>32767)
syn=-1;
}
elseswitch(ch)
{case'<':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='>')
{
syn=21;
token[m++]=ch;
}
elseif(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;case'>':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=20;
p--;
}
break;case':
':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=18;
token[m++]=ch;
}
else
{
syn=17;
p--;
}
break;case'*':
syn=13;token[0]=ch;break;case'/':
syn=14;token[0]=ch;break;case'+':
syn=15;token[0]=ch;break;case'-':
syn=16;token[0]=ch;break;case'=':
syn=25;token[0]=ch;break;case';':
syn=26;token[0]=ch;break;case'(':
syn=27;token[0]=ch;break;case')':
syn=28;token[0]=ch;break;case'#':
syn=0;token[0]=ch;break;case'\n':
syn=-2;break;default:
syn=-1;break;
}}
voidmain(){
p=0;
row=1;
cout<<"Pleaseinputstring:
"<do
{
cin.get(ch);
prog[p++]=ch;
}
while(ch!
='#');
p=0;
do
{
scaner();
switch(syn)
{
case11:
cout<<"("<case-1:
cout<<"Errorinrow"<"<case-2:
row=row++;break;
default:
cout<<"("<}
}
while(syn!
=0);}
四:
实验验证
4、给定源程序
beginx:
=9;ifx>0thenx:
=2*x+1/3;end#
输出结果
5、源程序(包括上式未有的while、do以及判断错误语句):
beginx<=$;whilea<0dob<>9-x;end#
输出结果
五:
总结
通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,根据识别语言单词的状态转换图,使用某种高级语言(例如C++语言)直接编写此法分析程序。
另外,也让我重新熟悉了C++语言的相关内容,加深了对C++语言的用途的理解。
比如:
main()函数中,用cin>>ch;语句得到ch值的话,给定源程序的结果第一行得到的是(10,beginx),因为得到的字符串中省略了空格,改用cin.get(ch);问题便解决了。
另外,我在程序中加入了row变量,以便能够准确得到错误所在。
编译原理语法分析器实验报告
1、实验目的:
结合课堂上学习的理论知识,通过C++实现语法分析器,更加深入的掌握语法分析;同时也可以更加了解语法分析的原理。
2、实验过程:
1、设计思路:
首先判断输入文法是否为算符文法,若是算符文法则构造它的FIRSTVT和LASTVT集,然后构造它的算符优先表,判断是否为算符优先文法;最后进行归约。
2、实验过程中的问题:
一开始实验很生疏,很难把理论知识融汇到编程上,后来通过多次看PPT和书本内容,渐渐把握到诀窍;不明确输入输出;这个也是通过PPT解决;和以前编其他东西很不一样,一开始不知道如何下手;通过网上的成熟代码学习了下。
实验代码:
#include#include#includetypedefstruct{
charR;
charr;
intflag;}array;
typedefstruct{
charE;
chare;}charLode;
typedefstruct{
charLode*base;
inttop;}charstack;
charstr[80][80],arr[80][80],brr[80][80];arrayF[20];intm,kk,p,ppp,FF=1;charr[10];intcrr[20][20],FLAG=0;charccrr1[1][20],ccrr2[20][1];
voidInitstack(charstack&s)//定义栈{
s.base=newcharLode[20];
s.top=-1;}
voidpush(charstack&s,charLodew)//入栈{
s.top++;
s.base[s.top].E=w.E;
s.base[s.top].e=w.e;}
voidpop(charstack&s,charLode&w)//出栈{
w.E=s.base[s.top].E;
w.e=s.base[s.top].e;
s.top--;}
intIsEmpty(charstacks)//判断是否到栈顶{
if(s.top==-1)
return1;
else
return0;}
intIsLetter(charch)//判断是不是大写字母(非终结符){
if(ch>='A'&&ch<='Z')
return1;
else
return0;}
//judge1是判断是否是算符文法:
若产生式中含有两个相继的非终结符则不是算符文法intjudge1(intn){
intj=3,flag=0;
for(inti=0;i<=n;i++)
while(str[i][j]!
='\0')
{
chara=str[i][j];
charb=str[i][j+1];
if(IsLetter(a)&&IsLetter(b))//两个非终结符相连,不是算符文法
{
flag=1;
break;
}
else
j++;
}
if(flag==1)//根据flag设定返回值
return0;
else
return1;}
//judge2是判断文法G是否为算符优先文法:
若不是算符文法或若文法中含空字或终结符的优先级不唯一则不是算符优先文法voidjudge2(intn){
for(inti=0;i<=n;i++)
if(str[i][3]=='~'||FLAG==1)//'~'代表空
{
cout<<"文法G不是算符优先文法!
"<FF=0;
break;
}
if(i>n)cout<<"文法G是算符优先文法!
"<//search1是查看存放终结符的数组r中是否含有重复的终结符intsearch1(charr[],intkk,chara){
for(inti=0;iif(r[i]==a)
break;
if(i==kk)
return0;
else
return1;}
//createF函数是用F数组存放每个终结符与非终结符和组合,并且值每队的标志位为0;F数组是一个结构体voidcreateF(intn){
intk=0,i=1;charg;
chart[10];//t数组用来存放非终结符
t[0]=str[0][0];
while(i<=n)
{
if(t[k]!
=str[i][0])
{
k++;
t[k]=str[i][0];
g=t[k];
i++;
}
elsei++;}
kk=0;
charc;
for(i=0;i<=n;i++)
{
intj=3;
while(str[i][j]!
='\0')
{
c=str[i][j];
if(IsLetter(c)==0)
{
if(!
search1(r,kk,c))
r[kk]=c;
kk++;//r数组用来存放终结符
}j++;}}m=0;
for(i=0;ifor(intj=0;j{
F[m].R=t[i];
F[m].r=r[j];
F[m].flag=0;
m++;
}}
//search函数是将在F数组中寻找到的终结符与非终结符对的标志位值为1voidsearch(charLodew){
for(inti=0;iif(F[i].R==w.E&&F[i].r==w.e)
{
F[i].flag=1;break;
}}
voidFirstVT(intn)//求FirstVT{
charstacksta;
charLodew;
inti=0;
Initstack(sta);
while(i<=n)
{
intk=3;
w.E=str[i][0];
chara=str[i][k];
charb=str[i][k+1];
if(!
IsLetter(a))//产生式的后选式的第一个字符就是终结符的情况
{
w.e=a;
push(sta,w);
search(w);
i++;
}
elseif(IsLetter(a)&&b!
='\0'&&!
IsLetter(b)){
w.e=b;
push(sta,w);
search(w);
i++;
}
elsei++;}
charLodeww;
while(!
IsEmpty(sta))
{
pop(sta,ww);
for(i=0;i<=n;i++)
{
w.E=str[i][0];
if(str[i][3]==ww.E&&str[i][4]=='\0')
{
w.e=ww.e;
push(sta,w);
search(w);
break;
}
}
}
p=0;intk=1;i=1;
while(i{
if(F[i-1].flag==1)
{
arr[p][0]=F[i-1].R;
arr[p][k]=F[i-1].r;
}
while(F[i].flag==0&&ii++;
if(F[i].flag==1)
{
if(F[i].R==arr[p][0])
k++;
else{arr[p][k+1]='\0';p++;k=1;}
i++;
}
}}
voidLastVT(intn)//求LastVT{
charstacksta;
charLodew;
for(inti=0;iF[i].flag=0;
i=0;
Initstack(sta);
while(i<=n)
{
intk=strlen(str[i]);
w.E=str[i][0];
chara=str[i][k-1];
charb=str[i][k-2];
if(!
IsLetter(a))
{
w.e=a;
push(sta,w);
search(w);
i++;
}
elseif(IsLetter(a)&&!
IsLetter(b))
{
w.e=b;
push(sta,w);
search(w);
i++;
}
elsei++;
}
charLodeee;
while(!
IsEmpty(sta))
{
pop(sta,ee);
for(i=0;i<=n;i++)
{
w.E=str[i][0];
if(str[i][3]==ee.E&&str[i][4]=='\0')
{
w.e=ee.e;
push(sta,w);
search(w);
}
}
}
intk=1;i=1;
ppp=0;
while(i{
if(F[i-1].flag==1)
{
brr[ppp][0]=F[i-1].R;
brr[ppp][k]=F[i-1].r;
}
while(F[i].flag==0&&ii++;
if(F[i].flag==1)
{
if(F[i].R==arr[ppp][0])
k++;
else{brr[ppp][k+1]='\0';ppp++;k=1;}
i++;
}
}}
voidcreateYXB(intn)//构造优先表{
inti,j;
for(j=1;j<=kk;j++)
ccrr1[0][j]=r[j-1];
for(i=1;i<=kk;i++)
ccrr2[i][0]=r[i-1];
for(i=1;i<=kk;i++)
for(j=1;j<=kk;j++)
crr[i][j]=0;
intI=0,J=3;
while(I<=n)
{
if(str[I][J+1]=='\0')//扫描右部
{
I++;
J=3;
}
else
{
while(str[I][J+1]!
='\0')
{
charaa=str[I][J];
charbb=str[I][J+1];
if(!
IsLetter(aa)&&!
IsLetter(bb))//优先及等于的情况,用1值表示等于
{
for(i=1;i<=kk;i++)
{
if(ccrr2[i][0]==aa)
break;
}
for(j=1;j<=kk;j++)
{
if(ccrr1[0][j]==bb)
break;
}
if(crr[i][j]==0)
crr[i][j]=1;
else{
FLAG=1;
I=n+1;
}
J++;
}
if(!
IsLetter(aa)&&IsLetter(bb)&&str[I][J+2]!
='\0'&&!
IsLetter(str[I][J+2]))//优先及等于的情况
{
for(i=1;i<=kk;i++)
{
if(ccrr2[i][0]==aa)
break;
}
for(intj=1;j<=kk;j++)
{
if(ccrr1[0][j]==str[I][J+2])
break;
}
if(crr[i][j]==0)
crr[i][j]=1;
else
{
FLAG=1;
I=n+1;
}
}
if(!
IsLetter(aa)&&IsLetter(bb))//优先及小于的情况,用2值表示小于
{
for(i=1;i<=kk;i++)
{
if(aa==ccrr2[i][0])
break;
}
for(j=0;j<=p;j++)
{
if(bb==arr[j][0])
break;
}
for(intmm=1;arr[j][mm]!
='\0';mm++)
{
for(intpp=1;pp<=kk;pp++)
{
if(ccrr1[0][pp]==arr[j][mm])
break;
}
if(crr[i][pp]==0)
crr[i][pp]=2;
else{
FLAG=1;I=n+1;
}
}
J++;
}
if(IsLetter(aa)&&!
IsLetter(bb))//优先及大于的情况,用3值表示大于
{
for(i=1;i<=kk;i++)
{
if(ccrr1[0][i]==bb)
break;
}
for(j=0;j<=ppp;j++)
{
if(aa==brr[j][0])
break;
}
for(intmm=1;brr[j][mm]!
='\0';mm++)
{
for(intpp=1;pp<=kk;pp++)
{
if(ccrr2[pp][0]==brr[j][mm])
break;
}
if(crr[pp][i]==0)
crr[pp][i]=3;
else{FLAG=1;I=n+1;}
}
J++;
}}}}}//judge3是用来返回在归约过程中两个非终结符相比较的值intjudge3(chars,chara){
inti=1,j=1;
while(ccrr2[i][0]!
=s)
i++;
while(ccrr1[0][j]!
=a)
j++;
if(crr[i][j]==3)
return3;
else
if(crr[i][j]==2)
return2;
else
if(crr[i][j]==1)
return1;
else
return0;}voidprint(chars[],charSTR[][20],intq,intu,intii,intk)//打印归约的过程{
cout<
for(inti=0;i<=k;i++)
cout<
cout<<"";
for(i=q;i<=ii;i++)
cout<cout<<"";}
voidprocess(charSTR[][20],intii)//对输入的字符串进行归约的过程{
cout<<"步骤"<<""<<"符号栈"<<""<<"输入串"<<""<<"动作"<intk=0,q=0,u=0,b,i,j;
chars[40],a;
s[k]='#';
print(s,STR,q,u,ii,k);
cout<<"预备"<k++;
u++;
s[k]=STR[0][q];
q++;
print(s,STR,q,u,ii,k);
cout<<"移进"<while(q<=ii)
{
a=STR[0][q];
if(!
IsLetter(s[k]))j=k;
e
|