消除文法的左递归实验
文法类型-消除左递归.doc

Chomsky文法类型判断消除文法的左递归年级___________专业___________学号___________姓名___________1. 实验目的要求:输入:一组任意的规则。
输出:相应的Chomsky 文法的类型。
2.实验原理1.0型文法(短语文法)如果对于某文法G,P中的每个规则具有下列形式:u:: = v其中u∈V+,v∈V*,则称该文法G为0型文法或短语文法,简写为PSG。
0型文法或短语结构文法的相应语言称为0型语言或短语结构语言L0。
这种文法由于没有其他任何限制,因此0型文法也称为无限制文法,其相应的语言称为无限制性语言。
任何0型语言都是递归可枚举的,故0型语言又称递归可枚举集。
这种语言可由图灵机(Turning)来识别。
2.1型文法(上下文有关文法)如果对于某文法G,P中的每个规则具有下列形式:xUy:: = xuy其中U∈V N;u∈V+;x,y∈V*,则称该文法G为1型文法或上下文有关文法,也称上下文敏感文法,简写为CSG。
1型文法的规则左部的U和右部的u具有相同的上文x和下文y,利用该规则进行推导时,要用u替换U,必须在前面有x和后面有y的情况下才能进行,显示了上下文有关的特性。
1型文法所确定的语言为1型语言L1,1型语言可由线性有界自动机来识别。
3.2型文法(上下文无关文法)如果对于某文法G,P中的每个规则具有下列形式:U :: = u其中U∈V N;u∈V+,则称该文法G为2型文法或上下文无关文法,简写为CFG。
按照这条规则,对于上下文无关文法,利用该规则进行推导时,无需考虑非终结符U所在的上下文,总能用u替换U,或者将u归约为U,显示了上下文无关的特点。
2型文法所确定的语言为2型语言L2,2型语言可由非确定的下推自动机来识别。
一般定义程序设计语言的文法是上下文无关的。
如C语言便是如此。
因此,上下文无关文法及相应语言引起了人们较大的兴趣与重视。
4.3型文法(正则文法,线性文法)如果对于某文法G,P中的每个规则具有下列形式:U :: = T 或 U :: = WT其中T∈V T;U,W∈V N,则称该文法G为左线性文法。
消除左递归例题

消除左递归例题
左递归是编译原理中语法分析部分的一个概念,它指的是某个非终结符A通过自身直接或间接的左递归定义产生式的规则。
消除左递归是为了简化语法分析,提高解析效率。
下面以一个简单的算术表达式为例来说明如何消除左递归:
原始的带有左递归的文法:
E -> E + T | T
T -> T * F | F
F -> (E) | id
这个文法中,E到自身的转换就构成了左递归。
消除左递归后的文法:
E -> TE'
E' -> + TE' | ε
T -> FT'
T' -> * FT' | ε
F -> (E) | id
解释一下这个变换过程:
1. 对于E,我们引入一个新的非终结符E',并将原产生式转换为`E -> TE'`和`E' -> + TE' | ε`,这里的ε表示空串,即加号后面可以没有E。
2. 同理,对于T也引入T',并将原产生式转换为`T -> FT'`和`T' -> * FT' | ε`。
这样,新的文法就没有了左递归,同时保持了原语义不变,能够描述同样的算术表达式结构。
编译原理实验二:消除文法的左递归.doc

编译原理实验报告实验名称消除文法的左递归实验时间2013年11月12日院系计算机科学与电子技术系班级11计算机软件学号JV114001 JV114095 JP114065 姓名唐茹韩强强徐思维1.试验目的:输入:任意的上下文无关文法。
输出:消除了左递归的等价文法。
2.实验原理:1.直接左递归的消除消除产生式中的直接左递归是比较容易的。
例如假设非终结符P 的规则为:P →P α / β其中,β是不以P 开头的符号串。
那么,我们可以把P 的规则改写为如下的非直接左递归形式: P →βP ’P ’→α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 α1 / P α2 /…/ P αn / β1 / β2 /…/βm其中,αi (I =1,2,…,n )都不为ε,而每个βj (j =1,2,…,m )都不以P 开头,将上述规则改写为如下形式即可消除P 的直接左递归:P →β1 P ’ / β2 P ’ /…/βm P ’P ’ →α1P ’ / α2 P ’ /…/ αn P ’ /ε 2.间接左递归的消除直接左递归见诸于表面,利用以上的方法可以很容易将其消除,即把直接左递归改写成直接右递归。
然而文法表面上不存在左递归并不意味着该文法就不存在左递归了。
有些文法虽然表面上不存在左递归,但却隐藏着左递归。
例如,设有文法G[S]:S →Qc/ c Q →Rb/ b R →Sa/ a虽不具有左递归,但S 、Q 、R 都是左递归的,因为经过若干次推导有 S ⇒Qc ⇒Rbc ⇒SabcQ ⇒Rb ⇒Sab ⇒Qcab R ⇒Sa ⇒Qca ⇒Rbca就显现出其左递归性了,这就是间接左递归文法。
消除左递归

