blob: ec06f15750632291cdc7d820aceddbeca02627d2 [file] [log] [blame]
/// \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;
}