yacc 可以解析的语言有class 种?

What is the class of languages that can be parsed with yacc?

我最近了解到C does not have a context-free grammar. I also recently learned that gcc used to use yacc to parse C. The manual for the the yacc utility states "The class of specifications accepted [by yacc] is a very general one: LALR(1) grammars with disambiguating rules", while Wikipedia states LALR 文法是确定性上下文无关文法的一个子集,它是上下文无关文法的一个子集。如果 C 甚至不是上下文无关的(更不用说确定性上下文无关语言),而 yacc 可以解析 C,那么 yacc 可以解析 class 种语言,如果不是上下文无关语言的子集LALR(1) 文法?

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

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

最后,没有什么可以阻止 yacc-generated 解析器最初接受预期语言的超集,然后分析 context-free 解析树并拒绝基于任意计算的某些构造,例如坚持认为变量在使用前声明(context-sensitive 计算)。

简而言之,real-world 解析器是实用编写的程序,而不是理论学术练习。 bison/yacc 解析的语言一般是 "mostly" LALR(1),它们的词法分析一般是 "mostly" 正则的,但是当计算机程序充分发挥其超越这些的能力时,不要感到惊讶限制。

这就是让编程如此有趣的原因 activity。

None 这使得学术理论的用处不大。 Bison/yacc 和其他解析器生成器在构建解析器时承担了很多繁重的工作,因为它们可以处理 "most of" 分析。一种语言越接近可分析的 context-free 模型,就越容易生成 ("most of") 其他有用的工具:linters、语法高亮器、重新格式化器、索引器、静态分析器、文档提取器等。等等。更不用说作为语言本身语法的文档了。

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

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

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

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

但是这种歧义不一定会出现在解析器中,因为词法分析器可以窥视范围,并根据 Atypedef 名称还是其他名称对 A 进行不同的分类否则,然后这些不同分类的标识符可以通过单独的语法规则来定位。这就像拥有一个用语义信息标记标记的神奇神谕,因此可以应用 context-free 技术。

另一个问题,首先,在 C 中,它有一个预处理器。 C 的语法是分开指定的:有一个预处理器语法,还有一个用于预处理令牌流的语法。 C 不可能有一个 context-free 语法来捕获其短语结构的细微差别,因为预处理可以重新定义语法,并且可以在任何地方调用宏,但注释和字符串文字除外。