LR分析实验报告.docx

上传人:b****5 文档编号:30749142 上传时间:2023-08-20 格式:DOCX 页数:27 大小:160.61KB
下载 相关 举报
LR分析实验报告.docx_第1页
第1页 / 共27页
LR分析实验报告.docx_第2页
第2页 / 共27页
LR分析实验报告.docx_第3页
第3页 / 共27页
LR分析实验报告.docx_第4页
第4页 / 共27页
LR分析实验报告.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

LR分析实验报告.docx

《LR分析实验报告.docx》由会员分享,可在线阅读,更多相关《LR分析实验报告.docx(27页珍藏版)》请在冰豆网上搜索。

LR分析实验报告.docx

LR分析实验报告

 

学号:

E10914106专业:

计算机科学与技术二班姓名:

杨雨露

 

实验日期:

2012/5/25教师签字:

成绩:

 

《编译原理》

 

课程实验报告

 

Word上实验四:

LR分析

 

引言1

 

第一章概述2

 

1.1设计题目及内容2

 

1.2设计环境2

 

第二章设计的基本原理3

 

2.1LR分析器的基本理3

 

2.2LR分析器工作过程算法3

 

第三章程序设计5

 

3.1总体方案设计5

 

3.2各模块设计5

 

第四章程序测试和结论以及心得..7

 

参考文献7

 

附录程序清单8

 

第一章概述

 

1.1设计题目及内容

设计题目:

根据LR分析表构造LR分析器

内容:

已知文法G:

(1)E→E+T

(2)E→T

(3)T→T*F

(4)T→F

(5)F→(E)

(6)F→I

LR分析表:

状态

ACTION(

动作)

GOTO(转换)

I

+

*

#

E

T

F

0

S5

S4

1

2

3

1

S6

Acc

2

R2

S7

R2

R2

3

R4

R4

R4

R4

4

S5

S4

8

2

3

5

R6

R6

R6

R6

6

S5

S4

9

3

7

S5

S4

10

8

S6

S11

9

R1

S7

R1

R1

10

R3

R3

R3

R3

11

R5

R5

R5

R5

 

注:

sj表示把下一状态j和现行输入符号a移进栈

rj表示按第j个产生式进行规约

acc表示接受

空格表示出错标志,报错

根据以上文法和LR分析表,构造LR分析器,并要求输出LR工作过程。

 

1.2设计环境

硬件设备:

一台PC机

软件设备:

Windows2000/XPOS,VC++6.0

实现语言:

C语言

 

第二章设计的基本原理

 

2.1基本原理

1.LR方法的基本思想:

在规范规约的过程中,一方面记住已移进和规约出的整个符号串,即记住

“历史”,另一方面根据所用的产生式推测未来可能碰到的输入符号,即对未来

进行“展望”。

当一串貌似句柄的符号串呈现于分析栈的顶端时,我们希望能够

根据记载的“历史”和“展望”以及“现实”的输入符号等三个方面的材料,来

确定栈顶的符号串是否构成相对某一产生式的句柄。

2.LR分析器实质上是一个带先进后出存储器(栈)的确定有限状态自动机。

3.LR分析器的每一步工作是由栈顶状态和现行输入符号所唯一决定的。

4.为清晰说明LR分析器实现原理和模型:

LR分析器的核心部分是一张分析表。

这张分析表包括两个部分,一是“动

作”(ACTION)表,另一是“状态转换”(GOTO)表。

他们都是二维数组。

ACTION(s,a)规定了当状态s面临输入符号a时应采取什么动作。

GOTO(s,X)规定了状态s面对文法符号X(终结符或非终结符)时下一状态是什么。

显然,GOTO(s,X)定

 

义了一个以文法符号为字母表的DFA。

每一项ACTION(s,a)所规定的动作不外是下述四种可能之一:

(1)移进把(s,a)的下一个转态s’=GOTO(s,X)和输入符号a

推进栈,下一输入符号变成现行输入符号。

(2)规约指用某一产生式A→β进行规约。

假若β的长度为r,规约

