LEMON源码分析——项目FOLLOW集求法
来源:互联网 发布:免费刷炫舞装备软件 编辑:程序博客网 时间:2024/05/29 21:36
LEMON源码分析——项目FOLLOW集求法
都知道FOLLOW集是针对非终结符的,而LEMON中的项目FOLLOW集是针对项目的,指的是项目产生式左部非终结符FOLLOW集。
知道了项目FOLLOW集,它的求法也自然清楚了。这里把项目分成两类,它们的FOLLOW集来源是不一样的:
A. 号点不在最左的项目,FOLLOW集来源于生产式相同,点号在它前面的项目。
B. 点号在最左的项目,FOLLOW集就是生产式左部非终结符FOLLOW集。
非终结符FOLLOW集的计算方法:
1. 对于方法的开始符S,将用于表示输入结束的’$’符放入FOLLOW(S)中;
2. 若A->αBβ是一个产生式,则把FIRST(β)/{ε}加至FOLLOW(B)中;
3. 若A->αB是一个产生式,或A->αBβ是一个产生式,且β->ε,则把FOLLOW(A)加至FOLLOW(B)中。
以状态项目的生成过程介绍项目FOLLOW集的计算。
开始状态中的所有项目都是B类型项目,于是计算开始符FOLLOW集,也就是方法1,对就代码为(FindStates):
for(rp=sp->rule;rp; rp=rp->nextlhs)
{
struct config *newcfp;
rp->lhsStart = 1;
newcfp = Configlist_addbasis(rp,0);
SetAdd(newcfp->fws,0);//第一个符号为$
}
对当前状态中的项目进行closure运算,也就是要产生B类的项目,此时运用方法2与方法3计算,对应代码(Configlist_closure函数中):
for(newrp=sp->rule;newrp; newrp=newrp->nextlhs)
{
newcfp =Configlist_add(newrp,0);//生成B型项目
for(i=dot+1;i<rp->nrhs;i++)
{
xsp = rp->rhs[i];
if( xsp->type==TERMINAL )
{
SetAdd(newcfp->fws,xsp->index);//运用方法2
break;
}
else if( xsp->type==MULTITERMINAL )
{
...
}
else
{
SetUnion(newcfp->fws,xsp->firstset);//运用方法2
if( xsp->lambda==LEMON_FALSE )break;
}
}
if(i==rp->nrhs )Plink_add(&cfp->fplp,newcfp);//运用方法3
}
运用方法3时,并没有进行真正的FOLLOW拷贝,而只是做了一个记录,在后面一起“结账”。这里也可以看出,config会将自己的FOLLOW集传给自己的fplp域。
求完闭包后,就开始传播了,传播产生A型项目。些时的FOLLOW集,直接由上级往下传就行了。代码位于函数buildshifts中:
for(bcfp=cfp;bcfp; bcfp=bcfp->next)
{
if(bcfp->status==COMPLETE )continue; /* Already used */
if(bcfp->dot>=bcfp->rp->nrhs )continue; /* Can't shift this one */
bsp =bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */
if( !same_symbol(bsp,sp) )continue; /* Must be same as for "cfp"*/
bcfp->status =COMPLETE; /* Mark this config as used */
new =Configlist_addbasis(bcfp->rp,bcfp->dot+1);
Plink_add(&new->bplp,bcfp); //A型项目FOLLOW集计算方法
}
这里也只是做了个标记,并没有真正传播FOLLOW集。从Plink_add(&new->bplp,bcfp);可以看出bplp暂存着可以将FOLLOW集传播给本项目的项目。
最后将标记转换成实际上的传播。
首先,把bplp转换为fplp(FindLinks):
for(i=0;i<lemp->nstate;i++)
{
stp =lemp->sorted[i];
for(cfp=stp->cfp;cfp; cfp=cfp->next)//遍历每个状态的所有项目
{
for(plp=cfp->bplp;plp; plp=plp->next)
{
other = plp->cfp;
Plink_add(&other->fplp,cfp);
}
}
}
再将项目的FOLLOW集,传给它的fplp(FindFollowSets):
voidFindFollowSets(structlemon *lemp)
{
...
do
{
progress = 0;
for(i=0; i<lemp->nstate;i++)//遍历所有状态
{
for(cfp=lemp->sorted[i]->cfp;cfp; cfp=cfp->next)//遍历状态内所有项目
{
if( cfp->status==COMPLETE )continue;
for(plp=cfp->fplp;plp; plp=plp->next)
{
change = SetUnion(plp->cfp->fws,cfp->fws);
if( change )
{
plp->cfp->status =INCOMPLETE;
progress = 1;
}
}
cfp->status =COMPLETE;
}
}
}
while(progress );
}
- LEMON源码分析——项目FOLLOW集求法
- LEMON源码分析笔记——分割源码
- LEMON源码分析笔记——压缩分析表
- LEMON源码分析笔记——状态默认动作
- First集和Follow集的求法
- First集和Follow集的求法
- 编译原理中Follow集的求法
- FIRST集求法和FOLLOW集的求法
- FiniteTimeAction,Follow,Speed源码分析
- 编译原理 FIRST集和FOLLOW集的求法
- 编译原理 FIRST集和FOLLOW集的求法
- 编译原理 FIRST集和FOLLOW集的求法
- 编译原理 First集和Follow集的求法
- 编译原理FIRST集合FOLLOW集的求法
- 编译原理中的first,follow和select集的求法
- First/Follow集合的求法
- 预测分析表中的FIRST和FOLLOW集合求法个人小结
- lemon oa前端页面——由user-base-list谈项目组织
- ExtJs 日期控件加时间
- Solr查询过程源码分析
- MFC关键技术
- Ubuntu 10.10下部署cherokee1.2.2
- 如何在Repeater的HeaderTemplate和FooterTemplate模板中寻找控件?
- LEMON源码分析——项目FOLLOW集求法
- JSON入门详解
- USACO 1.4.1 packing rectangles
- CUDA的配置
- linux下 看代码的工具kscope
- emacs的批量替换
- C#窗体间传值
- 网上书店的错题集
- ibatis cachemodel缓存实践