/// \file
/// Defines the implementation of the common node stream the default
/// tree node stream used by ANTLR.
///

// [The "BSD licence"]
// Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC
// http://www.temporal-wave.com
// http://www.linkedin.com/in/jimidle
//
// 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.

#include    <antlr3commontreenodestream.h>

#ifdef  ANTLR3_WINDOWS
#pragma warning( disable : 4100 )
#endif

// COMMON TREE STREAM API
//
static  void            addNavigationNode      (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_UINT32 ttype);
static  ANTLR3_BOOLEAN        hasUniqueNavigationNodes  (pANTLR3_COMMON_TREE_NODE_STREAM ctns);
static  pANTLR3_BASE_TREE      newDownNode          (pANTLR3_COMMON_TREE_NODE_STREAM ctns);
static  pANTLR3_BASE_TREE      newUpNode          (pANTLR3_COMMON_TREE_NODE_STREAM ctns);
static  void            reset            (pANTLR3_COMMON_TREE_NODE_STREAM ctns);
static  void            push            (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_INT32 index);
static  ANTLR3_INT32        pop              (pANTLR3_COMMON_TREE_NODE_STREAM ctns);
//static  ANTLR3_INT32        index            (pANTLR3_COMMON_TREE_NODE_STREAM ctns);
static  ANTLR3_UINT32        getLookaheadSize      (pANTLR3_COMMON_TREE_NODE_STREAM ctns);
// TREE NODE STREAM API
//
static  pANTLR3_BASE_TREE_ADAPTOR   getTreeAdaptor        (pANTLR3_TREE_NODE_STREAM tns);
static  pANTLR3_BASE_TREE      getTreeSource        (pANTLR3_TREE_NODE_STREAM tns);
static  pANTLR3_BASE_TREE      _LT              (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k);
static  pANTLR3_BASE_TREE      get              (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k);
static  void            setUniqueNavigationNodes  (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_BOOLEAN uniqueNavigationNodes);
static  pANTLR3_STRING        toString          (pANTLR3_TREE_NODE_STREAM tns);
static  pANTLR3_STRING        toStringSS          (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE start, pANTLR3_BASE_TREE stop);
static  void            toStringWork        (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE start, pANTLR3_BASE_TREE stop, pANTLR3_STRING buf);
static  void            replaceChildren        (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE parent, ANTLR3_INT32 startChildIndex, ANTLR3_INT32 stopChildIndex, pANTLR3_BASE_TREE t);

// INT STREAM API
//
static  void            consume            (pANTLR3_INT_STREAM is);
static  ANTLR3_MARKER        tindex            (pANTLR3_INT_STREAM is);
static  ANTLR3_UINT32        _LA              (pANTLR3_INT_STREAM is, ANTLR3_INT32 i);
static  ANTLR3_MARKER        mark            (pANTLR3_INT_STREAM is);
static  void            release            (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker);
static  void            rewindMark          (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker);
static  void            rewindLast          (pANTLR3_INT_STREAM is);
static  void            seek            (pANTLR3_INT_STREAM is, ANTLR3_MARKER index);
static  ANTLR3_UINT32        size            (pANTLR3_INT_STREAM is);


// Helper functions
//
static  void            fillBuffer          (pANTLR3_COMMON_TREE_NODE_STREAM ctns, pANTLR3_BASE_TREE t);
static  void            fillBufferRoot        (pANTLR3_COMMON_TREE_NODE_STREAM ctns);

// Constructors
//
static  void            antlr3TreeNodeStreamFree      (pANTLR3_TREE_NODE_STREAM tns);
static  void            antlr3CommonTreeNodeStreamFree    (pANTLR3_COMMON_TREE_NODE_STREAM ctns);

