U4_3 语法分析-自底向上分析-LR0/LR1/SLR分析

2024-01-01 09:12

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

文章目录

  • 一、LR分析法
    • 1、概念
    • 2、流程
    • 3、LR分析器结构及分析表构造
      • 1)结构
      • 2)一些概念
  • 二、LR(0)分析法
    • 1、流程
    • 2、分析动作
      • 1)移近
      • 2)归约(reduce)
    • 3、总结
      • 1)LR分析器
      • 2)构造DFA
      • 3)构造LR(0)的方法(三步)
    • 4、局限性
  • 三、LR(1)分析法
  • 四、SLR(1):简单LR分析法
    • 1、基本思想
    • 2、分析思路
      • 1)构建表
      • 2)SLR求ACTION表
    • 3、局限性
  • 五、彩蛋

一、LR分析法

1、概念

是一种自底向上的分析方法(1965年 D.Knuth 提出)。
L:从左向右分析 (left to right)
R:产生“最右推导”(right-most derivation)
k=0:不向前查看符号     k=1:向前查看1个符号
从左到右扫描(L)自底向上进行归约(Right-most Derivation)(一定是规范归约), 是自底向上分析方法的高度概括和集中
历史 + 展望 + 现状 => 句柄

2、流程

根据文法不断进行移进或者规约
在这里插入图片描述
规约后回退状态,且得到的终结符也需要回退
在这里插入图片描述

3、LR分析器结构及分析表构造

1)结构

状态栈、分析表、控制程序
在这里插入图片描述
栈顶状态概括了从分析开始到该状态的全部分析历史和展望信息

2)一些概念

符号串 X 1 X 2 . . . . . X m X_1X_2..... X_m X1X2.....Xm:从开始状态( S 0 S_0 S0)到当前状态( S m S_m Sm)所识别的规范句型的活前缀。

规范句型前缀: 将输入串的剩余部分与其连接起来就构成了规范句型。
如: x 1 x 2 . . . . . x m a i . . . a n x_1x_2..... x_ma_i... a_n x1x2.....xmai...an为规范句型( x i x_i xi已处理, a i a_i ai未处理)

对于句型 α β t αβt αβt β β β表示句柄, 如果 α β = u 1 u 2 … u r αβ= u_1u_2…u_r αβ=u1u2ur那么符号串 u 1 u 2 … u i ( 1 ≤ i ≤ r ) u_1u_2…u_i(1≤i≤r) u1u2ui(1ir)即是句型 α β t αβt αβt的活前缀。
在这里插入图片描述

活前缀: 若分析过程能够保证栈中符号串均是规范句型的前缀,则表示输入串已分析过的部分没有语法错误,所以称为规范句型的活前缀。

二、LR(0)分析法

1、流程

根据状态转移图得出状态转移表
在这里插入图片描述
状态栈:# S 0 x 1 S 1 x 2 . . . . . . x i − 1 S i − 1 x i S i S_0x_1S_1x_2...... x_{i-1}S_{i-1} x_iS_i S0x1S1x2......xi1Si1xiSi
S i − 1 S_{i-1} Si1—当前状态(栈顶状态)
x i x_i xi— 新的栈顶符号
S i S_i Si----新的栈顶状态(状态转移)

2、分析动作

1)移近

A C T I O N [ S i , a ] = s ACTION[S_i,a] = s ACTION[Si,a]=s (s表示 s h i f t shift shift,移进)
动作: 将 a a a推进栈,并设置新的栈顶状态 S j S_j Sj
S j = G O T O [ S i , a ] S_j= GOTO[S_i,a] Sj=GOTO[Si,a],将指针指向下一个输入符号

2)归约(reduce)

A C T I O N [ S i , a ] = r d ACTION [S_i,a] = r_d ACTION[Si,a]=rd (r表示 reduce,按规则d规约)
条件:某个项目集形如 A → β A→β Aβ.
动作: 将符号串β(假定长度为 n n n)连同状态从栈内
弹出, 把 A A A推进栈, 并设置新的栈顶状态 S j S_j Sj
S j = G O T O [ S i − n , A ] S_j= GOTO[S_{i-n},A] Sj=GOTO[Sin,A]

3、总结

1)LR分析器

构造LR分析器的关键是构造其分析表
构造LR分析表的方法是:

  1. 根据文法构造识别规范句型活前缀的有穷自动机DFA
  2. 由DFA构造分析表

2)构造DFA

在这里插入图片描述
构造DFA:
4. 确定 S S S集合,即 L R ( 0 ) LR(0) LR(0)项目集规范族,同时确定 S 0 S_0 S0
5. 确定状态转移函数GOTO

LR(0) 是DFA的状态集,其中每个状态又都是项目的集合

