快捷搜索: 王者荣耀 脱发

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

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的原始项目

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

经验分享 程序员 微信小程序 职场和发展