ANTLR_BEGIN_NAMESPACE()

template<class ImplTraits>
Lexer<ImplTraits>::Lexer(ANTLR_UINT32 sizeHint, RecognizerSharedStateType* state)
	:Lexer<ImplTraits>::RecognizerType(sizeHint, state)
	,m_input(NULL)
{
}

template<class ImplTraits>
Lexer<ImplTraits>::Lexer(ANTLR_UINT32 sizeHint, InputStreamType* input, RecognizerSharedStateType* state)
	:Lexer<ImplTraits>::RecognizerType(sizeHint, state)
{
	this->setCharStream(input);
}

template<class ImplTraits>
typename Lexer<ImplTraits>::InputStreamType* Lexer<ImplTraits>::get_input() const
{
	return m_input;
}

template<class ImplTraits>
typename Lexer<ImplTraits>::IntStreamType* Lexer<ImplTraits>::get_istream() const
{
	return m_input;
}

template<class ImplTraits>
typename Lexer<ImplTraits>::RecognizerType* Lexer<ImplTraits>::get_rec()
{
	return this;
}

template<class ImplTraits>
typename Lexer<ImplTraits>::TokenSourceType* Lexer<ImplTraits>::get_tokSource()
{
	return this;
}

template<class ImplTraits>
void Lexer<ImplTraits>::displayRecognitionError( ANTLR_UINT8** , ExceptionBaseType* ex)
{
	StringStreamType	err_stream;

	// See if there is a 'filename' we can use
    //
    if( ex->getName().empty() )
    {
		err_stream << "-unknown source-(";
    }
    else
    {
		err_stream << ex->get_streamName().c_str();
		err_stream << "(";
    }
    err_stream << ex->get_line() << ")";

	err_stream << ": lexer error " <<  ex->getName() << '(' << ex->getType() << ')' << " :\n\t"
		   << ex->get_message() << " at position [" << ex->get_line() << ", "
		   << ex->get_charPositionInLine()+1 << "], ";

	{
		ANTLR_UINT32	width;

		width	= ANTLR_UINT32_CAST(( (ANTLR_UINT8*)(m_input->get_data()) +
									  (m_input->size() )) - (ANTLR_UINT8*)( ex->get_index() ));

		if	(width >= 1)
		{
			if	(isprint(ex->get_c() ))
			{
				err_stream << "near '" << (typename StringType::value_type) ex->get_c() << "' :\n";
			}
			else
			{
				err_stream << "near char(" << std::hex << ex->get_c() << std::dec << ") :\n";
			}
			err_stream << "\t";
			err_stream.width( width > 20 ? 20 : width );
			err_stream << (typename StringType::const_pointer)ex->get_index() << "\n";
		}
		else
		{
			err_stream << "(end of input).\n\t This indicates a poorly specified lexer RULE\n\t or unterminated input element such as: \"STRING[\"]\n";
			err_stream << "\t The lexer was matching from line "
					   << this->get_state()->get_tokenStartLine()
					   << ", offset " << this->get_state()->get_tokenStartCharPositionInLine()
					   << ", which\n\t ";
			width = ANTLR_UINT32_CAST(((ANTLR_UINT8*)(m_input->get_data() )+
										(m_input->size())) -
										(ANTLR_UINT8*)(this->get_state()->get_tokenStartCharIndex() ));

			if	(width >= 1)
			{
				err_stream << "looks like this:\n\t\t";
				err_stream.width( width > 20 ? 20 : width );
				err_stream << (typename StringType::const_pointer)this->get_state()->get_tokenStartCharIndex() << "\n";
			}
			else
			{
				err_stream << "is also the end of the line, so you must check your lexer rules\n";
			}
		}
	}
	ImplTraits::displayRecognitionError( err_stream.str() );
}

template<class ImplTraits>
void Lexer<ImplTraits>::fillExceptionData( ExceptionBaseType* ex )
{
	ex->set_c( m_input->_LA(1) );					/* Current input character			*/
	ex->set_line( m_input->get_line() );						/* Line number comes from stream		*/
	ex->set_charPositionInLine( m_input->get_charPositionInLine() );	    /* Line offset also comes from the stream   */
	ex->set_index( m_input->index() );
	ex->set_streamName( m_input->get_fileName() );
	ex->set_message( "Unexpected character" );
}

