文档库 最新最全的文档下载
当前位置:文档库 › 递归下降分析实验报告

递归下降分析实验报告

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

实习二递归下降分析

一、实验目的:

根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对递归下降分析法的理解。

二、实验预习提示

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

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

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

改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法,3、递归下降分析法实验设计思想及算法

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

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

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

(2)若是非终结符号,则调用与此非终结符对应的过程。当A的右部有多个产生式时,

可用选择结构实现。

具体为:

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

U( )

{

ch=当前符号;

if(ch可能是u1字的开头) 处理u1的程序部分;

else if(ch可能是u2字的开头)处理u2的程序部分;

else error()

}

(2)对于每个右部u1->x1x2…x n的处理架构如下:

处理x1的程序;

处理x2的程序;

处理x n的程序;

(3)如果右部为空,则不处理。

(4)对于右部中的每个符号x i

①如果xi为终结符号:

if(xi= = 当前的符号)

{

NextChar(); /% NextChar为前进一个字符函数。%/

return;

}

②如果xi为非终结符号,直接调用相应的过程xi()

三、实验要求

程序输入/输出示例:

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

(1)E->TG

(2)G->+TG|-TG|ε

(3)T->FS

(4)S->*FS|/FS|ε

(5)F->(E)|i

输出的格式如下:

(1)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串例如:i+i*i#

(2)输出结果:i+i*i#为合法符号串

备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。

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

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

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

生式。

四、实验内容

4.1 功能描述

这个程序是一个递归下降分析程序,能够判定输入的一个字符串是否属于给定的文法。如果不是,则会给出一定的出错信息,并且列出每一步使用的产生式。

4.2 全局变量及其定义

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

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

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

int n1;//----------输入字符串的长度

char token;//--------------当前待分析字符

4.3 模块设计

int E();//-----------------E过程,对应产生式E->TG

int T();//-----------------T过程,对应产生式T->FS

int G();//-----------------G过程,对应产生式G->+TG|-TG|ε

int S();//-----------------S过程,对应产生式S->*FS|/FS|ε

int F();//-----------------F过程,对应产生式F->(E)|i

void output();//-----------------输出已分析字符串和当前字符

void input1();//-----------------输出剩余字符

4.4 程序流程图

图1 主函数main ()流程图 图2 E 函数()流程图

结束

输出分析信息 进行递归下降分析

得到第一个字符

将开始符放入堆栈

获取字符串长度

开始

输入要处理的字符串

Y N

开始

输出分析栈内容和当前动作

将分析栈的E 换为TG

TG

return 1

return 0 结束

N

结束

Y return 1 return 0

FS 将分析栈的T 换为FS

开始 输出分析栈内容和当前动作

图4 G函数()流程图

图5 F函数()流程图

图6 S函数()流程图

五、核心代码清单:

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

int E()

{

int f,t;

printf("E-->TG\t");

e[0]='E';

e[1]='=';

e[2]='>';

e[3]='T';

e[4]='G';

e[5]='#';

output();

input();

input1();

f=T();

if (f==0) return(0);

t=G();

if (t==0) return(0);

else return(1);

}

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

int T()

{

int f,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();

if (f==0) return(0);

t=S();

if (t==0) return(0);

else return(1);

}

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

int G()