ANTLR3_API pANTLR3_TREE_NODE_STREAM
antlr3TreeNodeStreamNew()
{
    pANTLR3_TREE_NODE_STREAM stream;

    // Memory for the interface structure
    //
    stream  = (pANTLR3_TREE_NODE_STREAM) ANTLR3_CALLOC(1, sizeof(ANTLR3_TREE_NODE_STREAM));

    if  (stream == NULL)
    {
    return  NULL;
    }

    // Install basic API 
    //
  stream->replaceChildren = replaceChildren;
    stream->free      = antlr3TreeNodeStreamFree;
    
    return stream;
}

static void
antlr3TreeNodeStreamFree(pANTLR3_TREE_NODE_STREAM stream)
{   
    ANTLR3_FREE(stream);
}

ANTLR3_API pANTLR3_COMMON_TREE_NODE_STREAM
antlr3CommonTreeNodeStreamNewTree(pANTLR3_BASE_TREE tree, ANTLR3_UINT32 hint)
{
  pANTLR3_COMMON_TREE_NODE_STREAM stream;

  stream = antlr3CommonTreeNodeStreamNew(tree->strFactory, hint);

  if  (stream == NULL)
  {
    return  NULL;
  }
  stream->root    = tree;

  return stream;
}

ANTLR3_API pANTLR3_COMMON_TREE_NODE_STREAM
antlr3CommonTreeNodeStreamNewStream(pANTLR3_COMMON_TREE_NODE_STREAM inStream)
{
  pANTLR3_COMMON_TREE_NODE_STREAM stream;

  // Memory for the interface structure
  //
  stream  = (pANTLR3_COMMON_TREE_NODE_STREAM) ANTLR3_CALLOC(1, sizeof(ANTLR3_COMMON_TREE_NODE_STREAM));

  if  (stream == NULL)
  {
    return  NULL;
  }

  // Copy in all the reusable parts of the originating stream and create new
  // pieces where necessary.
  //

  // String factory for tree walker
  //
  stream->stringFactory    = inStream->stringFactory;

  // Create an adaptor for the common tree node stream
  //
  stream->adaptor        = inStream->adaptor;

  // Create space for the tree node stream interface
  //
  stream->tnstream      = antlr3TreeNodeStreamNew();

  if  (stream->tnstream == NULL)
  {
    stream->free        (stream);

    return  NULL;
  }

  // Create space for the INT_STREAM interface
  //
  stream->tnstream->istream        =  antlr3IntStreamNew();

  if  (stream->tnstream->istream == NULL)
  {
    stream->tnstream->free    (stream->tnstream);
    stream->free        (stream);

    return  NULL;
  }

  // Install the common tree node stream API
  //
  stream->addNavigationNode        =  addNavigationNode;
  stream->hasUniqueNavigationNodes    =  hasUniqueNavigationNodes;
  stream->newDownNode          =  newDownNode;
  stream->newUpNode          =  newUpNode;
  stream->reset            =  reset;
  stream->push            =  push;
  stream->pop              =  pop;
  stream->getLookaheadSize      =  getLookaheadSize;

  stream->free          =  antlr3CommonTreeNodeStreamFree;

  // Install the tree node stream API
  //
  stream->tnstream->getTreeAdaptor      =  getTreeAdaptor;
  stream->tnstream->getTreeSource        =  getTreeSource;
  stream->tnstream->_LT            =  _LT;
  stream->tnstream->setUniqueNavigationNodes  =  setUniqueNavigationNodes;
  stream->tnstream->toString          =  toString;
  stream->tnstream->toStringSS        =  toStringSS;
  stream->tnstream->toStringWork        =  toStringWork;
  stream->tnstream->get            =  get;

  // Install INT_STREAM interface
  //
  stream->tnstream->istream->consume      =  consume;
  stream->tnstream->istream->index      =  tindex;
  stream->tnstream->istream->_LA      =  _LA;
  stream->tnstream->istream->mark      =  mark;
  stream->tnstream->istream->release      =  release;
  stream->tnstream->istream->rewind      =  rewindMark;
  stream->tnstream->istream->rewindLast   =  rewindLast;
  stream->tnstream->istream->seek      =  seek;
  stream->tnstream->istream->size      =  size;

  // Initialize data elements of INT stream
  //
  stream->tnstream->istream->type      = ANTLR3_COMMONTREENODE;
  stream->tnstream->istream->super      =  (stream->tnstream);

  // Initialize data elements of TREE stream
  //
  stream->tnstream->ctns =  stream;

  // Initialize data elements of the COMMON TREE NODE stream
  //
  stream->super          = NULL;
  stream->uniqueNavigationNodes  = ANTLR3_FALSE;
  stream->markers          = NULL;
  stream->nodeStack        = inStream->nodeStack;

  // Create the node list map
  //
  stream->nodes  = antlr3VectorNew(DEFAULT_INITIAL_BUFFER_SIZE);
  stream->p    = -1;

  // Install the navigation nodes     
  //
  
  // Install the navigation nodes     
  //
  antlr3SetCTAPI(&(stream->UP));
  antlr3SetCTAPI(&(stream->DOWN));
  antlr3SetCTAPI(&(stream->EOF_NODE));
  antlr3SetCTAPI(&(stream->INVALID_NODE));

  stream->UP.token            = inStream->UP.token;
  inStream->UP.token->strFactory      = stream->stringFactory;
  stream->DOWN.token            = inStream->DOWN.token;
  inStream->DOWN.token->strFactory    = stream->stringFactory;
  stream->EOF_NODE.token          = inStream->EOF_NODE.token;
  inStream->EOF_NODE.token->strFactory  = stream->stringFactory;
  stream->INVALID_NODE.token        = inStream->INVALID_NODE.token;
  inStream->INVALID_NODE.token->strFactory= stream->stringFactory;

  // Reuse the root tree of the originating stream
  //
  stream->root    = inStream->root;

  // Signal that this is a rewriting stream so we don't
  // free the originating tree. Anything that we rewrite or
  // duplicate here will be done through the adaptor or 
  // the original tree factory.
  //
  stream->isRewriter  = ANTLR3_TRUE;
  return stream;
}

