当前位置:   article > 正文

编译原理-4-上下文无关文法

上下文无关文法

上下文无关文法(CFG, Context-Free Grammer, 上下文无关文法)

  1. LL(1)可以完成手写分析器
  2. LR(1)可以更不容易出现细节问题
  3. Bison工具是本实验使用的工具。

1. 上下文无关文法(CFG)定义

  1. 上下文无关文法 G G G是一个四元组 G = ( T , N , P , S ) G=(T,N,P,S) G=(T,N,P,S):
    1. T是终结符号 Terminal集合, 对应于词法分析器产生的词法单元
    2. N是非终结符号 Non-terminal集合
    3. P是产生式 Production集合

A ∈ N → α ∈ ( T ∪ N ) ∗ A \in N \rightarrow \alpha \in (T \cup N)* ANα(TN)

  1. 头部/左部(Head) A A A:
    1. 单个非终结符,必须只有一个,是命名为上下文无关文法的原因。
    2. 如果有多个则不符合上下文无关文法,会被成为上下文有关文法,但是几乎无法处理。
  2. 体部/右部(Body) α \alpha α:
    1. 终结符与非终结符构成的串
    2. 也可以是空串 ϵ \epsilon ϵ
  3. S S S为开始(Start)符号
  4. 要求 S ∈ N S \in N SN且唯一。

1.1. 上下文无关文法示例

  1. 一个符号要么是终结符号,要么是非终结符号
  2. 终结符号表示到此为止,无法再进行替换

G = ( { S } , { ( , ) } , P , S ) S → S S S → ( S ) S → ( )

G=({S},{(,)},P,S)SSSS(S)S()
G=({S},{(,)},P,S)SSSS(S)S()

上面的文法表示任意嵌套的所有匹配好的括号串

G = ( { S } , { a , b } , P , S ) S → a S b S → ϵ

G=({S},{a,b},P,S)SaSbSϵ
G=({S},{a,b},P,S)SaSbSϵ

可以有很多的情况

1.2. 条件语句文法

  1. 条件语句文法中包含悬空(Dangling)-else文法的问
  2. 这样的文法是有问题,我们进一步分析才可以,OTHER作为终结符。

1.3. 约定

约定: 如果没有明确指定, 第一个产生式的头部就是开始符号,用来避免写如上例子中的一些描述

1.4. 关于终结符号的约定

下述符号是终结符号:(通常的约定)

  1. 在字母表里排在前面的小写字母,比如a、b、c。
  2. 运算符号,比如+、*等。
  3. 标点符号,比如括号、逗号等。
  4. 数字,0、1、… 9。
  5. 黑体字符串,比如id或if。每个这样的字符串表示一个终结符号。

1.5. 关于非终结符号的约定

下述符号是非终结符号:

  1. 在字母表中排在前面的大写字母,比如A、B、C。
  2. 字母S。它出现时通常表示开始符号。
  3. 小写、斜体的名字,比如expr或stmt.

2. 语义

  1. 上下文无关文法 G G G定义了一个语言 L ( G ) L(G) L(G)
  2. 语言是的集合

3. 推导(Derivation)的定义

3.1. 表达式文法

E → − E ∣ E + E ∣ E ∗ E ∣ ( E ) ∣ i d E \rightarrow -E|E + E | E ∗ E | (E) | id EEE+EEE(E)id

  1. 推导即是将某个产生式的左边替换成它的右边
  2. 每一步推导需要选择替换哪个非终结符号,以及使用哪个产生式

E ⇒ − E ⇒ − ( E ) ⇒ − ( E + E ) ⇒ − ( i d + E ) ⇒ − ( i d + i d ) E \Rightarrow -E \Rightarrow −(E) \Rightarrow −(E+E) \Rightarrow −(id+E) \Rightarrow −(id+id) EE(E)(E+E)(id+E)(id+id)

E ⇒ − E : 经 过 一 步 推 导 得 出 E ⇒ + − ( i d + E ) : 经 过 一 步 或 多 步 推 导 得 出 E ⇒ ∗ − ( i d + E ) : 经 过 零 步 或 多 步 推 导 得 出

