'Compiles a node, recursively.
This is one big switch on the node type.'

def compile_node(self, node):

    if (node.type == self.syms.Matcher):
        node = node.children[0]
    if (node.type == self.syms.Alternatives):
        alts = [self.compile_node(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.compile_node(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)]
    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()
