ANTLR_BEGIN_NAMESPACE()

template< class ImplTraits, class StreamType >
BaseRecognizer<ImplTraits, StreamType>::BaseRecognizer(ANTLR_UINT32 sizeHint,
											RecognizerSharedStateType* state)
{
	m_debugger = NULL;

	// If we have been supplied with a pre-existing recognizer state
	// then we just install it, otherwise we must create one from scratch
	//
	if	(state == NULL)
	{
		m_state = new RecognizerSharedStateType();
		m_state->set_sizeHint( sizeHint );
	}
	else
	{
		// Install the one we were given, and do not reset it here
		// as it will either already have been initialized or will
		// be in a state that needs to be preserved.
		//
		m_state = state;
	}
}

template< class ImplTraits, class StreamType >
ANTLR_INLINE typename BaseRecognizer<ImplTraits, StreamType>::SuperType* BaseRecognizer<ImplTraits, StreamType>::get_super()
{
	return static_cast<SuperType*>(this);
}

template< class ImplTraits, class StreamType >
ANTLR_INLINE typename BaseRecognizer<ImplTraits, StreamType>::RecognizerSharedStateType* BaseRecognizer<ImplTraits, StreamType>::get_state() const
{
	return m_state;
}
template< class ImplTraits, class StreamType >
ANTLR_INLINE typename BaseRecognizer<ImplTraits, StreamType>::DebugEventListenerType* BaseRecognizer<ImplTraits, StreamType>::get_debugger() const
{
	return m_debugger;
}
template< class ImplTraits, class StreamType >
ANTLR_INLINE void BaseRecognizer<ImplTraits, StreamType>::set_state( RecognizerSharedStateType* state )
{
	m_state = state;
}
template< class ImplTraits, class StreamType >
ANTLR_INLINE void BaseRecognizer<ImplTraits, StreamType>::set_debugger( DebugEventListenerType* debugger )
{
	m_debugger = debugger;
}

template< class ImplTraits, class StreamType >
const typename BaseRecognizer<ImplTraits, StreamType>::UnitType* 
BaseRecognizer<ImplTraits, StreamType>::match(ANTLR_UINT32 ttype, BitsetListType* follow)
{
	SuperType*  super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_istream();

	// Pick up the current input token/node for assignment to labels
	//
	const UnitType* matchedSymbol = this->getCurrentInputSymbol(is);

    if	(is->_LA(1) == ttype)
    {
		// The token was the one we were told to expect
		//
		is->consume();					   // Consume that token from the stream
		m_state->set_errorRecovery(false); // Not in error recovery now (if we were)
		m_state->set_failed(false);	// The match was a success
		return matchedSymbol;								// We are done
    }

    // We did not find the expected token type, if we are backtracking then
    // we just set the failed flag and return.
    //
    if	( m_state->get_backtracking() > 0)
    {
		// Backtracking is going on
		//
		m_state->set_failed(true);
		return matchedSymbol;
	}

    // We did not find the expected token and there is no backtracking
    // going on, so we mismatch, which creates an exception in the recognizer exception
    // stack.
    //
	matchedSymbol = this->recoverFromMismatchedToken(ttype, follow);
    return matchedSymbol;

}

template< class ImplTraits, class StreamType >
void BaseRecognizer<ImplTraits, StreamType>::matchAny()
{
	SuperType*  super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_istream();

	is->consume();
	m_state->set_errorRecovery(false);
	m_state->set_failed(false);
    return;
}

template< class ImplTraits, class StreamType >
bool BaseRecognizer<ImplTraits, StreamType>::mismatchIsUnwantedToken(IntStreamType* is, ANTLR_UINT32 ttype)
{
	ANTLR_UINT32 nextt = is->_LA(2);

	if	(nextt == ttype)
	{
		if(m_state->get_exception() != NULL)
			m_state->get_exception()->set_expecting(nextt);
		return true;		// This token is unknown, but the next one is the one we wanted
	}
	else
		return false;	// Neither this token, nor the one following is the one we wanted
}

