parameters: (self, leaves)
return_statement: return results
docstring: The main interface with the bottom matcher. The tree is
          traversed from the bottom using the constructed
          automaton. Nodes are only checked once as the tree is
          retraversed. When the automaton fails, we give it one more
          shot(in case the above tree matches as a whole with the
          rejected leaf), then we break for the next leaf. There is the
          special case of multiple arguments(see code comments) where we
          recheck the nodes
  
          Args:
             The leaves of the AST tree to be matched
  
          Returns:
             A dictionary of node matches with fixers as the keys
docstring_summary: The main interface with the bottom matcher. The tree is
          traversed from the bottom using the constructed
          automaton. Nodes are only checked once as the tree is
          retraversed. When the automaton fails, we give it one more
          shot(in case the above tree matches as a whole with the
          rejected leaf), then we break for the next leaf. There is the
          special case of multiple arguments(see code comments) where we
          recheck the nodes
docstring_tokens: The main interface with the bottom matcher . The tree is traversed from the bottom using the constructed automaton . Nodes are only checked once as the tree is retraversed . When the automaton fails we give it one more shot ( in case the above tree matches as a whole with the rejected leaf ) then we break for the next leaf . There is the special case of multiple arguments ( see code comments ) where we recheck the nodes
function: def run(self, leaves):
          """The main interface with the bottom matcher. The tree is
          traversed from the bottom using the constructed
          automaton. Nodes are only checked once as the tree is
          retraversed. When the automaton fails, we give it one more
          shot(in case the above tree matches as a whole with the
          rejected leaf), then we break for the next leaf. There is the
          special case of multiple arguments(see code comments) where we
          recheck the nodes
  
          Args:
             The leaves of the AST tree to be matched
  
          Returns:
             A dictionary of node matches with fixers as the keys
          """
          current_ac_node = self.root
          results = defaultdict(list)
          for leaf in leaves:
              current_ast_node = leaf
              while current_ast_node:
                  current_ast_node.was_checked = True
                  for child in current_ast_node.children:
                      # multiple statements, recheck
                      if isinstance(child, pytree.Leaf) and child.value == u";":
                          current_ast_node.was_checked = False
                          break
                  if current_ast_node.type == 1:
                      #name
                      node_token = current_ast_node.value
                  else:
                      node_token = current_ast_node.type
  
                  if node_token in current_ac_node.transition_table:
                      #token matches
                      current_ac_node = current_ac_node.transition_table[node_token]
                      for fixer in current_ac_node.fixers:
                          if not fixer in results:
                              results[fixer] = []
                          results[fixer].append(current_ast_node)
  
                  else:
                      #matching failed, reset automaton
                      current_ac_node = self.root
                      if (current_ast_node.parent is not None
                          and current_ast_node.parent.was_checked):
                          #the rest of the tree upwards has been checked, next leaf
                          break
  
                      #recheck the rejected node once from the root
                      if node_token in current_ac_node.transition_table:
                          #token matches
                          current_ac_node = current_ac_node.transition_table[node_token]
                          for fixer in current_ac_node.fixers:
                              if not fixer in results.keys():
                                  results[fixer] = []
                              results[fixer].append(current_ast_node)
  
                  current_ast_node = current_ast_node.parent
          return results
function_tokens: def run ( self , leaves ) : current_ac_node = self . root results = defaultdict ( list ) for leaf in leaves : current_ast_node = leaf while current_ast_node : current_ast_node . was_checked = True for child in current_ast_node . children : # multiple statements, recheck if isinstance ( child , pytree . Leaf ) and child . value == u";" : current_ast_node . was_checked = False break if current_ast_node . type == 1 : #name node_token = current_ast_node . value else : node_token = current_ast_node . type if node_token in current_ac_node . transition_table : #token matches current_ac_node = current_ac_node . transition_table [ node_token ] for fixer in current_ac_node . fixers : if not fixer in results : results [ fixer ] = [ ] results [ fixer ] . append ( current_ast_node ) else : #matching failed, reset automaton current_ac_node = self . root if ( current_ast_node . parent is not None and current_ast_node . parent . was_checked ) : #the rest of the tree upwards has been checked, next leaf break #recheck the rejected node once from the root if node_token in current_ac_node . transition_table : #token matches current_ac_node = current_ac_node . transition_table [ node_token ] for fixer in current_ac_node . fixers : if not fixer in results . keys ( ) : results [ fixer ] = [ ] results [ fixer ] . append ( current_ast_node ) current_ast_node = current_ast_node . parent return results