1、由正规则文法构造正规则式由正规(则)文法构造正规(则)式姓 名:学 号:指导老师:时 间:一、实验目的: 了解三型文法,正则表达式和正则集的概念;了解正则表达式的性质以及正则表达式和正则文法之间的关系。给出一个文法能判断其文法类型,并且能将一个正规文法转化为正规式。二、 实验内容:判断文法是第几类文法,并将正规文法转化为正规式。三、 程序流程:1.程序流程图2.正规文法转为正规式流程图四、 实验代码:#include#includeusing namespace std;struct CSS string left; /产生式左部 string right; /产生式右部;bool IsZer
2、o(CSS *p,int n) /判断0型文法(左部不含非终结符则不是0型文法) int i,j; for(i=0; in; i+) /遍历所有产生式 for(j=0; j=A&pi.leftj=Z) break; if(j=pi.left.length() cout该文法不是0型文法endl; return false; if(i=n) return true;/如果每个产生式都能找到非终结符bool IsFirst(CSS *p,int n) /判断1型文法(右边长度大于等于左边长度) if(IsZero(p,n) /先判断是否是0型文法 int i; for(i=0; ipi.right
3、.length()&pi.right.length()!=0) /判断产生式左部长度是否大于右部 break; if(i=n) return true; cout该文法是一个0型文法endl; return false;bool IsSecond(CSS *p,int n) /判断2型文法(左部是一个非终结符) int i; if(IsFirst(p,n) /同上,先判断低级文法是否成立 for(i=0; i=A&pi.left0=Z) /判断产生式左部长度是否为一,左部第一个是否是非终结符 break; if(i=n) return true; cout该文法是1型文法endl; retur
4、n false;bool IsThird(CSS *p,int n) /判断3型文法(形如Aa,AaB的形式) int i; if(IsSecond(p,n) /同上,先判断是否是2型文法 for(i=0; i=3)|(pi.right0=A&pi.right0=Z) /判断产生式右部字符个数是否是1或者2,判断右部第一个字符是否是非终结符 break; if(i=n) for(i=0; i=A&pi.right1=Z) break; if(i=n) cout该文法属于3型文法endl; return true; cout该文法属于2型文法endl; return false;/正规文法转换为
5、正规式void transfer(CSS *p,int n) int i,j,m,flag; /合并产生式 for (i=0; in; i+) for(j=i+1; jaA,A-bA的产生式为A-aA|bA的形式 if(pi.left=pj.left)&(pi.right1=pj.right1) pi.right=pi.right+|+pj.right; pj.left=; pj.right=; /正规文法到正规式的转换规则3(合并形如S-a,S-b,S-c的产生式为S-a|b|c的形式) if(pi.right.length()=1&pj.right.length()=1&pi.left=p
6、j.left) pi.right=pi.right+|+pj.right; pj.left=; pj.right=; /提取形如S-aA|bA的公因式为S-(a|b)A的形式 for(i=0; i2&A=pi.right1&pi.right1=Z&pi.right2=|) for(j=1; jxA|y-A-x*(y) for(i=0; i1) for(j=0; jn; j+) if(pi.left=pj.left&j!=i) for(m=0; mpj.right.length(); m+) if(A=pj.rightm&pj.rightm(xx)A A-aA 转化为S-(xx)a*A) for
7、(i=0; i1 & pi.left0!=pi.rightpi.right.length()-1) for(j=0; j1 & pi.rightpi.right.length()-1=pj.left0 & pj.left0=pj.rightpj.right.length()-1) pi.right=pi.right.substr(0,pi.right.length()-1)+pj.right.substr(0,pj.right.length()-1)+*+pj.rightpj.right.length()-1; pj.right=; pj.left=; /将表达式右部所有非终结符替换 flag
8、=n; while(flag=0)/当所有产生式的右部均为终结符构成时停止转换 for(i=0,flag=flag-1; in; i+) for(j=0; jpi.right.length(); j+) if(A=pi.rightj&pi.rightj=Z) for(m=0; mn; m+) if(pm.left0=pi.rightj&m!=i) pi.right=pi.right.substr(0,j)+pm.right+pi.right.substr(j+1); pm.left=; pm.right=; break; /再次合并左部相等的产生式 for(i=0; in; i+) for(j
9、=0; j1) pi.right=pi.right+|+(+pj.right+); pj.left=; pj.right=; else pi.right=pi.right+|+pj.right; pj.left=; pj.right=; int main( ) int i,j,n; string input; while(true) cout请输入文法产生式个数Nendln; CSS *p=new CSSn; / 初始化产生式数组 for(i=0; iinput; /输入 for(j=0; jinput.length(); j+) /改变输入数据的形式 if(inputj=-) pi.left
10、=input.substr(0,j); pi.right=input.substr(j+2,input.length(); if(IsThird(p,n) /调用文法类型判断,自顶向下,如果是正规文法,则输出正规式 cout该文法属于正规文法,它的正规式如下:endl; transfer(p,n); for(i=0; in; i+) /输出转换后的文法 if(pi.left0!=NULL) coutpi.left=; for(j=0; jpi.right.length(); j+) if(pi.rightj!= ) coutpi.rightj; coutendl; return 0;六、运行截图五、 设计总结 经过本次实验,加深了我对文法类型的理解,我学会了如何识别一个0型文法,1型文法,2型文法,正规文法。尤其加深了我对正规文法的理解。我学会了如何将一个正规文法转化为一个正规式。而且还锻炼了我编写程序的能力,总之,收获颇多。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1