递归下降语法分析设计基本知识与实现技术实验报告.docx
《递归下降语法分析设计基本知识与实现技术实验报告.docx》由会员分享,可在线阅读,更多相关《递归下降语法分析设计基本知识与实现技术实验报告.docx(21页珍藏版)》请在冰豆网上搜索。
递归下降语法分析设计基本知识与实现技术实验报告
递归下降语法分析设计原理与实现技术
实验报告
变更说明
日期
版本
变更位置
变更说明
作者
2014/4/16
1.0
初稿生成
房皓
一、实验目的:
本实验的目的在于在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握编译程序设计和构造的基本原理和实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神和专业素养,从而提高学生发现问题、分析问题和解决问题的能力。
2、实验内容:
[实验项目]
完成以下描述算术表达式的LL
(1)文法的递归下降分析程序
G[E]:
E→TE′
E′→ATE′|ε
T→FT′
T′→MFT′|ε
F→(E)|i
A→+|-
M→*|/
[设计说明]
终结符号i为用户定义的简单变量,即标识符的定义。
[设计要求]
(1)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;
(2)递归下降分析程序应能发现输入串出错;
(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。
3、实验环境:
操作系统:
Windows7
软件:
VC++6.0
4、程序功能描述:
●提供了两种输入方式:
键盘和文件,有文件输入时需为二元式序列;
●能够对输入的字符串做出正确的递归下降分析判断,并给出判断结果;
●能发现输入串中的错误,包含非法字符,输入不匹配等;
●能够处理一些可预见性的错误,如文件不存在,用户输入非法等。
五、数据结构设计:
全局:
局部(main()中):
六、程序结构描述:
●设计方法:
本程序采用从键盘输入或文件读取两种输入方式,其中文件的内容需为二元式序列,然后按照递归下降分析的方法对输入的字符串进行分析判断,并输出判断结果,程序通过对输入串的检查能够发现输入串中的错误。
程序规定的单词符号及其种别码见下表:
单词符号及其种别码表
单词符号
种别码
单词符号
种别码
(
1
*
5
)
2
/
6
+
3
i
7
-
4
#
8
●主要函数说明:
advance():
将下一个字符送入current;
error():
输出错误,表示不是该文法的句子;
error1();输出错误,输入内容不合法;
init():
初始化函数;
justify():
判断文件读取内容是否合法,包括检查非法字符和不匹配现象
main():
主函数
●函数调用关系说明:
main()调用justify()、init()、E()、error1();
justify()调用error1();
A()、E()、E1()、F()、M()、F()、T()、T1()根据输入串可互相调用或递归调用,这些函数均可调用error()函数;
A()、F()、M()调用advance()函数。
●执行框图:
1)总体结构图:
2)递归下降分析构框图:
E():
E1():
T():
T()1:
M():
A():
F():
七、实验过程结果截图:
●测试用例一:
i+i*i/i#
键盘:
文件:
●测试用例二:
i+i*i/#
键盘:
文件:
八、实验总结:
●实验心得:
通过本次实验我锻炼了自己的上机操作能力及编程能力,并对理论知识有了进一步的了解。
老师提供的相对应于非终结符号的函数的流程图给了我很大的帮助,使得本实验基本思路变得很清晰,用较为简单的算法就能实现;解决实验中遇到的问题也花费了一部分时间,我增长了处理关于文件错误的能力;
●实验中遇到的问题:
问题主要有在调用某个函数时没有在之前声明或定义过此函数;还有在当用户输入的选择方式非法时,提示错误并要求重新输入,这用一个while循环实现。
●程序的自我评价:
此程序实现了要求中的所有功能,并增加了对用户操作错误、输入串错误检测的功能,但因编程能力的欠缺,其中有的地方不免有些繁杂,还有一些潜藏的问题,需要进一步测试来时程序变得更加具有健壮性。
九、程序清单:
/****************************************************
课题名称:
递归下降语法分析设计原理与实现技术
作者:
房皓进修生13410801
最后修改时间:
2014.4.1613:
52
***************************************************/
/**************************************************单词符号及其分类编码
单词符号种别码
(1
)2
+3
-4
*5
/6
i7
#8
//////////////////////////////////////////////////文法
G[E]:
E→TE′
E′→ATE′|ε
T→FT′
T′→MFT′|ε
F→(E)|i
A→+|-
M→*|/
/***************************************************/
#include
#include
usingnamespacestd;
#defineMAX50
chartoken[MAX];
chartoken2[MAX];
charcurrent;
inti=0;
/****************************************************
函数声明
****************************************************/
voidE();
voidE1();
voidT();
voidA();
voidF();
voidT1();
voidM();
voiderror();
voiderror1();
voidinit()//初始化
{
current=token[i];
}
voidjustify(charch,inti)//判断文件读取内容是否合法,包括检查非法字符和不匹配现象
{
switch(ch)
{
case'1':
if(token[i]!
='(')
error1();
break;
case'2':
if(token[i]!
=')')
error1();
break;
case'3':
if(token[i]!
='+')
error1();
break;
case'4':
if(token[i]!
='-')
error1();
break;
case'5':
if(token[i]!
='*')
error1();
break;
case'6':
if(token[i]!
='/')
error1();
break;
case'7':
if(token[i]!
='i')
error1();
break;
case'8':
if(token[i]!
='#')
error1();
break;
default:
error1();
break;
}
}
voidadvance()//读取下一个字符
{
if(i==MAX)
exit(0);
current=token[++i];
}
voidE()
{
if(current=='i'||current=='(')
{
T();
E1();
}
else
error();
}
voidE1()
{
if(current=='+'||current=='-')
{
A();
T();
E1();
}
else
if(!
(current==')'||current=='#'))
error();
}
voidT()
{
if(current=='i'||current=='(')
{
F();
T1();
}
else
error();
}
voidT1()
{
if(current=='*'||current=='/')
{
M();
F();
T1();
}
else
if(!
(current==')'||current=='#'||current=='+'||current=='-'))
error();
}
voidM()
{
if(current=='*')
advance();
else
if(current=='/')
advance();
else
error();
}
voidA()
{
if(current=='+')
advance();
else
if(current=='-')
advance();
else
error();
}
voidF()
{
if(current=='(')
{
advance();
E();
if(current==')')
advance();
}
else
if(current=='i')
advance();
else
error();
}
voiderror()
{
cout<<"ERROR!
"<exit(0);
}
voiderror1()
{
cout<<"输入错误!
"<exit(0);
}
intmain()
{
intflag;//提供输入和文件两种方式
intj=1;
inti=0;
chartoken1[MAX];//用于检测文件输入是否匹配
FILE*fp;
cout<<"输入方式:
键盘
(1)/文件
(2):
";
while(!
(cin>>flag)||(flag!
=1&&flag!
=2))
{
cout<<"\nError!
Re-enter:
";
cin.clear();
cin.ignore(200,'\n');
}
if(flag==1)
{
cout<<"请输入长度不超过50且以#结束的字符串:
"<cin>>token;
}
else
{
if((fp=fopen("input.txt","r"))==NULL)
{
cout<<"文件打开失败!
"<exit(0);
}
token1[0]=fgetc(fp);
while(!
feof(fp))
{
token1[j++]=fgetc(fp);
if((j%5)==0)
{
token2[i]=token1[j-4];
token[i]=token1[j-2];
justify(token2[i],i);
i++;
}
}
if((j-1)%5!
=0)
error1();
cout<<"读入字符串为:
"<}
init();
E();
if(current=='#')
cout<<"SUCCESS!
"<return1;
}