如何重写无上下文语法以使其为LR(1)?

时间:2014-11-06 18:28:10

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

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

(id:id*)+

为:

id(:id+)*:id*

引起语法:

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

是LALR(1)。

实际上,我们刚刚将所有产品的一个标记向右移动,并且有一个通用算法可用于从任何LR(1)语法创建LR(k+1)语法{1}}。 (我使用的这个算法的版本来自S. Sippu& E. Soisalon-Soininen的解析理论,第二卷,第6.7节。)

新语法的非终端将具有k≥1形式,其中(x, V, y)是原始语法(终端或非终端)和V的符号,并且x是最大长度y的终端序列,以便:

k

(如果输入的结尾包含在跟随集中,则y ∈ FOLLOWk(V) x ∈ FIRSTk(Vy) y的长度可能小于x。有些人通过添加{{1}来避免此问题结束符号,但我认为这个版本同样简单。)

非终端k将生成k - 从原始语法中派生自(x, V, y)的字符串的派生词。非正式地,整个语法向右移动x个标记;每个非终端匹配缺少第一个Vy令牌的字符串,但使用以下k令牌进行扩充。

制作是从原始制作中机械生成的。首先,我们添加一个新的开始符号k,其中包含产品:

k
每个S'

。然后,为每个生产

S' → x (x, S, ε)

我们生成一组制作:

x ∈ FIRSTk(S)

并为每个终端T → V0 V1 … Vm生成一组制作

(x0,T,xm+1) → (x0,V0,x1) (x1,V1,x2) … (xm,Vm,xm+1)

由于新语法中的作品与旧语法中的作品有明显的同态,我们可以直接创建原始的解析树,虽然我们需要用语义值来玩一些技巧才能正确地附加它们到解析树。