ANTLR3_API pANTLR3_COMMON_TREE_NODE_STREAM
antlr3CommonTreeNodeStreamNew(pANTLR3_STRING_FACTORY strFactory, ANTLR3_UINT32 hint)
{
  pANTLR3_COMMON_TREE_NODE_STREAM stream;
  pANTLR3_COMMON_TOKEN      token;

  // Memory for the interface structure
  //
  stream  = (pANTLR3_COMMON_TREE_NODE_STREAM) ANTLR3_CALLOC(1, sizeof(ANTLR3_COMMON_TREE_NODE_STREAM));

  if  (stream == NULL)
  {
    return  NULL;
  }

  // String factory for tree walker
  //
  stream->stringFactory    = strFactory;

  // Create an adaptor for the common tree node stream
  //
  stream->adaptor        = ANTLR3_TREE_ADAPTORNew(strFactory);

  if  (stream->adaptor == NULL)
  {
    stream->free(stream);
    return  NULL;
  }

  // Create space for the tree node stream interface
  //
  stream->tnstream      = antlr3TreeNodeStreamNew();

  if  (stream->tnstream == NULL)
  {
    stream->adaptor->free    (stream->adaptor);
    stream->free        (stream);

    return  NULL;
  }

  // Create space for the INT_STREAM interface
  //
  stream->tnstream->istream        =  antlr3IntStreamNew();

  if  (stream->tnstream->istream == NULL)
  {
    stream->adaptor->free    (stream->adaptor);
    stream->tnstream->free    (stream->tnstream);
    stream->free        (stream);

    return  NULL;
  }

  // Install the common tree node stream API
  //
  stream->addNavigationNode        =  addNavigationNode;
  stream->hasUniqueNavigationNodes    =  hasUniqueNavigationNodes;
  stream->newDownNode          =  newDownNode;
  stream->newUpNode          =  newUpNode;
  stream->reset            =  reset;
  stream->push            =  push;
  stream->pop              =  pop;

  stream->free          =  antlr3CommonTreeNodeStreamFree;

  // Install the tree node stream API
  //
  stream->tnstream->getTreeAdaptor      =  getTreeAdaptor;
  stream->tnstream->getTreeSource        =  getTreeSource;
  stream->tnstream->_LT            =  _LT;
  stream->tnstream->setUniqueNavigationNodes  =  setUniqueNavigationNodes;
  stream->tnstream->toString          =  toString;
  stream->tnstream->toStringSS        =  toStringSS;
  stream->tnstream->toStringWork        =  toStringWork;
  stream->tnstream->get            =  get;

  // Install INT_STREAM interface
  //
  stream->tnstream->istream->consume      =  consume;
  stream->tnstream->istream->index      =  tindex;
  stream->tnstream->istream->_LA      =  _LA;
  stream->tnstream->istream->mark      =  mark;
  stream->tnstream->istream->release      =  release;
  stream->tnstream->istream->rewind      =  rewindMark;
  stream->tnstream->istream->rewindLast   =  rewindLast;
  stream->tnstream->istream->seek      =  seek;
  stream->tnstream->istream->size      =  size;

  // Initialize data elements of INT stream
  //
  stream->tnstream->istream->type      = ANTLR3_COMMONTREENODE;
  stream->tnstream->istream->super      =  (stream->tnstream);

  // Initialize data elements of TREE stream
  //
  stream->tnstream->ctns =  stream;

  // Initialize data elements of the COMMON TREE NODE stream
  //
  stream->super          = NULL;
  stream->uniqueNavigationNodes  = ANTLR3_FALSE;
  stream->markers          = NULL;
  stream->nodeStack        = antlr3StackNew(INITIAL_CALL_STACK_SIZE);

  // Create the node list map
  //
  if  (hint == 0)
  {
    hint = DEFAULT_INITIAL_BUFFER_SIZE;
  }
  stream->nodes  = antlr3VectorNew(hint);
  stream->p    = -1;

  // Install the navigation nodes     
  //
  antlr3SetCTAPI(&(stream->UP));
  antlr3SetCTAPI(&(stream->DOWN));
  antlr3SetCTAPI(&(stream->EOF_NODE));
  antlr3SetCTAPI(&(stream->INVALID_NODE));

  token            = antlr3CommonTokenNew(ANTLR3_TOKEN_UP);
  token->strFactory      = strFactory;
  token->textState      = ANTLR3_TEXT_CHARP;
  token->tokText.chars    = (pANTLR3_UCHAR)"UP";
  stream->UP.token      = token;

  token            = antlr3CommonTokenNew(ANTLR3_TOKEN_DOWN);
  token->strFactory      = strFactory;
  token->textState      = ANTLR3_TEXT_CHARP;
  token->tokText.chars    = (pANTLR3_UCHAR)"DOWN";
  stream->DOWN.token      = token;

  token            = antlr3CommonTokenNew(ANTLR3_TOKEN_EOF);
  token->strFactory      = strFactory;
  token->textState      = ANTLR3_TEXT_CHARP;
  token->tokText.chars    = (pANTLR3_UCHAR)"EOF";
  stream->EOF_NODE.token    = token;

  token            = antlr3CommonTokenNew(ANTLR3_TOKEN_INVALID);
  token->strFactory      = strFactory;
  token->textState      = ANTLR3_TEXT_CHARP;
  token->tokText.chars    = (pANTLR3_UCHAR)"INVALID";
  stream->INVALID_NODE.token  = token;


  return  stream;
}