template<class ImplTraits>
void	Lexer<ImplTraits>::setCharStream(InputStreamType* input)
{
    /* Install the input interface
     */
    m_input	= input;

    /* Set the current token to nothing
     */
	RecognizerSharedStateType* state = this->get_rec()->get_state();
    state->set_token_present( false );
	state->set_text("");
    state->set_tokenStartCharIndex(-1);

    /* Copy the name of the char stream to the token source
     */
    this->get_tokSource()->set_fileName( input->get_fileName() );
}

template<class ImplTraits>
void	Lexer<ImplTraits>::pushCharStream(InputStreamType* input)
{
	// We have a stack, so we can save the current input stream
	// into it.
	//
	this->get_istream()->mark();
	this->get_rec()->get_state()->get_streams().push(this->get_input());

	// And now we can install this new one
	//
	this->setCharStream(input);
}

template<class ImplTraits>
void	Lexer<ImplTraits>::popCharStream()
{
	InputStreamType* input;

    // If we do not have a stream stack or we are already at the
    // stack bottom, then do nothing.
    //
    typename RecognizerSharedStateType::StreamsType& streams = this->get_rec()->get_state()->get_streams();
    if	( streams.size() > 0)
    {
		// We just leave the current stream to its fate, we do not close
		// it or anything as we do not know what the programmer intended
		// for it. This method can always be overridden of course.
		// So just find out what was currently saved on the stack and use
		// that now, then pop it from the stack.
		//
		input	= streams.top();
		streams.pop();

		// Now install the stream as the current one.
		//
		this->setCharStream(input);
		this->get_istream()->rewindLast();
    }
    return;
}

template<class ImplTraits>
void	Lexer<ImplTraits>::emit(const CommonTokenType* token)
{
	this->get_rec()->get_state()->set_token(token);
}

template<class ImplTraits>
typename Lexer<ImplTraits>::CommonTokenType*	Lexer<ImplTraits>::emit()
{
	/* We could check pointers to token factories and so on, but
    * we are in code that we want to run as fast as possible
    * so we are not checking any errors. So make sure you have installed an input stream before
    * trying to emit a new token.
    */
	RecognizerSharedStateType* state = this->get_rec()->get_state();
	state->set_token_present(true);
    CommonTokenType* token = state->get_token();
	token->set_input( this->get_input() );

    /* Install the supplied information, and some other bits we already know
    * get added automatically, such as the input stream it is associated with
    * (though it can all be overridden of course)
    */
    token->set_type( state->get_type() );
    token->set_channel( state->get_channel() );
    token->set_startIndex( state->get_tokenStartCharIndex() );
    token->set_stopIndex( this->getCharIndex() - 1 );
    token->set_line( state->get_tokenStartLine() );
    token->set_charPositionInLine( state->get_tokenStartCharPositionInLine() );

	token->set_tokText( state->get_text() );
    token->set_lineStart( this->get_input()->get_currentLine() );

    return  token;
}

template<class ImplTraits>
Lexer<ImplTraits>::~Lexer()
{
	// This may have ben a delegate or delegator lexer, in which case the
	// state may already have been freed (and set to NULL therefore)
	// so we ignore the state if we don't have it.
	//
	RecognizerSharedStateType* state = this->get_rec()->get_state();

	if	( state != NULL)
	{
		state->get_streams().clear();
	}
}

template<class ImplTraits>
bool	Lexer<ImplTraits>::matchs(ANTLR_UCHAR* str )
{
	RecognizerSharedStateType* state = this->get_rec()->get_state();
	while   (*str != ANTLR_STRING_TERMINATOR)
	{
		if  ( this->get_istream()->_LA(1) != (*str))
		{
			if	( state->get_backtracking() > 0)
			{
				state->set_failed(true);
				return false;
			}

			this->exConstruct();
			state->set_failed( true );

			/* TODO: Implement exception creation more fully perhaps
			 */
			this->recover();
			return  false;
		}

		/* Matched correctly, do consume it
		 */
		this->get_istream()->consume();
		str++;

	}
	/* Reset any failed indicator
	 */
	state->set_failed( false );
	return  true;
}

