U4_1 语法分析之自顶向下分析

2023-12-11 08:53

本文主要是介绍U4_1 语法分析之自顶向下分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、定义
    • 1、任务
    • 2、对比
    • 3、方法
    • 4、自顶向下面临问题
  • 二、自顶向下分析
    • 1、概念
    • 2、特点
    • 3、二义性问题
    • 4、左递归问题
      • 1)概念
      • 2)消除
      • 3)间接左递归
    • 5、回溯问题
      • 1)概念
      • 2)消除
      • 3)解决方法
    • 6、总结
  • 三、递归子程序法(递归下降分析法)
    • 1、概念
    • 2、具体做法
  • 四、LL(1)文法
    • 1、预备知识
      • 1)FIRST集的计算
      • 2)FOLLOW的算法
    • 2、LL(1)文法的概念
    • 3、分析
      • 1)组成
      • 2)分析表
      • 3)符号栈
      • 4)执行程序
  • 五、LL(k)文法

一、定义

1、任务

根据语法规则(即语言的文法),分析并识别出各种语法成分,如表达式、各种说明、各种语句、过程、函数等,并进行语法正确性检查

2、对比

词法分析:3型(正则文法) 词法分析:字符串
语法分析:2型(上下文无关文法) 语法分析:符号串

3、方法

  1. 自顶向下(Top-Down)分析:推导(Derivations)
    Z = > + S 则 S ∈ L ( G [ Z ] ) 否则 S ∉ L ( G [ Z ] ) Z =>^+ S \ \ \ \ 则 S \in L(G[Z]) \ \ \ 否则 S \notin L(G[Z]) Z=>+S    SL(G[Z])   否则S/L(G[Z])
  2. 自底向上(Bottom-Up)分析:规约(Reductions)
    Z < = + S 则 S ∈ L ( G [ Z ] ) 否则 S ∉ L ( G [ Z ] ) Z <=^+ S \ \ \ \ 则 S \in L(G[Z]) \ \ \ 否则 S \notin L(G[Z]) Z<=+S    SL(G[Z])   否则S/L(G[Z])

本节主要分析自顶向下方法

4、自顶向下面临问题

推导顺序:有多个“非终结符”,优先用哪个?
避免二义性:避免文法有多个可用规则。

问题:左递归问题+回溯问题
常见方法:递归子程序法+LL分析法

二、自顶向下分析

1、概念

给定符号串S,若预测是某一语法成分,则可根据该语法成分的文法,设法为S构造一棵语法树,若成功,则S最终被识别为某一语法成分,即 S ∈ L ( G [ Z ] ) S\in L(G[Z]) SL(G[Z]),其中G[Z]为某语法成分的文法。若不成功, 则 S ∉ L ( G [ Z ] ) S \notin L(G[Z]) S/L(G[Z])

2、特点

  1. 分析过程是带预测的,对输入符号串要预测属于什么语法成分,然后根据该语法成分的文法建立语法树。
  2. 分析过程是一种试探过程,是尽一切办法(选用不同规则) 来建立语法树的过程, 由于是试探过程, 难免有失败, 所以分析过程需进行回溯, 因此也称这种方法是带回溯的自顶向下分析方法
  3. 最左推导可以编写程序来实现, 但带溯的自顶向下分析方法在实际上价值不大, 效率低。

3、二义性问题

若对于一个文法的某一句子(或句型)存在两棵不同的语法树,则该文法是二义性文法,否则是无二义性文法。

若一个文法的某句子存在两个不同的规范推导,则该文法是二义性的,否则是无二义性的。

若一个文法的某规范句型的句柄不唯一,则该文法是二义性的,否则是无二义性的。

PS:正则文法也会有二义性,但是可判定的(通过转换为自动机)

文法的二义性是不可判定的,因此解决方法是提出一些限制条件,称为无二义性的充分条件,当文法满足这些条件时,就可以判定文法是无二义性的。

4、左递归问题

1)概念

令U是文法的任一非终结符,文法中有规则 U ∷ = U ⋅ ⋅ ⋅ ⋅ 或者 U = > U ⋅ ⋅ ⋅ U∷=U····或者U => U··· U::=U⋅⋅⋅⋅或者U=>U⋅⋅⋅

自顶向下分析的基本缺点是:不能处理具有左递归性的文法。
(如果在匹配输入串的过程中,假定正好轮到要用非终结符U直接匹配输入串,即要用U的右部符号串U¨¨去匹配,为了用U¨¨去匹配,又得用U去匹配,这样无限的循环下
去将无法终止。)

2)消除

  1. 使用扩充的BNF表示来改写文法
    (1) E ∷ = E + T ∣ T = > E ∷ = T E∷=E+T|T \ \ \ \ => E∷=T E::=E+TT    =>E::=T{ + T +T +T}
    (2) T ∷ = T ∗ F ∣ T / F ∣ F = > T ∷ = F T∷=T*F|T/F|F \ \ \ \ => T ∷=F T::=TFT/FF    =>T::=F{ ∗ F ∣ / F *F|/F F∣/F}

