""" @package antlr3.tree
@brief ANTLR3 runtime package, tree module

This module contains all support classes for AST construction and tree parsers.

"""

# begin[licence]
#
# [The "BSD licence"]
# Copyright (c) 2005-2008 Terence Parr
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# end[licence]

# lot's of docstrings are missing, don't complain for now...
# pylint: disable-msg=C0111

import re

from antlr3.constants import UP, DOWN, EOF, INVALID_TOKEN_TYPE
from antlr3.recognizers import BaseRecognizer, RuleReturnScope
from antlr3.streams import IntStream
from antlr3.tokens import CommonToken, Token, INVALID_TOKEN
from antlr3.exceptions import MismatchedTreeNodeException, \
     MissingTokenException, UnwantedTokenException, MismatchedTokenException, \
     NoViableAltException


############################################################################
#
# tree related exceptions
#
############################################################################


class RewriteCardinalityException(RuntimeError):
    """
    @brief Base class for all exceptions thrown during AST rewrite construction.

    This signifies a case where the cardinality of two or more elements
    in a subrule are different: (ID INT)+ where |ID|!=|INT|
    """

    def __init__(self, elementDescription):
        RuntimeError.__init__(self, elementDescription)

        self.elementDescription = elementDescription


    def getMessage(self):
        return self.elementDescription


class RewriteEarlyExitException(RewriteCardinalityException):
    """@brief No elements within a (...)+ in a rewrite rule"""

    def __init__(self, elementDescription=None):
        RewriteCardinalityException.__init__(self, elementDescription)


class RewriteEmptyStreamException(RewriteCardinalityException):
    """
    @brief Ref to ID or expr but no tokens in ID stream or subtrees in expr stream
    """

    pass


############################################################################
#
# basic Tree and TreeAdaptor interfaces
#
############################################################################

class Tree(object):
    """
    @brief Abstract baseclass for tree nodes.

    What does a tree look like?  ANTLR has a number of support classes
    such as CommonTreeNodeStream that work on these kinds of trees.  You
    don't have to make your trees implement this interface, but if you do,
    you'll be able to use more support code.

    NOTE: When constructing trees, ANTLR can build any kind of tree; it can
    even use Token objects as trees if you add a child list to your tokens.

    This is a tree node without any payload; just navigation and factory stuff.
    """


    def getChild(self, i):
        raise NotImplementedError


    def getChildCount(self):
        raise NotImplementedError


    def getParent(self):
        """Tree tracks parent and child index now > 3.0"""

        raise NotImplementedError

    def setParent(self, t):
        """Tree tracks parent and child index now > 3.0"""

        raise NotImplementedError


    def hasAncestor(self, ttype):
        """Walk upwards looking for ancestor with this token type."""

        raise NotImplementedError

    def getAncestor(self, ttype):
        """Walk upwards and get first ancestor with this token type."""

        raise NotImplementedError

    def getAncestors(self):
        """Return a list of all ancestors of this node.

        The first node of list is the root and the last is the parent of
        this node.
        """

        raise NotImplementedError


    def getChildIndex(self):
        """This node is what child index? 0..n-1"""

        raise NotImplementedError

    def setChildIndex(self, index):
        """This node is what child index? 0..n-1"""

        raise NotImplementedError


    def freshenParentAndChildIndexes(self):
        """Set the parent and child index values for all children"""

        raise NotImplementedError


    def addChild(self, t):
        """
        Add t as a child to this node.  If t is null, do nothing.  If t
        is nil, add all children of t to this' children.
        """

        raise NotImplementedError


    def setChild(self, i, t):
        """Set ith child (0..n-1) to t; t must be non-null and non-nil node"""

        raise NotImplementedError


    def deleteChild(self, i):
        raise NotImplementedError


    def replaceChildren(self, startChildIndex, stopChildIndex, t):
        """
        Delete children from start to stop and replace with t even if t is
        a list (nil-root tree).  num of children can increase or decrease.
        For huge child lists, inserting children can force walking rest of
        children to set their childindex; could be slow.
        """

        raise NotImplementedError


    def isNil(self):
        """
        Indicates the node is a nil node but may still have children, meaning
        the tree is a flat list.
        """

        raise NotImplementedError


    def getTokenStartIndex(self):
        """
        What is the smallest token index (indexing from 0) for this node
           and its children?
        """

        raise NotImplementedError


    def setTokenStartIndex(self, index):
        raise NotImplementedError


    def getTokenStopIndex(self):
        """
        What is the largest token index (indexing from 0) for this node
        and its children?
        """

        raise NotImplementedError


    def setTokenStopIndex(self, index):
        raise NotImplementedError


    def dupNode(self):
        raise NotImplementedError


    def getType(self):
        """Return a token type; needed for tree parsing."""

        raise NotImplementedError


    def getText(self):
        raise NotImplementedError


    def getLine(self):
        """
        In case we don't have a token payload, what is the line for errors?
        """

        raise NotImplementedError


    def getCharPositionInLine(self):
        raise NotImplementedError


    def toStringTree(self):
        raise NotImplementedError


    def toString(self):
        raise NotImplementedError



class TreeAdaptor(object):
    """
    @brief Abstract baseclass for tree adaptors.

    How to create and navigate trees.  Rather than have a separate factory
    and adaptor, I've merged them.  Makes sense to encapsulate.

    This takes the place of the tree construction code generated in the
    generated code in 2.x and the ASTFactory.

    I do not need to know the type of a tree at all so they are all
    generic Objects.  This may increase the amount of typecasting needed. :(
    """

    # C o n s t r u c t i o n

    def createWithPayload(self, payload):
        """
        Create a tree node from Token object; for CommonTree type trees,
        then the token just becomes the payload.  This is the most
        common create call.

        Override if you want another kind of node to be built.
        """

        raise NotImplementedError


    def dupNode(self, treeNode):
        """Duplicate a single tree node.

        Override if you want another kind of node to be built."""

        raise NotImplementedError


    def dupTree(self, tree):
        """Duplicate tree recursively, using dupNode() for each node"""

        raise NotImplementedError


    def nil(self):
        """
        Return a nil node (an empty but non-null node) that can hold
        a list of element as the children.  If you want a flat tree (a list)
        use "t=adaptor.nil(); t.addChild(x); t.addChild(y);"
        """

        raise NotImplementedError


    def errorNode(self, input, start, stop, exc):
        """
        Return a tree node representing an error.  This node records the
        tokens consumed during error recovery.  The start token indicates the
        input symbol at which the error was detected.  The stop token indicates
        the last symbol consumed during recovery.

        You must specify the input stream so that the erroneous text can
        be packaged up in the error node.  The exception could be useful
        to some applications; default implementation stores ptr to it in
        the CommonErrorNode.

        This only makes sense during token parsing, not tree parsing.
        Tree parsing should happen only when parsing and tree construction
        succeed.
        """

        raise NotImplementedError


    def isNil(self, tree):
        """Is tree considered a nil node used to make lists of child nodes?"""

        raise NotImplementedError


    def addChild(self, t, child):
        """
        Add a child to the tree t.  If child is a flat tree (a list), make all
        in list children of t.  Warning: if t has no children, but child does
        and child isNil then you can decide it is ok to move children to t via
        t.children = child.children; i.e., without copying the array.  Just
        make sure that this is consistent with have the user will build
        ASTs. Do nothing if t or child is null.
        """

        raise NotImplementedError


    def becomeRoot(self, newRoot, oldRoot):
        """
        If oldRoot is a nil root, just copy or move the children to newRoot.
        If not a nil root, make oldRoot a child of newRoot.

           old=^(nil a b c), new=r yields ^(r a b c)
           old=^(a b c), new=r yields ^(r ^(a b c))

        If newRoot is a nil-rooted single child tree, use the single
        child as the new root node.

           old=^(nil a b c), new=^(nil r) yields ^(r a b c)
           old=^(a b c), new=^(nil r) yields ^(r ^(a b c))

        If oldRoot was null, it's ok, just return newRoot (even if isNil).

           old=null, new=r yields r
           old=null, new=^(nil r) yields ^(nil r)

        Return newRoot.  Throw an exception if newRoot is not a
        simple node or nil root with a single child node--it must be a root
        node.  If newRoot is ^(nil x) return x as newRoot.

        Be advised that it's ok for newRoot to point at oldRoot's
        children; i.e., you don't have to copy the list.  We are
        constructing these nodes so we should have this control for
        efficiency.
        """

        raise NotImplementedError


    def rulePostProcessing(self, root):
        """
        Given the root of the subtree created for this rule, post process
        it to do any simplifications or whatever you want.  A required
        behavior is to convert ^(nil singleSubtree) to singleSubtree
        as the setting of start/stop indexes relies on a single non-nil root
        for non-flat trees.

        Flat trees such as for lists like "idlist : ID+ ;" are left alone
        unless there is only one ID.  For a list, the start/stop indexes
        are set in the nil node.

        This method is executed after all rule tree construction and right
        before setTokenBoundaries().
        """

        raise NotImplementedError


    def getUniqueID(self, node):
        """For identifying trees.

        How to identify nodes so we can say "add node to a prior node"?
        Even becomeRoot is an issue.  Use System.identityHashCode(node)
        usually.
        """

        raise NotImplementedError


    # R e w r i t e  R u l e s

    def createFromToken(self, tokenType, fromToken, text=None):
        """
        Create a new node derived from a token, with a new token type and
        (optionally) new text.

        This is invoked from an imaginary node ref on right side of a
        rewrite rule as IMAG[$tokenLabel] or IMAG[$tokenLabel "IMAG"].

        This should invoke createToken(Token).
        """

        raise NotImplementedError


    def createFromType(self, tokenType, text):
        """Create a new node derived from a token, with a new token type.

        This is invoked from an imaginary node ref on right side of a
        rewrite rule as IMAG["IMAG"].

        This should invoke createToken(int,String).
        """

        raise NotImplementedError


    # C o n t e n t

    def getType(self, t):
        """For tree parsing, I need to know the token type of a node"""

        raise NotImplementedError


    def setType(self, t, type):
        """Node constructors can set the type of a node"""

        raise NotImplementedError


    def getText(self, t):
        raise NotImplementedError

    def setText(self, t, text):
        """Node constructors can set the text of a node"""

        raise NotImplementedError


    def getToken(self, t):
        """Return the token object from which this node was created.

        Currently used only for printing an error message.
        The error display routine in BaseRecognizer needs to
        display where the input the error occurred. If your
        tree of limitation does not store information that can
        lead you to the token, you can create a token filled with
        the appropriate information and pass that back.  See
        BaseRecognizer.getErrorMessage().
        """

        raise NotImplementedError


    def setTokenBoundaries(self, t, startToken, stopToken):
        """
        Where are the bounds in the input token stream for this node and
        all children?  Each rule that creates AST nodes will call this
        method right before returning.  Flat trees (i.e., lists) will
        still usually have a nil root node just to hold the children list.
        That node would contain the start/stop indexes then.
        """

        raise NotImplementedError


    def getTokenStartIndex(self, t):
        """
        Get the token start index for this subtree; return -1 if no such index
        """

        raise NotImplementedError


    def getTokenStopIndex(self, t):
        """
        Get the token stop index for this subtree; return -1 if no such index
        """

        raise NotImplementedError


    # N a v i g a t i o n  /  T r e e  P a r s i n g

    def getChild(self, t, i):
        """Get a child 0..n-1 node"""

        raise NotImplementedError


    def setChild(self, t, i, child):
        """Set ith child (0..n-1) to t; t must be non-null and non-nil node"""

        raise NotImplementedError


    def deleteChild(self, t, i):
        """Remove ith child and shift children down from right."""

        raise NotImplementedError


    def getChildCount(self, t):
        """How many children?  If 0, then this is a leaf node"""

        raise NotImplementedError


    def getParent(self, t):
        """
        Who is the parent node of this node; if null, implies node is root.
        If your node type doesn't handle this, it's ok but the tree rewrites
        in tree parsers need this functionality.
        """

        raise NotImplementedError


    def setParent(self, t, parent):
        """
        Who is the parent node of this node; if null, implies node is root.
        If your node type doesn't handle this, it's ok but the tree rewrites
        in tree parsers need this functionality.
        """

        raise NotImplementedError


    def getChildIndex(self, t):
        """
        What index is this node in the child list? Range: 0..n-1
        If your node type doesn't handle this, it's ok but the tree rewrites
        in tree parsers need this functionality.
        """

        raise NotImplementedError


    def setChildIndex(self, t, index):
        """
        What index is this node in the child list? Range: 0..n-1
        If your node type doesn't handle this, it's ok but the tree rewrites
        in tree parsers need this functionality.
        """

        raise NotImplementedError


    def replaceChildren(self, parent, startChildIndex, stopChildIndex, t):
        """
        Replace from start to stop child index of parent with t, which might
        be a list.  Number of children may be different
        after this call.

        If parent is null, don't do anything; must be at root of overall tree.
        Can't replace whatever points to the parent externally.  Do nothing.
        """

        raise NotImplementedError


    # Misc

    def create(self, *args):
        """
        Deprecated, use createWithPayload, createFromToken or createFromType.

        This method only exists to mimic the Java interface of TreeAdaptor.

        """

        if len(args) == 1 and isinstance(args[0], Token):
            # Object create(Token payload);
##             warnings.warn(
##                 "Using create() is deprecated, use createWithPayload()",
##                 DeprecationWarning,
##                 stacklevel=2
##                 )
            return self.createWithPayload(args[0])

        if (len(args) == 2
            and isinstance(args[0], (int, long))
            and isinstance(args[1], Token)
            ):
            # Object create(int tokenType, Token fromToken);
##             warnings.warn(
##                 "Using create() is deprecated, use createFromToken()",
##                 DeprecationWarning,
##                 stacklevel=2
##                 )
            return self.createFromToken(args[0], args[1])

        if (len(args) == 3
            and isinstance(args[0], (int, long))
            and isinstance(args[1], Token)
            and isinstance(args[2], basestring)
            ):
            # Object create(int tokenType, Token fromToken, String text);
##             warnings.warn(
##                 "Using create() is deprecated, use createFromToken()",
##                 DeprecationWarning,
##                 stacklevel=2
##                 )
            return self.createFromToken(args[0], args[1], args[2])

        if (len(args) == 2
            and isinstance(args[0], (int, long))
            and isinstance(args[1], basestring)
            ):
            # Object create(int tokenType, String text);
##             warnings.warn(
##                 "Using create() is deprecated, use createFromType()",
##                 DeprecationWarning,
##                 stacklevel=2
##                 )
            return self.createFromType(args[0], args[1])

        raise TypeError(
            "No create method with this signature found: %s"
            % (', '.join(type(v).__name__ for v in args))
            )


############################################################################
#
# base implementation of Tree and TreeAdaptor
#
# Tree
# \- BaseTree
#
# TreeAdaptor
# \- BaseTreeAdaptor
#
############################################################################