template<class ImplTraits>
bool	Lexer<ImplTraits>::matchc(ANTLR_UCHAR c)
{
	if	(this->get_istream()->_LA(1) == c)
	{
		/* Matched correctly, do consume it
		 */
		this->get_istream()->consume();

		/* Reset any failed indicator
		 */
		this->get_rec()->get_state()->set_failed( false );

		return	true;
	}

	/* Failed to match, exception and recovery time.
	 */
	if(this->get_rec()->get_state()->get_backtracking() > 0)
	{
		this->get_rec()->get_state()->set_failed( true );
		return	false;
	}

	this->exConstruct();

	/* TODO: Implement exception creation more fully perhaps
	 */
	this->recover();

	return  false;
}

template<class ImplTraits>
bool	Lexer<ImplTraits>::matchRange(ANTLR_UCHAR low, ANTLR_UCHAR high)
{
    ANTLR_UCHAR    c;

    /* What is in the stream at the moment?
     */
    c	= this->get_istream()->_LA(1);
    if	( c >= low && c <= high)
    {
		/* Matched correctly, consume it
		 */
		this->get_istream()->consume();

		/* Reset any failed indicator
		 */
		this->get_rec()->get_state()->set_failed( false );

		return	true;
    }

    /* Failed to match, execption and recovery time.
     */

    if	(this->get_rec()->get_state()->get_backtracking() > 0)
    {
		this->get_rec()->get_state()->set_failed( true );
		return	false;
    }

    this->exConstruct();

    /* TODO: Implement exception creation more fully
     */
    this->recover();

    return  false;
}

template<class ImplTraits>
void		Lexer<ImplTraits>::matchAny()
{
	this->get_istream()->consume();
}

template<class ImplTraits>
void		Lexer<ImplTraits>::recover()
{
	this->get_istream()->consume();
}

template<class ImplTraits>
ANTLR_UINT32	Lexer<ImplTraits>::getLine()
{
	return  this->get_input()->get_line();
}

template<class ImplTraits>
ANTLR_MARKER	Lexer<ImplTraits>::getCharIndex()
{
	return this->get_istream()->index();
}

template<class ImplTraits>
ANTLR_UINT32	Lexer<ImplTraits>::getCharPositionInLine()
{
	return  this->get_input()->get_charPositionInLine();
}

template<class ImplTraits>
typename Lexer<ImplTraits>::StringType	Lexer<ImplTraits>::getText()
{
	RecognizerSharedStateType* state = this->get_rec()->get_state();
	if ( !state->get_text().empty() )
	{
		return	state->get_text();

	}
	return  this->get_input()->substr( state->get_tokenStartCharIndex(),
									this->getCharIndex() - this->get_input()->get_charByteSize()
							);
}

template<class ImplTraits>
void Lexer<ImplTraits>::exConstruct()
{
	new ANTLR_Exception<ImplTraits, RECOGNITION_EXCEPTION, InputStreamType>( this->get_rec(), "" );
}

template< class ImplTraits>
typename Lexer<ImplTraits>::TokenType*	Lexer<ImplTraits>::getMissingSymbol( IntStreamType*,
										  ExceptionBaseType*,
										  ANTLR_UINT32	, BitsetListType*)
{
	return NULL;
}

template< class ImplTraits>
ANTLR_INLINE const typename Lexer<ImplTraits>::RecognizerType* Lexer<ImplTraits>::get_rec() const
{
	return this;
}

template< class ImplTraits>
ANTLR_INLINE const typename Lexer<ImplTraits>::RecognizerType* Lexer<ImplTraits>::get_recognizer() const
{
	return this->get_rec();
}

