递归下降分析实验报告.docx

上传人:b****4 文档编号:5415791 上传时间:2023-05-08 格式:DOCX 页数:30 大小:59.66KB
下载 相关 举报
递归下降分析实验报告.docx_第1页
第1页 / 共30页
递归下降分析实验报告.docx_第2页
第2页 / 共30页
递归下降分析实验报告.docx_第3页
第3页 / 共30页
递归下降分析实验报告.docx_第4页
第4页 / 共30页
递归下降分析实验报告.docx_第5页
第5页 / 共30页
递归下降分析实验报告.docx_第6页
第6页 / 共30页
递归下降分析实验报告.docx_第7页
第7页 / 共30页
递归下降分析实验报告.docx_第8页
第8页 / 共30页
递归下降分析实验报告.docx_第9页
第9页 / 共30页
递归下降分析实验报告.docx_第10页
第10页 / 共30页
递归下降分析实验报告.docx_第11页
第11页 / 共30页
递归下降分析实验报告.docx_第12页
第12页 / 共30页
递归下降分析实验报告.docx_第13页
第13页 / 共30页
递归下降分析实验报告.docx_第14页
第14页 / 共30页
递归下降分析实验报告.docx_第15页
第15页 / 共30页
递归下降分析实验报告.docx_第16页
第16页 / 共30页
递归下降分析实验报告.docx_第17页
第17页 / 共30页
递归下降分析实验报告.docx_第18页
第18页 / 共30页
递归下降分析实验报告.docx_第19页
第19页 / 共30页
递归下降分析实验报告.docx_第20页
第20页 / 共30页
亲,该文档总共30页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

递归下降分析实验报告.docx

《递归下降分析实验报告.docx》由会员分享,可在线阅读,更多相关《递归下降分析实验报告.docx(30页珍藏版)》请在冰点文库上搜索。

递归下降分析实验报告.docx

递归下降分析实验报告

实习二递归下降分析

一、实验目的:

根据某一文法编制调试递归下降分析程序.以便对任意输入的符号串进行分析。

本次实验的目的主要是加深对递归下降分析法的理解。

二、实验预习提示

1、递归下降分析法的功能

词法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。

2、递归下降分析法的前提

改造文法:

消除二义性、消除左递归、提取左因子.判断是否为LL〔1文法.

3、递归下降分析法实验设计思想及算法

为G的每个非终结符号U构造一个递归过程,不妨命名为U。

U的产生式的右边指出这个过程的代码结构:

<1>若是终结符号.则和向前看符号对照.若匹配则向前进一个符号;否则出错。

<2>若是非终结符号.则调用与此非终结符对应的过程。

当A的右部有多个产生式时,可用选择结构实现。

具体为:

〔1对于每个非终结符号U->u1|u2|…|un处理的方法如下:

U<>

{

ch=当前符号;

if处理u1的程序部分;

elseif处理u2的程序部分;

elseerror<>

}

〔2对于每个右部u1->x1x2…xn的处理架构如下:

处理x1的程序;

处理x2的程序;

处理xn的程序;

〔3如果右部为空.则不处理。

〔4对于右部中的每个符号xi

①如果xi为终结符号:

if

{

NextChar<>;/%NextChar为前进一个字符函数。

%/

return;

}

else出错处理

②如果xi为非终结符号.直接调用相应的过程xi<>

三、实验要求

程序输入/输出示例:

对下列文法.用递归下降分析法对任意输入的符号串进行分析:

〔1E->TG

〔2G->+TG|-TG|ε

〔3T->FS

〔4S->*FS|/FS|ε

〔5F->|i

输出的格式如下:

<1>输入一以#结束的符号串<包括+—*/〔i#>:

在此位置输入符号串例如:

i+i*i#

<2>输出结果:

i+i*i#为合法符号串

备注:

输入一符号串如i+i*#,要求输出为"非法的符号串"。

注意:

1.表达式中允许使用运算符〔+-*/、分割符〔括号、字符I.结束符#;

2.如果遇到错误的表达式.应输出错误提示信息〔该信息越详细越好;

3.学有余力的同学.可以详细的输出推导的过程.即详细列出每一步使用的产生式。

四、实验内容

4.1功能描述

这个程序是一个递归下降分析程序.能够判定输入的一个字符串是否属于给定的文法。

如果不是.则会给出一定的出错信息.并且列出每一步使用的产生式。

