183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Copyright 2006 Google, Inc. All Rights Reserved.
283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Licensed to PSF under a Contributor Agreement.
383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""
583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehPython parse tree definitions.
683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThis is a very concrete parse tree; we need to keep every token and
883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieheven the comments and whitespace between tokens.
983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThere's also a pattern matching implementation here.
1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""
1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh__author__ = "Guido van Rossum <guido@python.org>"
1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport sys
1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport warnings
1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom StringIO import StringIO
1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehHUGE = 0x7FFFFFFF  # maximum repeat count, default max
2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_type_reprs = {}
2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef type_repr(type_num):
2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    global _type_reprs
2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if not _type_reprs:
2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        from .pygram import python_symbols
2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # printing tokens is possible but not as useful
2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # from .pgen2 import token // token.__dict__.items():
2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for name, val in python_symbols.__dict__.items():
2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if type(val) == int: _type_reprs[val] = name
3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    return _type_reprs.setdefault(type_num, type_num)
3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Base(object):
3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Abstract base class for Node and Leaf.
3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    This provides some default functionality and boilerplate using the
3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    template pattern.
3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    A node may be a subnode of at most one parent.
4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # Default values for instance variables
4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    type = None    # int: token number (< 256) or symbol number (>= 256)
4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    parent = None  # Parent node pointer, or None
4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    children = ()  # Tuple of subnodes
4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    was_changed = False
4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    was_checked = False
4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __new__(cls, *args, **kwds):
5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Constructor that prevents Base from being instantiated."""
5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert cls is not Base, "Cannot instantiate Base"
5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return object.__new__(cls)
5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __eq__(self, other):
5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Compare two nodes for equality.
5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This calls the method _eq().
6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.__class__ is not other.__class__:
6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return NotImplemented
6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._eq(other)
6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    __hash__ = None # For Py3 compatibility.
6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __ne__(self, other):
6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Compare two nodes for inequality.
7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This calls the method _eq().
7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.__class__ is not other.__class__:
7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return NotImplemented
7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return not self._eq(other)
7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _eq(self, other):
7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Compare two nodes for equality.
8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This is called by __eq__ and __ne__.  It is only called if the two nodes
8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        have the same type.  This must be implemented by the concrete subclass.
8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Nodes should be considered equal if they have the same structure,
8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ignoring the prefix string and other context information.
8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise NotImplementedError
8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def clone(self):
8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Return a cloned (deep) copy of self.
9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This must be implemented by the concrete subclass.
9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise NotImplementedError
9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def post_order(self):
9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Return a post-order iterator for the tree.
9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This must be implemented by the concrete subclass.
10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise NotImplementedError
10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def pre_order(self):
10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Return a pre-order iterator for the tree.
10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This must be implemented by the concrete subclass.
10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise NotImplementedError
11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def set_prefix(self, prefix):
11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Set the prefix for the node (see Leaf class).
11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        DEPRECATED; use the prefix property directly.
11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        warnings.warn("set_prefix() is deprecated; use the prefix property",
11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                      DeprecationWarning, stacklevel=2)
12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.prefix = prefix
12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_prefix(self):
12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Return the prefix for the node (see Leaf class).
12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        DEPRECATED; use the prefix property directly.
12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        warnings.warn("get_prefix() is deprecated; use the prefix property",
12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                      DeprecationWarning, stacklevel=2)
13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.prefix
13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def replace(self, new):
13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Replace this node with a new one in the parent."""
13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert self.parent is not None, str(self)
13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert new is not None
13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not isinstance(new, list):
13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            new = [new]
13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        l_children = []
13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        found = False
14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for ch in self.parent.children:
14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if ch is self:
14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                assert not found, (self.parent.children, self, new)
14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if new is not None:
14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    l_children.extend(new)
14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                found = True
14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                l_children.append(ch)
14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert found, (self.children, self, new)
14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.parent.changed()
15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.parent.children = l_children
15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for x in new:
15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            x.parent = self.parent
15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.parent = None
15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_lineno(self):
15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return the line number which generated the invocant node."""
15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        node = self
15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        while not isinstance(node, Leaf):
15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not node.children:
16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return
16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            node = node.children[0]
16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return node.lineno
16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def changed(self):
16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.parent:
16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.parent.changed()
16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.was_changed = True
16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def remove(self):
17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Remove the node from the tree. Returns the position of the node in its
17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        parent's children before it was removed.
17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.parent:
17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for i, node in enumerate(self.parent.children):
17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if node is self:
17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    self.parent.changed()
17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    del self.parent.children[i]
17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    self.parent = None
18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    return i
18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    @property
18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def next_sibling(self):
18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The node immediately following the invocant in their parent's children
18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        list. If the invocant does not have a next sibling, it is None
18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.parent is None:
18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Can't use index(); we need to test by identity
19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for i, child in enumerate(self.parent.children):
19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if child is self:
19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                try:
19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    return self.parent.children[i+1]
19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                except IndexError:
19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    return None
19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    @property
20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def prev_sibling(self):
20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The node immediately preceding the invocant in their parent's children
20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        list. If the invocant does not have a previous sibling, it is None.
20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.parent is None:
20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Can't use index(); we need to test by identity
20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for i, child in enumerate(self.parent.children):
21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if child is self:
21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if i == 0:
21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    return None
21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return self.parent.children[i-1]
21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def leaves(self):
21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for child in self.children:
21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for x in child.leaves():
21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                yield x
21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def depth(self):
22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.parent is None:
22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return 0
22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return 1 + self.parent.depth()
22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_suffix(self):
22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Return the string immediately following the invocant node. This is
22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        effectively equivalent to node.next_sibling.prefix
22983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
23083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        next_sib = self.next_sibling
23183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if next_sib is None:
23283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return u""
23383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return next_sib.prefix
23483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
23583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if sys.version_info < (3, 0):
23683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def __str__(self):
23783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return unicode(self).encode("ascii")
23883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
23983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Node(Base):
24083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
24183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Concrete implementation for interior nodes."""
24283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
24383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self,type, children,
24483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                 context=None,
24583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                 prefix=None,
24683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                 fixers_applied=None):
24783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
24883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Initializer.
24983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
25083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Takes a type constant (a symbol number >= 256), a sequence of
25183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        child nodes, and an optional context keyword argument.
25283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
25383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        As a side effect, the parent pointers of the children are updated.
25483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
25583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert type >= 256, type
25683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.type = type
25783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.children = list(children)
25883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for ch in self.children:
25983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert ch.parent is None, repr(ch)
26083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ch.parent = self
26183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if prefix is not None:
26283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.prefix = prefix
26383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if fixers_applied:
26483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.fixers_applied = fixers_applied[:]
26583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
26683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.fixers_applied = None
26783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
26883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __repr__(self):
26983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return a canonical string representation."""
27083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return "%s(%s, %r)" % (self.__class__.__name__,
27183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                               type_repr(self.type),
27283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                               self.children)
27383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __unicode__(self):
27583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
27683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Return a pretty string representation.
27783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This reproduces the input source exactly.
27983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
28083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return u"".join(map(unicode, self.children))
28183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if sys.version_info > (3, 0):
28383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        __str__ = __unicode__
28483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _eq(self, other):
28683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Compare two nodes for equality."""
28783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return (self.type, self.children) == (other.type, other.children)
28883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def clone(self):
29083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return a cloned (deep) copy of self."""
29183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return Node(self.type, [ch.clone() for ch in self.children],
29283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    fixers_applied=self.fixers_applied)
29383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def post_order(self):
29583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return a post-order iterator for the tree."""
29683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for child in self.children:
29783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for node in child.post_order():
29883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                yield node
29983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        yield self
30083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def pre_order(self):
30283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return a pre-order iterator for the tree."""
30383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        yield self
30483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for child in self.children:
30583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for node in child.pre_order():
30683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                yield node
30783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _prefix_getter(self):
30983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
31083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The whitespace and comments preceding this node in the input.
31183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
31283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not self.children:
31383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return ""
31483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.children[0].prefix
31583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
31683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _prefix_setter(self, prefix):
31783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.children:
31883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.children[0].prefix = prefix
31983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    prefix = property(_prefix_getter, _prefix_setter)
32183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def set_child(self, i, child):
32383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
32483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Equivalent to 'node.children[i] = child'. This method also sets the
32583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        child's parent attribute appropriately.
32683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
32783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        child.parent = self
32883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.children[i].parent = None
32983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.children[i] = child
33083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.changed()
33183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def insert_child(self, i, child):
33383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
33483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Equivalent to 'node.children.insert(i, child)'. This method also sets
33583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        the child's parent attribute appropriately.
33683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
33783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        child.parent = self
33883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.children.insert(i, child)
33983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.changed()
34083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def append_child(self, child):
34283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
34383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Equivalent to 'node.children.append(child)'. This method also sets the
34483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        child's parent attribute appropriately.
34583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
34683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        child.parent = self
34783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.children.append(child)
34883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.changed()
34983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
35083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
35183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Leaf(Base):
35283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
35383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Concrete implementation for leaf nodes."""
35483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
35583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # Default values for instance variables
35683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    _prefix = ""  # Whitespace and comments preceding this token in the input
35783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    lineno = 0    # Line where this token starts in the input
35883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    column = 0    # Column where this token tarts in the input
35983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, type, value,
36183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                 context=None,
36283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                 prefix=None,
36383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                 fixers_applied=[]):
36483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
36583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Initializer.
36683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Takes a type constant (a token number < 256), a string value, and an
36883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        optional context keyword argument.
36983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
37083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert 0 <= type < 256, type
37183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if context is not None:
37283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._prefix, (self.lineno, self.column) = context
37383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.type = type
37483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.value = value
37583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if prefix is not None:
37683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._prefix = prefix
37783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.fixers_applied = fixers_applied[:]
37883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
37983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __repr__(self):
38083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return a canonical string representation."""
38183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return "%s(%r, %r)" % (self.__class__.__name__,
38283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                               self.type,
38383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                               self.value)
38483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
38583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __unicode__(self):
38683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
38783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Return a pretty string representation.
38883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
38983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This reproduces the input source exactly.
39083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
39183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.prefix + unicode(self.value)
39283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
39383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if sys.version_info > (3, 0):
39483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        __str__ = __unicode__
39583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
39683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _eq(self, other):
39783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Compare two nodes for equality."""
39883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return (self.type, self.value) == (other.type, other.value)
39983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def clone(self):
40183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return a cloned (deep) copy of self."""
40283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return Leaf(self.type, self.value,
40383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    (self.prefix, (self.lineno, self.column)),
40483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    fixers_applied=self.fixers_applied)
40583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def leaves(self):
40783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        yield self
40883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def post_order(self):
41083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return a post-order iterator for the tree."""
41183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        yield self
41283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
41383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def pre_order(self):
41483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return a pre-order iterator for the tree."""
41583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        yield self
41683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
41783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _prefix_getter(self):
41883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
41983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The whitespace and comments preceding this token in the input.
42083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
42183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._prefix
42283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
42383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _prefix_setter(self, prefix):
42483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.changed()
42583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._prefix = prefix
42683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
42783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    prefix = property(_prefix_getter, _prefix_setter)
42883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
42983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef convert(gr, raw_node):
43083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
43183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Convert raw node information to a Node or Leaf instance.
43283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
43383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    This is passed to the parser driver which calls it whenever a reduction of a
43483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    grammar rule produces a new complete node, so that the tree is build
43583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    strictly bottom-up.
43683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
43783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    type, value, context, children = raw_node
43883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if children or type in gr.number2symbol:
43983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # If there's exactly one child, return that child instead of
44083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # creating a new node.
44183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if len(children) == 1:
44283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return children[0]
44383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return Node(type, children, context=context)
44483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    else:
44583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return Leaf(type, value, context=context)
44683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass BasePattern(object):
44983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
45183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    A pattern is a tree matching pattern.
45283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    It looks for a specific node type (token or symbol), and
45483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    optionally for a specific content.
45583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    This is an abstract base class.  There are three concrete
45783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    subclasses:
45883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - LeafPattern matches a single leaf node;
46083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - NodePattern matches a single node (usually non-leaf);
46183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - WildcardPattern matches a sequence of nodes of variable length.
46283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
46383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
46483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # Defaults for instance variables
46583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    type = None     # Node type (token if < 256, symbol if >= 256)
46683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    content = None  # Optional content matching pattern
46783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    name = None     # Optional name used to store match in results dict
46883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
46983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __new__(cls, *args, **kwds):
47083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Constructor that prevents BasePattern from being instantiated."""
47183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert cls is not BasePattern, "Cannot instantiate BasePattern"
47283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return object.__new__(cls)
47383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
47483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __repr__(self):
47583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        args = [type_repr(self.type), self.content, self.name]
47683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        while args and args[-1] is None:
47783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            del args[-1]
47883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return "%s(%s)" % (self.__class__.__name__, ", ".join(map(repr, args)))
47983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def optimize(self):
48183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
48283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        A subclass can define this as a hook for optimizations.
48383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Returns either self or another node with the same effect.
48583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
48683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self
48783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def match(self, node, results=None):
48983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
49083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Does this pattern exactly match a node?
49183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Returns True if it matches, False if not.
49383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        If results is not None, it must be a dict which will be
49583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        updated with the nodes matching named subpatterns.
49683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Default implementation for non-wildcard patterns.
49883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
49983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.type is not None and node.type != self.type:
50083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return False
50183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.content is not None:
50283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            r = None
50383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if results is not None:
50483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                r = {}
50583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not self._submatch(node, r):
50683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return False
50783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if r:
50883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                results.update(r)
50983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if results is not None and self.name:
51083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            results[self.name] = node
51183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return True
51283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
51383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def match_seq(self, nodes, results=None):
51483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
51583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Does this pattern exactly match a sequence of nodes?
51683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
51783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Default implementation for non-wildcard patterns.
51883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
51983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if len(nodes) != 1:
52083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return False
52183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.match(nodes[0], results)
52283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
52383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def generate_matches(self, nodes):
52483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
52583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Generator yielding all matches for this pattern.
52683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
52783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Default implementation for non-wildcard patterns.
52883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
52983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        r = {}
53083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if nodes and self.match(nodes[0], r):
53183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            yield 1, r
53283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
53383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
53483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass LeafPattern(BasePattern):
53583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
53683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, type=None, content=None, name=None):
53783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
53883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Initializer.  Takes optional type, content, and name.
53983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
54083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The type, if given must be a token type (< 256).  If not given,
54183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        this matches any *leaf* node; the content may still be required.
54283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
54383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The content, if given, must be a string.
54483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
54583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        If a name is given, the matching node is stored in the results
54683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        dict under that key.
54783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
54883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if type is not None:
54983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert 0 <= type < 256, type
55083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if content is not None:
55183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert isinstance(content, basestring), repr(content)
55283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.type = type
55383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.content = content
55483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.name = name
55583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
55683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def match(self, node, results=None):
55783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Override match() to insist on a leaf node."""
55883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not isinstance(node, Leaf):
55983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return False
56083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return BasePattern.match(self, node, results)
56183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
56283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _submatch(self, node, results=None):
56383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
56483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Match the pattern's content to the node's children.
56583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
56683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This assumes the node type matches and self.content is not None.
56783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
56883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Returns True if it matches, False if not.
56983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
57083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        If results is not None, it must be a dict which will be
57183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        updated with the nodes matching named subpatterns.
57283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
57383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        When returning False, the results dict may still be updated.
57483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
57583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.content == node.value
57683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
57783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
57883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass NodePattern(BasePattern):
57983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
58083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    wildcards = False
58183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
58283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, type=None, content=None, name=None):
58383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
58483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Initializer.  Takes optional type, content, and name.
58583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
58683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The type, if given, must be a symbol type (>= 256).  If the
58783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        type is None this matches *any* single node (leaf or not),
58883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except if content is not None, in which it only matches
58983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        non-leaf nodes that also match the content pattern.
59083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
59183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The content, if not None, must be a sequence of Patterns that
59283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        must match the node's children exactly.  If the content is
59383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        given, the type must not be None.
59483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
59583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        If a name is given, the matching node is stored in the results
59683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        dict under that key.
59783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
59883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if type is not None:
59983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert type >= 256, type
60083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if content is not None:
60183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert not isinstance(content, basestring), repr(content)
60283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            content = list(content)
60383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for i, item in enumerate(content):
60483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                assert isinstance(item, BasePattern), (i, item)
60583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if isinstance(item, WildcardPattern):
60683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    self.wildcards = True
60783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.type = type
60883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.content = content
60983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.name = name
61083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _submatch(self, node, results=None):
61283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
61383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Match the pattern's content to the node's children.
61483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        This assumes the node type matches and self.content is not None.
61683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Returns True if it matches, False if not.
61883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        If results is not None, it must be a dict which will be
62083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        updated with the nodes matching named subpatterns.
62183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
62283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        When returning False, the results dict may still be updated.
62383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
62483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.wildcards:
62583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for c, r in generate_matches(self.content, node.children):
62683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if c == len(node.children):
62783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    if results is not None:
62883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        results.update(r)
62983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    return True
63083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return False
63183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if len(self.content) != len(node.children):
63283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return False
63383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for subpattern, child in zip(self.content, node.children):
63483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not subpattern.match(child, results):
63583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return False
63683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return True
63783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
63883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
63983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass WildcardPattern(BasePattern):
64083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
64183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
64283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    A wildcard pattern can match zero or more nodes.
64383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
64483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    This has all the flexibility needed to implement patterns like:
64583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
64683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    .*      .+      .?      .{m,n}
64783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    (a b c | d e | f)
64883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    (...)*  (...)+  (...)?  (...){m,n}
64983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
65083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    except it always uses non-greedy matching.
65183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
65283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
65383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, content=None, min=0, max=HUGE, name=None):
65483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
65583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Initializer.
65683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
65783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Args:
65883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            content: optional sequence of subsequences of patterns;
65983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                     if absent, matches one node;
66083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                     if present, each subsequence is an alternative [*]
66183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            min: optional minimum number of times to match, default 0
66283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            max: optional maximum number of times to match, default HUGE
66383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            name: optional name assigned to this match
66483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
66583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        [*] Thus, if content is [[a, b, c], [d, e], [f, g, h]] this is
66683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            equivalent to (a b c | d e | f g h); if content is None,
66783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            this is equivalent to '.' in regular expression terms.
66883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            The min and max parameters work as follows:
66983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                min=0, max=maxint: .*
67083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                min=1, max=maxint: .+
67183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                min=0, max=1: .?
67283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                min=1, max=1: .
67383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            If content is not None, replace the dot with the parenthesized
67483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            list of alternatives, e.g. (a b c | d e | f g h)*
67583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
67683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert 0 <= min <= max <= HUGE, (min, max)
67783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if content is not None:
67883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            content = tuple(map(tuple, content))  # Protect against alterations
67983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # Check sanity of alternatives
68083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert len(content), repr(content)  # Can't have zero alternatives
68183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for alt in content:
68283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                assert len(alt), repr(alt) # Can have empty alternatives
68383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.content = content
68483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.min = min
68583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.max = max
68683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.name = name
68783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
68883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def optimize(self):
68983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Optimize certain stacked wildcard patterns."""
69083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        subpattern = None
69183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if (self.content is not None and
69283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            len(self.content) == 1 and len(self.content[0]) == 1):
69383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            subpattern = self.content[0][0]
69483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.min == 1 and self.max == 1:
69583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if self.content is None:
69683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return NodePattern(name=self.name)
69783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if subpattern is not None and  self.name == subpattern.name:
69883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return subpattern.optimize()
69983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if (self.min <= 1 and isinstance(subpattern, WildcardPattern) and
70083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            subpattern.min <= 1 and self.name == subpattern.name):
70183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return WildcardPattern(subpattern.content,
70283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                   self.min*subpattern.min,
70383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                   self.max*subpattern.max,
70483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                   subpattern.name)
70583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self
70683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
70783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def match(self, node, results=None):
70883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Does this pattern exactly match a node?"""
70983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.match_seq([node], results)
71083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
71183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def match_seq(self, nodes, results=None):
71283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Does this pattern exactly match a sequence of nodes?"""
71383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for c, r in self.generate_matches(nodes):
71483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if c == len(nodes):
71583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if results is not None:
71683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    results.update(r)
71783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    if self.name:
71883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        results[self.name] = list(nodes)
71983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return True
72083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return False
72183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
72283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def generate_matches(self, nodes):
72383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
72483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Generator yielding matches for a sequence of nodes.
72583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
72683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Args:
72783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            nodes: sequence of nodes
72883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
72983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Yields:
73083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            (count, results) tuples where:
73183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            count: the match comprises nodes[:count];
73283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            results: dict containing named submatches.
73383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
73483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.content is None:
73583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # Shortcut for special case (see __init__.__doc__)
73683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for count in xrange(self.min, 1 + min(len(nodes), self.max)):
73783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                r = {}
73883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if self.name:
73983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    r[self.name] = nodes[:count]
74083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                yield count, r
74183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        elif self.name == "bare_name":
74283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            yield self._bare_name_matches(nodes)
74383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
74483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # The reason for this is that hitting the recursion limit usually
74583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # results in some ugly messages about how RuntimeErrors are being
74683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # ignored. We don't do this on non-CPython implementation because
74783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # they don't have this problem.
74883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if hasattr(sys, "getrefcount"):
74983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                save_stderr = sys.stderr
75083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                sys.stderr = StringIO()
75183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
75283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                for count, r in self._recursive_matches(nodes, 0):
75383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    if self.name:
75483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        r[self.name] = nodes[:count]
75583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    yield count, r
75683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except RuntimeError:
75783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # We fall back to the iterative pattern matching scheme if the recursive
75883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # scheme hits the recursion limit.
75983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                for count, r in self._iterative_matches(nodes):
76083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    if self.name:
76183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        r[self.name] = nodes[:count]
76283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    yield count, r
76383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            finally:
76483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if hasattr(sys, "getrefcount"):
76583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    sys.stderr = save_stderr
76683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
76783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _iterative_matches(self, nodes):
76883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Helper to iteratively yield the matches."""
76983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        nodelen = len(nodes)
77083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if 0 >= self.min:
77183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            yield 0, {}
77283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
77383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        results = []
77483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # generate matches that use just one alt from self.content
77583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for alt in self.content:
77683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for c, r in generate_matches(alt, nodes):
77783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                yield c, r
77883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                results.append((c, r))
77983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
78083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # for each match, iterate down the nodes
78183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        while results:
78283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            new_results = []
78383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for c0, r0 in results:
78483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # stop if the entire set of nodes has been matched
78583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if c0 < nodelen and c0 <= self.max:
78683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    for alt in self.content:
78783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        for c1, r1 in generate_matches(alt, nodes[c0:]):
78883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                            if c1 > 0:
78983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                r = {}
79083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                r.update(r0)
79183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                r.update(r1)
79283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                yield c0 + c1, r
79383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                new_results.append((c0 + c1, r))
79483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            results = new_results
79583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
79683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _bare_name_matches(self, nodes):
79783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Special optimized matcher for bare_name."""
79883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        count = 0
79983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        r = {}
80083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        done = False
80183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        max = len(nodes)
80283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        while not done and count < max:
80383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            done = True
80483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for leaf in self.content:
80583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if leaf[0].match(nodes[count], r):
80683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    count += 1
80783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    done = False
80883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    break
80983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        r[self.name] = nodes[:count]
81083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return count, r
81183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
81283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _recursive_matches(self, nodes, count):
81383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Helper to recursively yield the matches."""
81483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert self.content is not None
81583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if count >= self.min:
81683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            yield 0, {}
81783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if count < self.max:
81883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for alt in self.content:
81983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                for c0, r0 in generate_matches(alt, nodes):
82083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    for c1, r1 in self._recursive_matches(nodes[c0:], count+1):
82183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        r = {}
82283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        r.update(r0)
82383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        r.update(r1)
82483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        yield c0 + c1, r
82583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
82683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
82783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass NegatedPattern(BasePattern):
82883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
82983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, content=None):
83083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
83183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Initializer.
83283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
83383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The argument is either a pattern or None.  If it is None, this
83483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        only matches an empty sequence (effectively '$' in regex
83583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        lingo).  If it is not None, this matches whenever the argument
83683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pattern doesn't have any matches.
83783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
83883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if content is not None:
83983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert isinstance(content, BasePattern), repr(content)
84083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.content = content
84183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
84283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def match(self, node):
84383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # We never match a node in its entirety
84483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return False
84583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
84683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def match_seq(self, nodes):
84783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # We only match an empty sequence of nodes in its entirety
84883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return len(nodes) == 0
84983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
85083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def generate_matches(self, nodes):
85183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.content is None:
85283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # Return a match if there is an empty sequence
85383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if len(nodes) == 0:
85483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                yield 0, {}
85583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
85683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # Return a match if the argument pattern has no matches
85783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for c, r in self.content.generate_matches(nodes):
85883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return
85983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            yield 0, {}
86083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
86183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
86283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef generate_matches(patterns, nodes):
86383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
86483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Generator yielding matches for a sequence of patterns and nodes.
86583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
86683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Args:
86783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        patterns: a sequence of patterns
86883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        nodes: a sequence of nodes
86983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
87083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Yields:
87183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        (count, results) tuples where:
87283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        count: the entire sequence of patterns matches nodes[:count];
87383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        results: dict containing named submatches.
87483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
87583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if not patterns:
87683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        yield 0, {}
87783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    else:
87883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        p, rest = patterns[0], patterns[1:]
87983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for c0, r0 in p.generate_matches(nodes):
88083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not rest:
88183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                yield c0, r0
88283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
88383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                for c1, r1 in generate_matches(rest, nodes[c0:]):
88483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    r = {}
88583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    r.update(r0)
88683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    r.update(r1)
88783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    yield c0 + c1, r
888