带出错处理的算优先分析算法的程序实现Word下载.docx
《带出错处理的算优先分析算法的程序实现Word下载.docx》由会员分享,可在线阅读,更多相关《带出错处理的算优先分析算法的程序实现Word下载.docx(18页珍藏版)》请在冰豆网上搜索。
i#
>
<
e2e2
=
e3
e1
e4
可以根据已知的文法G和优先关系表编写带出错处理的算符优先分析算法程序。
对
输入的符号串进行“移进—归约”,若有错误出现,则进行错误处理,指出错误原因。
当归约到“#E#”时则分析完毕,实现了该算法。
1.2设计要求
对已知文法G实现其带出错处理的算符优先分析算法,对输入的符号串进行分析,显示“移进—归约”的具体过程,如果在此过程中出现错误,则调用错误处理子程序对错误进行处理,并在此“移进—归约”过程后面显示错误原因以及错误解决方法,然后继续进行分析。
结果保存于文件当中,用户可以在运行程序时让结果直接显示,也可以在文件当中进行查看。
5
第二章 设计的基本原理
2.1算法分析
要实现算符优先分析算符,首先得了解一下“最左素短语”这个概念。
所谓素短语是指这样的一个短语,它至少含有一个终结符,并且,除了它自身以外不再含任何更小的素短语。
所谓最左素短语是指处于句型最左边的那个素短语。
设句型的一般形式为:
#N1a1N2a2·
·
NnanNn+1#
其中,每个ai都是终
结符,Ni是可有可无的非终结符。
换言之,句型中含有n个终结符,任何两个终结
符之间顶多只有一个非终结符。
一个算法优先文法G的任何句型的最左素短语是满足如下条件的最左字串Njaj·
NiaiNi+1,
aj-1<
aj
aj=aj+1,·
ai-1=aiai>
ai+1
根据这个定理,可以构造算法优先算法。
设使用一个符号栈S,既用它寄存终结符,也用它寄存非终结符。
下面的分析算法是直接根据这个定理构造出来的,其中
k代表符号栈S的使用深度。
k:
=1;
S[k]:
=‘#’;
REPEAT
把下一个输入符号读进a中;
IFS[k]Î
VT
THEN j:
=k ELSE j:
k-1;
WHILES[j]>
aDOBEGIN
REPEAT
Q:
=S[j];
IF S[j-1]
Î
THENj:
j-1 ELSE j:
j-2
UNTIL S[j]<
Q;
把S[j+1]…S[k]归约为某个N;
=j+1;
=N;
ENDOFWHILE;
IFS[j]<
aORs[j]=aTHENBEGINk:
=k+1;
S[k]:
=aEND
ELSE ERROR /* 调用出错诊察程序 */
UNTILa=‘#’
在上述算法的工作过程中,若出现j减1后的值小于等于0时,则意味着输入串有错。
在正确的情况下,算法工作完毕时,符号栈S应呈现:
#N#
算法优先分析一般并不等价于规范归约。
在算法优先归约过程中,我们无法用那些右部仅含一个一个非终结符的产生式进行归约。
对该文法G的句子i+i,按算法优先分析法,归约过程是:
先把第一个i归为F,然后把第二个i也归约为F,最后把F+F直接归约为E。
在此过程中,单非产生式对归约没有发挥作用。
2.2错误处理
算符优先分析中的出错处理:
(1)如+或*被归约,则检查其两端是否出现非终结符。
否则,打印错误信息:
“缺表达式”。
(2)如i被归约,则检查其左端或右端是否有非终结符。
如果有,则给出信息:
“表达式间无运算符联结”。
(3)如()被归约,则检查是否在括号间有一非终结符。
如果没有,则给出信息:
“括号间无表达式”。
根据优先关系表中的e1,e2,e3,e4可以调用错误处理子程序。
(1)e1:
/*当表达式以左括号结尾时,调用此程序*/ 将‘(’从栈顶移去;
给出错误信息:
非法左括号。
(2)e2:
/*当i或)后跟i或(时,调用此程序*/ 在输入端插入‘+’;
给出错误信息:
缺少运算符。
(3)e3:
/*当表达式以右括号开始时,调用此程序*/ 从输入端删除‘)’;
非法右括号。
(4)e4:
若栈顶有非终结符E,则表达式分析完毕。
若为空,则在输入端插入i;
缺少表达式。
第三章 程序设计
3.1总体方案设计
先将优先关系表保存在一个二维数组Vtchart[6][6]里面,利用函数intVttoint(char ch)将算符数字化,这样利于后面判断,以确定两个算符之间在
Vtchart数组里面的关系。
在设计的程序中,就是利于函数voidOperatorFun(strings)进行综合处理,该函数就是算符优先算法的体现。
在此函数里面有一个循环,直到分析完毕则结束,在处理过程中调用各个处理函数以及错误处理函数。
Vtchart[m1][m2] ==
利用函数boolisVn(charch)和函数boolisVt(charch)判断符号串是否是非终结符和终结符。
在已归约串里面找到第一个终结符和输入串进行比较,若是Vtchart[m1][m2]=='
'
||Vtchart[m1][m2]=='
='
即已归约串里面的第一个终结符和
输入串的终结符的优先关系为<
或=,则将输入串移进;
若是
即它们的关系是>
则进行归约,在归约过程中,可能会遇到错误,这就要在归约函数里面进行处理了;
然后其他的情况即遇到‘a’,‘b’,‘c’,‘d’即优先关系表中的e1,e2,e3,e4,则程序就会调用错误处理子程序,在错误处理子程序里面进行相关处理。
就这样进行循环,直到分析完毕。
这个综合函数的流程图如下:
用第一个产生式归
用第二个产生式归
用第三个产生式归
Vtchart[m1][m2]
或=
归约
移进
6
用第四个错误处理程序
用第一个错误处理程序
用第二个错误处理程序
用第三个错误处理程序
‘<
’,’=’,’>
’,’a’,’b’,’c’,d’
a,b,c,d
错误处理
a
b
c
d
用第四个产生式归
3.2各模块设计
由于无法用那些右部仅含一个一个非终结符的产生式进行归约,第一个产生式
E→E+T|T可以只用E→E+T代替,第二个产生式T→T*F|F可以用T→T*F代替,第三个产生式为F→(E),第四个产生式为F→i。
如果+或*被归约,则检查其两端是否出现非终结符。
若缺左表达式,则归约串添加E;
若缺右表达式,则归约串添加E;
若缺左右表达式,则归约串添加两个E。
检查()中间是否有非终结符,若没有,则添加E。
若i被归约,检查其左端或右端是否有非终结符即检查已归约串i的左右两边的字符是否是非终结符,这可以利用函数bool isVn(char ch),如果有,则表明表达式间无运算符联结,则添加运算符
+。
若出现e1错误,则将‘(’从已归约串的栈顶移去,即pop();
,当然首先找到‘(’的位置;
若出现e2错误,在输入端加入‘+’,index--;
str2[index]='
+'
;
可以实现,index是分析到的输入串位置;
若出现e3错误,从输入端删除‘)’,index++;
就可实现,即分析的输入串向后移动一个位置。
若出现e4错误,若已归约串的栈顶
是非终结符E,则分析完毕。
若为空,即栈顶为‘#’,则在输入串插入i,index--;
str2[index]='
i'
即可实现。
每分析一步,则向文件输出一个步骤,有函数voidoutputfile()实现输出到文件。
17
第四章 程序测试
运行程序,则出现下面窗口:
即提示用户输入一符号串。
这个输入的符号串可以以‘#’结束,也可以不以‘#’结束,这在程序里面已经处理好了,即if(str2[lenofstr2-1]!
='
#'
) str2+='
,就是如果不以‘#’结束,就直接在符号串后面加上‘#’。
输入符号串,假如是:
ii+) 则在文件里面产生一个文件reduction.txt
文件里面是符号串“移进—归约”的步骤,在有错误的步骤后面有错误原因以及解决方法。
可以在运行程序的窗口里面显示结果,选择Y或y就可进行显示。
如果选择N或n,则会显示如下信息:
如果输入的是其他错误选择:
第五章 结论
经过学习实现了算符优先算法,能够对输入的符号串进行算符优先分析,并且能够处理分析过程中遇到的错误。
经过这次课程设计的练习,我感觉自己的编程能力得到了很好的锻炼,是一次很好的实践活动,对以后的学习也有很大的帮助。
【附录】 程序清单
主程序:
(main.cpp)
#include<
iostream>
#include"
analysis.h"
usingnamespacestd;
intlenofstr2;
ifstreaminfile("
reduction.txt"
ios:
:
in);
charch;
charchoice;
intmain()
{
cout<
"
----------------------------------
---------"
endl;
Pleaseinputastring(endof#):
cin>
str2;
lenofstr2=str2.length();
if(str2[lenofstr2-1]!
str2+='
OperatorFun(str2);
Wanttoseetheresult?
(Y/N):
"
choice;
if(choice=='
y'
||choice=='
Y'
cout.put(ch);
cout<
infile.close();
}
elseif(choice=='
n'
||choice=='
N'
Youcanseetheresultinthefile..."
else
YourchoiceisWrong!
!
endl