/// Free up any resources that belong to this common tree node stream.
///
static  void          antlr3CommonTreeNodeStreamFree  (pANTLR3_COMMON_TREE_NODE_STREAM ctns)
{

  // If this is a rewrting stream, then certain resources
  // belong to the originating node stream and we do not
  // free them here.
  //
  if  (ctns->isRewriter != ANTLR3_TRUE)
  {
    ctns->adaptor      ->free  (ctns->adaptor);

    if  (ctns->nodeStack != NULL)
    {
      ctns->nodeStack->free(ctns->nodeStack);
    }

    ANTLR3_FREE(ctns->INVALID_NODE.token);
    ANTLR3_FREE(ctns->EOF_NODE.token);
    ANTLR3_FREE(ctns->DOWN.token);
    ANTLR3_FREE(ctns->UP.token);
  }
  
  if  (ctns->nodes != NULL)
  {
    ctns->nodes      ->free  (ctns->nodes);
  }
  ctns->tnstream->istream ->free  (ctns->tnstream->istream);
    ctns->tnstream      ->free  (ctns->tnstream);


    ANTLR3_FREE(ctns);
}

// ------------------------------------------------------------------------------
// Local helpers
//

/// Walk and fill the tree node buffer from the root tree
///
static void
fillBufferRoot(pANTLR3_COMMON_TREE_NODE_STREAM ctns)
{
  // Call the generic buffer routine with the root as the
  // argument
  //
  fillBuffer(ctns, ctns->root);
  ctns->p = 0;          // Indicate we are at buffer start
}

