      id_attr = pattern[0].attrs[0]
      assert id_attr.attr == ID
      return id_attr.value
  
  
  cdef int get_action(const TokenPatternC* pattern, const TokenC* token) nogil:
      lookahead = &pattern[1]
      for attr in pattern.attrs[:pattern.nr_attr]:
          if get_token_attr(token, attr.attr) != attr.value:
              if pattern.quantifier == ONE:
                  return REJECT
              elif pattern.quantifier == ZERO:
                  return ACCEPT if lookahead.nr_attr == 0 else ADVANCE
              elif pattern.quantifier in (ZERO_ONE, ZERO_PLUS):
                  return ACCEPT_PREV if lookahead.nr_attr == 0 else ADVANCE_ZERO
              else:
                  return PANIC
      if pattern.quantifier == ZERO:
          return REJECT
      elif lookahead.nr_attr == 0:
          return ACCEPT
      elif pattern.quantifier in (ONE, ZERO_ONE):
          return ADVANCE
      elif pattern.quantifier == ZERO_PLUS:
          # This is a bandaid over the 'shadowing' problem described here:
          # https://github.com/explosion/spaCy/issues/864
          next_action = get_action(lookahead, token)
          if next_action is REJECT:
              return REPEAT
          else:
              return ADVANCE_ZERO
      else:
          return PANIC
  
  
  def _convert_strings(token_specs, string_store):
      # Support 'syntactic sugar' operator '+', as combination of ONE, ZERO_PLUS
      operators = {'!': (ZERO,), '*': (ZERO_PLUS,), '+': (ONE, ZERO_PLUS),
                   '?': (ZERO_ONE,), '1': (ONE,)}
      tokens = []
 
</s> remove     operators = {'!': (ZERO,), '*': (ZERO_PLUS,), '+': (ONE, ZERO_PLUS),
                 '?': (ZERO_ONE,), '1': (ONE,)}
 </s> add     operators = {'*': (ZERO_PLUS,), '+': (ONE, ZERO_PLUS),
                 '?': (ZERO_ONE,), '1': (ONE,), '!': (ZERO,)} </s> remove     assert id_attr.attr == ID
 </s> add  </s> remove cdef attr_t get_pattern_key(const TokenPatternC* pattern) except 0:
 </s> add cdef attr_t get_pattern_key(const TokenPatternC* pattern) nogil: </s> remove def align(cand_words, gold_words):
    cost, edit_path = _min_edit_path(cand_words, gold_words)
    alignment = []
    i_of_gold = 0
    for move in edit_path:
        if move == 'M':
            alignment.append(i_of_gold)
            i_of_gold += 1
        elif move == 'S':
            alignment.append(None)
            i_of_gold += 1
        elif move == 'D':
            alignment.append(None)
        elif move == 'I':
            i_of_gold += 1
        else:
            raise Exception(move)
    return alignment


 </s> add  </s> remove         cdef vector[StateC] partials
        cdef int n_partials = 0
        cdef int q = 0
        cdef int i, token_i
        cdef const TokenC* token
        cdef StateC state
        matches = []
        for token_i in range(doc.length):
            token = &doc.c[token_i]
            q = 0
            # Go over the open matches, extending or finalizing if able.
            # Otherwise, we over-write them (q doesn't advance)
            for state in partials:
                action = get_action(state.second, token)
                if action == PANIC:
                    raise Exception("Error selecting action in matcher")
                while action == ADVANCE_ZERO:
                    state.second += 1
                    action = get_action(state.second, token)
                if action == PANIC:
                    raise Exception("Error selecting action in matcher")

                if action == REPEAT:
                    # Leave the state in the queue, and advance to next slot
                    # (i.e. we don't overwrite -- we want to greedily match
                    # more pattern.
                    q += 1
                elif action == REJECT:
                    pass
                elif action == ADVANCE:
                    partials[q] = state
                    partials[q].second += 1
                    q += 1
                elif action in (ACCEPT, ACCEPT_PREV):
                    # TODO: What to do about patterns starting with ZERO? Need
                    # to adjust the start position.
                    start = state.first
                    end = token_i+1 if action == ACCEPT else token_i
                    ent_id = state.second[1].attrs[0].value
                    label = state.second[1].attrs[1].value
                    matches.append((ent_id, start, end))

            partials.resize(q)
            # Check whether we open any new patterns on this token
            for pattern in self.patterns:
                action = get_action(pattern, token)
                if action == PANIC:
                    raise Exception("Error selecting action in matcher")
                while action == ADVANCE_ZERO:
                    pattern += 1
                    action = get_action(pattern, token)
                if action == REPEAT:
                    state.first = token_i
                    state.second = pattern
                    partials.push_back(state)
                elif action == ADVANCE:
                    # TODO: What to do about patterns starting with ZERO? Need
                    # to adjust the start position.
                    state.first = token_i
                    state.second = pattern + 1
                    partials.push_back(state)
                elif action in (ACCEPT, ACCEPT_PREV):
                    start = token_i
                    end = token_i+1 if action == ACCEPT else token_i
                    ent_id = pattern[1].attrs[0].value
                    label = pattern[1].attrs[1].value
                    matches.append((ent_id, start, end))
        # Look for open patterns that are actually satisfied
        for state in partials:
            while state.second.quantifier in (ZERO, ZERO_ONE, ZERO_PLUS):
                state.second += 1
                if state.second.nr_attr == 0:
                    start = state.first
                    end = len(doc)
                    ent_id = state.second.attrs[0].value
                    label = state.second.attrs[0].value
                    matches.append((ent_id, start, end))
        for i, (ent_id, start, end) in enumerate(matches):
            on_match = self._callbacks.get(ent_id)
 </s> add         matches = find_matches(&self.patterns[0], self.patterns.size(), doc)
        for i, (key, start, end) in enumerate(matches):
            on_match = self._callbacks.get(key, None)
      id_attr = pattern[0].attrs[0]
      assert id_attr.attr == ID
      return id_attr.value
  































  def _convert_strings(token_specs, string_store):
      # Support 'syntactic sugar' operator '+', as combination of ONE, ZERO_PLUS
      operators = {'!': (ZERO,), '*': (ZERO_PLUS,), '+': (ONE, ZERO_PLUS),
                   '?': (ZERO_ONE,), '1': (ONE,)}
      tokens = []
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 Revert "Merge branch 'develop' of https://github.com/explosion/spaCy into develop"

This reverts commit c9ba3d3c2dc7067cf8bd55f878cec45a8c6d73d4, reversing
changes made to 92c26a35d425d4e8ca1b805ea776ea10f5ded3df. 
spacy/matcher.pyx