【问题标题】:What is the class of languages that can be parsed with yacc?可以用 yacc 解析的语言类别是什么?
【发布时间】:2019-10-27 13:06:27
【问题描述】:

我最近了解到C does not have a context-free grammar。我最近还了解到gcc used to use yacc to parse C。 yacc 实用程序的手册指出 "The class of specifications accepted [by yacc] is a very general one: LALR(1) grammars with disambiguating rules",而 Wikipedia states 指出 LALR 语法是确定性上下文无关语法的子集,它是上下文无关语法的子集。如果 C 甚至不是上下文无关的(更不用说确定性的上下文无关语言),但 yacc 可以解析 C,那么 yacc 可以解析哪类语言,如果不是具有 LALR(1) 的上下文无关语言的子集语法?

【问题讨论】:

  • C 通常用 Yacc 编译,在词法分析器和解析器之间有上下文感知反馈。这样才能正确处理typedef 名称之类的内容。
  • 仅供参考,您链接到的第一个问题是关于 C++,而不是 C,尽管 C 也是如此。
  • 正如@JonathanLeffler 所说,它使用解析器和词法分析器之间的反馈。我的猜测:定义名称后,它会被添加到词法分析器使用的标记表中,并且该名称的未来用途会得到正确分类。这使得它与上下文相关,即使语法不是。
  • 我没有说它来自手册页,我说它来自手册,并且我给出的引述字面上链接到 yacc 手册,其中说 yacc 接受 LALR(1) 语法作为输入。维基百科页面说 LALR 语法是上下文无关语法的子集。因此,yacc 接受上下文无关文法子集的规范作为输入。
  • @user207421 具有消除歧义规则的 LALR(1) 语法仍然不比上下文无关语法更强大。消歧规则是关于如何处理模棱两可的 CFG,它们不允许 YACC 突然接受上下文相关的语法。正如其他人所说,YACC 可以通过使解析器将信息反馈给词法分析器来解析 C - 这与消除歧义规则无关。

标签: parsing grammar yacc formal-languages


【解决方案1】:

Yacc 生成图灵完备的计算机程序。 yacc 框架使用 LALR(1) 框架来触发动作,但动作是任意代码。

此外,yacc 的输入是令牌流,而不是直接输入。令牌流是由另一个用图灵完备语言编写的计算机程序生成的,该程序还可以以不限于无上下文转码的方式操纵其输入。

最后,没有什么能阻止 yacc 生成的解析器最初接受预期语言的超集,然后分析上下文无关的解析树并拒绝基于任意计算的某些构造,例如坚持在使用前声明变量(上下文相关的计算)。

简而言之,现实世界的解析器是实用编写的程序,而不是理论上的学术练习。由 bison/yacc 解析的语言通常“大部分”是 LALR(1),它们的词法分析通常“大部分”是规则的,但当计算机程序利用其全部能力超越这些限制时不要感到惊讶。

这就是让编程成为有趣的活动的原因。

这些都不会降低学术理论的用处。 Bison/yacc 和其他解析器生成器消除了构建解析器的大量繁重工作,因为它们可以处理“大部分”分析。并且一种语言越接近于可分析的上下文无关模型,就越容易生成(“大部分”)其他有用的工具:linter、语法高亮、重新格式化、索引器、静态分析器、文档提取器等。更不用说作为语言本身语法的文档了。

【讨论】:

  • 我猜如果词法分析器是图灵完备的,那么它实际上可以解析整个事物,然后发出完整解析树的序列化表示,这意味着理论上它可以解析到自然语言。这很好地回答了我的问题。谢谢!
  • @user:C 与上下文无关性最明显的偏差是预处理器,不管任何人怎么说,它都是语言的基本部分。 C 宏还不是图灵完备的,但是预处理的结果并不对应于任何干净的理论模型。然而,它就在那里。 Yacc 很高兴地不知道在它交给令牌之前进行了哪些转换,以及在确定每次减少之后会发生什么。所以,是的,天空是极限。但有些语言比其他语言更适合 yacc。
【解决方案2】:

C 没有上下文无关文法,只是因为标识符标记(其词法类别)的语义分类有时需要了解它是如何声明的。 C 是为一次性编译而设计的,因此在解析的任何时候,与解析相关的所有内容都可以从先前的声明中得知。范围内的声明可用于将词法类别分配给标记。

例如,如果解析器在语句块的中间面对(A)(B),这可能是:

  • 表达式 (B) 被强制转换为类型 A

  • 参数列表(B)被应用于函数表达式(A)

但是这种歧义不必在解析器中出现,因为词法分析器可以窥视范围,并根据 Atypedef 名称还是其他名称对它们进行不同的分类,这些不同的分类然后可以通过单独的语法规则来定位标识符。这就像一个神奇的预言机,用语义信息标记令牌,因此可以应用上下文无关技术。

首先,C 语言的另一个问题是它有一个预处理器。 C 的语法是在单独的部分中指定的:有一个预处理器语法,还有一个用于预处理标记流的语法。对于 C 来说,不可能有一个上下文无关的语法来捕捉其短语结构的细微差别,因为预处理可以重新定义语法,并且可以在任何地方调用宏,除了 cmets 和字符串文字。

【讨论】:

    猜你喜欢
    • 2020-03-24
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    • 2014-06-18
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多