的动作是A,去除栈顶的r个项,使状态Sm-r变成栈顶状态,然后把(Sm-r,A)的下一状态s’=GOTO(Sm-r,A)和文法符号A推进栈。

规约动作不改变现行输入符号。

执行规约动作意味着β(=Xm-r+1,Xm)已呈现于栈顶而且是一个相对

于A的句柄。

(3)接受宣布分析成功,停止分析器的工作。

(4)报错发现源程序含有错误,调用出错处理程序。

 

2.2LR分析器工作过程算法描述

 

一个LR分析器的工作过程可看成是栈里的状态序列,已规约串和输入串所构成的三元式的变化过程。

分析开始时的初始三元式为

(s0,#,a1a2,,an#)

其中,s0为分析器的初态;#为句子的左括号;a1a2,,an为输入串;其后的

#为结束符(句子右括号)。

分析过程每步的结果可表示为

(s0s1,,sm,#X1X2,,Xmai,ai+1,,an#)

分析器的下一步动作是由栈顶状态sm和现行输入符号ai所唯一决定的。

即,执

行ACTION(sm,ai)所规定的动作。

经执行每种可能的动作之后,三元式的变化情形是:

(1)若ACTION(sm,ai)为移进,且s=GOTO(sm,ai),则三元式变成:

(s0s1,,sms,#X1X2,,Xmai,ai+1,,an#)

(2)若ACTION(sm,ai)={A→β},则按照产生式A→β进行规约。

此时三元式变为

(s0s1,,sms,#X1X2,,XmA,aiai+1,,an#)

此处s=GOTO(Sm-r,A),r为β的长度,β=Xm-r+1,,Xm。

(3)若ACTION(sm,ai)为“接受”,则三元式不再变化,变化过程终止,宣

 

布分析成功。

(4)若ACTION(sm,ai)为“报错”,则三元式的变化过程终止,报告错误。

一个LR分析器的工作过程就是一步一步的变换三元式,直至执行“接受”或“报错”为止。

 

第三章程序设计

 

3.1总体设计方案

 

建模

(1)分析表建模:

构造一个int型二维数组table[13][9],用于存放LR分析表。

并初始化。

作者这样规定:

0~11

表示

状态sj,其中0

对应s0,1对应s1,,

21~26

表示

规约rj,其中21

对应r1,22对应r2,,

12表示“接受”

-1表示规约出错,报错

(2)栈建模:

建立一个int型状态栈,该栈为顺序栈。

建立一个char型符号栈和一个char型输入串栈,该栈为顺序栈。

(3)规约表达式建模:

建立一个rule型结构,成员变量为char型非终结符和int型表示规约第几条表达式。

 

程序设计关键注意环节

(1)在输入串(句子)输入的过程中,涉及到一个压栈的问题。

但是输入串压入的字符顺序刚好与原理中的字符串模型刚好相反,这样需要先弹出的反而在栈底。

为了既要保证字符串输入,又要让输入的字符串存储顺序与输入的字符串相反。

采取以下措施:

先将输入的字符串压入符号栈symbol中,然后符号栈弹出的字符再压入输

入串栈instr中,这样实现了输入串的倒序存储。

(2)状态栈status_stack(status_p)和符号栈symbol_instr(symbol_p)

出(遍历)过程均采取自栈底到栈顶的顺序,而输入串栈symbol_instr(instr_p)

 

则是采取自栈顶到栈底的顺序输出。

 

 

3.2各模块设计

 

栈设计

构造一个int型“状态栈”status和一个char型“符号-输入串栈”

symbol_instr。

该栈包括初始化该栈init_status(),压栈push(),弹栈pop(),取栈顶元素

get_top(),自栈底到栈顶遍历元素out_stack1()和自栈顶到栈底遍历元素

out_stack2()。

LR分析器工作过程算法设计

构造一个状态转换函数实现状态转换

intgoto_char(status*status_p,symbol_instr*instr_p)

构造一个移进--规约函数实现移进规约动作

voidaction(status*status_p,symbol_instr*symbol_p,symbol_instr

*instr_p)

构造一个打印LR分析器的工作过程函数实现输出

voidprint(status*status_p,symbol_instr*symbol_p,symbol_instr

*instr_p)

 

流程图

 

初始化状态栈,符号栈,

输入串栈

 

输入串各字符压栈

 

求下一状态符号i

i=goto_char(status_p,instr_p)

 

i==-1?

 

i==12?

 

i>0&&i<=11

 

规约动作:

1.求出i对应规约规则右部

字符串长度x=r[i-21].y

2.在符号栈和状态栈中弹

出x个字符。

然后将该规

约规则左部压入输入串

 

规约出错!

常中止!

 

规约成功!

退

 

移进动作:

1.将现状态i压

push(status_p,i)

2.将当前输入串

字符压入符号

栈a=

pop(instr_p)

push(symbol_p,a)

 

打印该步工作过

 

LR分析器设计流程图

 

附录

程序源代码

 

一:

头文件lr.h

//LR分析表

#include

#include

//0--11表示状态结点,21--26表示规约标号,//-1表示error(出错),12表示acc(接受)inttable[13][9]={{5,-1,-1,4,-1,-1,1,2,3},\

{-1,6,-1,-1,-1,12,-1,-1,-1},\

{-1,22,7,-1,22,22,-1,-1,-1},\

{-1,24,24,-1,24,24,-1,-1,-1},\

{5,-1,-1,4,-1,-1,8,2,3},\

{-1,26,26,-1,26,26,-1,-1,-1},\

{5,-1,-1,4,-1,-1,-1,9,3},\{5,-1,-1,4,-1,-1,-1,-1,10},\{-1,6,-1,-1,11,-1,-1,-1,-1},\{-1,21,7,-1,21,21,-1,-1,-1},\{-1,23,23,-1,23,23,-1,-1,-1},\{-1,25,25,-1,25,25,-1,-1,-1}};

//规约规则structrule{charx;

inty;

}r[6]={{'E',3},{'E',1},{'T',3},{'T',1},{'F',3},{'F',1}};

//输入字符

charindex_char[9]={'i','+','*','(',')','#','E','T','F'};//

//获取index_char[9]中元素的位置intget_index_char(chari)

{

for(intj=0;j<9;j++)

{

if(index_char[j]==i)returnj;

}

return-1;

}

 

二:

头文件status_stack.h

#include

#include

#defineMAX20

 

typedefstruct{

intstack[MAX];

inttop;

}status;

//初始化栈

voidinit_stack(status*p)

{

 

if(!

p)

printf("\n初始化状态栈出错!

\n");

p->top=-1;

}

//压栈

voidpush(status*p,intx)

{

if(p->top

{

p->top++;

p->stack[p->top]=x;

}

elseprintf("\n状态栈溢出!

\n");

}

//弹栈

intpop(status*p)

{

intx;

if(p->top!

=0)

{

x=p->stack[p->top];

p->top--;

returnx;

}

else

{

printf("\n状态栈1空!

\n");

return0;

}

}

//取栈顶元素

intget_top(status*p)

{

intx;

if(p->top!

=-1)

{

 

x=p->stack[p->top];

returnx;

}

else

{

printf("\n状态栈2空!

\n");

return0;

}

}

//遍历栈元素

voidout_stack(status*p)

{

inti;

if(p->top<0)

printf("\n状态栈3空!

\n");

for(i=0;i<=p->top;i++)

{

printf("%d",p->stack[i]);

}

}

 

三:

头文件symbol_instr_stack..h

#include

#include

#defineMAX20

typedefstruct{

charstack[MAX];

inttop;

}symbol_instr;

//初始化栈

voidinit_stack(symbol_instr*p)

{

if(!

p)

printf("\n初始化符号栈出错!

\n");

p->top=-1;

}

//压栈

voidpush(symbol_instr*p,charx)

{

if(p->top

{

p->top++;

p->stack[p->top]=x;

}

 

elseprintf("\n符号栈溢出!

\n");

}

//弹栈

charpop(symbol_instr*p)

{

charx;

if(p->top!

=-1)

{

x=p->stack[p->top];

p->top--;

returnx;

}

else

{

printf("\n符号栈1空!

\n");

return0;

}

}

//取栈顶元素

charget_top(symbol_instr*p)

{

charx;

if(p->top!

=-1)

{

x=p->stack[p->top];

returnx;

}

else

{

printf("\n符号栈2空!

\n");

return0;

}

}

//自栈底到栈顶遍历栈元素

voidout_stack1(symbol_instr*p)

{

inti;

if(p->top<0)

printf("\n符号栈3空!

\n");

for(i=0;i<=p->top;i++)

{

printf("%c",p->stack[i]);

}

}

 

//自栈顶到栈底遍历栈元素

voidout_stack2(symbol_instr*p)

{

inti;

if(p->top<0)

printf("\n符号栈4空!

\n");

for(i=p->top;i>=0;i--)

{

printf("%c",p->stack[i]);

}

}

 

四:

主程序:

#include"status_stack.h"

#include"symbol_instr_stack.h"

#include"lr.h"

//打印LR分析器的工作过程

voidprint(status*status_p,symbol_instr*symbol_p,symbol_instr*instr_p)

 

{

inti;

out_stack(status_p);

for(i=0;i<20-status_p->top;i++)

printf("");

out_stack1(symbol_p);

for(i=0;i<20;i++)

printf("");

out_stack2(instr_p);

printf("\n");

}

//状态转换函数

intgoto_char(status*status_p,symbol_instr*instr_p)

{

charx;

inty,z;

x=get_top(instr_p);

y=get_top(status_p);

z=get_index_char(x);

returntable[y][z];

}

//移进--规约函数

voidaction(status

*status_p,symbol_instr

*symbol_p,symbol_instr

*instr_p)

{

 

inti,j,x;

chara;

i=goto_char(status_p,instr_p);

//规约出错if(i==-1)

printf("\n===============规约出错!

================\n");

//规约成功

if(i==12)

printf("\n===============规约成功!

================\n");

//移进动作if(i>=0&&i<=11)

{

push(status_p,i);

a=pop(instr_p);

push(symbol_p,a);

print(status_p,symbol_p,instr_p);

action(status_p,symbol_p,instr_p);

}

//规约动作

if(i>=21&&i<=26)

{

x=r[i-21].y;

for(j=0;j

{

pop(status_p);

pop(symbol_p);

}

push(instr_p,r[i-21].x);

action(status_p,symbol_p,instr_p);

 

}

}

 

intmain()

{

charx;

//分配空间status*status_p;

symbol_instr*symbol_p,*instr_p;

status_p=(status*)malloc(sizeof(status));

symbol_p=(symbol_instr*)malloc(sizeof(symbol_instr));instr_p=(symbol_instr*)malloc(sizeof(symbol_instr));

//初始化各栈

init_stack(status_p);

 

init_stack(symbol_p);

init_stack(instr_p);

//压进栈初始元素push(status_p,0);//push(symbol_p,'#');//

//输入表达式

printf("\n请输入要规约的输入串,各字符之间不能有空格,以'#'字

符结束!

\n");

printf("===========Expression=");

//先将输入串压进符号栈do{

 

scanf("%c",&x);

push(symbol_p,x);

}while(x!

='#');

//然后由符号栈弹出,压进输入栈

while(symbol_p->top!

=0)

{

x=pop(symbol_p);

push(instr_p,x);

}

printf("\n\n");

//打印框架

printf("\n状态栈==============符号栈==============输入串\n");

print(status_p,symbol_p,instr_p);//打印初始分析表

//移进,规约,并打印每一步分析过程

action(status_p,symbol_p,instr_p);

 

return0;

}

 

程序测试截图

 

(1)

 

(2)

 

图(3)

经过各种不同的输入表达式进行测试,测试结果准确无误。

完全符号设计要

求。

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

当前位置:首页 > 求职职场 > 简历

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

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