docs: def tag(self, tokens):
          """Return a list of (token, tag) tuples for a given list of tokens."""
          if not self._loaded_model:
              self.load(self.model)
          tags = [None] * len(tokens)
          norm = self._normalize(tokens)
          length = len(norm)
          # A set of allowed indexes for matches to start or end at
          delims = [0] + [i for span in [m.span() for m in self.delimiters.finditer(norm)] for i in span] + [length]
          # Token indices
          token_at_index = []
          for i, t in enumerate(tokens):
              token_at_index.extend([i] * (len(self.lexicon[t].normalized) + 1))
          start_i = 0
          end_i = 1
          matches = {}
          next_start = end_i
          # TODO: This could be a little more efficient by skipping indexes forward to next delim points.
          while True:
              current = norm[start_i:end_i]
              if self._dawg.has_keys_with_prefix(current):
                  # print('%s:%s:%s' % (start_i, end_i, current))
                  # If the current span is in the dawg, and isn't followed by an alphanumeric character
                  if current in self._dawg and start_i in delims and end_i in delims:
                      # print(current)
                      # Subsequent longer matches with same start_i will overwrite values in matches dict
                      matches[start_i] = (start_i, end_i, current)
                      # We can skip forward to after this match next time we increment start_i
                      next_start = end_i
                  # Increment end_i provided we aren't already at the end of the input
                  if end_i < length:
                      end_i += 1
                      continue
              # Increment start_i provided we aren't already at the end of the input
              start_i = next_start
              if start_i >= length - 1:
                  break
              end_i = start_i + 1
              next_start = end_i
          # Apply matches as tags to the relevant tokens
          for start_i, end_i, current in matches.values():
              start_token = token_at_index[start_i]
              end_token = token_at_index[end_i]
              # Possible for match to start in 'I' token from prev match. Merge matches by not overwriting to 'B'.
              if not tags[start_token] == 'I-%s' % self.entity:
                  tags[start_token] = 'B-%s' % self.entity
              tags[start_token+1:end_token+1] = ['I-%s' % self.entity] * (end_token - start_token)
          tokentags = list(zip(tokens, tags))
          return tokentags