词法分析的实验报告Word文档下载推荐.docx
《词法分析的实验报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《词法分析的实验报告Word文档下载推荐.docx(11页珍藏版)》请在冰豆网上搜索。
end
/
repeat
=
数
(一个或更多的数字)
until
<
read
{
write
}
;
2.2实验要求
●要求实现编译器的以下功能
1、按规则拼单词,并转换成二元式形式
2、删除注释行
3、删除空白符(空格、回车符、制表符)
4、列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式
5、发现并定位错误
●词法分析进行具体的要求
1、记号的二元式形式中种类采用枚举方法定义;
其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;
单词的属性就是表示的字符串值。
2、词法分析的具体功能实现是一个函数GetToken(),每次调用都对剩余的字符串分析得到一个单词或记号识别其种类,收集该记号的符号串属性,当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。
这样配合语法分析程序的分析需要的记号及其属性,生成一个语法树。
3、标示符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标示符。
3此法分析器的程序实现
3.1状态转换图
图1TINY语言的确定有限自动机(DFA)
3.2程序源码
#include<
iostream>
usingnamespacestd;
fstream>
string>
iomanip>
classCA
public:
voidgetToken();
//识别标识符
voidpreDo(char);
//预处理源程序
voiddisplay();
//打印出
CA()
{
m=n=0;
}
private:
longcount2;
charID[10][10];
//符号表
intm;
//设m为符号表中已有的标识符的个数
charCons[10][10];
//常数表
intn;
//设n为常数表中已有的常数的个数
charbuffer1[99999];
boolisDigit(char);
//检查是否为数字
boolisLetter(char);
//检查是否为字符
intInsertID(char*strToken);
//添加符号
intInsertConst(char*strToken);
intSearch(chara[][10],constchar*,int);
//二分查找
};
//enumvariety{标识符,数字,关键字1,关键字2,关键字3,关键字4,关键字5,关键字6,关键字7,关键字8,特殊符号1,
//特殊符号2,特殊符号3,特殊符号4,特殊符号5,特殊符号6,特殊符号7,特殊符号8,特殊符号9,特殊符号10};
//关键字bi编码12345678
charK[18][10]={"
else"
"
end"
if"
read"
repeat"
then"
until"
write"
"
%"
*"
+"
-"
/"
:
"
="
>
boolCA:
isDigit(charc)
if(c<
='
9'
&
c>
0'
)returntrue;
elsereturnfalse;
isLetter(charc)
if(c>
a'
c<
z'
||c>
A'
Z'
intCA:
Search(chara[18][10],constchar*b,intn)
intleft=0;
intright=n-1;
intmid=0;
while(left<
=right)
mid=(left+right)/2;
if(strcmp(a[mid],b)==0)returnmid;
elseif(strcmp(a[mid],b)<
0)left=mid+1;
elseright=mid-1;
return-1;
InsertID(char*strToken)
inti=0;
while(i<
m)//设m为符号表中已有的标识符的个数
{
if(!
strcmp(ID[i],strToken))
returni;
i++;
strcpy(ID[i],strToken);
m++;
returni;
InsertConst(char*strToken)
n)//设n为常数表中已有的常数的个数
strcmp(Cons[i],strToken))
strcpy(Cons[i],strToken);
n++;
voidCA:
display()
charfilename[30];
//输入的时候一定要是...:
/.../...格式
cout<
请输入源程序代码.cpp文件的绝对路径:
endl;
cin>
filename;
ifstreaminfile(filename,ios:
in);
if(!
infile)
cerr<
openerror!
abort();
charch;
intcount1=1;
count2=0;
第"
count1<
行"
while(infile.get(ch))
preDo(ch);
cout<
ch;
//逐行打印出源程序
if(ch=='
\n'
)
{
count1++;
cout<
}
buffer1[count2+1]='
\0'
//对buffer1中的字符进行扫描
getToken();
infile.close();
符号表:
for(inti=0;
i<
m;
i++)
ID[i]<
"
数字表:
for(intj=0;
j<
n;
j++)
Cons[j]<
preDo(charc)
char*p=buffer1;
buffer1[0]='
#'
//赋#给扫描缓冲区的第一个元素
count2++;
*(p+count2)=c;
if(buffer1[count2-1]=='
{'
)//删除注释
if(c=='
)cout<
注释不允许嵌套!
//注释不允许嵌套
if(c!
}'
)count2--;
elsecount2=count2-2;
elseif(buffer1[count2-1]=='
'
c=='
//若干相继的空白符结合成一个
if(c=='
\r'
\t'
getToken()
{
intn=1;
第1行:
for(inti=1;
strlen(buffer1);
if(buffer1[i]=='
){n++;
cout<
\n第"
n<
行:
;
}
elseif(isLetter(buffer1[i]))
stringtok="
tok+=buffer1[i];
while(isLetter(buffer1[++i]))
tok+=buffer1[i];
intr=Search(K,tok.c_str(),8);
i--;
if(r!
=-1)cout<
(关键字"
r+1<
tok<
)"
//关键字编码
else
{
cout<
(标识符,"
//标识符编码
r=InsertID((char*)tok.c_str());
}
elseif(isDigit(buffer1[i]))
while(isDigit(buffer1[++i]))
inty=InsertConst((char*)tok.c_str());
(数字,"
//数字编码
elseif(buffer1[i]=='
){}
else
intq=Search(K,tok.c_str(),18);
if(q!
=-1){cout<
(特殊符号,"
else
非法符号!
}
/***********************main函数*******************************/
intmain()
CAca;
ca.display();
return0;
3.3实验运行效果截图
4实验体会
本次实验是《编译技术》的第一次实验,按理说也应该是最简单的一次实验验,但是在具体的实现过程中还是遇到了这样或那样的问题,比如对原输入串进行分析的预处理是在注释的嵌套判断上出现了问题,调试了几次才发现是出现注释时计数值本来应该减2结果减了1。
类似的错误还有,但好在最后都解决了。
除了提升了自己的动手能力外本次实验最大的收获应该是对词法分析器的运行机制有了更深入的理解了,再画状态转换的过程中也激发了我的一些关于那些复杂的语言(如c++)的词法分析器是怎样书写的联想,希望在今后的学习实践中能有更深入的学习。
最后感谢老师的悉心指导,谢谢老师!