




















Interpreters: on-line (速度慢, 占用内存大)
Compilers: off-line

Compiler Five Phases:
Lexical Analysis: syntactic
recognize words

Parsing: syntactic: syntactic
diagramming sentences

Semantic Analysis: types and scopes
understand meaning (hard), catch inconsistencies
无法做到真正的解析语义, 所以只是寻找程序中自相矛盾的地方, 比如: 变量重复定义, 变量前后类型不同
Optimization
run faster, use less memory, less power, network, database…
Code Generation: translation to another languages, machine code or even high level programming language
编译器的提升:

COOL: Classroom Object Oriented Language
COOL 的语法main 的返回值

继承

递归和递推

init 函数

一些特性 (用 Object 模拟泛型)

这个的环境配置还是很简单的, 官方是提供了一个系统镜像
根据自己电脑版本下载Virtual Box 并安装
下载系统镜像 (这里可能需要一点魔法)
点击镜像中的 .vbox 文件直接运行即可

进入到桌面, 打开终端 (左下第四个图标) 进行测试

写个 hello.cl, coolc 编译出 hello.s, spim 执行 hello.s

测试成功
每个lexeme被分为不同的token classes

词法分析器接收, 生成类似于键值对的 token 二元组 <type - value>, 然后发送给解析器

过程总结:

Fortran 的一个例子 (因为历史原因, Fortran 中的空格不重要):
DO 5 I = 1,25 // 从此句到有标签 5 的句子做循环, I 是变量, 从 1 加到 25
DO 5 I = 1.25 // 声明一个变量 DO5I, 值为 1.25
在词法分析中虽然会扫描到关键字 DO, 但只有扫描到后面的 , 才能确定这是循环的关键字

lookahead: 根据后面的词语来确定当前词语的作用

总而言之, 正则语言是一个强大的工具

将语义和语法分离, 不同语法会有相同语义, 二者之间的映射关系必须是多对一


基本介绍:

DFA 和 NFA:

词法分析器:

转换示例:

一个例子:

方法:

例子:


优化一下 (压缩空间):

NFA 需要对每个状态都进行一次搜索, 所以就很慢:

DFA 和 NFA 的权衡:
| DFA | faster | less compact |
| NFA | slower | concise |
Parsing:


Parse Tree:

最左推导:

最右推导:


error kinds:

error detect:

error correction:


正常的语法树:

AST(Abstract Syntax Tree):

不匹配, 回溯:

匹配成功:

从上到下, 从左到右

一个完整的例子, 实际上整个过程就是 dfs:

没有遍历所有情况, 所以可能会有提前识别的风险

如上图, int * int 在被识别到第一个 int 后, 指针后移, 于是变成了识别 int 和 * int, 识别错误
Recursive Descent Algorithm 是从左到右进行分析, 而左递归是从右到左产生语言, 无法使用该算法分析, 所以要将左递归转换为右递归

转换方法:

总结:


LL(K): 从左到右扫描, 最左生成, 向前看 K 个 tokens(此章节中 K=1)
像之前的 $T \rightarrow T+E | T$ 的例子中, $T+E$ 和 $T$ 的第一个 token 相同, 所以无法用 LL(1) 语法预测, 所以引入了 left-factored 语法 (提取左边的公因式):


leftmost non-terminal: 最左非终结符
next input token: 下一个输入的 token
rhs of production to use: 生成式的右边部分

使用 LL(1) parsing table 的算法:

一个例子:


终结符的 First Set 是他本身, 所以 $First(t) = {t} \dots$
$E$ 根据 LL(1) 会识别到 $T$, 所以 $First(E) \supset First(T) $, 但是因为 $E$ 没有生成新的 (区别于 $First(T)$ ) 终结符, 所以 $First(E) = First(T)$


rightmost derivation


| 表示输入的位置

lhs: left hand side 推导式的左边部分
rhs: right hand side 推导式的右边部分





reduce: 规约, 生成式右到左执行
shift: 移入, 生成式左到右执行


red : reduce


此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。