对于给定的上下文无关语法:
S -> G $
G -> PG | P
P -> id : R
R -> id R | epsilon
如何重写语法以使其为LR(1)?
当解析输入“id:.id”时,当前语法有移位/减少冲突,其中“。”是解析器的输入指针
该语法产生满足正则表达式的语言(id:(id)*)+
答案 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)
由于新语法中的作品与旧语法中的作品有明显的同态,我们可以直接创建原始的解析树,虽然我们需要用语义值来玩一些技巧才能正确地附加它们到解析树。