下面是一个只包含符号 a 和 b 的正则表达式文法。它使用 + 替代表示并运算的字符 | ,以避免和文法中作为元符号使用的竖线相混淆:
rexpr -> rexpr + rterm | rterm rterm -> rterm rfactor | rfactor rfactor -> rfactor * | rprimary rprimary -> a | b
无左公因子
不适合
消除左递归
rexpr -> rterm A A -> + rterm A | ε rterm -> rfactor B B -> rfactor B | ε rfactor -> rprimary C C -> * C | ε rprimary -> a | b
适合?
对下面的文法重复练习 4.3.1
S -> S S + | S S * | a
提取左公因子
S -> S S A | a A -> + | *
// initial status 1)S -> S S A | a 2) A -> + | * // i = 1 1) S -> a B 2) B -> S A B | ε 3) A -> + | * // i = 2, j = 1 1) S -> a B 2) B -> a B A B | ε 3) A -> + | * // i = 3, j = 1 ~ 2 // nothing changed
适合
S -> 0 S 1 | 0 1
S -> 0 A A -> S 1 | 1
不适合,有间接左递归
// initial status 1) S -> 0 A 2) A -> S 1 | 1 // i = 1 // nothing changed // i = 2, j = 1 1) S -> 0 A 2) A -> 0 A 1 | 1
合适
S -> S (S) S | ε
不合适
// initial status 1) S -> S (S) S | ε // i = 1 1) S -> A 2) A -> (S) S A | ε // i = 2, j = 1 // nothing changed
S -> (L) | a 以及 L -> L, S | S
// initial status 1) S -> (L) | a 2) L -> L, S | S // i = 1 // nothing changed // i = 2, j = 1 1) S -> (L) | a 2) L -> (L) A | a A 3) A -> , S A | ε // i = 3, j = 1~2 // nothing changed
下面文法的目的是消除 4.3.2 节中讨论的 “悬空-else 二义性”:
stmt -> if expr then stmt | matchedStmt matchedStmt -> if expr then matchedStmt else stmt | other
说明这个文法仍然是二义性的。
看一段示范代码,我们通过缩进来表示代码解析的层次结构
if expr then if expr then matchedStmt else if expr then matchedStmt else stmt
这段代码还可以被解析成
所以这仍然是一个二义性的文法。原因在于 matchedStmt -> if expr then matchedStmt else stmt 中的最后一个 stmt,如果包含 else 语句的话,既可以认为是属于这个 stmt 的,也可以认为是属于包含这个 matchedStmt 的语句的。
matchedStmt -> if expr then matchedStmt else stmt
stmt
else
matchedStmt
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8