# -*- coding: utf-8 -*-

import os
import unittest
from StringIO import StringIO

from antlr3.tree import (CommonTreeNodeStream, CommonTree, CommonTreeAdaptor,
                         TreeParser, TreeVisitor, TreeIterator)
from antlr3 import CommonToken, UP, DOWN, EOF
from antlr3.treewizard import TreeWizard

class TestTreeNodeStream(unittest.TestCase):
    """Test case for the TreeNodeStream class."""

    def setUp(self):
        self.adaptor = CommonTreeAdaptor()


    def newStream(self, t):
        """Build new stream; let's us override to test other streams."""
        return CommonTreeNodeStream(t)


    def testSingleNode(self):
        t = CommonTree(CommonToken(101))

        stream = self.newStream(t)
        expecting = "101"
        found = self.toNodesOnlyString(stream)
        self.failUnlessEqual(expecting, found)

        expecting = "101"
        found = str(stream)
        self.failUnlessEqual(expecting, found)


    def testTwoChildrenOfNilRoot(self):
        class V(CommonTree):
            def __init__(self, token=None, ttype=None, x=None):
                if x is not None:
                    self.x = x

                if ttype is not None and token is None:
                    self.token = CommonToken(type=ttype)

                if token is not None:
                    self.token = token

            def __str__(self):
                if self.token is not None:
                    txt = self.token.text
                else:
                    txt = ""

                txt += "<V>"
                return txt

        root_0 = self.adaptor.nil();
        t = V(ttype=101, x=2)
        u = V(token=CommonToken(type=102, text="102"))
        self.adaptor.addChild(root_0, t)
        self.adaptor.addChild(root_0, u)
        self.assert_(root_0.parent is None)
        self.assertEquals(-1, root_0.childIndex)
        self.assertEquals(0, t.childIndex)
        self.assertEquals(1, u.childIndex)


    def test4Nodes(self):
        # ^(101 ^(102 103) 104)
        t = CommonTree(CommonToken(101))
        t.addChild(CommonTree(CommonToken(102)))
        t.getChild(0).addChild(CommonTree(CommonToken(103)))
        t.addChild(CommonTree(CommonToken(104)))

        stream = self.newStream(t)
        expecting = "101 102 103 104"
        found = self.toNodesOnlyString(stream)
        self.failUnlessEqual(expecting, found)

        expecting = "101 2 102 2 103 3 104 3"
        found = str(stream)
        self.failUnlessEqual(expecting, found)


    def testList(self):
        root = CommonTree(None)

        t = CommonTree(CommonToken(101))
        t.addChild(CommonTree(CommonToken(102)))
        t.getChild(0).addChild(CommonTree(CommonToken(103)))
        t.addChild(CommonTree(CommonToken(104)))

        u = CommonTree(CommonToken(105))

        root.addChild(t)
        root.addChild(u)

        stream = CommonTreeNodeStream(root)
        expecting = "101 102 103 104 105"
        found = self.toNodesOnlyString(stream)
        self.failUnlessEqual(expecting, found)

        expecting = "101 2 102 2 103 3 104 3 105"
        found = str(stream)
        self.failUnlessEqual(expecting, found)


    def testFlatList(self):
        root = CommonTree(None)

        root.addChild(CommonTree(CommonToken(101)))
        root.addChild(CommonTree(CommonToken(102)))
        root.addChild(CommonTree(CommonToken(103)))

        stream = CommonTreeNodeStream(root)
        expecting = "101 102 103"
        found = self.toNodesOnlyString(stream)
        self.failUnlessEqual(expecting, found)

        expecting = "101 102 103"
        found = str(stream)
        self.failUnlessEqual(expecting, found)


    def testListWithOneNode(self):
        root = CommonTree(None)

        root.addChild(CommonTree(CommonToken(101)))

        stream = CommonTreeNodeStream(root)
        expecting = "101"
        found = self.toNodesOnlyString(stream)
        self.failUnlessEqual(expecting, found)

        expecting = "101"
        found = str(stream)
        self.failUnlessEqual(expecting, found)


    def testAoverB(self):
        t = CommonTree(CommonToken(101))
        t.addChild(CommonTree(CommonToken(102)))

        stream = self.newStream(t)
        expecting = "101 102"
        found = self.toNodesOnlyString(stream)
        self.failUnlessEqual(expecting, found)

        expecting = "101 2 102 3"
        found = str(stream)
        self.failUnlessEqual(expecting, found)


    def testLT(self):
        # ^(101 ^(102 103) 104)
        t = CommonTree(CommonToken(101))
        t.addChild(CommonTree(CommonToken(102)))
        t.getChild(0).addChild(CommonTree(CommonToken(103)))
        t.addChild(CommonTree(CommonToken(104)))

        stream = self.newStream(t)
        self.failUnlessEqual(101, stream.LT(1).getType())
        self.failUnlessEqual(DOWN, stream.LT(2).getType())
        self.failUnlessEqual(102, stream.LT(3).getType())
        self.failUnlessEqual(DOWN, stream.LT(4).getType())
        self.failUnlessEqual(103, stream.LT(5).getType())
        self.failUnlessEqual(UP, stream.LT(6).getType())
        self.failUnlessEqual(104, stream.LT(7).getType())
        self.failUnlessEqual(UP, stream.LT(8).getType())
        self.failUnlessEqual(EOF, stream.LT(9).getType())
        # check way ahead
        self.failUnlessEqual(EOF, stream.LT(100).getType())


    def testMarkRewindEntire(self):
        # ^(101 ^(102 103 ^(106 107) ) 104 105)
        # stream has 7 real + 6 nav nodes
        # Sequence of types: 101 DN 102 DN 103 106 DN 107 UP UP 104 105 UP EOF
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r0.addChild(r1)
        r1.addChild(CommonTree(CommonToken(103)))
        r2 = CommonTree(CommonToken(106))
        r2.addChild(CommonTree(CommonToken(107)))
        r1.addChild(r2)
        r0.addChild(CommonTree(CommonToken(104)))
        r0.addChild(CommonTree(CommonToken(105)))

        stream = CommonTreeNodeStream(r0)
        m = stream.mark() # MARK
        for _ in range(13): # consume til end
            stream.LT(1)
            stream.consume()

        self.failUnlessEqual(EOF, stream.LT(1).getType())
        self.failUnlessEqual(UP, stream.LT(-1).getType())  #TODO: remove?
        stream.rewind(m)      # REWIND

        # consume til end again :)
        for _ in range(13): # consume til end
            stream.LT(1)
            stream.consume()

        self.failUnlessEqual(EOF, stream.LT(1).getType())
        self.failUnlessEqual(UP, stream.LT(-1).getType())  #TODO: remove?


    def testMarkRewindInMiddle(self):
        # ^(101 ^(102 103 ^(106 107) ) 104 105)
        # stream has 7 real + 6 nav nodes
        # Sequence of types: 101 DN 102 DN 103 106 DN 107 UP UP 104 105 UP EOF
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r0.addChild(r1)
        r1.addChild(CommonTree(CommonToken(103)))
        r2 = CommonTree(CommonToken(106))
        r2.addChild(CommonTree(CommonToken(107)))
        r1.addChild(r2)
        r0.addChild(CommonTree(CommonToken(104)))
        r0.addChild(CommonTree(CommonToken(105)))

        stream = CommonTreeNodeStream(r0)
        for _ in range(7): # consume til middle
            #System.out.println(tream.LT(1).getType())
            stream.consume()

        self.failUnlessEqual(107, stream.LT(1).getType())
        m = stream.mark() # MARK
        stream.consume() # consume 107
        stream.consume() # consume UP
        stream.consume() # consume UP
        stream.consume() # consume 104
        stream.rewind(m)      # REWIND

        self.failUnlessEqual(107, stream.LT(1).getType())
        stream.consume()
        self.failUnlessEqual(UP, stream.LT(1).getType())
        stream.consume()
        self.failUnlessEqual(UP, stream.LT(1).getType())
        stream.consume()
        self.failUnlessEqual(104, stream.LT(1).getType())
        stream.consume()
        # now we're past rewind position
        self.failUnlessEqual(105, stream.LT(1).getType())
        stream.consume()
        self.failUnlessEqual(UP, stream.LT(1).getType())
        stream.consume()
        self.failUnlessEqual(EOF, stream.LT(1).getType())
        self.failUnlessEqual(UP, stream.LT(-1).getType())


    def testMarkRewindNested(self):
        # ^(101 ^(102 103 ^(106 107) ) 104 105)
        # stream has 7 real + 6 nav nodes
        # Sequence of types: 101 DN 102 DN 103 106 DN 107 UP UP 104 105 UP EOF
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r0.addChild(r1)
        r1.addChild(CommonTree(CommonToken(103)))
        r2 = CommonTree(CommonToken(106))
        r2.addChild(CommonTree(CommonToken(107)))
        r1.addChild(r2)
        r0.addChild(CommonTree(CommonToken(104)))
        r0.addChild(CommonTree(CommonToken(105)))

        stream = CommonTreeNodeStream(r0)
        m = stream.mark() # MARK at start
        stream.consume() # consume 101
        stream.consume() # consume DN
        m2 = stream.mark() # MARK on 102
        stream.consume() # consume 102
        stream.consume() # consume DN
        stream.consume() # consume 103
        stream.consume() # consume 106
        stream.rewind(m2)      # REWIND to 102
        self.failUnlessEqual(102, stream.LT(1).getType())
        stream.consume()
        self.failUnlessEqual(DOWN, stream.LT(1).getType())
        stream.consume()
        # stop at 103 and rewind to start
        stream.rewind(m) # REWIND to 101
        self.failUnlessEqual(101, stream.LT(1).getType())
        stream.consume()
        self.failUnlessEqual(DOWN, stream.LT(1).getType())
        stream.consume()
        self.failUnlessEqual(102, stream.LT(1).getType())
        stream.consume()
        self.failUnlessEqual(DOWN, stream.LT(1).getType())


    def testSeek(self):
        # ^(101 ^(102 103 ^(106 107) ) 104 105)
        # stream has 7 real + 6 nav nodes
        # Sequence of types: 101 DN 102 DN 103 106 DN 107 UP UP 104 105 UP EOF
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r0.addChild(r1)
        r1.addChild(CommonTree(CommonToken(103)))
        r2 = CommonTree(CommonToken(106))
        r2.addChild(CommonTree(CommonToken(107)))
        r1.addChild(r2)
        r0.addChild(CommonTree(CommonToken(104)))
        r0.addChild(CommonTree(CommonToken(105)))

        stream = CommonTreeNodeStream(r0)
        stream.consume() # consume 101
        stream.consume() # consume DN
        stream.consume() # consume 102
        stream.seek(7)   # seek to 107
        self.failUnlessEqual(107, stream.LT(1).getType())
        stream.consume() # consume 107
        stream.consume() # consume UP
        stream.consume() # consume UP
        self.failUnlessEqual(104, stream.LT(1).getType())


    def testSeekFromStart(self):
        # ^(101 ^(102 103 ^(106 107) ) 104 105)
        # stream has 7 real + 6 nav nodes
        # Sequence of types: 101 DN 102 DN 103 106 DN 107 UP UP 104 105 UP EOF
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r0.addChild(r1)
        r1.addChild(CommonTree(CommonToken(103)))
        r2 = CommonTree(CommonToken(106))
        r2.addChild(CommonTree(CommonToken(107)))
        r1.addChild(r2)
        r0.addChild(CommonTree(CommonToken(104)))
        r0.addChild(CommonTree(CommonToken(105)))

        stream = CommonTreeNodeStream(r0)
        stream.seek(7)   # seek to 107
        self.failUnlessEqual(107, stream.LT(1).getType())
        stream.consume() # consume 107
        stream.consume() # consume UP
        stream.consume() # consume UP
        self.failUnlessEqual(104, stream.LT(1).getType())


    def testReset(self):
        # ^(101 ^(102 103 ^(106 107) ) 104 105)
        # stream has 7 real + 6 nav nodes
        # Sequence of types: 101 DN 102 DN 103 106 DN 107 UP UP 104 105 UP EOF
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r0.addChild(r1)
        r1.addChild(CommonTree(CommonToken(103)))
        r2 = CommonTree(CommonToken(106))
        r2.addChild(CommonTree(CommonToken(107)))
        r1.addChild(r2)
        r0.addChild(CommonTree(CommonToken(104)))
        r0.addChild(CommonTree(CommonToken(105)))

        stream = CommonTreeNodeStream(r0)
        v1 = self.toNodesOnlyString(stream) # scan all
        stream.reset()
        v2 = self.toNodesOnlyString(stream) # scan all
        self.assertEquals(v1, v2)


    def testIterator(self):
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r0.addChild(r1)
        r1.addChild(CommonTree(CommonToken(103)))
        r2 = CommonTree(CommonToken(106))
        r2.addChild(CommonTree(CommonToken(107)))
        r1.addChild(r2)
        r0.addChild(CommonTree(CommonToken(104)))
        r0.addChild(CommonTree(CommonToken(105)))

        stream = CommonTreeNodeStream(r0)

        expecting = [
            101, DOWN, 102, DOWN, 103, 106, DOWN, 107, UP, UP, 104, 105, UP]
        found = [t.type for t in stream]
        self.assertEqual(expecting, found)


    def toNodesOnlyString(self, nodes):
        buf = []
        for i in range(nodes.size()):
            t = nodes.LT(i+1)
            type = nodes.getTreeAdaptor().getType(t)
            if not (type==DOWN or type==UP):
                buf.append(str(type))

        return ' '.join(buf)


