# Path: py3kwarn2to3/btm_utils.py
# def reduce_tree(node, parent=None):
#     """
#     Internal function. Reduces a compiled pattern tree to an
#     intermediate representation suitable for feeding the
#     automaton. This also trims off any optional pattern elements(like
#     [a], a*).
#     """
# 
#     new_node = None
#     #switch on the node type
#     if node.type == syms.Matcher:
#         #skip
#         node = node.children[0]
# 
#     if node.type == syms.Alternatives:
#         #2 cases
#         if len(node.children) <= 2:
#             #just a single 'Alternative', skip this node
#             new_node = reduce_tree(node.children[0], parent)
#         else:
#             #real alternatives
#             new_node = MinNode(type=TYPE_ALTERNATIVES)
#             #skip odd children('|' tokens)
#             for child in node.children:
#                 if node.children.index(child) % 2:
#                     continue
#                 reduced = reduce_tree(child, new_node)
#                 if reduced is not None:
#                     new_node.children.append(reduced)
#     elif node.type == syms.Alternative:
#         if len(node.children) > 1:
# 
#             new_node = MinNode(type=TYPE_GROUP)
#             for child in node.children:
#                 reduced = reduce_tree(child, new_node)
#                 if reduced:
#                     new_node.children.append(reduced)
#             if not new_node.children:
#                 # delete the group if all of the children were reduced to None
#                 new_node = None
# 
#         else:
#             new_node = reduce_tree(node.children[0], parent)
# 
#     elif node.type == syms.Unit:
#         if (isinstance(node.children[0], pytree.Leaf) and
#             node.children[0].value == '('):
#             #skip parentheses
#             return reduce_tree(node.children[1], parent)
#         if ((isinstance(node.children[0], pytree.Leaf) and
#                node.children[0].value == '[')
#                or
#                (len(node.children)>1 and
#                hasattr(node.children[1], "value") and
#                node.children[1].value == '[')):
#             #skip whole unit if its optional
#             return None
# 
#         leaf = True
#         details_node = None
#         alternatives_node = None
#         has_repeater = False
#         repeater_node = None
#         has_variable_name = False
# 
#         for child in node.children:
#             if child.type == syms.Details:
#                 leaf = False
#                 details_node = child
#             elif child.type == syms.Repeater:
#                 has_repeater = True
#                 repeater_node = child
#             elif child.type == syms.Alternatives:
#                 alternatives_node = child
#             if hasattr(child, 'value') and child.value == '=': # variable name
#                 has_variable_name = True
# 
#         #skip variable name
#         if has_variable_name:
#             #skip variable name, '='
#             name_leaf = node.children[2]
#             if hasattr(name_leaf, 'value') and name_leaf.value == '(':
#                 # skip parenthesis
#                 name_leaf = node.children[3]
#         else:
#             name_leaf = node.children[0]
# 
#         #set node type
#         if name_leaf.type == token_labels.NAME:
#             #(python) non-name or wildcard
#             if name_leaf.value == 'any':
#                 new_node = MinNode(type=TYPE_ANY)
#             else:
#                 if hasattr(token_labels, name_leaf.value):
#                     new_node = MinNode(type=getattr(token_labels, name_leaf.value))
#                 else:
#                     new_node = MinNode(type=getattr(pysyms, name_leaf.value))
# 
#         elif name_leaf.type == token_labels.STRING:
#             #(python) name or character; remove the apostrophes from
#             #the string value
#             name = name_leaf.value.strip("'")
#             if name in tokens:
#                 new_node = MinNode(type=tokens[name])
#             else:
#                 new_node = MinNode(type=token_labels.NAME, name=name)
#         elif name_leaf.type == syms.Alternatives:
#             new_node = reduce_tree(alternatives_node, parent)
# 
#         #handle repeaters
#         if has_repeater:
#             if repeater_node.children[0].value == '*':
#                 #reduce to None
#                 new_node = None
#             elif repeater_node.children[0].value == '+':
#                 #reduce to a single occurrence i.e. do nothing
#                 pass
#             else:
#                 #TODO: handle {min, max} repeaters
#                 raise NotImplementedError
# 
#         #add children
#         if details_node and new_node is not None:
#             for child in details_node.children[1:-1]:
#                 #skip '<', '>' markers
#                 reduced = reduce_tree(child, new_node)
#                 if reduced is not None:
#                     new_node.children.append(reduced)
#     if new_node:
#         new_node.parent = parent
#     return new_node


import logging
import itertools
from collections import defaultdict
from . import pytree
from .btm_utils import reduce_tree
        from .pygram import python_symbols


class BMNode(object):
    """Class for a node of the Aho-Corasick automaton used in matching"""
    count = itertools.count()

    def __init__(self):
        self.transition_table = {}
        self.fixers = []
        self.id = next(BMNode.count)
        self.content = ''


class BottomMatcher(object):
    """The main matcher class. After instantiating the patterns should
    be added using the add_fixer method"""

    def __init__(self):
        self.match = set()
        self.root = BMNode()
        self.nodes = [self.root]
        self.fixers = []
        self.logger = logging.getLogger("RefactoringTool")

    def add_fixer(self, fixer):
        """Reduces a fixer's pattern tree to a linear path and adds it
        to the matcher(a common Aho-Corasick automaton). The fixer is
        appended on the matching states and called when they are
        reached"""
        self.fixers.append(fixer)