直接消除左递归方法:
回溯:分析工作要部分地或全部地退回去重做。
条件:在文法中,对于某个非终结符地规则是其右部有多个选择,并且根据所面临地输入符号不能准确地确定所要地选择时,就可能出现回溯.
回溯带来地问题:
严重地影响了效率,只有在理论地层面上地意义而没有实际地意义。
影响效率地原因:1)语法分析需要重做;2)语义处理工作要倒退重新来做;3)当一个非终结符用某一后选式匹配成功是,这种成功可能仅仅是暂时的;4)当最终报告分析不成功时,难以知道输入串出错地准确位置;5)穷尽试探法,效率低下,代价之高。
假定P关于的全部产生式是
P→Pα1| Pα2|…| Pαm| β 1| β 2 |… | βn
其中,每个α都不等于ε,而每个β都不以P开头,
那么消除P地直接左递归就是把这个规则改写成:
P→ | β 1 P’| β 2 P’|…| β n P’
P’ →α1P’| α2P’| …| αmP’| ε
例4.2消去以下文法的直接左递归。
E→E+T|T
T→T*F|F
F→(E)|i
解:
E →TE´
E ´→+TE´|ε
T →FT´
T´→*FT´|ε
F→(E)|i
练习1]:
已知G[E]:
E→T*F | T/F | F
T →F | T*F | T/F
请消除该文法的左递归。
python实现文法左递归的消除方法

