编译原理 简单样本语言的语法分析器2.docx
《编译原理 简单样本语言的语法分析器2.docx》由会员分享,可在线阅读,更多相关《编译原理 简单样本语言的语法分析器2.docx(24页珍藏版)》请在冰豆网上搜索。
编译原理简单样本语言的语法分析器2
昆明理工大学信息工程与自动化学院学生实验报告
(2012—2013学年第1学期)
课程名称:
编译原理开课实验室:
信自楼44年月日
年级、专业、班
学号
姓名
成绩
实验项目名称
简单样本语言的语法分析器
指导教师
李亚
教师评语
该同学是否了解实验原理:
A.了解□B.基本了解□C.不了解□
该同学的实验能力:
A.强□B.中等□C.差□
该同学的实验是否达到要求:
A.达到□B.基本达到□C.未达到□
实验报告是否规范:
A.规范□B.基本规范□C.不规范□
实验过程是否详细记录:
A.详细□B.一般□C.没有□
教师签名:
年月日
一、实验目的及内容
实现下述我们定义的语言语法分析器。
这种语言的程序结构很简单,语法相当于c的函数体,即由一对大括号括起来的语句序列,没有过程或函数。
声明语句、表达式语句及控制语句的写法都与c类似,但规定:
一条声明语句只能声明一个整型变量,没有数组;控制语句只是if、for和while三个语句,这三个语句本身也可以包含语句序列;表达式仅局限于布尔表达式和整型算术表达式,布尔表达式由对两个算术表达式的比较组成,该比较使用<,>,<=,>=,==,!
=比较运算符;算术表达式可以包括整型常数、变量以及+,-,*,/这四个运算符。
另外,还可以有复合语句。
用read和write语句实现输入输出。
注释用/*和*/括起来,但注释不能嵌套
二、实验原理及基本技术路线图(方框原理图或程序流程图)
对给定的程序通过语法分析器弄够识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。
而本程序则是通过对给定路径的文件的分析后以单词符号和文字提示显示。
流程图:
词法分析器产生下述语言的单词序列
这个语言的所有的单词符号,以及它们的种别编码和内部值如下表:
单词符号
种别编码
助记符
内码值
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看成一个标识符。
三、所用仪器、材料(设备名称、型号、规格等或使用软件)
Windows下的visualc++6.0;
四、实验方法、步骤(或:
程序代码或操作过程)
代码:
#include"stdlib.h"
#include"stdio.h"
#include"string.h"
#include
typedefstruct
{
charR;
charr;
intflag;
}array;
arrayF[30];
typedefstruct
{
charE;
chare;
}charLode;
typedefstruct
{
charLode*base;
inttop;
}charstack;
charstr[80][80],arr[80][80],brr[80][80];
intm,kk,p,ppp,FF=1;
charr[20];
intcrr[30][30],FLAG=0;
charccrr1[1][30],ccrr2[30][1];
voidInitstack(charstack*s)
{
s->base=(charLode*)malloc(30*sizeof(charLode));
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;
}
intjudge1(intn)
{
intj=3,flag=1,i;
for(i=0;i<=n;i++)
while(str[i][j]!
='\0')
{
chara=str[i][j];
charb=str[i][j+1];
if(IsLetter(a)&&IsLetter(b))
{
flag=0;
break;
}
else
j++;
}
returnflag;
}
voidjudge2(intn)
{
inti;
for(i=0;i<=n;i++)
if(str[i][3]=='~'||judge1(n)==0||FLAG==1)
{
printf("语法G不是操作符优先级的语法!
\n");
FF=0;
break;
}
if(i>n)
printf("语法G是操作符优先级的语法!
\n");
}
intsearch1(charr[],intkk,chara)
{
inti;
for(i=0;iif(r[i]==a)
break;
if(i==kk)
return0;
else
return1;
}
voidcreateF(intn)
{
intk=0,i=1;
charc;
intj;
chart[10];
t[0]=str[0][0];
while(i<=n)
{
if(t[k]!
=str[i][0])
{
k++;
t[k]=str[i][0];
i++;
}
else
i++;
}
kk=0;
for(i=0;i<=n;i++)
{
j=3;
while(str[i][j]!
='\0')
{
c=str[i][j];
if(IsLetter(c)==0)
{
if(!
search1(r,kk,c))
r[kk]=c;
kk++;
}
j++;
}
}
m=0;
for(i=0;ifor(j=0;j{
F[m].R=t[i];
F[m].r=r[j];
F[m].flag=0;
m++;
}
}
voidsearch(charLodew)
{
inti;
for(i=0;iif(F[i].R==w.E&&F[i].r==w.e)
{
F[i].flag=1;
break;
}
}
voidFirstVT(intn)
{
charstacksta;
charLodeww;
charLodew;
inti=0,k;
chara,b;
Initstack(&sta);
while(i<=n)
{
k=3;
w.E=str[i][0];
a=str[i][k];
b=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++;
}
else
i++;
}
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;
}
elseif(str[i][3]==ww.E&&w.E!
=ww.E)
{
w.e=ww.e;
push(&sta,w);
search(w);
break;
}
}
}
p=0;
k=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)
{
charstacksta;
charLodew;
charLodeee;
chara,b;
intk,i;
for(i=0;iF[i].flag=0;
i=0;
Initstack(&sta);
while(i<=n)
{
intk=strlen(str[i]);
w.E=str[i][0];
a=str[i][k-1];
b=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++;
}
else
i++;
}
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);
}
}
}
k=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;
intI,mm,pp,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;
I=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))
{
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(j=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))
{
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(mm=1;arr[j][mm]!
='\0';mm++)
{
for(pp=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))
{
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(mm=1;brr[j][mm]!
='\0';mm++)
{
for(pp=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++;
}
}
}
}
}
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;
elseif(crr[i][j]==2)
return2;
elseif(crr[i][j]==1)
return1;
elsereturn0;
}
voidprint(chars[],charSTR[][20],intq,intu,intii,intk)
{
inti;
printf("%d\t\t",u);
for(i=0;i<=k;i++)
printf("%c",s[i]);
printf("\t\t");
for(i=q;i<=ii;i++)
printf("%c",STR[0][i]);
printf("\t\t");
}
voidprocess(charSTR[][20],intii)
{
intk=0,q=0,u=0,b,i,j;
chars[40],a;
printf("step\t\tcharstack\tinputstring\tAction\n");
s[k]='#';
print(s,STR,q,u,ii,k);
printf("ready\n");
k++;
u++;
s[k]=STR[0][q];
q++;
print(s,STR,q,u,ii,k);
printf("shift\n");
while(q<=ii)
{
a=STR[0][q];
if(!
IsLetter(s[k]))
j=k;
else
j=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]='G';u++;
print(s,STR,q,u,ii,k);
printf("减小\n");
}
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]=='#')
printf("shift\n");
else
printf("接受\n");
}
else
{
printf("错误\n");
break;
}
}
if(s[0]=='#'&&s[1]=='N'&&s[2]=='#')
printf("还原成功\n");
else
printf("还原失败\n");
}
voidmain()
{
intn,i,j,o;
intii;
printf("请输入定义的语法G的数量:
");
scanf("%d",&n);
printf("请输入语法G");
printf("\n");
for(i=0;i{
scanf("%s",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]='#';
str[i][6]='\0';
printf("你定义的风格如下:
\n");
for(i=0;i<=n;i++)
printf("%s\n",str[i]);
if(judge1(n)==0)
printf(语法G不是操作符语法!
\n");
if(judge1(n)==1)
{
printf("语法G是操作符优先级语法!
\n");
createF(n);
FirstVT(n);
LastVT(n);
createYXB(n);
}
judge2(n);
if(FLAG==0)
{
for(i=0;i<=p;i++)
{
printf("FirstVT(%c)={",arr[i][0]);
for(o=1;arr[i][o+1]!
='\0';o++)
printf("%c,",arr[i][o]);
printf("%c}\n",arr[i][o]);
}
}
printf("FirstVT(Q)={#}\n");
for(i=0;i<=ppp;i++)
{
printf("LastVT(%c)={",arr[i][0]);
for(o=1;brr[i][o+1]!
='\0';o++)
printf("%c,",brr[i][o]);
printf("%c}\n",brr[i][o]);
}
printf("LastVT(Q)={#}\n");
printf("优先表如下:
\n");
for(i=1;i{
printf("");
printf("%c",ccrr1[0][i]);
}
printf("\n");
for(i=1;i{
printf("%c",ccrr2[i][0]);
for(j=1;j{
if(crr[i][j]==0)
printf("");
elseif(crr[i][j]==1)
printf("=");
elseif(crr[i][j]==2)
printf("<");
elseif(crr[i][j]==3)
printf(">");
printf("");
}
printf("\n");
}
if(FF==1)
{
charSTR[1][20];
printf("请输入字符串的法令:
\n");
scanf("%s",STR[0]);
//getchar();
//gets(STR[0]);
ii=strlen(STR[0]);
STR[0][ii]='#';
printf("分析如下:
\n");
process(STR,ii);
}
}
五、实验过程原始记录(测试数据、图表、计算等)
六、实验结果、分析和结论(误差分析与数据处理、成果总结等。
其中,绘制曲线图时必须用计算纸或程序运行