词法分析程序构造原理与实现技术实验报告文档.docx
《词法分析程序构造原理与实现技术实验报告文档.docx》由会员分享,可在线阅读,更多相关《词法分析程序构造原理与实现技术实验报告文档.docx(18页珍藏版)》请在冰豆网上搜索。
词法分析程序构造原理与实现技术实验报告文档
词法分析程序构造原理与实现技术
实验报告
变更说明
日期
版本
变更位置
变更说明
作者
2014/4/9
1.0
初稿生成
房皓
2014/4/9
1.0
完善
截稿
房皓
一、实验目的:
本实验的目的在于在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握编译程序设计和构造的基本原理和实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神和专业素养,从而提高学生发现问题、分析问题和解决问题的能力。
2、实验内容:
[实验项目]完成以下正则文法所描述的Pascal语言子集单词符号的词法分析程序。
<标识符>→字母︱<标识符>字母︱<标识符>数字
<无符号整数>→数字︱<无符号整数>数字
<单字符分界符>→+︱-︱*︱;︱(︱)
<双字符分界符>→<大于>=︱<小于>=︱<小于>>︱<冒号>=︱<斜竖>*<小于>→<
<等于>→=<大于>→><冒号>→:
<斜竖>→/
该语言的保留字:
beginendifthenelsefordowhileandornot
[设计说明]
(1)该语言大小写不敏感;
(2)字母为a-zA-Z,数字为0-9;(3)可以对上述文法进行扩充和改造;(4)‘/*……*/’为程序的注释部分。
[设计要求]
(1)给出各单词符号的类别编码;
(2)词法分析程序应能发现输入串中的错误;(3)词法分析作为单独一遍编写,词法分析结果为二元式序列组成的中间文件;(4)设计两个测试用例(尽可能完备),并给出测试结果。
3、实验环境:
操作系统:
Windows7
软件:
VC++6.0
4、程序功能描述:
●给出了各单词符号的类别编码;
●词法分析程序能够对给出的文件中的输入串做出正确的词法;
●词法分析程序能发现文件输入串中的错误;
●词法分析结果为二元式序列组成的中间文件;
●词法分析程序能兼容注释并能发现文件注释未关闭的错误
五、数据结构设计:
六、程序结构描述:
●设计方法:
本程序采用从文件读取字符串,根据已有文法、词法的构成及规定对字符串进行词法分析,其种类主要包括保留字、标识符、无符号数字、字符等,将分析的结果写入另一个文件。
程序规定的单词符号及其种别码见下表:
单词符号及其种别码表
单词符号
种别码
单词符号
种别码
begin
1
无符号整数
13
end
2
+
14
If
3
-
15
then
4
*
16
else
5
;
17
for
6
(
18
do
7
)
19
while
8
=
20
and
9
>
21
or
10
>=
22
not
11
<
23
标识符
12
<=
24
<>
25
:
=
26
/
27
/*
28
*/
29
●主要函数说明:
lookup():
每调用一次,就以TOKEN中的字符串查保留字表,若查到,就将相应关键字的类别码赋给整型变量c;否则将c置为0;
main():
主函数;
scanner():
扫描函数,完成程序的主要功能,包括读字符串、分析处理、分析处理等。
●函数调用关系说明:
main()函数调用scanner()函数;
scanner()函数调用lookup()函数。
●执行框图:
1)总体结构图:
2)扫描程序结构框图:
七、实验过程结果截图:
●测试用例一:
结果一:
●测试用例二:
结果二:
八、实验总结:
●实验心得:
通过本次实验我锻炼了自己的上机操作能力及编程能力,并对理论知识有了进一步的了解。
本实验基本思路比较清晰,用较为简单的算法就能实现;解决实验中遇到的问题也花费了一部分时间,我增长了处理关于文件错误的能力;
●实验中遇到的问题:
主要问题就是在读取文件时对文件末尾的判断预处理,有两个问题花费了大部分时间,一个是在回退时要判断是否为文件末尾,若是则不需要回退;另外一个就是要先读取一个字符再用feof(fp)来判断是否为文件尾,且两个应紧密相连;
●程序的自我评价:
此程序实现了要求中的所有功能,并增加了对注释的一些操作,但因编程能力的欠缺,其中有的地方不免有些繁杂,还有一些潜藏的问题,需要进一步测试来时程序变得更加具有健壮性。
九、程序清单:
/****************************************************
课题名称:
词法分析程序构造原理与实现技术
作者:
房皓进修生13410801
最后修改时间:
2014.4.919:
47
***************************************************/
/**************************************************单词符号及其分类编码
单词符号种别码单词符号种别码
begin1无符号整数13
end2+14
if3-15
then4*16
else5;17
for6(18
do7)19
while8=20
and9>21
or10>=22
not11<23
标识符12<=24
<>25
:
=26
/27
/*28
*///29
/***************************************************/
#include
#include
#include
#include
usingnamespacestd;
/////////////////////////////////////////////////////////////////////////////////////////
intlookup(char*str)//每调用一次,就以TOKEN中的字符串查保留字表,若查到,就将相应关键字的类别码赋给整型变量c;否则将c置为0
{
char*letter[11]={"begin","end","if","then","else","for","do","while","and","or","not"};//保留字
inti;
for(i=0;i<11;i++)
{
if(strcmp(str,letter[i])==0)//比较是否相同
returni+1;//若相同,返回相应的种别码
}
return0;
}
////////////////////////////////////////////////////////////////////////////////////
intscanner(FILE*fp)
{
charTOKEN[20];
FILE*fp_out=fopen("result.txt","w");
charch;
inti=0,c;
intzhushi=0;//zhushi等于0表示当前不是注释,zhushi=1表示当前及以后的都是注释
ch=fgetc(fp);
while(!
feof(fp))//判断文件结束
{
if(zhushi==0)
{
i=0;
if(ch==''||ch=='')
{}
else
if(isalpha(ch))//是否为字母
{
ch=tolower(ch);//转换成小写
TOKEN[0]=ch;
i++;
ch=fgetc(fp);
while(isalnum(ch))//数字或字母
{
if(isalpha(ch))
ch=tolower(ch);
TOKEN[i]=ch;
i++;
ch=fgetc(fp);
}
TOKEN[i]='\0';
if(ch!
=EOF)//经验证,若没有此判断,遇到文件结尾仍返回的话,则
fseek(fp,-1L,1);//ch的值永远为文件最后一个字符
c=lookup(TOKEN);//查找保留字
if(c==0)
{
fprintf(fp_out,"(%d,%s)",12,TOKEN);//标识符
printf("(%d,%s)\n",15,TOKEN);//标识符
}
else
{
fprintf(fp_out,"(%d,%s)",c,TOKEN);//保留字
printf("(%d,%s)\n",c,TOKEN);//保留字
}
}
else
if(isdigit(ch))//是否为数字
{
TOKEN[0]=ch;
ch=fgetc(fp);
i++;
while(isdigit(ch))
{
TOKEN[i]=ch;
i++;
ch=fgetc(fp);
}
TOKEN[i]='\0';
if(ch!
=EOF)
fseek(fp,-1L,1);
fprintf(fp_out,"(%d,%s)",13,TOKEN);//无符号整数
printf("(%d,%s)\n",16,TOKEN);//无符号整数
}
else
switch(ch)
{
case'<':
if(!
feof(fp))
ch=fgetc(fp);
if(ch=='=')
{
fprintf(fp_out,"(%d,%s)",24,"<=");
printf("(%d,%s)\n",24,"<=");
}
else
if(ch=='>')
{
fprintf(fp_out,"(%d,%s)",25,"<>");
printf("(%d,%s)\n",25,"<>");
}
else
{
if(ch!
=EOF)
fseek(fp,-1,1);
fprintf(fp_out,"(%d,%c)",23,'<');
printf("(%d,%c)\n",23,'<');
}
break;
case'=':
{
fprintf(fp_out,"(%d,%c)",20,'=');
printf("(%d,%c)\n",20,'=');
}
break;
case'>':
if(!
feof(fp))
ch=fgetc(fp);
if(ch=='=')
{
fprintf(fp_out,"(%d,%s)",22,">=");
printf("(%d,%s)\n",22,">=");
}
else
{
if(ch!
=EOF)
fseek(fp,-1,1);
fprintf(fp_out,"(%d,%c)",21,'>');
printf("(%d,%c)\n",21,'>');
}
break;
case'+':
{
fprintf(fp_out,"(%d,%c)",14,'+');
printf("(%d,%c)\n",14,'+');
}
break;
case'-':
{
fprintf(fp_out,"(%d,%c)",15,'-');
printf("(%d,%c)\n",15,'-');
}
break;
case'*':
{
fprintf(fp_out,"(%d,%c)",16,'*');
printf("(%d,%c)\n",16,'*');
}
break;
case';':
{
fprintf(fp_out,"(%d,%c)",17,';');
printf("(%d,%c)\n",17,';');
}
break;
case'(':
{
fprintf(fp_out,"(%d,%c)",18,'(');
printf("(%d,%c)\n",18,'(');
}
break;
case')':
{
fprintf(fp_out,"(%d,%c)",19,')');
printf("(%d,%c)\n",19,')');
}
break;
case'/':
if(!
feof(fp))
ch=fgetc(fp);
if(ch=='*')
{
zhushi=1;//zhushi=1;
fprintf(fp_out,"(%d,%s)",28,"/*");
printf("(%d,%s)\n",28,"/*");
}
else
{
if(ch!
=EOF)
fseek(fp,-1,1);
fprintf(fp_out,"(%d,%c)",27,'/');
printf("(%d,%c)\n",27,'/');
}
break;
case':
':
if(!
feof(fp))
ch=fgetc(fp);
if(ch=='=')
{
fprintf(fp_out,"(%d,%s)",26,":
=");
printf("(%d,%s)\n",26,":
=");
}
else
{
if(ch!
=EOF)
fseek(fp,-1,1);
}
break;
default:
fprintf(fp_out,"(%s,%c)","非法字符",ch);
printf("(%s,%c)\n","非法字符",ch);
break;
}
}
ch=fgetc(fp);
if(zhushi==1)//该部分为检查注释是否结束,若结束,则令shuzhi=0;
if(ch=='*')
{
if(!
feof(fp))
ch=fgetc(fp);
if(ch=='/')
{
fprintf(fp_out,"(%s,%s)","注释结束","*/");
printf("(%s,%s)\n","注释结束","*/");
zhushi=0;
ch=fgetc(fp);
}
else
{
if(ch!
=EOF)
fseek(fp,-1,1);
ch=fgetc(fp);
}
}
}
if(zhushi==1)//没有关闭注释
{
fprintf(fp_out,"(%s)","程序有错误,注释没有关闭!
");
printf("(%s)\n","程序有错误,注释没有关闭!
");
}
fclose(fp_out);
return1;
}
///////////////////////////////////////////////////////////////////////////////////////
intmain()
{
FILE*fp=fopen("input.txt","r");
scanner(fp);
fclose(fp);
return1;
}