算符优先分析过程模拟.docx

上传人:b****5 文档编号:6343189 上传时间:2023-01-05 格式:DOCX 页数:10 大小:76.29KB
下载 相关 举报
算符优先分析过程模拟.docx_第1页
第1页 / 共10页
算符优先分析过程模拟.docx_第2页
第2页 / 共10页
算符优先分析过程模拟.docx_第3页
第3页 / 共10页
算符优先分析过程模拟.docx_第4页
第4页 / 共10页
算符优先分析过程模拟.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

算符优先分析过程模拟.docx

《算符优先分析过程模拟.docx》由会员分享,可在线阅读,更多相关《算符优先分析过程模拟.docx(10页珍藏版)》请在冰豆网上搜索。

算符优先分析过程模拟.docx

算符优先分析过程模拟

目 录

一、需求分析

算符优先分析是自底而上分析方法的一种,这种方法是对输入符号串自左向右进行扫描,并将输入符逐个移入一个后进先出栈中,边移入边分析,一旦栈顶符号串形成某个句型的句柄或可规约串时(该句柄或可归约串对应产生式的右部),就用该产生式的左部非终结符代替相应右部的文法符号串,重复这样的归约过程,一直到只剩文法的开始符号时则为分析成功,也就是确认输入串是该文法的句子。

而算符优先分析的基本思想则是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系,由于算符优先分析不考虑非终结符之间的优先关系,在归约过程中只要找到可归约的串就归约,并不考虑归约到那个非终结符名。

在定义具体的由于算符优先关系之前,先说明由于算符优先关系符的定义,有三中由于算符优先关系符,分别是>,<,=

设G是一个不含ε产生式的算符文法,a,b是任意两个终结符,A,B,C是非终结符,算符优先关系=,<,>定义如下:

(1)a=b当且仅当G中含有形如A->…ab…或A->…aBb…的产生式

(2)a…aB…的产生式,且B可以多步推导出b…或B可以多步推倒出Cb…

(3)a>b当且仅当G中有型如A->…Bb…的产生式,且B可以多步推导出…a或B可以多步推导出…Ac

因为算符优先关系运算的次序只与运算符有关,而与运算对象无关,明显,对于算符优先文法的设计成为了关键。

二、概要设计

(一)、文法设计

算符优先分析只考虑算符(终结符)之间的优先关系,先设计文法G为:

(1)S->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*i#

移进

2

#i

+

i*i#

归约E->i

3

#E

+

i*i#

移进

4

#E+

i

*i#

移进

5

#E+i

*

i#

归约E->i

6

#E+E

*

i#

移进

7

#E+E*

i

#

移进

8

#E+E*i

#

归约E->i

9

#E+E*E

#

归约E->E*E

10

#E+E

#

归约E->E+E

11

#E

#

接受

分析过程:

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'&&result!

='i')

return'Q';//非法字符的判断,退出。

else{

while(token=='+'||token=='-'){

charabc=token;

my[expIdx-1]="终结符";//读入当前运算符号

getToken();//读取下一个字符

if(token=='Q'){

error="语法错误";

handleErr(error);

return'Q';

}

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";

}

else{

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]="归约"+"E→E"+abc+"E";

}

if(partialResult!

='E'&&partialResult!

='v'&&partialResult!

='i')

return'Q';

}

}

return'E';

}

}

对于加减法归约的方法实际上是对存储句子的字符串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='Q';

return;

}

//滤去空格

while(expIdx

Character.isWhitespace(exp.charAt(expIdx)))++expIdx;

if(expIdx==exp.length()){

mycmp=false;

token='Q';

return;

}

//读取下一个字符

token=exp.charAt(expIdx);

mystr[ind]=mystr[ind-1]+token;

mydel[ind]="移进";

wyq=wyq+token+"";

ind++;

if(cmp){

if(("+-/*()Evi=".indexOf(token)!

=-1)){

expIdx++;

}

else{

cmp=false;

handleErr("非法字符");

return;

}

cmp=false;

}

//对E->i的归约

else{

if(("+-/*()Evi".indexOf(token)!

=-1)){

expIdx++;

if(("vi".indexOf(token)!

=-1)&&ind!

=2){

mystr[ind]=mystr[ind-2]+"E";

mydel[ind]="归约"+"E→"+token;

ind++;

}

}

else{

handleErr("非法字符");

return;

}

}

return;

}

由算符优先分析表我们知道终结符i的优先级别是最高的,也就是说当读入到i时立即进行归约,于是我在读取到下一个字符的时候先进行判断,当这个字符是i时,立即归约。

四、测试结果

(一)、规定测试用例

(二)、对于有括号句型的分析

(三)、无法接受情况

(四)、接受到非法字符

五、总结

一个星期的课程设计结束了,但真正的学习才刚刚开始。

就像古语说的一样,事情都是看起来容易做起来难,说实话算符优先在我看来,是编译原理中比较简单的一个算法,但也就是这样一个简单的算法摧残了我近一个星期,不停的有新的问题,不停的需要修改,不断的翻书,很可惜还是没能用书上的方法实现。

虽然最后用递归的方法模拟了这个算法,却觉得还是不那么舒服,写报告的这两天我又去看了些别人写的代码,算是加深了对栈的理解吧。

其实,出现了问题并不可怕,可怕的是你逃避已经出现了的问题,或许我们在大学学到的就是解决问题的方法。

谢谢黄老师一个学期以来对我的帮助和指导,黄老师将会是给我影像较深的一个老师,我依然记得您在上课时,当听到学生不认真听讲或者睡觉时,那种恨铁不成钢的焦急心态,不知道我为什么始终记得这样的一件事,或许是能这样做的人太少了吧,呵呵。

最后祝您在以后的日子里,一切顺心。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1