Parsing LR(1)项目DFA-计算外观

Parsing LR(1)项目DFA-计算外观,parsing,context-free-grammar,lookahead,dfa,lr,Parsing,Context Free Grammar,Lookahead,Dfa,Lr,我很难理解如何计算LR(1)-项的lookahead 假设我有这样的语法: S -> AB A -> aAb | a B -> d LR(1)-项是具有前瞻性的LR(0)项。因此,我们将获得状态0的以下LR(0)-项: S -> .AB , {lookahead} A -> .aAb, {lookahead} A -> .a, {lookahead} 国家:1 A -> a.Ab, {lookahead} A -> a. ,{lo

我很难理解如何计算LR(1)-项的lookahead

假设我有这样的语法:

S -> AB
A -> aAb | a
B -> d
LR(1)-项是具有前瞻性的LR(0)项。因此,我们将获得状态0的以下LR(0)-项:

S -> .AB , {lookahead} 
A -> .aAb,  {lookahead} 
A -> .a,  {lookahead}
国家:1

A ->  a.Ab, {lookahead} 
A ->  a. ,{lookahead} 
A -> .aAb ,{lookahead} 
A ->.a ,{lookahead}
有人能解释一下如何计算lookaheads吗?一般做法是什么


提前感谢

LR(1)解析器中使用的lookahead计算如下。首先,开始状态有一个表单项

S -> .w  ($)
对于每个产品S->w,其中S是开始符号。在这里,$标记表示输入的结束

接下来,对于包含形式为A->x.By(t)的项的任何状态,其中x是终端和非终端的任意字符串,而B是非终端,您可以为每个产品B->w和集合中的每个终端(yt)添加形式为B->.w(s)的项。(这里,首先是指,在讨论LL解析器时通常会介绍它们。如果您以前没有见过它们,我将花几分钟时间查看这些课堂讲稿)

让我们试试你的语法。我们首先创建一个包含

S -> .AB ($)
接下来,使用我们的第二条规则,对于A的每一个产品,我们添加一个与该产品对应的新项目,并且每个终端的lookaheads位于第一位(B$)。因为B总是产生字符串d,FIRST(B$)=d,所以我们介绍的所有产生式都具有前瞻性d。这给

S -> .AB ($)
A -> .aAb (d)
A -> .a (d)
A -> a.Ab (d)
A -> a. (d)
A -> .aAb (b)
A -> .a (b)
现在,让我们构建对应于在初始状态中看到“a”的状态。我们首先将圆点移动到每个生产的一个步骤上,该步骤以:

A -> a.Ab (d)
A -> a. (d)
现在,由于第一个项在非终结符之前有一个点,我们使用我们的规则为a的每个结果添加一个项,使这些项先行(bd)=b。这给

S -> .AB ($)
A -> .aAb (d)
A -> .a (d)
A -> a.Ab (d)
A -> a. (d)
A -> .aAb (b)
A -> .a (b)
继续此过程最终将为此LR(1)解析器构造所有LR(1)状态。如下所示:

[0]
S -> .AB  ($)
A -> .aAb (d)
A -> .a   (d)

[1]
A -> a.Ab (d)
A -> a.   (d)
A -> .aAb (b)
A -> .a   (b)

[2]
A -> a.Ab (b)
A -> a.   (b)
A -> .aAb (b)
A -> .a   (b)

[3]
A -> aA.b (d)

[4]
A -> aAb. (d)

[5]
S -> A.B  ($)
B -> .d   ($)

[6]
B -> d.   ($)

[7]
S -> AB.  ($)

[8]
A -> aA.b (b)

[9]
A -> aAb. (b)
如果有帮助的话,我去年夏天教了一门编译器课程,并且有了。关于自底向上解析的幻灯片应该涵盖LR解析和解析表构造的所有细节,我希望您会发现它们很有用

希望这有帮助

您构建的LR(1)项集应该还有两个项

I8 A-->来自I2的aA.b、b

I9 A-->aAb,b从I8开始,这里是语法的LR(1)自动机,如下所示 我认为更好的理解是尝试绘制自动机,流程将使lookaheads的概念更清晰


我还得到了11个州,而不是8个州:

State 0
        S: .A B ["$"]
        A: .a A b ["d"]
        A: .a ["d"]
    Transitions
        S -> 1
        A -> 2
        a -> 5
    Reductions
        none
State 1
        S_Prime: S .$ ["$"]
    Transitions
        none
    Reductions
        none
State 2
        S: A .B ["$"]
        B: .d ["$"]
    Transitions
        B -> 3
        d -> 4
    Reductions
        none
State 3
        S: A B .["$"]
    Transitions
        none
    Reductions
        $ => S: A B .
State 4
        B: d .["$"]
    Transitions
        none
    Reductions
        $ => B: d .
State 5
        A: a .A b ["d"]
        A: .a A b ["b"]
        A: .a ["b"]
        A: a .["d"]
    Transitions
        A -> 6
        a -> 8
    Reductions
        d => A: a .
State 6
        A: a A .b ["d"]
    Transitions
        b -> 7
    Reductions
        none
State 7
        A: a A b .["d"]
    Transitions
        none
    Reductions
        d => A: a A b .
State 8
        A: a .A b ["b"]
        A: .a A b ["b"]
        A: .a ["b"]
        A: a .["b"]
    Transitions
        A -> 9
        a -> 8
    Reductions
        b => A: a .
State 9
        A: a A .b ["b"]
    Transitions
        b -> 10
    Reductions
        none
State 10
        A: a A b .["b"]
    Transitions
        none
    Reductions
        b => A: a A b .

非常感谢。你能解释一下为什么在下面的语法中,$包含在先行集合中,但它不在第一个($A)中吗?s→ •A{$}A→ • AA{$,b}A→ • bc{$,b}@mrjasmin-我需要了解更多的语法,以了解第一个和前瞻集应该是什么;你能多发一些吗?另外,请注意,您不应该在任何地方首先计算($A)。如果您有一个->.AA($),那么结果项的lookahead将是FIRST(A$)中的终端,而不是FIRST($A)。那有用吗?嗨!这个问题来自一次考试,给出的答案是:S->.A{$}A->.AA{}A->.bc{}学生应该找到前瞻集,答案是上面的帖子。我不明白美元是怎么回事lookahead@mrjasmin-最初的$可能来自于S是开始符号的事实,因此它的产品总是在事实之后标记为$。因此,生产A->.AA最初将有$作为前瞻,A->bc也是如此。接下来,由于A->.AA($)是一个项目,您需要为A的每一个产品添加新项目,首先是lookaheads(A$)。由于A->bc是A的产物,所以第一个(A$)的唯一元素是b。因此,您需要将A->.AA(b)和A->.bc(b)添加到项目集。将它们与A->.AA($)和A->.bc($)合并得到A->.AA($,b)和A->.bc($,b)。这有意义吗?为什么生产A->.AA最初会有美元作为前瞻?A->aAb | A最初不应该也有美元吗?谢谢