antlr/antlr4 · error · IllegalStateException

A parser interpreter can only be created for a parser or com

Error message

A parser interpreter can only be created for a parser or combined grammar.

What it means

Grammar.createGrammarParserInterpreter(TokenStream) constructs a GrammarParserInterpreter (rule-name-aware subclass) but a lexer grammar has no parser rules or parser ATN, so it throws IllegalStateException immediately when this.isLexer().

Source

Thrown at tool/src/org/antlr/v4/tool/Grammar.java:1347

		allChannels.addAll(channelValueToNameList);

		// must run ATN through serializer to set some state flags
		IntegerList serialized = ATNSerializer.getSerialized(atn);
		ATN deserializedATN = new ATNDeserializer().deserialize(serialized.toArray());
		return new LexerInterpreter(
				fileName,
				getVocabulary(),
				Arrays.asList(getRuleNames()),
				allChannels,
				((LexerGrammar)this).modes.keySet(),
				deserializedATN,
				input);
	}

	/** @since 4.5.1 */
	public GrammarParserInterpreter createGrammarParserInterpreter(TokenStream tokenStream) {
		if (this.isLexer()) {
			throw new IllegalStateException("A parser interpreter can only be created for a parser or combined grammar.");
		}
		// must run ATN through serializer to set some state flags
		IntegerList serialized = ATNSerializer.getSerialized(atn);
		ATN deserializedATN = new ATNDeserializer().deserialize(serialized.toArray());

		return new GrammarParserInterpreter(this, deserializedATN, tokenStream);
	}

	public ParserInterpreter createParserInterpreter(TokenStream tokenStream) {
		if (this.isLexer()) {
			throw new IllegalStateException("A parser interpreter can only be created for a parser or combined grammar.");
		}

		// must run ATN through serializer to set some state flags
		IntegerList serialized = ATNSerializer.getSerialized(atn);
		ATN deserializedATN = new ATNDeserializer().deserialize(serialized.toArray());

		return new ParserInterpreter(fileName, getVocabulary(), Arrays.asList(getRuleNames()), deserializedATN, tokenStream);

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Guard with if (g.isLexer()) skip/return before calling the method
  2. Load the parser/combined grammar when you need a parser interpreter

Example fix

// before
GrammarParserInterpreter it = g.createGrammarParserInterpreter(tokens);

// after
if (g.isLexer()) throw new IllegalStateException("not a parser grammar");
GrammarParserInterpreter it = g.createGrammarParserInterpreter(tokens);
Defensive patterns

Strategy: type-guard

Validate before calling

boolean canParse = !g.isLexer();

Type guard

static boolean supportsParserInterpreter(Grammar g) { return !g.isLexer(); }

Try / catch

try { g.createGrammarParserInterpreter(tokens); } catch (IllegalStateException e) { /* skip: grammar is lexer-only */ }

Prevention

When it happens

Trigger: Calling createGrammarParserInterpreter(tokens) on a Grammar loaded from a lexer-only grammar file (grammar type LEXER).

Common situations: Generic grammar-processing tooling that calls the interpreter factory on every loaded grammar without checking its type.

Related errors


AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14). Data as JSON: /api/errors/c6ba311e103e932e. Report an issue: GitHub.