实验3:LL(1)文法构造
更新时间:2024-06-20 06:15:01 阅读量: 综合文库 文档下载
- 实验室工作台厂商推荐度:
- 相关推荐
实 实验课程:编译原理学生姓名:学 号:专业班级:计科
验
报
告
实验3 LL(1)文法构造
一、实验目的
熟悉LL(1)文法的分析条件,了解LL(1)文法的构造方法。
二、实验内容
1、编制一个能够将一个非LL(1)文法转换为LL(1)文法; 2、消除左递归; 3、消除回溯。
三、实验要求
1、 将一个可转换非LL(1)文法转换为LL(1)文法,要经过两个阶段,1)消除文法
左递归,2)提取左因子,消除回溯。 2、 提取文法左因子算法:
1)对文法G的所有非终结符进行排序 2)按上述顺序对每一个非终结符Pi依次执行:
for( j=1; j< i-1;j++)
将Pj代入Pi的产生式(若可代入的话); 消除关于Pi的直接左递归:
Pi->Piα|β,其中β不以Pi开头,则修改产生式为:
Pi—>βPi′ Pi′—>αPi′|ε
3)化简上述所得文法。
3、 提取左因子的算法:
A —>δβ1|δβ2|?|δβn|γ1|γ2|?|γm
(其中,每个γ不以δ开头)
那么,可以把这些产生式改写成
A —>δA′|γ1| γ2?|γm
A′—>β1|β2|?|βn
4、 利用上述算法,实现构造一个LL(1)文法:
1) 从文本文件g.txt中读入文法,利用实验1的结果,存入实验1设计的数据结
构;
2) 设计函数remove_left_recursion()和remove_left_gene()实现消除左递归和
提取左因子算法,分别对文法进行操作,消除文法中的左递归和提出左因子; 3) 整理得到的新文法;
4) 在一个新的文本文件newg.txt输出文法,文法输出按照一个非终结符号一行,
开始符号引出的产生式写在第一行,同一个非终结符号的候选式用“|”分隔的方式输出。
四、实验环境
PC微机
DOS操作系统或 Windows 操作系统
Turbo C 程序集成环境或 Visual C++ 程序集成环境
五、实验步骤
1、学习LL(1)文法的分析条件; 2、学习构造LL(1)文法的算法;
3、结合实验1给出的数据结构,编程实现构造LL(1)文法的算法;
4、结合实验1编程和调试实现对一个具体文法运用上述算法,构造它的LL(1)文法形式;
5、 把实验结果写入一个新建立的文本文件。
六、测试数据
输入数据:
编辑一个文本文文件g.txt,在文件中输入如下内容:
正确结果:
选择新的非终结符号的不同,可能会得到不同的结果,下面只是可能的一个结果:
S->Qc|cT; T->@|ab; //由于无法输出ε,用@代替 Q->Rb|b; R->bcaU|caU|cabaU|aU; U->bcaU|@; 本实验的输出结果是不唯一的,根据消除左递归是选择非终结符号的顺序不同,或
S->Qc|c|cab; Q->Rb|b; R->Sa|a; 七、实验报告要求
实验报告应包括以下几个部分: 1、 满足LL(1)文法的分析条件; 2、 构造LL(1)文法的算法;
3、 消除左递归文法和提取左因子算法实现方法; 4、 整个测试程序的流程; 5、 程序的测试结果和问题; 6、 实验总结。
代码
#include
typedef struct Chomsky //定义一个产生式结构体 {
string left; //定义产生式的左部 string right; //定义产生式的右部 }Chomsky;
int n;//产生式总数 string strings;//存储产生式 char q[20];
void apart(Chomsky *p,int i) //分开产生式左右部i代表产生式的编号 { int j;
for(j=0;j if(strings[j]=='-') { p[i].left=strings.substr(0,j);//从0开始的j长度的子串即0~j-1 p[i].right=strings.substr(j+1,strings.length()-j);//从j+1开始的后面子串 } } int zero(Chomsky *p)//0型文法 { int flag(0),count(0); int i,j; for(i=0;i for(j=0;j<(int)p[i].left.length();j++) { if(p[i].left[j]>='A'&&p[i].left[j]<='Z') //有否非终结符 flag++;//非终结符个数加1 } if(flag>0)//说明某一个产生式左部有非终结符 { flag=0;//下个产生式判断前清零 count++;//左部存在非终结符的产生式 个数加1 } else break; //左部没有非终结符结束 } if(count==n) return 1; //属于0型文法 else { cout< int one(Chomsky *p)//1型文法 { int flag(0); int i; if(zero(p)) { for(i=0;i if(p[i].right.length() else //即不是0型文法 flag--;//flag=-1 if(flag>0) { cout< return 1; //属于1型文法 else return 0; } int two(Chomsky *p)//2型文法 { int flag(0); int i; if(one(p)) { for(i=0;i if((p[i].left.length()!=1)||!(p[i].left[0]>='A'&&p[i].left[0]<='Z')) //左部不属于一个字符或不属于非终结符 { flag++;//则不为2型 break; } } else//不为1型flag=-1 flag--; if(flag>0) { cout< return 1; //属于2型文法 } else return 0; } int remove(Chomsky *p,int n)//消除左递归 {//把文法的所有非终结符按某一顺序排序 int i,j,count=1,count1=n,flag=0,m,x; q[0]=p[0].left[0]; for(i=1;i for(j=0;j if(p[i].left==p[j].left)break; } if(j==i)q[count++]=p[i].left[0]; } count--; for(i=0;i if(p[i].left[0]==q[0]&&p[i].left[0]==p[i].right[0]) flag++; if(flag!=0)//消除第一个非终结符的直接左递归 { for(i=0;i if(p[i].left[0]==q[0]) { if(p[i].left[0]==p[i].right[0]) { p[i].left=p[i].left+\ p[i].right=p[i].right.substr(1,p[i].right.length())+p[i].left; } else p[i].right=p[i].right+p[i].left+\ } } p[count1].left=p[0].left; p[count1++].right=\用#代替空产生式 } //消一切左递归 for(m=0;m<=count;m++) { for(i=0;i if(p[i].left[0]==q[m]) { for(j=0;j { for(x=m+1;x<=count;x++) if(p[j].left[0]==q[x]&&p[j].right[0]==q[m]) { p[count1].left=p[j].left; p[count1].right=p[i].right+p[j].right.substr(1,p[j].right.length()); count1=count1+1; } } } } for(j=0;j { for(x=m+1;x<=count;x++) if(p[j].right[0]==q[m]&&p[j].left[0]==q[x]) { p[j].right=\ p[j].left=\ } } for(x=0,flag=0;x if(p[x].left[0]==q[m]&&p[x].left[0]==p[x].right[0]) flag++; //消直接左递归 if(flag!=0) { for(i=0;i if(p[i].left[0]==q[m]) { if(p[i].left[0]==p[i].right[0]) { p[i].left=p[i].left+\ p[i].right=p[i].right.substr(1,p[i].right.length())+p[i].left; p[count1].left=p[i].left; p[count1].right=\用#代替空产生式 } else p[i].right=p[i].right+p[i].left+\ } } count1=count1+1; } } count1--; return count1; } void main( ) { int i,j,count1; cout<<\编译原理实验非LL(1)文法到LL(1)文法的转换................\ cout<<\请输入产生式总数及各产生式\其中左右部之间用'-'表示空用'#'表示\ cin>>n; Chomsky *p=new Chomsky[50]; // 初始化产生式数组 for(i=0;i cin>>strings; apart(p,i); } if(two(p)) { cout<<\该文法属于二型文法实验继续...\ count1=remove(p,n); cout<<\转换后的文法输出如下\ for(i=0;i<=count1;i++) { if(p[i].left[0]!=NULL) cout< cout<<\该文法不是2型文法无需进行LL(1)的转换实验结束\ system(\ } 八、思考题 1、 是不是所有的文法都可以通过上述程序构造LL(1)文法? 2、 LL(1)文法在整个语法分析中的作用? 3、 实验1中设计的文法数据结构对本实验的影响? 4、 如何更好地组合实验1和实验3,使之具有更高的效率?
正在阅读:
实验3:LL(1)文法构造06-20
2010年哲学与人生期末考试试题10-24
中国保险行业营销渠道分析 毕业论文08-09
武汉中商:第六届四次监事会决议公告 2010-08-2307-23
国美电器营销策划07-24
她向他诉说着三年的情思的微小说11-21
法律服务委托合同书07-28
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 文法
- 构造
- 实验
- LL
- 《放牧》教案
- 【完整打印版】小学二年级《口语交际》教案 苏教版
- 学生会十月份工作总结开头
- 一种长货架期酸奶的制作方法
- 在阅读和写作中培养学生的联想想象能力-精选文档
- photoshop应用作业题
- 博克服装CAD制版说明操作手册
- 2017广东金融知识竞赛题库
- 红十字会制度
- 相互作用复习教案
- 2016-2021年中国电梯导轨型钢产业发展前景及供需格局预测报告
- Ka频段卫星在军事上的应用
- 三下乡惠民政策调研报告,团队
- 体验英语少儿阅读文库 Level 1教案
- 增城区第二高级中学2018-2019学年高二上学期第二次月考试卷数学
- 世界500强前十央企集团公司子公司行政公文处理实施细则
- 2018年湖南省岳阳市中考生物试卷及答案解析
- 小学语文成语大全及解释
- 盐城2016年会计继续教育《企业会计准则解释公告第7号》题库答案
- 人防设备生产建设工程项目可行性研究报告