以前学习能力还行的时候看不进去这本书,现在脑子转不过来了估计更是学不会了,虽然不知道我了解编译原理有什么作用,姑且当作一个消遣吧。
文章并不是为了完整地写读书笔记,零散地记录一些我不理解的知识,以及看起来比较重要的知识,标题里方括号对应的就是书中的章节,方便我回顾的时候对照看书。
引论部分 [§1]
编译器的结构 [§1.2]
- 分析 (analysis) 部分,即前端。
- 综合 (synthesis) 部分,后端。
仅看第一章还无法理解前后端分别做了什么,之后回顾的时候再补充。
环境与状态 [§1.6.2]
- 环境 (environment) 是从名字到储存位置的映射,或称为从名字到变量 (左值) 的映射;
- 状态 (state) 是从内存位置到值的映射,或称为把左值映射为右值。
虽然暂时没看懂这两个定义,但是提到了左值和右值,可能是需要注意的地方。
上下文无关文法、BNF (Backus-Naur 范式) [§2.2]
定义相关 [§2.2.1]
上下文无关文法组成部分:
- 终结符号的集合,或“词法单元”
- 非终结符号的集合,或“语法变量”,每个非终结符号表示一个终结符号串的集合
- 产生式的集合,包含一个产生式头(为非终结符号),一个箭头,和一个产生式体(由终结符号及非终结符号组成的序列)
- 指定一个非终结符号为开始符号
之前也看见过一些类似的文法,比如 toml 的定义 这种。大致能看懂这是在定义一些东西,不过不明白这个要怎么变成编译器的一部分。
另外,这里的“终结”不是指目标语言中的语句的终结,而是说这个定义就是它本身了,不再由其他东西产生,比如书里的例2.1
:
list -> list + digit
list -> list - digit
list -> digit
digit -> [0-9] # 这里我直接用了正则来表示数字,我自认为意思是表达到了。
这个文法的终结符号就包括 +
, -
, 0
, 1
, 2
, 3
, 4
, 5
, 6
, 7
, 8
, 9
;而 list
和 digit
是非终结符号。因为它们可以由其他符号产生。
语法分析树 [§2.2.3]
语法分析树 (parse tree) 的性质:
- 根节点的标号为文法的开始符号;
- 每个叶子节点的标号为终结符号(或 ε);
- 内部节点的标号为非终结符号;
- 如果非终结符号
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]
- 在非终结符号
A
的节点上,选择一个A
的产生式,并为这个产生式中的每个符号构造子节点; - 寻找下一个节点来构造子树。
当前被扫描的终结符号通常称为向前看 (lookahead) 符号。具体操作可以看书上的例子,比较通俗易懂。
预测分析法 [§2.4.2]
预测分析法是递归下降分析方法 (recursive-descent parsing) 的一种,Rust 的编译器就是用的递归下降分析法,书上的例子也大致描述了它是如何运作的。