项目:文法G的每个产生式(规则)的右部添加一个圆点就构成一个项目
在这里插入图片描述

3)构造LR(0)的方法(三步)

  1. 将文法拓广
    目的:使构造出来的分析表只有一个接受状态,这是为了实现的方便。
    在这里插入图片描述
  2. 根据文法列出所有的项目
  3. 将有关项目组合成集合,即DFA中的状态;
    所有状态再组合成一个集合,即LR(0)项目集规范族

举例分析:
在这里插入图片描述
3 将有关项目组成项目集,所有项目集构成的集合即为LR(0)
为实现这一步,先定义:
• 项目集闭包closure
• 状态转移函数GOTO
在这里插入图片描述
在这里插入图片描述

4、局限性

会存在两种冲突,导致LR(0)识别不出来

  1. Shift-Reduce冲突
    在这里插入图片描述
  2. Reduce-Reduce冲突
    在这里插入图片描述
    因此需要采用偷看解决问题, L R ( 0 ) → L R ( 1 ) LR(0) → LR(1) LR0LR1

三、LR(1)分析法

通过“偷看”一个右侧符号,在遇到冲突时辅助决定。
思路:将状态区分的更加细致,构造LR(1)的状态机。

优点就是可以将状态区分的更加细致,构造LR(1)的状态机。
优势:功能强大!任何LR(0)、LL(1)、确定型CFL、LL(k)、LR(k)都有LR(1)的等价文法。

主要问题:状态爆炸,实用性差。

四、SLR(1):简单LR分析法

1、基本思想

由DFA构造出的SLR分析表,在造表时, 只需向前看一个符号就能确定分析的动作是移进还是归约,所以称为SLR(1)分析表,简称SLR分析表,使用SLR分析表的分析器叫SLR分析器,兼有LR(0)和LR(1)的优点,放弃一些精度。

在LR(0)的基础上,只针对冲突进行处理。

当发生 S-R冲突时,根据FOLLOW集合确定S还是R

2、分析思路

1)构建表

先构造LR(0)的自动机,GOTO表。

2)SLR求ACTION表

  1. 求出文法每个非终结符的FOLLOW集合
  2. 若项目 A → α . a β ∈ k A→α.aβ ∈k Aα.aβk,且 a ∈ V t a ∈V_t aVt ,则置 A C T I O N [ k , a ] = s ACTION[k,a] = s ACTION[k,a]=s (移进)
  3. 若项目 A → α . ∈ k A→ α.∈k Aα.k, 那么对输入符号 a a a,若 a ∈ F O L L O W ( A ) a∈FOLLOW(A) aFOLLOW(A),则置 A C T I O N [ k , a ] = r j ACTION[k,a]=r_j ACTION[k,a]=rj,其中 A → α A→ α Aα为文法 G ’ G’ G的第j个产生式。
  4. 若项目 E ’ → E . ∈ k E’→E.∈k EE.k, 则置 A C T I O N ACTION ACTION[ k , k , k,#] = a c c e p t =accept =accept
  5. 空白格,均置error
    在这里插入图片描述
    看到 f o l l o w follow follow应该做规约(已经跳出表达式了)

3、局限性

在这里插入图片描述
F O L L O W ( R ) FOLLOW(R) FOLLOW(R)中有=,应该做规约,但是碰到=,E中表达式应该移进,因此还是冲突。

对文法G,若应用上述算法所造出的分析表具有多重定义入口,分析动作不唯一, 则文法G就不是SLR的,需要用别的方法来构造分析表。如下图
在这里插入图片描述

五、彩蛋

L L ( k ) LL(k) LL(k)是无二义性的, L L ( k ) LL(k) LL(k)文法识别的语言都是确定型下推自动机所识别的语言,但反之,不能保证任何一个确定型下推自动机 D P D A DPDA DPDA L L ( k ) LL(k) LL(k)等价

LL(k)文法总是一个LR(k)文法 L L ( k ) LL(k) LL(k) L R ( k ) LR(k) LR(k)的子集
在这里插入图片描述
定义上看,LR(0), LR(1), LR(k), SLR(1), LALR(1)等,要求构造出来的分析表是“确定性”的,也就是分析表不允许存在冲突,无二义性!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这篇关于U4_3 语法分析-自底向上分析-LR0/LR1/SLR分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

MySQL中读写分离方案对比分析与选型建议

《MySQL中读写分离方案对比分析与选型建议》MySQL读写分离是提升数据库可用性和性能的常见手段,本文将围绕现实生产环境中常见的几种读写分离模式进行系统对比,希望对大家有所帮助... 目录一、问题背景介绍二、多种解决方案对比2.1 原生mysql主从复制2.2 Proxy层中间件:ProxySQL2.3

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1