编译原理学习之:上下文无关文法(Context-free Grammar)和下推自动机(Push-down automata)

本文详细解析了上下文无关文法的概念、实例、二义性,以及如何转化为下推自动机(PDA)进行语言识别。介绍了PDA的工作原理,包括状态转移规则和栈操作,并通过实例说明如何判断字符串是否属于PDA语言。此外,区分了DPDA和NPDA,并展示了如何通过CFG构造PDA。
摘要由CSDN通过智能技术生成

  • 上下文无关文法和下推自动机是等价的,就像正则文法和 NFA, DFA 等价一样

上下文无关文法

  • 文法是一组替换规则,例如下面的例子
    在这里插入图片描述
  • 在下面的例子中,有几个重要的概念:
    • 变量 / 非终结符 (variable)
    • 终结符(teminals)
    • 句子(sentence)
    • 句型(sentential forms):变量 + 终结符
      在这里插入图片描述
  • 上面的例子中的 语法规则 可以表示语言 L ( G ) = { w w R ∣ w ∈ 0 , 1 ∗ } L(G) = \{ww^R | w ∈ {0, 1}^∗\} L(G)={wwRw0,1}
  • 我们把使用上下文无关文法表示的语言称为上下文无关语言;有些 context-free 语言并不是 regular 的例如 { 0 n 1 n ∣ n ≥ 1 } \{0^n1^n | n ≥ 1\} {0n1nn1}

上下文无关文法的定义

在这里插入图片描述

  • V V V 是所有非终结符的集合
  • Σ \Sigma Σ 是所有终结符的集合
  • R R R 是所有语法规则的集合;其中语法规则的组成是 “任意终结符和非终结符的组合”,符号表示为 ( V ∪ Σ ) ∗ (V\cup \Sigma)^* (VΣ)
  • S S S 表示开始状态
  • ⇒ ∗ \Rightarrow^* 来表示 ⇒ \Rightarrow 的自反闭包
    在这里插入图片描述

上下文无关文法举例

在这里插入图片描述
在这里插入图片描述

  • 如果我们没有特殊说明,那么规则的第一条使用的最左端的非终结符(variable)被认为是起始状态(start variable)
  • 假设我们现在有一个语言的某个句子为:
    在这里插入图片描述
  • 根据我们的文法规则,我们可以构造它的语法分析树
    在这里插入图片描述
  • 注意,一棵语法书的推导形式可以有很多种,它取决于我们想替换的非终结词的顺序;一般我们使用 leftmost(最左推导)方法进行推导:最左推导的意思就是永远都最先替换左侧的非终结符。
    在这里插入图片描述

上下文无关文法的二义性(Ambiguity)

  • 按照下面给定的语法规则:
    在这里插入图片描述
  • 如果我们要构造 3 + 7 ∗ 2 3+7*2 3+72 的语法分析树,我们会得到下面的情况:
    在这里插入图片描述
  • 当我们构造语法分析树的时候,如果对于某一个句子,出现了多棵语法分析书,我们就认为他是具有歧义性(二义性)的

下推自动机

  • 对于下面的语法规则
    在这里插入图片描述
  • 对句子 ( 3 + 7 ) ∗ 2 ( 3 + 7 ) ∗ 2 (3+7)2 采用最左推导可以得到:
    在这里插入图片描述
  • 之前我们使用的 NFA 和 DFA 受限于存储空间的问题,不能识别类似于 { 0 n 1 n , n > = 0 } \{0^n1^n, n>=0\} {0n1n,n>=0} 这种语言
  • 下推自动机通过一个 stack(栈)结构解决了这个问题
    在这里插入图片描述
  • 我们通过下面的这个过程,就能判断 a a a b b b 存在的数量,从而判断一个语句(input)是否符合上述语言的定义
    在这里插入图片描述
  • 每一步的判断取决于三个部分
    • 输入的字符
    • 栈顶的元素
    • 当前的状态
  • 根据这三个部分,决定要不要进入下一个状态,以及要对栈中的元素执行什么样的操作。
  • 每一个 transition 步骤,PDA 都会从 input 读一个字符,然后对栈进行压入或者弹出操作,或者两种操作一起执行
  • 我们还将讨论 non-deterministic 的 PDA,他可以忽略输入(input)

下推自动机的定义

在这里插入图片描述

  • Q Q Q 是状态集合
  • Σ \Sigma Σ 是有限的输入集合
  • Γ \Gamma Γ 是栈中的元素集合
  • δ \delta δ 是转换函数:根据当前状态,输入的字符,栈中元素,共同决定了 “下一个状态” 和 “下一个栈的状态”
  • q 0 q_0 q0 是起始状态,只有一个
  • F F F 是接受状态,可以是一个集合
  • δ ( q 5 , a , b ) = { ( q 7 , ϵ ) } δ(q_5, a, b) = \{(q_7, \epsilon)\} δ(q5,a,b)={(q7,ϵ)} 表示:在状态节点 q 5 q_5 q5 如果栈顶元素是 b b b,这时候如果读入 input 为 a a a 那么就会把这个 a a a 消耗掉,并将 b b b 弹出栈;进而进入新的状态 q 7 q_7 q7
  • δ ( q 5 , ϵ , b ) = { ( q 6 , a ) , ( q 7 , b ) } δ(q_5, \epsilon, b) = \{(q_6, a), (q_7, b)\} δ(q5,ϵ,b)={(q6,a),(q7,b)} 表示 在状态节点 q 5 q_5 q5 如果栈顶元素是 b b b,这时候如果读入 input 为 ϵ \epsilon ϵ 空; 那么有两种可能的选择:
    • 使用 a a a 代替了栈顶的 b b b;并进入新的状态 q 6 q_6 q6
    • 让栈保持原样( b b b 依然在栈顶),并进入新的状态 q 7 q_7 q7
    • 这两种情况都不会消耗输入的字符。

下推自动机举例

在这里插入图片描述
在这里插入图片描述

判断一个字符串是否属于 PDA 表示的语言(是不是 PDA 可以 accept 的)

在这里插入图片描述

  • 将字符串作为输入
  • 通过下推自动机进行字符串的 consume
  • 如果最终能够使得栈为空,那么就属于 PDA 表示的语言

Note:

  • 当机器停止运行时,栈可以是非空的
  • 尝试弹出一个空字符串会导致 “拒绝输入” 而不是报错

下推自动机举例2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

渐进式下推自动机(progressive push-down automata)

在这里插入图片描述

  • 当一个下推自动机的每个 transition 步骤都只消耗一个 input 符号,我们称之为 progressive 的下推自动机

确定性下推自动机(Deterministic Pushdown Automata)

  • 一个 DPDA 可以识别下面的 上下文无关语言
    在这里插入图片描述
  • 但是 DPDA 不能识别
    在这里插入图片描述
  • 因为 DPDA 无法知道中间位置在哪里;例如给定如下输入,DPDA 根本不知道从哪里开始 pop 数据
    在这里插入图片描述
  • DPDA 永远无法知道自己可以处理两种不同操作的位置;换言之,他每次只能处理一种情况。类似于 DFA

通过上下文无关文法构造下推自动机(CFG ⇒ \Rightarrow PDA)

  • 如果 CFG 的语法规则为 B → x A y B \rightarrow xAy BxAy,那么 B B B 将会被放在 PDA 的栈顶;而后使用 x A y xAy xAy 来替换栈中的 B B B 如图所示:
    在这里插入图片描述
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暖仔会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值