How can I emit an error token upon lexical error?

v3.1 required (but change state to "this" and should be ok in 3.0.1)

Sometimes you want the lexer to emit error tokens to the parser rather than consume the bad input and throw it away. To do this, we make a modification of FAQ entry How can I make the lexer exit upon first lexical error? Just override nextToken to do something different upon exception, which in this case means creating an error token.

grammar T;

@lexer::members {
	public Token nextToken() {
		while (true) {
			state.token = null;
			state.channel = Token.DEFAULT_CHANNEL;
			state.tokenStartCharIndex = input.index();
			state.tokenStartCharPositionInLine = input.getCharPositionInLine();
			state.tokenStartLine = input.getLine();
			state.text = null;
			if ( input.LA(1)==CharStream.EOF ) {
				return Token.EOF_TOKEN;
			}
			try {
				mTokens();
				if ( state.token==null ) {
					emit();
				}
				else if ( state.token==Token.SKIP_TOKEN ) {
					continue;
				}
				return state.token;
			}
			catch (RecognitionException re) {
				reportError(re);
				if ( re instanceof NoViableAltException ) { recover(re); }
                                // create token that holds mismatched char
				Token t = new CommonToken(input, Token.INVALID_TOKEN_TYPE,
				                          Token.DEFAULT_CHANNEL,
				                          state.tokenStartCharIndex,
				                          getCharIndex()-1);
				t.setLine(state.tokenStartLine);
				t.setCharPositionInLine(state.tokenStartCharPositionInLine);
				emit(t);
				return state.token;
			}
		}
	}
}

a
@init {
    for (Object t : ((CommonTokenStream)input).getTokens()) { // dump token stream from lexer
        System.out.println(t);
    }
}
  : 'hi' INT {System.out.println("not printed upon lexical error");}
  ;

INT : '0'..'9'+ ;
WS : (' '|'\n')+ {skip();} ;

Input "hi mom\n" gives:

line 1:3 no viable alternative at character 'm'
line 1:4 no viable alternative at character 'o'
line 1:5 no viable alternative at character 'm'
[@0,0:1='hi',<6>,1:0]
[@1,3:3='m',<0>,1:3]
[@2,4:4='o',<0>,1:4]
[@3,5:5='m',<0>,1:5]
line 1:3 mismatched input 'm' expecting INT

Input "ho 34\n" gives:

line 1:1 mismatched character 'o' expecting 'i'
[@0,0:1='ho',<0>,1:0]
[@1,3:4='34',<4>,1:3]
line 1:0 mismatched input 'ho ' expecting 'hi'

You can substitute Token.HIDDEN_CHANNEL for Token.DEFAULT_CHANNEL to make the parser ignore the invalid tokens.