template< class ImplTraits, class StreamType >
bool BaseRecognizer<ImplTraits, StreamType>::mismatchIsMissingToken(IntStreamType* is, BitsetListType* follow)
{
	bool	retcode;
	BitsetType*	followClone;
	BitsetType*	viableTokensFollowingThisRule;

	if	(follow == NULL)
	{
		// There is no information about the tokens that can follow the last one
		// hence we must say that the current one we found is not a member of the
		// follow set and does not indicate a missing token. We will just consume this
		// single token and see if the parser works it out from there.
		//
		return	false;
	}

	followClone						= NULL;
	viableTokensFollowingThisRule	= NULL;

	// The C bitset maps are laid down at compile time by the
	// C code generation. Hence we cannot remove things from them
	// and so on. So, in order to remove EOR (if we need to) then
	// we clone the static bitset.
	//
	followClone = follow->bitsetLoad();
	if	(followClone == NULL)
		return false;

	// Compute what can follow this grammar reference
	//
	if	(followClone->isMember( ImplTraits::CommonTokenType::EOR_TOKEN_TYPE))
	{
		// EOR can follow, but if we are not the start symbol, we
		// need to remove it.
		//
		followClone->remove(ImplTraits::CommonTokenType::EOR_TOKEN_TYPE);

		// Now compute the visiable tokens that can follow this rule, according to context
		// and make them part of the follow set.
		//
		viableTokensFollowingThisRule = this->computeCSRuleFollow();
		followClone->borInPlace(viableTokensFollowingThisRule);
	}

	/// if current token is consistent with what could come after set
	/// then we know we're missing a token; error recovery is free to
	/// "insert" the missing token
	///
	/// BitSet cannot handle negative numbers like -1 (EOF) so I leave EOR
	/// in follow set to indicate that the fall of the start symbol is
	/// in the set (EOF can follow).
	///
	if	(		followClone->isMember(is->_LA(1))
			||	followClone->isMember(ImplTraits::CommonTokenType::EOR_TOKEN_TYPE)
		)
	{
		retcode = true;
	}
	else
	{
		retcode	= false;
	}

	if	(viableTokensFollowingThisRule != NULL)
	{
		delete viableTokensFollowingThisRule;
	}
	if	(followClone != NULL)
	{
		delete followClone;
	}

	return retcode;
}