EE:E\xRightarrow+(id+E):E\xRightarrow(id+E):
EE:E+ (id+E):E (id+E):

E ⇒ − E ⇒ − ( E ) ⇒ − ( E + E ) ⇒ − ( E + i d ) ⇒ − ( i d + i d ) E \Rightarrow -E \Rightarrow −(E) \Rightarrow −(E+E) \Rightarrow −(E+id) \Rightarrow −(id+id) EE(E)(E+E)(E+id)(id+id)

3.2. Definition (Sentential Form,句型)

如果 S ⇒ ∗ α S \xRightarrow{*} \alpha S α,且 α ∈ ( T ∪ N ) ∗ \alpha \in ( T \cup N)^* α(TN),则称 α \alpha α是文法G的一个句型(包含非终结符)

E → − E ∣ E + E ∣ E ∗ E ∣ ( E ) ∣ i d E ⇒ − E ⇒ − ( E ) ⇒ − ( E + E ) ⇒ − ( i d + E ) ⇒ − ( i d + i d )

EE|E+E|EE|(E)|idEE(E)(E+E)(id+E)(id+id)
EEE+EEE(E)idEE(E)(E+E)(id+E)(id+id)

3.3. Definition (Sentence,句子)

  1. 如果 S ⇒ ∗ w S \xRightarrow{*} w S w,且 w ∈ T ∗ w \in T^* wT,则称w是文法G的一个句子(没有非终结符了)
  2. 句子就是这个语言中的串

4. Definition (文法G生成的语言L(G))

文法F的语言L(G)是它能推导出的所有句子构成的集合。

w ∈ L ( G ) ⇔ S ⇒ ∗ w w \in L(G) \Leftrightarrow S \xRightarrow{*} w wL(G)S w

4.1. 关于文法G的两个基本问题

  1. Membership问题:给定字符串 x ∈ T ∗ , x ∈ L ( G ) x \in T^*, x \in L(G) xT,xL(G)?字符串可不可以由文法推理得到
  2. L(G)究竟是什么?

4.1.1. 问题一:Membership问题

  1. 给定字符串 x ∈ T ∗ , x ∈ L ( G ) x \in T^*, x \in L(G) xT,xL(G),(即检查x是否符合文法G)
  2. 这就是语法分析器的任务:为输入的词法单元流寻找推导、构建语法分析树, 或者报错

  1. 根节点是文法G的起始符号
  2. 叶子节点是输入的词法单元流
  3. 常用的语法分析器以自顶向下自底向上的方式构建中间部分

4.1.2. 问题二:L(G) 是什么?

这是程序设计语言设计者需要考虑的问题

4.1.2.1. 根据文法G推导语言L(G)

例子一
S → S S S → ( S ) S → ( ) S → ϵ L ( G ) = { 良 匹 配 括 号 串 }

SSSS(S)S()SϵL(G)={}
SSSS(S)S()SϵL(G)={}

例子二
S → a S b S → ϵ L ( G ) = a n b n ∣ n ≥ 0

SaSbSϵL(G)=anbn|n0
SaSbSϵL(G)=anbnn0

4.1.2.2. 根据语言L(G)来推导文法G
  1. 目标生成:字母表 ∑ = a , b \sum = {a, b} =a,b上的所有回文串(Palindrome)构成的语言

S → a S a S → b S b S → a S → b S → ϵ S → a S a ∣ b S b ∣ a ∣ b ∣ ϵ

SaSaSbSbSaSbSϵSaSa|bSb|a|b|ϵ
SaSaSbSbSaSbSϵSaSabSbabϵ

  1. 目标生成: b n a m b 2 n ∣ n ≥ 0 , m ≥ 0 {b^na^mb^{2n}|n \geq 0, m \geq 0} bnamb2nn0,m0
    S → b S b b ∣ A A → a A ∣ ϵ

    SbSbb|AAaA|ϵ
    SbSbbAAaAϵ

  2. 目标生成: { x ∈ { a , b } ∗ ∣ x 中 a , b 个 数 相 同 } \{x\in \{a, b\}^* | x 中a,b个数相同 \} {x{a,b}xa,b}

    1. 证明:a可以是空串
    2. 证明:a以a开头,那么后面肯定能找到一个b保证被分为了aVbV并且V中的ab数量均相同,以b开头类似。