# Path: py3kwarn2to3/btm_utils.py
# def reduce_tree(node, parent=None):
#     """
#     Internal function. Reduces a compiled pattern tree to an
#     intermediate representation suitable for feeding the
#     automaton. This also trims off any optional pattern elements(like
#     [a], a*).
#     """
# 
#     new_node = None
#     #switch on the node type
#     if node.type == syms.Matcher:
#         #skip
#         node = node.children[0]
# 
#     if node.type == syms.Alternatives:
#         #2 cases
#         if len(node.children) <= 2:
#             #just a single 'Alternative', skip this node
#             new_node = reduce_tree(node.children[0], parent)
#         else:
#             #real alternatives
#             new_node = MinNode(type=TYPE_ALTERNATIVES)
#             #skip odd children('|' tokens)
#             for child in node.children:
#                 if node.children.index(child) % 2:
#                     continue
#                 reduced = reduce_tree(child, new_node)
#                 if reduced is not None:
#                     new_node.children.append(reduced)
#     elif node.type == syms.Alternative:
#         if len(node.children) > 1:
# 
#             new_node = MinNode(type=TYPE_GROUP)
#             for child in node.children:
#                 reduced = reduce_tree(child, new_node)
#                 if reduced:
#                     new_node.children.append(reduced)
#             if not new_node.children:
#                 # delete the group if all of the children were reduced to None
#                 new_node = None
# 
#         else:
#             new_node = reduce_tree(node.children[0], parent)
# 
#     elif node.type == syms.Unit:
#         if (isinstance(node.children[0], pytree.Leaf) and
#             node.children[0].value == '('):
#             #skip parentheses
#             return reduce_tree(node.children[1], parent)
#         if ((isinstance(node.children[0], pytree.Leaf) and
#                node.children[0].value == '[')
#                or
#                (len(node.children)>1 and
#                hasattr(node.children[1], "value") and
#                node.children[1].value == '[')):
#             #skip whole unit if its optional
#             return None
# 
#         leaf = True
#         details_node = None
#         alternatives_node = None
#         has_repeater = False
#         repeater_node = None
#         has_variable_name = False
# 
#         for child in node.children:
#             if child.type == syms.Details:
#                 leaf = False
#                 details_node = child
#             elif child.type == syms.Repeater:
#                 has_repeater = True
#                 repeater_node = child
#             elif child.type == syms.Alternatives:
#                 alternatives_node = child
#             if hasattr(child, 'value') and child.value == '=': # variable name
#                 has_variable_name = True
# 
#         #skip variable name
#         if has_variable_name:
#             #skip variable name, '='
#             name_leaf = node.children[2]
#             if hasattr(name_leaf, 'value') and name_leaf.value == '(':
#                 # skip parenthesis
#                 name_leaf = node.children[3]
#         else:
#             name_leaf = node.children[0]
# 
#         #set node type
#         if name_leaf.type == token_labels.NAME:
#             #(python) non-name or wildcard
#             if name_leaf.value == 'any':
#                 new_node = MinNode(type=TYPE_ANY)
#             else:
#                 if hasattr(token_labels, name_leaf.value):
#                     new_node = MinNode(type=getattr(token_labels, name_leaf.value))
#                 else:
#                     new_node = MinNode(type=getattr(pysyms, name_leaf.value))
# 
#         elif name_leaf.type == token_labels.STRING:
#             #(python) name or character; remove the apostrophes from
#             #the string value
#             name = name_leaf.value.strip("'")
#             if name in tokens:
#                 new_node = MinNode(type=tokens[name])
#             else:
#                 new_node = MinNode(type=token_labels.NAME, name=name)
#         elif name_leaf.type == syms.Alternatives:
#             new_node = reduce_tree(alternatives_node, parent)
# 
#         #handle repeaters
#         if has_repeater:
#             if repeater_node.children[0].value == '*':
#                 #reduce to None
#                 new_node = None
#             elif repeater_node.children[0].value == '+':
#                 #reduce to a single occurrence i.e. do nothing
#                 pass
#             else:
#                 #TODO: handle {min, max} repeaters
#                 raise NotImplementedError
# 
#         #add children
#         if details_node and new_node is not None:
#             for child in details_node.children[1:-1]:
#                 #skip '<', '>' markers
#                 reduced = reduce_tree(child, new_node)
#                 if reduced is not None:
#                     new_node.children.append(reduced)
#     if new_node:
#         new_node.parent = parent
#     return new_node


# Path: py3kwarn2to3/btm_matcher.py
import logging
import itertools
from collections import defaultdict
from . import pytree
from .btm_utils import reduce_tree
        from .pygram import python_symbols



class BMNode(object):
    """Class for a node of the Aho-Corasick automaton used in matching"""
    count = itertools.count()

    def __init__(self):
        self.transition_table = {}
        self.fixers = []
        self.id = next(BMNode.count)
        self.content = ''


class BottomMatcher(object):
    """The main matcher class. After instantiating the patterns should
    be added using the add_fixer method"""

    def __init__(self):
        self.match = set()
        self.root = BMNode()
        self.nodes = [self.root]
        self.fixers = []
        self.logger = logging.getLogger("RefactoringTool")

    def add_fixer(self, fixer):
        """Reduces a fixer's pattern tree to a linear path and adds it
        to the matcher(a common Aho-Corasick automaton). The fixer is
        appended on the matching states and called when they are
        reached"""
        self.fixers.append(fixer)

        tree = reduce_tree(fixer.pattern_tree)