编译原理实验报告 (1).doc
《编译原理实验报告 (1).doc》由会员分享,可在线阅读,更多相关《编译原理实验报告 (1).doc(30页珍藏版)》请在冰点文库上搜索。
编译原理实验报告
CompilersPrinciplesExperimentReport
所在学院:
所在班级:
学生姓名:
学号:
指导教师:
教务处
2015年12月
词法分析程序
一、实验目的:
设计、编制和调试一个具体的词法分析程序,加深对词法分析的理解。
二、实验要求:
1、通过对PL/0词法分析程序(GETSYS)的分析,编制一个具有以下功能的词法分析程序:
a.输入为字符串(或待进行词法分析的源程序),输出为单词串,即由(单词,类别)所组成的二元组序列;
b.有一定的错误检查能力,例如能发现2a这类
不能作为单词的字符串。
三、实验代码
#defineID12//标识符
#defineINT13//常数
#defineJF14//界符
#defineYSF15//运算符
#defineN30//字符读取的最大长度
charTOKEN[N];
FILE*write;
//查询一个字符串,看其是否与指定的字符相匹配,如果匹配返回1个非零的值,如果不匹配,则返回一个0值*/
intlooksame(char*a)
{
inti;
char*key[22]={"begin","end","if","then","else","for","do","while","and","or","not","BEGIN","END","IF","THEN","ELSE","FOR","DO","WHILE","AND","OR","NOT"};
for(i=0;i<22;i++)
{
if(strcmp(key[i],a)==0)//该字符串是否与关键字相匹配
return(i%11+1);
}
return0;
}
//把a输入到指定文件中,然后从该文件中读出字符串,放到一个数组中输出
voidout(inta,char*b)
{
FILE*write;
write=fopen("E:
\\b.txt","a+");
if(write==NULL)
{
printf("文件打开失败");
exit(0);
}
fprintf(write,"%d\t",a);
fwrite(b,strlen(b),1,write);
fprintf(write,"\n");
fclose(write);
printf("%d%20s\t\t",a,b);
}
interror()
{
printf("书写格式错误,未被识别\n");
return0;
}
voidfunction(FILE*fp)
{
charch='';
inti,c;
while(ch!
=EOF)
{
ch=fgetc(fp);//从文件中读取字符
while(ch==''||ch=='\t'||ch=='\n'){
ch=fgetc(fp);
}
if(isalpha(ch))//isalpha()判断是否为英文字母,是则返回非
零值,否则返回零
{
TOKEN[0]=ch;
ch=fgetc(fp);
i=1;
while(isalnum(ch))//isalnum()判断字符是否为英文字
母或数字,如果是则返回非零值,如果不是则返回零//
{
TOKEN[i]=ch;
i++;
ch=fgetc(fp);
}
TOKEN[i]='\0';
fseek(fp,-1,1);
//用于二进制方式打开的文件,移动文件读写指针位置
c=looksame(TOKEN);
if(c==0)
{
out(ID,TOKEN);printf("标识符\n");
}
else
{
out(c,TOKEN);printf("关键字\n");
}
}
elseif(isdigit(ch))//isdigit()判断是否为0-9的数字
{
TOKEN[0]=ch;
ch=fgetc(fp);
i=1;
while(isdigit(ch))
{
TOKEN[i]=ch;
i++;
ch=fgetc(fp);
}
TOKEN[i]='\0';
fseek(fp,-1,1);
out(INT,TOKEN);
printf("常数\n");
}
else
{
switch(ch)
{
case'+':
out(YSF,"+");printf("运算符\n");
break;
case'-':
out(YSF,"-");printf("运算符\n");
break;
case';':
out(JF,";");printf("界符\n");
break;
case',':
out(JF,",");printf("界符\n");
break;
case'|':
out(YSF,"|");printf("运算符\n");
break;
case'{':
out(JF,"{");printf("界符\n");
break;
case'(':
out(JF,"(");printf("界符\n");
break;
case'!
':
out(JF,"!
");printf("界符\n");
break;
case'^':
out(JF,"^");printf("界符\n");
break;
case')':
out(JF,")");printf("界符\n");
break;
case'}':
out(JF,"}");printf("界符\n");
break;
case'<':
ch=fgetc(fp);
if(ch=='=')
{
out(YSF,"<=");
printf("运算符\n");
}
elseif(ch=='>')
{
out(YSF,"<>");
printf("运算符\n");
}
else
{
fseek(fp,-1,1);
out(YSF,"<");
printf("运算符\n");
}
break;
case'=':
out(YSF,"=");printf("运算符\n");
break;
case'>':
ch=fgetc(fp);
if(ch=='=')
{
out(YSF,">=");
printf("运算符\n");
}
else
{
fseek(fp,-1,1);
out(YSF,">");
printf("运算符\n");
}
break;
case':
':
ch=fgetc(fp);
if(ch=='=')
{
out(YSF,":
=");
printf("运算符\n");
}
else
{
fseek(fp,-1,1);
out(JF,":
");
printf("界符\n");
}
break;
case'/':
ch=fgetc(fp);
if(ch=='*')
{
out(JF,"/*");
printf("界符\n");
while
(1)//注释的内容在词法分析中不显示
while(ch!
='/')
ch=fgetc(fp);
fseek(fp,-2,1);
ch=fgetc(fp);
if(ch=='*')
{
fseek(fp,1,1);
break;
}
else
{
fseek(fp,2,1);
ch=fgetc(fp);
}
fseek(fp,-2,1);
}
else
{
fseek(fp,-1,1);
out(JF,"/");
printf("界符\n");
}
break;
case'*':
ch=fgetc(fp);
if(ch=='/')
{
out(JF,"*/");
printf("界符\n");
}
else
{
fseek(fp,-1,1);
out(YSF,"*");
printf("运算符\n");
}
break;
caseEOF:
break;
default:
error();
break;
}
}
}
}
intmain()
{
FILE*read;
read=fopen("E:
\\a.txt","r");
write=fopen("E:
\\b.txt","a+");
if(read==NULL)
{
printf("FILEOPENFAIL!
");
exit(0);
}
printf("===========================================================\n");
printf("====================词法分析程序===========================\n");
printf("===========该分析程序的文件存放在E:
\\a.txt目录下==========\n");
printf("===========该程序的分析结果存放在E:
\\b.txt目录下===========\n");
printf("============================================================\n");
function(read);
fclose(read);
system("pause");
return0;
}
四、实验截图
a.txtb.txt
基于LL
(1)方法的语法分析程序
一、实验目的
设计、编制和调试一个典型的语法分析方法,进一步掌握常用的语法分析方法。
二、实验要求
1、根据LL
(1)分析法编写一个语法分析程序,可根据自己实际情况,选择以下一项作为分析算法的输入:
a.直接输入根据已知文法构造的分析表M;
b.输入文法的FIRST(α)和FOLLOW(U)集合,由
程序自动生成文法的分析表M;
c.输入已知文法,由程序自动构造文法的分析表M。
2、程序具有通用性
所开发的程序可适用于不同的文法和任意输入串,且能判断该文法是否为LL
(1)文法。
3、有运行实例
对于输入的文法和符号串,所编制的语法分析程序应能正确判断此串是否为文法的句子,并要求输出分析过程。
三、实验代码
#include"stdafx.h"
#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[5];/*产生式右边字符*/
intlength;/*字符个数*/
}type;
typee,t,g,g1,s,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");
}
int_tmain(intargc,_TCHAR*argv[])
{
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;
g1.origin='G';
g1.array[0]='^';
g1.length=1;
s.origin='S';
strcpy(s.array,"*FS");
s.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<=5;n++)
C[m][n].origin='N';/*全部赋为空*/
/*填充分析表*/
C[0][0]=e;C[0][3]=e;
C[1][1]=g;C[1][4]=g1;C[1][5]=g1;
C[2][0]=t;C[2][3]=t;
C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;
C[4][0]=f1;C[4][3]=f;
printf("提示:
本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析,\n");
printf("请输入要分析的字符串:
");
do/*读入分析串*/
{
scanf("%c",&ch);
if((ch!
='i')&&(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<=5;j++)/*判断是否为终结符*/
if(x==v1[j])
{
flag=1;
break;
}
if(flag==1)/*如果是终结符*/
{
if(x=='#')
{
finish=1;/*结束标记*/
printf("acc!
\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<=5;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);
return0;
}
四、实验截图
基于LR(0)方法的语法分析程序
一、实验目的
设计、编制和调试一个典型的语法分析方法,进一步掌握常用的语法分析方法。
二、实验要求
可根据自己实际情况,选择以下一项作为分析算法的输入:
(1)直接输入根据己知文法构造的LR(0)分析表。
(2)输入已知文法的项目集规范族和转换函数,由程序自动生成LR(0)分析表;
(3)输入已知文法,由程序自动生成LR(0)分析表。
三、程序代码
#include"stdafx.h"
#include
#include
#include
#include
usingnamespacestd;
structstack{
inttop;
intst[15];//状态栈
charsn[15];//符号栈
}*sign;
structanalysis{
//动作表结构
charact;
intstatus;
}action[][6]={
{
's',5,'$',0,'$',0,'s',4,'$',0,'$',0
},
{
'$',0,'s',6,'$',0,'$',0,'$',0,'A',0
},
{
'$',0,'r',2,'s',7,'$',0,'r',2,'r',2
},
{
'$',0,'r',4,'r',4,'$',0,'r',4,'r',4
},
{
's',5,'$',0,'$',0,'s',4,'$',0,'$',0
},
{
'$',0,'r',6,'r',6,'$',0,'r',6,'r',6
},
{
's',5,'$',0,'$',0,'s',4,'$',0,'$',0
},
{
's',5,'$',0,'$',0,'s',4,'$',0,'$',0
},
{
'$',0,'s',6,'$',0,'$',0,'s',11,'$',0
},
{
'$',0,'r