LL1分析法.docx
- 文档编号:9526097
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:43
- 大小:360.65KB
LL1分析法.docx
《LL1分析法.docx》由会员分享,可在线阅读,更多相关《LL1分析法.docx(43页珍藏版)》请在冰豆网上搜索。
LL1分析法
编译原理
实
验
报
告
日期:
班级:
题目:
LL
(1)分析法
组员:
LL
(1)语法分析程序
1.实验目的:
1.根据某一文法编制调试LL
(1)分析程序,以便对任意输入的符号串进行分析。
2.本次实验的目的主要是加深对预测分析LL
(1)分析法的理解。
2.实验平台
Windows+VC+Win32Console
范例程序:
“3-LL1.c”
3.实验内容
1.在范例程序的基础上完善功能
对下列文法,用LL
(1)分析法对任意输入的符号串进行分析:
(1)E→TG
(2)G→+TG|—TG
(3)G→ε
(4)T→FS
(5)S→*FS|/FS
(6)S→ε
(7)F→(E)
(8)F→i
程序输入/输出示例:
程序现有功能:
输入:
一个以#结束的符号串(包括+*()i#):
例如:
i+i*i#
步骤
分析栈
剩余输入串
所用产生式
1
#E
i+i*i#
E→TG
输出:
只能输出步骤1,格式如下:
程序目前还不能对所有输入串进行正确的分析.
需要完善的功能:
(1)请输出完整的分析过程。
即详细输出每一步骤分析栈和剩余串的变化情况,及每一步所用的产生式.
(2)请输出最终的分析结果,即输入串“合法”或“非法”.
(3)示例程序只能完成+、*、(、)的语法分析,请加入-和/的语法分析
(4)可将测试用的表达式事先放在文本文件中,一行存放一个表达式,以分号分割。
同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;
备注:
1.在“所用产生式”一列中,
如果对应有推导,则写出所用产生式;如果为匹配终结符,则写明匹配的终结符;
如分析异常出错则,写为“分析出错”;如成功结束则写为“分析成功”。
2.对一个新的文法实现LL
(1)分析。
4.程序代码
第一种文法
#include
#include
#include
#include
charA[20];/*分析栈*/
charB[20];/*剩余串*/
charv1[20]={'i','+','-','*','/','(',')','#'};/*终结符*/
charv2[20]={'E','G','T','S','F'};/*非终结符*/
intj=0,b=0,top=0,l;/*L为输入串长度*/
typedefstructtype/*产生式类型定义*/
{
charorigin;/*大写字符*/
chararray[7];/*产生式右边字符*/
intlength;/*字符个数*/
}type;
typee,t,g,g0,g1,s,s0,s1,f,f1;/*结构体变量*/
typeC[10][10];/*预测分析表*/
voidprint()/*输出分析栈*/
{
inta;/*指针*/
for(a=0;a<=top+1;a++)
printf("%c",A[a]);
printf("\t\t");
}/*print*/
voidprint1()/*输出剩余串*/
{
intj;
for(j=0;j
printf("");
for(j=b;j<=l;j++)
printf("%c",B[j]);
printf("\t\t\t");
}/*print1*/
voidmain()
{
intm,n,k=0,flag=0,finish=0;
charch,x;
typecha;/*用来接受C[m][n]*/
/*把文法产生式赋值结构体*/
e.origin='E';
strcpy(e.array,"TG");
e.length=2;
t.origin='T';
strcpy(t.array,"FS");
t.length=2;
g.origin='G';
strcpy(g.array,"+TG");
g.length=3;
g0.origin='G';
strcpy(g0.array,"-TG");
g0.length=3;
g1.origin='G';
g1.array[0]='^';
g1.length=1;
s.origin='S';
strcpy(s.array,"*FS");
s.length=3;
s0.origin='S';
strcpy(s0.array,"/FS");
s0.length=3;
s1.origin='S';
s1.array[0]='^';
s1.length=1;
f.origin='F';
strcpy(f.array,"(E)");
f.length=3;
f1.origin='F';
f1.array[0]='i';
f1.length=1;
for(m=0;m<=4;m++)/*初始化分析表*/
for(n=0;n<=7;n++)
C[m][n].origin='N';/*全部赋为空*/
/*填充分析表*/
C[0][0]=e;C[0][5]=e;
C[1][1]=g;
C[1][2]=g0;
C[1][6]=g1;C[1][7]=g1;
C[2][0]=t;C[2][5]=t;
C[3][1]=s1;C[3][2]=s1;C[3][3]=s;
C[3][4]=s0;
C[3][6]=s1;C[3][7]=s1;
C[4][0]=f1;C[4][5]=f;
printf("提示:
本程序只能对由'i','+','-','*','/','(',')'构成的以'#'结束的字符串进行分析,\n");
printf("请输入要分析的字符串:
\n");
do/*读入分析串*/
{
scanf("%c",&ch);
if((ch!
='i')&&(ch!
='+')&&(ch!
='-')&&(ch!
='*')&&(ch!
='/')&&(ch!
='(')&&(ch!
=')')&&(ch!
='#'))
{
printf("输入串中有非法字符\n");
exit
(1);
}
B[j]=ch;
j++;
}while(ch!
='#');
l=j;/*分析串长度*/
ch=B[0];/*当前分析字符*/
A[top]='#';A[++top]='E';/*'#','E'进栈*/
printf("步骤\t\t分析栈\t\t剩余字符\t\t所用产生式\n");
do
{
x=A[top--];/*x为当前栈顶字符*/
printf("%d",k++);
printf("\t\t");
for(j=0;j<=7;j++)/*判断是否为终结符*/
if(x==v1[j])
{
flag=1;
break;
}
if(flag==1)/*如果是终结符*/
{
if(x=='#')
{
finish=1;/*结束标记*/
printf("合法\n");/*接受*/
getchar();
getchar();
exit
(1);
}/*if*/
if(x==ch)
{
print();
print1();
printf("%c匹配\n",ch);
ch=B[++b];/*下一个输入字符*/
flag=0;/*恢复标记*/
}/*if*/
else/*出错处理*/
{
print();
print1();
printf("%c出错\n",ch);/*输出出错终结符*/
exit
(1);
}/*else*/
}/*if*/
else/*非终结符处理*/
{
for(j=0;j<=4;j++)
if(x==v2[j])
{
m=j;/*行号*/
break;
}
for(j=0;j<=7;j++)
if(ch==v1[j])
{
n=j;/*列号*/
break;
}
cha=C[m][n];
if(cha.origin!
='N')/*判断是否为空*/
{
print();
print1();
printf("%c->",cha.origin);/*输出产生式*/
for(j=0;j printf("%c",cha.array[j]); printf("\n"); for(j=(cha.length-1);j>=0;j--)/*产生式逆序入栈*/ A[++top]=cha.array[j]; if(A[top]=='^')/*为空则不进栈*/ top--; }/*if*/ else/*出错处理*/ { print(); print1(); printf("%c出错\n",x);/*输出出错非终结符*/ exit (1); }/*else*/ }/*else*/ }while(finish==0); }/*main*/ 测试一 (1)测试i+i# (2)测试i-i (3)测试i*i# (4)测试i/i# (5)测试i+i*i# (6)测试输入非法字符i+i*# 第二中文发 #include #include #include /*******************************************/ intcount=0;/*分解的产生式的个数*/ intnumber;/*所有终结符和非终结符的总数*/ charstart;/*开始符号*/ chartermin[50];/*终结符号*/ charnon_ter[50];/*非终结符号*/ charv[50];/*所有符号*/ charleft[50];/*左部*/ charright[50][50];/*右部*/ charfirst[50][50],follow[50][50];/*各产生式右部的FIRST和左部的FOLLOW集合*/ charfirst1[50][50];/*所有单个符号的FIRST集合*/ charselect[50][50];/*各单个产生式的SELECT集合*/ charf[50],F[50];/*记录各符号的FIRST和FOLLOW是否已求过*/ charempty[20];/*记录可直接推出^的符号*/ charTEMP[50];/*求FOLLOW时存放某一符号串的FIRST集合*/ intvalidity=1;/*表示输入文法是否有效*/ intll=1;/*表示输入文法是否为LL (1)文法*/ intM[20][20];/*分析表*/ charchoose;/*用户输入时使用*/ charempt[20];/*求_emp()时使用*/ charfo[20];/*求FOLLOW集合时使用*/ /******************************************* 判断一个字符是否在指定字符串中 ********************************************/ intin(charc,char*p) { inti; if(strlen(p)==0) return(0); for(i=0;;i++) { if(p[i]==c) return (1);/*若在,返回1*/ if(i==strlen(p)) return(0);/*若不在,返回0*/ } } /******************************************* 得到一个不是非终结符的符号 ********************************************/ charc() { charc='A'; while(in(c,non_ter)==1) c++; return(c); } /******************************************* 分解含有左递归的产生式 ********************************************/ voidrecur(char*point) {/*完整的产生式在point[]中*/ intj,m=0,n=3,k; chartemp[20],ch; ch=c();/*得到一个非终结符*/ k=strlen(non_ter); non_ter[k]=ch; non_ter[k+1]='\0'; for(j=0;j<=strlen(point)-1;j++) { if(point[n]==point[0]) {/*如果'|'后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++) { while(point[j]! ='|'&&point[j]! ='\0') temp[m++]=point[j++]; left[count]=ch; memcpy(right[count],temp,m); right[count][m]=ch; right[count][m+1]='\0'; m=0; count++; if(point[j]=='|') { n=j+1; break; } } } else {/*如果'|'后的首符号和左部不同*/ left[count]=ch; right[count][0]='^'; right[count][1]='\0'; count++; for(j=n;j<=strlen(point)-1;j++) { if(point[j]! ='|') temp[m++]=point[j]; else { left[count]=point[0]; memcpy(right[count],temp,m); right[count][m]=ch; right[count][m+1]='\0'; printf("count=%d",count); m=0; count++; } } left[count]=point[0]; memcpy(right[count],temp,m); right[count][m]=ch; right[count][m+1]='\0'; count++; m=0; } } } /******************************************* 分解不含有左递归的产生式 ********************************************/ voidnon_re(char*point) { intm=0,j; chartemp[20]; for(j=3;j<=strlen(point)-1;j++) { if(point[j]! ='|') temp[m++]=point[j]; else { left[count]=point[0]; memcpy(right[count],temp,m); right[count][m]='\0'; m=0; count++; } } left[count]=point[0]; memcpy(right[count],temp,m); right[count][m]='\0'; count++; m=0; } /******************************************* 读入一个文法 ********************************************/ chargrammer(char*t,char*n,char*left,charright[50][50]) { charvn[50],vt[50]; chars; charp[50][50]; inti,j,k; printf("\n请输入文法的非终结符号串: "); scanf("%s",vn); getchar(); i=strlen(vn); memcpy(n,vn,i); n[i]='\0'; printf("请输入文法的终结符号串: "); scanf("%s",vt); getchar(); i=strlen(vt); memcpy(t,vt,i); t[i]='\0'; printf("请输入文法的开始符号: "); scanf("%c",&s); getchar(); printf("请输入文法产生式的条数: "); scanf("%d",&i); getchar(); for(j=1;j<=i;j++) { printf("请输入文法的第%d条(共%d条)产生式: ",j,i); scanf("%s",p[j-1]); getchar(); } for(j=0;j<=i-1;j++) if(p[j][1]! ='-'||p[j][2]! ='>') {printf("\ninputerror! "); validity=0; return('\0'); }/*检测输入错误*/ for(k=0;k<=i-1;k++) {/*分解输入的各产生式*/ if(p[k][3]==p[k][0]) recur(p[k]); else non_re(p[k]); } return(s); } /******************************************* 将单个符号或符号串并入另一符号串 ********************************************/ voidmerge(char*d,char*s,inttype) {/*d是目标符号串,s是源串,type=1,源串中的'^'一并并入目串; type=2,源串中的'^'不并入目串*/ inti,j; for(i=0;i<=strlen(s)-1;i++) { if(type==2&&s[i]=='^') ; else { for(j=0;;j++) { if(j break; if(j==strlen(d)) { d[j]=s[i]; d[j+1]='\0'; break; } } } } } /******************************************* 求所有能直接推出^的符号 ********************************************/ voidemp(charc) {/*即求所有由'^'推出的符号*/ chartemp[10]; inti; for(i=0;i<=count-1;i++) { if(right[i][0]==c&&strlen(right[i])==1) { temp[0]=left[i]; temp[1]='\0'; merge(empty,temp,1); emp(left[i]); } } } /******************************************* 求某一符号能否推出'^' ********************************************/ int_emp(charc) {/*若能推出,返回1;否则,返回0*/ inti,j,k,result=1,mark=0; chartemp[20]; temp[0]=c; temp[1]='\0'; merge(empt,temp,1); if(in(c,empty)==1) return (1); for(i=0;;i++) { if(i==count) return(0); if(left[i]==c)/*找一个左部为c的产生式*/ { j=strlen(right[i]);/*j为右部的长度*/ if(j==1&&in(right[i][0],empty)==1) return (1); elseif(j==1&&in(right[i][0],termin)==1) return(0); else { for(k=0;k<=j-1;k++) if(in(right[i][k],empt)==1) mark=1; if(mark==1) continue; else { for(k=0;k<=j-1;k++) { result*=_emp(right[i][k]); temp[0]=right[i][k]; temp[1]='\0'; merge(empt,temp,1); } } } if(result==0&&i continue; elseif(result==1&&i return (1); } } } /******************************************* 判断读入的文法是否正确 *******
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- LL1 分析