Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

语言与文法

复习

  • 从字符串变为程序:编译器分阶段处理源码
  • 字符串:字符的序列
  • 集合:一组对象的整体

TL;DR

  • 语言是合法字符串的集合
  • 文法用规则描述哪些字符串属于语言
  • 推导是从起始符号一步步生成句子的过程
  • 编译器需要一种能描述程序嵌套结构的文法

正文

  编译器要“读懂”源代码。可我们先得回答一个更基础的问题:怎样严谨地描述一门语言,说明哪些字符串是合法的?

语言就是一个集合

  从数学上说,一门语言不过是一个字符串的集合:所有合法的句子,构成这个集合;不合法的,就不在里面。

  比如“所有由 0 和 1 组成、且不包含连续两个 0 的字符串”,就是一个语言。

  可问题是:语言可能包含无穷多个字符串,你没法把它们一个个列出来。于是需要一个更紧凑的描述方式——文法

文法:用规则生成语言

  文法由几部分组成:

  • 终结符:最终出现在句子里的基本符号(比如 +、数字、字母)
  • 非终结符:代表某个语法成分的占位符(比如“表达式”)
  • 产生式:形如“某个非终结符可以改写成什么”的规则
  • 起始符号:从哪个非终结符开始生成

  从起始符号出发,不断把非终结符按产生式改写成别的东西,直到得到一个只含终结符的字符串——这个过程叫推导,得到的字符串就是语言里的一句。

  举个例子,一个描述加减表达式的文法:

表达式 → 数字
表达式 → 表达式 + 数字
表达式 → 表达式 - 数字

  从“表达式”出发反复代入,就能推出 1 + 2 - 3 这样的句子。文法用有限的规则,描述了一个可能无限大的语言。

为什么这样描述有用

  用规则而不是列举,好处是显而易见的:规则短小、有限,却能覆盖无穷多种情况。 而且,规则的结构往往和程序的结构对应。

  编译器要处理的程序语言,含有大量嵌套(括号、语句块、函数……)。要描述这种嵌套,就需要一种特别合适的文法——这将是后面章节的重点。先记一句话:好的文法,能让“解析程序结构”这件事变得有章可循。

  那么,文法描述的是“字符层面的句子”。在用它之前,我们得先把字符切成语法单位——这就是词法分析。

思考题 1

  文法在“描述一门语言”时,扮演什么角色?

思考题 2

  为什么用规则(推导)来描述语言,比直接列举所有合法句子更现实?

小结

知识点

  • 语言是合法字符串的集合
  • 文法由终结符、非终结符、产生式和起始符号组成
  • 推导从起始符号生成合法句子
  • 文法用有限规则描述可能无限的语言

参考资料

  1. Wikipedia(zh):形式文法:用规则描述形式语言的工具
  2. Wikipedia(zh):形式语言:由形式文法定义的字符串集合

思考题答案(仅供参考)

思考题 1

  它提供了一种用有限规则描述语言的机制:通过产生式和推导,规定哪些字符串是合法的。文法既是语言的精确描述,也是编译器后续分析程序结构的依据。

思考题 2

  因为语言通常包含无穷多个合法字符串,无法逐一列举。而文法用有限的规则,就能生成全部合法句子,既简洁又能覆盖无穷情况,还便于机器处理。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