lemon源码基本概念整理

1 数据结构

1.1 字符串存储

定义一个x1a的全局变量,存放.y文件经过词法分析器分割出来的字符串

struct s_x1 {
  int size;               /* The number of available slots. */
                          /*   Must be a power of 2 greater than or */
                          /*   equal to 1 */
  int count;              /* Number of currently slots filled */
  struct s_x1node *tbl;  /* The data stored here */
  struct s_x1node **ht;  /* Hash table for lookups */
};

/* There is one instance of this structure for every data element
** in an associative array of type "x1".
*/
typedef struct s_x1node {
  const char *data;        /* The data */
  struct s_x1node *next;   /* Next entry with the same hash */
  struct s_x1node **from;  /* Previous link */
} x1node;

/* There is only one instance of the array, which is the following */
static struct s_x1 *x1a;

tbl是一个存放data的数组,ht是一个哈希数组,存放着tbl数据的地址,如果哈希表的key值相同,则插入到一个双向链表里,下面是往容器里存数据的代码
在这里插入图片描述

1.2 符号

符号用symbol结构体,即终结符和非终结符,存放在x2a容器里,结构和上面一样,代码在Symbol_insert里

1.3 rule

rule就是.y文件中的各条产生式,如下图
在这里插入图片描述
rule结构体如下
在这里插入图片描述
主要关注下nextlhs,这个链表把左边具有相同symbol的产生式链接在一起

1.4 config

这个结构就是把rule和要移进前的*再组成要给结构体,所有config放在一个x3a的容器里
在这里插入图片描述

1.5 state

state就是把config和action再整合成一个结构体,数据放在x4a容器,其中config包括基本项目和全部项目
在这里插入图片描述
直观的感受可以看.out文件
在这里插入图片描述
其中红框是是state,绿框和黑框都是config存放再cfg链表里,其中黑框是基本项目,存放再bp链表里

2 状态生成

入口函数在FindStates,先生成基本状态
在这里插入图片描述
这条产生式一般是第一条,就是最后归约的那一条

program ::= expr(A) TK_SEM(B).

然后就是getstate和buildshifts的相互递归调用,如果状态不存在的话则生成一个新状态,以1.5为例,传入的是黑框bp,然后调用Configlist_closure(lemp);生成所有绿框,最后再整合成红框state
在这里插入图片描述
这里看一下Configlist_closure的代码,注意方框框起来的地方,不要把循环体搞错了
在这里插入图片描述
这个i=dot+1的循环是针对rp的而不是针对newrp的,我第一次看的时候就在这里搞混了

fplp的作用在计算follow集的时候会用到,newfp是由cfp派生出来的,cfp中如果出现sp右边是空串的情况,那么算newfp时也要把cfp的follow集算上,这个看下求follow集的代码就知道了
在这里插入图片描述

3 移进

移进时的代码是buildshifts,在getstate的最后时候调用,进入buildshifts的时候,已经生成了第1.5节红框框起来的所有项目,buildshifts里有两层循环,这个代码非常难以理解
在这里插入图片描述
为了清晰起见再把1.5节的这张图贴一下
在这里插入图片描述
外层for循环遍历所有的项目,先取出*右边的符号,以第1个为例取出expr,内层for循环找到所有右边是expr的项目,去转移到新状态,这里是转到状态10,我们看下状态10的项目,果然符合预期

State 10:
          expr ::= expr * TK_IMPL expr
      (3) expr ::= TK_NEG expr *

                     {default} reduce 3

也就是说通过两个for循环把*右边的符合进行分组划分新状态。

来看看bplp的作用,从下面代码可以看到,newcfg和bcfp具有相同的rp,只不过newcfg的dot多了1,也就是在newcfg->bplp中记录移进到newcfg的原始项目
在这里插入图片描述

先写这么多吧,有空再把动作相关代码整理一下

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值