class BaseTree(Tree):
    """
    @brief A generic tree implementation with no payload.

    You must subclass to
    actually have any user data.  ANTLR v3 uses a list of children approach
    instead of the child-sibling approach in v2.  A flat tree (a list) is
    an empty node whose children represent the list.  An empty, but
    non-null node is called "nil".
    """

    # BaseTree is abstract, no need to complain about not implemented abstract
    # methods
    # pylint: disable-msg=W0223

    def __init__(self, node=None):
        """
        Create a new node from an existing node does nothing for BaseTree
        as there are no fields other than the children list, which cannot
        be copied as the children are not considered part of this node.
        """

        Tree.__init__(self)
        self.children = []
        self.parent = None
        self.childIndex = 0


    def getChild(self, i):
        try:
            return self.children[i]
        except IndexError:
            return None


    def getChildren(self):
        """@brief Get the children internal List

        Note that if you directly mess with
        the list, do so at your own risk.
        """

        # FIXME: mark as deprecated
        return self.children


    def getFirstChildWithType(self, treeType):
        for child in self.children:
            if child.getType() == treeType:
                return child

        return None


    def getChildCount(self):
        return len(self.children)


    def addChild(self, childTree):
        """Add t as child of this node.

        Warning: if t has no children, but child does
        and child isNil then this routine moves children to t via
        t.children = child.children; i.e., without copying the array.
        """

        # this implementation is much simpler and probably less efficient
        # than the mumbo-jumbo that Ter did for the Java runtime.

        if childTree is None:
            return

        if childTree.isNil():
            # t is an empty node possibly with children

            if self.children is childTree.children:
                raise ValueError("attempt to add child list to itself")

            # fix parent pointer and childIndex for new children
            for idx, child in enumerate(childTree.children):
                child.parent = self
                child.childIndex = len(self.children) + idx

            self.children += childTree.children

        else:
            # child is not nil (don't care about children)
            self.children.append(childTree)
            childTree.parent = self
            childTree.childIndex = len(self.children) - 1


    def addChildren(self, children):
        """Add all elements of kids list as children of this node"""

        self.children += children


    def setChild(self, i, t):
        if t is None:
            return

        if t.isNil():
            raise ValueError("Can't set single child to a list")

        self.children[i] = t
        t.parent = self
        t.childIndex = i


    def deleteChild(self, i):
        killed = self.children[i]

        del self.children[i]

        # walk rest and decrement their child indexes
        for idx, child in enumerate(self.children[i:]):
            child.childIndex = i + idx

        return killed


    def replaceChildren(self, startChildIndex, stopChildIndex, newTree):
        """
        Delete children from start to stop and replace with t even if t is
        a list (nil-root tree).  num of children can increase or decrease.
        For huge child lists, inserting children can force walking rest of
        children to set their childindex; could be slow.
        """

        if (startChildIndex >= len(self.children)
            or stopChildIndex >= len(self.children)
            ):
            raise IndexError("indexes invalid")

        replacingHowMany = stopChildIndex - startChildIndex + 1

        # normalize to a list of children to add: newChildren
        if newTree.isNil():
            newChildren = newTree.children

        else:
            newChildren = [newTree]

        replacingWithHowMany = len(newChildren)
        delta = replacingHowMany - replacingWithHowMany


        if delta == 0:
            # if same number of nodes, do direct replace
            for idx, child in enumerate(newChildren):
                self.children[idx + startChildIndex] = child
                child.parent = self
                child.childIndex = idx + startChildIndex

        else:
            # length of children changes...

            # ...delete replaced segment...
            del self.children[startChildIndex:stopChildIndex+1]

            # ...insert new segment...
            self.children[startChildIndex:startChildIndex] = newChildren

            # ...and fix indeces
            self.freshenParentAndChildIndexes(startChildIndex)


    def isNil(self):
        return False


    def freshenParentAndChildIndexes(self, offset=0):
        for idx, child in enumerate(self.children[offset:]):
            child.childIndex = idx + offset
            child.parent = self


    def sanityCheckParentAndChildIndexes(self, parent=None, i=-1):
        if parent != self.parent:
            raise ValueError(
                "parents don't match; expected %r found %r"
                % (parent, self.parent)
                )

        if i != self.childIndex:
            raise ValueError(
                "child indexes don't match; expected %d found %d"
                % (i, self.childIndex)
                )

        for idx, child in enumerate(self.children):
            child.sanityCheckParentAndChildIndexes(self, idx)


    def getChildIndex(self):
        """BaseTree doesn't track child indexes."""

        return 0


    def setChildIndex(self, index):
        """BaseTree doesn't track child indexes."""

        pass


    def getParent(self):
        """BaseTree doesn't track parent pointers."""

        return None

    def setParent(self, t):
        """BaseTree doesn't track parent pointers."""

        pass


    def hasAncestor(self, ttype):
        """Walk upwards looking for ancestor with this token type."""
        return self.getAncestor(ttype) is not None

    def getAncestor(self, ttype):
        """Walk upwards and get first ancestor with this token type."""
        t = self.getParent()
        while t is not None:
            if t.getType() == ttype:
                return t
            t = t.getParent()

        return None

    def getAncestors(self):
        """Return a list of all ancestors of this node.

        The first node of list is the root and the last is the parent of
        this node.
        """
        if selfgetParent() is None:
            return None

        ancestors = []
        t = self.getParent()
        while t is not None:
            ancestors.insert(0, t) # insert at start
            t = t.getParent()

        return ancestors


    def toStringTree(self):
        """Print out a whole tree not just a node"""

        if len(self.children) == 0:
            return self.toString()

        buf = []
        if not self.isNil():
            buf.append('(')
            buf.append(self.toString())
            buf.append(' ')

        for i, child in enumerate(self.children):
            if i > 0:
                buf.append(' ')
            buf.append(child.toStringTree())

        if not self.isNil():
            buf.append(')')

        return ''.join(buf)


    def getLine(self):
        return 0


    def getCharPositionInLine(self):
        return 0


    def toString(self):
        """Override to say how a node (not a tree) should look as text"""

        raise NotImplementedError



class BaseTreeAdaptor(TreeAdaptor):
    """
    @brief A TreeAdaptor that works with any Tree implementation.
    """

    # BaseTreeAdaptor is abstract, no need to complain about not implemented
    # abstract methods
    # pylint: disable-msg=W0223

    def nil(self):
        return self.createWithPayload(None)


    def errorNode(self, input, start, stop, exc):
        """
        create tree node that holds the start and stop tokens associated
        with an error.

        If you specify your own kind of tree nodes, you will likely have to
        override this method. CommonTree returns Token.INVALID_TOKEN_TYPE
        if no token payload but you might have to set token type for diff
        node type.

        You don't have to subclass CommonErrorNode; you will likely need to
        subclass your own tree node class to avoid class cast exception.
        """

        return CommonErrorNode(input, start, stop, exc)


    def isNil(self, tree):
        return tree.isNil()


    def dupTree(self, t, parent=None):
        """
        This is generic in the sense that it will work with any kind of
        tree (not just Tree interface).  It invokes the adaptor routines
        not the tree node routines to do the construction.
        """

        if t is None:
            return None

        newTree = self.dupNode(t)

        # ensure new subtree root has parent/child index set

        # same index in new tree
        self.setChildIndex(newTree, self.getChildIndex(t))

        self.setParent(newTree, parent)

        for i in range(self.getChildCount(t)):
            child = self.getChild(t, i)
            newSubTree = self.dupTree(child, t)
            self.addChild(newTree, newSubTree)

        return newTree


    def addChild(self, tree, child):
        """
        Add a child to the tree t.  If child is a flat tree (a list), make all
        in list children of t.  Warning: if t has no children, but child does
        and child isNil then you can decide it is ok to move children to t via
        t.children = child.children; i.e., without copying the array.  Just
        make sure that this is consistent with have the user will build
        ASTs.
        """

        #if isinstance(child, Token):
        #    child = self.createWithPayload(child)

        if tree is not None and child is not None:
            tree.addChild(child)


    def becomeRoot(self, newRoot, oldRoot):
        """
        If oldRoot is a nil root, just copy or move the children to newRoot.
        If not a nil root, make oldRoot a child of newRoot.

          old=^(nil a b c), new=r yields ^(r a b c)
          old=^(a b c), new=r yields ^(r ^(a b c))

        If newRoot is a nil-rooted single child tree, use the single
        child as the new root node.

          old=^(nil a b c), new=^(nil r) yields ^(r a b c)
          old=^(a b c), new=^(nil r) yields ^(r ^(a b c))

        If oldRoot was null, it's ok, just return newRoot (even if isNil).

          old=null, new=r yields r
          old=null, new=^(nil r) yields ^(nil r)

        Return newRoot.  Throw an exception if newRoot is not a
        simple node or nil root with a single child node--it must be a root
        node.  If newRoot is ^(nil x) return x as newRoot.

        Be advised that it's ok for newRoot to point at oldRoot's
        children; i.e., you don't have to copy the list.  We are
        constructing these nodes so we should have this control for
        efficiency.
        """

        if isinstance(newRoot, Token):
            newRoot = self.create(newRoot)

        if oldRoot is None:
            return newRoot

        if not isinstance(newRoot, CommonTree):
            newRoot = self.createWithPayload(newRoot)

        # handle ^(nil real-node)
        if newRoot.isNil():
            nc = newRoot.getChildCount()
            if nc == 1:
                newRoot = newRoot.getChild(0)

            elif nc > 1:
                # TODO: make tree run time exceptions hierarchy
                raise RuntimeError("more than one node as root")

        # add oldRoot to newRoot; addChild takes care of case where oldRoot
        # is a flat list (i.e., nil-rooted tree).  All children of oldRoot
        # are added to newRoot.
        newRoot.addChild(oldRoot)
        return newRoot


    def rulePostProcessing(self, root):
        """Transform ^(nil x) to x and nil to null"""

        if root is not None and root.isNil():
            if root.getChildCount() == 0:
                root = None

            elif root.getChildCount() == 1:
                root = root.getChild(0)
                # whoever invokes rule will set parent and child index
                root.setParent(None)
                root.setChildIndex(-1)

        return root


    def createFromToken(self, tokenType, fromToken, text=None):
        if fromToken is None:
            return self.createFromType(tokenType, text)

        assert isinstance(tokenType, (int, long)), type(tokenType).__name__
        assert isinstance(fromToken, Token), type(fromToken).__name__
        assert text is None or isinstance(text, basestring), type(text).__name__

        fromToken = self.createToken(fromToken)
        fromToken.type = tokenType
        if text is not None:
            fromToken.text = text
        t = self.createWithPayload(fromToken)
        return t


    def createFromType(self, tokenType, text):
        assert isinstance(tokenType, (int, long)), type(tokenType).__name__
        assert isinstance(text, basestring) or text is None, type(text).__name__

        fromToken = self.createToken(tokenType=tokenType, text=text)
        t = self.createWithPayload(fromToken)
        return t


    def getType(self, t):
        return t.getType()


    def setType(self, t, type):
        raise RuntimeError("don't know enough about Tree node")


    def getText(self, t):
        return t.getText()


    def setText(self, t, text):
        raise RuntimeError("don't know enough about Tree node")


    def getChild(self, t, i):
        return t.getChild(i)


    def setChild(self, t, i, child):
        t.setChild(i, child)


    def deleteChild(self, t, i):
        return t.deleteChild(i)


    def getChildCount(self, t):
        return t.getChildCount()


    def getUniqueID(self, node):
        return hash(node)


    def createToken(self, fromToken=None, tokenType=None, text=None):
        """
        Tell me how to create a token for use with imaginary token nodes.
        For example, there is probably no input symbol associated with imaginary
        token DECL, but you need to create it as a payload or whatever for
        the DECL node as in ^(DECL type ID).

        If you care what the token payload objects' type is, you should
        override this method and any other createToken variant.
        """

        raise NotImplementedError


