编译原理-语法分析
FIRST
¶如果
是一个终结符号,那么如果
是一个产生式,那么如果
是一个非终结符号,且 是一个产生式:对于
,如果 都有 成立,则
向
加入 的所有非 符号如果
,再加入 的所有非 符号;以此类推如过
对 均成立,则将 加入 中
FOLLOW
¶将
放到 中如果存在一个产生式
,将 中所有的非 符号放入到 中如果存在一个产生式
或存在一个产生式 且 ,将 中所有符号放到 中
自顶向下的语法分析
¶LL(1) 文法
¶有二义性和左递归的文法都不是
的一个文法是
的,当且仅当 的任意两个不同的产生式 满足: 和 是不相交的集合。也就是不存在左公因子。如果
,则 和 是不相交的集合如果
,则 和 是不相交的集合
预测分析表
¶对于
对于
中的每个终结符号 ,将 加入到 中如果
在 中:那么对于
中的每个终结符号 ,将 加入到 中如果
在 中,将 加入到 中
自底向上的语法分析
¶规范 LR(0) 项集族
¶项集的闭包
¶如果
是文法 的一个项集,那么 可由下面两个规则从 构造得到。将
中的各个项加入到 中如果
在 中, 是一个产生式,并且项 不在 中,就将这个项加入其中。 不断应用这个规则,直到没有新项加入到 中为止
直观地讲,
中的项 表明在语法分析过程的某点上,我们认为接下来可能会在输入中看到一个能够从 推导得到的子串。
GOTO 函数
¶ ,其中 是一个项集, 是一个文法符号。 被定义为 中所有形如 的项所对应的项 的集合的闭包。
直观地讲,
函数用于定义一个文法的 自动机中的转换,描述了当输入为 时离开状态 的转换。
构造项集族
¶初始时,
对于
中的每个项集 :对于每个文法符号
:- 如果
非空且不在 中,将 加入到 中
- 如果
重复过程 2
构造 SLR 语法分析表
¶构造
的规范 项集族 .根据
构造得到状态 。状态 的语法分析动作按照下面的方法决定:如果
在 中,并且 ,令 ,即移入 ;其中, 必须是终结符。如果
在 中,那么对于 中的所有 ,令 ,即规约 ;其中, 为 产生式 的编号; .如果
在 中,令 ,即接受。
如果根据上面的规则生成了任何冲突动作,则这个文法不是
的。状态 对于各个非终结符号 的 转换使用下面的规则构造得到:- 如果
, 那么, 。
- 如果
规则 (2) 和规则 (3) 没有定义的条目均设为 “报错”。
语法分析器的初始状态是根据
所在项集构造得到的状态。
有效 LR(1) 项集族
¶可行前缀
- 可以出现在一个移入--规约的语法分析器的栈中的最右句型前缀,称为可行前缀
项形如
的项,称为 项;其中 是一个产生式, 是一个终结符或右端结束标记形如
的项只有在下一个输入符号为 时才选择 规约。
可行前缀的有效项
项 对于可行前缀 有效的条件是:存在一个最右推导
,且 ,且要么
是 的第一个符号,要么 且
项集的闭包
¶如果
如果
是文法 的一个项集,那么 可由下列规则从 中构造得到。对于
中的每个项对于
中的每个产生式对于
中的每个终结符号- 将
加入到集合 中
- 将
本质上,
是利用 自动机能够识别可行前缀这一事实构造的语法分析方案; 在此基础上考虑了对可行前缀的有效性。 和 构造闭包的算法的区别在于:不再对于任意的
添加到闭包中了,这样做的目的是为了减少移入--规约冲突。 也就是,如果 中有产生式 ,对于产生式 : : 直接将 加进 的闭包中 : 由于有一个向前看符号,不妨记 的向前看符号为 ,那么仅当满足 时才能将 加进 的闭包
GOTO 函数
¶计算
将
初始化为空集对于
中的每个项- 将项
加入到集合 中
- 将项
返回
构造项集族
¶初始时,
对于
中的每个项集对于每个文法符号
如果
非空且不在 中- 将
加入 中
- 将
构造规范 LR(1) 语法分析表
¶构造
的规范 项集族 .根据
构造得到状态 。状态 的语法分析动作按照下面的方法决定:如果
在 中,并且 , 令 ,即移入 ;其中, 必须是终结符。如果
在 中,且 ; 那么令 ,即规约 ;其中, 为产生式 的编号。如果
在 中,令 ,即接受。
如果根据上面的规则生成了任何冲突动作,则这个文法不是
的。状态 对于各个非终结符号 的 转换使用下面的规则构造得到:- 如果
, 那么, 。
- 如果
规则(2) 和规则(3) 没有定义的条目均设为“报错”。
语法分析器的初始状态是根据
所在项集构造得到的状态。