lemon源码分析

2023-05-16

基本概念见上篇
《lemon源码基本概念整理》

1. follow集

对于如下4条产生式

          program ::= expr TK_SEM
          expr ::=  expr TK_IMPL expr
          expr ::=  TK_LPAREN expr TK_RPAREN
          expr ::=  TK_NEG expr

现在要求expr ::= TK_LPAREN expr TK_RPAREN*的follow集方法如下

      expr ::=  TK_LPAREN expr TK_RPAREN*
 =  expr ::=  TK_LPAREN expr* TK_RPAREN
  =  expr ::=  TK_LPAREN *expr TK_RPAREN
  =  expr ::=  *TK_LPAREN expr TK_RPAREN

上面这4条,后面是前面的bplp,这个见上篇文章的最后。同时前面也就是后面的fplp,代码如下
在这里插入图片描述
expr ::= *TK_LPAREN expr TK_RPAREN的follow集由下面这些项目决定

          program ::= *expr TK_SEM
          expr ::= * expr TK_IMPL expr
          expr ::=  expr TK_IMPL *expr
          expr ::=  TK_LPAREN *expr TK_RPAREN
          expr ::=  TK_NEG *expr

代码在Configlist_closure函数里
在这里插入图片描述
反正经过上面的步骤最终可以求得expr ::= TK_LPAREN expr TK_RPAREN的follow集是下面这3个
在这里插入图片描述
这个也符号我们对follow集的直观感受,那么follow集在哪里会用到呢?这个在规约时会用到,见下面代码
在这里插入图片描述
也就是
在产生式最右边时,会把这个项目的follow集加到归约动作里

2. 压缩动作链表

这个就是把本来这样的状态输出

State 9:
          expr ::= expr * TK_IMPL expr
      (1) expr ::= expr TK_IMPL expr *

                       TK_IMPL reduce 1
                        TK_SEM reduce 1
                     TK_RPAREN reduce 1

压缩成

State 12:
          expr ::= expr * TK_IMPL expr
      (1) expr ::= expr TK_IMPL expr *

                     {default} reduce 1

代码如下,在CompressTables函数里
在这里插入图片描述
这里之所以if( rp2==rbest ) continue;的原因是,绿框这个循环在rbest赋值之前就已经把rp的数量统计好了,当rbest赋值后已经是下一个大循环了,所以不必再对rbest做处理

3.类型联合

所有终结符和非终结符类型组成一个联合体,定义成一个YYMINORTYPE类型,代码在print_stack_union里,
在这里插入图片描述

4.动作数组

4.1 框架

首先定义一个ax数组,这个数组有2*nstate个元素,每2个元素分为终结符和非终结符关联绑定一个stp,代码如下
在这里插入图片描述
整体流程代码如下
在这里插入图片描述
首先肯定是遍历所有ax数组,获得状态stp,然后分为终结符和非终结符两个分支进行处理。这里值得注意的是,对于每个stp,先遍历所有的动作链表ap,同时执行acttab_action把动作数据放在pActtab->aLookahead里。执行完for循环后调用acttab_insert把该状态里的所有动作数据放在p->aAction里,并把pActtab->aLookahead清零
在这里插入图片描述

4.2 动作的数值

原先动作由struct action结构体表示,生成语法解析文件后会转换成一个整数。对于移进动作,动作取对应的状态编号。对于归约动作,动作数值取状态总数加对应的产生式编号,相关代码如下
在这里插入图片描述

4.3 每个状态的所有动作

每个状态的所有动作会放在pActtab->aLookahead里,每增加一个动作nLookahead加1,同时会记录该状态中动作关联的先行符的最小值和最大值,代码实现在acttab_action函数里
在这里插入图片描述
可以看到每个动作和先行符绑定在一起放在aLookahead里,aLookahead的每个元素是紧挨在一起的

4.4 所有状态的动作插入

