消除文法的左递归实验
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理实验报告
实验名称消除文法的左递归
实验时间
院系
班级
学号
姓名
1.试验目的
◆掌握和理解消除左递归(包括直接左递归和间接左递归)在构建LL(1)文法的作用和目的
◆掌握消除左递归(包括直接左递归和间接左递归)的方法和步骤。
◆写出对于输入任意的上下文无关文法可以输出消除了左递归的等价文法。
2.实验原理
◆直接左递归的消除
消除产生式中的直接左递归是比较容易的。例如假设非终结符P的规则为
P→Pα / β
其中,β是不以P开头的符号串。那么,我们可以把P的规则改写为如下的非直接左递归形式:P→βP’
P’→αP’ / ε
考虑更一般的情况,假定关于非终结符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’ /ε
◆间接左递归的消除
直接左递归见诸于表面,利用以上的方法可以很容易将其消除,
即把直接左递归改写成直接右递归。然而文法表面上不存在左递归并不意味着该文法就不存在左递归了。有些文法虽然表面上不存在左递归,但却隐藏着左递归。
消除间接左递归的方法是,把间接左递归文法改写为直接左递归文法,然后用消除直接左递归的方法改写文法。
◆消除左递归算法:
把文法G的所有非终结符按任一顺序排列,例如,A1,A2,…,An。
for (i=1;i<=n;i++)
for (j=1;j<=i-1;j++)
{ 把形如Ai→Ajγ的产生式改写成Ai→δ1γ /δ2γ /…/δkγ
其中Aj→δ1 /δ2 /…/δk是关于的Aj全部规则;
消除Ai规则中的直接左递归;
}
化简由(2)所得到的文法,即去掉多余的规则。
3..实验内容
◆利用消除左递归算法上机了实现对于输入任意的上下文无关文法可以输出消除了左递归的等价文法。
4.实验心得
◆通过本次试验更加清晰的理解了消除左递归在构建LL(1)文法的重要作用,以及如何的消除文法中的左递归。在本次试验中原本想用
P→Pα1 |Pα2 |…|Pαn |β1 | β2 |…|βm这种相同左部的产生式右部用或连
接起来形式来消除左递归但是在实现上不是很容易,所以只有分开书写利用消除左递归的算法来实现.
5.实验代码与结果
源代码(C)
#include
#include
struct Node//定义产生式结构
{
char left[20];//产生式左部
char right[50];//产生式右部
int flags;
}P[30];
int count=0;//产生式数量
void creat()
{
int i;
printf("输入产生式数量:");
scanf("%d",&count);
for(i=0;i { flushall(); printf("输入第%d条产生式的左部:",i+1); gets(P[i].left); flushall(); printf("\n"); printf("输入第%d条产生式的右部:",i+1); gets(P[i].right); flushall(); printf("\n"); P[i].flags=0; } printf("*******************************************************\n"); printf("你输入的产生式是:\n"); for(i=0;i { printf("%s->%s\n",P[i].left,P[i].right); } } void Replace(char *ch1,char ch2[20]) { int i; char ch3[20]; strcpy(ch3,ch2); for(i=0;i<(int)strlen(ch3);i++) ch3[i]=ch3[i+1]; strcat(ch1,ch3); } void Sort(char *ch1,char ch2[2]) { int i; for(i=0;i<(int)strlen(ch1);i++) ch1[i]=ch1[i+1]; strcat(ch1,ch2); } void Analysis()//消除间接左递归 { int i,j,flags=0; char ch[50]; int num=count; for(i=0;i { flags=0; for(j=0;j { if(P[i].right[0]==P[j].left[0]) { strcpy(ch,P[j].right); strcpy(P[count].left,P[i].left); Replace(ch,P[i].right); strcpy(P[count].right,ch); P[count].flags=0; flags=1; count++; } } if(flags==1)P[i].flags=1; } } void Analysis1()//消除直接左递归 { int i,j; char ch[50]; char chx[2]; int num=count;