############################################################################
#
# common tree implementation
#
# Tree
# \- BaseTree
#    \- CommonTree
#       \- CommonErrorNode
#
# TreeAdaptor
# \- BaseTreeAdaptor
#    \- CommonTreeAdaptor
#
############################################################################


class CommonTree(BaseTree):
    """@brief A tree node that is wrapper for a Token object.

    After 3.0 release
    while building tree rewrite stuff, it became clear that computing
    parent and child index is very difficult and cumbersome.  Better to
    spend the space in every tree node.  If you don't want these extra
    fields, it's easy to cut them out in your own BaseTree subclass.

    """

    def __init__(self, payload):
        BaseTree.__init__(self)

        # What token indexes bracket all tokens associated with this node
        # and below?
        self.startIndex = -1
        self.stopIndex = -1

        # Who is the parent node of this node; if null, implies node is root
        self.parent = None

        # What index is this node in the child list? Range: 0..n-1
        self.childIndex = -1

        # A single token is the payload
        if payload is None:
            self.token = None

        elif isinstance(payload, CommonTree):
            self.token = payload.token
            self.startIndex = payload.startIndex
            self.stopIndex = payload.stopIndex

        elif payload is None or isinstance(payload, Token):
            self.token = payload

        else:
            raise TypeError(type(payload).__name__)



    def getToken(self):
        return self.token


    def dupNode(self):
        return CommonTree(self)


    def isNil(self):
        return self.token is None


    def getType(self):
        if self.token is None:
            return INVALID_TOKEN_TYPE

        return self.token.getType()

    type = property(getType)


    def getText(self):
        if self.token is None:
            return None

        return self.token.text

    text = property(getText)


    def getLine(self):
        if self.token is None or self.token.getLine() == 0:
            if self.getChildCount():
                return self.getChild(0).getLine()
            else:
                return 0

        return self.token.getLine()

    line = property(getLine)


    def getCharPositionInLine(self):
        if self.token is None or self.token.getCharPositionInLine() == -1:
            if self.getChildCount():
                return self.getChild(0).getCharPositionInLine()
            else:
                return 0

        else:
            return self.token.getCharPositionInLine()

    charPositionInLine = property(getCharPositionInLine)


    def getTokenStartIndex(self):
        if self.startIndex == -1 and self.token is not None:
            return self.token.getTokenIndex()

        return self.startIndex

    def setTokenStartIndex(self, index):
        self.startIndex = index

    tokenStartIndex = property(getTokenStartIndex, setTokenStartIndex)


    def getTokenStopIndex(self):
        if self.stopIndex == -1 and self.token is not None:
            return self.token.getTokenIndex()

        return self.stopIndex

    def setTokenStopIndex(self, index):
        self.stopIndex = index

    tokenStopIndex = property(getTokenStopIndex, setTokenStopIndex)


    def setUnknownTokenBoundaries(self):
        """For every node in this subtree, make sure it's start/stop token's
        are set.  Walk depth first, visit bottom up.  Only updates nodes
        with at least one token index < 0.
        """

        if self.children is None:
            if self.startIndex < 0 or self.stopIndex < 0:
                self.startIndex = self.stopIndex = self.token.getTokenIndex()

            return

        for child in self.children:
            child.setUnknownTokenBoundaries()

        if self.startIndex >= 0 and self.stopIndex >= 0:
            # already set
            return

        if self.children:
            firstChild = self.children[0]
            lastChild = self.children[-1]
            self.startIndex = firstChild.getTokenStartIndex()
            self.stopIndex = lastChild.getTokenStopIndex()


    def getChildIndex(self):
        #FIXME: mark as deprecated
        return self.childIndex


    def setChildIndex(self, idx):
        #FIXME: mark as deprecated
        self.childIndex = idx


    def getParent(self):
        #FIXME: mark as deprecated
        return self.parent


    def setParent(self, t):
        #FIXME: mark as deprecated
        self.parent = t


    def toString(self):
        if self.isNil():
            return "nil"

        if self.getType() == INVALID_TOKEN_TYPE:
            return "<errornode>"

        return self.token.text

    __str__ = toString



    def toStringTree(self):
        if not self.children:
            return self.toString()

        ret = ''
        if not self.isNil():
            ret += '(%s ' % (self.toString())

        ret += ' '.join([child.toStringTree() for child in self.children])

        if not self.isNil():
            ret += ')'

        return ret


INVALID_NODE = CommonTree(INVALID_TOKEN)


class CommonErrorNode(CommonTree):
    """A node representing erroneous token range in token stream"""

    def __init__(self, input, start, stop, exc):
        CommonTree.__init__(self, None)

        if (stop is None or
            (stop.getTokenIndex() < start.getTokenIndex() and
             stop.getType() != EOF
             )
            ):
            # sometimes resync does not consume a token (when LT(1) is
            # in follow set.  So, stop will be 1 to left to start. adjust.
            # Also handle case where start is the first token and no token
            # is consumed during recovery; LT(-1) will return null.
            stop = start

        self.input = input
        self.start = start
        self.stop = stop
        self.trappedException = exc


    def isNil(self):
        return False


    def getType(self):
        return INVALID_TOKEN_TYPE


    def getText(self):
        if isinstance(self.start, Token):
            i = self.start.getTokenIndex()
            j = self.stop.getTokenIndex()
            if self.stop.getType() == EOF:
                j = self.input.size()

            badText = self.input.toString(i, j)

        elif isinstance(self.start, Tree):
            badText = self.input.toString(self.start, self.stop)

        else:
            # people should subclass if they alter the tree type so this
            # next one is for sure correct.
            badText = "<unknown>"

        return badText


    def toString(self):
        if isinstance(self.trappedException, MissingTokenException):
            return ("<missing type: "
                    + str(self.trappedException.getMissingType())
                    + ">")

        elif isinstance(self.trappedException, UnwantedTokenException):
            return ("<extraneous: "
                    + str(self.trappedException.getUnexpectedToken())
                    + ", resync=" + self.getText() + ">")

        elif isinstance(self.trappedException, MismatchedTokenException):
            return ("<mismatched token: "
                    + str(self.trappedException.token)
                    + ", resync=" + self.getText() + ">")

        elif isinstance(self.trappedException, NoViableAltException):
            return ("<unexpected: "
                    + str(self.trappedException.token)
                    + ", resync=" + self.getText() + ">")

        return "<error: "+self.getText()+">"