每遍历完一个状态的所有动作后,会把aLookahead的动作数据转移到aAction数组里,因为aAction的数据会导入到yy_action里,只要传入当前状态和先行符就可以通过yy_action求得当前的动作,公式是

yy_action[ yy_shift_ofst[S] + X ]

在这里插入图片描述

代码实现在acttab_insert里,aAction数组的下标是先行符,一般来说数组里会有很多空闲,后一个状态的数据插入时会先查看能不能往空隙里插数据,如果能的话就像两把梳子对接起来,不行的话只能往数组的最后添加了
在这里插入图片描述
最后返回i - p->mnLookahead,这个值存放在stp->iTknOfst里,将来会导入yy_shift_ofst[S]数组,即每个状态的最小先行符在aAction数组里的起始位置
在这里插入图片描述
再来分析一下前面蓝框里的代码,这个代码有点莫名奇妙的

        for(j=0; j<p->nLookahead; j++){
          k = p->aLookahead[j].lookahead - p->mnLookahead + i;
          if( k<0 ) break;
          if( p->aAction[k].lookahead>=0 ) break;
        }
        if( j<p->nLookahead ) continue;
        for(j=0; j<p->nAction; j++){
          if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
        }
        if( j==p->nAction ){
          break;  /* Fits in empty slots */
        }

因为前面的for循环已经出来了,到这里说明已经找到空隙。 p->aAction[j].lookahead== j+p->mnLookahead-i这里的j绝对不可能是上面的k,因为
p->aAction[k].lookahead<0
k+p->mnLookahead-i>0
所以不可能满足p->aAction[j].lookahead==j+p->mnLookahead-i这个条件,那么这个j就不是新加入的动作,而是原来状态的动作,为什么原来的状态和现在的状态的最小先行符mnLookahead不能相同呢,这个还不知道原因

5.语法分析

lemon文件运行后会输出一个语法分析的.c文件,再来看看这个.c文件是怎么工作的
首先会根据先行符和当前的状态,找到对应的动作,代码如下
在这里插入图片描述
获得动作的值后,就可以判断是移进还是规约,进而到相应的函数里处理
在这里插入图片描述
yy_shift时会更新当前的状态
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

