编译原理实验 简单词法分析含源代码和实验结果.docx
- 文档编号:28766124
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:36
- 大小:189.59KB
编译原理实验 简单词法分析含源代码和实验结果.docx
《编译原理实验 简单词法分析含源代码和实验结果.docx》由会员分享,可在线阅读,更多相关《编译原理实验 简单词法分析含源代码和实验结果.docx(36页珍藏版)》请在冰豆网上搜索。
编译原理实验简单词法分析含源代码和实验结果
附录一实验报告样式
《编译原理》实验报告
实验2简单词法分析
姓名陈婷婷学号**********班级计科1001班
时间:
2012/4/5地点:
文波
同组人:
无
指导教师:
***
实验目的
通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;加深对课堂教学的理解;提高词法分析方法的实践能力。
掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法;掌握词法分析的实现方法;上机调试编出的词法分析程序。
实验内容
⑴掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。
⑵掌握词法分析的实现方法。
⑶上机调试编出的词法分析程序。
⑷为简单起见,假设编译语言为具有下特征的C_minus。
该词法分析器要求至少能够识别C_minus中的以下几类单词:
a.关键字:
elseifintreturnvoidwhile共6个,所有的关键字都是保留字,并且必须是小写;
b.标识符:
识别与C语言词法规定相一致的标识符,通过下列正则表达式定义:
ID=letter(letter|digit)*;
c.常数:
NUM=(+|-|ε)digitdigit*(.digitdigit*|ε)(e(+|-|ε)digitdigit*|ε),letter=a|..|z|A|..|Z|,digit=0|..|9,包括整数,如123,-123,+123等;小数,如123.45,+123.45,-123.45;科学计数法表示的常数,如+1.23e3,-2.3e-9;
d.专用符号:
+-*/<<=>>===!
==;,()[]{}/**/;
实验环境
软件:
VC++6.0
实验前准备
1、方案设计:
1准备模拟数据:
本实验中使用“测试文件.c”
②程序思想:
该实验要识别关键字、标识符、常数、专用符号(分界符、算术运算符和关系运算符)。
对于关键字本实验主要识别10个(break、do、elsefloatifintforswitchmainchar),使用的数据结构为:
structKey//用于关键字和标识符及常数,由于常数有科学计数法的表示,所以该实验中把常数当做字符串进行检测输出
{
charname[20];
inti;
intt;
};
Keykeyword[10];//存放10个关键字
然后在函数voidinitial()对Keykeyword[10]进行初始化。
函数intsearch_key(char*teststring,FILE*f)用来将识别到的以字母开头的字符串teststring与定义的关键字一一比较,如果是关键字则把它写入文件f中,否则在检验是否是标识符;如果是关键字则返回1,否则返回0.
对与标识符和常数,使用的数据结构是一样的,这是因为识别一个标识符和识别一个常数都是要读入多个字符才能识别一个完整的,而且标识符表和常数表都是在识别过程中建立的,都所以用到的数据结构为:
structKey//用于关键字和标识符及常数
{
charname[20];
inti;
intt;
};
structkey_infor//记录标识符表,常数表的相关信息
{
structKey*head;
intkey_length;
};
识别到一个以字母开头的符号串后如果不是关键字,就调用voidsearch_table(char*teststring,key_infor*p,FILE*f)与已经识别到的标识符一一比较,如果是新的则赋予新的i值并打印输出到屏幕并且写入f中(只要是标志符就写入文件f中)。
Main()中将识别到的标识符(不重复)写入另外的文件中。
search_table中关键部分如下:
while(j
{
j++;
}//与已有的标识符一一比较
if(j==i)//说明是新的标识符
{
strcpy(point[j].name,teststring);
p->key_length++;
point[j].i=j;
point[j].t=6;
}
识别到一个完整的常数则进行与标识符相似的处理,voidsearch_number(char*teststring,key_infor*p,FILE*f)的思想与voidsearch_table(char*teststring,key_infor*p,FILE*f)的基本一致。
Main()中将识别到的常数(不重复)写入另外的文件中。
如果既不是字母开头也不是数字开头,则调用voidsearch_sign(charx,FILE*file,FILE*f),该函数实现对专用符号的识别,并把识别到的专用符号写入文件f中。
该实验有六个输出文件,存放输出结果。
其中与标志符相关的有两个,一个存放识别到的所有标识符(有重复,即测试文件中的所有标识符),一个存放不重复的(重复的只存一次),与常数相关的文件类似也2个,另外的的两个分别存放识别到的专用符号和关键字。
2、程序设计
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
structKey//用于关键字和标识符及常数,由于常数有科学计数法的表示,所以该实验中把常数当做字符串进行检测输出
{
charname[20];
inti;
intt;
};
Keykeyword[10];//存放10个关键字
structkey_infor//记录标识符表,常数表的相关信息
{
structKey*head;
intkey_length;
};
structop//用于除关系运算符以外的专用符号
{
charmark;
intii;
inttt;
};
opseperateop[8];
opmathop[4];
structreop//用于除关系运算符以外的专用符号
{
charremark[3];
intiii;
intttt;
};
reoprelatop[8];
chara[10]={',',';','.','=','(',')','{','}','[',']'};//分界符
charb[4]={'+','-','*','/'};//算术运算符
charsignal[8][4]={"<","<=","=",">",">=","<>","==","!
="};
voidinitial()//初始化关键字表分界符表算术运算符表关系运算符表
{
for(intj=0;j<10;j++)//初始化关键字表
{
keyword[j].t=1;
keyword[j].i=j;
}
strcpy(keyword[0].name,"break");
strcpy(keyword[1].name,"do");
strcpy(keyword[2].name,"else");
strcpy(keyword[3].name,"float");
strcpy(keyword[4].name,"if");
strcpy(keyword[5].name,"int");
strcpy(keyword[6].name,"for");
strcpy(keyword[7].name,"switch");
strcpy(keyword[8].name,"main");
strcpy(keyword[9].name,"char");
printf("以下是可以识别的关键字内部表示\n");
printf("关键字i值t值\n");
for(intk=0;k<10;k++)
{
printf("%s\t",keyword[k].name);
printf("%d\t",keyword[k].i);
printf("%d\n",keyword[k].t);
}
for(intm=0;m<10;m++)//初始化分界符表
{
seperateop[m].mark=a[m];
seperateop[m].ii=m;
seperateop[m].tt=2;
}
printf("以下是可以识别的分界符内部表示\n");
printf("分界符i值t值\n");
for(intn=0;n<10;n++)
{
printf("%c\t",seperateop[n].mark);
printf("%d\t",seperateop[n].ii);
printf("%d\n",seperateop[n].tt);
}
for(intp=0;p<4;p++)//初始化算术运算符表
{
mathop[p].mark=b[p];
mathop[p].ii=p+16;//先用十进制表示
mathop[p].tt=3;
}
printf("以下是可以识别的算术运算符内部表示\n");
printf("算术运算符i值t值\n");
for(intq=0;q<4;q++)
{
printf("%c\t\t",mathop[q].mark);
printf("%d\t",mathop[q].ii);//查如何用十六进制输出
printf("%d\n",mathop[q].tt);
}
for(intr=0;r<8;r++)//初始化关系运算符表
{
strcpy(relatop[r].remark,signal[r]);
relatop[r].iii=r;//这里用十进制表示
relatop[r].ttt=4;
}
printf("以下是可以识别的关系运算符内部表示\n");
printf("关系运算符i值t值\n");
for(ints=0;s<8;s++)
{
printf("%s\t\t",relatop[s].remark);
printf("%d\t",relatop[s].iii);//查如何用十六进制输出
printf("%d\n",relatop[s].ttt);
}
}
intsearch_key(char*teststring,FILE*f)//设置返回值用于确定是否需要检验是不是标识符
{//检测是否为关键字,如果是则写入关键字文件中
intj=0;
inti=10;
while(j
{
j++;
}//与关键字一一比较
if(j==i)//不是关键字则返回
return0;
else//是关键字打印该关键字并将该关键字写入文件
{
printf("%s是关键字,i=%d,t=%d\n",keyword[j].name,keyword[j].i,keyword[j].t);
}
fprintf(f,"%s\t%5d\%5d\n",keyword[j].name,keyword[j].i,keyword[j].t);//将识别到的关键字写入文件f中
return1;
}
voidsearch_table(char*teststring,key_infor*p,FILE*f)//查填符号表函数,p为指向结构体的指针
{
inti=p->key_length;//i记录标识符表的长度
intj=0;
Key*point;
point=p->head;
while(j
{
j++;
}//与已有的标识符一一比较
if(j==i)//说明是新的标识符
{
strcpy(point[j].name,teststring);
p->key_length++;
point[j].i=j;
point[j].t=6;
}
printf("%s是标志符,i=%d,t=%d\n",point[j].name,point[j].i,point[j].t);
fprintf(f,"%s\t%5d\t%5d\n",point[j].name,point[j].i,point[j].t);//将新的标识符写入标识符文件f中
return;
}
voidsearch_number(char*teststring,key_infor*p,FILE*f)//查填常数表函数,p为指向结构体的指针
{
inti=p->key_length;//i记录常数表的长度
intj=0;
Key*point;
point=p->head;
while(j
{
j++;
}//与已有的标识符一一比较
if(j==i)//说明是新的标识符
{
strcpy(point[j].name,teststring);
p->key_length++;
point[j].i=j;
point[j].t=5;
}
printf("%s是常数,i=%d,t=%d\n",point[j].name,point[j].i,point[j].t);
fprintf(f,"%s\t%5d\t%5d\n",point[j].name,point[j].i,point[j].t);//将新的常数写入文件f中
return;
}
Voidsearch_sign(charx,FILE*file,FILE*f)
{//检测是否为专用符号
intj=0;
chartemp=x;
while(j<10&&x!
=seperateop[j].mark)//检测是否为分界符
{
j++;
}//与定义的8个分隔符一一比较
if(j<10)//是分隔符
{
printf("%c是分界符,i=%d,t=%d\n",seperateop[j].mark,seperateop[j].ii,seperateop[j].tt);
fprintf(f,"%c\t%d\t%d\n",seperateop[j].mark,seperateop[j].ii,seperateop[j].tt);//将识别到的分隔符写入文件f中
}
else//不是分界符,就把j赋值0,与算术运算符比较
{
j=0;
while(j<4&&x!
=mathop[j].mark)
{
j++;
}//与定义的4个算术运算符一一比较
if(j<4)//是算术运算符
{
printf("%c是算术运算符,i=%d,t=%d\n",mathop[j].mark,mathop[j].ii,mathop[j].tt);
fprintf(f,"%c\t%d\t%d\n",mathop[j].mark,mathop[j].ii,mathop[j].tt);//将识别到的算术运算符写入文件f中
}
else
switch(x)
{
case'>':
{
x=fgetc(file);
if(x=='=')
{
printf("%s是关系运算符,i=%d,t=%d\n",relatop[4].remark,relatop[4].iii,relatop[4].ttt);
fprintf(f,"%s\t%d\t%d\n",relatop[4].remark,relatop[4].iii,relatop[4].ttt);//将识别到的关系运算符写入文件f中
break;
}
else
{
fseek(file,-1L,SEEK_CUR);
x=temp;
printf("%s是关系运算符,i=%d,t=%d\n",relatop[3].remark,relatop[3].iii,relatop[3].ttt);
fprintf(f,"%s\t%d\t%d\n",relatop[3].remark,relatop[3].iii,relatop[3].ttt);//将识别到的关系运算符写入文件f中
break;
}
}
case'<':
{
x=fgetc(file);
if(x=='=')
{
printf("%s是关系运算符,i=%d,t=%d\n",relatop[1].remark,relatop[1].iii,relatop[1].ttt);
fprintf(f,"%s\t%d\t%d\n",relatop[1].remark,relatop[1].iii,relatop[1].ttt);//将识别到的关系运算符写入文件f中
break;
}
elseif(x=='>')
{
printf("%s是关系运算符,i=%d,t=%d\n",relatop[5].remark,relatop[5].iii,relatop[5].ttt);
fprintf(f,"%s\t%d\t%d\n",relatop[5].remark,relatop[5].iii,relatop[5].ttt);//将识别到的关系运算符写入文件f中
break;
}
else
{
fseek(file,-1L,SEEK_CUR);
x=temp;
printf("%s是关系运算符,i=%d,t=%d\n",relatop[0].remark,relatop[0].iii,relatop[0].ttt);
fprintf(f,"%s\t%d\t%d\n",relatop[0].remark,relatop[0].iii,relatop[0].ttt);//将识别到的关系运算符写入文件f中
break;
}
}
case'=':
{
x=fgetc(file);
if(x=='=')
{
printf("%s是关系运算符,i=%d,t=%d\n",relatop[6].remark,relatop[6].iii,relatop[6].ttt);
fprintf(f,"%s\t%d\t%d\n",relatop[6].remark,relatop[6].iii,relatop[6].ttt);//将识别到的关系运算符写入文件f中
break;
}
else
{
fseek(file,-1L,SEEK_CUR);
x=temp;
printf("%s是关系运算符,i=%d,t=%d\n",relatop[2].remark,relatop[2].iii,relatop[2].ttt);
fprintf(f,"%s\t%d\t%d\n",relatop[2].remark,relatop[2].iii,relatop[2].ttt);//将识别到的关系运算符写入文件f中
break;
}
}
case'!
':
{
x=fgetc(file);
if(x=='=')
{
printf("%s是关系运算符,i=%d,t=%d\n",relatop[7].remark,relatop[7].iii,relatop[7].ttt);
fprintf(f,"%s\t%d\t%d\n",relatop[7].remark,relatop[7].iii,relatop[7].ttt);//将识别到的关系运算符写入文件f中
break;
}
}
}
}
return;
}
voidmain()
{
charreadchar;
charteststr[20];//存放标识符
charlinkstr[2]={0};//用于把字符readchar连接到teststr
initial();
FILE*key_result;//新建并打开关键字结果.txt文件
key_result=fopen("关键字结果.txt","w+");
fprintf(key_result,"关键字\ti值t值\n");
FILE*table_result;//新建并打开文件
table_result=fopen("标识符结果.txt","w+");
fprintf(table_result,"标识符\ti值t值\n");
key_inforinformation;//用于指向符号表
Keymark[400];//定义符号表最多可以有400个符号
information.head=mark;
information.key_length=0;
key_infornuminformation;//用于指向常数表
Keynummark[400];//定义符号表最多可以有400个符号
numinformation.head=nummark;
numinformation.key_length=0;
FILE*sign_result;//新建并打开专用符号结果.txt文件
sign_result=fopen("专用符号结果.txt","w+");
fprintf(sign_result,"专用符号\ti值\tt值\n");
FILE*number_result;//新建并打开常数结果.txt文件
number_result=fopen("常数结果.txt","w+");
fprintf(number_result,"常数\ti值t值\n");
FILE*fp;
fp=fopen("测试文件.c","r");
if(fp==NULL)
{
printf("打开文件失败!
");
exit(0);
}//打开测试文件fp
readchar=fgetc(fp);
while(readchar!
=EOF)
{
teststr[0]=0;
if(readchar<='z'&&readchar>='a'||r
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译原理实验 简单词法分析含源代码和实验结果 编译 原理 实验 简单 词法 分析 源代码 结果