4.2全局变量及其定义

chara[50];//-----------存储输入的字符串

charch;//-----------暂时存储输入的字符

chard[200];//--------记录当前堆栈中的产生式

intn1;//----------输入字符串的长度

chartoken;//--------------当前待分析字符

4.3模块设计

intE<>;//-----------------E过程.对应产生式E->TG

intT<>;//-----------------T过程.对应产生式T->FS

intG<>;//-----------------G过程.对应产生式G->+TG|-TG|ε

intS<>;//-----------------S过程.对应产生式S->*FS|/FS|ε

intF<>;//-----------------F过程.对应产生式F->|i

voidoutput<>;//-----------------输出已分析字符串和当前字符

voidinput1<>;//-----------------输出剩余字符

4.4程序流程图

图1主函数main〔流程图图2E函数〔流程图

图3T函数〔流程图

图4G函数〔流程图

图5F函数〔流程图

图6S函数〔流程图

五、核心代码清单:

函数功能描述:

根据文法E->TG,先从主函数开始调入第一个非终结符函数执行.并且显示调用产生式.根据程序的状态.调用非终结符函数T〔或G〔.进行递归向下分析。

intE<>

{

intf,t;

printf<"E-->TG\t">;

e[0]='E';

e[1]='=';

e[2]='>';

e[3]='T';

e[4]='G';

e[5]='#';

output<>;

flag=1;

input<>;

input1<>;

f=T<>;

ifreturn<0>;

t=G<>;

ifreturn<0>;

elsereturn<1>;

}

函数功能描述:

根据文法G->+TG|—TG|ε.如果当前字符变量ch为"+".则显示调用产生式.首先判断是算式递归向下分析是否结束.若没有结束则继续依次嵌套调用非终结符函数T〔和G〔;如果当前字符变量ch为"-".则显示调用产生式.从文件文档中读取下一个字符.让字符指针变量指向下一个字符.继续依次嵌套调用非终结符函数T〔和G〔;如果当前字符变量ch既不为"+"也不为"-".非终结符G指向为空.函数只用于显示指向为空.找不到可以和文件中字符匹配的非终结符。

intT<>

{

intf,t;

printf<"T-->FS\t">;

e[0]='T';

e[1]='=';

e[2]='>';

e[3]='F';

e[4]='S';

e[5]='#';

output<>;

flag=1;

input<>;

input1<>;

f=F<>;

ifreturn<0>;

t=S<>;

ifreturn<0>;

elsereturn<1>;

}

函数功能描述:

根据文法T->FS,先显示算式匹配所用的显示调用的产生式.然后依次嵌套调用非终结符函数F〔和S〔.进行递归向下分析。

intG<>

