递归下降分析器

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

题目:编程识别由下列文法所定义的表达式的递归下降语法分析器。

E→E+T | E-T | T

T→T*F | T/F |F

F→(E) | i

输入:每行含一个表达式的文本文件。

输出:分析成功或不成功信息。

解答:

(1)分析

a) ∵E=>E+T=>E+T*F=>E+T*(E)即有E=>E+T*(E)存在左递归。用直接改写法消除左递归,得到如下:

E →TE’

E’ →+TE’ | −TE’|ε

T →FT’

T’ →*FT’ | /FT’|ε

F → (E) | i

b) 对于以上改进的方法。可得:

对于E’:FIRST( E’ )=FIRST(+TE’)∪FIRST(-TE’)∪{ε}={+,−,ε} 对于T’:FIRST( T’ )=FIRST(*FT’)∪FIRST(/FT’)∪{ε}={*,∕,ε}

而且:FIRST( E ) = FIRST( T ) = FIRST( F )=FIRST((E))∪

FIRST(i)={(,i }

由此我们容易得出各非终结符的FOLLOW集合如下:

FOLLOW( E )= { ),#}

FOLLOW(E’)= FOLLOW(E)={ ),#}

FOLLOW( T )= FIRST(E’)\ε∪FOLLOW(E’)={+,−,),#}

FOLLOW( T’ ) = FOLLOW( T ) ={+,−,),#}

FOLLOW( F )=FIRST(T’)\ε∪FOLLOW(T’)={*,∕,+,−,),#}由以上FOLLOW集可以我们可以得出SELECT集如下:

对E SELECT(E→TE’)=FIRST(TE’)=FIRST(T)={ (,i }

对E’ SELECT(E’ →+TE’)={ + }

SELECT(E’ →−TE’)={ − }

SELECT(E’ →ε)={ε,),#}

对T SELECT(T→FT’)={(,i}

对T’ SELECT(T’ →*FT’)={ * }

SELECT(T’ →∕FT’)={ ∕ }

SELECT(T’ →ε)={ε,+,−,),#}

对F SELECT(F→(E) )={ ( }

SELECT(F→i)={ i }

∴SELECT(E’ →+TE’)∩SELECT(E’ →−TE’)∩SELECT(E’ →ε)=ΦSELECT(T’ →*FT’)∩SELECT(T’ →∕FT’)∩SELECT(T’ →ε)=Φ

SELECT(F→(E) )∩SELECT(F→i)= Φ

由上可知,有相同左部产生式的SELECT集合的交集为空,所以文法是LL (1)文法。因此,转化后的文法可以用递归下降分析法作语法分析。

(2)设计

这里采用递归下降分析法形象描述递归子程序。程序中将要用到的几个重要数据如下:

一个全局变量ch,存放由文件输入得到的字符。

一个函数宏READ(ch),实现读取文件中的字符。

五个子函数:P(E)、P(E’)、P(T)、P(T’)、P(F)。

程序主要的子函数模块流程图如下:

程序子模块图

(3)程序代码如下

/******************************************************************** ****

* 文件名:ana.c

* 文件描述:递归下降语法分析器。分析如下方法:

* E->E+T | E-T | T

* T->T*F | T/F |F

* F->(E) | i

* 输入:每行含一个表达式的文本文件。

* 输出:分析成功或不成功信息。

* 创建人:余洪周 2006-12-8

* 版本号:1.0

********************************************************************* **/

#include

#include

#define READ(ch) ch=getc(fp) /*宏:READ(ch)*/

char ch; /*声明为全局变量*/

int right=0;

FILE *fp;

struct struCH{

char ch;

struct struCH *next;

}struCH,*temp,*head,*shift;

/*head指向字符线性链表的头结点*/

/*shift指向动态建成的结点(游标)*/

void main(int argc,char *argv[]){

void E (); /* P(E) */

void E1(); /* P(E')*/

void T (); /* P(T) */

void T1(); /* P(T')*/

void F (); /* P(F) */

int errnum=0,k=0,m=0,countchar=0,rownum;

int charerr=0; /*开关控制量*/

/************************以只读方式打开文件*********************/

if((fp=fopen(argv[1],"r"))==NULL)

{

printf("\n\tCan not open file %s,or not exist it!\n",argv[1]);

exit(0); /*文件不存在or打不开时,正常退出程序*/

}

else printf("\n\tSuccess open file: %s\n",argv[1]); /*成功打开文件*/

/******************遍历整个文件检测是否有非法字符

********************/

/*如果用while(!feof(fp))语言,将会多出一个字符

*所以这里采用以下方法遍历整个文件检测其否有非法字符

*/

/*[1]计算文件中字符数量*/

while(!feof(fp)){

READ(ch); /*这里读取字符只是让文件指针往前移*/

countchar++; /*统计文件中的字符数(包括换行符及文件结束符)*/

}

rewind(fp); /*将fp文件指针重新指向文件头处,以备后面对文件的操作*/

if(countchar==0){ /*空文件*/

printf("\t%s is a blank file!\n",argv[1]);

相关文档
最新文档