• 第4章 语法分析


    自顶向下语法分析

    消除回溯

    • 路标法设有规则U∷=a1V1|a2V2|…|anVn,若ai为互不相同的终结符时,将ai作为路标,当被分析符号串为ai时,便可按规则U∷=aiVi往下分析,这样可以消除回溯。
    • 提取左因子法当文法不满足上述路标法条件,即规则右部首符号相同时,可以采用提取左因子法对文法进行改写。

    消除直接左递归

    • 重复表示法:使用扩充BNF重新表示规则
    • 改写法A引入一个新的非终结符A′,将A∷=Aα|β等价写成A∷=βA′;A′∷=αA′|ε

    消除间接左递归

    对于间接左递归先将间接左递归变成直接左递归,然后消除直接左递归
    例如:A ∷=aB|Bb(1);B ∷=Ac|d(2)
    先将(1)代入(2)中,得B ∷=Bbc|aBc|d(3)
    由此将(3)改写为:B ∷=(aBc|d)B′∷=bcB′|ε

    LL(1)语法分析

    LL(1)分析方法也是一种自顶向下不带回溯的分析方法,LL的意思是:从左到右扫描输入符号串并建立它的最左推导。数字1是指向前看一个符号来决定选择同一个非终结符的不同规则。

    构造头终极符号集FIRST

    FIRST(α)α的所有可能推导的开头终结符或可能的ε

    对于文法中的每一个文法符X∈(VNUVT),构造FIRST(X)时,只要连续使用下列规则,直至每个FIRST集不再扩大为止。�

    1. X∈VT,则FIRST(X)={X}。�
    2. X∈VN,且有形如X∷=aα规则(a∈VT),或X∷=ε的规则,把a或(和)ε加入FIRST(X)中。�
    3. 设文法G中有形如X∷=Y1Y2…Yk的规则,若Y1∈VN,则将FIRST(Y1)中一切ε符号加进FIRST(X)中,若Y1=>*ε,则把Y2中首符号集FIRST(除ε外)也加入FIRST(X)中,如此继续下去,直到Yk-1=>*ε,则把Yk中首符号集(除ε外)也入FIRST(X)中。
    4. Y1,Y2…Yk每个非终结符号都可能推导出空符号串,即Y1,Y2…Yk=>*ε,则把ε也加进FIRST(X)

    构造后继终结符号集FOLLOW

    FOLLOW(B)是所有句型中出现在紧接B之后的终结符#

    对文法中每个非终结符B,为了构造FOLLOW(B),可反复应用如下规则,直到每个FOLLOW集不再扩大为止。�

    1. B是文法的开始符号,令#∈FOLLOW(B)
    2. 若文法中有形如A∷=αBβ的规则,且β≠ε,则将FIRST(β)中一切ε符号加进FOLLOW(B)中。�
    3. 若文法中有形如A∷=αBA∷=αBβ的规则,且β=>*ε,则将FOLLOW(A)中全部终结符写入FOLLOW(B),其中α可以为ε

    构造分析表M

    1. 求出符号串FIRST集合和所有非终结符FOLLOW集合
    2. 对于G中每一个规则A∷=α,可按如下算法确定表中各元素:
      • FIRST(α)中每一终结符a,置M[A, a]=“A→α”;
      • ε∈FIRST(α),则对属于FOLLOW(A)中的每一符号b (b为终结符或),置M[A,b]=“A→α”
      • M中所有不能按规则①、②定义的元素均置为出错,置为空。

    LL(1)分析符号串

    • 分析栈从左到右是栈底到栈顶,栈底放置#,符号串从左到右是首元素和末尾元素,某尾放置#
    • 每次分析栈顶元素遇到余留符号串首字符,并将分析表中规则右部倒序放入分析栈
    • 如果栈顶元素和余留符号串首字符相同,则两者匹配去除,直到分析栈和预留符号串皆剩下#,则分析成功

     

    LL(1)文法

    • 一个文法G,如果它的分析表M不含多重定义入口,则称该文法是LL(1)文法。
    • LL(1)文法是2型文法,但并不是所有2型文法都是LL(1)文法。
    • LL(1)文法不是二义的,也不含左递归。

    证明文法GLL(1)文法,当且仅当G的任何两个规则A∷=α|β,满足下面条件:�

    1. FIRST(α)∩ FIRST(β)=Ø,也就是αβ推导不出以某个同一终结符a为首的符号串。
    2. αβ中最多只有一个可能推出空串.
    3. 如果β=>*ε,那么α推出任何串不会以FOLLOW(A)中的终结符开始,即若β=>*εFIRST(α) ∩FOLLOW(A) =Ø。

    自底向上语法分析

    活前缀:是规范句型的一个前缀,不含有句柄后任何符号

    活前缀和句柄的关系

    • 活前缀已包含句柄全部符号,用A∷=β·表示,意味着相应的分析动作应是用此规则进行归约,称可归约的活前缀。
    • 活前缀中只含句柄一部分符号,用A∷=β1·β2表示,意味着β1已出现在栈顶,正期待着从余留输入串中看到能由β2推出的符号串。
    • 活前缀不包含句柄的任何符号,用A∷=·β表示,意味着右部符号串β不在分析栈顶,正期待从余留输入串中由规则A∷=ββ所能推出的符号串。

    LR(0)项目

    • 对于形如A∷=β·项目, 因为它表明右部符号串β已出现在栈顶,此时相应分析动作应按规则进行归约,称此种项目为归约项目
    • 对于形如A∷=β1·aβ2,其中β1可以是ε,a是终结符相应分析动作应将当前输入符号移入栈中,故称此项目为移进项目
    • 对于形如A∷=β1·Bβ2,其中β1可以是ε,B是非终结符由于期待着从余留输入符号串中进行归约而得到B,称此类项目为待约项目

    构造识别活前缀的NFA

    • 拓广文法:设开始文法S′,将项目S′∷=·S称为项目集I0的基本项目。对于规则A∷=β对应项目数为|β|+1个,根据·号位置不同进行拓广文法;
    • 闭包的构建(自我拓展):若状态中有形如A→β1·Bβ2LR(0)项目,则将B→x1|x2|...|xn所有项目加入此状态,重复以上过程,直至新产生的LR(0)项目圆点后全是总结符号位置(B∈VN)
    • 延伸:状态中所有形如A→β1·αβ2LR(0)项目(α可以是VN也可以是VT),标注一条箭弧(箭弧上的符号为α)延伸至新的状态,新状态中必会有A→β1αβ2LR(0)项目。所有状态都要进行延伸,直至圆点后无符号或出现自回路为止。

    LR(0)分析表的构建

    • 移进项目:在ACTION表填入Sj(j为下一状态)
    • 待约项目:在GOTO表中填入下一状态
    • 归约项目:在ACTION表整行填入rj(j为规则编号)
    • 接受项目S′∷=S·,在#位置填入acc

         

    根据分析表分析过程

    1. E∷=E+T
    2. E∷=T
    3. T∷=T*F�
    4. T∷=F
    5. F∷=(E)
    6. F∷=i

     

    • 移进项目Sj:将j压入状态栈,并且将输入串首字符压入符号栈
    • 归约项目rj
      1. 根据j号规则替换符号栈的内容,然后根据j号规则右部有几个字符,则删去状态栈几个状态,
      2. 然后剩下的状态在查找此时符号栈对于的GOTO表,将查找的状态写入状态栈
    • 接受项目acc:当符号栈只剩下开始符号,输入串没有字符,此时分析动作为acc,则表示分析成功。

    LR(1)语法分析

    只有以下两个部分与LR(0)不同:

    1. 在闭包扩展时,需要增加“,超前搜索符”,超前搜索符求解如下:
      • 对于项目S′∷=·S,#,超前搜索符一定是#
      • 扩展的S∷=·a,#中的超前搜索符#,是求解S后面的所有(包括超前搜索符)的FIRST
      • 如果求解的FIRST集的非终结符号有多个,则超前搜索符也填写多个
    2. 归约项目填表时,只对ACTION表中,超前搜索符所在的列填写rj

     

    越努力越幸运!
  • 相关阅读:
    微服务实战SpringCloud之Spring Cloud Feign替代HTTP Client
    JS如何去掉一个数组的重复元素 (数组去重)
    原生JS写了一个小demo,根据输入的数字生成不同背景颜色的小方块儿~
    请教前辈:关于JS的一个奇怪的错误,不知是解析顺序造成的,还是什么原因。。
    JS中的offsetWidth、offsetHeight、clientWidth、clientHeight等等的详细介绍
    记录来到博客园的第一天~
    凡事预则立
    软件产品案例分析(福大公众号)
    组员交换
    事后诸葛亮
  • 原文地址:https://www.cnblogs.com/Littlejiajia/p/13530724.html
Copyright © 2020-2023  润新知