具体规则
提因子:若: U ∷ = x y ∣ x w ∣ … . ∣ x z 则可改写为: U ∷ = x ( y ∣ w ∣ … . ∣ z ) U∷=xy|xw|….|xz则可改写为:U∷=x(y|w|….|z) U::=xyxw.∣xz则可改写为:U::=x(yw.∣z)

若有文法规则: U ∷ = x ∣ y ∣ … … ∣ z ∣ U v 可以改写为 U ∷ = ( x ∣ y ∣ … … ∣ z ) U∷=x|y|……|z|Uv可以改写为U∷=(x|y|……|z) U::=xy……zUv可以改写为U::=(xy……z){ v v v}
其特点是:具有一个直接左递归的右部并位于最后,这表明该语法类U是由x或y……或z其后随有零个或多个v组成。
通过以上两条规则,就能消除文法的直接左递归,并保持文法的等价性。

  1. 将左递归规则改为右递归规则
    若: P ∷ = P a ∣ b P∷=Pa| b P::=Pab 则可改写为: P ∷ = b P ’     P ’ ∷ = a P ’ ∣ ε P ∷= bP’ \ \ \ \ P’ ∷= aP’| ε P::=bP    P::=aP’∣ε
    在这里插入图片描述

3)间接左递归

在这里插入图片描述
此时需要代入成直接左递归后再处理
在这里插入图片描述

  1. 检查规则R是否存在直接左递归 R ∷ = S a ∣ a R∷=Sa|a R::=Saa
  2. 把R代入Q的有关选择,改写规则Q Q ∷ = S a b ∣ a b ∣ b Q∷=Sab|ab|b Q::=Sababb
  3. 检查Q是否存在直接左递归
  4. 把Q代入S的右部选择 S ∷ = S a b c ∣ a b c ∣ b c ∣ c S∷=Sabc|abc|bc|c S::=Sabcabcbcc
  5. 消除S的直接左递归 S ∷ = ( a b c ∣ b c ∣ c ) S∷=(abc|bc|c) S::=(abcbcc){ a b c abc abc}

5、回溯问题

1)概念

概念:分析工作要部分地或全部地退回去。

造成回溯的条件:文法中,对于某个非终结符号的规则其右部有多个选择,并根据所面临的输入符号不能准确地确定所要的选择时,就可能出现回溯。

2)消除

对于 U : : = α 1 ∣ α 2 ∣ α 3 U::= α_1 | α_2 | α_3 U::=α1α2α3
定义: F I R S T ( α i ) = FIRST(α_i) = FIRST(αi)={ a ∣ α i = > ∗ a … , a ∈ V t a | α_i =>^* a…, a \in V_t aαi=>a,aVt}
为了避免回溯,对文法的要求是: F I R S T ( α i ) ∩ F I R S T ( α j ) = φ ( i ≠ j ) FIRST(α_i) ∩ FIRST(α_j)=φ (i\neq j) FIRST(αi)FIRST(αj)=φ(i=j)

3)解决方法

  1. 改写文法
    判断后若有相交,则需要把相交的部分提出放到高一级的文法中,如下例子:
    在这里插入图片描述
  2. 超前扫描(偷看)
    当文法不满足避免回溯的条件时,即各选择的首符号相交时,可以采用超前扫描的方法,即向前侦察各输入符号串的第二个、第三个符号来确定要选择的目标。

这种方法是通过向前多看几个符号来确定所选择的目标,从本质上来讲也有回溯的味道,因此比第一种方法费时,但是假读仅仅是向前侦察情况,不作任何语义处理工作

6、总结

为了在不采取超前扫描的前提下实现不带回溯的自顶向下分析,文法需要满足两个条件:

  1. 文法是非左递归的
  2. 对文法的任一非终结符,若其规则右部有多个选择时, 各选择所推出的终结符号串的首符号集合要两两不相交。

在上述条件下,就可以根据文法构造有效的、不带回溯的自顶向下分析器。

对于第二点,我们只有 F I R S T FIRST FIRST集合是不够的:
定义 F O L L O W ( A ) = FOLLOW(A)= FOLLOW(A)={ a ∣ Z = > ∗ … A a … , a ∈ V t a| Z=>^*…Aa…,a∈V_t aZ=>AaaVt}
A ∈ V n A \in V_n AVn 该集合称为A的后继符号集合
特殊地: 若 Z = > ∗ . . . A 若Z =>^*...A Z=>...A 则 # ∈ F O L L O W ( A ) ∈FOLLOW(A) FOLLOW(A)

