English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

访客
1 / ?
返回课程列表

文法作为图结构

编译器通过构建解析树来翻译源代码——一棵有根树,其中每个节点代表所应用的文法规则,每个叶子代表一个终端符号(变量名、字面值、运算符)。

树的几何

具有n个节点和n−1条边的树。深度d:从根到任何叶子的最大距离。对于深度为d的平衡二叉树:最多2^d个叶子和2^(d+1)−1个总节点。

典型表达式的解析树不是平衡的:运算符优先级创建右倾斜或左倾斜的树。A + B C产生一棵树,其中+更深,编码*的绑定更紧密。

BNF与ALGOL

Backus-Naur Form (BNF)为指定ALGOL而发明,将文法形式化为生产规则:

`` <expr> ::= <term> | <expr> + <term> <term> ::= <factor> | <term> * <factor> <factor> ::= id | (<expr>) ``

每个生产规则定义树的一个级别。文法是非终端符号上的有向图;解析一个句子通过该图从起始符号追踪一条路径到叶子。

软件几何:复杂度与冗余

解析树深度与表达式复杂性

对于表达式(A + B) * (C + D),解析树在标准运算符优先级下具有特定结构。

解析树的深度影响编译器性能:在递归下降解析期间,更深的树需要更多的栈帧。

使用上面的文法绘制或描述表达式`(A + B) * (C + D)`的解析树。它有多少个内部节点?树的深度是多少(根 = 深度 0)?然后:递归下降解析器使用O(depth)栈空间。对于n个运算符的完全括号化表达式(每个深度与n成正比),Big-O栈空间是什么?

Shannon熵与冗余

Hamming注意到口语约60%冗余,书面语言约40%。这具有精确的信息论含义。

Shannon熵

对于从字母表A生成符号且概率为{p₁, p₂, ..., pₙ}的信源:

H = −Σ pᵢ log₂(pᵢ) (每符号比特数)

最大熵:均匀分布(所有符号等可能)。对于n个符号,H_max = log₂(n)。

冗余R:不携带信息的比特的分数(可以删除而不丢失内容):

R = 1 − H / H_max

如果R = 0.4(40%冗余):40%的比特可以从上下文预测。以8比特/字符传送英文文本的通道只使用其容量的60%来传送信息;40%是接收者已知的结构。

错误检测使用冗余:如果40%的比特是可预测的,传输错误可能产生违反冗余结构的序列——即使没有纠错码也可检测。

APL的接近零冗余:单个字符更改几乎永远不会从单独的上下文中检测到。英语的60%冗余:即使字母缺失或错误,您也可以从周围上下文重建单词。

计算冗余

英文字母频率(近似):'e'出现~12.7%的时间;'z'出现~0.07%。英文的实际熵约H ≈ 1.0比特/字符(考虑单词级上下文)。26字母字母表的最大熵:H_max = log₂(26) ≈ 4.70比特/字符。

使用H = 1.0比特/字符和H_max = log₂(26)计算英文的冗余R = 1 − H/H_max。然后为具有H = 3.5比特/字符和相同26符号字母表的语言计算R。哪种语言具有更多的错误检测容量,以及系数是多少?

作为几何的增长曲线

编译器算法处理大小为n的程序(令牌、行或节点)。算法选择决定编译时间如何随程序大小缩放。

常见复杂度类

| 类别 | 运行时 | 例子 | |---|---|---| | O(n) | 线性 | 词法扫描 | | O(n log n) | 拟线性 | 最优排序 | | O(n²) | 二次 | 朴素重复检测 | | O(n³) | 三次 | 矩阵乘法,CYK解析 | | O(2ⁿ) | 指数 | 朴素定理证明 |

几何图像:绘制运行时与n的关系。O(n)是一条线。O(n²)是抛物线。O(2ⁿ)是一条指数曲线,在n=0附近看起来平坦,在n=50附近几乎垂直。

通用上下文无关文法解析(CYK算法)在O(n³)中运行。对于大多数实际编程语言,文法设计为LR(1)-可解析,允许O(n)解析。ALGOL的文法比FORTRAN的更复杂,导致编译器更慢——这是1958年编译花费数小时时的实际摩擦。

交叉点

朴素符号表查找为具有n个标识符的程序使用O(n²)总操作(n个查找中每个的线性扫描)。哈希表符号表使用O(n)预期总操作。

假设:O(n²)算法在1958年硬件上以10⁶操作/秒运行。O(n)算法以相同速度运行,但需要100n个设置操作(哈希表构造)。

对于具有n = 1000个标识符的程序:计算两个算法的总时间(以秒为单位)。在n的什么值时两个算法花费相等时间?显示代数。