/// Walk tree with depth-first-search and fill nodes buffer.
/// Don't add in DOWN, UP nodes if the supplied tree is a list (t is isNilNode)
// such as the root tree is.
///
static void
fillBuffer(pANTLR3_COMMON_TREE_NODE_STREAM ctns, pANTLR3_BASE_TREE t)
{
  ANTLR3_BOOLEAN  nilNode;
  ANTLR3_UINT32  nCount;
  ANTLR3_UINT32  c;

  nilNode = ctns->adaptor->isNilNode(ctns->adaptor, t);

  // If the supplied node is not a nil (list) node then we
  // add in the node itself to the vector
  //
  if  (nilNode == ANTLR3_FALSE)
  {
    ctns->nodes->add(ctns->nodes, t, NULL);  
  }

  // Only add a DOWN node if the tree is not a nil tree and
  // the tree does have children.
  //
  nCount = t->getChildCount(t);

  if  (nilNode == ANTLR3_FALSE && nCount>0)
  {
    ctns->addNavigationNode(ctns, ANTLR3_TOKEN_DOWN);
  }

  // We always add any children the tree contains, which is
  // a recursive call to this function, which will cause similar
  // recursion and implement a depth first addition
  //
  for  (c = 0; c < nCount; c++)
  {
    fillBuffer(ctns, ctns->adaptor->getChild(ctns->adaptor, t, c));
  }

  // If the tree had children and was not a nil (list) node, then we
  // we need to add an UP node here to match the DOWN node
  //
  if  (nilNode == ANTLR3_FALSE && nCount > 0)
  {
    ctns->addNavigationNode(ctns, ANTLR3_TOKEN_UP);
  }
}


// ------------------------------------------------------------------------------
// Interface functions
//

/// Reset the input stream to the start of the input nodes.
///
static  void    
reset      (pANTLR3_COMMON_TREE_NODE_STREAM ctns)
{
  if  (ctns->p != -1)
  {
    ctns->p                  = 0;
  }
  ctns->tnstream->istream->lastMarker    = 0;


  // Free and reset the node stack only if this is not
  // a rewriter, which is going to reuse the originating
  // node streams node stack
  //
  if  (ctns->isRewriter != ANTLR3_TRUE)
    {
    if  (ctns->nodeStack != NULL)
    {
      ctns->nodeStack->free(ctns->nodeStack);
      ctns->nodeStack = antlr3StackNew(INITIAL_CALL_STACK_SIZE);
    }
  }
}


static pANTLR3_BASE_TREE
LB(pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k)
{
  if  ( k==0)
  {
    return  &(tns->ctns->INVALID_NODE.baseTree);
  }

  if  ( (tns->ctns->p - k) < 0)
  {
    return  &(tns->ctns->INVALID_NODE.baseTree);
  }

  return tns->ctns->nodes->get(tns->ctns->nodes, tns->ctns->p - k);
}