不带回溯的充分必要条件是:对于G的
每一个非终结符A的任意两条规则 A : : = α ∣ β A::=α|β A::=αβ,下列条件成立:

  1. F I R S T ( α ) ∩ F I R S T ( β ) = Ф FIRST(α) ∩ FIRST(β) = Ф FIRST(α)FIRST(β)=Ф
  2. 若 β = = > ∗ ε , 则 F I R S T ( α ) ∩ F O L L O W ( A ) = Ф 若β==>^* ε, 则FIRST(α) ∩ FOLLOW(A) = Ф β==>ε,FIRST(α)FOLLOW(A)=Ф

三、递归子程序法(递归下降分析法)

1、概念

具体做法:对语法的每一个非终结符都编一个分析程序,当根据文法和当时的输入符号预测到要用某个非终结符去匹配输入串时,就调用该非终结符的分析程序

2、具体做法

在这里插入图片描述

  1. 检查并改写文法
    在这里插入图片描述
  2. 检查文法的递归性
    在这里插入图片描述
    因此,Z和U的分析程序要编成递归子程序
  3. 算法框图
    非终结符号的分析子程序的功能是:用规则右部符号串去匹配输入串
    在这里插入图片描述
    在这里插入图片描述

要注意子程序之间的接口,在程序编制时进入某个非终结符的分析程序时其所要分析的语法成分的第一个符号已读入sym中

递归子程序法对应的是最左推导过程

四、LL(1)文法

1、预备知识

1)FIRST集的计算

F I R S T ( α i ) = FIRST(α_i) = FIRST(αi)={ a ∣ α i = > ∗ a … , a ∈ V t a | α_i =>^* a…, a \in V_t aαi=>a,aVt}
α = > ∗ ε ,则 ε ∈ F I R S T ( α ) α=>^*ε,则ε \in FIRST(α) α=>ε,则εFIRST(α)

α = X 1 X 2 . . . X n , X i ∈ V n U V t (即 X i ∈ V ) α=X_1X_2...X_n, X_i∈V_n \ \ U \ \ V_t (即 X_i ∈V) α=X1X2...Xn,XiVn  U  Vt(即XiV)
首先求出组成α的每一个符号 X i X_i Xi的FIRST集合
在这里插入图片描述
在这里插入图片描述
注意:要顺序往下做,一旦不满足条件,过程就要中断进行
得到 F I R S T ( X i ) ,即可求出 F I R S T ( α ) FIRST(X_i),即可求出FIRST(α) FIRST(Xi),即可求出FIRST(α)

2)FOLLOW的算法

算法:连续使用以下规则,直至FOLLOW集合不再扩大
在这里插入图片描述

2、LL(1)文法的概念

第一个L:从左向右分析 (Left to right)
第二个L:产生“最左推导”(Left-most derivation)
k=1:向前查看“k=1”个符号,通过向前看1个符号就能够有效分析
无二义,无左递归,且能够消除回溯
因此判断LL(1)文法的条件就是为了在不采取超前扫描的前提下实现不带回溯的自顶向下分析所满足的条件
无左递归且
在这里插入图片描述

3、分析

1)组成

由三部分组成

  1. 分析表
  2. 执行程序 (总控程序)
  3. 符号栈 (分析栈)
    在这里插入图片描述
    在实际语言中,每一种语法成分都有确定的左右界符,为了研究问题方便,统一以‘#’表示。

2)分析表

在这里插入图片描述
在这里插入图片描述
算法:
在这里插入图片描述

3)符号栈

四种状态
在这里插入图片描述
在这里插入图片描述

4)执行程序

主要实现如下操作

  1. 把#和文法识别符号E推进栈, 读入下一个符号,重复下述过程直到正常结束或出错。
  2. 测定栈顶符号X和当前输入符号a,执行如下操作:
    KaTeX parse error: Expected 'EOF', got '#' at position 5: X=a=#̲,分析成功,停止。E匹配输入串成功。
    KaTeX parse error: Expected 'EOF', got '#' at position 5: X=a≠#̲,把X推出栈,再读入下一个符号。
    X ∈ V n X∈V_n XVn,查分析表M。
    注意a)中U在栈顶!

在这里插入图片描述
PS:文法没有 x→ε,则不需要计算 FOLLOW 集!!!!

五、LL(k)文法

LL(k)是无二义性的文法,其识别的语言都是确定型下推自动机所识别的语言,但反之不能保证一个确定型下推自动机与LL(k)等价。因此关系图如下:
一个无二义的CFG文法不一定能得到LL(k)文法
在这里插入图片描述

LL(k)文法总是一个LR(k)文法

这篇关于U4_1 语法分析之自顶向下分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/480135

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

关于MyISAM和InnoDB对比分析

《关于MyISAM和InnoDB对比分析》:本文主要介绍关于MyISAM和InnoDB对比分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录开篇:从交通规则看存储引擎选择理解存储引擎的基本概念技术原理对比1. 事务支持:ACID的守护者2. 锁机制:并发控制的艺

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb