def step(self):
     if self.debug:
         print 'iteration', self.iteration
         print 'dna =', limit_string(self.dna)
         
     
     try:
         p = self.pattern()
         if self.debug:
             print 'pattern ', ''.join(map(str, p))
         t = self.template()
         if self.debug:
             print 'template', ''.join(map(str, t))
             
         for pp in p:
             self.pattern_freqs[type(pp)] += 1
         for tt in t:
             self.template_freqs[type(tt)] += 1
             
     finally:
         index = self.parser.index
         self.cost += index
         self.parser = None
         self.item_starts = []
         del self.dna[:index]
         
     self.matchreplace(p, t)
     self.parser = DNA_parser(self.dna, self.freqs)
     self.iteration += 1
     
     if self.debug:
         print 'len(rna) =', len(self.rna)
         print
 def matchreplace(self, pattern, template):
     e = []
     i = 0
     c = []
     dna = self.dna
     for p in pattern:
         tp = type(p)
         if tp is Base:
             self.cost += 1
             if dna[i] == p:
                 i += 1
             else:
                 if self.debug:
                     print 'failed match (base)'
                 return
             
         elif tp is Skip:
             i += p
             if i > len(dna):
                 if self.debug:
                     print 'failed match (skip)'
                 return
             
         elif tp is Search:
             j = next(kmp.find(dna, p, start=i), None)
             if j is not None:
                 self.cost += j + len(p) - i
                 i = j + len(p)
             else:
                 self.cost += len(dna) - i
                 if self.debug:
                     print 'failed match (search)'
                 return
             
         elif tp is OpenParen:
             c.append(i)
         elif tp is CloseParen:
             e.append((c.pop(), i))
         else:
             assert False, 'unknown pattern element'
     
     if self.debug:
         print 'succesful match of length', i
         for j, ee in enumerate(e):
             print 'e[{0}] = {1}'.format(j, limit_string(dna[ee[0]: ee[1]]))
     r = self.replacement(template, e)
     dna[:i] = r