//in @parser::includes
typedef struct {
#ifdef __cplusplus
	String*			message;					// error message
#else
	void*			message;
#endif
	int				start;						// starting index of erroneous token
	int				stop;						// ending index of erroneous token
	ANTLR3_BOOLEAN	occurred;					// TRUE if error occurred
} Error_State;

// in my .cpp file
extern "C"
void display_syntax_error(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_UINT8 *token_names)	// override displayRecognitionError to capture errors in strings
{
	pANTLR3_EXCEPTION		ex = recognizer->state->exception;	// pick up exception
	pANTLR3_COMMON_TOKEN	token = reinterpret_cast<pANTLR3_COMMON_TOKEN>(recognizer->state->exception->token);	// and offending token - need start and stop (vs. exception->charPositionInLine)
	pANTLR3_PARSER			base_parser = reinterpret_cast<pANTLR3_PARSER>(recognizer->super);	// the base parser owns the recognizer
	Parser_Type*			parser = reinterpret_cast<Parser_Type*>(base_parser->super);	// but the base parser is owned by our parser (which holds the error variable directly)

	parser->error.occurred = true;				// an error happened

	if (token->start != 0)						// make sure a position was given
	{
		parser->error.start = token->start - parser->input_start;	// save position of token causing error (as an index)
		parser->error.stop = token->stop - parser->input_start;
	}

	switch (ex->type)							// build message based on exception type
	{
		case ANTLR3_RECOGNITION_EXCEPTION:		// found something completely unexpected
		case ANTLR3_NO_VIABLE_ALT_EXCEPTION:	// DFA stuck due to an invalid character in its current state (####most errors end up here!)
			parser->error.message = new String("Syntax error:  Unexpected text");
			break;
		case ANTLR3_MISMATCHED_TOKEN_EXCEPTION:	// expected one thing, got another that is recognized
			parser->error.message = new String("Expected ");
			add_error_token(ex->expecting, token_names, *parser->error.message);
			break;
		case ANTLR3_MISMATCHED_SET_EXCEPTION:	// expected one of a set of characters, but found none of them
			parser->error.message = new String("Unexpected input");
			decode_set(ex->expectingSet, token_names, *parser->error.message);	// add the expected characters
			break;
		case ANTLR3_EARLY_EXIT_EXCEPTION:		// expected a list of things, but exited before we expected to (too few items in list)
			parser->error.message = new String("Missing elements");	//####can we be more specific? - do we know the parent token?
			break;
		case ANTLR3_UNWANTED_TOKEN_EXCEPTION:	// spurious input followed by something we recognize/expect
			parser->error.message = new String("Extraneous character(s), expected ");
			add_error_token(ex->expecting, token_names, *parser->error.message);
			break;
		case ANTLR3_MISSING_TOKEN_EXCEPTION:	// valid if given token included
			parser->error.message = new String("Missing ");
			add_error_token(ex->expecting, token_names, *parser->error.message);
			break;
		case ANTLR3_FAILED_PREDICATE_EXCEPTION:	// semantic error
			parser->error.message = new String("Semantic error: ID not found");	//####we need to look at ex->message, which contains the predicate (and ex->rule contains the rule that failed)
			parser->error.start = token->start;	// (for some reason, parser->input_start is garbage if we get this exception)
			parser->error.stop = token->stop;
			break;
		default:								// ANTLR3_MISMATCHED_TREE_NODE_EXCEPTION, ANTLR3_REWRITE_EARLY_EXCEPTION, which we should never come up in the parser, all fall here
			parser->error.message = new String("Unknown error ");
			*parser->error.message += lexical_cast<String>(ex->type);
			break;
	}
}