/// Get tree node at current input pointer + i ahead where i=1 is next node.
/// i<0 indicates nodes in the past.  So -1 is previous node and -2 is
/// two nodes ago. 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 analogous 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. :)
///
static  pANTLR3_BASE_TREE      
_LT      (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k)
{
  if  (tns->ctns->p == -1)
  {
    fillBufferRoot(tns->ctns);
  }

  if  (k < 0)
  {
    return LB(tns, -k);
  }
  else if  (k == 0)
  {
    return  &(tns->ctns->INVALID_NODE.baseTree);
  }

  // k was a legitimate request, 
  //
  if  (( tns->ctns->p + k - 1) >= (ANTLR3_INT32)(tns->ctns->nodes->count))
  {
    return &(tns->ctns->EOF_NODE.baseTree);
  }

  return  tns->ctns->nodes->get(tns->ctns->nodes, tns->ctns->p + k - 1);
}

/// Where is this stream pulling nodes from?  This is not the name, but
/// the object that provides node objects.
///
static  pANTLR3_BASE_TREE      
getTreeSource  (pANTLR3_TREE_NODE_STREAM tns)
{
    return  tns->ctns->root;
}

/// Consume the next node from the input stream
///
static  void        
consume  (pANTLR3_INT_STREAM is)
{
    pANTLR3_TREE_NODE_STREAM    tns;
    pANTLR3_COMMON_TREE_NODE_STREAM  ctns;

    tns      = (pANTLR3_TREE_NODE_STREAM)(is->super);
    ctns    = tns->ctns;

  if  (ctns->p == -1)
  {
    fillBufferRoot(ctns);
  }
  ctns->p++;
}

static  ANTLR3_UINT32      
_LA      (pANTLR3_INT_STREAM is, ANTLR3_INT32 i)
{
  pANTLR3_TREE_NODE_STREAM    tns;
  pANTLR3_BASE_TREE        t;

  tns      = (pANTLR3_TREE_NODE_STREAM)(is->super);

  // Ask LT for the 'token' at that position
  //
  t = tns->_LT(tns, i);

  if  (t == NULL)
  {
    return  ANTLR3_TOKEN_INVALID;
  }

  // Token node was there so return the type of it
  //
  return  t->getType(t);
}

/// Mark the state of the input stream so that we can come back to it
/// after a syntactic predicate and so on.
///
static  ANTLR3_MARKER      
mark  (pANTLR3_INT_STREAM is)
{
  pANTLR3_TREE_NODE_STREAM    tns;
  pANTLR3_COMMON_TREE_NODE_STREAM  ctns;

  tns      = (pANTLR3_TREE_NODE_STREAM)(is->super);
  ctns    = tns->ctns;

  if  (tns->ctns->p == -1)
  {
    fillBufferRoot(tns->ctns);
  }

  // Return the current mark point
  //
  ctns->tnstream->istream->lastMarker = ctns->tnstream->istream->index(ctns->tnstream->istream);

  return ctns->tnstream->istream->lastMarker;
}

static  void        
release  (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)
{
}

/// Rewind the current state of the tree walk to the state it
/// was in when mark() was called and it returned marker.  Also,
/// wipe out the lookahead which will force reloading a few nodes
/// but it is better than making a copy of the lookahead buffer
/// upon mark().
///
static  void        
rewindMark      (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)
{
  is->seek(is, marker);
}

static  void        
rewindLast  (pANTLR3_INT_STREAM is)
{
   is->seek(is, is->lastMarker);
}

/// consume() ahead until we hit index.  Can't just jump ahead--must
/// spit out the navigation nodes.
///
static  void        
seek  (pANTLR3_INT_STREAM is, ANTLR3_MARKER index)
{
    pANTLR3_TREE_NODE_STREAM    tns;
    pANTLR3_COMMON_TREE_NODE_STREAM  ctns;

    tns      = (pANTLR3_TREE_NODE_STREAM)(is->super);
    ctns    = tns->ctns;

  ctns->p = ANTLR3_UINT32_CAST(index);
}

