实验3LL1文法构造Word文档格式.docx
- 文档编号:20305313
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:12
- 大小:73.90KB
实验3LL1文法构造Word文档格式.docx
《实验3LL1文法构造Word文档格式.docx》由会员分享,可在线阅读,更多相关《实验3LL1文法构造Word文档格式.docx(12页珍藏版)》请在冰豆网上搜索。
消除关于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操作系统
TurboC程序集成环境或VisualC++程序集成环境
五、实验步骤
1、学习LL
(1)文法的分析条件;
2、学习构造LL
(1)文法的算法;
3、结合实验1给出的数据结构,编程实现构造LL
(1)文法的算法;
4、结合实验1编程和调试实现对一个具体文法运用上述算法,构造它的LL
(1)文法形式;
5、把实验结果写入一个新建立的文本文件。
六、测试数据
输入数据:
编辑一个文本文文件g.txt,在文件中输入如下内容:
S->
Qc|c|cab;
Q->
Rb|b;
R->
Sa|a;
正确结果:
本实验的输出结果是不唯一的,根据消除左递归是选择非终结符号的顺序不同,或选择新的非终结符号的不同,可能会得到不同的结果,下面只是可能的一个结果:
Qc|cT;
T->
@|ab;
//由于无法输出ε,用@代替
bcaU|caU|cabaU|aU;
U->
bcaU|@;
七、实验报告要求
实验报告应包括以下几个部分:
1、满足LL
(1)文法的分析条件;
2、构造LL
(1)文法的算法;
3、消除左递归文法和提取左因子算法实现方法;
4、整个测试程序的流程;
5、程序的测试结果和问题;
6、实验总结。
代码
#include<
iostream>
string>
usingnamespacestd;
typedefstructChomsky//定义一个产生式结构体
{
stringleft;
//定义产生式的左部
stringright;
//定义产生式的右部
}Chomsky;
intn;
//产生式总数
stringstrings;
//存储产生式
charq[20];
voidapart(Chomsky*p,inti)//分开产生式左右部i代表产生式的编号
intj;
for(j=0;
j<
strings.length();
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开始的后面子串
}
}
intzero(Chomsky*p)//0型文法
intflag(0),count(0);
inti,j;
for(i=0;
i<
n;
i++)
(int)p[i].left.length();
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)
return1;
//属于0型文法
else
cout<
<
endl<
"
所输产生式不属于任何文法。
endl;
return0;
intone(Chomsky*p)//1型文法
intflag(0);
inti;
if(zero(p))
if(p[i].right.length()<
p[i].left.length())//右部长度是否小于左部不是1型
else//即不是0型文法
flag--;
//flag=-1
0)
此文法属于0型文法即短语文法。
//不属于1型文法
if(flag==0)
//属于1型文法
inttwo(Chomsky*p)//2型文法
if(one(p))
if((p[i].left.length()!
=1)||!
(p[i].left[0]>
p[i].left[0]<
))//左部不属于一个字符或不属于非终结符
//则不为2型
else//不为1型flag=-1
此文法属于1型文法即上下文有关文法。
//不属于2型文法
//属于2型文法
intremove(Chomsky*p,intn)//消除左递归
{//把文法的所有非终结符按某一顺序排序
inti,j,count=1,count1=n,flag=0,m,x;
q[0]=p[0].left[0];
for(i=1;
i;
if(p[i].left==p[j].left)break;
if(j==i)q[count++]=p[i].left[0];
count--;
i++)//判断第一个非终结符是否存在直接左递归
if(p[i].left[0]==q[0]&
p[i].left[0]==p[i].right[0])
if(flag!
=0)//消除第一个非终结符的直接左递归
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;
p[i].right=p[i].right+p[i].left+"
p[count1].left=p[0].left;
p[count1++].right="
#"
//用#代替空产生式
//消一切左递归
for(m=0;
m<
=count;
m++)
if(p[i].left[0]==q[m])
count1;
{for(x=m+1;
x<
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(x=m+1;
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++)//判断第m个非终结符是否存在直接左递归
if(p[x].left[0]==q[m]&
p[x].left[0]==p[x].right[0])
//消直接左递归
=0)
p[count1].left=p[i].left;
p[count1].right="
count1--;
returncount1;
voidmain()
inti,j,count1;
...............编译原理实验非LL
(1)文法到LL
(1)文法的转换................"
请输入产生式总数及各产生式"
其中左右部之间用'
表示空用'
#'
表示"
cin>
>
Chomsky*p=newChomsky[50];
//初始化产生式数组
strings;
apart(p,i);
if(two(p))
该文法属于二型文法实验继续..."
count1=remove(p,n);
转换后的文法输出如下"
=count1;
if(p[i].left[0]!
=NULL)
p[i].left<
->
p[i].right<
该文法不是2型文法无需进行LL
(1)的转换实验结束"
system("
pause"
);
八、思考题
1、是不是所有的文法都可以通过上述程序构造LL
(1)文法?
2、LL
(1)文法在整个语法分析中的作用?
3、实验1中设计的文法数据结构对本实验的影响?
4、如何更好地组合实验1和实验3,使之具有更高的效率?
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 LL1 文法 构造
![提示](https://static.bdocx.com/images/bang_tan.gif)