这些语法和最小解析器怎么识别它?

16

我正在尝试学习如何制作编译器。为此,我阅读了很多关于上下文无关语言的资料。但是有一些问题我自己还无法理解。

由于这是我的第一个编译器,我不知道一些惯例。我提出的问题是为了构建一个解析器生成器,而不是编译器或词法分析器。有些问题可能很明显。

我阅读过的内容包括:自底向上解析自顶向下解析形式化语法。图像来自于:杂项解析。所有资料均来自斯坦福大学CS143班级。

Parsers / Grammars Hierarchy

以下是要点:

0)模棱两可的和左递归/右递归的方式如何影响算法选择?是否还有其他描述语法的方式?

1)多义语法是指具有多个解析树的语法。但是选择最左派导或最右派导是否应该导致解析树的唯一性?

[编辑:在这里回答了]。

2.1)但是,语法的歧义是否与k有关?我的意思是,给出一个LR(2)语法,对于LR(1)解析器来说,它是否是不明确的而对于LR(2)解析器来说不是?

[编辑:不是,LR(2)语法意味着解析器需要向前看两个标记才能选择正确的规则。另一方面,多义语法是指可能导致多个解析树的语法。]

2.2)那么,只要您可以想象到它,LR(*)解析器就没有任何歧义的语法,因此可以解析整个上下文无关语言集吗?

[编辑:由Ira Baxter回答,LR(*)比GLR弱,因为它不能处理多个解析树。]

3)根据前面的答案,下面的问题可能是自相矛盾的。考虑LR解析,模棱两可的语法是否会触发移位-归约冲突?一个不明确的语法是否也会触发这种冲突?同样,减少-减少冲突呢?

[编辑:这是它,模糊语法会导致移进规约和规约规约冲突。反证法表明,如果没有冲突,则语法是唯一的。]

4)相比LL(k),LR(k)解析器具有解析左递归语法的能力,这是它们之间的唯一区别吗?

[编辑:是的。]

5)给出G1:

G1 :
S -> S + S
S -> S - S
S -> a

5.1) G1语法同时具有左递归、右递归和二义性,对吗?它是LR(2)文法吗?我们可以使它无歧义:

G2 :
S -> S + a
S -> S - a
S -> a

5.2) G2是否仍然含糊不清?G2的解析器是否需要两个lookahead?通过因式分解,我们有:

G3 :
S -> S V
V -> + a
V -> - a
S -> a

5.3) 现在,G3的解析器是否只需要一个前瞻?进行这些转换的对应部分是什么?LR(1)是所需的最小解析器吗?

5.4) G1具有左递归性质,为了使用LL解析器解析它,需要将其转化为右递归语法:

G4 :
S -> a + S
S -> a - S
S -> a

那么。
G5 :
S -> a V
V -> - V
V -> + V
V -> a

5.5) G4需要至少LL(2)分析器吗?仅G5可由LL(1)分析器分析,G1-G5定义了相同的语言,该语言为(a(+/- a)^n)。是真的吗?

5.6) 对于每个文法G1到G5,它所属的最小集合是什么?

6) 最后,由于许多不同的文法可以定义相同的语言,如何选择文法和相关的解析器?结果产生的解析树重要吗?解析树的影响是什么?

我提出了很多问题,并不指望完整的答案,但任何帮助都将非常感激。

感谢阅读!

1个回答

11

许多语法可能定义同一种语言,那么怎么选择呢?

通常情况下,您可以选择符合以下标准的语法:

  • 概念上尽可能简单(暗示:比其他语法更小)
  • 尽可能跟随语言参考手册中的术语
  • 弯曲度最小以满足解析器生成器的约束条件

最后一个标准可能会破坏您的概念简单性,而您各种解析器样式图表显示了根据生成器选择面临的不同问题数量。这还加剧了在实际选择语法之前做出选择的事实。

减少语法弯曲的一种方法是选择处理完全无上下文语法的解析器生成器。 GLR解析 具有这个非常重要的优势。我用它进行了15年,并使用它完成了几十种真实语言。


谢谢。使用GLR,它可以解析任何CFG,语法尽可能简单,给出类似的简单解析树。然后出现一个问题:GLR = LR(*)吗?此外,使用GLR解析器,您不需要减少弯曲量的语法,对吧? - dader
1
从技术上讲,是的。有一些CFG会导致GLR呈指数行为,因此您仍然需要进行一些调整。通常情况下,这种行为非常罕见。当您构建解析器时,您会发现有时您想添加超出CFG能力范围的语义约束(例如通过匹配行号将多个Fortran DO循环头与同一个CONTINUE语句相匹配),因此您仍然需要对语法进行一些调整。但最终,使用GLR时您需要弯曲语法的程度要少得多。是的,GLR具有“无限前瞻”,它可以执行LR(*)所能执行的任何操作。 - Ira Baxter
1
LR(*)不能处理有歧义的语法。许多真实的语言(包括C++,请参见https://dev59.com/6nVC5IYBdhLWcg3wnCSA#1004737)如果只坚持语法,就会产生歧义。对于这样的语言,解析并收集歧义通常更容易,在解析阶段完成后消除这些歧义。否则,您将得到类似于经典C/C++编译器黑客的东西,其中符号表(上下文敏感)数据被馈入词法分析器/解析器,从而造成混乱。 - Ira Baxter
1
@dader51:触发它的语法规则是:“stmt = exp;”(对于变量xy,x乘以变量y),以及“stmt = declaration;”(对于x作为类型,x作为指向x类型的指针,以及y作为声明为x*-type的变量)。LR解析器问题:exp的语法规则和declaration的语法规则都会声称它们看到了有效的令牌字符串“x * y;”。此时,解析器存在一个归约-归约冲突。这意味着LR解析器无法决定要通过哪个产生式进行归约,这就是当语法中存在歧义时发生的情况。 - Ira Baxter
2
对于可能会来到这里的任何人,我只是想提醒一下:BRNGLR算法是Elizabeth Scott编写的GLR算法的一个变体,它修复了指数行为,对于任何上下文无关文法都是最坏情况下的立方级别。 - paulotorrens
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接