{

intf;

if

{

b[i1]=ch;

printf<"G-->+TG\t">;

e[0]='G';

e[1]='=';

e[2]='>';

e[3]='+';

e[4]='T';

e[5]='G';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=T<>;

ifreturn<0>;

G<>;

return<1>;

}

if

{

b[i1]=ch;

printf<"G-->+TG\t">;

e[0]='G';

e[1]='=';

e[2]='>';

e[3]='+';

e[4]='T';

e[5]='G';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=T<>;

ifreturn<0>;

G<>;

return<1>;

}

printf<"G-->^\t">;

e[0]='G';

e[1]='=';

e[2]='>';

e[3]='^';

e[4]='#';

output<>;

flag=1;

input<>;

input1<>;

return<1>;

intS<>

{

intf,t;

if

{

b[i1]=ch;

printf<"S-->*FS\t">;

e[0]='S';

e[1]='=';

e[2]='>';

e[3]='*';

e[4]='F';

e[5]='S';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=F<>;

ifreturn<0>;

t=S<>;

ifreturn<0>;

elsereturn<1>;

}

if

{

b[i1]=ch;

printf<"S-->*FS\t">;

e[0]='S';

e[1]='=';

e[2]='>';

e[3]='*';

e[4]='F';

e[5]='S';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=F<>;

ifreturn<0>;

t=S<>;

ifreturn<0>;

elsereturn<1>;

}

printf<"S-->^\t">;

e[0]='S';

e[1]='=';

e[2]='>';

e[3]='^';

e[4]='#';

output<>;

flag=1;

a[i1]=ch;

input<>;

input1<>;

return<1>;

printf<"S-->^\t">;

e[0]='S';

e[1]='=';

e[2]='>';

e[3]='^';

e[4]='#';

output<>;

flag=1;

a[i1]=ch;

input<>;

input1<>;

return<1>;

}

函数功能描述:

根据文法S->*FS|/FS|ε.如果当前字符变量ch为"*".则显示调用产生式.从文件文档中读取下一个字符.让字符指针变量指向下一个字符.依次嵌套调用非终结符函数F〔和递归调用自身S〔;如果当前字符变量ch为"/".则显示调用产生式.从文件文档中读取下一个字符.让字符指针变量指向下一个字符.依次嵌套调用非终结符函数F〔和递归调用自身S〔;如果当前字符变量ch既不为"*"也不为"/".G中找不到可以匹配的算式则非终结符G指向为空。

intF<>

{

intf;

if

{

b[i1]=ch;

printf<"F-->\t">;

e[0]='F';

e[1]='=';

e[2]='>';

e[3]='<';

e[4]='E';

e[5]='>';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=E<>;

ifreturn<0>;

if'>

{

b[i1]=ch;

printf<"F-->\t">;

flag=0;

input<>;

input1<>;

ch=a[++i1];

}

else

{

printf<"error\n">;

return<0>;

}

}

elseif

{

b[i1]=ch;

printf<"F-->i\t">;

e[0]='F';

e[1]='=';

e[2]='>';

e[3]='i';

e[4]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

}

else

{

printf<"error\n">;

return<0>;

}

return<1>;

}

voidinput<>

{

intj=0;

for<;j<=i1-flag;j++>

printf<"%c",b[j]>;/*输出分析串*/

printf<"\t\t">;

printf<"%c\t\t",ch>;/*输出分析字符*/

}

voidinput1<>

{

intj;

for

printf<"%c",a[j]>;/*输出剩余字符*/

printf<"\n">;

}

六、程序运行结果:

}

七、实验中遇到的问题:

因为前面的好多实习.都是用JAVA编程实现老师规定的任务.所以对C语言的编程有点淡忘了。

于是.这次决定用C语言编程实现.以巩固我的C语言编程能力。

在这次实习的过程中.遇到了很多问题。

最令我印象深刻的是内存分配问题上。

因为在JAVA中不涉及手动分配内存的问题.而在C语言中对于数组等变量要手动分配内存。

所以.在实习中.总是忘了手动分配内存.出现内存读写错误。

于是.经过一步一步的Debug后.发现了问题的所在。

还有一个问题是:

在添加打印出分析栈内容的时候.打印出来的分析栈内容与自己的预期很不吻合.经过调试才发现在匹配成功后.没有返回1.然后就程序只能接着执行后面的语句.所以导致分析错误。

八、实验总结:

通过这次实习.不仅使我对递归下降分析过程有了更进一步的了解.而且使我对C语言的编程进行了温习。

这次实验前.花了一个半小时理解书中的理论并且自己在纸上模拟了一遍分析过程。

递归下降分析就是对每个非终结符按其产生式结构来构造相应语法分析子程序.其中终结符产生匹配命令.而非终极符则产生过程调用命令。

因为文法递归相应子程序也递归.所以称这种方法为递归子程序下降法或递归下降法。

有了前面的基础.在编程的时候对程序流程就比较熟悉了。

花了一个半小时来设计程序.用了两个小时的时间调试上面出现的错误。

通过这次实验.对递归下降分析程序的设计方法有了更深的理解.同时.也提高了自己的程序设计能力和调试技巧。

总之.这次实习.我收获很大。

九、完整代码:

#include

#include

#include

#include

chara[50],b[50],d[200],e[10];

charch;

intn1,i1=0,flag=1,n=5;

intE<>;

intE1<>;

intT<>;

intG<>;

intS<>;

intF<>;

voidinput<>;

voidinput1<>;

voidoutput<>;

intmain<>/*递归分析*/

{

intf,p,j=0;

charx;

d[0]='E';

d[1]='=';

d[2]='>';

d[3]='T';

d[4]='G';

d[5]='#';

printf<"\n请输入字符串<长度<50,以#号结束\n">;

do

{

scanf<"%c",&ch>;

a[j]=ch;

j++;

}

while

='#'>;

n1=j;

ch=b[0]=a[0];

printf<"文法\t分析串\t\t分析字符\t剩余串\n">;

f=E1<>;

if

return0;

if

{

printf<"accept\n">;

p=0;

x=d[p];

while

='#'>

{

printf<"%c",x>;

p=p+1;

x=d[p];/*输出推导式*/

}

}

else

{

printf<"error\n">;

printf<"回车返回\n">;

getchar<>;

getchar<>;

return0;

}

printf<"\n">;

printf<"回车返回\n">;

getchar<>;

getchar<>;

return0;

}

