词法分析器Flex源码及算法分析(一)

 

  • 概念
  1. 正则表达式

 

  1. NFA

使用bison来解析输入文件,将输入文件的规则区中的正则表达式转换为NFA图

 

典型的NFA状态图可见下面的示例

  1. DFA

NFA到DFA的计算过程:

  1. 从NFA图中得到每个对应DFA状态的NFA状态集合c1(每次转换一步)
  2. 求c1的epsilon闭包,得到一个新的NFA状态集合c2
  3. 根据c2求出一个对应的DFA状态,对应的节点集合为c3

重复步骤a-c,直至所有的转换都已完成(已无新的NFA状态集合),整个构造过程是动态的,NFA状态集合是动态计算得到,一旦有新的NFA状态集合求出,对应的DFA状态也对应增加

  1. 等价类

等价类(Equivalence Classes)指的是将输入字符根据规则需要分类,例如下面的例子EC总数为8;而meta-等价类(Meta-Equivalence Classes)则是用于模型机的(template),是一种更抽象的分类,如下面的例子meta-EC总数为3

  1. 转换表和转换算法
  1. 转换矩阵

 

根据上面DFA计算结果以及所有的等价类,求出从一个DFA状态转换到另一DFA状态的转换矩阵,两个转换状态的转换边(转换条件)为EC

 

DFA状态集合和转换矩阵可见下面的示例

 

  1. Template 和proto

 

Template 和proto用于减少转换表项的空间,及加速查找和转换过程;

两种表项均为双向链表

 

Template 和proto表项可见下面的示例

 

  1. 四个一维数组

 

  1. def
  2. base
  3. chk
  4. nxt

 

  1. 快速转换算法

 

/* mk1tbl - create table entries for a state (or state fragment) which

 *            has only one out-transition

 */

 

void mk1tbl( state, sym, onenxt, onedef )

int state, sym, onenxt, onedef;

    {

    if ( firstfree < sym )

        firstfree = sym;

 

    while ( chk[firstfree] != 0 )

        if ( ++firstfree >= current_max_xpairs )

            expand_nxt_chk();

 

    base[state] = firstfree - sym;

    def[state] = onedef;

    chk[firstfree] = state;

    nxt[firstfree] = onenxt;

 

    if ( firstfree > tblend )

        {

        tblend = firstfree++;

 

        if ( firstfree >= current_max_xpairs )

            expand_nxt_chk();

        }

}

 

或者:

 

base[statenum] = tblbase;

def[statenum] = deflink;

 

for (i = minec; i <= maxec; ++i)

     if (state[i] != SAME_TRANS)

         if (state[i] != 0 || deflink != JAMSTATE) {

             nxt[tblbase + i] = state[i];

             chk[tblbase + i] = statenum;

         }

 

if (baseaddr == firstfree)

     /* Find next free slot in tables. */

     for (++firstfree; chk[firstfree] != 0; ++firstfree) ;

 

tblend = MAX (tblend, tbllast);

 

从以上的算法中可以看到firstfree= base[state]+sym(sym代表EC或者meta-EC),因此chk[firstfree] = chk[base[state]+sym] = state 如果成立,则表示存在这个转换表项,就将nxt[firstfree] = nxt[base[state]+sym] = onenxt 的值赋给next(下一表项)

 

  • 一个例子:
  1. Test.l文件内容:

%%                        

if                                                                                    printf("KEY: %s\n",yytext);   

[a-z][a-z0-9]*                                                       printf("ID: %s\n",yytext);

[0-9]+                                                                   printf("NUM: %s\n", yytext);

"/"                                                                        printf("OPER: %s\n",yytext);

"*"                                                                        printf("OPER: %s\n",yytext);

"/*"(.)*"*/"                                                         printf("ANNOTATION: %s\n",yytext);

%%

void main(int argc, char** argv)

{

            yylex();

}

 

int yywrap()

{

            return 1;

}

 

  1. 输出的各类表项:

 

G:\meterial\compiler\726lexYacc\flex-2.5.4a-1-src\src\flex\2.5.4a\flex-2.5.4a>flex.exe -T test.l

 

a.正则表达式

%%

1       if

2       [a-z][a-z0-9]*

3       [0-9]+

4       "\/"

5       "\*"

6       "\/\*"(.)*"\*\/"

7       End Marker

加上默认的“.”规则总共有7个规则

 

 

********** beginning dump of nfa with start state 38

state #    1    257:     0,    0

state #    2    257:     0,    0

state #    3    105:     4,    0

state #    4    102:     5,    0

state #    5    257:     0,    0  [1]

state #    6    257:     1,    3

state #    7     -1:    11,    0

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值