在 Kernighan 和 Ritchie 所著的《C 编程语言》第二版的附录 A 中,提到了“产生式”这个词:
本手册描述了 1988 年 10 月 31 日提交给 ANSI 的草案所指定的 C 语言,以供批准为“美国信息系统标准 - 编程语言 C,X3.159-1989”。本手册是对拟议草案的解释。标准,而不是标准本身,尽管我们已尽力使其成为该语言的可靠指南。在很大程度上,本文档遵循该标准的总体轮廓,而该标准又遵循本书第一版的轮廓,尽管组织在细节上有所不同。除了重命名一些产生式以及没有形式化词汇标记或预处理器的定义之外,此处给出的语言本身的语法与标准的语法等效。
但我似乎无法弄清楚它的实际含义。我的猜测是它指的是语法部分中键的值:
翻译单元:外部声明 翻译单元外部声明
A 13 节中的以下内容应该暗示了作者的意思,但我自己似乎无法弄清楚,因为我错过了一些基本术语:
该语法具有未定义的终结符整数常量、字符常量、浮点常量、标识符、字符串和枚举常量;打字机风格的单词和符号是 按字面给出的终端。该语法可以机械地转换为自动解析器生成器可接受的输入。除了添加用于指示产生式中的替代项的任何语法标记之外,还需要扩展“其中一个”结构,并且(取决于解析器生成器的规则)使用opt 符号复制每个产生式,一旦使用符号和曾经没有。通过进一步的更改,即删除产生式 typedef-name: 标识符并使 typedef-name 成为终结符,该语法可以被 YACC 解析器生成器接受。它只有一个冲突,是由 if-else 歧义产生的。
我也不知道那些大胆的词/句子是什么意思。有人能给我一个见解吗?
在计算机科学中,形式语法是使用产生式规则来描述的。例如,以下形式的规则:
\n\n\n磷 \xe2\x86\x92 xyz
\n
表示符号P可以用符号 xyz 代替,并且形式的规则
\n\n\nQ \xe2\x86\x92 一个P | bP
\n
表示符号Q可以被符号a和符号P或者符号b和符号P替代替代。
\n形式语法指定一个起始符号,例如Q,并说明哪些符号是非终结符号(不出现在最终字符串中的占位符),哪些是终结符号(可能出现在最终字符串中)。如果Q是具有上述两个规则的语法的起始符号,则这些规则描述包含两个字符串 axyz 和 bxyz 的语法,因为这是可以使用这些规则组成的唯一两个字符串。语法可以产生的字符串集合称为它的语言。
\n\xce\xbb 常用来表示空字符串,即没有符号的字符串。
\n该文法包含非终结符号S、终结符号 a 和 b 以及起始符号S:
\n\n\nS \xe2\x86\x92 一个S bb | \xce\xbb
\n
可以通过将S替换为空字符串来生成空字符串,或者可以通过将S替换为S bb 然后用空字符串替换新的S来生成 abb ,或者可以通过将S替换为S bb 然后替换来生成 aabbbb新的S与S bb,产生 aa S bbbb,然后替换S用空字符串我们可以看到这个语法的语言是包含一定数量的 a 字符(可能为零)的所有字符串的集合,后跟两倍数量的 b 字符。
\nC 标准使用正式语法(带有一些英语限定和修改)来定义 C 语言。例如,它包含此产生式(其中使用 \xe2\x80\x9c:\xe2\x80\x9d 而不是我上面使用的 \xe2\x80\x9c\xe2\x86\x92\xe2\x80\x9d 并使用单独的行而不是 \xe2\x80\x9c|\xe2\x80\x9d 来指示选择):
\n\n\n语句:
\n
\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0标记语句
\n\xc2\xa0\xc2\xa0\ xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0复合语句
\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2 \xa0\xc2\xa0\xc2\xa0表达式语句
\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 选择语句
\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0迭代语句
\n\xc2\xa0\xc2\xa0\xc2\ xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0跳转语句
关于您用粗体标记的其他术语:
\n\n\n未定义的终结符整数常量,\xe2\x80\xa6
\n
《C 编程语言》中给出的 C 语法似乎是部分语法,留下整数常量保留为未定义符号,因此充当终结符号。在官方ANSI C 1990标准中,它是官方ANSI C 1990标准中定义的非终结符。
\n\n\n\xe2\x80\xa6 打字机风格的单词和符号是字面给出的终端。
\n
这在原文中更清楚,其中使用的字体表明 \xe2\x80\x9ctypewriter\xe2\x80\x9d 样式是固定宽度字体:
\n\n\n\xe2\x80\xa6 的
\ntypewriter样式单词和符号是字面给出的终结符。
这连同其前面的文本意味着,在语法中,斜体字(如声明)是语法的非终结符,\xe2\x80\x9c 通过语法的产生而变成其他东西\xe2\x80\x9d,而 \xe2\x80\x9ctypewriter\xe2\x80\x9d 字体中的单词,例如typedef, 是终端符号,它们是其名称中文字字符的符号;typedef语法中的 表示源代码中的字符 t、y、p、e、d、e 和 f。
\n\n\xe2\x80\xa6 使用 opt 符号复制每个产生式,一次带有该符号,一次不带\xe2\x80\xa6
\n
标准使用下标 \xe2\x80\x9copt\xe2\x80\x9d,如下所示:
\n\n\nP : Q R选项
\n
意思是R是可选的。从形式上来说,这实际上是两条规则:
\n\n\nP \xe2\x86\x92 Q R
\n
\n P \xe2\x86\x92 Q
意味着存在一个用Q R替换P 的规则和一个用Q替换P的规则,并且可以使用其中任何一个。因此,R 是可选的。使用 \xe2\x80\x9copt\xe2\x80\x9d 下标只是编写规则的不同方式。
\n\n\n\xe2\x80\xa6 这个语法是 YACC 解析器生成器可以接受的。它只有一个冲突,是由 if-else 歧义产生的。
\n
在计算机科学理论中,解析器是检查字符串是否属于某种语言的软件。(在实践中,它经常同时做其他有用的事情,例如通过将字符串的一部分解释为数字,一部分解释为变量等,将 \xe2\x80\x9cmeaning\xe2\x80\x9d 分配给字符串。) YACC是读取语法规范并为语法描述的语言的解析器生成源代码的软件。
\nYACC 生成的解析器类型需要决定在读取每个标记时将应用哪种产生式。当语法不足以确定应用哪个产生式时,就会发生冲突。在 C 形式语法中,if (x) if (y) S1 else S2可以通过两种方式产生,一种else S2与第一种关联if,另一种else S2与第二种关联if。这必须通过向语法添加信息来解决;YACC 被告知将与当前没有 的else S2最新版本关联起来。ifelse