intE1<>

{

intf,t;

printf<"E-->TG\t">;

flag=1;

input<>;

input1<>;

f=T<>;

ifreturn<0>;

t=G<>;

ifreturn<0>;

elsereturn<1>;

}

intE<>

{

intf,t;

printf<"E-->TG\t">;

e[0]='E';

e[1]='=';

e[2]='>';

e[3]='T';

e[4]='G';

e[5]='#';

output<>;

flag=1;

input<>;

input1<>;

f=T<>;

ifreturn<0>;

t=G<>;

ifreturn<0>;

elsereturn<1>;

}

intT<>

{

intf,t;

printf<"T-->FS\t">;

e[0]='T';

e[1]='=';

e[2]='>';

e[3]='F';

e[4]='S';

e[5]='#';

output<>;

flag=1;

input<>;

input1<>;

f=F<>;

ifreturn<0>;

t=S<>;

ifreturn<0>;

elsereturn<1>;

}

intG<>

{

intf;

if

{

b[i1]=ch;

printf<"G-->+TG\t">;

e[0]='G';

e[1]='=';

e[2]='>';

e[3]='+';

e[4]='T';

e[5]='G';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=T<>;

ifreturn<0>;

G<>;

return<1>;

}

if

{

b[i1]=ch;

printf<"G-->+TG\t">;

e[0]='G';

e[1]='=';

e[2]='>';

e[3]='+';

e[4]='T';

e[5]='G';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=T<>;

ifreturn<0>;

G<>;

return<1>;

}

printf<"G-->^\t">;

e[0]='G';

e[1]='=';

e[2]='>';

e[3]='^';

e[4]='#';

output<>;

flag=1;

input<>;

input1<>;

return<1>;

}

intS<>

{

intf,t;

if

{

b[i1]=ch;

printf<"S-->*FS\t">;

e[0]='S';

e[1]='=';

e[2]='>';

e[3]='*';

e[4]='F';

e[5]='S';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=F<>;

ifreturn<0>;

t=S<>;

ifreturn<0>;

elsereturn<1>;

}

if

{

b[i1]=ch;

printf<"S-->*FS\t">;

e[0]='S';

e[1]='=';

e[2]='>';

e[3]='*';

e[4]='F';

e[5]='S';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=F<>;

ifreturn<0>;

t=S<>;

ifreturn<0>;

elsereturn<1>;

}

printf<"S-->^\t">;

e[0]='S';

e[1]='=';

e[2]='>';

e[3]='^';

e[4]='#';

output<>;

flag=1;

a[i1]=ch;

input<>;

input1<>;

return<1>;

printf<"S-->^\t">;

e[0]='S';

e[1]='=';

e[2]='>';

e[3]='^';

e[4]='#';

output<>;

flag=1;

a[i1]=ch;

input<>;

input1<>;

return<1>;

}

intF<>

{

intf;

if

{

b[i1]=ch;

printf<"F-->\t">;

e[0]='F';

e[1]='=';

e[2]='>';

e[3]='<';

e[4]='E';

e[5]='>';

e[6]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

f=E<>;

ifreturn<0>;

if'>

{

b[i1]=ch;

printf<"F-->\t">;

flag=0;

input<>;

input1<>;

ch=a[++i1];

}

else

{

printf<"error\n">;

return<0>;

}

}

elseif

{

b[i1]=ch;

printf<"F-->i\t">;

e[0]='F';

e[1]='=';

e[2]='>';

e[3]='i';

e[4]='#';

output<>;

flag=0;

input<>;

input1<>;

ch=a[++i1];

}

else

{

printf<"error\n">;

return<0>;

}

return<1>;

}

voidinput<>

{

intj=0;

for<;j<=i1-flag;j++>

printf<"%c",b[j]>;/*输出分析串*/

printf<"\t\t">;

printf<"%c\t\t",ch>;/*输出分析字符*/

}

voidinput1<>

{

intj;

for

printf<"%c",a[j]>;/*输出剩余字符*/

printf<"\n">;

}

voidoutput<>/*推导式计算*/

{

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

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

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2