template< class ImplTraits, class StreamType >
void BaseRecognizer<ImplTraits, StreamType>::mismatch(ANTLR_UINT32 ttype, BitsetListType* follow)
{
	this->get_super()->mismatch( ttype, follow );
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::reportError()
{
	this->reportError( ClassForwarder<SuperType>() );
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::reportError( ClassForwarder<LexerType> )
{
	// Indicate this recognizer had an error while processing.
	//
	m_state->inc_errorCount();

    this->displayRecognitionError(m_state->get_tokenNames());
}

template< class ImplTraits, class StreamType >
template<typename CompType>
void	BaseRecognizer<ImplTraits, StreamType>::reportError(ClassForwarder<CompType> )
{
	    // Invoke the debugger event if there is a debugger listening to us
	//
	if	( m_debugger != NULL)
	{
		m_debugger->recognitionException( m_state->get_exception() );
	}

    if	( m_state->get_errorRecovery() == true)
    {
		// Already in error recovery so don't display another error while doing so
		//
		return;
    }

    // Signal we are in error recovery now
    //
    m_state->set_errorRecovery(true);

	// Indicate this recognizer had an error while processing.
	//
	m_state->inc_errorCount();

	// Call the error display routine
	//
    this->displayRecognitionError( m_state->get_tokenNames() );
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::displayRecognitionError(ANTLR_UINT8** tokenNames)
{
	// Retrieve some info for easy reading.
	//
	ExceptionBaseType* ex	    =		m_state->get_exception();
	StringType ttext;

	// See if there is a 'filename' we can use
	//
	SuperType* super = static_cast<SuperType*>(this);
	super->displayRecognitionError(tokenNames, ex);
}

template< class ImplTraits, class StreamType >
ANTLR_UINT32 BaseRecognizer<ImplTraits, StreamType>::getNumberOfSyntaxErrors()
{
	return	m_state->get_errorCount();
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::recover()
{
	SuperType* super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_parser_istream();
	// Are we about to repeat the same error?
	//
    if	( m_state->get_lastErrorIndex() == is->index())
    {
		// The last error was at the same token index point. This must be a case
		// where LT(1) is in the recovery token set so nothing is
		// consumed. Consume a single token so at least to prevent
		// an infinite loop; this is a failsafe.
		//
		is->consume();
    }

    // Record error index position
    //
    m_state->set_lastErrorIndex( is->index() );

    // Work out the follows set for error recovery
    //
    BitsetType* followSet	= this->computeErrorRecoverySet();

    // Call resync hook (for debuggers and so on)
    //
    this->beginResync();

    // Consume tokens until we have resynced to something in the follows set
    //
    this->consumeUntilSet(followSet);

    // End resync hook
    //
    this->endResync();

    // Destroy the temporary bitset we produced.
    //
    delete followSet;

    // Reset the inError flag so we don't re-report the exception
    //
    m_state->set_error(false);
    m_state->set_failed(false);
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::beginResync()
{
	if	(m_debugger != NULL)
	{
		m_debugger->beginResync();
	}
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::endResync()
{
	if	(m_debugger != NULL)
	{
		m_debugger->endResync();
	}
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::beginBacktrack(ANTLR_UINT32 level)
{
	if	(m_debugger != NULL)
	{
		m_debugger->beginBacktrack(level);
	}
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::endBacktrack(ANTLR_UINT32 level, bool successful)
{
	if	(m_debugger != NULL)
	{
		m_debugger->endBacktrack(level);
	}
}

template< class ImplTraits, class StreamType >
typename BaseRecognizer<ImplTraits, StreamType>::BitsetType*	BaseRecognizer<ImplTraits, StreamType>::computeErrorRecoverySet()
{
	return   this->combineFollows(false);
}

template< class ImplTraits, class StreamType >
typename BaseRecognizer<ImplTraits, StreamType>::BitsetType*	BaseRecognizer<ImplTraits, StreamType>::computeCSRuleFollow()
{
	return   this->combineFollows(false);
}

template< class ImplTraits, class StreamType >
typename BaseRecognizer<ImplTraits, StreamType>::BitsetType*	BaseRecognizer<ImplTraits, StreamType>::combineFollows(bool exact)
{
	BitsetType*	followSet;
    BitsetType*	localFollowSet;
    ANTLR_UINT32	top;
    ANTLR_UINT32	i;

    top	= static_cast<ANTLR_UINT32>( m_state->get_following().size() );

    followSet	    = new BitsetType(0);
	localFollowSet	= NULL;

    for (i = top; i>0; i--)
    {
		localFollowSet =  m_state->get_following().at(i-1).bitsetLoad();

		if  (localFollowSet != NULL)
		{
			followSet->borInPlace(localFollowSet);

			if	(exact == true)
			{
				if	(localFollowSet->isMember( ImplTraits::CommonTokenType::EOR_TOKEN_TYPE) == false)
				{
					// Only leave EOR in the set if at top (start rule); this lets us know
					// if we have to include the follow(start rule); I.E., EOF
					//
					if	(i>1)
					{
						followSet->remove(ImplTraits::CommonTokenType::EOR_TOKEN_TYPE);
					}
				}
				else
				{
					break;	// Cannot see End Of Rule from here, just drop out
				}
			}
			delete localFollowSet;
			localFollowSet = NULL;
		}
    }

	if	(localFollowSet != NULL)
	{
		delete localFollowSet;
	}
    return  followSet;
}

template< class ImplTraits, class StreamType >
const typename BaseRecognizer<ImplTraits, StreamType>::UnitType* 
BaseRecognizer<ImplTraits, StreamType>::recoverFromMismatchedToken( ANTLR_UINT32	ttype, BitsetListType*	follow)
{
	SuperType* super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_parser_istream();
	const UnitType* matchedSymbol;

	// If the next token after the one we are looking at in the input stream
	// is what we are looking for then we remove the one we have discovered
	// from the stream by consuming it, then consume this next one along too as
	// if nothing had happened.
	//
	if	( this->mismatchIsUnwantedToken( is, ttype) == true)
	{
		// Create an exception if we need one
		//
		new ANTLR_Exception<ImplTraits, UNWANTED_TOKEN_EXCEPTION, StreamType>(this, "");

		// Call resync hook (for debuggers and so on)
		//
		if	(m_debugger != NULL)
		{
			m_debugger->beginResync();
		}

		// "delete" the extra token
		//
		this->beginResync();
		is->consume();
		this->endResync();
		// End resync hook
		//
		if	(m_debugger != NULL)
		{
			m_debugger->endResync();
		}

		// Print out the error after we consume so that ANTLRWorks sees the
		// token in the exception.
		//
		this->reportError();

		// Return the token we are actually matching
		//
		matchedSymbol = this->getCurrentInputSymbol(is);

		// Consume the token that the rule actually expected to get as if everything
		// was hunky dory.
		//
		is->consume();

		m_state->set_error(false); // Exception is not outstanding any more

		return	matchedSymbol;
	}

	// Single token deletion (Unwanted above) did not work
	// so we see if we can insert a token instead by calculating which
	// token would be missing
	//
	if	( this->mismatchIsMissingToken(is, follow))
	{
		// We can fake the missing token and proceed
		//
		new ANTLR_Exception<ImplTraits, MISSING_TOKEN_EXCEPTION, StreamType>(this, "");
		matchedSymbol = this->getMissingSymbol( is, m_state->get_exception(), ttype, follow);
		m_state->get_exception()->set_token( matchedSymbol );
		m_state->get_exception()->set_expecting(ttype);

		// Print out the error after we insert so that ANTLRWorks sees the
		// token in the exception.
		//
		this->reportError();

		m_state->set_error(false);	// Exception is not outstanding any more

		return	matchedSymbol;
	}

	// Create an exception if we need one
	//
	new ANTLR_Exception<ImplTraits, RECOGNITION_EXCEPTION, StreamType>(this, "");

	// Neither deleting nor inserting tokens allows recovery
	// must just report the exception.
	//
	m_state->set_error(true);
	return NULL;
}

template< class ImplTraits, class StreamType >
const typename BaseRecognizer<ImplTraits, StreamType>::UnitType* 
BaseRecognizer<ImplTraits, StreamType>::recoverFromMismatchedSet(BitsetListType*	follow)
{
	SuperType* super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_parser_istream();
	const UnitType* matchedSymbol;

	if	(this->mismatchIsMissingToken(is, follow) == true)
	{
		// We can fake the missing token and proceed
		//
		new ANTLR_Exception<ImplTraits, MISSING_TOKEN_EXCEPTION, StreamType>(this);
		matchedSymbol = this->getMissingSymbol(is, m_state->get_exception(), follow);
		m_state->get_exception()->set_token(matchedSymbol);

		// Print out the error after we insert so that ANTLRWorks sees the
		// token in the exception.
		//
		this->reportError();

		m_state->set_error(false);	// Exception is not outstanding any more

		return	matchedSymbol;
	}

    // TODO - Single token deletion like in recoverFromMismatchedToken()
    //
    m_state->set_error(true);
	m_state->set_failed(true);
	return NULL;
}

template< class ImplTraits, class StreamType >
bool  BaseRecognizer<ImplTraits, StreamType>::recoverFromMismatchedElement(BitsetListType*	followBits)
{
	SuperType* super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_parser_istream();

	BitsetType* follow	= followBits->load();
	BitsetType*   viableToksFollowingRule;

    if	(follow == NULL)
    {
		/* The follow set is NULL, which means we don't know what can come
		 * next, so we "hit and hope" by just signifying that we cannot
		 * recover, which will just cause the next token to be consumed,
		 * which might dig us out.
		 */
		return	false;
    }

    /* We have a bitmap for the follow set, hence we can compute
     * what can follow this grammar element reference.
     */
    if	(follow->isMember( ImplTraits::CommonTokenType::EOR_TOKEN_TYPE) == true)
    {
		/* First we need to know which of the available tokens are viable
		 * to follow this reference.
		 */
		viableToksFollowingRule	= this->computeCSRuleFollow();

		/* Remove the EOR token, which we do not wish to compute with
		 */
		follow->remove( ImplTraits::CommonTokenType::EOR_TOKEN_TYPE);
		delete viableToksFollowingRule;
		/* We now have the computed set of what can follow the current token
		 */
    }

    /* We can now see if the current token works with the set of tokens
     * that could follow the current grammar reference. If it looks like it
     * is consistent, then we can "insert" that token by not throwing
     * an exception and assuming that we saw it.
     */
    if	( follow->isMember(is->_LA(1)) == true)
    {
		/* report the error, but don't cause any rules to abort and stuff
		 */
		this->reportError();
		if	(follow != NULL)
		{
			delete follow;
		}
		m_state->set_error(false);
		m_state->set_failed(false);
		return true;	/* Success in recovery	*/
    }

    if	(follow != NULL)
    {
		delete follow;
    }

    /* We could not find anything viable to do, so this is going to
     * cause an exception.
     */
    return  false;
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::consumeUntil(ANTLR_UINT32   tokenType)
{
	SuperType* super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_parser_istream();

	// What do have at the moment?
    //
    ANTLR_UINT32 ttype	= is->_LA(1);

    // Start eating tokens until we get to the one we want.
    //
    while   (ttype != ImplTraits::CommonTokenType::TOKEN_EOF && ttype != tokenType)
    {
		is->consume();
		ttype	= is->_LA(1);
    }
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::consumeUntilSet(BitsetType*	set)
{
    ANTLR_UINT32	    ttype;
	SuperType* super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_parser_istream();

    // What do have at the moment?
    //
    ttype	= is->_LA(1);

    // Start eating tokens until we get to one we want.
    //
    while   (ttype != ImplTraits::CommonTokenType::TOKEN_EOF && set->isMember(ttype) == false)
    {
		is->consume();
		ttype	= is->_LA(1);
    }

}

template< class ImplTraits, class StreamType >
ANTLR_MARKER	BaseRecognizer<ImplTraits, StreamType>::getRuleMemoization( ANTLR_INTKEY	ruleIndex, ANTLR_MARKER	ruleParseStart)
{
	/* The rule memos are an ANTLR3_LIST of ANTLR3_LIST.
     */
	typedef IntTrie<ImplTraits, ANTLR_MARKER> RuleListType;
	typedef TrieEntry<ImplTraits, RuleListType*> EntryType;
	typedef TrieEntry<ImplTraits, ANTLR_MARKER> SubEntryType;
    ANTLR_MARKER	stopIndex;
    EntryType*	entry;

    /* See if we have a list in the ruleMemos for this rule, and if not, then create one
     * as we will need it eventually if we are being asked for the memo here.
     */
    entry	= m_state->get_ruleMemo()->get(ruleIndex);

    if	(entry == NULL)
    {
		/* Did not find it, so create a new one for it, with a bit depth based on the
		 * size of the input stream. We need the bit depth to incorporate the number if
		 * bits required to represent the largest possible stop index in the input, which is the
		 * last character. An int stream is free to return the largest 64 bit offset if it has
		 * no idea of the size, but you should remember that this will cause the leftmost
		 * bit match algorithm to run to 63 bits, which will be the whole time spent in the trie ;-)
		 */
		m_state->get_ruleMemo()->add( ruleIndex, new RuleListType(63) );

		/* We cannot have a stopIndex in a trie we have just created of course
		 */
		return	MEMO_RULE_UNKNOWN;
    }

    RuleListType* ruleList	= entry->get_data();

    /* See if there is a stop index associated with the supplied start index.
     */
    stopIndex	= 0;

    SubEntryType* sub_entry = ruleList->get(ruleParseStart);
    if (sub_entry != NULL)
    {
		stopIndex = sub_entry->get_data();
    }

    if	(stopIndex == 0)
    {
		return MEMO_RULE_UNKNOWN;
    }

    return  stopIndex;
}

template< class ImplTraits, class StreamType >
bool	BaseRecognizer<ImplTraits, StreamType>::alreadyParsedRule(ANTLR_MARKER	ruleIndex)
{
	SuperType* super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_istream();

    /* See if we have a memo marker for this.
     */
    ANTLR_MARKER stopIndex	    = this->getRuleMemoization( ruleIndex, is->index() );

    if	(stopIndex  == MEMO_RULE_UNKNOWN)
    {
		return false;
    }

    if	(stopIndex == MEMO_RULE_FAILED)
    {
		m_state->set_failed(true);
    }
    else
    {
		is->seek(stopIndex+1);
    }

    /* If here then the rule was executed for this input already
     */
    return  true;
}

template< class ImplTraits, class StreamType >
void	BaseRecognizer<ImplTraits, StreamType>::memoize(ANTLR_MARKER ruleIndex, ANTLR_MARKER ruleParseStart)
{
   /* The rule memos are an ANTLR3_LIST of ANTLR3_LIST.
    */
	typedef IntTrie<ImplTraits, ANTLR_MARKER> RuleListType;
	typedef TrieEntry<ImplTraits, RuleListType*> EntryType;
    EntryType*	    entry;
    ANTLR_MARKER	    stopIndex;
	SuperType* super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_istream();

    stopIndex	= (m_state->get_failed() == true) ? MEMO_RULE_FAILED : is->index() - 1;

    entry	= m_state->get_ruleMemo()->get(ruleIndex);

    if	(entry != NULL)
    {
		RuleListType*	ruleList = entry->get_data();

		/* If we don't already have this entry, append it. The memoize trie does not
		 * accept duplicates so it won't add it if already there and we just ignore the
		 * return code as we don't care if it is there already.
		 */
		ruleList->add(ruleParseStart, stopIndex);
    }
}

template< class ImplTraits, class StreamType >
const typename BaseRecognizer<ImplTraits, StreamType>::UnitType*
BaseRecognizer<ImplTraits, StreamType>::getCurrentInputSymbol( IntStreamType* istream )
{
	return this->getCurrentInputSymbol( istream, ClassForwarder<SuperType>() );
}

template< class ImplTraits, class StreamType >
const typename BaseRecognizer<ImplTraits, StreamType>::UnitType*
BaseRecognizer<ImplTraits, StreamType>::getCurrentInputSymbol(IntStreamType* istream, ClassForwarder<LexerType>)
{
	return NULL;
}

template< class ImplTraits, class StreamType >
const typename BaseRecognizer<ImplTraits, StreamType>::UnitType*
BaseRecognizer<ImplTraits, StreamType>::getCurrentInputSymbol(IntStreamType* istream, ClassForwarder<ParserType>)
{
	typedef typename ImplTraits::TokenStreamType TokenStreamType;
	TokenStreamType* token_stream = static_cast<TokenStreamType*>(istream);
	return token_stream->_LT(1);
}

template< class ImplTraits, class StreamType >
const typename BaseRecognizer<ImplTraits, StreamType>::UnitType*
BaseRecognizer<ImplTraits, StreamType>::getCurrentInputSymbol(IntStreamType* istream, ClassForwarder<TreeParserType>)
{
	typedef typename ImplTraits::TreeNodeStreamType TreeNodeStreamType;
	TreeNodeStreamType*	ctns = static_cast<TreeNodeStreamType*>(istream);
	return ctns->_LT(1);
}


template< class ImplTraits, class StreamType >
typename BaseRecognizer<ImplTraits, StreamType>::UnitType*	BaseRecognizer<ImplTraits, StreamType>::getMissingSymbol( IntStreamType* istream,
										  ExceptionBaseType*		e,
										  ANTLR_UINT32			expectedTokenType,
										  BitsetListType*	follow)
{
	return this->get_super()->getMissingSymbol( istream, e, expectedTokenType, follow );
}


template< class ImplTraits, class StreamType >
	template<typename Predicate>
bool  BaseRecognizer<ImplTraits, StreamType>::synpred(ClassForwarder<Predicate> pred)
{
	ANTLR_MARKER   start;
    SuperType* super = static_cast<SuperType*>(this);
	IntStreamType* is = super->get_istream();

    /* Begin backtracking so we can get back to where we started after trying out
     * the syntactic predicate.
     */
    start   = is->mark();
    m_state->inc_backtracking();

    /* Try the syntactical predicate
     */
    this->get_super()->synpred( pred );

    /* Reset
     */
    is->rewind(start);
    m_state->dec_backtracking();

    if	( m_state->get_failed() == true)
    {
		/* Predicate failed
		 */
		m_state->set_failed(false);
		return	false;
    }
    else
    {
		/* Predicate was successful
		 */
		m_state->set_failed(false);
		return	true;
    }
}

template< class ImplTraits, class StreamType >
void BaseRecognizer<ImplTraits, StreamType>::exConstruct()
{
	this->get_super()->exConstruct();
}

template< class ImplTraits, class StreamType >
void  BaseRecognizer<ImplTraits, StreamType>::reset()
{
	this->reset( ClassForwarder<SuperType>() );
}

template< class ImplTraits, class StreamType >
template< typename CompType >
void  BaseRecognizer<ImplTraits, StreamType>::reset( ClassForwarder<CompType> )
{
	typedef typename RecognizerSharedStateType::RuleMemoType RuleMemoType;
	 m_state->get_following().clear();

	// Reset the state flags
	//
	m_state->set_errorRecovery(false);
	m_state->set_lastErrorIndex(-1);
	m_state->set_failed(false);
	m_state->set_errorCount(0);
	m_state->set_backtracking(0);

	if	(m_state->get_ruleMemo() != NULL)
	{
		delete m_state->get_ruleMemo();
		m_state->set_ruleMemo( new RuleMemoType(15) );	/* 16 bit depth is enough for 32768 rules! */
	}
}

template< class ImplTraits, class StreamType >
void  BaseRecognizer<ImplTraits, StreamType>::reset( ClassForwarder<LexerType> )
{
	m_state->set_token_present( false );
    m_state->set_type( ImplTraits::CommonTokenType::TOKEN_INVALID );
    m_state->set_channel( TOKEN_DEFAULT_CHANNEL );
    m_state->set_tokenStartCharIndex( -1 );
    m_state->set_tokenStartCharPositionInLine(-1);
    m_state->set_tokenStartLine( -1 );
    m_state->set_text("");
}

template< class ImplTraits, class StreamType >
BaseRecognizer<ImplTraits, StreamType>::~BaseRecognizer()
{
	// Did we have a state allocated?
	//
	if	(m_state != NULL)
	{
		// Free any rule memoization we set up
		//
		if	(m_state->get_ruleMemo() != NULL)
		{
			delete m_state->get_ruleMemo();
			m_state->set_ruleMemo(NULL);
		}


		// Free any exception space we have left around
		//
		ExceptionBaseType* thisE = m_state->get_exception();
		if	(thisE != NULL)
		{
			delete thisE;
		}

		// Free the shared state memory
		//
		delete m_state;
	}

	// Free the actual recognizer space
	//
}



ANTLR_END_NAMESPACE()