python实现⽂法左递归的消除⽅法前⾔继词法分析后,⼜来到语法分析范畴。
完成语法分析需要解决⼏个⼦问题,今天就完成⽂法左递归的消除。
没借鉴任何博客,完全⾃⼰造轮⼦。
开始之前⽂法左递归消除程序的核⼼是对字符串的处理,输⼊的产⽣式作为字符串,对它的拆分、替换与合并操作贯穿始终,处理过程的逻辑和思路稍有错漏便会漏洞百出。
采⽤直接改写法,不理解左递归消除⽅法很难读懂代码。
要求CFG⽂法判断左递归的类型消除直接左递归和间接左递归界⾯源码import osimport tkinter as tkimport tkinter.messageboximport tkinter.font as tfzhuizhong = ""wenfa = {"⾮左递归⽂法"}xi_ = ""huo = ""window = ()window.title('消除左递归')window.minsize(500,500)#转换坐标显⽰形式为元组def getIndex(text, pos):return tuple(map(int, str.split(text.index(pos), ".")))def zhijie(x,y):if not len(y):passelse:if x == y[0]:wenfa.discard("⾮左递归⽂法")#处理直接左递归zuobian = y.split('|')feizhongjie = []zhongjie = []for item in zuobian:if x in item:item = item[1:]textt = str(item) + str(x) + "'"feizhongjie.append(textt)else:text = str(item) + str(x) + "'"zhongjie.append(text)if not zhongjie:#处理A -> Ax的情况zhongjie.append(str(x + "'"))cheng = str(x) + " -> " + "|".join(zhongjie)zi = str(x) + "'" + " -> " + "|".join(feizhongjie) + "|є"text_output.insert('insert','直接左递归⽂法','tag1')text_output.insert('insert','\n')text_output.insert('insert',cheng,'tag2')text_output.insert('insert','\n')text_output.insert('insert',zi,'tag2')'''加上会判断输出⾮递归产⽣式,但会导致间接左递归不能删除多余产⽣式else:h ="不变: " + x + " -> " + ytext_output.insert('insert','⾮左递归⽂法','tag1')text_output.insert('insert','\n')text_output.insert('insert',h,'tag2')'''text_output.insert('insert','\n')def zhijie2(x,y):if not len(y):passelse:if x == y[0]:wenfa.discard("⾮左递归⽂法")#处理直接左递归zuobian = y.split('|')feizhongjie = []zhongjie = []for item in zuobian:if x in item:item = item[1:]textt = str(item) + str(x) + "'"feizhongjie.append(textt)else:text = str(item) + str(x) + "'"zhongjie.append(text)cheng = str(x) + " -> " + "|".join(zhongjie)zi = str(x) + "'" + " -> " + "|".join(feizhongjie) + "|є"text_output.insert('insert',"间接左递归⽂法",'tag1')text_output.insert('insert','\n')text_output.insert('insert',cheng,'tag2')text_output.insert('insert','\n')text_output.insert('insert',zi,'tag2')text_output.insert('insert','\n')def tihuan(xk,yi,yk):yi_you = []yi_wu =[]yi_he = ""yi_wuhe = ""yi_zhong = ""yi_feizhong = []if xk in yi:yk_replace = yk.split('|')yi_fenjie = yi.split('|')#将含⾮终结与不含分开for ba in yi_fenjie:if xk in ba:yi_you.append(ba)else:yi_wu.append(ba)yi_he = "|".join(yi_you)for item in yk_replace:yi_zhong = yi_he.replace(xk,item)#替换yi_feizhong.append(yi_zhong)yi_wuhe = "|".join(yi_wu)#再合并global zhuizhongzhuizhong = "|".join(yi_feizhong) + "|" + yi_wuhe#点击按钮后执⾏的函数def changeString():text_output.delete('1.0','end')text = text_input.get('1.0','end')text_list = list(text.split('\n'))#⼀⾏⼀⾏的拿⽂法text_list.pop()if not text_list[0]:print(tkinter.messagebox.showerror(title = '出错了!',message='输⼊不能为空')) else:for cfg in text_list:x,y = cfg.split('->')#将⽂法左右分开x = ''.join(x.split())#消除空格y = ''.join(y.split())if not (len(x) == 1 and x >= 'A' and x <= 'Z'):pos = text_input.search(x, '1.0', stopindex="end")result = tkinter.messagebox.showerror(title = '出错了!',message='⾮上下⽂⽆关⽂法!坐标%s'%(getIndex(text_input, pos),))# 返回值为:okprint(result)return 0else:zhijie(x,y)for i in range(len(text_list)):for k in range(i):xi,yi = text_list[i].split('->')xi = ''.join(xi.split())#消除空格yi = ''.join(yi.split())xk,yk = text_list[k].split('->')xk = ''.join(xk.split())#消除空格yk = ''.join(yk.split())tihuan(xk,yi,yk)tihuan(xk,zhuizhong,yk)global xi_xi_ = xizhijie2(xi_,zhuizhong)for item in wenfa:text_output.insert('insert',item,'tag1')#创建⽂本输⼊框和按钮text_input = tk.Text(window, width=80, height=16)text_output = tk.Text(window, width=80, height=20)#简单样式ft = tf.Font(family='微软雅⿊',size=12)text_output.tag_config("tag1",background="yellow",foreground="red",font=ft)text_output.tag_config('tag2',font = ft)#按钮button = tk.Button(window,text="消除左递归",command=changeString,padx=32,pady=4,bd=4) text_input.pack()text_output.pack()button.pack()window.mainloop()是不是很难懂,看看半吊⼦流程图主要流程直接左递归间接左递归合并运⾏截图总结(1)确定⽅向做⼀件事并不难,最难的是没有⽅向,不知道要做什么;只是感觉时光流逝⾃⼰却⼀点东西都没产出。
消除文法左递归