class TestCommonTreeNodeStream(unittest.TestCase):
    """Test case for the CommonTreeNodeStream class."""

    def testPushPop(self):
        # ^(101 ^(102 103) ^(104 105) ^(106 107) 108 109)
        # stream has 9 real + 8 nav nodes
        # Sequence of types: 101 DN 102 DN 103 UP 104 DN 105 UP 106 DN 107 UP 108 109 UP
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r1.addChild(CommonTree(CommonToken(103)))
        r0.addChild(r1)
        r2 = CommonTree(CommonToken(104))
        r2.addChild(CommonTree(CommonToken(105)))
        r0.addChild(r2)
        r3 = CommonTree(CommonToken(106))
        r3.addChild(CommonTree(CommonToken(107)))
        r0.addChild(r3)
        r0.addChild(CommonTree(CommonToken(108)))
        r0.addChild(CommonTree(CommonToken(109)))

        stream = CommonTreeNodeStream(r0)
        expecting = "101 2 102 2 103 3 104 2 105 3 106 2 107 3 108 109 3"
        found = str(stream)
        self.failUnlessEqual(expecting, found)

        # Assume we want to hit node 107 and then "call 102" then return

        indexOf102 = 2
        indexOf107 = 12
        for _ in range(indexOf107):# consume til 107 node
            stream.consume()

        # CALL 102
        self.failUnlessEqual(107, stream.LT(1).getType())
        stream.push(indexOf102)
        self.failUnlessEqual(102, stream.LT(1).getType())
        stream.consume() # consume 102
        self.failUnlessEqual(DOWN, stream.LT(1).getType())
        stream.consume() # consume DN
        self.failUnlessEqual(103, stream.LT(1).getType())
        stream.consume() # consume 103
        self.failUnlessEqual(UP, stream.LT(1).getType())
        # RETURN
        stream.pop()
        self.failUnlessEqual(107, stream.LT(1).getType())


    def testNestedPushPop(self):
        # ^(101 ^(102 103) ^(104 105) ^(106 107) 108 109)
        # stream has 9 real + 8 nav nodes
        # Sequence of types: 101 DN 102 DN 103 UP 104 DN 105 UP 106 DN 107 UP 108 109 UP
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r1.addChild(CommonTree(CommonToken(103)))
        r0.addChild(r1)
        r2 = CommonTree(CommonToken(104))
        r2.addChild(CommonTree(CommonToken(105)))
        r0.addChild(r2)
        r3 = CommonTree(CommonToken(106))
        r3.addChild(CommonTree(CommonToken(107)))
        r0.addChild(r3)
        r0.addChild(CommonTree(CommonToken(108)))
        r0.addChild(CommonTree(CommonToken(109)))

        stream = CommonTreeNodeStream(r0)

        # Assume we want to hit node 107 and then "call 102", which
        # calls 104, then return

        indexOf102 = 2
        indexOf107 = 12
        for _ in range(indexOf107): # consume til 107 node
            stream.consume()

        self.failUnlessEqual(107, stream.LT(1).getType())
        # CALL 102
        stream.push(indexOf102)
        self.failUnlessEqual(102, stream.LT(1).getType())
        stream.consume() # consume 102
        self.failUnlessEqual(DOWN, stream.LT(1).getType())
        stream.consume() # consume DN
        self.failUnlessEqual(103, stream.LT(1).getType())
        stream.consume() # consume 103

        # CALL 104
        indexOf104 = 6
        stream.push(indexOf104)
        self.failUnlessEqual(104, stream.LT(1).getType())
        stream.consume() # consume 102
        self.failUnlessEqual(DOWN, stream.LT(1).getType())
        stream.consume() # consume DN
        self.failUnlessEqual(105, stream.LT(1).getType())
        stream.consume() # consume 103
        self.failUnlessEqual(UP, stream.LT(1).getType())
        # RETURN (to UP node in 102 subtree)
        stream.pop()

        self.failUnlessEqual(UP, stream.LT(1).getType())
        # RETURN (to empty stack)
        stream.pop()
        self.failUnlessEqual(107, stream.LT(1).getType())


    def testPushPopFromEOF(self):
        # ^(101 ^(102 103) ^(104 105) ^(106 107) 108 109)
        # stream has 9 real + 8 nav nodes
        # Sequence of types: 101 DN 102 DN 103 UP 104 DN 105 UP 106 DN 107 UP 108 109 UP
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r1.addChild(CommonTree(CommonToken(103)))
        r0.addChild(r1)
        r2 = CommonTree(CommonToken(104))
        r2.addChild(CommonTree(CommonToken(105)))
        r0.addChild(r2)
        r3 = CommonTree(CommonToken(106))
        r3.addChild(CommonTree(CommonToken(107)))
        r0.addChild(r3)
        r0.addChild(CommonTree(CommonToken(108)))
        r0.addChild(CommonTree(CommonToken(109)))

        stream = CommonTreeNodeStream(r0)

        while stream.LA(1) != EOF:
            stream.consume()

        indexOf102 = 2
        indexOf104 = 6
        self.failUnlessEqual(EOF, stream.LT(1).getType())

        # CALL 102
        stream.push(indexOf102)
        self.failUnlessEqual(102, stream.LT(1).getType())
        stream.consume() # consume 102
        self.failUnlessEqual(DOWN, stream.LT(1).getType())
        stream.consume() # consume DN
        self.failUnlessEqual(103, stream.LT(1).getType())
        stream.consume() # consume 103
        self.failUnlessEqual(UP, stream.LT(1).getType())
        # RETURN (to empty stack)
        stream.pop()
        self.failUnlessEqual(EOF, stream.LT(1).getType())

        # CALL 104
        stream.push(indexOf104)
        self.failUnlessEqual(104, stream.LT(1).getType())
        stream.consume() # consume 102
        self.failUnlessEqual(DOWN, stream.LT(1).getType())
        stream.consume() # consume DN
        self.failUnlessEqual(105, stream.LT(1).getType())
        stream.consume() # consume 103
        self.failUnlessEqual(UP, stream.LT(1).getType())
        # RETURN (to empty stack)
        stream.pop()
        self.failUnlessEqual(EOF, stream.LT(1).getType())


