语法分析.docx
《语法分析.docx》由会员分享,可在线阅读,更多相关《语法分析.docx(25页珍藏版)》请在冰豆网上搜索。
语法分析
组员
学号
姓名
实验名称
实验二:
语法分析
实验室
实
验
目
的
或
要
求
一、实验目的
根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
也可以采用预测分析方法、算符优先分析方法来进行分析。
具体参照课本上的说明,以下是递归下降分析法的介绍。
二、实验原理
A.算法表达式文法如下:
E->E+T|E-T|T
T->T*F|T/F|F
F->(E)|i
B.要求:
任给一个表达式(含括号嵌套),判断是否合法,如果非法,给出提示(含出错位置)。
C.实现方法:
可以采用LL
(1)分析、递归下降分析、优先分析、LR
(1)分析这四种分析方法中的任意一种方法。
如果用LL
(1)分析,则首先需要消除左递归(改写文法),然后自行构造LL
(1)分析表;如果用递归下降分析,也首先需要消除左递归;优先分析和LR
(1)分析则无需消除左递归。
D.语言环境要求:
可以用任何一种可视化编程的平台开发,基于WEB的也可,要求有界面。
E.递归下降分析法示例:
1.递归下降分析法的功能
词法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。
2.递归下降分析法的前提
改造文法:
消除二义性、消除左递归、提取左因子,判断是否为LL
(1)文法。
3.递归下降分析法实验设计思想及算法
4.递归下降分析法实验设计思想及算法
为G的每个非终结符号U构造一个递归过程,不妨命名为U。
U的产生式的右边指出这个过程的代码结构:
(1)若是终结符号,则和向前看符号对照,若匹配则向前进一个符号;否则出错。
(2)若是非终结符号,则调用与此非终结符对应的过程。
当A的右部有多个产生式时,可用选择结构实现,具体为:
(1)对于每个非终结符号U->u1|u2|…|un处理的方法如下
U()
{
ch=当前符号;
if(ch可能是u1字的开头)处理u1的程序部分;
elseif(ch可能是u2字的开头)处理u2的程序部分;
…..
elseerror();
}
(2)对于每个右部u1->x1x2…xn的处理架构如下:
处理x1的程序;
处理x2的程序;
……
处理xn的程序;
(3)如果非终结符U有空产生式:
Uε,则还需考虑ch属于Follow(U)的情况。
F程序要求:
对算术表达式文法,用递归下降分析法(或预测分析方法、算符优先分析方法等)对任意输入的符号串进行分析,如合法给出相应信息,如果不合法,最好能给出发生错误的位置。
算术表达式至少包含+、-、*、/、()。
例如:
32+123*(34-58/2)
实
验
原
理
(
算
法
流
程
)
自顶向下语法分析法指从文法开始符号出发,企图推导出与输入单词串完全相匹配的句子旺其宗旨在于对任何输入单词串用一切可能的办法,从文法开始符号出发自上而下从左到右为输入串建立分析树,若输入串是给定文法的句子,则必能建立。
其本质是一种试探过程,反复使用不同的产生式谋求与输入串匹配的过程。
算法的关键在于利用堆栈先进后出的功能保留程序正在处理文法规则节点的位置信息,借助于递归算法的递归功能进行穷举试探,使处理流程在进入某条文法规则之后发现该文法规则不符合,可以退出到上一次的情况,对后续的文法规则进行处理。
程
序
界
面
(
效
果
图
)
输入S->a:
输出:
程
序
代
码
#include
#include
#include
typedefstruct
{
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数组中寻找到的终结符与非终结符对的标志位值为1
voidsearch(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;
elsej=k-1;
b=judge3(s[j],a);
if(b==3)//大于的情况进行归约
{
while(IsLetter(s[j-1]))
j--;
for(i=j;i<=k;i++)
s[i]='\0';
k=j;
s[k]='N';
u++;
print(s,STR,q,u,ii,k);
cout<<"归约"<}
elseif(b==2||b==1)//小于或等于的情况移进
{
k++;
s[k]=a;
u++;
q++;
print(s,STR,q,u,ii,k);
if(s[0]=='#'&&s[1]=='N'&&s[2]=='#')
cout<<"接受"<elsecout<<"移进"<}
else
{
cout<<"出错"<break;
}
}
if(s[0]=='#'&&s[1]=='N'&&s[2]=='#')
cout<<"归约成功"<elsecout<<"归约失败"<}
voidmain()
{
intn,i,j;
cout<<"请输入你要定义的文法G的产生式的个数n:
";
cin>>n;
cout<<"请输入文法产生式:
"<for(i=0;i{
gets(str[i]);
j=strlen(str[i]);
str[i][j]='\0';
}
str[i][0]='Q';//最末行添加扩展
str[i][1]='-';
str[i][2]='>';
str[i][3]='#';
str[i][4]=str[0][0];
str[i][5]='#';
cout<<"你定义的产生式如下:
"<str[i][6]='\0';
for(i=0;i<=n;i++)
cout<if(judge1(n)==0)//判断文法G是否为算符文法
cout<<"文法G不是算符文法!
"<if(judge1(n)==1)
{
cout<<"文法G是算符文法!
"<}
createF(n);
FirstVT(n);
LastVT(n);
createYXB(n);
for(i=0;i<=p;i++)//打印FirstVT
{
cout<<"FirstVT("<for(intl=1;arr[i][l+1]!
='\0';l++)
cout<cout<}
cout<<"FirstVT(Q)={#}"<for(i=0;i<=ppp;i++)//打印LastVT
{
cout<<"LastVT("<for(intl=1;brr[i][l+1]!
='\0';l++)
cout<cout<}
cout<<"LastVT(Q)={#}"<cout<<"优先表如下:
"<for(i=1;i{
cout<<"";
cout<}
cout<for(i=1;i{
cout<for(j=1;j{
if(crr[i][j]==0)
cout<<"";
elseif(crr[i][j]==1)
cout<<"=";
elseif(crr[i][j]==2)
cout<<"<";
elseif(crr[i][j]==3)
cout<<">";
cout<<"";
}
cout<}
judge2(n);//判断文