V → a V b V ∣ b V a V ∣ ϵ

VaVbV|bVaV|ϵ
VaVbVbVaVϵ

  1. 目标生成: { x ∈ { a , b } ∗ ∣ x 中 a , b 个 数 不 同 } \{x\in \{a, b\}^* | x 中a,b个数不同 \} {x{a,b}xa,b}
    1. T表示a多一个或者更多
    2. U表示b多一个或者更多
    3. UT不能同时出现,和V去组合即可
    4. 证明

S → T ∣ U T → V a T ∣ V a V U → V b U ∣ V b V V → a V b V ∣ b V a V ∣ ϵ

ST|UTVaT|VaVUVbU|VbVVaVbV|bVaV|ϵ
STUTVaTVaVUVbUVbVVaVbVbVaVϵ

4.2. 顺序语句、条件语句、打印语句

上图中的L是顺序语句

5. L-System(不考)

L-System:这不是上下文无关文法, 但精神高度一致

v a r i a b l e s : A B c o n s t a n t s : + − s t a r t : A r u l e s : ( A → B − A − B ) , ( B → A + B + A ) a n g l e s : 6 0 ′

variables:ABconstants:+start:Arules:(ABAB),(BA+B+A)angles:60
variables:ABconstants:+start:Arules:(ABAB),(BA+B+A)angles:60

  1. A , B A,B A,B:向前移动并画线
  2. +:左转
  3. -:右转
  4. 每一步都并行地应用所有规则

v a r i a b l e s : X Y c o n s t a n t s : F + − s t a r t : F X r u l e s : ( X → X + Y F + ) , ( Y → − F X − Y ) a n g l e s : 9 0 ′

variables:XYconstants:F+start:FXrules:(XX+YF+),(YFXY)angles:90
variables:XYconstants:F+start:FXrules:(XX+YF+),(YFXY)angles:90

  1. F F F:向前移动并画线
  2. +:右转
  3. -:左转
  4. X:仅用于展开,在作画时被忽略
  5. 每一步都并行地应用所有规则

6. 最左(leftmost) 推导与最右(rightmost) 推导

E → E + E ∣ E ∗ E ∣ ( E ) ∣ i d E ⇒ l m − E ⇒ l m − ( E ) ⇒ l m − ( E + E ) ⇒ l m − ( i d + E ) ⇒ l m − ( i d + i d )

EE+E|EE|(E)|idE\xRightarrow[lm]E\xRightarrow[lm](E)\xRightarrow[lm](E+E)\xRightarrow[lm](id+E)\xRightarrow[lm](id+id)
EE+EEE(E)idE lmE lm(E) lm(E+E) lm(id+E) lm(id+id)

  1. E ⇒ l m − E E \xRightarrow[lm]{} -E E lmE:经过一步最左推导得出
  2. E ⇒ l m + − ( i d + E ) E \xRightarrow[lm]{+} -(id + E) E+ lm(id+E):经过一步或多步最左推导得出
  3. E ⇒ l m ∗ − ( i d + E ) E \xRightarrow[lm]{*} -(id + E) E lm(id+E):经过零步或多步最左推导得出
  4. 最左推导是有非终结符优先选择最左侧的进行推导
  5. 最右推导是有非终结符有限选择最右侧的进行推导

E ⇒ r m − E ⇒ r m − ( E ) ⇒ r m − ( E + E ) ⇒ r m − ( E + i d ) ⇒ r m − ( i d + i d ) E \xRightarrow[rm]{} -E \xRightarrow[rm]{} -(E) \xRightarrow[rm]{} -(E+E) \xRightarrow[rm]{} -(E + id) \xRightarrow[rm]{} -(id+id) E rmE rm(E) rm(E+E) rm(E+id) rm(id+id)

