/// \file
|
/// Default implementation of CommonTokenStream
|
///
|
|
// [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 <antlr3tokenstream.h>
|
|
#ifdef ANTLR3_WINDOWS
|
#pragma warning( disable : 4100 )
|
#endif
|
|
// COMMON_TOKEN_STREAM API
|
//
|
static void setTokenTypeChannel (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 ttype, ANTLR3_UINT32 channel);
|
static void discardTokenType (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_INT32 ttype);
|
static void discardOffChannel (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_BOOLEAN discard);
|
static pANTLR3_VECTOR getTokens (pANTLR3_COMMON_TOKEN_STREAM cts);
|
static pANTLR3_LIST getTokenRange (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop);
|
static pANTLR3_LIST getTokensSet (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_BITSET types);
|
static pANTLR3_LIST getTokensList (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_LIST list);
|
static pANTLR3_LIST getTokensType (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, ANTLR3_UINT32 type);
|
static void reset (pANTLR3_COMMON_TOKEN_STREAM cts);
|
|
// TOKEN_STREAM API
|
//
|
static pANTLR3_COMMON_TOKEN tokLT (pANTLR3_TOKEN_STREAM ts, ANTLR3_INT32 k);
|
static pANTLR3_COMMON_TOKEN dbgTokLT (pANTLR3_TOKEN_STREAM ts, ANTLR3_INT32 k);
|
static pANTLR3_COMMON_TOKEN get (pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 i);
|
static pANTLR3_TOKEN_SOURCE getTokenSource (pANTLR3_TOKEN_STREAM ts);
|
static void setTokenSource (pANTLR3_TOKEN_STREAM ts, pANTLR3_TOKEN_SOURCE tokenSource);
|
static pANTLR3_STRING toString (pANTLR3_TOKEN_STREAM ts);
|
static pANTLR3_STRING toStringSS (pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop);
|
static pANTLR3_STRING toStringTT (pANTLR3_TOKEN_STREAM ts, pANTLR3_COMMON_TOKEN start, pANTLR3_COMMON_TOKEN stop);
|
static void setDebugListener (pANTLR3_TOKEN_STREAM ts, pANTLR3_DEBUG_EVENT_LISTENER debugger);
|
|
// INT STREAM API
|
//
|
static void consume (pANTLR3_INT_STREAM is);
|
static void dbgConsume (pANTLR3_INT_STREAM is);
|
static ANTLR3_UINT32 _LA (pANTLR3_INT_STREAM is, ANTLR3_INT32 i);
|
static ANTLR3_UINT32 dbgLA (pANTLR3_INT_STREAM is, ANTLR3_INT32 i);
|
static ANTLR3_MARKER mark (pANTLR3_INT_STREAM is);
|
static ANTLR3_MARKER dbgMark (pANTLR3_INT_STREAM is);
|
static void release (pANTLR3_INT_STREAM is, ANTLR3_MARKER mark);
|
static ANTLR3_UINT32 size (pANTLR3_INT_STREAM is);
|
static ANTLR3_MARKER tindex (pANTLR3_INT_STREAM is);
|
static void rewindStream (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker);
|
static void dbgRewindStream (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker);
|
static void rewindLast (pANTLR3_INT_STREAM is);
|
static void dbgRewindLast (pANTLR3_INT_STREAM is);
|
static void seek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index);
|
static void dbgSeek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index);
|
static pANTLR3_STRING getSourceName (pANTLR3_INT_STREAM is);
|
static void antlr3TokenStreamFree (pANTLR3_TOKEN_STREAM stream);
|
static void antlr3CTSFree (pANTLR3_COMMON_TOKEN_STREAM stream);
|
|
// Helpers
|
//
|
static void fillBuffer (pANTLR3_COMMON_TOKEN_STREAM tokenStream);
|
static ANTLR3_UINT32 skipOffTokenChannels (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 i);
|
static ANTLR3_UINT32 skipOffTokenChannelsReverse (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 i);
|
static pANTLR3_COMMON_TOKEN LB (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 i);
|
|
ANTLR3_API pANTLR3_TOKEN_STREAM
|
antlr3TokenStreamNew()
|
{
|
pANTLR3_TOKEN_STREAM stream;
|
|
// Memory for the interface structure
|
//
|
stream = (pANTLR3_TOKEN_STREAM) ANTLR3_MALLOC(sizeof(ANTLR3_TOKEN_STREAM));
|
|
if (stream == NULL)
|
{
|
return NULL;
|
}
|
|
// Install basic API
|
//
|
stream->free = antlr3TokenStreamFree;
|
|
|
return stream;
|
}
|
|
static void
|
antlr3TokenStreamFree(pANTLR3_TOKEN_STREAM stream)
|
{
|
ANTLR3_FREE(stream);
|
}
|
|
static void
|
antlr3CTSFree (pANTLR3_COMMON_TOKEN_STREAM stream)
|
{
|
// We only free up our subordinate interfaces if they belong
|
// to us, otherwise we let whoever owns them deal with them.
|
//
|
if (stream->tstream->super == stream)
|
{
|
if (stream->tstream->istream->super == stream->tstream)
|
{
|
stream->tstream->istream->free(stream->tstream->istream);
|
stream->tstream->istream = NULL;
|
}
|
stream->tstream->free(stream->tstream);
|
}
|
|
// Now we free our own resources
|
//
|
if (stream->tokens != NULL)
|
{
|
stream->tokens->free(stream->tokens);
|
stream->tokens = NULL;
|
}
|
if (stream->discardSet != NULL)
|
{
|
stream->discardSet->free(stream->discardSet);
|
stream->discardSet = NULL;
|
}
|
if (stream->channelOverrides != NULL)
|
{
|
stream->channelOverrides->free(stream->channelOverrides);
|
stream->channelOverrides = NULL;
|
}
|
|
// Free our memory now
|
//
|
ANTLR3_FREE(stream);
|
}
|
|
// Reset a token stream so it can be used again and can reuse it's
|
// resources.
|
//
|
static void
|
reset (pANTLR3_COMMON_TOKEN_STREAM cts)
|
{
|
|
// Free any resources that ar most like specifc to the
|
// run we just did.
|
//
|
if (cts->discardSet != NULL)
|
{
|
cts->discardSet->free(cts->discardSet);
|
cts->discardSet = NULL;
|
}
|
if (cts->channelOverrides != NULL)
|
{
|
cts->channelOverrides->free(cts->channelOverrides);
|
cts->channelOverrides = NULL;
|
}
|
|
// Now, if there were any existing tokens in the stream,
|
// then we just reset the vector count so that it starts
|
// again. We must traverse the entries unfortunately as
|
// there may be free pointers for custom token types and
|
// so on. However that is just a quick NULL check on the
|
// vector entries.
|
//
|
if (cts->tokens != NULL)
|
{
|
cts->tokens->clear(cts->tokens);
|
}
|
else
|
{
|
/* Install the token tracking tables
|
*/
|
cts->tokens = antlr3VectorNew(0);
|
}
|
|
// Reset to defaults
|
//
|
cts->discardOffChannel = ANTLR3_FALSE;
|
cts->channel = ANTLR3_TOKEN_DEFAULT_CHANNEL;
|
cts->p = -1;
|
}
|
|
ANTLR3_API pANTLR3_COMMON_TOKEN_STREAM
|
antlr3CommonTokenDebugStreamSourceNew(ANTLR3_UINT32 hint, pANTLR3_TOKEN_SOURCE source, pANTLR3_DEBUG_EVENT_LISTENER debugger)
|
{
|
pANTLR3_COMMON_TOKEN_STREAM stream;
|
|
// Create a standard token stream
|
//
|
stream = antlr3CommonTokenStreamSourceNew(hint, source);
|
|
// Install the debugger object
|
//
|
stream->tstream->debugger = debugger;
|
|
// Override standard token stream methods with debugging versions
|
//
|
stream->tstream->initialStreamState = ANTLR3_FALSE;
|
|
stream->tstream->_LT = dbgTokLT;
|
|
stream->tstream->istream->consume = dbgConsume;
|
stream->tstream->istream->_LA = dbgLA;
|
stream->tstream->istream->mark = dbgMark;
|
stream->tstream->istream->rewind = dbgRewindStream;
|
stream->tstream->istream->rewindLast = dbgRewindLast;
|
stream->tstream->istream->seek = dbgSeek;
|
|
return stream;
|
}
|
|
ANTLR3_API pANTLR3_COMMON_TOKEN_STREAM
|
antlr3CommonTokenStreamSourceNew(ANTLR3_UINT32 hint, pANTLR3_TOKEN_SOURCE source)
|
{
|
pANTLR3_COMMON_TOKEN_STREAM stream;
|
|
stream = antlr3CommonTokenStreamNew(hint);
|
|
stream->channel = ANTLR3_TOKEN_DEFAULT_CHANNEL;
|
|
stream->channelOverrides = NULL;
|
stream->discardSet = NULL;
|
stream->discardOffChannel = ANTLR3_FALSE;
|
|
stream->tstream->setTokenSource(stream->tstream, source);
|
|
stream->free = antlr3CTSFree;
|
return stream;
|
}
|
|
ANTLR3_API pANTLR3_COMMON_TOKEN_STREAM
|
antlr3CommonTokenStreamNew(ANTLR3_UINT32 hint)
|
{
|
pANTLR3_COMMON_TOKEN_STREAM stream;
|
|
/* Memory for the interface structure
|
*/
|
stream = (pANTLR3_COMMON_TOKEN_STREAM) ANTLR3_MALLOC(sizeof(ANTLR3_COMMON_TOKEN_STREAM));
|
|
if (stream == NULL)
|
{
|
return NULL;
|
}
|
|
/* Create space for the token stream interface
|
*/
|
stream->tstream = antlr3TokenStreamNew();
|
stream->tstream->super = stream;
|
|
/* Create space for the INT_STREAM interfacce
|
*/
|
stream->tstream->istream = antlr3IntStreamNew();
|
stream->tstream->istream->super = (stream->tstream);
|
stream->tstream->istream->type = ANTLR3_TOKENSTREAM;
|
|
/* Install the token tracking tables
|
*/
|
stream->tokens = antlr3VectorNew(0);
|
|
/* Defaults
|
*/
|
stream->p = -1;
|
|
/* Install the common token stream API
|
*/
|
stream->setTokenTypeChannel = setTokenTypeChannel;
|
stream->discardTokenType = discardTokenType;
|
stream->discardOffChannelToks = discardOffChannel;
|
stream->getTokens = getTokens;
|
stream->getTokenRange = getTokenRange;
|
stream->getTokensSet = getTokensSet;
|
stream->getTokensList = getTokensList;
|
stream->getTokensType = getTokensType;
|
stream->reset = reset;
|
|
/* Install the token stream API
|
*/
|
stream->tstream->_LT = tokLT;
|
stream->tstream->get = get;
|
stream->tstream->getTokenSource = getTokenSource;
|
stream->tstream->setTokenSource = setTokenSource;
|
stream->tstream->toString = toString;
|
stream->tstream->toStringSS = toStringSS;
|
stream->tstream->toStringTT = toStringTT;
|
stream->tstream->setDebugListener = setDebugListener;
|
|
/* Install INT_STREAM interface
|
*/
|
stream->tstream->istream->_LA = _LA;
|
stream->tstream->istream->mark = mark;
|
stream->tstream->istream->release = release;
|
stream->tstream->istream->size = size;
|
stream->tstream->istream->index = tindex;
|
stream->tstream->istream->rewind = rewindStream;
|
stream->tstream->istream->rewindLast= rewindLast;
|
stream->tstream->istream->seek = seek;
|
stream->tstream->istream->consume = consume;
|
stream->tstream->istream->getSourceName = getSourceName;
|
|
return stream;
|
}
|
|
// Install a debug listener adn switch to debug mode methods
|
//
|
static void
|
setDebugListener (pANTLR3_TOKEN_STREAM ts, pANTLR3_DEBUG_EVENT_LISTENER debugger)
|
{
|
// Install the debugger object
|
//
|
ts->debugger = debugger;
|
|
// Override standard token stream methods with debugging versions
|
//
|
ts->initialStreamState = ANTLR3_FALSE;
|
|
ts->_LT = dbgTokLT;
|
|
ts->istream->consume = dbgConsume;
|
ts->istream->_LA = dbgLA;
|
ts->istream->mark = dbgMark;
|
ts->istream->rewind = dbgRewindStream;
|
ts->istream->rewindLast = dbgRewindLast;
|
ts->istream->seek = dbgSeek;
|
}
|
|
/** Get the ith token from the current position 1..n where k=1 is the
|
* first symbol of lookahead.
|
*/
|
static pANTLR3_COMMON_TOKEN
|
tokLT (pANTLR3_TOKEN_STREAM ts, ANTLR3_INT32 k)
|
{
|
ANTLR3_INT32 i;
|
ANTLR3_INT32 n;
|
pANTLR3_COMMON_TOKEN_STREAM cts;
|
|
cts = (pANTLR3_COMMON_TOKEN_STREAM)ts->super;
|
|
if (k < 0)
|
{
|
return LB(cts, -k);
|
}
|
|
if (cts->p == -1)
|
{
|
fillBuffer(cts);
|
}
|
|
// Here we used to check for k == 0 and return 0, but this seems
|
// a superfluous check to me. LT(k=0) is therefore just undefined
|
// and we won't waste the clock cycles on the check
|
//
|
|
if ((cts->p + k - 1) >= (ANTLR3_INT32)ts->istream->cachedSize)
|
{
|
pANTLR3_COMMON_TOKEN teof = &(ts->tokenSource->eofToken);
|
|
teof->setStartIndex (teof, ts->istream->index (ts->istream));
|
teof->setStopIndex (teof, ts->istream->index (ts->istream));
|
return teof;
|
}
|
|
i = cts->p;
|
n = 1;
|
|
/* Need to find k good tokens, skipping ones that are off channel
|
*/
|
while ( n < k)
|
{
|
/* Skip off-channel tokens */
|
i = skipOffTokenChannels(cts, i+1); /* leave p on valid token */
|
n++;
|
}
|
if ( (ANTLR3_UINT32) i >= ts->istream->cachedSize)
|
{
|
pANTLR3_COMMON_TOKEN teof = &(ts->tokenSource->eofToken);
|
|
teof->setStartIndex (teof, ts->istream->index(ts->istream));
|
teof->setStopIndex (teof, ts->istream->index(ts->istream));
|
return teof;
|
}
|
|
// Here the token must be in the input vector. Rather then incur
|
// function call penalty, we just return the pointer directly
|
// from the vector
|
//
|
return (pANTLR3_COMMON_TOKEN)cts->tokens->elements[i].element;
|
//return (pANTLR3_COMMON_TOKEN)cts->tokens->get(cts->tokens, i);
|
}
|
|
/// Debug only method to flag consumption of initial off-channel
|
/// tokens in the input stream
|
///
|
static void
|
consumeInitialHiddenTokens(pANTLR3_INT_STREAM is)
|
{
|
ANTLR3_MARKER first;
|
ANTLR3_INT32 i;
|
pANTLR3_TOKEN_STREAM ts;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
first = is->index(is);
|
|
for (i=0; i<first; i++)
|
{
|
ts->debugger->consumeHiddenToken(ts->debugger, ts->get(ts, i));
|
}
|
|
ts->initialStreamState = ANTLR3_FALSE;
|
|
}
|
|
/// As per the normal tokLT but sends information to the debugger
|
///
|
static pANTLR3_COMMON_TOKEN
|
dbgTokLT (pANTLR3_TOKEN_STREAM ts, ANTLR3_INT32 k)
|
{
|
if (ts->initialStreamState == ANTLR3_TRUE)
|
{
|
consumeInitialHiddenTokens(ts->istream);
|
}
|
return tokLT(ts, k);
|
}
|
|
#ifdef ANTLR3_WINDOWS
|
/* When fully optimized VC7 complains about non reachable code.
|
* Not yet sure if this is an optimizer bug, or a bug in the flow analysis
|
*/
|
#pragma warning( disable : 4702 )
|
#endif
|
|
static pANTLR3_COMMON_TOKEN
|
LB(pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_INT32 k)
|
{
|
ANTLR3_INT32 i;
|
ANTLR3_INT32 n;
|
|
if (cts->p == -1)
|
{
|
fillBuffer(cts);
|
}
|
if (k == 0)
|
{
|
return NULL;
|
}
|
if ((cts->p - k) < 0)
|
{
|
return NULL;
|
}
|
|
i = cts->p;
|
n = 1;
|
|
/* Need to find k good tokens, going backwards, skipping ones that are off channel
|
*/
|
while (n <= (ANTLR3_INT32) k)
|
{
|
/* Skip off-channel tokens
|
*/
|
|
i = skipOffTokenChannelsReverse(cts, i - 1); /* leave p on valid token */
|
n++;
|
}
|
if (i < 0)
|
{
|
return NULL;
|
}
|
// Here the token must be in the input vector. Rather then incut
|
// function call penalty, we jsut return the pointer directly
|
// from the vector
|
//
|
return (pANTLR3_COMMON_TOKEN)cts->tokens->elements[i].element;
|
}
|
|
static pANTLR3_COMMON_TOKEN
|
get (pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 i)
|
{
|
pANTLR3_COMMON_TOKEN_STREAM cts;
|
|
cts = (pANTLR3_COMMON_TOKEN_STREAM)ts->super;
|
|
return (pANTLR3_COMMON_TOKEN)(cts->tokens->get(cts->tokens, i)); /* Token index is zero based but vectors are 1 based */
|
}
|
|
static pANTLR3_TOKEN_SOURCE
|
getTokenSource (pANTLR3_TOKEN_STREAM ts)
|
{
|
return ts->tokenSource;
|
}
|
|
static void
|
setTokenSource ( pANTLR3_TOKEN_STREAM ts,
|
pANTLR3_TOKEN_SOURCE tokenSource)
|
{
|
ts->tokenSource = tokenSource;
|
}
|
|
static pANTLR3_STRING
|
toString (pANTLR3_TOKEN_STREAM ts)
|
{
|
pANTLR3_COMMON_TOKEN_STREAM cts;
|
|
cts = (pANTLR3_COMMON_TOKEN_STREAM)ts->super;
|
|
if (cts->p == -1)
|
{
|
fillBuffer(cts);
|
}
|
|
return ts->toStringSS(ts, 0, ts->istream->size(ts->istream));
|
}
|
|
static pANTLR3_STRING
|
toStringSS(pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop)
|
{
|
pANTLR3_STRING string;
|
pANTLR3_TOKEN_SOURCE tsource;
|
pANTLR3_COMMON_TOKEN tok;
|
ANTLR3_UINT32 i;
|
pANTLR3_COMMON_TOKEN_STREAM cts;
|
|
cts = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;
|
|
if (cts->p == -1)
|
{
|
fillBuffer(cts);
|
}
|
if (stop >= ts->istream->size(ts->istream))
|
{
|
stop = ts->istream->size(ts->istream) - 1;
|
}
|
|
/* Who is giving us these tokens?
|
*/
|
tsource = ts->getTokenSource(ts);
|
|
if (tsource != NULL && cts->tokens != NULL)
|
{
|
/* Finally, let's get a string
|
*/
|
string = tsource->strFactory->newRaw(tsource->strFactory);
|
|
for (i = start; i <= stop; i++)
|
{
|
tok = ts->get(ts, i);
|
if (tok != NULL)
|
{
|
string->appendS(string, tok->getText(tok));
|
}
|
}
|
|
return string;
|
}
|
return NULL;
|
|
}
|
|
static pANTLR3_STRING
|
toStringTT (pANTLR3_TOKEN_STREAM ts, pANTLR3_COMMON_TOKEN start, pANTLR3_COMMON_TOKEN stop)
|
{
|
if (start != NULL && stop != NULL)
|
{
|
return ts->toStringSS(ts, (ANTLR3_UINT32)start->getTokenIndex(start), (ANTLR3_UINT32)stop->getTokenIndex(stop));
|
}
|
else
|
{
|
return NULL;
|
}
|
}
|
|
/** Move the input pointer to the next incoming token. The stream
|
* must become active with LT(1) available. consume() simply
|
* moves the input pointer so that LT(1) points at the next
|
* input symbol. Consume at least one token.
|
*
|
* Walk past any token not on the channel the parser is listening to.
|
*/
|
static void
|
consume (pANTLR3_INT_STREAM is)
|
{
|
pANTLR3_COMMON_TOKEN_STREAM cts;
|
pANTLR3_TOKEN_STREAM ts;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
cts = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;
|
|
if ((ANTLR3_UINT32)cts->p < cts->tokens->count)
|
{
|
cts->p++;
|
cts->p = skipOffTokenChannels(cts, cts->p);
|
}
|
}
|
|
|
/// As per ordinary consume but notifies the debugger about hidden
|
/// tokens and so on.
|
///
|
static void
|
dbgConsume (pANTLR3_INT_STREAM is)
|
{
|
pANTLR3_TOKEN_STREAM ts;
|
ANTLR3_MARKER a;
|
ANTLR3_MARKER b;
|
pANTLR3_COMMON_TOKEN t;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
|
if (ts->initialStreamState == ANTLR3_TRUE)
|
{
|
consumeInitialHiddenTokens(is);
|
}
|
|
a = is->index(is); // Where are we right now?
|
t = ts->_LT(ts, 1); // Current token from stream
|
|
consume(is); // Standard consumer
|
|
b = is->index(is); // Where are we after consuming 1 on channel token?
|
|
ts->debugger->consumeToken(ts->debugger, t); // Tell the debugger that we consumed the first token
|
|
if (b>a+1)
|
{
|
// The standard consume caused the index to advance by more than 1,
|
// which can only happen if it skipped some off-channel tokens.
|
// we need to tell the debugger about those tokens.
|
//
|
ANTLR3_MARKER i;
|
|
for (i = a+1; i<b; i++)
|
{
|
ts->debugger->consumeHiddenToken(ts->debugger, ts->get(ts, (ANTLR3_UINT32)i));
|
}
|
|
}
|
}
|
|
/** A simple filter mechanism whereby you can tell this token stream
|
* to force all tokens of type ttype to be on channel. For example,
|
* when interpreting, we cannot execute actions so we need to tell
|
* the stream to force all WS and NEWLINE to be a different, ignored,
|
* channel.
|
*/
|
static void
|
setTokenTypeChannel (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 ttype, ANTLR3_UINT32 channel)
|
{
|
if (tokenStream->channelOverrides == NULL)
|
{
|
tokenStream->channelOverrides = antlr3ListNew(10);
|
}
|
|
/* We add one to the channel so we can distinguish NULL as being no entry in the
|
* table for a particular token type.
|
*/
|
tokenStream->channelOverrides->put(tokenStream->channelOverrides, ttype, ANTLR3_FUNC_PTR((ANTLR3_UINT32)channel + 1), NULL);
|
}
|
|
static void
|
discardTokenType (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 ttype)
|
{
|
if (tokenStream->discardSet == NULL)
|
{
|
tokenStream->discardSet = antlr3ListNew(31);
|
}
|
|
/* We add one to the channel so we can distinguish NULL as being no entry in the
|
* table for a particular token type. We could use bitsets for this I suppose too.
|
*/
|
tokenStream->discardSet->put(tokenStream->discardSet, ttype, ANTLR3_FUNC_PTR((ANTLR3_UINT32)ttype + 1), NULL);
|
}
|
|
static void
|
discardOffChannel (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_BOOLEAN discard)
|
{
|
tokenStream->discardOffChannel = discard;
|
}
|
|
static pANTLR3_VECTOR
|
getTokens (pANTLR3_COMMON_TOKEN_STREAM tokenStream)
|
{
|
if (tokenStream->p == -1)
|
{
|
fillBuffer(tokenStream);
|
}
|
|
return tokenStream->tokens;
|
}
|
|
static pANTLR3_LIST
|
getTokenRange (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop)
|
{
|
return tokenStream->getTokensSet(tokenStream, start, stop, NULL);
|
}
|
/** Given a start and stop index, return a List of all tokens in
|
* the token type BitSet. Return null if no tokens were found. This
|
* method looks at both on and off channel tokens.
|
*/
|
static pANTLR3_LIST
|
getTokensSet (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_BITSET types)
|
{
|
pANTLR3_LIST filteredList;
|
ANTLR3_UINT32 i;
|
ANTLR3_UINT32 n;
|
pANTLR3_COMMON_TOKEN tok;
|
|
if (tokenStream->p == -1)
|
{
|
fillBuffer(tokenStream);
|
}
|
if (stop > tokenStream->tstream->istream->size(tokenStream->tstream->istream))
|
{
|
stop = tokenStream->tstream->istream->size(tokenStream->tstream->istream);
|
}
|
if (start > stop)
|
{
|
return NULL;
|
}
|
|
/* We have the range set, now we need to iterate through the
|
* installed tokens and create a new list with just the ones we want
|
* in it. We are just moving pointers about really.
|
*/
|
filteredList = antlr3ListNew((ANTLR3_UINT32)tokenStream->tstream->istream->size(tokenStream->tstream->istream));
|
|
for (i = start, n = 0; i<= stop; i++)
|
{
|
tok = tokenStream->tstream->get(tokenStream->tstream, i);
|
|
if ( types == NULL
|
|| types->isMember(types, tok->getType(tok) == ANTLR3_TRUE)
|
)
|
{
|
filteredList->put(filteredList, n++, (void *)tok, NULL);
|
}
|
}
|
|
/* Did we get any then?
|
*/
|
if (filteredList->size(filteredList) == 0)
|
{
|
filteredList->free(filteredList);
|
filteredList = NULL;
|
}
|
|
return filteredList;
|
}
|
|
static pANTLR3_LIST
|
getTokensList (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_LIST list)
|
{
|
pANTLR3_BITSET bitSet;
|
pANTLR3_LIST newlist;
|
|
bitSet = antlr3BitsetList(list->table);
|
|
newlist = tokenStream->getTokensSet(tokenStream, start, stop, bitSet);
|
|
bitSet->free(bitSet);
|
|
return newlist;
|
|
}
|
|
static pANTLR3_LIST
|
getTokensType (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, ANTLR3_UINT32 type)
|
{
|
pANTLR3_BITSET bitSet;
|
pANTLR3_LIST newlist;
|
|
bitSet = antlr3BitsetOf(type, -1);
|
newlist = tokenStream->getTokensSet(tokenStream, start, stop, bitSet);
|
|
bitSet->free(bitSet);
|
|
return newlist;
|
}
|
|
static ANTLR3_UINT32
|
_LA (pANTLR3_INT_STREAM is, ANTLR3_INT32 i)
|
{
|
pANTLR3_TOKEN_STREAM ts;
|
pANTLR3_COMMON_TOKEN tok;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
|
tok = ts->_LT(ts, i);
|
|
if (tok != NULL)
|
{
|
return tok->getType(tok);
|
}
|
else
|
{
|
return ANTLR3_TOKEN_INVALID;
|
}
|
}
|
|
/// As per _LA() but for debug mode.
|
///
|
static ANTLR3_UINT32
|
dbgLA (pANTLR3_INT_STREAM is, ANTLR3_INT32 i)
|
{
|
pANTLR3_TOKEN_STREAM ts;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
|
if (ts->initialStreamState == ANTLR3_TRUE)
|
{
|
consumeInitialHiddenTokens(is);
|
}
|
ts->debugger->LT(ts->debugger, i, tokLT(ts, i));
|
return _LA(is, i);
|
}
|
|
static ANTLR3_MARKER
|
mark (pANTLR3_INT_STREAM is)
|
{
|
is->lastMarker = is->index(is);
|
return is->lastMarker;
|
}
|
|
/// As per mark() but with a call to tell the debugger we are doing this
|
///
|
static ANTLR3_MARKER
|
dbgMark (pANTLR3_INT_STREAM is)
|
{
|
pANTLR3_TOKEN_STREAM ts;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
|
is->lastMarker = is->index(is);
|
ts->debugger->mark(ts->debugger, is->lastMarker);
|
|
return is->lastMarker;
|
}
|
|
static void
|
release (pANTLR3_INT_STREAM is, ANTLR3_MARKER mark)
|
{
|
return;
|
}
|
|
static ANTLR3_UINT32
|
size (pANTLR3_INT_STREAM is)
|
{
|
pANTLR3_COMMON_TOKEN_STREAM cts;
|
pANTLR3_TOKEN_STREAM ts;
|
|
if (is->cachedSize > 0)
|
{
|
return is->cachedSize;
|
}
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
cts = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;
|
|
is->cachedSize = cts->tokens->count;
|
return is->cachedSize;
|
}
|
|
static ANTLR3_MARKER
|
tindex (pANTLR3_INT_STREAM is)
|
{
|
pANTLR3_COMMON_TOKEN_STREAM cts;
|
pANTLR3_TOKEN_STREAM ts;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
cts = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;
|
|
return cts->p;
|
}
|
|
static void
|
dbgRewindLast (pANTLR3_INT_STREAM is)
|
{
|
pANTLR3_TOKEN_STREAM ts;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
|
ts->debugger->rewindLast(ts->debugger);
|
|
is->rewind(is, is->lastMarker);
|
}
|
static void
|
rewindLast (pANTLR3_INT_STREAM is)
|
{
|
is->rewind(is, is->lastMarker);
|
}
|
static void
|
rewindStream (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)
|
{
|
is->seek(is, (ANTLR3_UINT32)(marker));
|
}
|
static void
|
dbgRewindStream (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)
|
{
|
pANTLR3_TOKEN_STREAM ts;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
|
ts->debugger->rewind(ts->debugger, marker);
|
|
is->seek(is, (ANTLR3_UINT32)(marker));
|
}
|
|
static void
|
seek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index)
|
{
|
pANTLR3_COMMON_TOKEN_STREAM cts;
|
pANTLR3_TOKEN_STREAM ts;
|
|
ts = (pANTLR3_TOKEN_STREAM) is->super;
|
cts = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;
|
|
cts->p = (ANTLR3_UINT32)index;
|
}
|
static void
|
dbgSeek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index)
|
{
|
// TODO: Implement seek in debugger when Ter adds it to Java
|
//
|
seek(is, index);
|
}
|
ANTLR3_API void
|
fillBufferExt(pANTLR3_COMMON_TOKEN_STREAM tokenStream)
|
{
|
fillBuffer(tokenStream);
|
}
|
static void
|
fillBuffer(pANTLR3_COMMON_TOKEN_STREAM tokenStream) {
|
ANTLR3_UINT32 index;
|
pANTLR3_COMMON_TOKEN tok;
|
ANTLR3_BOOLEAN discard;
|
void * channelI;
|
|
/* Start at index 0 of course
|
*/
|
index = 0;
|
|
/* Pick out the next token from the token source
|
* Remember we just get a pointer (reference if you like) here
|
* and so if we store it anywhere, we don't set any pointers to auto free it.
|
*/
|
tok = tokenStream->tstream->tokenSource->nextToken(tokenStream->tstream->tokenSource);
|
|
while (tok != NULL && tok->type != ANTLR3_TOKEN_EOF)
|
{
|
discard = ANTLR3_FALSE; /* Assume we are not discarding */
|
|
/* I employ a bit of a trick, or perhaps hack here. Rather than
|
* store a pointer to a structure in the override map and discard set
|
* we store the value + 1 cast to a void *. Hence on systems where NULL = (void *)0
|
* we can distinguish "not being there" from "being channel or type 0"
|
*/
|
|
if (tokenStream->discardSet != NULL
|
&& tokenStream->discardSet->get(tokenStream->discardSet, tok->getType(tok)) != NULL)
|
{
|
discard = ANTLR3_TRUE;
|
}
|
else if ( tokenStream->discardOffChannel == ANTLR3_TRUE
|
&& tok->getChannel(tok) != tokenStream->channel
|
)
|
{
|
discard = ANTLR3_TRUE;
|
}
|
else if (tokenStream->channelOverrides != NULL)
|
{
|
/* See if this type is in the override map
|
*/
|
channelI = tokenStream->channelOverrides->get(tokenStream->channelOverrides, tok->getType(tok) + 1);
|
|
if (channelI != NULL)
|
{
|
/* Override found
|
*/
|
tok->setChannel(tok, ANTLR3_UINT32_CAST(channelI) - 1);
|
}
|
}
|
|
/* If not discarding it, add it to the list at the current index
|
*/
|
if (discard == ANTLR3_FALSE)
|
{
|
/* Add it, indicating that we will delete it and the table should not
|
*/
|
tok->setTokenIndex(tok, index);
|
tokenStream->p++;
|
tokenStream->tokens->add(tokenStream->tokens, (void *) tok, NULL);
|
index++;
|
}
|
|
tok = tokenStream->tstream->tokenSource->nextToken(tokenStream->tstream->tokenSource);
|
}
|
|
/* Cache the size so we don't keep doing indirect method calls. We do this as
|
* early as possible so that anything after this may utilize the cached value.
|
*/
|
tokenStream->tstream->istream->cachedSize = tokenStream->tokens->count;
|
|
/* Set the consume pointer to the first token that is on our channel
|
*/
|
tokenStream->p = 0;
|
tokenStream->p = skipOffTokenChannels(tokenStream, tokenStream->p);
|
|
}
|
|
/// Given a starting index, return the index of the first on-channel
|
/// token.
|
///
|
static ANTLR3_UINT32
|
skipOffTokenChannels(pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 i) {
|
ANTLR3_INT32 n;
|
pANTLR3_COMMON_TOKEN tok;
|
|
n = tokenStream->tstream->istream->cachedSize;
|
|
while (i < n)
|
{
|
tok = (pANTLR3_COMMON_TOKEN)tokenStream->tokens->elements[i].element;
|
|
if (tok->channel!= tokenStream->channel)
|
{
|
i++;
|
}
|
else
|
{
|
return i;
|
}
|
}
|
return i;
|
}
|
|
static ANTLR3_UINT32
|
skipOffTokenChannelsReverse(pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 x)
|
{
|
pANTLR3_COMMON_TOKEN tok;
|
|
while (x >= 0)
|
{
|
tok = (pANTLR3_COMMON_TOKEN)tokenStream->tokens->elements[x].element;
|
|
if ((tok->channel != tokenStream->channel))
|
{
|
x--;
|
}
|
else
|
{
|
return x;
|
}
|
}
|
return x;
|
}
|
|
/// Return a string that represents the name assoicated with the input source
|
///
|
/// /param[in] is The ANTLR3_INT_STREAM interface that is representing this token stream.
|
///
|
/// /returns
|
/// /implements ANTLR3_INT_STREAM_struct::getSourceName()
|
///
|
static pANTLR3_STRING
|
getSourceName (pANTLR3_INT_STREAM is)
|
{
|
// Slightly convoluted as we must trace back to the lexer's input source
|
// via the token source. The streamName that is here is not initialized
|
// because this is a token stream, not a file or string stream, which are the
|
// only things that have a context for a source name.
|
//
|
return ((pANTLR3_TOKEN_STREAM)(is->super))->tokenSource->fileName;
|
}
|