LCOV - code coverage report
Current view: top level - src - NFA.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 169 196 86.2 %
Date: 2010-12-13 Functions: 27 38 71.1 %
Branches: 75 110 68.2 %

           Branch data     Line data    Source code
       1                 :            : // $Id: NFA.cc 6219 2008-10-01 05:39:07Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "config.h"
       6                 :            : 
       7                 :            : #include "NFA.h"
       8                 :            : #include "EquivClass.h"
       9                 :            : 
      10                 :            : static int nfa_state_id = 0;
      11                 :            : 
      12                 :      55051 : NFA_State::NFA_State(int arg_sym, EquivClass* ec)
      13                 :            :         {
      14                 :      55051 :         sym = arg_sym;
      15                 :      55051 :         ccl = 0;
      16                 :      55051 :         accept = NO_ACCEPT;
      17                 :      55051 :         mark = 0;
      18                 :      55051 :         epsclosure = 0;
      19                 :      55051 :         id = ++nfa_state_id;
      20                 :            : 
      21                 :            :         // Fix up equivalence classes based on this transition.  Note that any
      22                 :            :         // character which has its own transition gets its own equivalence
      23                 :            :         // class.  Thus only characters which are only in character classes
      24                 :            :         // have a chance at being in the same equivalence class.  E.g. "a|b"
      25                 :            :         // puts 'a' and 'b' into two different equivalence classes.  "[ab]"
      26                 :            :         // puts them in the same equivalence class (barring other differences
      27                 :            :         // elsewhere in the input).
      28                 :            : 
      29 [ +  +  +  -  - :      55051 :         if ( ec && sym != SYM_EPSILON /* no associated symbol */ )
              + ][ #  # ]
      30                 :      18336 :                 ec->UniqueChar(sym);
      31                 :      55051 :         }
      32                 :            : 
      33                 :       4279 : NFA_State::NFA_State(CCL* arg_ccl)
      34                 :            :         {
      35                 :       4279 :         sym = SYM_CCL;
      36                 :       4279 :         ccl = arg_ccl;
      37                 :       4279 :         accept = NO_ACCEPT;
      38                 :       4279 :         mark = 0;
      39                 :       4279 :         id = ++nfa_state_id;
      40                 :       4279 :         epsclosure = 0;
      41                 :       4279 :         }
      42                 :            : 
      43                 :        442 : NFA_State::~NFA_State()
      44                 :            :         {
      45 [ +  + ][ #  # ]:       1101 :         for ( int i = 0; i < xtions.length(); ++i )
                 [ +  + ]
      46                 :        659 :                 Unref(xtions[i]);
      47 [ +  - ][ #  # ]:        442 :         }
                 [ -  + ]
      48                 :            : 
      49                 :      10998 : void NFA_State::AddXtionsTo(NFA_state_list* ns)
      50                 :            :         {
      51         [ +  + ]:      21996 :         for ( int i = 0; i < xtions.length(); ++i )
      52                 :      10998 :                 ns->append(xtions[i]);
      53                 :      10998 :         }
      54                 :            : 
      55                 :       2072 : NFA_State* NFA_State::DeepCopy()
      56                 :            :         {
      57         [ +  + ]:       2072 :         if ( mark )
      58                 :        230 :                 return mark;
      59                 :            : 
      60         [ +  + ]:       1842 :         NFA_State* copy = ccl ? new NFA_State(ccl) : new NFA_State(sym, 0);
      61                 :       1842 :         SetMark(copy);
      62                 :            : 
      63         [ +  + ]:       3272 :         for ( int i = 0; i < xtions.length(); ++i )
      64                 :       1430 :                 copy->AddXtion(xtions[i]->DeepCopy());
      65                 :            : 
      66                 :       2072 :         return copy;
      67                 :            :         }
      68                 :            : 
      69                 :       2072 : void NFA_State::ClearMarks()
      70                 :            :         {
      71         [ +  + ]:       2072 :         if ( mark )
      72                 :            :                 {
      73                 :       1842 :                 SetMark(0);
      74         [ +  + ]:       3272 :                 for ( int i = 0; i < xtions.length(); ++i )
      75                 :       1430 :                         xtions[i]->ClearMarks();
      76                 :            :                 }
      77                 :       2072 :         }
      78                 :            : 
      79                 :      11442 : NFA_state_list* NFA_State::EpsilonClosure()
      80                 :            :         {
      81         [ +  + ]:      11442 :         if ( epsclosure )
      82                 :      10783 :                 return epsclosure;
      83                 :            : 
      84                 :        659 :         epsclosure = new NFA_state_list;
      85                 :            : 
      86                 :        659 :         NFA_state_list states;
      87                 :        659 :         states.append(this);
      88                 :        659 :         SetMark(this);
      89                 :            : 
      90                 :            :         int i;
      91         [ +  + ]:      14876 :         for ( i = 0; i < states.length(); ++i )
      92                 :            :                 {
      93                 :      14217 :                 NFA_State* ns = states[i];
      94         [ +  + ]:      14217 :                 if ( ns->TransSym() == SYM_EPSILON )
      95                 :            :                         {
      96                 :       9318 :                         NFA_state_list* x = ns->Transitions();
      97         [ +  + ]:      22882 :                         for ( int j = 0; j < x->length(); ++j )
      98                 :            :                                 {
      99                 :      13564 :                                 NFA_State* nxt = (*x)[j];
     100         [ +  + ]:      13564 :                                 if ( ! nxt->Mark() )
     101                 :            :                                         {
     102                 :      13558 :                                         states.append(nxt);
     103                 :      13558 :                                         nxt->SetMark(nxt);
     104                 :            :                                         }
     105                 :            :                                 }
     106                 :            : 
     107         [ +  + ]:       9318 :                         if ( ns->Accept() != NO_ACCEPT )
     108                 :       9318 :                                 epsclosure->append(ns);
     109                 :            :                         }
     110                 :            : 
     111                 :            :                 else
     112                 :            :                         // Non-epsilon transition - keep it.
     113                 :       4899 :                         epsclosure->append(ns);
     114                 :            :                 }
     115                 :            : 
     116                 :            :         // Clear out markers.
     117         [ +  + ]:      14876 :         for ( i = 0; i < states.length(); ++i )
     118                 :      14217 :                 states[i]->SetMark(0);
     119                 :            : 
     120                 :            :         // Make it fit.
     121                 :        659 :         epsclosure->resize(0);
     122                 :            : 
     123                 :      11442 :         return epsclosure;
     124                 :            :         }
     125                 :            : 
     126                 :          0 : void NFA_State::Describe(ODesc* d) const
     127                 :            :         {
     128                 :          0 :         d->Add("NFA state");
     129                 :          0 :         }
     130                 :            : 
     131                 :          0 : void NFA_State::Dump(FILE* f)
     132                 :            :         {
     133         [ #  # ]:          0 :         if ( mark )
     134                 :          0 :                 return;
     135                 :            : 
     136                 :          0 :         fprintf(f, "NFA state %d, sym = %d, accept = %d:\n", id, sym, accept);
     137                 :            : 
     138         [ #  # ]:          0 :         for ( int i = 0; i < xtions.length(); ++i )
     139                 :          0 :                 fprintf(f, "\ttransition to %d\n", xtions[i]->ID());
     140                 :            : 
     141                 :          0 :         SetMark(this);
     142         [ #  # ]:          0 :         for ( int i = 0; i < xtions.length(); ++i )
     143                 :          0 :                 xtions[i]->Dump(f);
     144                 :            :         }
     145                 :            : 
     146                 :          0 : unsigned int NFA_State::TotalMemoryAllocation() const
     147                 :            :         {
     148                 :            :         return padded_sizeof(*this)
     149                 :            :                 + xtions.MemoryAllocation() - padded_sizeof(xtions)
     150         [ #  # ]:          0 :                 + (epsclosure ? epsclosure->MemoryAllocation() : 0);
     151                 :            :         }
     152                 :            : 
     153                 :      24784 : NFA_Machine::NFA_Machine(NFA_State* first, NFA_State* final)
     154                 :            :         {
     155                 :      24784 :         first_state = first;
     156 [ +  + ][ #  # ]:      24784 :         final_state = final ? final : first;
     157                 :      24784 :         eol = bol = 0;
     158                 :      24784 :         }
     159                 :            : 
     160                 :      19590 : NFA_Machine::~NFA_Machine()
     161                 :            :         {
     162                 :      19590 :         Unref(first_state);
     163 [ +  - ][ #  # ]:      19590 :         }
                 [ #  # ]
     164                 :            : 
     165                 :       4490 : void NFA_Machine::InsertEpsilon()
     166                 :            :         {
     167                 :       4490 :         NFA_State* eps = new EpsilonState();
     168                 :       4490 :         eps->AddXtion(first_state);
     169                 :       4490 :         first_state = eps;
     170                 :       4490 :         }
     171                 :            : 
     172                 :      26383 : void NFA_Machine::AppendEpsilon()
     173                 :            :         {
     174                 :      26383 :         AppendState(new EpsilonState());
     175                 :      26383 :         }
     176                 :            : 
     177                 :        444 : void NFA_Machine::AddAccept(int accept_val)
     178                 :            :         {
     179                 :            :         // Hang the accepting number off an epsilon state.  If it is associated
     180                 :            :         // with a state that has a non-epsilon out-transition, then the state
     181                 :            :         // will accept BEFORE it makes that transition, i.e., one character
     182                 :            :         // too soon.
     183                 :            : 
     184         [ +  + ]:        444 :         if ( final_state->TransSym() != SYM_EPSILON )
     185                 :         96 :                 AppendState(new EpsilonState());
     186                 :            : 
     187                 :        444 :         final_state->SetAccept(accept_val);
     188                 :        444 :         }
     189                 :            : 
     190                 :        212 : void NFA_Machine::LinkCopies(int n)
     191                 :            :         {
     192         [ +  + ]:        212 :         if ( n <= 0 )
     193                 :        170 :                 return;
     194                 :            : 
     195                 :            :         // Make all the copies before doing any appending, otherwise
     196                 :            :         // subsequent DuplicateMachine()'s will include the extra
     197                 :            :         // copies!
     198                 :         42 :         NFA_Machine** copies = new NFA_Machine*[n];
     199                 :            : 
     200                 :            :         int i;
     201         [ +  + ]:        176 :         for ( i = 0; i < n; ++i )
     202                 :        134 :                 copies[i] = DuplicateMachine();
     203                 :            : 
     204         [ +  + ]:        176 :         for ( i = 0; i < n; ++i )
     205                 :        134 :                 AppendMachine(copies[i]);
     206                 :            : 
     207         [ +  - ]:        212 :         delete [] copies;
     208                 :            :         }
     209                 :            : 
     210                 :        642 : NFA_Machine* NFA_Machine::DuplicateMachine()
     211                 :            :         {
     212                 :        642 :         NFA_State* new_first_state = first_state->DeepCopy();
     213                 :        642 :         NFA_Machine* new_m = new NFA_Machine(new_first_state, final_state->Mark());
     214                 :        642 :         first_state->ClearMarks();
     215                 :            : 
     216                 :        642 :         return new_m;
     217                 :            :         }
     218                 :            : 
     219                 :      31233 : void NFA_Machine::AppendState(NFA_State* s)
     220                 :            :         {
     221                 :      31233 :         final_state->AddXtion(s);
     222                 :      31233 :         final_state = s;
     223                 :      31233 :         }
     224                 :            : 
     225                 :      19586 : void NFA_Machine::AppendMachine(NFA_Machine* m)
     226                 :            :         {
     227                 :      19586 :         AppendEpsilon();
     228                 :      19586 :         final_state->AddXtion(m->FirstState());
     229                 :      19586 :         final_state = m->FinalState();
     230                 :            : 
     231                 :      19586 :         Ref(m->FirstState());        // so states stay around after the following
     232                 :      19586 :         Unref(m);
     233                 :      19586 :         }
     234                 :            : 
     235                 :       4490 : void NFA_Machine::MakeOptional()
     236                 :            :         {
     237                 :       4490 :         InsertEpsilon();
     238                 :       4490 :         AppendEpsilon();
     239                 :       4490 :         first_state->AddXtion(final_state);
     240                 :       4490 :         Ref(final_state);
     241                 :       4490 :         }
     242                 :            : 
     243                 :       2307 : void NFA_Machine::MakePositiveClosure()
     244                 :            :         {
     245                 :       2307 :         AppendEpsilon();
     246                 :       2307 :         final_state->AddXtion(first_state);
     247                 :       2307 :         Ref(first_state);
     248                 :       2307 :         }
     249                 :            : 
     250                 :        188 : void NFA_Machine::MakeRepl(int lower, int upper)
     251                 :            :         {
     252                 :        188 :         NFA_Machine* dup = 0;
     253 [ +  + ][ +  + ]:        188 :         if ( upper > lower || upper == NO_UPPER_BOUND )
     254                 :        182 :                 dup = DuplicateMachine();
     255                 :            : 
     256                 :        188 :         LinkCopies(lower - 1);
     257                 :            : 
     258         [ +  + ]:        188 :         if ( upper == NO_UPPER_BOUND )
     259                 :            :                 {
     260                 :         12 :                 dup->MakeClosure();
     261                 :         12 :                 AppendMachine(dup);
     262                 :         12 :                 return;
     263                 :            :                 }
     264                 :            : 
     265         [ +  + ]:        684 :         while ( upper > lower )
     266                 :            :                 {
     267                 :            :                 NFA_Machine* dup2;
     268         [ +  + ]:        496 :                 if ( --upper == lower )
     269                 :            :                         // Don't need "dup" for any further copies
     270                 :        170 :                         dup2 = dup;
     271                 :            :                 else
     272                 :        326 :                         dup2 = dup->DuplicateMachine();
     273                 :            : 
     274                 :        496 :                 dup2->MakeOptional();
     275                 :        496 :                 AppendMachine(dup2);
     276                 :            :                 }
     277                 :            :         }
     278                 :            : 
     279                 :          0 : void NFA_Machine::Describe(ODesc* d) const
     280                 :            :         {
     281                 :          0 :         d->Add("NFA machine");
     282                 :          0 :         }
     283                 :            : 
     284                 :          0 : void NFA_Machine::Dump(FILE* f)
     285                 :            :         {
     286                 :          0 :         first_state->Dump(f);
     287                 :          0 :         first_state->ClearMarks();
     288                 :          0 :         }
     289                 :            : 
     290                 :          0 : void NFA_Machine::DumpStats(FILE* f)
     291                 :            :         {
     292                 :          0 :         fprintf(f, "highest NFA state ID is %d\n", nfa_state_id);
     293                 :          0 :         }
     294                 :            : 
     295                 :       2377 : NFA_Machine* make_alternate(NFA_Machine* m1, NFA_Machine* m2)
     296                 :            :         {
     297         [ -  + ]:       2377 :         if ( ! m1 )
     298                 :          0 :                 return m2;
     299         [ -  + ]:       2377 :         if ( ! m2 )
     300                 :          0 :                 return m1;
     301                 :            : 
     302                 :       2377 :         NFA_State* first = new EpsilonState();
     303                 :       2377 :         NFA_State* last = new EpsilonState();
     304                 :            : 
     305                 :       2377 :         first->AddXtion(m1->FirstState());
     306                 :       2377 :         first->AddXtion(m2->FirstState());
     307                 :            : 
     308                 :       2377 :         m1->AppendState(last);
     309                 :       2377 :         m2->AppendState(last);
     310                 :       2377 :         Ref(last);
     311                 :            : 
     312                 :       2377 :         return new NFA_Machine(first, last);
     313                 :            :         }
     314                 :            : 
     315                 :            : 
     316                 :       1082 : NFA_state_list* epsilon_closure(NFA_state_list* states)
     317                 :            :         {
     318                 :            :         // We just keep one of this as it may get quite large.
     319 [ +  + ][ +  - ]:       1084 :         static IntSet closuremap;
                 [ #  # ]
     320                 :       1082 :         closuremap.Clear();
     321                 :            : 
     322                 :       1082 :         NFA_state_list* closure = new NFA_state_list;
     323                 :            : 
     324         [ +  + ]:      12524 :         for ( int i = 0; i < states->length(); ++i )
     325                 :            :                 {
     326                 :      11442 :                 NFA_state_list* stateclosure = (*states)[i]->EpsilonClosure();
     327                 :            : 
     328         [ +  + ]:      47651 :                 for ( int j = 0; j < stateclosure->length(); ++j )
     329                 :            :                         {
     330                 :      36209 :                         NFA_State* ns = (*stateclosure)[j];
     331         [ +  + ]:      36209 :                         if ( ! closuremap.Contains(ns->ID()) )
     332                 :            :                                 {
     333                 :      35933 :                                 closuremap.Insert(ns->ID());
     334                 :      35933 :                                 closure->sortedinsert(ns, NFA_state_cmp_neg);
     335                 :            :                                 }
     336                 :            :                         }
     337                 :            :                 }
     338                 :            : 
     339                 :            :         // Make it fit.
     340                 :       1082 :         closure->resize(0);
     341                 :            : 
     342         [ +  - ]:       1082 :         delete states;
     343                 :            : 
     344                 :       1082 :         return closure;
     345                 :            :         }
     346                 :            : 
     347                 :      82094 : int NFA_state_cmp_neg(const void* v1, const void* v2)
     348                 :            :         {
     349                 :      82094 :         const NFA_State* n1 = (const NFA_State*) v1;
     350                 :      82094 :         const NFA_State* n2 = (const NFA_State*) v2;
     351                 :            : 
     352         [ +  + ]:      82094 :         if ( n1->ID() < n2->ID() )
     353                 :      32894 :                 return -1;
     354         [ -  + ]:      49200 :         else if ( n1->ID() == n2->ID() )
     355                 :          0 :                 return 0;
     356                 :            :         else
     357                 :      82094 :                 return 1;
     358 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8