class TestCommonTree(unittest.TestCase):
    """Test case for the CommonTree class."""

    def setUp(self):
        """Setup test fixure"""

        self.adaptor = CommonTreeAdaptor()


    def testSingleNode(self):
        t = CommonTree(CommonToken(101))
        self.failUnless(t.parent is None)
        self.failUnlessEqual(-1, t.childIndex)


    def test4Nodes(self):
        # ^(101 ^(102 103) 104)
        r0 = CommonTree(CommonToken(101))
        r0.addChild(CommonTree(CommonToken(102)))
        r0.getChild(0).addChild(CommonTree(CommonToken(103)))
        r0.addChild(CommonTree(CommonToken(104)))

        self.failUnless(r0.parent is None)
        self.failUnlessEqual(-1, r0.childIndex)


    def testList(self):
        # ^(nil 101 102 103)
        r0 = CommonTree(None)
        c0=CommonTree(CommonToken(101))
        r0.addChild(c0)
        c1=CommonTree(CommonToken(102))
        r0.addChild(c1)
        c2=CommonTree(CommonToken(103))
        r0.addChild(c2)

        self.failUnless(r0.parent is None)
        self.failUnlessEqual(-1, r0.childIndex)
        self.failUnlessEqual(r0, c0.parent)
        self.failUnlessEqual(0, c0.childIndex)
        self.failUnlessEqual(r0, c1.parent)
        self.failUnlessEqual(1, c1.childIndex)
        self.failUnlessEqual(r0, c2.parent)
        self.failUnlessEqual(2, c2.childIndex)


    def testList2(self):
        # Add child ^(nil 101 102 103) to root 5
        # should pull 101 102 103 directly to become 5's child list
        root = CommonTree(CommonToken(5))

        # child tree
        r0 = CommonTree(None)
        c0=CommonTree(CommonToken(101))
        r0.addChild(c0)
        c1=CommonTree(CommonToken(102))
        r0.addChild(c1)
        c2=CommonTree(CommonToken(103))
        r0.addChild(c2)

        root.addChild(r0)

        self.failUnless(root.parent is None)
        self.failUnlessEqual(-1, root.childIndex)
        # check children of root all point at root
        self.failUnlessEqual(root, c0.parent)
        self.failUnlessEqual(0, c0.childIndex)
        self.failUnlessEqual(root, c0.parent)
        self.failUnlessEqual(1, c1.childIndex)
        self.failUnlessEqual(root, c0.parent)
        self.failUnlessEqual(2, c2.childIndex)


    def testAddListToExistChildren(self):
        # Add child ^(nil 101 102 103) to root ^(5 6)
        # should add 101 102 103 to end of 5's child list
        root = CommonTree(CommonToken(5))
        root.addChild(CommonTree(CommonToken(6)))

        # child tree
        r0 = CommonTree(None)
        c0=CommonTree(CommonToken(101))
        r0.addChild(c0)
        c1=CommonTree(CommonToken(102))
        r0.addChild(c1)
        c2=CommonTree(CommonToken(103))
        r0.addChild(c2)

        root.addChild(r0)

        self.failUnless(root.parent is None)
        self.failUnlessEqual(-1, root.childIndex)
        # check children of root all point at root
        self.failUnlessEqual(root, c0.parent)
        self.failUnlessEqual(1, c0.childIndex)
        self.failUnlessEqual(root, c0.parent)
        self.failUnlessEqual(2, c1.childIndex)
        self.failUnlessEqual(root, c0.parent)
        self.failUnlessEqual(3, c2.childIndex)


    def testDupTree(self):
        # ^(101 ^(102 103 ^(106 107) ) 104 105)
        r0 = CommonTree(CommonToken(101))
        r1 = CommonTree(CommonToken(102))
        r0.addChild(r1)
        r1.addChild(CommonTree(CommonToken(103)))
        r2 = CommonTree(CommonToken(106))
        r2.addChild(CommonTree(CommonToken(107)))
        r1.addChild(r2)
        r0.addChild(CommonTree(CommonToken(104)))
        r0.addChild(CommonTree(CommonToken(105)))

        dup = self.adaptor.dupTree(r0)

        self.failUnless(dup.parent is None)
        self.failUnlessEqual(-1, dup.childIndex)
        dup.sanityCheckParentAndChildIndexes()


    def testBecomeRoot(self):
        # 5 becomes root of ^(nil 101 102 103)
        newRoot = CommonTree(CommonToken(5))

        oldRoot = CommonTree(None)
        oldRoot.addChild(CommonTree(CommonToken(101)))
        oldRoot.addChild(CommonTree(CommonToken(102)))
        oldRoot.addChild(CommonTree(CommonToken(103)))

        self.adaptor.becomeRoot(newRoot, oldRoot)
        newRoot.sanityCheckParentAndChildIndexes()


    def testBecomeRoot2(self):
        # 5 becomes root of ^(101 102 103)
        newRoot = CommonTree(CommonToken(5))

        oldRoot = CommonTree(CommonToken(101))
        oldRoot.addChild(CommonTree(CommonToken(102)))
        oldRoot.addChild(CommonTree(CommonToken(103)))

        self.adaptor.becomeRoot(newRoot, oldRoot)
        newRoot.sanityCheckParentAndChildIndexes()


    def testBecomeRoot3(self):
        # ^(nil 5) becomes root of ^(nil 101 102 103)
        newRoot = CommonTree(None)
        newRoot.addChild(CommonTree(CommonToken(5)))

        oldRoot = CommonTree(None)
        oldRoot.addChild(CommonTree(CommonToken(101)))
        oldRoot.addChild(CommonTree(CommonToken(102)))
        oldRoot.addChild(CommonTree(CommonToken(103)))

        self.adaptor.becomeRoot(newRoot, oldRoot)
        newRoot.sanityCheckParentAndChildIndexes()


    def testBecomeRoot5(self):
        # ^(nil 5) becomes root of ^(101 102 103)
        newRoot = CommonTree(None)
        newRoot.addChild(CommonTree(CommonToken(5)))

        oldRoot = CommonTree(CommonToken(101))
        oldRoot.addChild(CommonTree(CommonToken(102)))
        oldRoot.addChild(CommonTree(CommonToken(103)))

        self.adaptor.becomeRoot(newRoot, oldRoot)
        newRoot.sanityCheckParentAndChildIndexes()


    def testBecomeRoot6(self):
        # emulates construction of ^(5 6)
        root_0 = self.adaptor.nil()
        root_1 = self.adaptor.nil()
        root_1 = self.adaptor.becomeRoot(CommonTree(CommonToken(5)), root_1)

        self.adaptor.addChild(root_1, CommonTree(CommonToken(6)))

        self.adaptor.addChild(root_0, root_1)

        root_0.sanityCheckParentAndChildIndexes()


    # Test replaceChildren

    def testReplaceWithNoChildren(self):
        t = CommonTree(CommonToken(101))
        newChild = CommonTree(CommonToken(5))
        error = False
        try:
        	t.replaceChildren(0, 0, newChild)

        except IndexError:
        	error = True

        self.failUnless(error)


    def testReplaceWithOneChildren(self):
        # assume token type 99 and use text
        t = CommonTree(CommonToken(99, text="a"))
        c0 = CommonTree(CommonToken(99, text="b"))
        t.addChild(c0)

        newChild = CommonTree(CommonToken(99, text="c"))
        t.replaceChildren(0, 0, newChild)
        expecting = "(a c)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceInMiddle(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b")))
        t.addChild(CommonTree(CommonToken(99, text="c"))) # index 1
        t.addChild(CommonTree(CommonToken(99, text="d")))

        newChild = CommonTree(CommonToken(99, text="x"))
        t.replaceChildren(1, 1, newChild)
        expecting = "(a b x d)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceAtLeft(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b"))) # index 0
        t.addChild(CommonTree(CommonToken(99, text="c")))
        t.addChild(CommonTree(CommonToken(99, text="d")))

        newChild = CommonTree(CommonToken(99, text="x"))
        t.replaceChildren(0, 0, newChild)
        expecting = "(a x c d)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceAtRight(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b")))
        t.addChild(CommonTree(CommonToken(99, text="c")))
        t.addChild(CommonTree(CommonToken(99, text="d"))) # index 2

        newChild = CommonTree(CommonToken(99, text="x"))
        t.replaceChildren(2, 2, newChild)
        expecting = "(a b c x)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceOneWithTwoAtLeft(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b")))
        t.addChild(CommonTree(CommonToken(99, text="c")))
        t.addChild(CommonTree(CommonToken(99, text="d")))

        newChildren = self.adaptor.nil()
        newChildren.addChild(CommonTree(CommonToken(99, text="x")))
        newChildren.addChild(CommonTree(CommonToken(99, text="y")))

        t.replaceChildren(0, 0, newChildren)
        expecting = "(a x y c d)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceOneWithTwoAtRight(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b")))
        t.addChild(CommonTree(CommonToken(99, text="c")))
        t.addChild(CommonTree(CommonToken(99, text="d")))

        newChildren = self.adaptor.nil()
        newChildren.addChild(CommonTree(CommonToken(99, text="x")))
        newChildren.addChild(CommonTree(CommonToken(99, text="y")))

        t.replaceChildren(2, 2, newChildren)
        expecting = "(a b c x y)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceOneWithTwoInMiddle(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b")))
        t.addChild(CommonTree(CommonToken(99, text="c")))
        t.addChild(CommonTree(CommonToken(99, text="d")))

        newChildren = self.adaptor.nil()
        newChildren.addChild(CommonTree(CommonToken(99, text="x")))
        newChildren.addChild(CommonTree(CommonToken(99, text="y")))

        t.replaceChildren(1, 1, newChildren)
        expecting = "(a b x y d)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceTwoWithOneAtLeft(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b")))
        t.addChild(CommonTree(CommonToken(99, text="c")))
        t.addChild(CommonTree(CommonToken(99, text="d")))

        newChild = CommonTree(CommonToken(99, text="x"))

        t.replaceChildren(0, 1, newChild)
        expecting = "(a x d)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceTwoWithOneAtRight(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b")))
        t.addChild(CommonTree(CommonToken(99, text="c")))
        t.addChild(CommonTree(CommonToken(99, text="d")))

        newChild = CommonTree(CommonToken(99, text="x"))

        t.replaceChildren(1, 2, newChild)
        expecting = "(a b x)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceAllWithOne(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b")))
        t.addChild(CommonTree(CommonToken(99, text="c")))
        t.addChild(CommonTree(CommonToken(99, text="d")))

        newChild = CommonTree(CommonToken(99, text="x"))

        t.replaceChildren(0, 2, newChild)
        expecting = "(a x)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


    def testReplaceAllWithTwo(self):
        t = CommonTree(CommonToken(99, text="a"))
        t.addChild(CommonTree(CommonToken(99, text="b")))
        t.addChild(CommonTree(CommonToken(99, text="c")))
        t.addChild(CommonTree(CommonToken(99, text="d")))

        newChildren = self.adaptor.nil()
        newChildren.addChild(CommonTree(CommonToken(99, text="x")))
        newChildren.addChild(CommonTree(CommonToken(99, text="y")))

        t.replaceChildren(0, 2, newChildren)
        expecting = "(a x y)"
        self.failUnlessEqual(expecting, t.toStringTree())
        t.sanityCheckParentAndChildIndexes()


