LL1文法的判别c语言,编译原理实验七:LL1文法的判断

《编译原理实验七:LL1文法的判断》由会员分享,可在线阅读,更多相关《编译原理实验七:LL1文法的判断(11页珍藏版)》请在人人文库网上搜索。

1、实验七:LL(1)文法的判断 一:要求输入:任意的上下文无关文法。输出:判断是否为LL(1)文法二:实验目的1掌握LL(1)的判断,掌握求first和follow集合的算法2熟悉运用C/C+语言对求first和follow集合进行实现 三:实验原理设x1x2xn,FIRST()可按下列方法求得:令FIRST(),i1;(1)若xiVT,则xiFIRST();(2)若xiVN; 若 FIRST(xi),则FIRST(xi)FIRST(); 若FIRST(xi),则FIRST(xi)FIRST();(3)ii+1,重复(1)、(2),直到xiVT,(i2,3,n)或xiVN且若 FIRST(xi)。

2、或in为止。当一个文法中存在产生式时,例如,存在A,只有知道哪些符号可以合法地出现在非终结符A之后,才能知道是否选择A产生式。这些合法地出现在非终结符A之后的符号组成的集合被称为FOLLOW集合。下面我们给出文法的FOLLOW集的定义。设文法GS(VN,VT,P,S),则FOLLOW(A)a | S Aa ,aVT。若S A,#FOLLOW(A)。由定义可以看出,FOLLOW(A)是指在文法GS的所有句型中,紧跟在非终结符A后的终结符号的集合。FOLLOW集可按下列方法求得:(1)对于文法GS的开始符号S,有#FOLLOW(S);(2)若文法GS中有形如BxAy的规则,其中x,yV *,则FI。

3、RST(y)FOLLOW(A);(3)若文法GS中有形如BxA的规则,或形如BxAy的规则且FIRST(y),其中x,yV *,则FOLLOW(B)FOLLOW(A);四:数据结构与算法typedef struct Chomsky /定义一个产生式结构体string left; /定义产生式的左部string right; /定义产生式的右部Chomsky;void apart(Chomsky *p,int i) /分开产生式左右部,i代表产生式的编号string is_empty(Chomsky *p)/判断某非终结符能否直接推出空,空用#代替string isempty(Chomsky *。

4、p)/可以间接推出空的非终结符void search(Chomsky *p,int n)/提取产生式中的非终结符void First(Chomsky *p,int n,char m,int mm)/求文法中非终结符的First集void Follow(Chomsky *p,int n,int m)/求文法的follow集string erase(string s)/去First集及follow集中的重复字符void select(string s1,string s2)/求产生式的select集,s1是产生式左部,s2是产生式右部五:出错分析1:select集计算不出,关键在于能产生空的非终结。

5、符没有求出来2:单个符号的first集与一串符号的first集区别3:实验最后没能输出select集,没能判断出来是否是LL(1)文法 六:实验结果与分析七:源代码#include#includeusing namespace std;#define max 100typedef struct Chomsky /定义一个产生式结构体string left; /定义产生式的左部string right; /定义产生式的右部Chomsky;int n;/产生式总数string strings;/存储产生式string noend;/存放文法中的非终结符string empty;/存放可以推出空的非。

6、终结符string firstmax;/存放非终结符的first集string followmax;/存放非终结符的follow集string selectmax;/存放产生式的select集void apart(Chomsky *p,int i) /分开产生式左右部,i代表产生式的编号int j;for(j=0;j=0)/若此非终结符已经存在直接推出空那里,在此无需重复计算elsefor(j=0;j=0&noend.find(pi.left0)=0&noend.find(pi.rightj)=pi.right0)firstmm=firstmm+pi.right.substr(0,1);if(pi.right0=#)firstmm=firstmm+pi.right.substr(0,1);if(A=pi.right0)for(j=0;jn;Chomsky *p=new Chomskyn; / 初始化产生式数组for(i=0;istrings; apart(p,i); coutf;search(p,n);/提取产生式中的非终结符/empty=is_empty(p)+isempty(p);/可以推出空的所有非终结符for(m=0;mpi.right:selectiendl;system(pause。

本程序的所用的存储结构都是string类型的,最主要的存储文法的数据结构为自定义结构,里面包括一个产生式的左部,右部以及select集合,至于非终结符的first和follow集合,则是定义了一个string类型的数组进行存储。 本程序的求first,follow,select集合的算法即为书上所介绍的方法,即求first的集合时,只看本产生式,求follow集合时,要进行递归查找一个非终结符的所有后跟字符,求select其实就是对first与follow集合的运算,最终根据所有的select集合,便可以判断文法是否为LL(1)文法。 对于不是LL(1)文法的产生式,本程序在判断后进行转换,先进行消除左递归,然后提取左公因子,在这两步的每一步结束之后,都要对产生式进行整合,去掉空存储,去掉无法到达的产生式,将select全部置空。 每进行一次非LL(1)到LL(1)的转换之后,都要对其文法性质进行判断,如果是LL(1),则跳出,不是则继续,但是当循环一定次数之后仍不是,程序判定其无法转换,也要跳出。 其还有对第一个非终结字符的右部替换与否进行选择,原因是,有些通过替换就可以很方便的进行转换,这个要通过人为进行输入。 提取公因子也有上一段所说的类似的判断机制,目的是为了防止文法的左公因子无法提取完的情况出现。 最终有三种结果,一种是是LL(1)文法,一种是不是LL(1),但是经过转换变成了LL(1),还有一种是经过转换也无法变成LL(1)。 输入文本格式样例: A A->ad A->Bc B->aA B->bB
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值