FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx

上传人:b****5 文档编号:5667991 上传时间:2022-12-31 格式:DOCX 页数:62 大小:279.35KB
下载 相关 举报
FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx_第1页
第1页 / 共62页
FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx_第2页
第2页 / 共62页
FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx_第3页
第3页 / 共62页
FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx_第4页
第4页 / 共62页
FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx_第5页
第5页 / 共62页
点击查看更多>>
下载资源
资源描述

FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx

《FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx》由会员分享,可在线阅读,更多相关《FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx(62页珍藏版)》请在冰豆网上搜索。

FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文.docx

FOR循环语句的翻译程序设计LL1法输出四元式含代码和实验报告册毕业设计论文

FOR循环语句的翻译程序设计

——LL

(1)法、输出四元式

1.系统描述

1.1问题描述

用LL

(1)法设计、编制、调试一个FOR(表达式1;表达式2;表达式3)〈赋值语句〉的语法及语义分析程序,输出四元式。

1.2功能描述

(1)能够识别出单词、单词类型、单词位置

(2)能够用LL

(1)方法识别单词序列是否符合FOR循环文法

(3)能够完成对FOR循环中3个表达式的翻译

(4)能够完成对FOR循环中赋值语句(含复杂表达式)的翻译

(5)能够对FOR循环3个表达式中有表达式1或3缺少时翻译

(6)能够用标准化的四元式进行翻译结果输出

(7)能够用四元式清晰、正确地反映FOR循环的执行流程

(8)能够用文本输入FOR语句循环,再用txt文本输出分析结果

2文法及属性文法的描述

2.1文法的语言描述

A->for(条件){赋值语句}

条件->语句1语句2语句3

语句1->i=表达式;//i表示标识符

语句1->;

语句2->i>表达式;

语句2->i<表达式;

语句3->i=表达式;

语句3->

赋值语句->m=表达式//m表示标识符,作为左值出现

赋值语句->

表达式->表达式+表达式

表达式->表达式-表达式

表达式->表达式*表达式

表达式->表达式/表达式

表达式->(表达式)

表达式->i//i表示标识符、常数、字符、或字符串

2.2属性文法描述

2.2.1FOR语句

FOR(CDG)

nC

n+1ifD==truegotoY.start

n+2gotoY.end+3

Y.start...................//赋值语句的开始

.........................

Y.end...................//赋值语句结束

Y.end+1G

Y.end+2goton+1

Y.end+3//跳出循环体后第一条语句

2.2.2赋值语句

Y->m=E;{m.value=E.Value}

E->E1opE2(op:

+,-,*,/,>或<)

{

E.place=newtemp;//生成新的变量

E.value=E1.valueopE2.value

}

N->(E){N.value=E.value}

N->i{N.value=i.value}

3.语法分析方法描述及语法分析表设计

3.1对LL

(1)分析的描述

LL

(1):

第1个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将用最左推导,1表明只需向右看一个符号便可决定如何推导即选择哪个产生式(规则)进行推导。

从文法的开始符号出发企图推导出与输入的单词串完全相匹配的句子,若输入串是文法给定的句子,则必能推出,反之必然出错。

LL

(1)优点:

实现方法简单、直观,便于手工构造或自动生成语法分析器。

文法很容易写出。

LL

(1)缺点:

对文法有一定得限制,要求推导过程中紧跟在飞终结符右边可能出现的终结符集不相交。

另外在做语法制导翻译时中间代码的输出方案相对于LR法比较复杂。

LR分析法的句柄即体现了算符的优先级,出现句柄即做相应的归约动作,中间代码很容易写出,实现很简单。

LL

(1)是做自顶向下推导,因此设计LL

(1)的语法制导翻译输出中间代码很需要技巧,涉及到了判断符号的优先级。

3.2语法分析表设计

文法(消除了左递归)及相应的选择符集

NO.

文法

SELECT集

0

A->f(B){Y}

{f}

1

B->CDG

{;,i}

2

Y->

{}}

3

Y->m=E

{m}

4

C->;

