def METHOD_NAME(self, node):
    """Compiles a node, recursively.
    This is one big switch on the node type.
    """
    # XXX Optimize certain Wildcard-containing-Wildcard patterns
    # that can be merged
    if node.type == self.syms.Matcher:
        node = node.children[0] # Avoid unneeded recursion
    if node.type == self.syms.Alternatives:
        # Skip the odd children since they are just '|' tokens
        alts = [self.METHOD_NAME(ch) for ch in node.children[::2]]
        if len(alts) == 1:
            return alts[0]
        p = pytree.WildcardPattern([[a] for a in alts], min=1, max=1)
        return p.optimize()
    if node.type == self.syms.Alternative:
        units = [self.METHOD_NAME(ch) for ch in node.children]
        if len(units) == 1:
            return units[0]
        p = pytree.WildcardPattern([units], min=1, max=1)
        return p.optimize()
    if node.type == self.syms.NegatedUnit:
        pattern = self.compile_basic(node.children[1:])
        p = pytree.NegatedPattern(pattern)
        return p.optimize()
    assert node.type == self.syms.Unit
    name = None
    nodes = node.children
    if len(nodes) >= 3 and nodes[1].type == token.EQUAL:
        name = nodes[0].value
        nodes = nodes[2:]
    repeat = None
    if len(nodes) >= 2 and nodes[-1].type == self.syms.Repeater:
        repeat = nodes[-1]
        nodes = nodes[:-1]
    # Now we've reduced it to: STRING | NAME [Details] | (...) | [...]
    pattern = self.compile_basic(nodes, repeat)
    if repeat is not None:
        assert repeat.type == self.syms.Repeater
        children = repeat.children
        child = children[0]
        if child.type == token.STAR:
            min = 0
            max = pytree.HUGE
        elif child.type == token.PLUS:
            min = 1
            max = pytree.HUGE
        elif child.type == token.LBRACE:
            assert children[-1].type == token.RBRACE
            assert  len(children) in (3, 5)
            min = max = self.get_int(children[1])
            if len(children) == 5:
                max = self.get_int(children[3])
        else:
            assert False
        if min != 1 or max != 1:
            pattern = pattern.optimize()
            pattern = pytree.WildcardPattern([[pattern]], min=min, max=max)
    if name is not None:
        pattern.name = name
    return pattern.optimize()