算符优先分析过程模拟Word格式.docx
- 文档编号:18609650
- 上传时间:2022-12-29
- 格式:DOCX
- 页数:10
- 大小:76.34KB
算符优先分析过程模拟Word格式.docx
《算符优先分析过程模拟Word格式.docx》由会员分享,可在线阅读,更多相关《算符优先分析过程模拟Word格式.docx(10页珍藏版)》请在冰豆网上搜索。
v=E
(2)E->
E+E
(3)E->
E-E
(4)E->
E*E
(5)E->
E/E
(6)E->
(E)
(7)E->
v
(8)E->
i
(二)、算符优先关系设计
通常在算术表达式求值过程中,运算次序是先乘除后加减,这说明了乘除运算先级别高于加减运算的优先级,乘除为同一优先级但运算符在前边的先做,这叫作左结合,同样加减运算也是如此,这也说明了运算的次序只与运算符有关,而与运算对象无关,因而我根据这样的基本原理开始设计运算符之间的优先关系。
(1)*,/的优先级别较高,高于+,-,遵循左结合。
相当于*>
*,*>
/,/>
*。
(2)+,-的优先级别较低,遵循左结合相当于+>
+,+>
-,->
+。
(3)对‘(’‘)’规定括号的优先性大于括号外的运算符,小于括号内的运算符。
(4)对于句子括号‘#’号规定与它相邻的任何运算符号的优先性都比它高。
、
(5)运算对象的终结符i,它优先级别最高。
算符优先关系表
+
-
*
/
(
)
i
#
>
<
=
I
(三)、理论结果分析
对于算符优先分析方法,在文法G下,预计总控程序的输出结果为:
对输入串i+i*i的归约过程
步骤
栈S
当前输入符
剩余串
动作
1
+i*i#
移进
2
#i
i*i#
归约E->
3
#E
4
#E+
*i#
5
#E+i
i#
6
#E+E
7
#E+E*
8
#E+E*i
9
#E+E*E
E*E
10
E+E
11
接受
分析过程:
1、S栈中的“#”优先级小于当前输入符号i,移进。
2、栈顶符号“i”优先级大于当前输入符号+,对终结符i进行归约。
3、栈顶符号“#”优先级小于当前输入符号+,移进。
4、栈顶符号“+”优先级小于当前输入符号i,移进。
5、栈顶符号“i”优先级大于当前输入符号*,对终结符i进行归约。
6、栈顶符号“+”优先级小于当前输入符号*,移进。
7、栈顶符号“*”优先级小于当前输入符号i,移进。
8、栈顶符号“i”优先级大于当前输入符号#,对终结符i进行归约。
9、栈顶符号“*”优先级大于当前输入符号#,归约,E->
E*E。
10、栈顶符号“+”优先级大于当前输入符号#,归约,E->
E+E。
11、接受。
三、详细设计
(一)、设计思路
大多数对于算符优先分析方法都是设计两个栈,通过比较符号栈顶元素和邻近的运算符之间的优先关系。
进行归约,移进的控制。
而我用的却是另一种方法。
我将所输入的句型放在一个字符串Mystr中,然后对字符串进行扫描,当扫描到的当前字符是“+,-,*,/,()”时分别调用与之对应的五种不同的方法,当当前字符(token)是“+”调用方法evalExp2(),
因为*/法和()的有线级高于“+”法,所以在evalExp2()中要调用evalExp3()扫描后续的句子,后续的句子如果有“*,/”法,用evalExp3()完成对“*,/”法的归约。
同理括号中的算法的优先级别高于括号外的,所以evalExp3()的方法中要先调用evalExp4()对于括号的归约方法。
在完成后依次回溯到前一个方法,很明显我是通过递归的方法来实现算符优先关系。
当然对于加减法evalExp2(),乘除法evalExp3(),括号evalExp4(),它们都可以单独调用,这由当前输入字符Taken确定。
归约的实现实际上是对字符串的处理,在下面的“模块设计”中将具体解释。
(二)、模块设计
1、对于加减法的归约。
privatecharevalExp2()throwsParserException
{
charresult;
charpartialResult;
result=evalExp3();
//调用乘除法的归约方法
if(result!
='
E'
&
result!
v'
i'
return'
Q'
;
//非法字符的判断,退出。
else{
while(token=='
+'
||token=='
-'
){
charabc=token;
my[expIdx-1]="
终结符"
//读入当前运算符号
getToken();
//读取下一个字符
if(token=='
){
error="
语法错误"
handleErr(error);
return'
}
else{//mystr用于保存输入的句子,mydel用于"
动作"
的输出
partialResult=evalExp3();
mystr[ind]=mystr[ind-1];
mydel[ind]=mydel[ind-1];
ind++;
if("
+-*/)"
.indexOf(token)==-1||!
mycmp)
{
mystr[ind-1]=mystr[ind-2].substring(0,mystr[ind-2].indexOf(abc,2))+mystr[ind-2].substring(mystr[ind-2].indexOf(abc,2)+2);
mydel[ind-1]="
归约"
+"
E→E"
+abc+"
E"
if(mystr[ind-3].indexOf(abc,mystr[ind-3].indexOf(abc)+1)!
=-1){
mystr[ind-2]=mystr[ind-3].substring(0,mystr[ind-3].indexOf(abc,mystr[ind-3].indexOf(abc)+1))+mystr[ind-3].substring(mystr[ind-3].indexOf(abc,mystr[ind-3].indexOf(abc)+1)+2);
mystr[ind-1]=mystr[ind-1].substring(0,mystr[ind-1].indexOf(abc,mystr[ind-1].indexOf(abc)+1))+mystr[ind-1].substring(mystr[ind-3].indexOf(abc,mystr[ind-1].indexOf(abc)+1)+2);
else{//对于字符串的归约
mystr[ind-2]=mystr[ind-3].substring(0,mystr[ind-3].indexOf(abc,2))+mystr[ind-3].substring(mystr[ind-3].indexOf(abc,2)+2);
mystr[ind-1]=mystr[ind-1].substring(0,mystr[ind-1].indexOf(abc,2))+mystr[ind-1].substring(mystr[ind-1].indexOf(abc,2)+2);
mydel[ind-2]="
if(partialResult!
partialResult!
}
对于加减法归约的方法实际上是对存储句子的字符串mystr的操作,
给定一个句子,程序从逐个读入字符,当出现“+,-”号时调用evalExp2(),在一系列的合法性判断之后,进行规约。
这里主要用到了substring(int
start,int
end),方法,这是读取指定位置的字串。
例如,我们现在有一个句子v=E+E*E,要对加减法归约,先通过INDEX方法读取到加号的位置,然后对字符串的前后求子串,
我们可以把所有的句子假设为…E+E…的形式,并假设当前算符位置为taken通过substring(0,taken-1)读出前一个“…”,
然后连接上规约的结果E(E->
E+E),最后再连接上后面的子串直接用substring(taken+1)输出后面的子串。
最终将…E+E…的形式规约为…E…的形式。
对于乘除法和括号的规约方法和加法的归约方法基本类似,也是对字符串的处理,由此实现对运算符的归约。
2、读取下一个字符,对E->
i的归约。
privatevoidgetToken()
if(expIdx==exp.length()){
mycmp=false;
token='
return;
//滤去空格
while(expIdx<
exp.length()&
Character.isWhitespace(exp.charAt(expIdx)))++expIdx;
if(expIdx==exp.length()){
}
//读取下一个字符
token=exp.charAt(expIdx);
mystr[ind]=mystr[ind-1]+token;
mydel[ind]="
移进"
wyq=wyq+token+"
"
if(cmp){
if(("
+-/*()Evi="
.indexOf(token)!
=-1)){
expIdx++;
cmp=false;
handleErr("
非法字符"
);
//对E->
i的归约
+-/*()Evi"
=-1)){
expIdx++;
if(("
vi"
=-1)&
ind!
=2){
mystr[ind]=mystr[ind-2]+"
mydel[ind]="
E→"
+token;
ind++;
}
由算符优先分析表我们知道终结符i的优先级别是最高的,也就是说当读入到i时立即进行归约,于是我在读取到下一个字符的时候先进行判断,当这个字符是i时,立即归约。
四、测试结果
(一)、规定测试用例
(二)、对于有括号句型的分析
(三)、无法接受情况
(四)、接受到非法字符
五、总结
一个星期的课程设计结束了,但真正的学习才刚刚开始。
就像古语说的一样,事情都是看起来容易做起来难,说实话算符优先在我看来,是编译原理中比较简单的一个算法,但也就是这样一个简单的算法摧残了我近一个星期,不停的有新的问题,不停的需要修改,不断的翻书,很可惜还是没能用书上的方法实现。
虽然最后用递归的方法模拟了这个算法,却觉得还是不那么舒服,写报告的这两天我又去看了些别人写的代码,算是加深了对栈的理解吧。
其实,出现了问题并不可怕,可怕的是你逃避已经出现了的问题,或许我们在大学学到的就是解决问题的方法。
谢谢黄老师一个学期以来对我的帮助和指导,黄老师将会是给我影像较深的一个老师,我依然记得您在上课时,当听到学生不认真听讲或者睡觉时,那种恨铁不成钢的焦急心态,不知道我为什么始终记得这样的一件事,或许是能这样做的人太少了吧,呵呵。
最后祝您在以后的日子里,一切顺心。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 优先 分析 过程 模拟
![提示](https://static.bdocx.com/images/bang_tan.gif)