学号:专业:姓名:实验日期:2012.4.13 教师签字:成绩:实验名称:实验二:消除文法的左递归实验目的:1. 掌握上下文无关文法类型的定义,及与其他类型文法的区别;2.熟悉上下文无关文法类型的判断,能够快速按照要求写出对应文法类型的文法用例;3.给出一个上下文无关文法类型,能够正确判断其是否存在左递归,若存在则消除直接、间接左递归。
实验原理:1.文法中如果存在左递归,会产生循环递归,故需要将文法中的左递归给删除掉。
2.删除左递归需要删除直接左递归与间接左递归。
3.在删除左递归是,使用循环消元法,将左线性递归修改为又递归。
4.最后删除无用产生式。
实验内容:1.实验要求:输入任意的一个上下文无关文法,判断其是否存在左递归,若存在左递归则输出消除了左递归的等价文法。
2.实验代码:#include <iostream>#include <fstream>#include <string>#include <algorithm>#include <vector>using namespace std;struct relation{string _left;string _right;}; //关系最大为MAXN条vector<relation> rel;string VN;void print(){cout<<"[CFG消除左递归COPYRIGHT FROM NINGYU 2012/4/13]"<<endl; }bool cmp(const relation &r1,const relation &r2){if(r1._left>r2._left) return true;else if(r1._left==r2._left&&r1._right >r2._right) return true;return false;}relation get_realation(string str){ //将一个字符串生成式分为左右部输入格式为->,返回生成式结构体int t=str.find('-');relation r;r._left=str.substr(0,t);r._right=str.substr(t+2,str.length()-t);return r;}bool isUpper(char c){if(c>='A'&&c<='Z') return true;else return false;}vector<relation> find_firstVn(char c_left,char c_right){ //查找所有c为左部的产生式,c_right 为右部产生式vector<relation> v;for(int i=0;i<rel.size();i++){if(rel[i]._left[0]==c_left&&rel[i]._right[0]==c_right){v.push_back(rel[i]);rel.erase(rel.begin()+i);}return v;}vector<relation> find_Vn(char c){ //查找左部为c的产生式vector<relation> v;for(int i=0;i<rel.size();i++)if(rel[i]._left[0]==c){v.push_back(rel[i]);//rel.erase(rel.begin()+i);}return v;}bool is_exist(relation r){int i;for(i=0;i<rel.size();i++){if(r._left==rel[i]._left&&r._right==rel[i]._right)break;}if(i==rel.size()) return true;return false;}void releft(){ //消除一切左递归vector<relation> v1,v2,v3;relation r;for(int i=0;i<VN.length();i++)for (int j=0;j<=i-1;j++){v1=find_firstVn(VN[i],VN[j]);for(int t=0;t<v1.size();t++){r._left=v1[t]._left;r._right=v1[t]._right.substr(1,v1[t]._right.length()-1);if(is_exist(r)) rel.push_back(r);v2=find_Vn(VN[j]);for(int q=0;q<v2.size();q++){r._right=v2[q]._right+v1[t]._right.substr(1,v1[t]._right.length()-1); //得到替换Ai->br;if(is_exist(r)) rel.push_back(r);}}}void init(){cout<<"请输入文法,以Ctrl+Z结束"<<endl;string strPath;relation r;int p;while(cin>>strPath){rel.push_back(get_realation(strPath));//得到左部与右部;if(rel[rel.size()-1]._left.length()==1){ //得到左部的非终结符char c=rel[rel.size()-1]._left[0];if(c<='Z'&&c>='A'){int t=VN.find(c);if(t==string::npos)VN+=c;}}}}vector<relation> find_1(char c){ //查找c的直接左递归vector<relation> v;for(int i=0;i<rel.size();i++)if(rel[i]._left[0]==c&&rel[i]._right[0]==c){v.push_back(rel[i]);rel.erase(rel.begin()+i);}return v;}vector<relation> find_2(char c){//查找c的非左递归vector<relation> v;for(int i=0;i<rel.size();i++)if(rel[i]._left[0]==c&&rel[i]._right[0]!=c&&*(rel[i]._right.end()-1)!='.'){ v.push_back(rel[i]);rel.erase(rel.begin()+i);}return v;}void re_dir_left(int i){//删除有问题生成式!!!char c=VN[i];vector<relation> v1,v2;v1=find_1(c);relation r;string ch;ch.push_back(c);ch.push_back('.');bool p=false;////////////if(v1.size()>=1)p=true;/////////////////if(p){v2=find_2(c);r._left="";r._left.push_back(c);r._right="";r._right.push_back('#');if(is_exist(r)) rel.push_back(r);}for (int q=0;q<v1.size();q++){r._left=v1[q]._left;r._right=v1[q]._right.substr(1,v1[q]._right.length()-1)+ch;if(is_exist(r)) rel.push_back(r);for(int k=0;k<v2.size();k++){r._right=v2[k]._right+ch;if(is_exist(r)) rel.push_back(r);}}}int main(){print();init();sort(rel.begin(),rel.end(),cmp);releft();//消除左递归函数for(int i=0;i<VN.size();i++)re_dir_left(i);cout<<endl<<"消除左递归之后的文法为:"<<endl;sort(rel.begin(),rel.end(),cmp);for(int i=0;i<rel.size();i++)//测试读入关系是否正确cout<<rel[i]._left<<"->"<<rel[i]._right<<endl;print();}3..实验结果:。
编译原理消除左递归

