zoukankan      html  css  js  c++  java
  • 「编译原理」“根据LL(1)求FIRST集” 书本算法的解析及改进

    笔者使用的是 刘坚编著的《编译原理基础(第二版)》2008年9月第2版 2012年5月第8次印刷的版本。

    书P74页中
    算法3.5 计算X的FIRST集合
    输入:文法符号X。
    输出:X的FIRST集合。
    方法:应用下述规则,
    (1)若X是终结符,则FIRST(X) = {X}。
    (2)若X是非终结符且有X→ε,则加入ε到FIRST(X)中。
    (3)若X是非终结符且有X→Y1Y2…Yk,并令Y0=ε,Yk+1=ε,则从左到右对所有j(0≤j≤k),若a∈FIRST(Yj+1)且ε∈FIRST(Yj),则加入a到FIRST(X)中。

    以下为自己的一些想法,如有纰漏,还望指正!

    首先,解释一下什么是FIRST集

    对于一个符号X最后转化为实例(只由终结符组成)时,这个实例的第一个字符(如果实例长度为0则用ε表示这个字符)的所有可能情况组成的集合称为X的FIRST集合简称FIRST(X)

    对于算法3.5执行流程,我的理解是这样的:

    规则(1):对于终结符a,因为它的实例只有a一个,所以FIRST(a)必然是{a}
    规则(2):对于非终结符A,存在文法 A→ε,那么A的实例为空,即长度为0所以用ε表示该实例的第一个字符,将ε加入到FIRST(A)中。
    规则(3):对于非终结符A,存在文法 A→BCDE,将该文法的右部看成εBCDEε
    ①判断ε∈FIRST(ε),如果符合的话则将FIRST(B)加入到FIRST(A)中
    ②判断ε∈FIRST(B),如果符合的话则将FIRST(C)加入到FIRST(A)中
    ③判断ε∈FIRST(C),如果符合的话则将FIRST(D)加入到FIRST(A)中
    ④判断ε∈FIRST(E),如果符合的话则将ε加入到FIRST(A)中

    对于规则(1)(2)较为容易理解,我也并没有什么可改进的。
    对于规则(3)我的理解如下:

    按照FIRST集的定义,对于文法A→BCDE,FIRST(A)是指A的所有实例第一个字符的集合,那么我们将BCDE转换为实例有两种可能:
    1) B不为空时,这时符号A的第一个字符必然属于B不为空时所有可能第一个字符的集合,即应该将 FIRST(B)-{ε} 加入 FIRST(A)
    2) B为空时,这时文法A→BCDE就缩减成A→CDE,这个时候只需要重复上面的步骤即可。

    那么我们需要考虑的问题是如下:
    算法3.5 为什么要做

    从左到右对所有j(0≤j≤k),若a∈FIRST(Yj+1)且ε∈FIRST(Yj),则加入a到FIRST(X)中

    我们再看上面的算法执行流程:

    ①判断ε∈FIRST(ε),如果符合的话则将FIRST(B)加入到FIRST(A)中
    ②判断ε∈FIRST(B),如果符合的话则将FIRST(C)加入到FIRST(A)中
    ③判断ε∈FIRST(C),如果符合的话则将FIRST(D)加入到FIRST(A)中
    ④判断ε∈FIRST(E),如果符合的话则将ε加入到FIRST(A)中

    ~

    在第一步做看似毫无意义的判断ε∈FIRST(ε)的原因是:符号B作为文法A→BCDE右部的第一个符号,必然需要将FIRST(B)加入到FIRST(A)中,所以判断本身并不重要,但做判断后能提高算法的统一性和表达的简洁性,如果单列出来,算法会显得过于冗长;

    在后续步骤中,不断判断ε∈FIRST(B/C/D/E)的原因是:考虑到B/C/D/E有可能为空,则文法形式可能会不断缩减,极端的实例是BCDE都为空,则文法变成A→ε,所以在最后将ε加入FIRST(A)

    这么看来算法3.5好像没有什么问题,但我注意到:

    推论:如果B绝对不为空,即文法A→BCDE绝对不会缩减成A→CDE,这时会怎么样?也就是说无论CDE是否可能为空,那么文法一定是A→B……,那么对于这个文法,FIRST(A)必然等于FIRST(B)

    那么按照这个设定(ε∉FIRST(B),ε∈FIRST(C)),我们再看算法的执行过程

    ①判断ε∈FIRST(ε),符合!将FIRST(B)加入到FIRST(A)中;
    ②判断ε∈FIRST(B),不符合;
    ③判断ε∈FIRST(C),符合!将FIRST(D)加入到FIRST(A)中

    这个时候FIRST(A)包含了FIRST(B)和FIRST(D),但是按照我们推论,FIRST(A)必然等于FIRST(B),而FIRST(B)和FIRST(D)之间的关系是不明确的,所以按照算法3.5得到的结果存在问题

    所以我认为该算法应该做一定修改,以下是我做出修改后的算法

    算法3.5改 计算X的FIRST集合
    输入:文法符号X。
    输出:X的FIRST集合。
    方法:应用下述规则,
    (1)若X是终结符,则FIRST(X) = {X}。
    (2)若X是非终结符且有X→ε,则加入ε到FIRST(X)中。
    (3)若X是非终结符且有X→Y1Y2…Yk,对于j(1≤j≤k),若ε∈FIRST(Yj),则将到 FIRST(Yj)-{ε} 加入 FIRST(X)中,其中若j=k,则将ε加入 FIRST(X)中;否则,将FIRST(Yj)加入 FIRST(X)中,直接结束算法。

    按照这个修改后的算法执行设定(ε∉FIRST(B),ε∈FIRST(C)):

    ①判断ε∈FIRST(B),不符合!将FIRST(B)加入到FIRST(A)中,结束算法;

    这时FIRST(A)等于FIRST(B),符合预期。

    原创文章,转载请全文转载并注明出处

    http://www.cnblogs.com/777777-716/p/5003960.html 

  • 相关阅读:
    读jQuery之十六(事件代理)
    双向列表(JS)
    单向链表(JS)
    子程序(过程、函数、方法)
    jQuery(1.6.3) 中css方法对浮动的实现缺陷
    操作class属性的新APIclassList
    ajax后退解决方案(四)
    设置元素浮动的几种方式
    各浏览器中使用getAttribute获取checkbox/radio的checked值不同
    IE6/7不支持hashchange事件
  • 原文地址:https://www.cnblogs.com/777777-716/p/5003960.html
Copyright © 2011-2022 走看看