{;}

5

C->i=E

{i}

6

D->iF;

{i}

7

F->

{<}

8

F->>E

{>}

9

G->

{)}

10

G->i=E

{i}

11

E->LM

{(,i}

12

M->+LM

{+}

13

M->-LM

{-}

14

M->

{),;}

15

L->NP

{(,i}

16

P->*NP

{*}

17

P->/NP

{/}

18

P->

{+,-,),;}

19

N->i

{i}

20

N->(E)

{(}

3.3预测分析表设计

表达式文法的预测分析表

f

i

m

;

<

>

+

-

*

/

{

}

=

A

0

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

B

-1

1

-1

1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

C

-1

5

-1

4

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

D

-1

6

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

E

-1

11

-1

-1

-1

-1

-1

-1

-1

-1

11

-1

-1

-1

-1

F

-1

-1

-1

-1

7

8

-1

-1

-1

-1

-1

-1

-1

-1

-1

G

-1

10

-1

-1

-1

-1

-1

-1

-1

-1

-1

9

-1

-1

-1

L

-1

15

-1

-1

-1

-1

-1

-1

-1

-1

15

-1

-1

-1

-1

M

-1

-1

-1

14

-1

-1

12

13

-1

-1

-1

14

-1

-1

-1

N

-1

19

-1

-1

-1

-1

-1

-1

-1

-1

20

-1

-1

-1

-1

P

-1

-1

-1

18

-1

-1

18

18

16

17

-1

18

-1

-1

-1

Y

-1

-1

3

-1

-1

-1

-1

-1

-1

-1

-1

-1

-1

2

-1

说明:

1.第1列为终结符,第1行为非终结符

2.非终结符与终结符的交点出表示将要选择哪个产生式做预测分析进行推导

3.-1表示出错,其余数字为产生式的序号NO,表示选择相应的产生式

4.间代码形式的描述及中间代码序列的结构设计

4.1四元式描述

四元式是一种比较普遍采用的中间代码形式。

四元式的四个组成部分是:

算符op,第一和第二运算对象ARG1和ARG2及运算结果RESULT,运算对象和运算结果有时指用户自己定义的变量,有时指编译程序引进的临时变量。

例如a=b*c+b*d的四元式表示如下:

  

(1)(*,b,c,t1)

  

(2)(*,b,d,t2)

  (3)(+,t1,t2,t3)

(4)(=,t3,-,a)

四元式表示很类似于三地址指令,有时把这类中间表示称为“三地址代码”,因为这种表示可以看成一种虚拟三地址机的通用汇编码,即这种虚拟机的每条“指令”包含操作符和三个地址,两个是为运算对象的,一个为结果的。

有时为了更直观,也把四元式写成简单赋值形式。

(1)t1=b*c

(2)t2=b*d

(3)t3=t1+t2

(4)a=t3

把(jump,—,—,L)写成gotoL

把(jrop,B,C,L)写成ifBropCgotoL

我采用的是更直观的形式。

4.2中间代码序列的结构设计

以for(i=0;i

中间代码序列的结构应如下:

1.i=0

2.ifi

3.goto11

4.t1=n-1

5.t2=t1/5

6.t3=3*2

7.t4=t2-t3

8.m=t4

9.i=i+1

10.goto2

11.

我的中间代码结构是这样设计的:

第1条语句输出表达式1,表达式为空时输出空行;

第2条输出条件判断;

第3条输出gototemp+7;

第4条至第4+temp条输出赋值语句的四元式;

第5+temp条输出条件表达式3;

第6+temp条输出"goto2"

第7+temp条输出空

说明:

其中temp表示最终生成的中间变量个数,例如上例中,生成了t1,t2,t3,t4共4个中间变量,所以temp=4.

由于临时变量的产生个数是未知的,在语法制导翻译中要先对语句进行保存,等临时变量temp产生完后在对相应中间代码语句进行回填,最后输出。

以便达到输出的中间代码跳转出入口及顺序是正确的。

5.编译系统的概要设计

5.1问题分析

在该阶段严格按照设计指导书,分析要完成什么功能。

词法分析提取单词,写出正确的文法,语法分析检查输入单词串是否符合文法,语义分析完成中间代码的输出,使用LL

(1)法语法分析。

5.2LL

(1)分析

根据平时课程对LL

(1)分析方法的学习,把握好分析方法的实质。

即从左向右扫描输入串,自顶向下最左推导。

推导时非终结符面临剩余输入串串头采用相应的推导产生式,产生式右边进分析栈,栈顶为首符。

若首符为非终结符,则继续推导;

若首符为终结符,则匹配,匹配不成功报错,匹配成功栈顶下移,剩余串串头右移。

重复该过程,直至结束。

5.3符合for循环的文法

过程非常重要,文法写不好,就会产生推导时面临相同选择符的推导冲突,并且文法往往决定了你能够分析的语句有哪些格式,哪些能够处理,哪些不能够处理。

对于for循环语句,要考虑到表达1可以为空,表达式3也可以为空,这样根据是否有表达式1,3有4种情况。

对于赋值语句,赋值语句,应该考虑到赋值语句为空的特殊情况,因为在采用for循环延时的时候,赋值语句就是空的。

对于赋值语句,不能是简简单单的m=b;还应该有m=b+c*d(e-f)/n这样的复杂的赋值语句。

5.4语义动作

语义分析,其实关键还是在于赋值语句上。

因为赋值语句是有优先级的,而语法分析时LL

(1)只是自左向右扫描,推导,匹配,并没涉及到优先级。

因此在写出文法后要给出恰当的语义动作。

我在设计时使用了算符栈和操作数栈。

当输入串串头为算符时,用算符栈栈顶算符与输入串串头算符进行比较。

若大于,栈顶算符退栈,操作数栈退出两个操作数,执行运算,产生中间变量,再中间变量进栈;若小于,则串头算符进算符栈;若等于,表明是(和)匹配,将(退栈。

6.详细的算法描述

6.1伪代码概述

(1)扫描输入的字符char_input[],将字符根据构词规则截取出一个个单词word_input[]。

根据不同类型的单词有不同的构词规则进行单词类型分类word_tyep[],并记录其出现的位置word_position[]。

(2)#进分析栈,开始符A进分析栈

(3)取符号栈顶元素a和剩余输入串队头元素b,

若a为非终结符,那么以(a,b)在预测分析表找到对应的数字i,根据i找到产生式。

若i为-1则出错,报出错误。

找到产生式后,a退栈,产生式入栈,按照产生式从右向左对应分析栈从底向顶的对应顺序入栈。

重复(3)

若a为终结符,则根据(a==b),匹配成功,则a出栈,串头后移。

若a不为"#",重复(3)。

a为"#",执行(4)。

匹配失败则报错。

(4)输出“匹配成功!

6.2语义动作方案

6.2.1赋值语句动作

while(c_get!

=";"||GetTop(OPTR,OPTR_i)!

=';')

{

if(!

In(c_get,OP))

{PushND(OPND,c_get,OPND_i);l++;c_get=a[l];}

else

switch(Precede(GetTop(OPTR,OPTR_i),c_get))//运算优先级的比较

{

case'<':

PushTR(OPTR,c_get,OPTR_i);

l++;

c_get=a[l];

break;

case'=':

x=PopTR(OPTR,OPTR_i);

l++;

c_get=a[l];

break;

case'>':

optr=PopTR(OPTR,OPTR_i);

opnd2=PopND(OPND,OPND_i);

opnd1=PopND(OPND,OPND_i);

PushND(OPND,Operate(opnd1,optr,opnd2,temp_i),OPND_i);

break;

}

}

(1)如果c_get为是标识符,PushND(OPND,c_get,OPND_i);将C_get入操作数栈OPND

(2)如果c_get是算符,Precede(GetTop(OPTR,OPTR_i),c_get),将OPTR这个运算符栈的栈顶运算符与c_get比较,出现>,<,或=

(3)若<,则PushTR(OPTR,c_get,OPTR_i),将c_get算符入栈OPTR

若=,则c_get为),栈顶算符为(,x=PopTR(OPTR,OPTR_i),将(退栈。

若>,则可以运算了:

optr=PopTR(OPTR,OPTR_i)运算符出栈

opnd2=PopND(OPND,OPND_i)先出操作数栈的是第2操作数

opnd1=PopND(OPND,OPND_i)后出操作数栈的是第1操作数

PushND(OPND,Operate(opnd1,optr,opnd2,temp_i),OPND_i)计算结果作为临时变量压入操作数栈。

temp_i记录临时变量的个数

执行Operated()时,将运算四元式保存到expression[]中,作为将来输出标准的四元式使用。

expression[temp_i]=temp[temp_i]+"="+opnd1+optr+opnd2;temp_i++

6.2.2FOR句动作

以FOR语句中的2个;和1个)为界,在语法分析时截取表达式:

Quaternion[1]中存储语法分析截取的第1个表达式

Quaternion[2]中存储语义分析截取的第2个表达式

Quaternion[3]中存储语义分析截取的第3个表达式

cout<<1<<"."<

cout<<2<<"."<<"if"<

cout<<3<<"."<<"goto"<<3+4+temp_i<

temp_i记录在语法分析制导中赋值表达式产生中间变量的个数,因此goto语句的地址入口要等赋值语句做完产生所有的临时变量后才能知道。

...........赋值语句动作...............

cout<<5+temp_i<<"."<

cout<<6+temp_i<<"."<<"goto2"<

cout<<7+temp_i<

7.软件的测试方法和测试结果

7.1测试方法

根据自己当初的设计思想,设计了测试用例。

包括没有for中第1个表达式的情况,没有第3个表达式的情况,没有赋值语句的情况,赋值语句比较复杂等情况。

用文本输入for循环语句,用txt文本输出分析出的四元式。

7.2测试用例

在文本文件中输入源程序:

for(i=0;i

输入测试文件:

词法分析结果:

其中第一列为位置序号;第二列为截取的单词;第三列为类型

类型1:

关键字类型2:

标识符类型3:

常数类型4:

运算符类型5:

界符

语法分析结果:

语义分析结果:

输出四元式,txt文档记录:

8研制报告

8.1研制过程

8.1.1分析过程

本次课程设计在思考阶段花费了两天多的时间,开始时做过赋值语句的词法分析、语法分析和语义分析,不过使用LR方法做的。

感觉LR方法比较简单一些。

但是实验题目要求我要用LL

(1)方法来做,开始时不知如何下手,有一些担心自己做不出来的情绪。

后来就从LL

(1)的思想着手,从代表性的例题看起,按部就班的来。

感觉LL

(1)方法做语法分析比LR法要简单。

但是LL

(1)方法做语法制导翻译比LR法要复杂一些。

我的观点是:

LL

(1)方法单纯的做语法分析很简单,从左向右,自顶向下,没有优先级可言,语法分析匹配了则成功,不匹配则失败,但是对于语义动作要通过优先级来考虑,例如如a-b*c+d,a匹配,-匹配,b匹配,总不能做a-b,而是要a入操作数栈,-入算符栈,b入操作数栈,-优先级小于*,所以不做a-b,而*优先级大于+,可以做b*c,在比较-和+优先级;LR法在做语法分析时,要画识别文法活前缀的DFA,这点比较繁琐,但它把优先级的思想通过句柄来体现,句柄出现则进行归约,在把含*短语归约之前,绝不会把含-短语先归约,这样就很容易通过非常简单语义动作产生后缀式。

虽然用LL

(1)做语义动作困难一些,我想不妨先易后难,先把语法分析作出来,在做语义动作的时候因为是用语法制导,可以在写程序时加入语义动作。

因为以前做LR法分析赋值语句的时候我就是这么做的。

8.1.2写文法的过程

写文法的时候,因为要考虑到for循环的3个表达式,一般来说第2个表达式条件控制是必须的,而第1个和第3个可以为空的。

对于赋值语句,可以有,也可以是空的。

因此在考虑时要有推出为空的情况。

同时要保证所写文法不能含有左递归,相同非终结符所用产生式的select集不能有交集。

我的思想是尽量让右边的产生式以终结符作为开头。

这样会减少交集情况,减少左递归。

但是事实最后证明,这种方法有缺陷,进一步限制了文法。

由于开始没有考虑循环嵌套,所以没有实现for循环的嵌套的语法语义分析。

8.2本设计的评价特点、不足

本设计的优点在于能够将词法分析结果、语法分析结果清晰的展现出来,词法分析输出了单词、类型,位置,语法分析过程的每一步都输出了分析栈和剩余串,可以对照文法验证推导的正确性。

能够输出正确的四元式,找到正确的出口和入口。

能够对for循环中缺少表达式1或表达式3的情况进行相应处理,能够处理赋值语句为空的情况,能够处理复杂的赋值语句。

不足之处是,没有考虑到循环的嵌套,不能对嵌套的for循环进行语义分析,没有进行赋值时的类型分析,如不同类型变量之间的赋值。

8.3收获体会

本次编译课程设计收获到很多东西,最大的收获在于认识到了自己的不足,对编译原理的基本方法有了初步了解。

结合相关书籍以及互联网上的资料,实现了本次程序的研制。

在确定了所要设计的for语句属性文法之后,对程序整体划分了几个部分进行分析。

在这几天的课程设计里,暴露出了个人能力需要很大提高这个缺陷,在txt文档输出中,有时候会出现文件名弄错导致不能文档输出的现象,进过改进和不断地测试,最终完成了该课程设计,达到了基本的课设要求。

在今后的学习中,我会多多向他人学习,多借鉴他人优秀的编程方法和思想,并且多做练习,达到学以致用,有时间的话我会把这个程序做的更加完美。

9.参考文献

[1]殷人昆.数据结构(用面向对象方法与C++语言).清华大学出版社.2003.02

[2]闵联营,何克右.C++程序设计教程(第二版).武汉理工大学出版社.2005.07

[3]张素琴,吕映芝,蒋维杜,戴桂兰.编译原理(第2版).清华大学出版社.2002.06

[4]李文生.编译程序设计原理与技术.北京邮电大学出版社.2006.05

/////////////////////////////////处理空格问题如inta;intb;处理数值问题,整数,小数等;处理读入读出问题,文件

//;处理报错、纠错问题;处理格式类问题;

#include

#include

#include

#include

#include

usingnamespacestd;

intpredictor[12][15]=

{

//01234567891011121314

//fim;<>+-*/(){}=

/*00A*/{0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},

/*01B*/{-1,1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},

/*02C*/{-1,5,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},

/*03D*/{-1,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},

/*04E*/{-1,11,-1,-1,-1,-1,-1,-1,-1,-1,11,-1,-1,-1,-1},

/*05F*/{-1,-1,-1,-1,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},

/*06G*/{-1,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,-1,-1,-1},

/*07L*/{-1,15,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,-1},

/*08M*/{-1,-1,-1,14,-1,-1,12,13,-1,-1,-1,14,-1,-1,-1},

/*09N*/{-1,19,-1,-1,-1,-1,-1,-1,-1,-1,20,-1,-1,-1,-1},

/*10P*/{-1,-1,-1,18,-1,-1,18,18,16,17,-1,18,-1,-1,-1},

/*11Y*/{-1,-1,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,-1}

};

stringgrammar[21]=//文法

{

/*00A*/"}Y{)B(f",//A->f(B){Y}

/*01B*/"GDC",//B->CDG

/*02Y*/"",//Y->0

/*03Y*/";E=m",//Y->m=E;

/*04C*/";",//C->;

/*05C*/";E=i",//C->i=E;

/*06D*/";Fi",//D->iF;

/*07F*/"E<",//F->

/*08F*/"E>",//F->>E

/*09G*/"",//G

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

当前位置:首页 > 医药卫生 > 基础医学

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

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