docs: def _get_features(self, i, context, prev, prev2):
          """Map tokens into a feature representation."""
          w = self.lexicon[context[i]]
          features = [
              'bias',
              'w:shape=%s' % w.shape,
              'w:lower=%s' % w.lower,
              'p1:tag=%s' % prev,
              'p2:tag=%s' % prev2,
              'p1:tag+w:lower=%s+%s' % (prev, w.lower),
              'p1:tag+p2:tag=%s+%s' % (prev, prev2),
          ]
          if w.like_number:
              features.append('w:like_number')
          elif w.is_punct:
              features.append('w:is_punct')
          elif w.like_url:
              features.append('w:like_url')
          else:
              features.extend([
                  'w:suffix2=%s' % w.lower[-2:],
                  'w:suffix3=%s' % w.lower[-3:],
                  'w:suffix4=%s' % w.lower[-4:],
                  'w:suffix5=%s' % w.lower[-5:],
                  'w:prefix1=%s' % w.lower[:1],
                  'w:prefix2=%s' % w.lower[:2],
                  'w:prefix3=%s' % w.lower[:3],
              ])
              if w.is_alpha:
                  features.append('w:is_alpha')
              elif w.is_hyphenated:
                  features.append('w:is_hyphenated')
              if w.is_upper:
                  features.append('w:is_upper')
              elif w.is_lower:
                  features.append('w:is_lower')
              elif w.is_title:
                  features.append('w:is_title')
          if self.clusters and w.cluster:
              features.extend([
                  'w:cluster4=%s' % w.cluster[:4],
                  'w:cluster6=%s' % w.cluster[:6],
                  'w:cluster10=%s' % w.cluster[:10],
                  'w:cluster20=%s' % w.cluster[:20],
              ])
          # Add features for previous tokens if present
          if i > 0:
              p1 = self.lexicon[context[i-1]]
              features.extend([
                  'p1:lower=%s' % p1.lower,
                  'p1:shape=%s' % p1.shape,
              ])
              if not (p1.like_number or p1.is_punct or p1.like_url):
                  features.append('p1:suffix3=%s' % p1.lower[-3:])
              if self.clusters and p1.cluster:
                  features.extend([
                      'p1:cluster4=%s' % p1.cluster[:4],
                      'p1:cluster6=%s' % p1.cluster[:6],
                      'p1:cluster10=%s' % p1.cluster[:10],
                      'p1:cluster20=%s' % p1.cluster[:20],
                  ])
              if i > 1:
                  p2 = self.lexicon[context[i-2]]
                  features.extend([
                      'p2:lower=%s' % p2.lower,
                      'p2:shape=%s' % p2.shape,
                  ])
                  if self.clusters and p2.cluster:
                      features.extend([
                          'p2:cluster4=%s' % p2.cluster[:4],
                          'p2:cluster6=%s' % p2.cluster[:6],
                          'p2:cluster10=%s' % p2.cluster[:10],
                          'p2:cluster20=%s' % p2.cluster[:20],
                      ])
          # Add features for next tokens if present
          end = len(context) - 1
          if i < end:
              n1 = self.lexicon[context[i+1]]
              features.extend([
                  'n1:lower=%s' % n1.lower,
                  'n1:shape=%s' % n1.shape
              ])
              if not (n1.like_number or n1.is_punct or n1.like_url):
                  features.append('n1:suffix3=%s' % n1.lower[-3:])
              if self.clusters and n1.cluster:
                  features.extend([
                      'n1:cluster4=%s' % n1.cluster[:4],
                      'n1:cluster6=%s' % n1.cluster[:6],
                      'n1:cluster10=%s' % n1.cluster[:10],
                      'n1:cluster20=%s' % n1.cluster[:20],
                  ])
              if i < end - 1:
                  n2 = self.lexicon[context[i+2]]
                  features.extend([
                      'n2:lower=%s' % n2.lower,
                      'n2:shape=%s' % n2.shape
                  ])
                  if self.clusters and n2.cluster:
                      features.extend([
                          'n2:cluster4=%s' % n2.cluster[:4],
                          'n2:cluster6=%s' % n2.cluster[:6],
                          'n2:cluster10=%s' % n2.cluster[:10],
                          'n2:cluster20=%s' % n2.cluster[:20],
                      ])
          # Add position features
          if i == 0:
              features.append('-firsttoken-')
          elif i == 1:
              features.append('-secondtoken-')
          elif i == end - 1:
              features.append('-secondlasttoken-')
          elif i == end:
              features.append('-lasttoken-')
          return features