static  ANTLR3_MARKER        
tindex  (pANTLR3_INT_STREAM is)
{
    pANTLR3_TREE_NODE_STREAM    tns;
    pANTLR3_COMMON_TREE_NODE_STREAM  ctns;

    tns      = (pANTLR3_TREE_NODE_STREAM)(is->super);
    ctns    = tns->ctns;

  return (ANTLR3_MARKER)(ctns->p);
}

/// Expensive to compute the size of the whole tree while parsing.
/// This method only returns how much input has been seen so far.  So
/// after parsing it returns true size.
///
static  ANTLR3_UINT32        
size  (pANTLR3_INT_STREAM is)
{
    pANTLR3_TREE_NODE_STREAM    tns;
    pANTLR3_COMMON_TREE_NODE_STREAM  ctns;

    tns      = (pANTLR3_TREE_NODE_STREAM)(is->super);
    ctns    = tns->ctns;

  if  (ctns->p == -1)
  {
    fillBufferRoot(ctns);
  }

  return ctns->nodes->size(ctns->nodes);
}

/// 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.
///
static  void        
addNavigationNode      (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_UINT32 ttype)
{
  pANTLR3_BASE_TREE      node;

  node = NULL;

  if  (ttype == ANTLR3_TOKEN_DOWN)
  {
    if  (ctns->hasUniqueNavigationNodes(ctns) == ANTLR3_TRUE)
    {
      node    = ctns->newDownNode(ctns);
    }
    else
    {
      node    = &(ctns->DOWN.baseTree);
    }
  }
  else
  {
    if  (ctns->hasUniqueNavigationNodes(ctns) == ANTLR3_TRUE)
    {
      node    = ctns->newUpNode(ctns);
    }
    else
    {
      node    = &(ctns->UP.baseTree);
    }
  }

  // Now add the node we decided upon.
  //
  ctns->nodes->add(ctns->nodes, node, NULL);
}


static  pANTLR3_BASE_TREE_ADAPTOR          
getTreeAdaptor  (pANTLR3_TREE_NODE_STREAM tns)
{
    return  tns->ctns->adaptor;
}

static  ANTLR3_BOOLEAN      
hasUniqueNavigationNodes      (pANTLR3_COMMON_TREE_NODE_STREAM ctns)
{
    return  ctns->uniqueNavigationNodes;
}

static  void        
setUniqueNavigationNodes      (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_BOOLEAN uniqueNavigationNodes)
{
    tns->ctns->uniqueNavigationNodes = uniqueNavigationNodes;
}


/// Print out the entire tree including DOWN/UP nodes.  Uses
/// a recursive walk.  Mostly useful for testing as it yields
/// the token types not text.
///
static  pANTLR3_STRING      
toString      (pANTLR3_TREE_NODE_STREAM tns)
{

    return  tns->toStringSS(tns, tns->ctns->root, NULL);
}

static  pANTLR3_STRING      
toStringSS      (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE start, pANTLR3_BASE_TREE stop)
{
    pANTLR3_STRING  buf;

    buf = tns->ctns->stringFactory->newRaw(tns->ctns->stringFactory);

    tns->toStringWork(tns, start, stop, buf);

    return  buf;
}

