自动生成LR0分析表
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理实验报告
实验名称自动生成LR(0)分析表实验时间2011年6月13日
院系计算机科学与技术
班级08计算机科技一班
学号E10814065
姓名王全鸿
1.试验目的
输入:任意的压缩了的上下文无关文法。
输出:相应的LR(0)分析表。
2.实验原理
在LR分析工作过程中的任何时候,栈里的文法符号(自栈底而上)X1X2…Xm应该构成活前缀,把输入串的剩余部分配上之后即应成为规范句型(如果整个输入串确实构成一个句子)。因此,只要输入串的已扫描部分保持可归约成一个活前缀,那就意味着所扫描过的部分没有错误。
构造识别文法活前缀DFA有3种方法:
(1)根据形式定义求出活前缀的正则表达式,然后由此正则表达式构造NFA再
确定为DFA;
(2)求出文法的所有项目,按一定规则构造识别活前缀的NFA再确定化为DFA;
(3)使用闭包函数(CLOSURE)和转向函数(GO(I,X))构造文法G’的LR(0)的项目集规范族,再由转换函数建立状态之间的连接关系来得到识别活前缀的DFA。
对于LR(0)文法,我们可以直接从它的项目集规范族C和活前缀识别自动机的状态转换函数GO构造出LR分析表。下面是构造LR(0)分析表的算法。
假定C={I0, I1,…,In},令每个项目集Ik的下标k为分析器的一个状态,因此,G'的LR(0)分析表含有状态0,1,…,n。令那个含有项目S'→.S的Ik的下标k为初态。ACTION子表和GOTO子表可按如下方法构造:
(1)若项目A→α.aβ属于Ik且GO (Ik, a)= Ij, a为终结符,则置ACTION[k, a]为“把状态j和符号a移进栈”,简记为“sj”;
(2)若项目A→α.属于Ik,那么,对任何终结符a,置ACTION[k,a]为“用产生式A→α进行规约”,简记为“rj”;其中,假定A→α为文法G'的第j个产生式;
(3)若项目S'→S.属于Ik, 则置ACTION[k, #]为“接受”,简记为“acc”;
(4)若GO (Ik, A)= Ij, A为非终结符,则置GOTO[k, A]=j;
(5)分析表中凡不能用上述1至4填入信息的空白格均置上“出错标志”。
按上述算法构造的含有ACTION和GOTO两部分的分析表,如果每个入口不含多重定义,则称它为文法G的一张LR(0)分析表。具有LR(0)表的文法G称为一个LR(0)文法,LR(0)文法是无二义的。
3.实验内容
(1) 实现计算闭包closure(I)的算法;
(2) 实现转向函数Go(q,a)的算法;
(3)构造文法项目集函数CreateProjectSet();
定义数据结构:
typedef struct{
SElemType *base,*top;
int stacksize;
}SqStack;
struct grammer{
char **g;
char vt[127];
char vn[27];
char s;
int line;
};
typedef struct prjset
{
int id;//项目集编号,从10000开始,与
项目编号(从0开始)区别
struct prjset *next;//指向下个项目集
char
prjt[PROJECT_SET_SIZE+1];//PROJECT_SET_SI ZE个单元,存储项目的编号,prjt[0]项目编号的个数
char pointafter[PROJECT_SET_SIZE+1];//圆点后的字符,pointafter[0]字符个数
struct prjset *actorgo[PROJECT_SET_SIZE];
char pointbefore;
}prjset,*pprjset;
4.实验心得
通过这次实验我对LR(0)语法分析有了一个更熟悉的掌握,对预先定义的文法规则,并集成词法分析、符号表管理等程序来生成LR(0)分析表有了清醒的认识,并且对高级程序语言一般结构和主要共同特征有了全面的认识和理解.
5.实验代码
void CreateProjectSet()
{//构造文法的项目集
int i;
int j;
int k;
int id = ID;
pprjset p,q;
root.I = root.tail = NULL;
if((p = (pprjset)malloc(sizeof(prjset))) == NULL) exit(1);
p->id = id;
p->next = NULL;
p->prjt[0] = 0;
p->pointafter[0] = 0;
p->pointbefore = '\0';
for(j=0; j p->actorgo[j] = NULL; for(j=0; j p->actorgo[j] = NULL; root.I = p; root.tail = p; root.size = 1; for(i=0; i { if(project.s==project.gp[i][GRAMME R_START_CHAR_POS]&&DOT== project.gp[i][GRAMMER_START_CH AR_POS+1]) { JoinSet(root.I->prjt, project.gp[i][PROJECT_ID_POS]); JoinSet(root.I->pointafter, project.gp[i][AFCHAR_POS]); break; }//if }//for Closure(root.I); int pos; for(q=root.I; q!=NULL; q=q->next) { for(i=1; i<=q->pointafter[0]; i++) { pos = i; pos--; if((p = (pprjset)malloc(sizeof(prjset))) == NULL) exit(1); p->next = NULL; p->prjt[0] = 0; p->pointafter[0] = 0; p->pointbefore = q->pointafter[i]; for(j=0; j p->actorgo[j] = NULL; for(j=1; j<=q->prjt[0]; j++) {