【问题标题】:How do I rewrite a context free grammar so that it is LR(1)?如何重写上下文无关语法使其成为 LR(1)?
【发布时间】:2014-11-06 18:28:10
【问题描述】:

对于给定的上下文无关语法:

S -> G $
G -> PG | P
P -> id : R
R -> id R | epsilon

如何重写语法使其成为 LR(1)?
当前语法在解析输入“id : .id”时存在移位/减少冲突,其中“。”是解析器的输入指针。
该文法产生满足正则表达式 (id:(id)*)+

的语言

【问题讨论】:

    标签: parsing context-free-grammar shift-reduce-conflict kleene-star lr1


    【解决方案1】:

    为同一种语言生成 LR(1) 语法很容易。诀窍是找到一个具有相似解析树的解析树,或者至少可以轻松地从中恢复原始解析树。

    这是一个手动生成的语法,它是从一般算法略微简化的。实际上,我们重写了正则表达式:

    (id:id<sup>*</sup>)<sup>+</sup>

    到:

    id(:id<sup>+</sup>)<sup>*</sup>:id<sup>*</sup>

    引出语法:

    S  → id G $ 
    G  → P G | P'
    P' → : R'
    P  → : R
    R' → ε | id R'
    R  → ε | id R
    

    这是 LALR(1)。

    实际上,我们只是将所有产生式向右移动了一个标记,并且有一个通用算法可用于从LR(k+1) 语法为任何k≥1 创建LR(1) 语法。 (我使用的这个算法的版本来自 S. Sippu 和 E. Soisalon-Soininen 的 Parsing Theory,第二卷,第 6.7 节。)

    新语法的非终结符将具有(x, V, y) 的形式,其中V 是原始语法的符号(终结符或非终结符),xy 是终结符序列最大长度k 使得:

    y ∈ FOLLOWk(V)
    x ∈ FIRSTk(Vy)
    

    (如果输入的结尾包含在后续集中,y 和因此x 的长度可能小于k。有些人通过添加k 结束符号来避免这个问题,但我认为这个版本同样简单。)

    非终结符(x, V, y) 将生成从原始语法中派生自Vy 的字符串的x-导数。非正式地,整个语法向右移动k标记;每个非终结符都匹配一个缺少第一个 k 标记但增加了以下 k 标记的字符串。

    这些作品是从原始作品中机械生成的。首先,我们添加一个新的开始符号,S' 和产生式:

    S' → x (x, S, ε)
    

    对于每个x ∈ FIRST<sub>k</sub>(S)。然后,对于每个生产

    T → V<sub>0</sub> V<sub>1</sub> … V<sub>m</sub>

    我们生成一组产品:

    (x<sub>0</sub>,T,x<sub>m+1</sub>) → (x<sub>0</sub>,V<sub>0</sub>,x<sub>1</sub>) (x<sub>1</sub>,V<sub>1</sub>,x<sub>2</sub>) … (x<sub>m</sub>,V<sub>m</sub>,x<sub>m+1</sub>)

    对于每个终端A,我们生成一组产品

    (Ax,A,xB) → B    if |x| = k
    (Ax,A,x) → ε     if |x| ≤ k
    

    由于新语法中的产生式与旧语法中的产生式之间存在明显的同态性,因此我们可以直接创建原始解析树,尽管我们需要对语义值进行一些技巧才能正确附加它们到解析树。

    【讨论】:

      猜你喜欢
      • 2021-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-04
      • 2022-01-09
      • 1970-01-01
      • 2014-04-26
      • 1970-01-01
      相关资源
      最近更新 更多