class TestTreeContext(unittest.TestCase):
    """Test the TreeParser.inContext() method"""

    tokenNames = [
        "<invalid>", "<EOR>", "<DOWN>", "<UP>", "VEC", "ASSIGN", "PRINT",
        "PLUS", "MULT", "DOT", "ID", "INT", "WS", "'['", "','", "']'"
        ]

    def testSimpleParent(self):
        tree = "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID[x] (VEC INT[1] INT[2] INT[3]))))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID (VEC INT %x:INT INT))))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = True
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "VEC")
        self.assertEquals(expecting, found)


    def testNoParent(self):
        tree = "(PRINT (MULT ID[x] (VEC INT[1] INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(%x:PRINT (MULT ID (VEC INT INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = False
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "VEC")
        self.assertEquals(expecting, found)


    def testParentWithWildcard(self):
        tree = "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID[x] (VEC INT[1] INT[2] INT[3]))))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID (VEC INT %x:INT INT))))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = True
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "VEC ...")
        self.assertEquals(expecting, found)


    def testWildcardAtStartIgnored(self):
        tree = "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID[x] (VEC INT[1] INT[2] INT[3]))))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID (VEC INT %x:INT INT))))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = True
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "...VEC")
        self.assertEquals(expecting, found)


    def testWildcardInBetween(self):
        tree = "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID[x] (VEC INT[1] INT[2] INT[3]))))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID (VEC INT %x:INT INT))))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = True
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "PRINT...VEC")
        self.assertEquals(expecting, found)


    def testLotsOfWildcards(self):
        tree = "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID[x] (VEC INT[1] INT[2] INT[3]))))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID (VEC INT %x:INT INT))))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = True
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "... PRINT ... VEC ...")
        self.assertEquals(expecting, found)


    def testDeep(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = True
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "VEC ...")
        self.assertEquals(expecting, found)


    def testDeepAndFindRoot(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = True
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "PRINT ...")
        self.assertEquals(expecting, found)


    def testDeepAndFindRoot2(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = True
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "PRINT ... VEC ...")
        self.assertEquals(expecting, found)


    def testChain(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = True
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "PRINT MULT VEC MULT")
        self.assertEquals(expecting, found)


    ## TEST INVALID CONTEXTS

    def testNotParent(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = False
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "VEC")
        self.assertEquals(expecting, found)


    def testMismatch(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = False
        ## missing MULT
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "PRINT VEC MULT")
        self.assertEquals(expecting, found)


    def testMismatch2(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = False
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "PRINT VEC ...")
        self.assertEquals(expecting, found)


    def testMismatch3(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        expecting = False
        found = TreeParser._inContext(adaptor, self.tokenNames, node, "VEC ... VEC MULT")
        self.assertEquals(expecting, found)


    def testDoubleEtc(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        try:
            TreeParser._inContext(adaptor, self.tokenNames, node, "PRINT ... ... VEC")
            self.fail()
        except ValueError, exc:
            expecting = "invalid syntax: ... ..."
            found = str(exc)
            self.assertEquals(expecting, found)


    def testDotDot(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        labels = {}
        valid = wiz.parse(
            t,
            "(PRINT (MULT ID (VEC (MULT INT %x:INT) INT INT)))",
            labels)
        self.assertTrue(valid)
        node = labels.get("x")

        try:
            TreeParser._inContext(adaptor, self.tokenNames, node, "PRINT .. VEC")
            self.fail()
        except ValueError, exc:
            expecting = "invalid syntax: .."
            found = str(exc)
            self.assertEquals(expecting, found)


class TestTreeVisitor(unittest.TestCase):
    """Test of the TreeVisitor class."""

    tokenNames = [
        "<invalid>", "<EOR>", "<DOWN>", "<UP>", "VEC", "ASSIGN", "PRINT",
        "PLUS", "MULT", "DOT", "ID", "INT", "WS", "'['", "','", "']'"
        ]

    def testTreeVisitor(self):
        tree = "(PRINT (MULT ID[x] (VEC (MULT INT[9] INT[1]) INT[2] INT[3])))"
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokenNames)
        t = wiz.create(tree)

        found = []
        def pre(t):
            found.append("pre(%s)" % t)
            return t
        def post(t):
            found.append("post(%s)" % t)
            return t

        visitor = TreeVisitor(adaptor)
        visitor.visit(t, pre, post)

        expecting = [ "pre(PRINT)", "pre(MULT)", "pre(x)", "post(x)",
                      "pre(VEC)", "pre(MULT)", "pre(9)", "post(9)", "pre(1)",
                      "post(1)", "post(MULT)", "pre(2)", "post(2)", "pre(3)",
                      "post(3)", "post(VEC)", "post(MULT)", "post(PRINT)" ]

        self.assertEquals(expecting, found)


class TestTreeIterator(unittest.TestCase):
    tokens = [
        "<invalid>", "<EOR>", "<DOWN>", "<UP>",
        "A", "B", "C", "D", "E", "F", "G" ]

    def testNode(self):
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokens)
        t = wiz.create("A")
        it = TreeIterator(t)
        expecting = "A EOF"
        found = self.toString(it)
        self.assertEquals(expecting, found)


    def testFlatAB(self):
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokens)
        t = wiz.create("(nil A B)")
        it = TreeIterator(t)
        expecting = "nil DOWN A B UP EOF"
        found = self.toString(it)
        self.assertEquals(expecting, found)


    def testAB(self):
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokens)
        t = wiz.create("(A B)")
        it = TreeIterator(t)
        expecting = "A DOWN B UP EOF"
        found = self.toString(it)
        self.assertEquals(expecting, found)


    def testABC(self):
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokens)
        t = wiz.create("(A B C)")
        it = TreeIterator(t)
        expecting = "A DOWN B C UP EOF"
        found = self.toString(it)
        self.assertEquals(expecting, found)


    def testVerticalList(self):
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokens)
        t = wiz.create("(A (B C))")
        it = TreeIterator(t)
        expecting = "A DOWN B DOWN C UP UP EOF"
        found = self.toString(it)
        self.assertEquals(expecting, found)


    def testComplex(self):
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokens)
        t = wiz.create("(A (B (C D E) F) G)")
        it = TreeIterator(t)
        expecting = "A DOWN B DOWN C DOWN D E UP F UP G UP EOF"
        found = self.toString(it)
        self.assertEquals(expecting, found)


    def testReset(self):
        adaptor = CommonTreeAdaptor()
        wiz = TreeWizard(adaptor, self.tokens)
        t = wiz.create("(A (B (C D E) F) G)")
        it = TreeIterator(t)
        expecting = "A DOWN B DOWN C DOWN D E UP F UP G UP EOF"
        found = self.toString(it)
        self.assertEquals(expecting, found)

        it.reset()
        expecting = "A DOWN B DOWN C DOWN D E UP F UP G UP EOF"
        found = self.toString(it)
        self.assertEquals(expecting, found)


    def toString(self, it):
        buf = []
        for n in it:
            buf.append(str(n))

        return ' '.join(buf)


if __name__ == "__main__":
    unittest.main(testRunner=unittest.TextTestRunner(verbosity=2))
