递归下降分析器
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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
* 输入:每行含一个表达式的文本文件。
* 输出:分析成功或不成功信息。
* 创建人:余洪周
* 版本号: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]);