How can I make the lexer exit upon first lexical error?

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

You need to override the default behavior which tries to recover and keep lexing. There are two approaches depending upon if you care about the lexer throwing a proper RecognitionException or not. If not, just override the nextToken() method as shown in the following example:

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);
				throw new RuntimeException("Bailing out!"); // or throw Error
			}
		}
	}
}

a : 'hi' INT {System.out.println("not printed upon lexical error");} ;

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

Running through ANTLRWorks with input "hi 34" works fine, but input "hi mom" results in the following:

line 1:3 no viable alternative at character 'm'
Exception in thread "main" java.lang.RuntimeException: Bailing out!
	at TLexer.nextToken(TLexer.java:37)
	at org.antlr.runtime.CommonTokenStream.fillBuffer(CommonTokenStream.java:119)
	at org.antlr.runtime.CommonTokenStream.LT(CommonTokenStream.java:238)
	at org.antlr.runtime.CommonTokenStream.LA(CommonTokenStream.java:300)
	at org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:71)
	at TParser.a(TParser.java:77)
	at __Test__.main(__Test__.java:14)

You cannot throw an exception because the interface for TokenStream was designed to not transmit lexical errors through to the parser. What would the parser do with a lexical error? Better to throw an exception that makes the entire system go back to the invoking main method or whatever. Java (without some tricks) does not allow throwing exceptions without altering the method interface so we must use either an Error object or a RuntimeObject, which are considered unchecked. Other targets will not have this problem. just override and get rid of the catch-clause.

The second approach overrides the reportError method and causes it to throw the RecognitionException it is passed. Because this method does not declare that it will throw the checked exception RecognitionException a trick must be used to make this work. This will bail out all the way to the code that invoked the parser (or lexer) and allow that code to deal with the problem.

@lexer::members {
  @Override
  public void reportError(RecognitionException e) {
    Thrower.sneakyThrow(e);
  }

  /**
   * See "Puzzle 43: Exceptionally Unsafe" from Bloch Gafter, <i>Java Puzzlers</i>. Addison Wesley 2005.
   */
  static class Thrower {
    private static Throwable t;
    private Thrower() throws Throwable {
      throw t;
    }
    public static synchronized void sneakyThrow(Throwable t) {
      Thrower.t = t;
      try {
        Thrower.class.newInstance();
      } catch (InstantiationException e) {
        throw new IllegalArgumentException(e);
      } catch (IllegalAccessException e) {
        throw new IllegalArgumentException(e);
      } finally {
        Thrower.t = null; // Avoid memory leak
      }
    }
  }
}

Or, more succinctly

@lexer::members {
  @Override
  public void reportError(RecognitionException e) {
    throw new IllegalArgumentException(e);
  }
}