blob: 4dce47cfbd9557349dbc676c06b6a2480e3fec9b [file] [log] [blame]
ANTLR_BEGIN_NAMESPACE()
template<class ImplTraits>
CommonTreeNodeStream<ImplTraits>::CommonTreeNodeStream(ANTLR_UINT32 hint)
{
this->init(hint);
}
template<class ImplTraits>
void CommonTreeNodeStream<ImplTraits>::init( ANTLR_UINT32 hint )
{
m_root = NULL;
m_adaptor = new TreeAdaptorType;
// Create the node list map
//
if (hint == 0)
hint = DEFAULT_INITIAL_BUFFER_SIZE;
m_nodes.reserve( DEFAULT_INITIAL_BUFFER_SIZE );
m_p = -1;
m_currentNode = NULL;
m_previousNode = NULL;
m_currentChildIndex = 0;
m_absoluteNodeIndex = 0;
m_lookAhead = NULL;
m_lookAheadLength = 0;
m_head = 0;
m_tail = 0;
m_uniqueNavigationNodes = false;
m_isRewriter = false;
CommonTokenType* token = new CommonTokenType(CommonTokenType::TOKEN_UP);
token->set_tokText( "UP" );
m_UP.set_token( token );
token = new CommonTokenType(CommonTokenType::TOKEN_DOWN);
token->set_tokText( "DOWN" );
m_DOWN.set_token( token );
token = new CommonTokenType(CommonTokenType::TOKEN_EOF);
token->set_tokText( "EOF" );
m_EOF_NODE.set_token( token );
token = new CommonTokenType(CommonTokenType::TOKEN_INVALID);
token->set_tokText( "INVALID" );
m_EOF_NODE.set_token( token );
}
template<class ImplTraits>
CommonTreeNodeStream<ImplTraits>::CommonTreeNodeStream( const CommonTreeNodeStream& ctn )
{
m_root = ctn.m_root;
m_adaptor = ctn.m_adaptor;
m_nodes.reserve( DEFAULT_INITIAL_BUFFER_SIZE );
m_nodeStack = ctn.m_nodeStack;
m_p = -1;
m_currentNode = NULL;
m_previousNode = NULL;
m_currentChildIndex = 0;
m_absoluteNodeIndex = 0;
m_lookAhead = NULL;
m_lookAheadLength = 0;
m_head = 0;
m_tail = 0;
m_uniqueNavigationNodes = false;
m_isRewriter = true;
m_UP.set_token( ctn.m_UP.get_token() );
m_DOWN.set_token( ctn.m_DOWN.get_token() );
m_EOF_NODE.set_token( ctn.m_EOF_NODE.get_token() );
m_INVALID_NODE.set_token( ctn.m_INVALID_NODE.get_token() );
}
template<class ImplTraits>
CommonTreeNodeStream<ImplTraits>::CommonTreeNodeStream( TreeType* tree, ANTLR_UINT32 hint )
{
this->init(hint);
m_root = tree;
}
template<class ImplTraits>
CommonTreeNodeStream<ImplTraits>::~CommonTreeNodeStream()
{
// If this is a rewrting stream, then certain resources
// belong to the originating node stream and we do not
// free them here.
//
if ( m_isRewriter != true)
{
delete m_adaptor;
m_nodeStack.clear();
delete m_INVALID_NODE.get_token();
delete m_EOF_NODE.get_token();
delete m_DOWN.get_token();
delete m_UP.get_token();
}
m_nodes.clear();
}
template<class ImplTraits>
typename CommonTreeNodeStream<ImplTraits>::TreeType* CommonTreeNodeStream<ImplTraits>::_LT(ANTLR_INT32 k)
{
if ( m_p == -1)
{
this->fillBufferRoot();
}
if (k < 0)
{
return this->LB(-k);
}
else if (k == 0)
{
return &(m_INVALID_NODE);
}
// k was a legitimate request,
//
if (( m_p + k - 1) >= (ANTLR_INT32)(m_nodes.size()))
{
return &(m_EOF_NODE);
}
return m_nodes[ m_p + k - 1 ];
}
template<class ImplTraits>
typename CommonTreeNodeStream<ImplTraits>::TreeType* CommonTreeNodeStream<ImplTraits>::getTreeSource()
{
return m_root;
}
template<class ImplTraits>
typename CommonTreeNodeStream<ImplTraits>::TreeAdaptorType* CommonTreeNodeStream<ImplTraits>::getTreeAdaptor()
{
return m_adaptor;
}
template<class ImplTraits>
void CommonTreeNodeStream<ImplTraits>::set_uniqueNavigationNodes(bool uniqueNavigationNodes)
{
m_uniqueNavigationNodes = uniqueNavigationNodes;
}
template<class ImplTraits>
typename CommonTreeNodeStream<ImplTraits>::StringType CommonTreeNodeStream<ImplTraits>::toString()
{
return this->toStringSS(m_root, NULL);
}
template<class ImplTraits>
typename CommonTreeNodeStream<ImplTraits>::StringType CommonTreeNodeStream<ImplTraits>::toStringSS(TreeType* start, TreeType* stop)
{
StringType buf;
this->toStringWork(start, stop, buf);
return buf;
}
template<class ImplTraits>
void CommonTreeNodeStream<ImplTraits>::toStringWork(TreeType* start, TreeType* stop, StringType& str)
{
ANTLR_UINT32 n;
ANTLR_UINT32 c;
StringStreamType buf;
if (!start->isNilNode() )
{
StringType text;
text = start->toString();
if (text.empty())
{
buf << ' ';
buf << start->getType();
}
else
buf << text;
}
if (start == stop)
{
return; /* Finished */
}
n = start->getChildCount();
if (n > 0 && ! start->isNilNode() )
{
buf << ' ';
buf << CommonTokenType::TOKEN_DOWN;
}
for (c = 0; c<n ; c++)
{
TreeType* child;
child = start->getChild(c);
this->toStringWork(child, stop, buf);
}
if (n > 0 && ! start->isNilNode() )
{
buf << ' ';
buf << CommonTokenType::TOKEN_UP;
}
str = buf.str();
}
template<class ImplTraits>
typename CommonTreeNodeStream<ImplTraits>::TreeType* CommonTreeNodeStream<ImplTraits>::get(ANTLR_INT32 k)
{
if( m_p == -1 )
{
this->fillBufferRoot();
}
return m_nodes[k];
}
template<class ImplTraits>
void CommonTreeNodeStream<ImplTraits>::replaceChildren(TreeType* parent,
ANTLR_INT32 startChildIndex,
ANTLR_INT32 stopChildIndex,
TreeType* t)
{
if (parent != NULL)
{
TreeAdaptorType* adaptor;
adaptor = this->getTreeAdaptor();
adaptor->replaceChildren(parent, startChildIndex, stopChildIndex, t);
}
}
template<class ImplTraits>
typename CommonTreeNodeStream<ImplTraits>::TreeType* CommonTreeNodeStream<ImplTraits>::LB(ANTLR_INT32 k)
{
if ( k==0)
{
return &(m_INVALID_NODE);
}
if ( (m_p - k) < 0)
{
return &(m_INVALID_NODE);
}
return m_nodes[ m_p - k ];
}
template<class ImplTraits>
void CommonTreeNodeStream<ImplTraits>::addNavigationNode(ANTLR_UINT32 ttype)
{
TreeType* node;
node = NULL;
if (ttype == CommonTokenType::TOKEN_DOWN)
{
if (this->hasUniqueNavigationNodes() == true)
{
node = this->newDownNode();
}
else
{
node = &m_DOWN;
}
}
else
{
if (this->hasUniqueNavigationNodes() == true)
{
node = this->newUpNode();
}
else
{
node = &m_UP;
}
}
// Now add the node we decided upon.
//
m_nodes.push_back(node);
}
template<class ImplTraits>
typename CommonTreeNodeStream<ImplTraits>::TreeType* CommonTreeNodeStream<ImplTraits>::newDownNode()
{
TreeType* dNode;
CommonTokenType* token;
token = new CommonTokenType(CommonTokenType::TOKEN_DOWN);
token->set_tokText("DOWN");
dNode = new TreeType(token);
return &dNode;
}
template<class ImplTraits>
typename CommonTreeNodeStream<ImplTraits>::TreeType* CommonTreeNodeStream<ImplTraits>::newUpNode()
{
TreeType* uNode;
CommonTokenType* token;
token = new CommonTokenType(CommonTokenType::TOKEN_UP);
token->set_tokText("UP");
uNode = new TreeType(token);
return &uNode;
}
template<class ImplTraits>
bool CommonTreeNodeStream<ImplTraits>::hasUniqueNavigationNodes() const
{
return m_uniqueNavigationNodes;
}
template<class ImplTraits>
ANTLR_UINT32 CommonTreeNodeStream<ImplTraits>::getLookaheadSize()
{
return m_tail < m_head
? (m_lookAheadLength - m_head + m_tail)
: (m_tail - m_head);
}
template<class ImplTraits>
void CommonTreeNodeStream<ImplTraits>::push(ANTLR_INT32 index)
{
m_nodeStack.push(m_p); // Save current index
this->seek(index);
}
template<class ImplTraits>
ANTLR_INT32 CommonTreeNodeStream<ImplTraits>::pop()
{
ANTLR_INT32 retVal;
retVal = m_nodeStack.top();
m_nodeStack.pop();
this->seek(retVal);
return retVal;
}
template<class ImplTraits>
void CommonTreeNodeStream<ImplTraits>::reset()
{
if ( m_p != -1)
{
m_p = 0;
}
BaseType::m_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 (m_isRewriter != true)
m_nodeStack.clear();
}
template<class ImplTraits>
void CommonTreeNodeStream<ImplTraits>::fillBufferRoot()
{
// Call the generic buffer routine with the root as the
// argument
//
this->fillBuffer(m_root);
m_p = 0; // Indicate we are at buffer start
}
template<class ImplTraits>
void CommonTreeNodeStream<ImplTraits>::fillBuffer(TreeType* t)
{
bool nilNode;
ANTLR_UINT32 nCount;
ANTLR_UINT32 c;
nilNode = m_adaptor->isNilNode(t);
// If the supplied node is not a nil (list) node then we
// add in the node itself to the vector
//
if (nilNode == false)
{
m_nodes.push_back(t);
}
// Only add a DOWN node if the tree is not a nil tree and
// the tree does have children.
//
nCount = t->getChildCount();
if (nilNode == false && nCount>0)
{
this->addNavigationNode( CommonTokenType::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++)
{
this->fillBuffer( m_adaptor->getChild(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 == false && nCount > 0)
{
this->addNavigationNode(CommonTokenType::TOKEN_UP);
}
}
ANTLR_END_NAMESPACE()