知识

解析树和派生

考虑以下表达式:

E→E+E | E*E |(E)|-E | id

id+id*id的最左导数

alt alt

替代解析树与派生

这里有什么问题?

两个截然不同的最左边的派生词! alt

模棱两可(二义性)
  • 一个语法为一个句子生成多个解析树,称为歧义语法。

对于大多数解析器来说,语法必须是明确的。

  • 明确的语法➔ 句子解析树的唯一选择

  • 我们应该在编译器的设计阶段消除语法中的歧义。

  • 应编写歧义语法以消除歧义。

  • 我们必须选择一个句子的解析树(由歧义语法生成)来消除该语法的歧义,通过“扔掉”不需要的解析树来限制这种选择

id+id*id的两个解析树

alt

歧义–运算符优先级
  • 可以根据优先级和关联性规则消除歧义语法(因为存在歧义运算符)。 alt
消除歧义(第174页)

考虑下面的语法部分:

stmt → if expr then stmt
| if expr then stmt else stmt
| other (any other statement)

有什么问题吗?

让我们考虑一个简单的解析树:

alt

否则必须与上一个匹配。

结构指示表达式的解析子树。

示例:这个字符串会发生什么?

alt

一个歧义句子的两个解析树

alt

  • 我们更喜欢第二个解析树(else与最近的if匹配)。

  • 因此,我们必须消除语法歧义,以反映这一选择。

  • 明确的语法将是:

stmt → matchedstmt 
| unmatchedstmt
matchedstmt → if expr then matchedstmt else matchedstmt 
| otherstmts
unmatchedstmt → if expr then stmt 
| if expr then matchedstmt else unmatchedstmt

一般的规则是“用最接近的前一个未匹配的进行匹配”

左递归(第176页)
  • 语法是递归的(左递归) 如果它有一个非终端a,这样就有一个派生a→ Aα表示某个字符串α。

  • 左递归可能出现在推导的单个步骤中(立即左递归直接左递归), 或者可能出现在推导的多个步骤中。

  • 自上而下的解析技术无法处理左递归语法。

  • 因此,我们必须将我们的左递归语法转换为一个等价的非左递归语法。

为什么左递归是个问题?

alt

这是如何构建字符串的?

每个字符串都必须以什么开头?

立即左递归

alt

消除课堂上的直接左递归练习1

alt

左递归——问题
  • 语法不能立即保持递归,但仍然可以保持递归。

  • 仅仅通过消除直接左递归,我们可能不会得到一个非左递归的语法。 alt

作业

1. 消除下列文法的左递归性。

(1) S→SA|A

A→SB|B|(S)|( )

B→[S]|[ ]

(2) S→(L)|a

L → L, S | S

(3) S→AS|b

A→SA|a

2. 给定文法

S->aSbS|bSaS|e (注: e是空)

a) 该文法是否有二义性,证明之。

b) 构造abab的最右推导

c) 构造abab语法树

3. 考虑文法

S→aSbS | bSaS | e

为某个句子构造两个不同的最左推导,以证明它是二义性的