随笔-341  评论-2670  文章-0  trackbacks-0
    算法的具体说明可以看这里

    今天花了一个晚上完成并测试了从NFA到DFA的代码。NFA到DFA的主要过程就是构造出一个等价于NFA的状态机,使得从任何一个状态出去的状态转换都不具有相同的条件。这个约束就是“确定性”的含义,给定一个状态和一个输入,最多只能跳转到一个目标状态。于是知道了这个过程,代码就很好写了:

  1         Automaton::Ref NfaToDfa(Automaton::Ref source, IGroup<State*, State*>& dfaStateMap)
  2         {
  3             Automaton::Ref target=new Automaton;
  4             Group<Transition*, Transition*> nfaTransitions;
  5             CopyFrom(target->captureNames.Wrap(), source->captureNames.Wrap());
  6             State* startState=target->NewState();
  7             target->startState=startState;
  8             dfaStateMap.Add(startState, source->startState);
  9 
 10             for(int i=0;i<target->states.Count();i++)
 11             {
 12                 State* currentState=target->states[i].Obj();
 13                 nfaTransitions.Clear();
 14 
 15                 //对该DFA状态的所有等价NFA状态进行遍历
 16                 const IReadonlyList<State*>& nfaStates=dfaStateMap[currentState];
 17                 for(int j=0;j<nfaStates.Count();j++)
 18                 {
 19                     State* nfaState=nfaStates[j];
 20                     //对每一个NFA状态的所有转换进行遍历
 21                     for(int k=0;k<nfaState->transitions.Count();k++)
 22                     {
 23                         Transition* nfaTransition=nfaState->transitions[k];
 24                         //检查该NFA转换类型是否已经具有已经被记录
 25                         Transition* transitionClass=0;
 26                         for(int l=0;l<nfaTransitions.Keys().Count();l++)
 27                         {
 28                             Transition* key=nfaTransitions.Keys()[l];
 29                             if(AreEqual(key, nfaTransition))
 30                             {
 31                                 transitionClass=key;
 32                                 break;
 33                             }
 34                         }
 35                         //不存在则创建一个转换类型
 36                         if(transitionClass==0)
 37                         {
 38                             transitionClass=nfaTransition;
 39                         }
 40                         //注册转换
 41                         nfaTransitions.Add(transitionClass, nfaTransition);
 42                     }
 43                 }
 44 
 45                 //遍历所有种类的NFA转换
 46                 for(int j=0;j<nfaTransitions.Count();j++)
 47                 {
 48                     const IReadonlyList<Transition*>& transitionSet=nfaTransitions.GetByIndex(j);
 49                     //对所有转换的NFA目标状态集合进行排序
 50                     SortedList<State*> transitionTargets;
 51                     for(int l=0;l<transitionSet.Count();l++)
 52                     {
 53                         State* nfaState=transitionSet[l]->target;
 54                         if(!transitionTargets.Contains(nfaState))
 55                         {
 56                             transitionTargets.Add(nfaState);
 57                         }
 58                     }
 59                     //判断转换类的所有转换的NFA目标状态组成的集合是否已经有一个对应的DFA状态
 60                     State* dfaState=0;
 61                     for(int k=0;k<dfaStateMap.Count();k++)
 62                     {
 63                         //将DFA的等价NFA状态集合进行排序
 64                         SortedList<State*> relativeStates;
 65                         CopyFrom(relativeStates.Wrap(), dfaStateMap.GetByIndex(k));
 66                         //比较两者是否相等
 67                         if(relativeStates.Count()==transitionTargets.Count())
 68                         {
 69                             bool equal=true;
 70                             for(int l=0;l<relativeStates.Count();l++)
 71                             {
 72                                 if(relativeStates[l]!=transitionTargets[l])
 73                                 {
 74                                     equal=false;
 75                                     break;
 76                                 }
 77                             }
 78                             if(equal)
 79                             {
 80                                 dfaState=dfaStateMap.Keys()[k];
 81                                 break;
 82                             }
 83                         }
 84                     }
 85                     //不存在等价DFA状态则创建一个
 86                     if(!dfaState)
 87                     {
 88                         dfaState=target->NewState();
 89                         for(int k=0;k<transitionTargets.Count();k++)
 90                         {
 91                             dfaStateMap.Add(dfaState, transitionTargets[k]);
 92                             if(transitionTargets[k]->finalState)
 93                             {
 94                                 dfaState->finalState=true;
 95                             }
 96                         }
 97                     }
 98                     //将该转换复制到新状态机里
 99                     Transition* transitionClass=nfaTransitions.Keys()[j];
100                     Transition* newTransition=target->NewTransition(currentState, dfaState);
101                     newTransition->capture=transitionClass->capture;
102                     newTransition->index=transitionClass->index;
103                     newTransition->range=transitionClass->range;
104                     newTransition->type=transitionClass->type;
105                 }
106             }
107 
108             return target;
109         }

    这里频繁使用了Group和IGroup作为数据结构来计算。Group是一个多对多映射,也就是说Group<K, V>的内部结构等价于Map<K, List<V>>。从NFA到DFA转换的同时,这个函数还记录了每一个DFA对象所对应的NFA对象集合。

    接下来就要分两步走了,第一个先做纯匹配的正则表达式,然后接着做贪婪匹配(包含捕获、预查和指向捕获的匹配等高级功能)。根据Vczh Library++2.0的经验,纯匹配的正则表达式用来实现词法分析器的时候,不亚于纯手写的词法分析器,这一点令他的应用范围变广。
