以前学习能力还行的时候看不进去这本书,现在脑子转不过来了估计更是学不会了,虽然不知道我了解编译原理有什么作用,姑且当作一个消遣吧。

文章并不是为了完整地写读书笔记,零散地记录一些我不理解的知识,以及看起来比较重要的知识,标题里方括号对应的就是书中的章节,方便我回顾的时候对照看书。

引论部分 [§1]

编译器的结构 [§1.2]

环境与状态 [§1.6.2]

  1. 环境 (environment) 是从名字到储存位置的映射,或称为从名字到变量 (左值) 的映射;
  2. 状态 (state) 是从内存位置到值的映射,或称为把左值映射为右值。
    虽然暂时没看懂这两个定义,但是提到了左值和右值,可能是需要注意的地方。

上下文无关文法、BNF (Backus-Naur 范式) [§2.2]

定义相关 [§2.2.1]

上下文无关文法组成部分:

  1. 终结符号的集合,或“词法单元”
  2. 非终结符号的集合,或“语法变量”,每个非终结符号表示一个终结符号串的集合
  3. 产生式的集合,包含一个产生式头(为非终结符号),一个箭头,和一个产生式体(由终结符号及非终结符号组成的序列)
  4. 指定一个非终结符号为开始符号
    之前也看见过一些类似的文法,比如 toml 的定义 这种。大致能看懂这是在定义一些东西,不过不明白这个要怎么变成编译器的一部分。

另外,这里的“终结”不是指目标语言中的语句的终结,而是说这个定义就是它本身了,不再由其他东西产生,比如书里的例2.1:

list -> list + digit
list -> list - digit
list -> digit
digit -> [0-9] # 这里我直接用了正则来表示数字,我自认为意思是表达到了。

这个文法的终结符号就包括 +, -, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;而 listdigit 是非终结符号。因为它们可以由其他符号产生。

语法分析树 [§2.2.3]

语法分析树 (parse tree) 的性质:

  1. 根节点的标号为文法的开始符号;
  2. 每个叶子节点的标号为终结符号(或 ε);
  3. 内部节点的标号为非终结符号;
  4. 如果非终结符号 A 是某内部节点的标号,它的子节点的标号依次为 X₁, X₂, ... Xₙ,则必然存在产生式 A -> X₁X₂...Xₙ

运算优先级 [§2.2.6]

在文法中,运算符按照优先级递增的顺序排列,这里直接给出加减乘除运算符的产生式,如果有更多层优先级,可以类推。

expr -> expr + term | expr - term | term
term -> term * factor | term / factor | factor
factor -> digit | (expr)

语法分析 [§2.4]

自顶向下分析方法 [§2.4.1]

  1. 在非终结符号 A 的节点上,选择一个 A 的产生式,并为这个产生式中的每个符号构造子节点;
  2. 寻找下一个节点来构造子树。

当前被扫描的终结符号通常称为向前看 (lookahead) 符号。具体操作可以看书上的例子,比较通俗易懂。

预测分析法 [§2.4.2]

预测分析法是递归下降分析方法 (recursive-descent parsing) 的一种,Rust 的编译器就是用的递归下降分析法,书上的例子也大致描述了它是如何运作的。