算符优先语法分析设计原理与实现技术实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算符优先语法分析设计原理与实现技术
实验报告
变更说明
一、实验目的:
本实验的目的在于在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握编译程序设计和构造的基本原理和实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神和专业素养,从而提高学生发现问题、分析问题和解决问题的能力。
二、实验内容:
[实验项目]
实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。
G[E]:
E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
[实验说明]
终结符号i 为用户定义的简单变量,即标识符的定义。
[设计要求]
(1)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果。
输出为输入串是否为该文法定义的算术表达式的判断结果;
(2)算符优先分析过程应能发现输入串出错;
(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。
三、实验环境:
操作系统:Windows 7
软件:VC++6.0
四、程序功能描述:
●提供了文件输入方式,且输入的内容为二元式序列;
●能够对输入的字符串做出正确的算符优先分析判断,并给出判断结果,判断
结果输出到文件,并显示在屏幕;
●能发现输入串中的错误,包含非法字符,输入不匹配等;
●能够处理一些可预见性的错误,如文件不存在,输入非法等。
五、数据结构设计:
六、程序结构描述:
●设计方法:
本程序采用从文件读取的输入方式,输入的内容需为二元式序列,然后按照算符优先分析的方法对输入的字符串进行分析判断,分析完成后输出判断结果到文件,并在屏幕显示。
程序通过对输入串的检查能够发现输入串中的错误。
程序规定的单词符号及其种别码见下表:
算符优先矩阵
+ - * / ( ) i #
+ > > < < < > < >
- > > < < < > < >
* > > > > < > < >
/ > > > > < > < >
( < < < < < = < >
) > > > > > >
i > > > > > >
# < < < < < < < =
●算符优先分析法简介
基本思路是根据既定的规则构建算符优先矩阵,然后根据算符之间的优先关系寻找输入串中的最左素短语,若找到,则寻找与最左素短语匹配的产生式进行规约;否则进行移进操作,及输入的算符进分析栈。
循环直至输入串的末尾,若
分析栈开始的’#’与输入串末尾的’#’相匹配则接受,其他情况均失败。
●主要函数说明:
error():void型,输出错误,表示不是该文法的句子;
getIndexVt(char ch):int型,获取并返回终结符号ch的序号;
init():void型,初始化函数,读文件到输入串;
IsEqualTo(char ch1,char ch2):bool型,若终结符号ch1和ch2的优先级别相
同则返回true,否则返回false;
IsHigherThan(char ch1,char ch2):bool型,若终结符号ch1的优先级别高于
ch2,则返回true,否则返回false;
IsLowerThan(char ch1,char ch2):bool型,若终结符号ch1的优先级别低于ch2,
则返回true,否则返回false;
IsReduce(int begin,int end,int len):bool型,函数功能:寻找与最左素短语匹
配的产生式;入口参数:int begin,int end,int len;入口参数
意义:最左素短语的开头和结束位置及最左素短语的长度;
返回值:若存在相应产生式则返回true,否则返回false IsVt(char ch):bool型,判断ch是否为终结符号,是则返回true,否则返回
false;
parser(void):void型,函数功能:寻找最左素短语、控制规约与移进;
main():主函数。
●函数调用关系说明:
函数main()调用init()、parser(void);
函数parser(void)调用error()、IsEqualTo(char ch1,char ch2)、IsHigherThan(char ch1,char ch2)、IsLowerThan(char ch1,char ch2)、IsReduce(int begin,int end,int len)、IsVt(char ch);
函数IsEqualTo(char ch1,char ch2)、IsHigherThan(char ch1,char ch2)、IsLowerThan(char ch1,char ch2)均调用getIndexVt(char ch)。
●执行框图:
●测试用例一:i+i*i#
●测试用例二:i+i*i/#
八、实验总结:
●实验心得:
通过本次实验我锻炼了自己的上机操作能力及编程能力,并对理论知识有了进一步的了解。
老师提供的算符优先分析法的流程图给了我很大的帮助,使得本实验基本思路变得很清晰,用较为简单的算法就能实现,程序的难点是算符优先矩阵的构造及寻找与最左素短语相匹配的产生式进行规约,解决实验中遇到的问题也花费了一部分时间,我增长了处理错误的能力。
●实验中遇到的问题及解决方法:
问题主要有
i.在寻找与最左素短语相匹配的产生式时没有思路,经过对文法的分
析,发现只有长度为1或3的产生式,基于这一点,再根据各产生
式及最左素短语的特点,利用终结符号的匹配进行寻找;
ii.当输入内容不匹配或输入内容非法时要退出程序,此时若不关闭已经打开的文件可能导致文件内容受到破坏;解决方法是将文件指针
变量设置为全局变量,error()函数在退出程序之前先将未关闭的文件
关闭。
●程序的自我评价:
此程序实现了要求中的所有功能,并增加了输入串错误检测的功能,但因编程能力及经验的有限,其中有的地方不免有些繁杂,还有一些潜藏的问题,需要进一步测试与修改来提高程序的健壮性。
九、程序清单:
/****************************************************
课题名称:算符优先语法分析设计原理与实现技术
作者:房皓进修生13410801
最后修改时间:2014.5.7
***************************************************/
/*************单词符号及其分类编码******************
单词符号种别码
( 1
) 2
+ 3
- 4
* 5
/ 6
i 7
# 8
****************************************************
**********************文法**************************
G[E]:E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
*******************算符优先矩阵********************* + - * / ( ) i #
+ > > < < < > < >
- > > < < < > < >
* > > > > < > < >
/ > > > > < > < >
( < < < < < = < >
) > > > > > >
i > > > > > >
# < < < < < < < =
***************************************************/
#include<iostream>
using namespace std;
#define MAXINPUT 300
#define MAXSTACK 100
#define NewVn 'N'
char stack[MAXSTACK],a[MAXINPUT];
FILE *fpin,*fpout;
int array[8][8]={ //优先矩阵,1='>',-1='<',0='=' { 1, 1,-1,-1,-1, 1,-1, 1},
{ 1, 1,-1,-1,-1, 1,-1, 1},
{ 1, 1, 1, 1,-1, 1,-1, 1},
{ 1, 1, 1, 1,-1, 1,-1, 1},
{-1,-1,-1,-1,-1, 0,-1, 1},
{ 1, 1, 1, 1,' ',1,' ',1},
{ 1, 1, 1, 1,' ',1,' ',1},
{-1,-1,-1,-1,-1,-1,-1, 0}
};
void init()
{
char a1[MAXINPUT];
int i=0,j=0;
if((fpin=fopen("input.txt","r"))==NULL)
{
cout<<"文件打开失败!"<<endl;
exit(0);
}
if((fpout=fopen("result.txt","w"))==NULL)
{
fclose(fpin);
cout<<"文件打开失败!"<<endl;
exit(0);
}
a1[i++]=fgetc(fpin);
while(!feof(fpin))
{
a1[i++]=fgetc(fpin);
if((i%5)==0)
a[j++]=a1[i-2];
}
fclose(fpin);
cout<<"读入字符串为:";
cout<<a<<endl;
}
void error()
{
cout<<"FAIL!"<<endl;
fprintf(fpout,"%s","FAIL!");
fclose(fpout);
exit(0);
}
int getIndexVt(char ch) //获取终结符号ch的序号{
char vt[8]={'+','-','*','/','(',')','i','#'};
int i;
for(i=0;i<8;i++)
if(ch==vt[i])
break;
return i;
}
bool IsHigherThan(char ch1,char ch2) {
int c1,c2;
c1=getIndexVt(ch1);
c2=getIndexVt(ch2);
if(array[c1][c2]==1)
return true;
return false;
}
bool IsLowerThan(char ch1,char ch2) {
int c1,c2;
c1=getIndexVt(ch1);
c2=getIndexVt(ch2);
if(array[c1][c2]==-1)
return true;
return false;
}
bool IsEqualTo(char ch1,char ch2) {
int c1,c2;
c1=getIndexVt(ch1);
c2=getIndexVt(ch2);
if(array[c1][c2]==0)
return true;
return false;
}
bool IsVt(char ch)
{
char vt[8]={'+','-','*','/','(',')','i','#'};
int i;
for(i=0;i<8;i++)
if(ch==vt[i])
return true;
return false;
}
/***********************************************
函数名:IsReduce(int begin,int end,int len)
函数类型:bool
函数功能:寻找与最左素短语匹配的产生式
入口参数:int begin,int end,int len
入口参数意义:最左素短语的开头和结束位置及最左素短语的长度
返回值:若存在相应产生式则返回true,否则返回false
***********************************************/
bool IsReduce(int begin,int end,int len)
{
if(len==1)
if(stack[begin]=='i')
return true;
if(len==3)
if(stack[begin]=='(' && stack[end]==')' && !(IsVt(stack[begin+1])))
return true;
else
if(!(IsVt(stack[begin])))
if(!(IsVt(stack[end])))
if(stack[begin+1]=='+' || stack[begin+1]=='-' || stack[begin+1]=='*' || stack[begin+1]=='/')
return true;
return false;
}
/***********************************************
函数名:parser(void)
函数类型:void
函数功能:寻找最左素短语、控制规约与移进
入口参数:无
返回值:无
***********************************************/
void parser(void)
{
int i,k;
char r;
i=0;k=0;
stack[0]='#';
do
{
int j;
r=a[i++];
if(IsVt(stack[k]))
j=k;
else
j=k-1;
while(IsHigherThan(stack[j],r))
{
char q;
do
{
q=stack[j];
if(IsVt(stack[j-1]))
j--;
else
j-=2;
}while(!IsLowerThan(stack[j],q));
if(IsReduce(j+1,k,k-j))
{
k=j+1; //规约
stack[k]=NewVn;
}
else
error();
}
if(IsLowerThan(stack[j],r) || IsEqualTo(stack[j],r))
stack[++k]=r; //移进else
error();
}while(r != '#');
cout<<"SUCCESS!"<<endl;
fprintf(fpout,"%s","SUCCESS!");
fclose(fpout);
}
int main()
{
init();
parser();
return 1;
}。