目录
1.基本概念
(1)前文回顾
在上一篇文章中(活前缀及构造活前缀的DFA_驼驼学编程的博客-CSDN博客)我们简单的介绍了我们该如何的去构造活前缀的DFA,但是只讲了概念,很多同学都还是一头雾水,在这篇文章中我将会详细的介绍如何的去构造活前缀的DFA。
(2)项目->NFA->DFA
大家可能看这个图有点懵,不知道是怎么来的,其实这个图是将项目转化为左边的NFA,再根据第二章NFA和DFA转化的知识转化为了左边的DFA。
对于左边的图,中间的每一个状态都是活前缀的识别态,特别是画出了双圈的状态,代表了句柄识别态马上可以规约。
比如说
状态8,对应的是A->CA· 意味着CA已经识别了,应该把它规约为A
状态18,d已经形成了,应该把它规约成B
对于右边的图,是把NFA确定化之后得到的一个识别活前缀的DFA,DFA由子集法得到。里面的符号串(活前缀)在不断形成,就相当于在这个DFA上不断游走。
我们来用上面的图举例子,DFA初始状态为0,我们来分析一下输入串是bd#的情况
刚开始分析栈内的状态和符号分别是0和#
我们可以根据LR分析表可知要将b移入,对应DFA我们可以看出转到了状态3,将3和b分别压入状态栈和符号栈,操作过程如下
我们接着往后看,这时候将d压入栈中,对照DFA,我们可以看出来到了状态11,将11和d分别压入状态栈和符号栈,操作过程如下
这时候我们可以看到栈中符号栈自栈顶向下分别是db,这刚好符合了状态11的项目B->d·,这说明d要进行规约,DFA回退到状态3,将规约后的B压入栈中,此时符号栈中为bB
此时为状态7,接着上面的过程继续。保证栈里面的符号始终满足DFA的要求,也就是始终保持栈里面是活前缀
(3)Closure->Go->DFA
1.有效项目
我们假设ω是终结符构成的串,那么在这种情况下,我们就说这个项目对于活前缀αβ1是有效的,点前面的β1和A前面的α一起构成一个活前缀
我们来举个例子
利用左边图片的规则,来求出右边图片对应哪些活前缀是有效的
对于活前缀bc,我们要经过路径bc
这个意思是通俗易懂的,对于同一个状态,其中一个项目成立,对于这个状态的其他项目也是有效的。
2.项目集的闭包CLOSURE
定义依旧是非常的复杂,我还是通过一个例子来进行讲解吧
从S‘->E开始推导,根据Closure的规定,此时的· 在E的前面,E又可以推出aA和bB,故·也在他们的前面,利用Go来推导第一个式子,此时的Closure要将里面的圆点向后移动一位,对于E来说就变成了E·,结束了。接着推导第二个式子,圆点向后移动一位,此时的项目为S’->a·A,S’->a·A当然在他的Closure中,而A->cA|d,由此可知可以将圆点放在他们的第一位,也就是A->·cA和A->·d,将这个集合记为I2,Go(I0,b)也是通过这种方式推导得到的,如下如所示,接着一直推导,完整过程请同学们补充。
我们来看一下对于G这个文法我们按照刚才的算法是怎么样一步一步计算出项目集,是怎样把项目集连成DFA的,最开始的时候零状态,只有一个项目(左图),那么要对它做闭包,那么关于E的两个产生式,他的两个项目就应该进来(右图)
然后从他出发做GO函数,会产生更多的项目集,例如他识别E之后,那么这里面只有第一个项目,然后接着推导到a,b的项目集,推导过程就是上面的项目集转移函数计算,最后我们也能推导出完整的项目集
最后的答案也是这个图,是不是感觉很熟悉。