实验报告实验一编写词法分析程序文档格式.docx
《实验报告实验一编写词法分析程序文档格式.docx》由会员分享,可在线阅读,更多相关《实验报告实验一编写词法分析程序文档格式.docx(22页珍藏版)》请在冰豆网上搜索。
![实验报告实验一编写词法分析程序文档格式.docx](https://file1.bdocx.com/fileroot1/2023-1/5/aca35ebd-7232-4018-a8fd-92b41293044f/aca35ebd-7232-4018-a8fd-92b41293044f1.gif)
|>
=|<
=|!
=|==
6)注释符:
/**/
/*(没有连续的*/的任意字符串|ℇ)*/
2、对每个文法或者正则表达式分别构造NFA
(a|b|……|z|A|B……|Z)(0|1|……|9|a|b|……|z|A|B……|Z)*
2)无符号整数:
((1|2|……|9)(0|1|……|9)*)|0
3)分界符:
4)运算符:
5)注释符:
3、将NFA合并,确定化,化简得到最终的DFA。
NFA:
DFA:
三、实验过程
1、完成整个实验的先后步骤
a)根据TEST语言的词法规则,分别写出每条规则的正则文法或者正则表达式;
b)将每一个正则文法或者正则表达式转换为NFA;
c)将多个NFA合并后进行确定化并化简;
d)根据化简后的DFA画出流程图;
e)参阅教材PP.69-71的TEST语言语法规则,确定单词分类、单词输出方案;
f)编写词法分析程序;
g)对下面的TEST语言源程序进行词法分析,将合法单词存入lex.txt,并报告词法错误及其位置。
注:
不能修改源程序
{
/*Thisatestprogram.*/
intabc;
int123;
intA$@;
inti;
intn;
intb,c;
int2a;
inta2;
readn;
n=012345;
for(i=1;
i<
=n;
i=i+1)
{
abc=abc+i;
}
if(i!
=n)n=n+i;
if(!
n)b=b+c;
/*Theloopended
writeabc;
2、实验调试记录(问题表现,分析原因,解决方案,解决结果)
a)问题表现:
1.不能处理除号
2.不能处理不完整的注释符
3.对于”0123”这类字符串的处理不正确,我之前处理为直接报错说一位以上的数字首位不能为0
b)分析原因:
问题1,2的原因都是在“/”符号处理时出现的问题导致的,程序中出现bug使得一遇到‘/’就会进入死循环。
问题3,不应该直接报错说一位以上的数字首位不能为0,遇到0应该直接输出0这个单词,再接着读数字。
c)解决方案:
d)对于问题1,2,重新梳理逻辑,一步一步对照流程图和DFA来调试修改代码。
对于问题3,遇到0应该直接输出0这个单词,再接着读数字。
e)解决结果:
成功解决了程序遇到‘/’进入死循环问题和“0123”这类字符串的处理。
三、实验结果
列出实验结果并进行分析(含分步测试结果)。
lex.txt文件(存放编译的合法内容)内容:
1{{
2/*Thisatestprogram.*//*Thisatestprogram.*/
3intint
3IDabc
3;
;
4intint
4NUM123
4;
5intint
5IDA
5;
6intint
6IDi
6;
7intint
7IDn
7;
8intint
8IDb
8IDc
8;
9intint
9NUM2
9IDa
9;
10intint
10IDa2
10;
11readread
11IDn
11;
12IDn
12==
12NUM0
12NUM12345
12;
13forfor
13((
13IDi
13==
13NUM1
13;
13<
=<
=
13IDn
13++
13))
14{{
15IDabc
15==
15++
15IDi
15;
16}}
17ifif
17((
17IDi
17!
=!
17IDn
17))
17==
17++
17;
18ifif
18((
18IDn
18))
18IDb
18==
18++
18IDc
18;
四、讨论与分析
1.你的编写词法分析程序满足最长匹配原则吗?
如果满足请给出你的实现方案。
如果不满足请给出改进方案。
答:
不满足,我的处理先后顺序是:
标识符或保留字、数字、分界符、运算符(除开/)、除或者注释,我应该吧注释放在前面,因为一般来说注释都比其它类型符号长些。
改进措施便是将注释这一条词法规则最早处理。
2.给出你的单词分类方案,并说明理由。
根据TEST语言可将单词分为六类:
a)标识符:
b)保留字:
标识符的子集,包括:
c)无符号整数:
d)分界符:
e)运算符:
f)注释符:
3.构建词法分析程序一般过程是怎样的?
构建词法分析程序的一般过程:
1、根据词法规则写出正则文法或者正则文法。
2、为每一个正则表达式构造一个NFA,然后将多个NFA合并为一个NFA
3、将NFA转化成DFA,并且化简最小化DFA
4、确定单词的输出形式
5、根据化简后的DFA和单词输出程序构造词法分析程序
(主要部分:
通过实验对课程知识点的理解;
回答实验指导书的实验思考提出的问题等)
五、附录:
关键代码(给出适当注释,可读性高)
#include<
iostream>
fstream>
stdio.h>
stdlib.h>
string>
usingnamespacestd;
constintKWN=8;
//关键字的个数
constintMAXSIZE=400;
//标识符最长个数
charkword[KWN][10]={//关键字
"
if"
"
else"
for"
while"
do"
int"
read"
write"
};
intline=1;
//行号
interrors=0;
//记录错误个数
ofstreamfout;
//输出文件流
ifstreamfin;
//输入文件流
ofstreamlexout;
//存放合法单词的文件流
chartype[6][30]={
ID"
"
保留字"
NUM"
分界符"
运算符"
注释符"
intmain()
{
intTEST();
//函数声明
TEST();
if(errors==0)
{
cout<
<
"
编译成功。
endl;
}
else
编译失败。
共发现"
errors<
个错误!
return0;
}
////判断是否为字母
intis_Char(charch)
if((ch>
='
a'
&
ch<
z'
)||(ch>
A'
Z'
))
return1;
////判断是否为无符号整数
intis_Uint(charch)
if('
0'
=ch&
9'
)
////判断是否为分界符
intis_Deli(charch)
if(ch=='
('
||ch=='
)'
;
'
{'
}'
////判断是否为操作符
intis_Oper(charch)
charOperater[10]="
+-*!
=>
//没有考虑/号
for(inti=0;
8;
i++)
if(ch==Operater[i])
{
return1;
}
////输入控制
intin(char&
ch)
fin.get(ch);
\n'
==ch)
line++;
if(fin.eof())
ch=EOF;
return1;
////输出控制
voidout(char*type,char*buf)
if(strcmp(type,"
)==0||strcmp(type,"
)==0)
lexout<
line<
type<
buf<
//cout<
:
////编译程序主要的函数
intTEST()
intevent=0;
//用于判断输入是否为文件末
//charfilename[300];
//存储文件的路径
//////打开文件的操作
//打开编译程序存放合法单词的文件
lexout.open("
lex.txt"
);
//打开用户的文件
请输入要编译的文件的路径:
reinput_in:
//cin.get(filename,300,'
//charfilename[300]={"
D:
\Software\MicrosoftVisualC++6.0\MicrosoftVisualStudio\MyProjects\编译原理实验一\in.txt"
fin.open("
in.txt"
if(fin==NULL)
文件打开失败,请重新输入文件路径:
gotoreinput_in;
请输入词法分析结果文件存储路径:
reinput_out:
cin.clear();
//清理输出缓冲
cin.sync();
//清空流
//charfilename[300]={"
\Software\MicrosoftVisualC++6.0\MicrosoftVisualStudio\MyProjects\编译原理实验一\out.txt"
fout.open("
out.txt"
if(fout==NULL)
gotoreinput_out;
//////开始判断
charbuf[300];
charch;
in(ch);
while(!
fin.eof())
while(ch=='
'
\t'
\r'
in(ch);
//判断是否为标识符或保留字
if(is_Char(ch))
intt=0;
while(is_Char(ch))
{
buf[t++]=ch;
in(ch);
}
buf[t]='
\0'
//判断保留字
intj=0;
for(;
j<
KWN;
j++)
if(strcmp(kword[j],buf)==0)
{
out(type[1],buf);
break;
}
//ID标识符
if(j>
=KWN)
while(is_Char(ch)||is_Uint(ch))
buf[t++]=ch;
in(ch);
buf[t]='
out(type[0],buf);
//判断是否为数字
elseif(is_Uint(ch))
while(is_Uint(ch))
if(t==1)
out(type[2],buf);
elseif(buf[0]=='
inti=-1;
while(i<
t&
buf[++i]=='
out(type[2],&
0"
out(type[2],buf+i);
else
//判断是否为分界符
elseif(is_Deli(ch))
buf[0]=ch;
buf[1]='
out(type[3],buf);
//判断是否为运算符(除开/)
elseif(is_Oper(ch))
if(ch=='
+'
-'
*'
buf[0]=ch;
buf[1]='
out(type[4],buf);
elseif(ch=='
!
if(ch=='
buf[1]=ch;
buf[2]='
out(type[4],buf);
else
cout<
error"
++errors<
line"
不合法的符号!
>
buf[1]='
elseif(ch=='
/'
)//判断是除还是注释
buf[t++]=ch;
charch0;
in(ch0);
while
(1)
if(ch0==EOF)
匹配错误,缺少*/"
ch=ch0;
in(ch0);
if(ch=='
&
ch0=='
buf[t++]=ch0;
buf[t]='
out(type[5],buf);
else
cout<
未知符号"
}
fin.close();
fout.close();
lexout.close();
returnerrors;
/*
\Software\MicrosoftVisualC++6.0\MicrosoftVisualStudio\MyProjects\编译原理实验一\in.txt
\Software\MicrosoftVisualC++6.0\MicrosoftVisualStudio\MyProjects\编译原理实验一\out.txt
/*Thisatestprogram.
*//*
charch1=getc(fin);
while(true)
if(ch1==EOF)
printf("
Line%d\t%s\t没有匹配!
\n"
line,"
错误:
);
break;
ch=ch1;
ch1=getc(fin);
if(ch=='
ch1=='
ch=getc(fin);
/*Theloopended
writeabc;
*/
六、实验者自评(主要从实验态度、方法、效果上给一个客观公正的自我评价)
我自认为实验态度很好,只是实验的方法不太好,实验的效果一般。
我是看着DFA图来敲的代码,而不是看流程图来写的代码,这导致我敲到后面出现好几个难以发现的bug,这两个bug花了我相当多的时间,后来为了解决这个问题,我画出流程图再来一点一点对照我的代码,最终终于发现了bug,过程相当艰辛,光只是敲代码画了足足两天时间。
实验效果一般,实验所花的总时长太长,效率不高。