posted on 2009-11-03 08:34 陈梓瀚(vczh) 阅读(2712) 评论(8)  编辑 收藏 引用 所属分类: VL++3.0开发纪事

评论:
# re: Vczh Library++3.0之正则表达式引擎(从NFA到DFA) 2009-11-03 22:49 | 白开水
看到这个文章,突然感觉很怀念,真正把我编程带入门的文章。

转眼就两年了。

正则表达式引擎到了后面效率可能会卡在内存的吞吐上,一般的PC配置(这个一般我也不太确定),极限应该在30MB/S.

这个东西热爱计算机编程的人都该尝试去做下。非常考基本功。基本的数据结构,stack, avl tree, map, bit-vector, list都有牵涉,而算法那块也逃不出一般算法书的经典算法部分,编译原理也有部分涉及。假如你是个学生,又不知道该做点啥,那么这个东西,你该试着做做。

  回复  更多评论
  
# re: Vczh Library++3.0之正则表达式引擎(从NFA到DFA)[未登录] 2009-11-04 07:06 | L.S.Winson
话说你写这NFA到DFA转换写了多少次了。。。。我都觉得写这算法写得麻木了。。。
怎么又把你的VL重写么?  回复  更多评论
  
# re: Vczh Library++3.0之正则表达式引擎(从NFA到DFA) 2009-11-04 20:57 | 陈梓瀚(vczh)
@L.S.Winson
嗯,这个前面说过了,因为有重大升级,所以全部重写。  回复  更多评论
  
# re: Vczh Library++3.0之正则表达式引擎(从NFA到DFA) 2009-11-04 20:57 | 陈梓瀚(vczh)
@白开水
我也很怀念之前你那个正则表达式啊,嘿嘿  回复  更多评论
  
# re: Vczh Library++3.0之正则表达式引擎(从NFA到DFA) 2009-11-06 16:17 | zblc
@白开水
啊 你就是传说中的vczh的徒弟~收我为徒吧~  回复  更多评论
  
# re: Vczh Library++3.0之正则表达式引擎(从NFA到DFA) 2009-11-07 05:16 | 陈梓瀚(vczh)
# re: Vczh Library++3.0之正则表达式引擎(从NFA到DFA) 2009-11-08 01:12 | v.k
囧, 怎么你的徒弟走上C#了  回复  更多评论
  
# re: Vczh Library++3.0之正则表达式引擎(从NFA到DFA) 2009-11-08 07:35 | 陈梓瀚(vczh)
@v.k
人总是要多学点的  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理