Manually implementing "include" functionality using ANTLREdit
Please note that this solution is only required with ANTLR 3.0. Newer versions have built in stream stacking support which makes this considerably easier; see 'Implementing "include" functionality using ANTLR'.
ANTLR 3.0 solution
These two posts were made to the antlr-interest mailing list in a thread titled, 'Implementing "include" functionality with C runtime':
- http://www.antlr.org:8080/pipermail/antlr-interest/2007-June/021502.html
 - http://www.antlr.org:8080/pipermail/antlr-interest/2007-June/021503.html
 
Here, Cameron Esfahani of Apple describes how to implement "include" functionality when using the C target.
First, the Java-centric tips on the subject can be found here.
Cameron describes his approach using the C target as:
I’ve hooked into the
nextToken()vector of the lexer’s token source, and I set up a simple stack to save and restore thepLexer->inputANTLR3_INPUT_STREAM.I make sure to call
mark()on the currentANTLR3_INPUT_STREAMso when it gets switched back in by thenextToken()override, I can just callrewindLast()on it.
The code is:
	: 'include' WS? f = STRING {
		ANTLR3_INPUT_STREAM*				Input;
		ANTLR3_UINT8*						FileName;
		int									Length;
		// Extract out the file name from within the quotes.
		Length = strlen( f->getText( f )->chars + 1 );
		FileName = malloc( Length );
		strcpy( FileName, f->getText( f )->chars + 1 );
		FileName[ Length - 1 ] = 0;
		Input = antlr3AsciiFileStreamNew( FileName );
		// Remember where we are in this stream, and save it.
		gLexer->pLexer->input->istream->mark( gLexer->pLexer->input->istream );
		gIncludeStack->push( gIncludeStack, gLexer->pLexer->input, NULL );
		gLexer->pLexer->setCharStream( gLexer->pLexer, Input );
		free( FileName );
		}
ANTLR3_COMMON_TOKEN*
NextToken( ANTLR3_TOKEN_SOURCE* TokenSource )
{
	ANTLR3_COMMON_TOKEN*				Token;
	ANTLR3_INPUT_STREAM*				SavedStream;
	Token = gOriginalNextToken( TokenSource );
	if ( Token == &TokenSource->eofToken )
	{
		// We've reached the end of this file.  Pop anything off the include
		// stack and continue.
		if ( gIncludeStack->size( gIncludeStack ) > 0 )
		{
			SavedStream = gIncludeStack->top;
			gLexer->pLexer->setCharStream( gLexer->pLexer, SavedStream );
			SavedStream->istream->rewindLast( SavedStream->istream );
			Token = gOriginalNextToken( TokenSource );
			gIncludeStack->pop( gIncludeStack );
		}
	}
	if ( ( ( ANTLR3_INT64 ) Token->getStartIndex( Token ) ) < 0 )
	{
		Token = gOriginalNextToken( TokenSource );
	}
	return( Token );
}
Cameron then goes on to clarify:
It looks like I need to switch the input in the token factory as well. I added the following code to switch the token factory input to the new input and things look better
gLexer->pLexer->tokFactory->unTruc.input = SavedStream;