6.1. Definition (Left-sentential Form,最左句型)

  1. 如果 S ⇒ l m ∗ α S \xRightarrow[lm]{*} \alpha S lmα, 并且 α ∈ ( T ∪ N ) ∗ \alpha \in (T \cup N)^* α(TN),则称 α \alpha α是文法G的一个最左句型

E ⇒ l m − E ⇒ l m − ( E ) ⇒ l m − ( E + E ) ⇒ l m − ( i d + E ) ⇒ l m − ( i d + i d ) E \xRightarrow[lm]{} -E \xRightarrow[lm]{} -(E) \xRightarrow[lm]{} -(E+E) \xRightarrow[lm]{} -(id + E) \xRightarrow[lm]{} -(id+id) E lmE lm(E) lm(E+E) lm(id+E) lm(id+id)

6.2. Definition (Right-sentential Form,最右句型)

  1. 如果 S ⇒ r m ∗ α S \xRightarrow[rm]{*} \alpha S rmα, 并且 α ∈ ( T ∪ N ) ∗ \alpha \in (T \cup N)^* α(TN),则称 α \alpha α是文法G的一个最右句型

E ⇒ r m − E ⇒ r m − ( E ) ⇒ r m − ( E + E ) ⇒ r m − ( i d + E ) ⇒ r m − ( i d + i d ) E \xRightarrow[rm]{} -E \xRightarrow[rm]{} -(E) \xRightarrow[rm]{} -(E+E) \xRightarrow[rm]{} -(id + E) \xRightarrow[rm]{} -(id+id) E rmE rm(E) rm(E+E) rm(id+E) rm(id+id)

7. 语法分析树

  1. 语法分析树是静态的, 它不关心动态的推导顺序

  1. 一棵语法分析树对应多个推导
  2. 但是, 一棵语法分析树与最左(最右) 推导一一对应

7.1. 二义性引入

  1. 1 - 2 - 3的语法树的两种不同表达形式
  2. 以下的两棵语法树是不同的,生成出来的目标代码也是不同的
  3. 这个文法是有问题的,这个文法具有二义性,我们需要通过修改文法避开二义性问题。
  4. 语法没有二义性的描述,L(G)本身只是一个串的集合。

7.2. Definition (二义性(Ambiguous) 文法)

  1. 如果L(G) 中的某个句子有一个以上语法树/最左推导/最右推导,则文法G是二义性的。
  2. 1 + 2 * 3的语法树

7.3. 悬空-else

8. 二义性文法

  1. 不同的语法分析树产生不同的语义
  2. 所有语法分析器都要求文法是无二义性

  1. Q:如何识别二义性文法?这是不可判定的问题,是指没有通用的算法,可以判断任意的文法G
  2. Q:如何消除文法的二义性?

8.1. 消除文法二义性

  1. 四则运算均是左结合的
  2. 优先级: 括号最先, 先乘除后加减
  3. 二义性表达式文法以相同的方式处理所有的算术运算符
  4. 要消除二义性, 需要区别对待不同的运算符
  5. 将运算的"先后" 顺序信息编码到语法树的"层次"结构中

E → E + E ∣ i d

EE+E|id
EE+Eid

8.2. 左结合文法

E → E + T T → i d

EE+TTid
EE+TTid

8.3. 右结合文法

E → T + E T → i d

ET+ETid
ET+ETid

8.4. 使用左(右)递归实现左(右)结合

8.5. 括号最先, 先乘后加文法

乘号更靠近叶子节点

E → E + E ∣ E ∗ E ∣ ( E ) ∣ i d E → E + T ∣ T T → T ∗ F ∣ F F → ( E ) ∣ i d

EE+E|EE|(E)|idEE+T|TTTF|FF(E)|id
EE+EEE(E)idEE+TTTTFFF(E)id

8.6. Summary

E → E + E ∣ E − E ∣ E ∗ E ∣ E / E ∣ ( E ) ∣ i d ∣ n u m b e r E → E + T ∣ E − T ∣ T T → T ∗ F ∣ T / F ∣ F F → ( E ) ∣ i d ∣ n u m b e r