{

int f;

if(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();

if (f==0) return(0);

G();

return(1);

}

if(ch=='-')

{

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();

if (f==0) return(0);

G();

return(1);

}

printf("G-->^\t");

e[1]='=';

e[2]='>';

e[3]='^';

e[4]='#';

output();

flag=1;

input();

input1();

return(1);

int S()

{

int f,t;

if(ch=='*')

{

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();

if (f==0) return(0);

t=S();

if (t==0) return(0);

else return(1);

}

if(ch=='/')

{

b[i1]=ch;

printf("S-->*FS\t");

e[0]='S';

e[1]='=';

e[3]='*';

e[4]='F';

e[5]='S';

e[6]='#';

output();

flag=0;

input();

input1();

ch=a[++i1];

f=F();

if (f==0) return(0);

t=S();

if (t==0) return(0);

else 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);

printf("S-->^\t");

e[0]='S';

e[1]='=';

e[2]='>';

e[3]='^';

e[4]='#';

output();

flag=1;

a[i1]=ch;

input();

input1();

return(1);

}

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

int F()

{

int f;

if(ch=='(')

{

b[i1]=ch;

printf("F-->(E)\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();

if (f==0) return(0);

if(ch==')')

{

b[i1]=ch;

printf("F-->(E)\t");

flag=0;

input();

input1();

ch=a[++i1];

}

else

{

printf("error\n");

return(0);

}

}

{

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

}

void input()

{

int j=0;

for (; j<=i1-flag; j++)

printf("%c",b[j]); /*输出分析串*/ printf("\t\t");

printf("%c\t\t",ch); /*输出分析字符*/ }

void input1()

{

int j;

for (j=i1+1-flag; j

printf("%c",a[j]); /*输出剩余字符*/ printf("\n");

}

六、程序运行结果:

}

七、实验中遇到的问题:

因为前面的好多实习,都是用JA V A编程实现老师规定的任务,所以对C语言的编程有点淡忘了。于是,这次决定用C语言编程实现,以巩固我的C语言编程能力。在这次实习的过程中,

题,而在C语言中对于数组等变量要手动分配内存。所以,在实习中,总是忘了手动分配内存,出现内存读写错误。于是,经过一步一步的Debug后,发现了问题的所在。还有一个问题是:在添加打印出分析栈内容的时候,打印出来的分析栈内容与自己的预期很不吻合,经过调试才发现在匹配成功后,没有返回1,然后就程序只能接着执行后面的语句,所以导致分析错误。

八、实验总结:

通过这次实习,不仅使我对递归下降分析过程有了更进一步的了解,而且使我对C语言的编程进行了温习。这次实验前,花了一个半小时理解书中的理论并且自己在纸上模拟了一遍分析过程。递归下降分析就是对每个非终结符按其产生式结构来构造相应语法分析子程序,其中终结符产生匹配命令,而非终极符则产生过程调用命令。因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。有了前面的基础,在编程的时候对程序流程就比较熟悉了。花了一个半小时来设计程序,用了两个小时的时间调试上面出现的错误。通过这次实验,对递归下降分析程序的设计方法有了更深的理解,同时,也提高了自己的程序设计能力和调试技巧。总之,这次实习,我收获很大。

九、完整代码:

#include

#include

#include

#include

char a[50] ,b[50],d[200],e[10];

char ch;

int n1,i1=0,flag=1,n=5;

int E();

int E1();

int T();

int G();

int S();

int F();

void input();

void input1();

void output();

int main() /*递归分析*/

{

int f,p,j=0;

char x;

d[0]='E';

d[4]='G';

d[5]='#';

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

do

{

scanf("%c",&ch);

a[j]=ch;

j++;

}

while(ch!='#');

n1=j;

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

printf("文法\t分析串\t\t分析字符\t剩余串\n");

f=E1();

if (f==0)

return 0;

if (ch=='#')

{

printf("accept\n");

p=0;

x=d[p];

while(x!='#')

{

printf("%c",x);

p=p+1;

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

}

else

{

printf("error\n");

printf("回车返回\n");

getchar();

getchar();

return 0;

}

printf("\n");

printf("回车返回\n");

}

int E1()

{

int f,t;

printf("E-->TG\t");

flag=1;

input();

input1();

f=T();

if (f==0) return(0);

t=G();

if (t==0) return(0);

else return(1);

}

int E()

{

int f,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();

if (f==0) return(0);

t=G();

if (t==0) return(0);

else return(1);

}

int 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();

if (f==0) return(0);

t=S();

if (t==0) return(0);

else return(1);

}

int G()

{

int f;

if(ch=='+')

{

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();

if (f==0) return(0);

G();

return(1);

if(ch=='-')

{

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();

if (f==0) return(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);

}

int S()

{

int f,t;

if(ch=='*')

{

b[i1]=ch;

printf("S-->*FS\t");

e[1]='=';

e[2]='>';

e[3]='*';

e[4]='F';

e[5]='S';

e[6]='#';

output();

flag=0;

input();

input1();

ch=a[++i1];

f=F();

if (f==0) return(0);

t=S();

if (t==0) return(0);

else return(1);

}

if(ch=='/')

{

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();

if (f==0) return(0);

t=S();

if (t==0) return(0);

else return(1);

}

printf("S-->^\t");

e[0]='S';

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

}

int F()

{

int f;

if(ch=='(')

{

b[i1]=ch;

printf("F-->(E)\t");

e[0]='F';

e[1]='=';

e[2]='>';

e[3]='(';

e[4]='E';

e[5]=')';

e[6]='#';

output();

flag=0;

input();

input1();

if (f==0) return(0);

if(ch==')')

{

b[i1]=ch;

printf("F-->(E)\t");

flag=0;

input();

input1();

ch=a[++i1];

}

else

{

printf("error\n");

return(0);

}

}

else if(ch=='i')

{

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

}

void input()

消除文法的左递归实验

编译原理实验报告 实验名称 _____________ 消除文法的左递归__________________________ 实验时间 _____________________________________________ 院系 _________________________________________ 班级 ______________________________________________ 学号 ____________________________________________ 姓名

1. 试验目的 ?掌握和理解消除左递归(包括直接左递归和间接左递归)在构建 LL(1)文法的作用和目的 ?掌握消除左递归(包括直接左递归和间接左递归)的方法和步骤。 ?写出对于输入任意的上下文无关文法可以输出消除了左递归的等 价文法。 2. 实验原理 ?直接左递归的消除 消除产生式中的直接左递归是比较容易的。例如假设非终结符 P的规则为 P—P a/ B 其中,B是不以P开头的符号串。那么,我们可以把P的规则改写为 如下的非直接左递归形式:P—尸’ P'—P'£ 考虑更一般的情况,假定关于非终结符P的规则为 P—P a / P o2 / …/ P a n / [31 / [32 / …/ p m 其中,a (I = 1, 2,…,n)都不为£而每个p j (j = 1, 2,…,m) 都不以P开头,将上述规则改写为如下形式即可消除P的直接左递归: P— p l P'/ 32 P'/…/p m P' P' — 01P' / a P'/…/ a n P'/£

实验报告 分治与递归

实验报告分治与递归 中国矿业大学计算机科学与技术学院孟靖宇 一、实验目的与要求 1、熟悉C/C++语言的集成开发环境; 2、通过本实验加深对递归过程的理解 二、实验内容: 掌握递归算法的概念和基本思想,分析并掌握“整数划分”问题的递归算法。 三、实验题 任意输入一个整数,输出结果能够用递归方法实现整数的划分。 四、算法思想 对于数据n,递归计算最大加数等于x 的划分个数+最大加数不大于x-1的划分个数。最大加数x 从n 开始,逐步变小为n-1, (1) 考虑增加一个自变量:对于数据n,最大加数n1不大于m 的划分个数记作),(m n q 。则有: ???????>>=<==-+--+=1 1,1),()1,()1,(1),(1),(m n m n m n m n m m n q m n q n n q n n q m n q 五、代码实现 #include "stdafx.h" #include #include #include using namespace std; int q(intn,int m); int main(){ int n; cout<<"请输入要划分的整数:"<>n; int p=q(n,n); cout<<"正整数"<

return 0; } int q(intn,int m){ if((n<1)||(m<1)) return 0; if((n==1)||(m==1)) return 1; if(n

递归下降语法分析程序设计

编译方法实验报告实验名称:简单的语法分析程序设计

实验要求 1.功能:对简单的赋值语句进行语法分析 随机输入赋值语句,输出所输入的赋值语句与相应的四元式 2.采用递归下降分析程序完成(自上而下的分析) 3.确定各个子程序的功能并画出流程图 4.文法如下:

5.编码、调试通过 采用标准输入输出方式。输入输出的样例如下: 【样例输入】 x:=a+b*c/d-(e+f) 【样例输出】(说明,语句和四元式之间用5个空格隔开) T1:=b*c (*,b,c,T1) T2:=T1/d (/,T1,d,T2) T3:=a+T2 (+,a,T2,T3) T4:=e+f (+,e,f,T4) T5:=T3-T4 (-,T3,T4,T5) x:=T5 (:=,T5,-,x) 【样例说明】程序除能够正确输出四元式外,当输入的表达式错误时,还应能检测出语法错误,给出相应错误提示。 6.设计3-5个赋值语句测试实例,检验程序能否输出正确的四元式;当输入错误 的句子时,检验程序能够给出语法错误的相应提示信息。 7.报告内容包括: 递归程序的调用过程,各子程序的流程图和总控流程图,详细设计,3-5个测试用例的程序运行截图及相关说明,有详细注释的程序代码清单等。

目录 1.语法分析递归下降分析算法............................... 错误!未定义书签。 背景知识............................................. 错误!未定义书签。 消除左递归........................................... 错误!未定义书签。 2.详细设计及流程图....................................... 错误!未定义书签。 函数void V( ) .|z ................................. 错误!未定义书签。 函数void A( ) 错误!未指定书签。错误!未指定书签。错误!未指定书签。错误!未指定书签。错误!未指定书签。试用例及截图........................ 错误!未定义书签。 测试用例1及截图..................................... 错误!未定义书签。 测试用例2及截图..................................... 错误!未定义书签。 测试用例3及截图..................................... 错误!未定义书签。 代码清单................................................. 错误!未定义书签。

递归与分治实验报告

递归与分治实验报告 班级:计科1102 姓名:赵春晓学号:2011310200631 实验目的:进一步掌握递归与分治算法的设计思想,通过实际问题来应用递归与分治设计算法。 实际问题:1集合划分问题,2输油管道问题,3邮局选址问题,4整数因子分解问题,5众数问题。 问题1:集合划分 算法思想:对于n个元素的集合,可以划分为由m个子集构成的集合,例如{{1,2}{3,4}}就是由2个子集构成的非空子集。假设f(n,m)表示将n个元素划分成由m个子集构成的集合的个数。那么1)若m == 1 ,则f(n,m)= 1 ;2)若n == m ,则f(n,m)= 1 ;3)若不是上面两种情况则有下面两种情况构成:3.1)向n-1个元素划分成的m个集合里面添加一个新的元素,则有m*f(n-1,m)种方法;3.2)向n-1个元素划分成的m-1个集合里添加一个由一个元素形成的独立的集合,则有f(n-1,m-1)种方法。 实验代码: #include #include using namespace std ; int jihehuafen( int n , int m ) { if( m == 1 || n == m ) return 1 ; else return jihehuafen( n - 1 , m - 1 ) + m*jihehuafen( n - 1 , m ) ; } int main() { ifstream fin("C:/input.txt") ; ofstream fout("C:/output.txt") ; int N , M , num ; fin >> N >> M ; num = jihehuafen( N , M) ; fout << num << endl ; return 0 ; } 问题2:输油管道 算法思想:由于主管道由东向西铺设。故主管道的铺设位置只和各油井的y坐标有关。要使主管道的y坐标最小,主管道的位置y坐标应是各个油井y坐标的中位数。先用快速排序法把各个油井的y坐标排序,然后取其中位数再计算各个油

编译原理-编写递归下降语法分析器

学号107 成绩 编译原理上机报告 名称:编写递归下降语法分析器 学院:信息与控制工程学院 专业:计算机科学与技术 班级:计算机1401班 姓名:叶达成 2016年10月31日

一、上机目的 通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握常用的语法分析方法。通过本实验,应达到以下目标: 1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2、掌握词法分析的实现方法。 3、上机调试编出的词法分析程序。 二、基本原理和上机步骤 递归下降分析程序实现思想简单易懂。程序结构和语法产生式有直接的对应关系。因为每个过程表示一个非终结符号的处理,添加语义加工工作比较方便。 递归下降分析程序的实现思想是:识别程序由一组子程序组成。每个子程序对应于一个非终结符号。 每一个子程序的功能是:选择正确的右部,扫描完相应的字。在右部中有非终结符号时,调用该非终结符号对应的子程序来完成。 自上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。分析速度慢。而无回溯的自上向下分析技术,当选择某非终结符的产生时,可根据输入串的当前符号以及各产生式右部首符号而进行,效率高,且不易出错。 无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。 无左递归:既没有直接左递归,也没有间接左递归。 无回溯:对于任一非终结符号U的产生式右部x1|x2|…|x n,其对应的字的首终结符号两两不相交。 如果一个文法不含回路(形如P?+ P的推导),也不含以ε为右部的产生式,那么可以通过执行消除文法左递归的算法消除文法的一切左递归(改写后的文法可能含有以ε为右部的产生式)。 三、上机结果 测试数据: (1)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串例如:i+i*i# (2)输出结果:i+i*i#为合法符号串 (3)输入一符号串如i+i*#,要求输出为“非法的符号串”。 程序清单: #include #include char str[50]; int index=0; void E(); //E->TX; void X(); //X->+TX | e void T(); //T->FY void Y(); //Y->*FY | e void F(); //F->(E) | i int main() /*递归分析*/ { int len; int m;

算法设计与分析实验报告

本科实验报告 课程名称:算法设计与分析 实验项目:递归与分治算法 实验地点:计算机系实验楼110 专业班级:物联网1601 学号:2016002105 学生姓名:俞梦真 指导教师:郝晓丽

2018年05月04 日 实验一递归与分治算法 1.1 实验目的与要求 1.进一步熟悉C/C++语言的集成开发环境; 2.通过本实验加深对递归与分治策略的理解和运用。 1.2 实验课时 2学时 1.3 实验原理 分治(Divide-and-Conquer)的思想:一个规模为n的复杂问题的求解,可以划分成若干个规模小于n的子问题,再将子问题的解合并成原问题的解。 需要注意的是,分治法使用递归的思想。划分后的每一个子问题与原问题的性质相同,可用相同的求解方法。最后,当子问题规模足够小时,可以直接求解,然后逆求原问题的解。 1.4 实验题目 1.上机题目:格雷码构造问题 Gray码是一个长度为2n的序列。序列无相同元素,每个元素都是长度为n的串,相邻元素恰好只有一位不同。试设计一个算法对任意n构造相应的Gray码(分治、减治、变治皆可)。 对于给定的正整数n,格雷码为满足如下条件的一个编码序列。 (1)序列由2n个编码组成,每个编码都是长度为n的二进制位串。 (2)序列中无相同的编码。 (3)序列中位置相邻的两个编码恰有一位不同。 2.设计思想:

根据格雷码的性质,找到他的规律,可发现,1位是0 1。两位是00 01 11 10。三位是000 001 011 010 110 111 101 100。n位是前n-1位的2倍个。N-1个位前面加0,N-2为倒转再前面再加1。 3.代码设计:

消除左递归实验报告

共享知识分享快乐 编译原理实验报告 实验名称消除文法左递归 实验时间2014年12月12日 院系软件工程 ______________ 班级软件工程(2)班 学号E01214215 __________ 姓名刘翼________________

实验目的: 输入:任意的上下文无关文法。输出:消除了左递归的等价文法。 实验原理: 1.直接左递归的消除 消除产生式中的直接左递归是比较容易的。例如假设非终结符P 的规则为 P—P a / B 其中,B是不以P开头的符号串。那么,我们可以把P的规则改写为如下的非直接左递归形式:P —B P' P'—a P' / £ 这两条规则和原来的规则是等价的,即两种形式从P推出的符号串是相同的。 设有简单表达式文法G[E] : E —E+T/ T T —T*F/ F F —(E)/ I 经消除直接左递归后得到如下文法: E —TE' E ' —+TE' / £ T —FT' T' —*FT' / £ F —(E)/ I 考虑更一般的情况,假定关于非终结符P的规则为 P—P a 1 / P a 2 / …/ P a n / B 1 / B 2 / …/ B m 其中,a i (I = 1,2,…,n)都不为£,而每个B j (j = 1,2,…,m都不以P开头,将上述规则改写为如下形式即可消除P的直接左递归: P—B 1 P' / B 2 P' / …/ B m P' P' —a 1P' / a 2 P' / …/ a n P' / £ 2.间接左递归的消除 直接左递归见诸于表面,利用以上的方法可以很容易将其消除,即把直接左递归改写成直接右递归。然而文法表面上不存在左递归并不意味着该文法就不存在左递归了。有些文法虽然表面上不存在左递归,但却隐藏着左递归。例如,设有文法G[S] : S—Qc/ c Q—Rb/ b R—Sa/ a 虽不具有左递归,但S、Q R都是左递归的,因为经过若干次推导有 S Qc Rbc Sabc Q Rb Sab Qcab R Sa Qca Rbca

实验三 递归下降分析程序实现

实验三递归下降分析法 一、实验目的: 根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对递归下降分析法的理解。 程序比较复杂,需要利用到程序设计语言的知识和大量编程技巧,递归下降分析法是一种较实用的分析法,通过这个练习可大大提高软件开发能力。通过练习,掌握函数间相互调 用的方法。 二、实验要求 1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。 2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。 3.编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。 三、实验内容 程序输入/输出示例: 对下列文法,用递归下降分析法对任意输入的符号串进行分析: (1)E-TG (2)G-+TG|—TG (3)G-ε (4)T-FS (5)S-*FS|/FS (6)S-ε (7)F-(E) (8)F-i 输出的格式如下: (1)递归下降分析程序,编制人:姓名,学号,班级 (2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串例如:i+i*i# (3)输出结果:i+i*i#为合法符号串 备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。 引用也要改变)。 注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符I,结束符#; 2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好); 3.对学有余力的同学,可以详细的输出推导的过程,即详细列出每一步使用的产生式。 四、实验学时 4学时 五、实验步骤 (一)准备:

1.阅读课本有关章节, 2.考虑好设计方案; 3.设计出模块结构、测试数据,初步编制好程序。 (二)上课上机: 将源代码拷贝到机上调试,发现错误,再修改完善。第二次上机调试通过。 (三)程序思路(仅供参考): 0.定义部分:定义常量、变量、数据结构。 1.初始化:从文件将输入符号串输入到字符缓冲区中。 2.利用递归下降分析法分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。 六、实验预习提示 1、递归下降分析法的功能 词法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。 2、递归下降分析法的前提 改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法, 3、递归下降分析法实验设计思想及算法 为G的每个非终结符号U构造一个递归过程,不妨命名为U。 U的产生式的右边指出这个过程的代码结构: (1)若是终结符号,则和向前看符号对照, 若匹配则向前进一个符号;否则出错。 (2)若是非终结符号,则调用与此非终结符对应的过程。当A的右部有多个产生式时,可用选择结构实现。 具体为: (1)对于每个非终结符号U-u1|u2|…|un处理的方法如下: U( ) { ch=当前符号; if(ch可能是u1字的开头) 处理u1的程序部分; else if(ch可能是u2字的开头)处理u2的程序部分; … else error() } (2)对于每个右部u1-x1x2…xn的处理架构如下: 处理x1的程序; 处理x2的程序; … 处理xn的程序; (3)如果右部为空,则不处理。

递归下降分析法

《编译原理》课程实验报告 实验名称:递归下降分析法 一.实验目的 1.理解递归下降语法分析方法的主要原理 2.理解递归下降分析法对文法的要求 3.熟练掌握Predict集合的求法 4.熟练掌握文法变换算法(消除左递归和消除公共前缀) 二.实验内容 #include char token[20]; char sym; int p; void S(); void T(); void U(); void Scanner(); void Error(); void S() { if (sym == 'a' || sym == '^') Scanner(); else if (sym == '(') { Scanner(); T(); if (sym == ')') Scanner(); else Error(); } else Error();

} void T() { S(); U(); } void U() { if (sym == ',') { Scanner(); S(); U(); } else if(sym != ')') Error(); } void Scanner() { sym = token[p++]; } void Error() { //exit(0); } int main() { printf("输入: "); gets(token); p = 0; Scanner(); S(); if (sym == '$') printf("Success!"); else printf("Fail!"); return 0; } 三.实验步骤 调试程序的结果:

编译原理-实验二-递归下降分析程序构造

集美大学计算机工程学院实验报告 课程名称:编译原理 指导教师:付永钢 实验成绩: 实验编号: 实验二 实验名称:递归下降分析程序构造 班级:计算12 姓名: 学号: 上机实践日期:2014.11 上机实践时间: 4学时 一、实验目的 通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握常用的语法分析方法。通过本实验,应达到以下目标: (1) 掌握从源程序文件中读取有效字符的方法和产生源程序内部表示文件的方法; (2)掌握语法分析的实现方法; (3)上机调试编出的语法分析程序。 二、实验环境 Windows7 x64、VC6.0 三、实验原理 递归下降法是语法分析中最易懂的一种方法。它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。其中子程序的结构与产生式结构几乎是一致的。 递归下降分析程序的实现思想是:识别程序由一组子程序组成。每个子程序对应于一个非终结符号。每一个子程序的功能是:选择正确的右部,扫描完相应的字。在右部中有非终结符号时,调用该非终结符号对应的子程序来完成。 自上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。分析速度慢。而无回溯的自上向下分析技术,可根据输入串的当前符号以及各产生式右部首符,选择某非终结符的产生式,效率高,且不易出错。 无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。即:假设A 的全部产生式为A →α1|α2|……|αn ,则必须满足如下条件才能保证可以唯一的选择合适的产生式 First(A →αi )∩First (A →αj )=Φ,当i≠j. 无左递归:既没有直接左递归,也没有间接左递归。 无回溯:对于人以非中介符号U 的产生式右部n x x x |...||21,其对应的字的首终结符号两两不相交。 如果一个文法不含回路(形如P P +?的推导),也不含以ε为右部的产生式,那么可以通过执行消除左递归的算法消除文法的一切左递归。 四、实验内容 完成以下描述算术表达式的LL(1)文法的递归下降分析程序构造 G[E]: E →TE ′ E ′→+TE ′|ε T →FT ′

实验三_递归下降法的语法分析器

魏陈强 23020092204168 实验3 递归下降法的语法分析器 一、实验目的 学习用递归下降法构造语法分析器的原理,掌握递归下降法的编程方法。 二、实验内容 用递归下降法编写一个语法分析程序,使之与词法分析器结合,能够根据语言的上下文无关文法,识别输入的单词序列是否文法的句子。 这里只要求实现部分产生式,文法的开始符号为program。(完整的源语言的文法定义见教材附录 A.1,p394) program→ block block→{stmts } stmts→stmt stmts | stmt→id=expr; | if(bool)stmt | if( bool)stmt else stmt | while(bool)stmt | do stmt while(bool ) ; | break ; | block bool →expr < expr | expr <= expr | expr > expr | expr >= expr | expr expr→ expr + term | expr - term | term

term→ term * factor | term / factor | factor factor→ ( e xpr ) | id| num 三、实验要求 1.个人完成,提交实验报告。 2.实验报告中给出采用测试源代码片断,及其对应的最左推导过程(形式可以自行考虑)。 测试程序片断: { i = 2; while (i <=100) { sum = sum + i; i = i + 2; } } 对应的推导过程为: program?block ?{stmts } ?{stmt stmts} ?{id=expr;stmts } ?{id=num;stmts } ?{id=num;stmt stmts } ?{id=num;while(bool)stmt stmts } ?{id=num;while(e xpr<= expr)stmt stmts } ?{id=num;while(id<= expr)stmt stmts } ?{id=num;while(id<= num)stmt stmts } ?{id=num;while(id<= num)block stmts } ?{id=num;while(id<= num){stmts }stmts } ?....... 四、实验思路 之前编写的词法分析器,能够将语句中的每一个词素都识别出来,因此,在此基础上,定义一个二维字符串数组finaltable[100][20],用于存放由词法分析器提取出来的每个词素,比如,i=2,则finaltable[0]=”id”,

算法分析实验报告--分治策略

《算法设计与分析》实验报告 分治策略 姓名:XXX 专业班级:XXX 学号:XXX 指导教师:XXX 完成日期:XXX

一、试验名称:分治策略 (1)写出源程序,并编译运行 (2)详细记录程序调试及运行结果 二、实验目的 (1)了解分治策略算法思想 (2)掌握快速排序、归并排序算法 (3)了解其他分治问题典型算法 三、实验内容 (1)编写一个简单的程序,实现归并排序。 (2)编写一段程序,实现快速排序。 (3)编写程序实现循环赛日程表。设有n=2k个运动员要进行网球循环赛。现 要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其它n-1个选手各赛一次(2)每个选手一天只能赛一场(3)循环赛进行n-1天 四、算法思想分析 (1)编写一个简单的程序,实现归并排序。 将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行 排序,最终将排好序的子集合合并成为所要求的排好序的集合。 (2)编写一段程序,实现快速排序。 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有 数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数 据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据 变成有序序列。 (3)编写程序实现循环日赛表。 按分治策略,将所有的选手分为两组,n个选手的比赛日程表就可以通

过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割, 直到只剩下2个选手时,比赛日程表的制定就变得很简单。这时只要让 这2个选手进行比赛就可以了。 五、算法源代码及用户程序 (1)编写一个简单的程序,实现归并排序。 #include #include #define MAX 10 using namespace std; void merge(int array[],int p,int q,int r) { int i,k; int begin1,end1,begin2,end2; int* temp = new int[r-p+1]; begin1 = p; end1 = q; begin2 = q+1; end2 = r; k = 0; while((begin1 <= end1)&&(begin2 <= end2)) { if(array[begin1] < array[begin2]) { temp[k] = array[begin1]; begin1++; } else { temp[k] = array[begin2]; begin2++; } k++; } while(begin1 <= end1) {

递归下降分析法

编译原理课程实验报告 班级学号:姓名: 实验名称:递归下降分析法 一、实验目的: 根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对递归下降分析法的理解。 二、实验要求: 对下列文法,用递归下降分析法对任意输入的符号串进行分析: (1)E->TG (2)G->+TG|—TG (3)G->ε (4)T->FS (5)S->*FS|/FS (6)S->ε (7)F->(E) (8)F->i 输出的格式如下: (1)递归下降分析程序,编制人:姓名,学号,班级 (2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串例如:i+i*i# (3)输出结果:i+i*i#为合法符号串 备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。 注意: 1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#; 2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好); 三、实验过程: 程序设计: 1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。 2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。 程序编写: 1.定义部分:定义常量、变量、数据结构。 2.初始化:从文件将输入符号串输入到字符缓冲区中。 3.利用递归下降分析法,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。 四、实验结果

(1)程序流程图 主函数main( )流程图 E( )过程流程图 T( )过程流程图

G( )过程流程图 F( )过程流程图

编译原理实验报告

院系:计算机科学学院 专业、年级: 07计科2大班 课程名称:编译原理 学号姓名: 指导教师: 2010 年11月17 日 组员学号姓名

实验 名称 实验一:词法分析实验室9205 实验目的或要求 通过设计一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。 具体要求:输入为某语言源代码,达到以下功能: 程序输入/输出示例:如源程序为C语言。输入如下一段: main() { int a,b; a=10; b=a+20; } 要求输出如下(并以文件形式输出或以界面的形式输出以下结果)。 (2,”main”) (5,”(“) (5,”)“) (5,”{“} (1,”int”) (2,”a”) (5,”,”) (2,”b”) (5,”;”) (2,”a”) (4,”=”) (3,”10”) (5,”;”) (2,”b”) (4,”=”) (2,”a”) (4,”+”) (3,”20”) (5,”;”) (5,”}“) 要求: 识别保留字:if、int、for、while、do、return、break、continue等等,单词种别码为1。 其他的标识符,单词种别码为2。常数为无符号数,单词种别码为3。 运算符包括:+、-、*、/、=、>、<等;可以考虑更复杂情况>=、<=、!= ;单词种别码为4。分隔符包括:“,”“;”“(”“)”“{”“}”等等,单词种别码为5。

算法设计与分析:递归与分治法-实验报告

应用数学学院信息安全专业班学号姓名 实验题目递归与分治法 综合实验评分表

实验报告 一、实验目的与要求 1.掌握递归算法的设计思想 2.掌握分治法设计算法的一般过程 3.理解并掌握算法渐近时间复杂度的分析方法 二、实验内容 1、折半查找的递归算法 (1)源程序代码 #include #include using namespace std; int bin_search(int key[],int low, int high,int k) { int mid; if(low>high) return -1; else{ mid = (low+high) / 2; if(key[mid]==k) return mid; if(k>key[mid]) return bin_search(key,mid+1,high,k); else return bin_search(key,low,mid-1,k); } } int main() { int n , i , addr; int A[10] = {2,3,5,7,8,10,12,15,19,21}; cout << "在下面的10个整数中进行查找" << endl; for(i=0;i<10;i++){ cout << A[i] << " " ; } cout << endl << endl << "请输入一个要查找的整数" << endl; cin >> n; addr = bin_search(A,0,9,n);

if(-1 != addr) cout << endl << n << "是上述整数中的第" << addr << "个数" << endl; else cout << endl << n << "不在上述的整数中" << endl << endl; getchar(); return 0; } (2)运行界面 ①查找成功 ②查找失败

编译原理-实验报告2-递归下降分析法

计算机硬件实验室实验报告 一、实验目的: 根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对递归下降分析法的理解。 二、实验要求: 对下列文法,用递归下降分析法对任意输入的符号串进行分析: (1)E->TG (2)G->+TG|—TG (3)G->ε (4)T->FS (5)S->*FS|/FS (6)S->ε (7)F->(E) (8)F->i 输出的格式如下: (1)递归下降分析程序,编制人:姓名,学号,班级 (2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串例如:i+i*i# (3)输出结果:i+i*i#为合法符号串 备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。 注意: 1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#; 2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好); 三、实验过程:

程序设计: 1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。 2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。 程序编写: 1.定义部分:定义常量、变量、数据结构。 2.初始化:从文件将输入符号串输入到字符缓冲区中。 3.利用递归下降分析法,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。 四、实验结果 (1)程序流程图 (2)运行结果 示例程序: #include <> #include<> #include<> #include<> char a[50] ,b[50],d[500],e[10]; char ch; int n1,i1=0,flag=1,n=5; int E(); int E1(); int T(); int G();

编译原理实验报告

学生学号0120810680316 实验课成绩 武汉理工大学 学生实验报告书 实验课程名称《编译原理》 开课学院计算机科学与技术学院 指导老师姓名何九周 学生姓名刘洋 学生专业班级软件工程0803 2010 —2011 学年第二学期

实验课程名称:编译原理 实验项目名称单词的词法分析程序设计实验成绩实验者刘洋专业班级软件0803 组别 同组者实验日期 2011 年 5 月 17日 第一部分:实验分析与设计(可加页) 一、实验内容描述(问题域描述) 实验目的: 设计,编制并调试一个词法分析程序,加深对词法分析原理的理解。 实验要求: 在上机前应认真做好各种准备工作,熟悉机器的操作系统和语言的集成环境,独立完成算法编制和程序代码的编写;上机时应随带有关的高级语言教材或参考书;要学会程序调试与纠错;每次实验后要交实验报告。 实验题目: 对于给定的源程序(如C语言或Pascal等),要求从组成源程序的字符行中寻找出单词,并给出它们的种别和属性——输出二元组序列。以便提供给语法分析的时候使用。要求能识别所有的关键字,标志符等,并且能够对出先的一些词法规则的错误进行必要的处理。 二、实验基本原理与设计(包括实验方案设计,实验手段的确定,试验步骤等,用硬件逻辑或 者算法描述) 实验原理: 由于这是一个用高级语言编写一个词法分析器,使之能识别输入串,并把分析结果(单词符号,标识符,关键字等等)输出.输入源程序,输入单词符号,本词法分析器可以辨别关键字,标识符,常数,运算符号和某些界符,运用了文件读入来获取源程序代码,再对该源程序代码进行词法分析,这就是词法分析器的基本功能.当词法分析器调用预处理子程序处理出一串输入字符放进扫描缓冲区之后,分析器就从此缓冲区中逐一识别单词符号.当缓冲区里的字符串被处理完之后,它又调用预处理子程序来处理新串. 编写的时候,使用了文件的输入和输出,以便于词法分析的通用型,同时在文件输出时,并保存在输出文件output文件中。 从左到右扫描程序,通过初始化:1为关键字;2为标志符; 3为常数;4为运算符或界符。 三、主要仪器设备及耗材 计算机

算法实验报告

实验一分治与递归算法的应用 一、实验目的 1.掌握分治算法的基本思想(分-治-合)、技巧和效率分析方法。 2.熟练掌握用递归设计分治算法的基本步骤(基准与递归方程)。 3.学会利用分治算法解决实际问题。 二 . 实验内容 金块问题 老板有一袋金块(共n块,n是2的幂(n≥2)),最优秀的雇员得到其中最重的一块,最差的雇员得到其中最轻的一块。假设有一台比较重量的仪器,希望用最少的比较次数找出最重和最轻的金块。并对自己的程序进行复杂性分析。 三.问题分析: 一般思路:假设袋中有n 个金块。可以用函数M a x(程序 1 - 3 1)通过n-1次比较找到最重的金块。找到最重的金块后, 可以从余下的n-1个金块中用类似法通过n-2次比较找出最轻的金块。这样,比较的总次数为2n-3。

分治法:当n很小时,比如说,n≤2,识别出最重和最轻的金块,一次比较就足够了。当n 较大时(n>2),第一步,把这袋金块平分成两个小袋A和B。第二步,分别找出在A和B中最重和最轻的金块。设A中最重和最轻的金块分别为HA 与LA,以此类推,B中最重和最轻的金块分别为HB 和LB。第三步,通过比较HA 和HB,可以找到所有金块中最重的;通过比较LA 和LB,可以找到所有金块中最轻的。在第二步中,若n>2,则递归地应用分而治之方法 程序设计 据上述步骤,可以得出程序1 4 - 1的非递归代码。该程序用于寻找到数组w [ 0 : n - 1 ]中的最小数和最大数,若n < 1,则程序返回f a l s e,否则返回t r u e。 当n≥1时,程序1 4 - 1给M i n和M a x置初值以使w [ M i n ]是最小的重量,w [ M a x ]为最大的重量。 首先处理n≤1的情况。若n>1且为奇数,第一个重量w [ 0 ]将成为最小值和最大值的候选值,因此将有偶,数个重量值w [ 1 : n - 1 ]参与f o r循环。当n 是偶数时,首先将两个重量值放在for 循环外进行比较,较小和较大的重量值分别置为Min和Max,因此也有偶数个重量值w[2:n-1]参与for循环。 在for 循环中,外层if 通过比较确定( w [ i ] , w [ i + 1 ] )中的较大和较小者。此工作与前面提到的分而治之算法步骤中的2) 相对应,而内层的i f负责找出较小重量值和较大重量值中的最小值和最大值,

递归下降分析算术表达式

递归下降分析算术表达式 计算机092—07 邹芬芬 ●实验目的: (1)掌握自上而下语法分析的要求与特点。 (2)掌握递归下降语法分析的基本原理和方法。 (3)掌握相应数据结构的设计方法。 ●实验内容: 编程实现给定算术表达式的递归下降分析器。 算术表达式文法如下:E→E+T | T T→T*F | F F→(E) | i ●设计分析 题目所给的文法不为LL(1)文法,应改写成如下文法: E →TE2 E2→+TE2 |∑ T →FT2 T2→*FT2 | ∑ F →(E) | i 采用递归下降分析法时,需要求出E2和T2 的FOLLOW集: FOLLOW(E2)={),#} FOLLOW(T2)={+,),#} 递归下降分析法是确定的自上而下分析法,基本思想是,对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分。因此需要分别构造E,E2,T,T2,F函数来执行自己的识别功能,根据文法的内容顺序决定函数的识别功能。advance函数用于字符串的推进,input函数用于字符串的输入。 ●程序代码 #include using namespace std; char a[80]; // 字符串的存入 char sym; // 单个的判断字符 int i=0; // 字符串下标 void E(); // 功能识别函数 void E2(); // 功能识别函数 void T(); // 功能识别函数 void T2(); // 功能识别函数 void F(); // 功能识别函数 void input(); // 输入函数

编译原理语法分析实验报告

编译原理实验报告 实验名称:编写语法分析程序 实验类型:设计性实验 指导教师:蒋勇 专业班级:软件工程1401 姓名:**** 学号:********** 实验地点:东六E座301 实验成绩:_________________ 日期:2016年5月17日

实验一 编写词法分析程序 一、实验目的: 1.设计、编写、调试一个递归下降分析程序,实现对词法分析程序提供的 单词序列进行语法检查和结构分析。 2.掌握递归下降语法分析方法。 3.巩固理论知识。 二、实验设计: 1.设计原理: 1)对于文法的每一个非终结符U的文法规则是一个识别U的过程定义, 为每一个非终结符构造子程序。 2)如果U的右部符号串只有一个候选式则从左到右依次构造U的识别 代码。 3)如果U的右部符号串有终结符号,则判断输入的符号是否匹配终结 符号,如果相等,则读入下一个符号;如果不相等,则有语法错误, 应当报错。 4)如果是非终结符号,则调用非终结符号的子程序即可。 5)如果U的右部有多个候选式,应该根据每个候选式的第一个符号来 确定该分支。 6)对于含有ε表达式的文法规则需要判断输入的符号是否在U的 FOLLOW集里面。 2.设计方法: (1)文法改造,消除二义性; (2)对含有左递归或者左公因子的文法消除左递归,提取左公因子; (3)求每一个右部符号串的FIRST集合,如果右部含有ε,则需要求出其 产生式左部非终结符的FOLLOW集。判断文法是否是LL(1)文法, 若不是LL(1)文法,说明文法的复杂性超过自顶向下方法的分析能力。 (4)根据改写后的文法设计程序,依据设计原理构造每一个非终结符的子 程序。 3.设计过程: (1)改写文法、消除左递归(将左递归改为右递归)、提取左公因子; (2)求出相应的First集和Follow集; (3)设计程序流程图,设计程序; (4)编写程序; 4.框架思路,错误信息输出: 对每一个非终结符构造其子程序,设定一个返回值。如果语法分析有错 则返回1,没有错误就返回0;对于错误,在程序的相应行数报错。各 个非终结符之间依据文法规则调用。每次遇到终结符函数都判断是否匹 配当前终结符号,如果不匹配则报错,返回1。如果匹配,则读入下一

相关文档
相关文档 最新文档