编译原理消除左递归一、前言编译原理是计算机科学中的重要分支之一,它研究如何将高级语言转化成机器语言,使计算机能够理解并执行程序。
编译器是完成这一过程的关键工具之一。
编译器的核心任务是将源代码转换为目标代码,其中一个重要的步骤就是消除左递归。
二、概述在文法中,如果一个非终结符可以推导出以自身为左部的产生式,则称该文法具有左递归。
例如,对于以下文法:```A -> Aa | b```可以发现非终结符 A 可以推导出 Aa 这个产生式,而 Aa 中又包含了非终结符 A,因此该文法具有左递归。
左递归会导致递归下降分析法和 LL(1) 分析法无法正确处理该文法。
因此,在进行语法分析时需要先将文法中的左递归消除。
三、消除直接左递归直接左递归指的是形如 A -> Ab | c 的产生式中以 A 为左部且右部以A 开头的情况。
消除直接左递归需要进行以下步骤:1. 将所有以 A 开头的产生式提取出来,并将它们的右部中的 A 去掉,得到新的产生式:```A -> cA'A' -> bA' | ε```2. 将新产生式中的 A' 替换为原来的非终结符 A,得到最终结果:```A -> cA'A' -> bA' | ε```四、消除间接左递归间接左递归指的是存在一系列非终结符 A1, A2, ..., An,使得文法中存在产生式 A1 -> A2B,A2 -> A3C,..., An-1 -> AnD,An -> A1E 的情况。
消除间接左递归需要进行以下步骤:1. 将文法中所有非终结符按照拓扑排序的方式排列,并将它们编号为1, 2, ..., n。
2. 对于每个非终结符 Ai,将其可以推导出的所有非终结符按照编号从小到大排序,并将它们存储在一个集合 Bi 中。
3. 对于每个集合 Bi 中的非终结符 Bj,将其可以推导出的所有非终结符按照编号从小到大排序,并将它们存储在一个集合 Ci 中。
编译原理递归下降分析器 C语言

数学与软件科学学院实验报告学期:2015至2016第2学期2016年3月21日课程名称:编译原理专业:信息与计算科学2013级5班实验编号:2实验名称:递归下降分析器指导教师:王开端姓名:李丹学号:2013060510实验成绩:实验二递归下降分析器实验目的:通过设计、编制、调试递归下降语法分析程序,对输入的符号串进行分析匹配,观察输入符号串是否为给定文法的句子。
实验内容:根据文法G[E]设计递归下降分析器并分析输入串)(*321i i i +是否为文法的句子。
G[E]:E→E+T|TT→T*F|F F→(E)|i实验步骤:在进行递归下降分析法之前,必须对文法进行左递归和回溯的消除。
1消除左递归直接消除见诸于产生式中的左递归比较容易,其方法是引入一个新的非终结符,把含有左递归的产生式改为右递归。
文法G[E]经过消去直接左递归后得到文法G’[E]为:G’[E]:iE F FT T FT T TE E TE E |)(|'*''|'''→→→+→→εε2消除回溯回溯发生的原因在于候选式存在公共的左因子。
一般情况下,设文法中关于A 的产生式为ji i A ββδβδβδβ|...|||...||121+→,那么,可以把这些产生式改写为⎩⎨⎧→→+ij i A A A ββββδ|...|'|...||'11经过反复提取左因子,就能把每个非终结符(包括新引进者)的所有候选首字符集变为两两不相交(既不含有公共左因子)。
3什么是递归下降分析法递归下降分析法是一种自顶向下的分析方法,文法的每个非终结符对应一个递归过程(函数)。
分析过程就是从文法开始符出发执行一组递归过程(函数),这样向下推导直到推出句子;或者说从根节点出发,自顶向下为输入串寻找一个最左匹配序列,建立一棵语法树。
在不含左递归和每个非终结符的所有候选终结首字符集都两两不相交条件下,我们就可能构造出一个不带回溯的自顶向下的分析程序,这个分析程序是由一组递归过程(或函数)组成的,每个过程(或函数)对应文法的而一个非终结符。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验名称消除文法的左递归
实验时间
院系
班级
学号
姓名
1.试验目的
♦掌握和理解消除左递归(包括直接左递归和间接左递归)在构建
LL(1)文法的作用和目的
♦掌握消除左递归(包括直接左递归和间接左递归)的方法和步骤。
♦写出对于输入任意的上下文无关文法可以输出消除了左递归的等
价文法。
2.实验原理
♦直接左递归的消除
{
strcpy(ch,P[j].right); strcpy(P[cou nt].left,P[i].left); Replace(ch,P[i].right); strcpy(P[co un t].right,ch); P[cou nt].flags=0;
flags=1;
coun t++;
}
} if(flags==1)P[i].flags=1;
{
if(P[i].left[0]==P[i].right[0])flags1=1;
}
if(flags1==1)
{
chx[O]=P[i].left[O];
strcpy(P[co unt].l eft,chx);
strcpy(ch,P[i].right);
Sort(ch,chx);
strcpy(P[co un t].right,ch);
strcat(ch1,ch2);
}
void Analysis()//消除间接左递归
{
int i,j,flags=0;
char ch[50];
int num=co unt;
for(i=0;i< nu m;i++)
{
flags=0;
for(j=0;j<i;j++)
{
if(P[i].right[O]==P[j]」eft[O])
gets(P[i].left);
flushall();
prin tf("\n”);
printf("输入第%d条产生式的右部:",i+1);
gets(P[i].right);
flushall();
prin tf("\n”);
P[i].flags=0;
}
printf(" *******************************************************\n");
法,然后用消除直接左递归的方法改写文法。
♦消除左递归算法:
把文法G的所有非终结符按任一顺序排列,例如,A1,A2,…,
An。
for
(i=1;
iv=n;
i++)
for
(j=1;
j<=i-
1;j++)
{把形如AifAj丫的产生式改写成Aif81y/<2丫/…/ck丫
其中Ajf81 / 32/…/8是关于的Aj全部规则;
int flags;
}P[30];
int count=O;〃产生式数量
void creat()
{
int i;
printf("输入产生式数量:”);
scan f("%d",&count);
for(i=0;i<co un t;i++)
{
flushall();
printf("输入第%d条产生式的左部:",i+1);
for(i=0;i<(i nt)strle n( ch3);i++)
ch3[i]=ch3[i+1]; strcat(ch1,ch3);
}
void Sort(char *ch1,char ch2[2])
{
int i;
for(i=0;i<(i nt)strle n(ch1);i++) ch1[i]=ch1[i+1];
消除Ai规则中的直接左递归;
}
化简由(2)所得到的文法,即去掉多余的规则。
3..实验内容
♦利用消除左递归算法上机了实现对于输入任意的上下文无关文法
可以输出消除了左递归的等价文法。
4.实验心得
♦通过本次试验更加清晰的理解了消除左递归在构建LL(1)文法的重
要作用,以及如何的消除文法中的左递归。在本次试验中原本想用
PfPal |Pa2|…|Pa|B1 |超|…|师这种相同左部的产生式右部用或连
5.实验代码与结果
源代码(
#in clude<stdio.h>
#in clude<stri ng.h>
struct Node//定义产生式结构
{
char left[20];〃产生式左部
char right[50];〃产生式右部
P
P'—01P'/aP'/…/an P'/£
♦间接左递归的消除
直接左递归见诸于表面,利用以上的方法可以很容易将其消除, 即把直接左递归改写成直接右递归。然而文法表面上不存在左递归并 不意味着该文法就不存在左递归了。有些文法虽然表面上不存在左递 归,但却隐藏着左递归。
消除间接左递归的方法是,把间接左递归文法改写为直接左递归文
printf("你输入的产生式是:\n");
for(i=0;i<co un t;i++)
{
prin tf("%s->%s\n",P[i].left,P[i].right);
}
}
void Replace(char *ch1,char ch2[20])
{
int i;
char ch3[20]; strcpy(ch3,ch2);
}
}
void Analysis1()〃消除直接左递归
{
int i,j;
char ch[50];
char chx[2];
int num=co unt;
int flagsl;
strcpy(chx,"*1");
for(i=0;i<num;i++)〃消除直接左递归
{
flags 1=0;
if(P[i].flags==0)
消除产生式中的直接左递归是比较容易的。例如假设非终结符
P的规则为
P
其中,B是不以P开头的符号串。那么,我们可以把P的规则改写为
如下的非直接左递归形式:P—尸’
P'—P'£
考虑更一般的情况Pan/[31/[32/…/pm
其中,a(I=1,2,…,n)都不为£而每个pj(j=1,2,…,m)都不以P开头,将上述规则改写为如下形式即可消除P的直接左递归: