编译原理及实现技术:15. 语法分析_LR(1) 方法
语法分析
语法分析是编译器的第二阶段,它的任务是对源程序的语法进行检查和分析,确保程序符合语言的语法规则。语法分析的结果是一个语法树,它可以用来生成中间代码。
LR(1) 方法
LR(1) 方法是一种语法分析算法,它由 Donald Knuth 在 1965 年提出。LR(1) 方法可以处理 Ambiguous 语法,且可以生成语法树。LR(1) 方法的主要思想是对非终极符的每个不同出现求其后继符,而不是给每个非终极符求其统一的后继符。
LR(1) 项目
LR(1) 项目是 LR(1) 分析器的基本组成部分。它是一个二元组,[A→α·β, a],其中 A→α·β 是一个产生式,a 是一个展望符。LR(1) 项目集是所有 LR(1) 项目的集合。
闭包集和 GO 函数
闭包集是 LR(1) 项目集的扩展,它包括所有可以从 LR(1) 项目集中推导出来的项目。GO 函数是 LR(1) 分析器中的一个重要函数,它用来计算从一个状态到另一个状态的转换关系。
可归前缀图的构造
可归前缀图是 LR(1) 分析器中的一个重要数据结构,它用来存储语法分析的结果。可归前缀图的构造是一个迭代的过程,首先生成初始项目集,然后不断地应用 GO 函数来生成新的项目集,直到不再产生新的状态。
例子
有文法:Z→BB, B→aB, B→bb, Z→BB#, B→#B, B→aB, B→b#。我们可以使用 LR(1) 方法来构造可归前缀图,并生成语法分析表。
LR 分析表
LR 分析表是 LR(1) 分析器的输出结果,它包括 Action 表和 Goto 表。Action 表用来存储语法分析的结果,Goto 表用来存储状态之间的转换关系。
在上面的例子中,我们可以生成以下 LR 分析表:
| 状态栈 | 符号栈 | 输入串 | Action | GoTo |
| --- | --- | --- | --- | --- |
| 0 | | abaab# | S6 | 0,6 |
| 4 | 0,6 | a | S4 | 0,6,4 |
| 1 | 0,6,4 | ab | S5 | 0,6,4,5 |
| 3 | 0,6,4,5 | a | R3 | 7,0,6,7 |
| 2 | 0,6,4,5,7 | R2 | 8,0,6,7 |
| ... | ... | ... | ... | ... |
这个 LR 分析表可以用来生成语法树,并且可以用于语法检查和错误恢复。
结论
LR(1) 方法是一种强大的语法分析算法,它可以处理 Ambiguous 语法,且可以生成语法树。LR(1) 方法的主要思想是对非终极符的每个不同出现求其后继符,而不是给每个非终极符求其统一的后继符。LR(1) 方法的应用非常广泛,它可以用于编译器、解释器、语法检查等领域。