EE+E|EE|EE|E/E|(E)|id|numberEE+T|ET|TTTF|T/F|FF(E)|id|number
EE+EEEEEE/E(E)idnumberEE+TETTTTFT/FFF(E)idnumber

  1. 无二义性的表达式文法
    1. E:表达式(expression)
    2. T:项(term)
    3. F:因子(factor)
  2. 将运算的"先后"顺序信息编码到语法树的"层次"结构中

8.7. IF-Then-Else问题

每个else与最近的尚未匹配的then匹配

  1. 基本思想: then与else之间的语句必须是"已匹配的"
  2. 证明两件事情:证明部分不作为重点
    1. L ( G ) = L ( G ′ ) L(G) = L(G') L(G)=L(G)
    2. G ′ G' G是无二义性的

8.7.1. L ( G ) = L ( G ′ ) L(G) = L(G') L(G)=L(G)证明过程

L ( G ′ ) ⊆ L ( G ) 简 单 容 易 证 明

L(G)L(G)
L(G)L(G)

文法是递归的,我们可以使用数学归纳法,对推导步骤进行归纳
L ( G ) ⊆ L ( G ′ ) x ∈ L ( G ) → x ∈ L ( G ′ ) s t m t → . . . → x

L(G)L(G)xL(G)xL(G)stmt...x
L(G)L(G)xL(G)xL(G)stmt...x

  1. 只要G中展开一步,G’中都有相应的对应即证明了 L ( G ) ⊆ L ( G ′ ) L(G) \subseteq L(G') L(G)L(G)

8.7.2. G ′ G' G 是无二义性的

  1. 每个句子对应的语法分析树是唯一的
  2. 只需证明: 每个非终结符的展开方式是唯一的

L ( m a t c h e d _ s t m t ) ∩ L ( o p e n _ s t m t ) = ∅ L ( m a t c h e d _ s t m t 1 ) ∩ L ( m a t c h e d _ s t m t 2 ) = ∅ L ( o p e n _ s t m t 1 ) ∩ L ( o p e n _ s t m t 2 ) = ∅

L(matched_stmt)L(open_stmt)=L(matched_stmt1)L(matched_stmt2)=L(open_stmt1)L(open_stmt2)=
L(matched_stmt)L(open_stmt)=L(matched_stmt1)L(matched_stmt2)=L(open_stmt1)L(open_stmt2)=

上面的下标代表子句

  1. Q:为什么不使用优雅、强大的正则表达式描述程序设计语言的语法?
  2. A:正则表达式的表达能力严格弱于上下文无关文法

每个正则表达式r对应的语言L® 都可以使用上下文无关文法来描述

r = ( a ∣ b ) ∗ a b b r=(a|b)^∗abb r=(ab)abb

  1. 此外, 若 δ ( A i , ϵ ) = A j \delta(A_i,\epsilon) = A_j δ(Ai,ϵ)=Aj,则添加 A i → A j A_i \rightarrow A_j AiAj

S → a S b S → ϵ L = a n b n ∣ n ≥ 0

SaSbSϵL=anbn|n0
SaSbSϵL=anbnn0

  1. 该语言无法使用正则表达式来描述
  2. 定理: L = { a n b n ∣ n ≥ 0 } L = \{a^nb^n | n ≥ 0\} L={anbnn0} 无法使用正则表达式描述
  3. 反证法
    1. 假设存在正则表达式r: L ( r ) = L L(r) = L L(r)=L
    2. 则存在有限状态自动机D®: L ( D ( r ) ) = L L(D(r)) = L L(D(r))=L; 设其状态数为k
    3. 考虑输入 a m ( m > k ) a^m(m>k) am(m>k)

  1. D ( r ) D(r) D(r)也能接受a{i+j}bi,矛盾
  2. Pumping Lemma for Regular Languages: L = a n b n ∣ n ≥ 0 L = {a^nb^n | n \geq 0} L=anbnn0
  3. Pumping Lemma for Context-free Languages: L = a n b n c n ∣ n ≥ 0 L = {a^nb^nc^n | n \geq 0} L=anbncnn0
  4. 只考虑无二义性的文法这意味着,每个句子对应唯一的一棵语法分析树
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/331263
推荐阅读
相关标签
  

闽ICP备14008679号