class CommonTreeAdaptor(BaseTreeAdaptor):
    """
    @brief A TreeAdaptor that works with any Tree implementation.

    It provides
    really just factory methods; all the work is done by BaseTreeAdaptor.
    If you would like to have different tokens created than ClassicToken
    objects, you need to override this and then set the parser tree adaptor to
    use your subclass.

    To get your parser to build nodes of a different type, override
    create(Token), errorNode(), and to be safe, YourTreeClass.dupNode().
    dupNode is called to duplicate nodes during rewrite operations.
    """

    def dupNode(self, treeNode):
        """
        Duplicate a node.  This is part of the factory;
        override if you want another kind of node to be built.

        I could use reflection to prevent having to override this
        but reflection is slow.
        """

        if treeNode is None:
            return None

        return treeNode.dupNode()


    def createWithPayload(self, payload):
        return CommonTree(payload)


    def createToken(self, fromToken=None, tokenType=None, text=None):
        """
        Tell me how to create a token for use with imaginary token nodes.
        For example, there is probably no input symbol associated with imaginary
        token DECL, but you need to create it as a payload or whatever for
        the DECL node as in ^(DECL type ID).

        If you care what the token payload objects' type is, you should
        override this method and any other createToken variant.
        """

        if fromToken is not None:
            return CommonToken(oldToken=fromToken)

        return CommonToken(type=tokenType, text=text)


    def setTokenBoundaries(self, t, startToken, stopToken):
        """
        Track start/stop token for subtree root created for a rule.
        Only works with Tree nodes.  For rules that match nothing,
        seems like this will yield start=i and stop=i-1 in a nil node.
        Might be useful info so I'll not force to be i..i.
        """

        if t is None:
            return

        start = 0
        stop = 0

        if startToken is not None:
            start = startToken.index

        if stopToken is not None:
            stop = stopToken.index

        t.setTokenStartIndex(start)
        t.setTokenStopIndex(stop)


    def getTokenStartIndex(self, t):
        if t is None:
            return -1
        return t.getTokenStartIndex()


    def getTokenStopIndex(self, t):
        if t is None:
            return -1
        return t.getTokenStopIndex()


    def getText(self, t):
        if t is None:
            return None
        return t.getText()


    def getType(self, t):
        if t is None:
            return INVALID_TOKEN_TYPE

        return t.getType()


    def getToken(self, t):
        """
        What is the Token associated with this node?  If
        you are not using CommonTree, then you must
        override this in your own adaptor.
        """

        if isinstance(t, CommonTree):
            return t.getToken()

        return None # no idea what to do


    def getChild(self, t, i):
        if t is None:
            return None
        return t.getChild(i)


    def getChildCount(self, t):
        if t is None:
            return 0
        return t.getChildCount()


    def getParent(self, t):
        return t.getParent()


    def setParent(self, t, parent):
        t.setParent(parent)


    def getChildIndex(self, t):
        if t is None:
            return 0
        return t.getChildIndex()


    def setChildIndex(self, t, index):
        t.setChildIndex(index)


    def replaceChildren(self, parent, startChildIndex, stopChildIndex, t):
        if parent is not None:
            parent.replaceChildren(startChildIndex, stopChildIndex, t)


############################################################################
#
# streams
#
# TreeNodeStream
# \- BaseTree
#    \- CommonTree
#
# TreeAdaptor
# \- BaseTreeAdaptor
#    \- CommonTreeAdaptor
#
############################################################################



class TreeNodeStream(IntStream):
    """@brief A stream of tree nodes

    It accessing nodes from a tree of some kind.
    """

    # TreeNodeStream is abstract, no need to complain about not implemented
    # abstract methods
    # pylint: disable-msg=W0223

    def get(self, i):
        """Get a tree node at an absolute index i; 0..n-1.
        If you don't want to buffer up nodes, then this method makes no
        sense for you.
        """

        raise NotImplementedError


    def LT(self, k):
        """
        Get tree node at current input pointer + i ahead where i=1 is next node.
        i<0 indicates nodes in the past.  So LT(-1) is previous node, but
        implementations are not required to provide results for k < -1.
        LT(0) is undefined.  For i>=n, return null.
        Return null for LT(0) and any index that results in an absolute address
        that is negative.

        This is analogus to the LT() method of the TokenStream, but this
        returns a tree node instead of a token.  Makes code gen identical
        for both parser and tree grammars. :)
        """

        raise NotImplementedError


    def getTreeSource(self):
        """
        Where is this stream pulling nodes from?  This is not the name, but
        the object that provides node objects.
        """

        raise NotImplementedError


    def getTokenStream(self):
        """
        If the tree associated with this stream was created from a TokenStream,
        you can specify it here.  Used to do rule $text attribute in tree
        parser.  Optional unless you use tree parser rule text attribute
        or output=template and rewrite=true options.
        """

        raise NotImplementedError


    def getTreeAdaptor(self):
        """
        What adaptor can tell me how to interpret/navigate nodes and
        trees.  E.g., get text of a node.
        """

        raise NotImplementedError


    def setUniqueNavigationNodes(self, uniqueNavigationNodes):
        """
        As we flatten the tree, we use UP, DOWN nodes to represent
        the tree structure.  When debugging we need unique nodes
        so we have to instantiate new ones.  When doing normal tree
        parsing, it's slow and a waste of memory to create unique
        navigation nodes.  Default should be false;
        """

        raise NotImplementedError


    def reset(self):
        """
        Reset the tree node stream in such a way that it acts like
        a freshly constructed stream.
        """

        raise NotImplementedError


    def toString(self, start, stop):
        """
        Return the text of all nodes from start to stop, inclusive.
        If the stream does not buffer all the nodes then it can still
        walk recursively from start until stop.  You can always return
        null or "" too, but users should not access $ruleLabel.text in
        an action of course in that case.
        """

        raise NotImplementedError


    # REWRITING TREES (used by tree parser)
    def replaceChildren(self, parent, startChildIndex, stopChildIndex, t):
        """
 	Replace from start to stop child index of parent with t, which might
        be a list.  Number of children may be different
        after this call.  The stream is notified because it is walking the
        tree and might need to know you are monkeying with the underlying
        tree.  Also, it might be able to modify the node stream to avoid
        restreaming for future phases.

        If parent is null, don't do anything; must be at root of overall tree.
        Can't replace whatever points to the parent externally.  Do nothing.
        """

        raise NotImplementedError