static  void      
toStringWork  (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE p, pANTLR3_BASE_TREE stop, pANTLR3_STRING buf)
{

  ANTLR3_UINT32   n;
  ANTLR3_UINT32   c;

  if  (!p->isNilNode(p) )
  {
    pANTLR3_STRING  text;

    text  = p->toString(p);

    if  (text == NULL)
    {
      text = tns->ctns->stringFactory->newRaw(tns->ctns->stringFactory);

      text->addc  (text, ' ');
      text->addi  (text, p->getType(p));
    }

    buf->appendS(buf, text);
  }

  if  (p == stop)
  {
    return;    /* Finished */
  }

  n = p->getChildCount(p);

  if  (n > 0 && ! p->isNilNode(p) )
  {
    buf->addc   (buf, ' ');
    buf->addi   (buf, ANTLR3_TOKEN_DOWN);
  }

  for  (c = 0; c<n ; c++)
  {
    pANTLR3_BASE_TREE   child;

    child = p->getChild(p, c);
    tns->toStringWork(tns, child, stop, buf);
  }

  if  (n > 0 && ! p->isNilNode(p) )
  {
    buf->addc   (buf, ' ');
    buf->addi   (buf, ANTLR3_TOKEN_UP);
  }
}

static  ANTLR3_UINT32      
getLookaheadSize  (pANTLR3_COMMON_TREE_NODE_STREAM ctns)
{
    return  ctns->tail < ctns->head 
      ?  (ctns->lookAheadLength - ctns->head + ctns->tail)
      :  (ctns->tail - ctns->head);
}

static  pANTLR3_BASE_TREE      
newDownNode    (pANTLR3_COMMON_TREE_NODE_STREAM ctns)
{
    pANTLR3_COMMON_TREE      dNode;
    pANTLR3_COMMON_TOKEN    token;

    token          = antlr3CommonTokenNew(ANTLR3_TOKEN_DOWN);
  token->textState    = ANTLR3_TEXT_CHARP;
  token->tokText.chars  = (pANTLR3_UCHAR)"DOWN";
    dNode          = antlr3CommonTreeNewFromToken(token);

    return  &(dNode->baseTree);
}

static  pANTLR3_BASE_TREE      
newUpNode    (pANTLR3_COMMON_TREE_NODE_STREAM ctns)
{
    pANTLR3_COMMON_TREE      uNode;
    pANTLR3_COMMON_TOKEN    token;

    token          = antlr3CommonTokenNew(ANTLR3_TOKEN_UP);
  token->textState    = ANTLR3_TEXT_CHARP;
  token->tokText.chars  = (pANTLR3_UCHAR)"UP";
    uNode          = antlr3CommonTreeNewFromToken(token);

    return  &(uNode->baseTree);
}

/// 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 monkey-ing with the underlying
/// tree.  Also, it might be able to modify the node stream to avoid
/// re-streaming 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.
///
static  void            
replaceChildren        (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE parent, ANTLR3_INT32 startChildIndex, ANTLR3_INT32 stopChildIndex, pANTLR3_BASE_TREE t)
{
  if  (parent != NULL)
  {
    pANTLR3_BASE_TREE_ADAPTOR  adaptor;
    pANTLR3_COMMON_TREE_ADAPTOR  cta;

    adaptor  = tns->getTreeAdaptor(tns);
    cta    = (pANTLR3_COMMON_TREE_ADAPTOR)(adaptor->super);

    adaptor->replaceChildren(adaptor, parent, startChildIndex, stopChildIndex, t);
  }
}

static  pANTLR3_BASE_TREE
get              (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k)
{
  if  (tns->ctns->p == -1)
  {
    fillBufferRoot(tns->ctns);
  }

  return tns->ctns->nodes->get(tns->ctns->nodes, k);
}

static  void
push            (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_INT32 index)
{
  ctns->nodeStack->push(ctns->nodeStack, ANTLR3_FUNC_PTR(ctns->p), NULL);  // Save current index
  ctns->tnstream->istream->seek(ctns->tnstream->istream, index);
}

static  ANTLR3_INT32
pop              (pANTLR3_COMMON_TREE_NODE_STREAM ctns)
{
  ANTLR3_INT32  retVal;

  retVal = ANTLR3_UINT32_CAST(ctns->nodeStack->pop(ctns->nodeStack));
  ctns->tnstream->istream->seek(ctns->tnstream->istream, retVal);
  return retVal;
}