lemon源码分析 的相关文章

  • MAVROS 源码分析

    转载自 xff1a https blog csdn net SIR wkp article details 87861658 MAVROS 源码分析 SIR wkp 2019 02 21 17 52 53 2778 收藏 34 分类专栏 x
  • PX4源码分析6:位置解算模块需要掌握哪几个核心点?

    转载自 xff1a https blog csdn net XL MAX article details 105780717 PX4源码分析6 xff1a 位置结算模块需要掌握哪几个核心点 xff1f XL MAX 2020 04 27 0
  • LinkedList源码分析

    LinkedList源码分析 注意 本笔记分析对象为 Java8 版本 随版本不同 源码会发生变化 基本介绍与类图 LinkedList 同时实现了 List 接口和 Deque 对口 也就是收它既可以看作一个顺序容器 又可以看作一个队列
  • ViewModel源码分析

    首先 xff0c 还是先看一个例子 xff1a public class MyViewModel extends ViewModel private MutableLiveData lt List lt User gt gt users p
  • PX4源码分析6:位置结算模块需要掌握哪几个核心点?

    位置解算源码位置 xff1a local position estimator main cpp 核心点1 xff1a 在北东地坐标系里 xff0c 如何由准确加速度对飞机的三维速度和三维位置进行估计 xff1f 核心点2 xff1a 如图
  • 【5G核心网】free5GC Path Switch Request源码分析

    Path Switch Request 过程的目的是请求将 NG U 传输承载的下行链路终结点切换到新的终结点 Figure 8 4 4 2 1 Path switch request successful operation NG RAN
  • 【containerd 源码分析】containerd image pull 源码分析

    本文分析 containerd pull 镜像的分析过程 xff0c 包括 ctr image 命令行以及 containerd daemon 执行 过程 xff0c 也包含镜像 metadata xff0c content 等内容 1 执
  • Apache IoTDB’s UDF源码分析(1)

    目录 前言 命令行注册UDF函数 Create Function xxx as 34 全限定类名 34 语法分析 生成物理计划 执行物理计划进行函数注册 Select带有UDF函数的查询 前言 继上个月开始了Apache IoTDB的源码贡
  • lemon源码基本概念整理

    1 数据结构 1 1 字符串存储 定义一个x1a的全局变量 xff0c 存放 y文件经过词法分析器分割出来的字符串 span class token keyword struct span s x1 span class token pun
  • Hadoop源码分析——MapReduce输入和输出

    Hadoop中的MapReduce库支持集中不同的格式的输入数据 例如 xff0c 文本模式的输入数据的每一行被视为一个key value键值对 key是文件的偏移量 xff0c value是那一行的内容 另一种常见的格式是以key进行排序
  • PX4源码分析7_添加mavlink自定义消息

    一 自定义mavlink消息 xff1a 根据uorb消息 xff08 msg xff09 自定义mavlink消息 方法为利用mavlink generator工具在xml文件生成mavlink所需相应的头文件 二 发送自定义mavlin
  • Netty源码分析 (八)----- write过程 源码分析

    上一篇文章主要讲了netty的read过程 xff0c 本文主要分析一下write和writeAndFlush 主要内容 本文分以下几个部分阐述一个java对象最后是如何转变成字节流 xff0c 写到socket缓冲区中去的 pipelin
  • 【ROS】源码分析-消息订阅与发布

    说明 本文通过NodeHandle subscribe和Publication publish 源码作为入口 xff0c 来分析PubNode SubNode之间是网络连接是如何建立的 xff0c 消息是如何发布的 xff0c topic队
  • [JavaSE 源码分析] 关于HashMap的个人理解

    目录 HashMap是什么 HashMap的底层数据结构是什么 table容量为什么必须是二的倍数 table容量怎么做到二的倍数 Entry是怎样的结构 Node Entry在HashMap中的具体实现处理hash冲突的方法HashMap
  • 如何动态调试Python的第三方库

    注意 本文方法仅限于调试安装时附带py源码的库 如sklearn 引入 用sklearn中的sklearn feature extraction text TfidfTransformer来获取TF特征 但发现sklearn的计算结果与我手
  • Log4j2注入漏洞(CVE-2021-44228)万字深度剖析(四)—漏洞修复原理(2.15.0-RC1、2.15.0、2.16.0)

    系列文章 2 15 0之前版漏洞相关文章 Log4j2注入漏洞 CVE 2021 44228 万字深度剖析 一 开篇与基础知识 Log4j2注入漏洞 CVE 2021 44228 万字深度剖析 二 漏洞原理 Log4j2注入漏洞 CVE 2
  • Spring创建Bean的全过程(一)

    Spring测试环境搭建 Spring模块概览 Spring中八大模块 黑色表示该模块的jar包 也就是组件 例如我们想要使用IOC容器 也就是绿色的CoreContainer 我们需要导入Beans Core Context SpEL s
  • 【源码分析】zeebe actor模型源码解读

    zeebe actor 模型 如果有阅读过zeebe 源码的朋友一定能够经常看到actor run 之类的语法 那么这篇文章就围绕actor run 方法 说说zeebe actor 的模型 环境 zeebe release 8 1 14
  • Scanner 类 源码分析

    Scanner 类 一个简单的文本扫描器 可以使用正则表达式解析原始类型和字符串 A Scanner分隔符模式将输入打破到令牌 默认情况下匹配空格 然后可以使用各种next方法将得到的令牌转换成不同类型的值 Scanner sc new S
  • Golang 中实现注解功能的思路分析

    文章目录 注解的作用 一些实现注解的开源 Golang 工程 Golang 中实现注解的基本思路 第一步 源码词法分析 第二步 代码生成 第三步 自动执行 番外 Golang 中一种代替注解的方案 注解的作用 提到注解 需要短暂的说明其前世

随机推荐