class CommonTreeNodeStream(TreeNodeStream):
    """@brief A buffered stream of tree nodes.

    Nodes can be from a tree of ANY kind.

    This node stream sucks all nodes out of the tree specified in
    the constructor during construction and makes pointers into
    the tree using an array of Object pointers. The stream necessarily
    includes pointers to DOWN and UP and EOF nodes.

    This stream knows how to mark/release for backtracking.

    This stream is most suitable for tree interpreters that need to
    jump around a lot or for tree parsers requiring speed (at cost of memory).
    There is some duplicated functionality here with UnBufferedTreeNodeStream
    but just in bookkeeping, not tree walking etc...

    @see UnBufferedTreeNodeStream
    """

    def __init__(self, *args):
        TreeNodeStream.__init__(self)

        if len(args) == 1:
            adaptor = CommonTreeAdaptor()
            tree = args[0]

            nodes = None
            down = None
            up = None
            eof = None

        elif len(args) == 2:
            adaptor = args[0]
            tree = args[1]

            nodes = None
            down = None
            up = None
            eof = None

        elif len(args) == 3:
            parent = args[0]
            start = args[1]
            stop = args[2]

            adaptor = parent.adaptor
            tree = parent.root

            nodes = parent.nodes[start:stop]
            down = parent.down
            up = parent.up
            eof = parent.eof

        else:
            raise TypeError("Invalid arguments")

        # all these navigation nodes are shared and hence they
        # cannot contain any line/column info
        if down is not None:
            self.down = down
        else:
            self.down = adaptor.createFromType(DOWN, "DOWN")

        if up is not None:
            self.up = up
        else:
            self.up = adaptor.createFromType(UP, "UP")

        if eof is not None:
            self.eof = eof
        else:
            self.eof = adaptor.createFromType(EOF, "EOF")

        # The complete mapping from stream index to tree node.
        # This buffer includes pointers to DOWN, UP, and EOF nodes.
        # It is built upon ctor invocation.  The elements are type
        #  Object as we don't what the trees look like.

        # Load upon first need of the buffer so we can set token types
        # of interest for reverseIndexing.  Slows us down a wee bit to
        # do all of the if p==-1 testing everywhere though.
        if nodes is not None:
            self.nodes = nodes
        else:
            self.nodes = []

        # Pull nodes from which tree?
        self.root = tree

        # IF this tree (root) was created from a token stream, track it.
        self.tokens = None

        # What tree adaptor was used to build these trees
        self.adaptor = adaptor

        # Reuse same DOWN, UP navigation nodes unless this is true
        self.uniqueNavigationNodes = False

        # The index into the nodes list of the current node (next node
        # to consume).  If -1, nodes array not filled yet.
        self.p = -1

        # Track the last mark() call result value for use in rewind().
        self.lastMarker = None

        # Stack of indexes used for push/pop calls
        self.calls = []


    def __iter__(self):
        return TreeIterator(self.root, self.adaptor)


    def fillBuffer(self):
        """Walk tree with depth-first-search and fill nodes buffer.
        Don't do DOWN, UP nodes if its a list (t is isNil).
        """

        self._fillBuffer(self.root)
        self.p = 0 # buffer of nodes intialized now


    def _fillBuffer(self, t):
        nil = self.adaptor.isNil(t)

        if not nil:
            self.nodes.append(t) # add this node

        # add DOWN node if t has children
        n = self.adaptor.getChildCount(t)
        if not nil and n > 0:
            self.addNavigationNode(DOWN)

        # and now add all its children
        for c in range(n):
            self._fillBuffer(self.adaptor.getChild(t, c))

        # add UP node if t has children
        if not nil and n > 0:
            self.addNavigationNode(UP)


    def getNodeIndex(self, node):
        """What is the stream index for node? 0..n-1
        Return -1 if node not found.
        """

        if self.p == -1:
            self.fillBuffer()

        for i, t in enumerate(self.nodes):
            if t == node:
                return i

        return -1


    def addNavigationNode(self, ttype):
        """
        As we flatten the tree, we use UP, DOWN nodes to represent
        the tree structure.  When debugging we need unique nodes
        so instantiate new ones when uniqueNavigationNodes is true.
        """

        navNode = None

        if ttype == DOWN:
            if self.hasUniqueNavigationNodes():
                navNode = self.adaptor.createFromType(DOWN, "DOWN")

            else:
                navNode = self.down

        else:
            if self.hasUniqueNavigationNodes():
                navNode = self.adaptor.createFromType(UP, "UP")

            else:
                navNode = self.up

        self.nodes.append(navNode)


    def get(self, i):
        if self.p == -1:
            self.fillBuffer()

        return self.nodes[i]


    def LT(self, k):
        if self.p == -1:
            self.fillBuffer()

        if k == 0:
            return None

        if k < 0:
            return self.LB(-k)

        if self.p + k - 1 >= len(self.nodes):
            return self.eof

        return self.nodes[self.p + k - 1]


    def getCurrentSymbol(self):
        return self.LT(1)


    def LB(self, k):
        """Look backwards k nodes"""

        if k == 0:
            return None

        if self.p - k < 0:
            return None

        return self.nodes[self.p - k]


    def isEOF(self, obj):
        return self.adaptor.getType(obj) == EOF


    def getTreeSource(self):
        return self.root


    def getSourceName(self):
        return self.getTokenStream().getSourceName()


    def getTokenStream(self):
        return self.tokens


    def setTokenStream(self, tokens):
        self.tokens = tokens


    def getTreeAdaptor(self):
        return self.adaptor


    def hasUniqueNavigationNodes(self):
        return self.uniqueNavigationNodes


    def setUniqueNavigationNodes(self, uniqueNavigationNodes):
        self.uniqueNavigationNodes = uniqueNavigationNodes


    def consume(self):
        if self.p == -1:
            self.fillBuffer()

        self.p += 1


    def LA(self, i):
        return self.adaptor.getType(self.LT(i))


    def mark(self):
        if self.p == -1:
            self.fillBuffer()


        self.lastMarker = self.index()
        return self.lastMarker


    def release(self, marker=None):
        # no resources to release

        pass


    def index(self):
        return self.p


    def rewind(self, marker=None):
        if marker is None:
            marker = self.lastMarker

        self.seek(marker)


    def seek(self, index):
        if self.p == -1:
            self.fillBuffer()

        self.p = index


    def push(self, index):
        """
        Make stream jump to a new location, saving old location.
        Switch back with pop().
        """

        self.calls.append(self.p) # save current index
        self.seek(index)


    def pop(self):
        """
        Seek back to previous index saved during last push() call.
        Return top of stack (return index).
        """

        ret = self.calls.pop(-1)
        self.seek(ret)
        return ret


    def reset(self):
        self.p = 0
        self.lastMarker = 0
        self.calls = []


    def size(self):
        if self.p == -1:
            self.fillBuffer()

        return len(self.nodes)


    # TREE REWRITE INTERFACE

    def replaceChildren(self, parent, startChildIndex, stopChildIndex, t):
        if parent is not None:
            self.adaptor.replaceChildren(
                parent, startChildIndex, stopChildIndex, t
                )


    def __str__(self):
        """Used for testing, just return the token type stream"""

        if self.p == -1:
            self.fillBuffer()

        return ' '.join([str(self.adaptor.getType(node))
                         for node in self.nodes
                         ])


    def toString(self, start, stop):
        if start is None or stop is None:
            return None

        if self.p == -1:
            self.fillBuffer()

        #System.out.println("stop: "+stop);
        #if ( start instanceof CommonTree )
        #    System.out.print("toString: "+((CommonTree)start).getToken()+", ");
        #else
        #    System.out.println(start);
        #if ( stop instanceof CommonTree )
        #    System.out.println(((CommonTree)stop).getToken());
        #else
        #    System.out.println(stop);

        # if we have the token stream, use that to dump text in order
        if self.tokens is not None:
            beginTokenIndex = self.adaptor.getTokenStartIndex(start)
            endTokenIndex = self.adaptor.getTokenStopIndex(stop)

            # if it's a tree, use start/stop index from start node
            # else use token range from start/stop nodes
            if self.adaptor.getType(stop) == UP:
                endTokenIndex = self.adaptor.getTokenStopIndex(start)

            elif self.adaptor.getType(stop) == EOF:
                endTokenIndex = self.size() -2 # don't use EOF

            return self.tokens.toString(beginTokenIndex, endTokenIndex)

        # walk nodes looking for start
        i, t = 0, None
        for i, t in enumerate(self.nodes):
            if t == start:
                break

        # now walk until we see stop, filling string buffer with text
        buf = []
        t = self.nodes[i]
        while t != stop:
            text = self.adaptor.getText(t)
            if text is None:
                text = " " + self.adaptor.getType(t)

            buf.append(text)
            i += 1
            t = self.nodes[i]

        # include stop node too
        text = self.adaptor.getText(stop)
        if text is None:
            text = " " +self.adaptor.getType(stop)

        buf.append(text)

        return ''.join(buf)


    ## iterator interface
    def __iter__(self):
        if self.p == -1:
            self.fillBuffer()

        for node in self.nodes:
            yield node


#############################################################################
#
# tree parser
#
#############################################################################