template< class ImplTraits>
ANTLR_INLINE typename Lexer<ImplTraits>::RecognizerSharedStateType* Lexer<ImplTraits>::get_lexstate() const
{
	return this->get_rec()->get_state();
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::set_lexstate( RecognizerSharedStateType* lexstate )
{
	this->get_rec()->set_state(lexstate);
}

template< class ImplTraits>
ANTLR_INLINE const typename Lexer<ImplTraits>::TokenSourceType* Lexer<ImplTraits>::get_tokSource() const
{
	return this;
}

template< class ImplTraits>
ANTLR_INLINE typename Lexer<ImplTraits>::CommonTokenType* Lexer<ImplTraits>::get_ltoken() const
{
	return this->get_lexstate()->token();
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::set_ltoken( const CommonTokenType* ltoken )
{
	this->get_lexstate()->set_token( ltoken );
}

template< class ImplTraits>
ANTLR_INLINE bool Lexer<ImplTraits>::hasFailed() const
{
	return this->get_lexstate()->get_failed();
}

template< class ImplTraits>
ANTLR_INLINE ANTLR_INT32 Lexer<ImplTraits>::get_backtracking() const
{
	return this->get_lexstate()->get_backtracking();
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::inc_backtracking()
{
	this->get_lexstate()->inc_backtracking();
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::dec_backtracking()
{
	this->get_lexstate()->dec_backtracking();
}

template< class ImplTraits>
ANTLR_INLINE bool Lexer<ImplTraits>::get_failedflag() const
{
	return this->get_lexstate()->get_failed();
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::set_failedflag( bool failed )
{
	this->get_lexstate()->set_failed(failed);
}

template< class ImplTraits>
ANTLR_INLINE typename Lexer<ImplTraits>::InputStreamType* Lexer<ImplTraits>::get_strstream() const
{
	return this->get_input();
}

template< class ImplTraits>
ANTLR_INLINE ANTLR_MARKER  Lexer<ImplTraits>::index() const
{
	return this->get_istream()->index();
}

template< class ImplTraits>
ANTLR_INLINE void	Lexer<ImplTraits>::seek(ANTLR_MARKER index)
{
	this->get_istream()->seek(index);
}

template< class ImplTraits>
ANTLR_INLINE const typename Lexer<ImplTraits>::CommonTokenType* Lexer<ImplTraits>::EOF_Token() const
{
	const CommonTokenType& eof_token = this->get_tokSource()->get_eofToken();
	return &eof_token;
}

template< class ImplTraits>
ANTLR_INLINE bool Lexer<ImplTraits>::hasException() const
{
	return this->get_lexstate()->get_error();
}

template< class ImplTraits>
ANTLR_INLINE typename Lexer<ImplTraits>::ExceptionBaseType* Lexer<ImplTraits>::get_exception() const
{
	return this->get_lexstate()->get_exception();
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::constructEx()
{
	this->get_rec()->exConstruct();
}

template< class ImplTraits>
ANTLR_INLINE ANTLR_MARKER Lexer<ImplTraits>::mark()
{
	return this->get_istream()->mark();
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::rewind(ANTLR_MARKER marker)
{
	this->get_istream()->rewind(marker);
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::rewindLast()
{
	this->get_istream()->rewindLast();
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::memoize(ANTLR_MARKER	ruleIndex, ANTLR_MARKER	ruleParseStart)
{
	this->get_rec()->memoize( ruleIndex, ruleParseStart );
}

template< class ImplTraits>
ANTLR_INLINE bool Lexer<ImplTraits>::haveParsedRule(ANTLR_MARKER	ruleIndex)
{
	return this->get_rec()->alreadyParsedRule(ruleIndex);
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::setText( const StringType& text )
{
	this->get_lexstate()->set_text(text);
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::skip()
{
	CommonTokenType& skipToken = this->get_tokSource()->get_skipToken();
	this->get_lexstate()->set_token( &skipToken );
}

template< class ImplTraits>
ANTLR_INLINE typename Lexer<ImplTraits>::RuleMemoType* Lexer<ImplTraits>::getRuleMemo() const
{
	return this->get_lexstate()->get_rulememo();
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::setRuleMemo(RuleMemoType* rulememo)
{
	return this->get_lexstate()->set_rulememo(rulememo);
}

template< class ImplTraits>
ANTLR_INLINE typename Lexer<ImplTraits>::DebuggerType* Lexer<ImplTraits>::get_debugger() const
{
	return this->get_rec()->get_debugger();
}

template< class ImplTraits>
ANTLR_INLINE ANTLR_UINT32 Lexer<ImplTraits>::LA(ANTLR_INT32 i)
{
	return this->get_istream()->_LA(i);
}

template< class ImplTraits>
ANTLR_INLINE void Lexer<ImplTraits>::consume()
{
	return this->get_istream()->consume();
}

ANTLR_END_NAMESPACE()