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)
。
但是这种歧义不一定会出现在解析器中,因为词法分析器可以窥视范围,并根据 A
是 typedef
名称还是其他名称对 A
进行不同的分类否则,然后这些不同分类的标识符可以通过单独的语法规则来定位。这就像拥有一个用语义信息标记标记的神奇神谕,因此可以应用 context-free 技术。
另一个问题,首先,在 C 中,它有一个预处理器。 C 的语法是分开指定的:有一个预处理器语法,还有一个用于预处理令牌流的语法。 C 不可能有一个 context-free 语法来捕获其短语结构的细微差别,因为预处理可以重新定义语法,并且可以在任何地方调用宏,但注释和字符串文字除外。
我最近了解到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)
。
但是这种歧义不一定会出现在解析器中,因为词法分析器可以窥视范围,并根据 A
是 typedef
名称还是其他名称对 A
进行不同的分类否则,然后这些不同分类的标识符可以通过单独的语法规则来定位。这就像拥有一个用语义信息标记标记的神奇神谕,因此可以应用 context-free 技术。
另一个问题,首先,在 C 中,它有一个预处理器。 C 的语法是分开指定的:有一个预处理器语法,还有一个用于预处理令牌流的语法。 C 不可能有一个 context-free 语法来捕获其短语结构的细微差别,因为预处理可以重新定义语法,并且可以在任何地方调用宏,但注释和字符串文字除外。