class TreeParser(BaseRecognizer):
    """@brief Baseclass for generated tree parsers.

    A parser for a stream of tree nodes.  "tree grammars" result in a subclass
    of this.  All the error reporting and recovery is shared with Parser via
    the BaseRecognizer superclass.
    """

    def __init__(self, input, state=None):
        BaseRecognizer.__init__(self, state)

        self.input = None
        self.setTreeNodeStream(input)


    def reset(self):
        BaseRecognizer.reset(self) # reset all recognizer state variables
        if self.input is not None:
            self.input.seek(0) # rewind the input


    def setTreeNodeStream(self, input):
        """Set the input stream"""

        self.input = input


    def getTreeNodeStream(self):
        return self.input


    def getSourceName(self):
        return self.input.getSourceName()


    def getCurrentInputSymbol(self, input):
        return input.LT(1)


    def getMissingSymbol(self, input, e, expectedTokenType, follow):
        tokenText = "<missing " + self.tokenNames[expectedTokenType] + ">"
        adaptor = input.adaptor
        return adaptor.createToken(
            CommonToken(type=expectedTokenType, text=tokenText))


    # precompiled regex used by inContext
    dotdot = ".*[^.]\\.\\.[^.].*"
    doubleEtc = ".*\\.\\.\\.\\s+\\.\\.\\..*"
    dotdotPattern = re.compile(dotdot)
    doubleEtcPattern = re.compile(doubleEtc)

    def inContext(self, context, adaptor=None, tokenName=None, t=None):
        """Check if current node in input has a context.

        Context means sequence of nodes towards root of tree.  For example,
        you might say context is "MULT" which means my parent must be MULT.
        "CLASS VARDEF" says current node must be child of a VARDEF and whose
        parent is a CLASS node.  You can use "..." to mean zero-or-more nodes.
        "METHOD ... VARDEF" means my parent is VARDEF and somewhere above
        that is a METHOD node.  The first node in the context is not
        necessarily the root.  The context matcher stops matching and returns
        true when it runs out of context.  There is no way to force the first
        node to be the root.
        """

        return _inContext(
            self.input.getTreeAdaptor(), self.getTokenNames(),
            self.input.LT(1), context)

    @classmethod
    def _inContext(cls, adaptor, tokenNames, t, context):
        """The worker for inContext.

        It's static and full of parameters for testing purposes.
        """

        if cls.dotdotPattern.match(context):
            # don't allow "..", must be "..."
            raise ValueError("invalid syntax: ..")

        if cls.doubleEtcPattern.match(context):
            # don't allow double "..."
            raise ValueError("invalid syntax: ... ...")

        # ensure spaces around ...
        context = context.replace("...", " ... ")
        context = context.strip()
        nodes = context.split()

        ni = len(nodes) - 1
        t = adaptor.getParent(t)
        while ni >= 0 and t is not None:
            if nodes[ni] == "...":
                # walk upwards until we see nodes[ni-1] then continue walking
                if ni == 0:
                    # ... at start is no-op
                    return True
                goal = nodes[ni-1]
                ancestor = cls._getAncestor(adaptor, tokenNames, t, goal)
                if ancestor is None:
                    return False
                t = ancestor
                ni -= 1

            name = tokenNames[adaptor.getType(t)]
            if name != nodes[ni]:
                return False

            # advance to parent and to previous element in context node list
            ni -= 1
            t = adaptor.getParent(t)

        # at root but more nodes to match
        if t is None and ni >= 0:
            return False

        return True

    @staticmethod
    def _getAncestor(adaptor, tokenNames, t, goal):
        """Helper for static inContext."""
        while t is not None:
            name = tokenNames[adaptor.getType(t)]
            if name == goal:
                return t
            t = adaptor.getParent(t)

        return None


    def matchAny(self, ignore): # ignore stream, copy of this.input
        """
        Match '.' in tree parser has special meaning.  Skip node or
        entire tree if node has children.  If children, scan until
        corresponding UP node.
        """

        self._state.errorRecovery = False

        look = self.input.LT(1)
        if self.input.getTreeAdaptor().getChildCount(look) == 0:
            self.input.consume() # not subtree, consume 1 node and return
            return

        # current node is a subtree, skip to corresponding UP.
        # must count nesting level to get right UP
        level = 0
        tokenType = self.input.getTreeAdaptor().getType(look)
        while tokenType != EOF and not (tokenType == UP and level==0):
            self.input.consume()
            look = self.input.LT(1)
            tokenType = self.input.getTreeAdaptor().getType(look)
            if tokenType == DOWN:
                level += 1

            elif tokenType == UP:
                level -= 1

        self.input.consume() # consume UP


    def mismatch(self, input, ttype, follow):
        """
        We have DOWN/UP nodes in the stream that have no line info; override.
        plus we want to alter the exception type. Don't try to recover
        from tree parser errors inline...
        """

        raise MismatchedTreeNodeException(ttype, input)


    def getErrorHeader(self, e):
        """
        Prefix error message with the grammar name because message is
        always intended for the programmer because the parser built
        the input tree not the user.
        """

        return (self.getGrammarFileName() +
                ": node from %sline %s:%s"
                % (['', "after "][e.approximateLineInfo],
                   e.line,
                   e.charPositionInLine
                   )
                )

    def getErrorMessage(self, e, tokenNames):
        """
        Tree parsers parse nodes they usually have a token object as
        payload. Set the exception token and do the default behavior.
        """

        if isinstance(self, TreeParser):
            adaptor = e.input.getTreeAdaptor()
            e.token = adaptor.getToken(e.node)
            if e.token is not None: # could be an UP/DOWN node
                e.token = CommonToken(
                    type=adaptor.getType(e.node),
                    text=adaptor.getText(e.node)
                    )

        return BaseRecognizer.getErrorMessage(self, e, tokenNames)


    def traceIn(self, ruleName, ruleIndex):
        BaseRecognizer.traceIn(self, ruleName, ruleIndex, self.input.LT(1))


    def traceOut(self, ruleName, ruleIndex):
        BaseRecognizer.traceOut(self, ruleName, ruleIndex, self.input.LT(1))


#############################################################################
#
# tree visitor
#
#############################################################################

class TreeVisitor(object):
    """Do a depth first walk of a tree, applying pre() and post() actions
    we go.
    """

    def __init__(self, adaptor=None):
        if adaptor is not None:
            self.adaptor = adaptor
        else:
            self.adaptor = CommonTreeAdaptor()

    def visit(self, t, pre_action=None, post_action=None):
        """Visit every node in tree t and trigger an action for each node
        before/after having visited all of its children.  Bottom up walk.
        Execute both actions even if t has no children.  Ignore return
        results from transforming children since they will have altered
        the child list of this node (their parent).  Return result of
        applying post action to this node.

        The Python version differs from the Java version by taking two
        callables 'pre_action' and 'post_action' instead of a class instance
        that wraps those methods. Those callables must accept a TreeNode as
        their single argument and return the (potentially transformed or
        replaced) TreeNode.
        """

        isNil = self.adaptor.isNil(t)
        if pre_action is not None and not isNil:
            # if rewritten, walk children of new t
            t = pre_action(t)

        idx = 0
        while idx < self.adaptor.getChildCount(t):
            child = self.adaptor.getChild(t, idx)
            self.visit(child, pre_action, post_action)
            idx += 1

        if post_action is not None and not isNil:
            t = post_action(t)

        return t

#############################################################################
#
# tree iterator
#
#############################################################################

class TreeIterator(object):
    """
    Return a node stream from a doubly-linked tree whose nodes
    know what child index they are.

    Emit navigation nodes (DOWN, UP, and EOF) to let show tree structure.
    """

    def __init__(self, tree, adaptor=None):
        if adaptor is None:
            adaptor = CommonTreeAdaptor()

        self.root = tree
        self.adaptor = adaptor

        self.first_time = True
        self.tree = tree

        # If we emit UP/DOWN nodes, we need to spit out multiple nodes per
        # next() call.
        self.nodes = []

        # navigation nodes to return during walk and at end
        self.down = adaptor.createFromType(DOWN, "DOWN")
        self.up = adaptor.createFromType(UP, "UP")
        self.eof = adaptor.createFromType(EOF, "EOF")


    def reset(self):
        self.first_time = True
        self.tree = self.root
        self.nodes = []


    def __iter__(self):
        return self


    def has_next(self):
        if self.first_time:
            return self.root is not None

        if len(self.nodes) > 0:
            return True

        if self.tree is None:
            return False

        if self.adaptor.getChildCount(self.tree) > 0:
            return True

        # back at root?
        return self.adaptor.getParent(self.tree) is not None


    def next(self):
        if not self.has_next():
            raise StopIteration

        if self.first_time:
            # initial condition
            self.first_time = False
            if self.adaptor.getChildCount(self.tree) == 0:
                # single node tree (special)
                self.nodes.append(self.eof)
                return self.tree

            return self.tree

        # if any queued up, use those first
        if len(self.nodes) > 0:
            return self.nodes.pop(0)

        # no nodes left?
        if self.tree is None:
            return self.eof

        # next node will be child 0 if any children
        if self.adaptor.getChildCount(self.tree) > 0:
            self.tree = self.adaptor.getChild(self.tree, 0)
            # real node is next after DOWN
            self.nodes.append(self.tree)
            return self.down

        # if no children, look for next sibling of tree or ancestor
        parent = self.adaptor.getParent(self.tree)
        # while we're out of siblings, keep popping back up towards root
        while (parent is not None
               and self.adaptor.getChildIndex(self.tree)+1 >= self.adaptor.getChildCount(parent)):
            # we're moving back up
            self.nodes.append(self.up)
            self.tree = parent
            parent = self.adaptor.getParent(self.tree)

        # no nodes left?
        if parent is None:
            self.tree = None # back at root? nothing left then
            self.nodes.append(self.eof) # add to queue, might have UP nodes in there
            return self.nodes.pop(0)

        # must have found a node with an unvisited sibling
        # move to it and return it
        nextSiblingIndex = self.adaptor.getChildIndex(self.tree) + 1
        self.tree = self.adaptor.getChild(parent, nextSiblingIndex)
        self.nodes.append(self.tree) # add to queue, might have UP nodes in there
        return self.nodes.pop(0)



#############################################################################
#
# streams for rule rewriting
#
#############################################################################

class RewriteRuleElementStream(object):
    """@brief Internal helper class.

    A generic list of elements tracked in an alternative to be used in
    a -> rewrite rule.  We need to subclass to fill in the next() method,
    which returns either an AST node wrapped around a token payload or
    an existing subtree.

    Once you start next()ing, do not try to add more elements.  It will
    break the cursor tracking I believe.

    @see org.antlr.runtime.tree.RewriteRuleSubtreeStream
    @see org.antlr.runtime.tree.RewriteRuleTokenStream

    TODO: add mechanism to detect/puke on modification after reading from
    stream
    """

    def __init__(self, adaptor, elementDescription, elements=None):
        # Cursor 0..n-1.  If singleElement!=null, cursor is 0 until you next(),
        # which bumps it to 1 meaning no more elements.
        self.cursor = 0

        # Track single elements w/o creating a list.  Upon 2nd add, alloc list
        self.singleElement = None

        # The list of tokens or subtrees we are tracking
        self.elements = None

        # Once a node / subtree has been used in a stream, it must be dup'd
        # from then on.  Streams are reset after subrules so that the streams
        # can be reused in future subrules.  So, reset must set a dirty bit.
        # If dirty, then next() always returns a dup.
        self.dirty = False

        # The element or stream description; usually has name of the token or
        # rule reference that this list tracks.  Can include rulename too, but
        # the exception would track that info.
        self.elementDescription = elementDescription

        self.adaptor = adaptor

        if isinstance(elements, (list, tuple)):
            # Create a stream, but feed off an existing list
            self.singleElement = None
            self.elements = elements

        else:
            # Create a stream with one element
            self.add(elements)


    def reset(self):
        """
        Reset the condition of this stream so that it appears we have
        not consumed any of its elements.  Elements themselves are untouched.
        Once we reset the stream, any future use will need duplicates.  Set
        the dirty bit.
        """

        self.cursor = 0
        self.dirty = True


    def add(self, el):
        if el is None:
            return

        if self.elements is not None: # if in list, just add
            self.elements.append(el)
            return

        if self.singleElement is None: # no elements yet, track w/o list
            self.singleElement = el
            return

        # adding 2nd element, move to list
        self.elements = []
        self.elements.append(self.singleElement)
        self.singleElement = None
        self.elements.append(el)


    def nextTree(self):
        """
        Return the next element in the stream.  If out of elements, throw
        an exception unless size()==1.  If size is 1, then return elements[0].

        Return a duplicate node/subtree if stream is out of elements and
        size==1. If we've already used the element, dup (dirty bit set).
        """

        if (self.dirty
            or (self.cursor >= len(self) and len(self) == 1)
            ):
            # if out of elements and size is 1, dup
            el = self._next()
            return self.dup(el)

        # test size above then fetch
        el = self._next()
        return el


    def _next(self):
        """
        do the work of getting the next element, making sure that it's
        a tree node or subtree.  Deal with the optimization of single-
        element list versus list of size > 1.  Throw an exception
        if the stream is empty or we're out of elements and size>1.
        protected so you can override in a subclass if necessary.
        """

        if len(self) == 0:
            raise RewriteEmptyStreamException(self.elementDescription)

        if self.cursor >= len(self): # out of elements?
            if len(self) == 1: # if size is 1, it's ok; return and we'll dup
                return self.toTree(self.singleElement)

            # out of elements and size was not 1, so we can't dup
            raise RewriteCardinalityException(self.elementDescription)

        # we have elements
        if self.singleElement is not None:
            self.cursor += 1 # move cursor even for single element list
            return self.toTree(self.singleElement)

        # must have more than one in list, pull from elements
        o = self.toTree(self.elements[self.cursor])
        self.cursor += 1
        return o


    def dup(self, el):
        """
        When constructing trees, sometimes we need to dup a token or AST
        subtree.  Dup'ing a token means just creating another AST node
        around it.  For trees, you must call the adaptor.dupTree() unless
        the element is for a tree root; then it must be a node dup.
        """

        raise NotImplementedError


    def toTree(self, el):
        """
        Ensure stream emits trees; tokens must be converted to AST nodes.
        AST nodes can be passed through unmolested.
        """

        return el


    def hasNext(self):
        return ( (self.singleElement is not None and self.cursor < 1)
                 or (self.elements is not None
                     and self.cursor < len(self.elements)
                     )
                 )


    def size(self):
        if self.singleElement is not None:
            return 1

        if self.elements is not None:
            return len(self.elements)

        return 0

    __len__ = size


    def getDescription(self):
        """Deprecated. Directly access elementDescription attribute"""

        return self.elementDescription


class RewriteRuleTokenStream(RewriteRuleElementStream):
    """@brief Internal helper class."""

    def toTree(self, el):
        # Don't convert to a tree unless they explicitly call nextTree.
        # This way we can do hetero tree nodes in rewrite.
        return el


    def nextNode(self):
        t = self._next()
        return self.adaptor.createWithPayload(t)


    def nextToken(self):
        return self._next()


    def dup(self, el):
        raise TypeError("dup can't be called for a token stream.")


class RewriteRuleSubtreeStream(RewriteRuleElementStream):
    """@brief Internal helper class."""

    def nextNode(self):
        """
        Treat next element as a single node even if it's a subtree.
        This is used instead of next() when the result has to be a
        tree root node.  Also prevents us from duplicating recently-added
        children; e.g., ^(type ID)+ adds ID to type and then 2nd iteration
        must dup the type node, but ID has been added.

        Referencing a rule result twice is ok; dup entire tree as
        we can't be adding trees as root; e.g., expr expr.

        Hideous code duplication here with super.next().  Can't think of
        a proper way to refactor.  This needs to always call dup node
        and super.next() doesn't know which to call: dup node or dup tree.
        """

        if (self.dirty
            or (self.cursor >= len(self) and len(self) == 1)
            ):
            # if out of elements and size is 1, dup (at most a single node
            # since this is for making root nodes).
            el = self._next()
            return self.adaptor.dupNode(el)

        # test size above then fetch
        el = self._next()
        while self.adaptor.isNil(el) and self.adaptor.getChildCount(el) == 1:
            el = self.adaptor.getChild(el, 0)

        # dup just the root (want node here)
        return self.adaptor.dupNode(el)


    def dup(self, el):
        return self.adaptor.dupTree(el)



class RewriteRuleNodeStream(RewriteRuleElementStream):
    """
    Queues up nodes matched on left side of -> in a tree parser. This is
    the analog of RewriteRuleTokenStream for normal parsers.
    """

    def nextNode(self):
        return self._next()


    def toTree(self, el):
        return self.adaptor.dupNode(el)


    def dup(self, el):
        # we dup every node, so don't have to worry about calling dup; short-
        #circuited next() so it doesn't call.
        raise TypeError("dup can't be called for a node stream.")


class TreeRuleReturnScope(RuleReturnScope):
    """
    This is identical to the ParserRuleReturnScope except that
    the start property is a tree nodes not Token object
    when you are parsing trees.  To be generic the tree node types
    have to be Object.
    """

    def __init__(self):
        self.start = None
        self.tree = None


    def getStart(self):
        return self.start


    def getTree(self):
        return self.tree
