antlr/antlr4 · error · IllegalArgumentException

can't create parser to match incoming

Error message

can't create parser to match incoming {parserClass}

What it means

deriveTempParserInterpreter reflects on the incoming parser's class to find a (Grammar, ATN, TokenStream) constructor for subclasses of ParserInterpreter. If the subclass lacks that exact constructor (or construction fails), the reflective exception is wrapped in IllegalArgumentException naming the offending parser class.

Solutions

  1. Add a public constructor with signature (Grammar, ATN, TokenStream) to your ParserInterpreter subclass that calls super(...)
  2. Alternatively pass a plain generated parser or base ParserInterpreter, which takes the generated-parser branch and avoids reflection

Example fix

// before
class MyParserInterpreter extends ParserInterpreter {
    MyParserInterpreter(Grammar g, ATN atn, TokenStream ts, ExtraConfig cfg) { super(g, atn, ts); }
}

// after
class MyParserInterpreter extends ParserInterpreter {
    public MyParserInterpreter(Grammar g, ATN atn, TokenStream ts) { super(g, atn, ts); }
    MyParserInterpreter(Grammar g, ATN atn, TokenStream ts, ExtraConfig cfg) { this(g, atn, ts); }
}
Defensive patterns

Strategy: validation

Validate before calling

Constructor<?> ctor = parserClass.getConstructor(Grammar.class, ATN.class, TokenStream.class); // throws NoSuchMethodException if missing

Type guard

static boolean hasInterpreterCtor(Class<? extends ParserInterpreter> c) {
    try { c.getConstructor(Grammar.class, ATN.class, TokenStream.class); return true; }
    catch (NoSuchMethodException e) { return false; }
}

Try / catch

try { deriveTempParserInterpreter(g, parser, tokens); } catch (IllegalArgumentException e) { /* add (Grammar,ATN,TokenStream) ctor to subclass or pass base ParserInterpreter */ }

Prevention

When it happens

Trigger: Passing a custom ParserInterpreter subclass into deriveTempParserInterpreter (directly or via GrammarParserInterpreter.parseFromStartRule / profiling paths) when the subclass does not declare a public ParserInterpreter(Grammar, ATN, TokenStream) constructor.

Common situations: User-defined ParserInterpreter subclasses for instrumentation or error recovery that add constructors but forget the (Grammar, ATN, TokenStream) one, or make it non-public.

Related errors


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

Appendix: source

Thrown at tool/src/org/antlr/v4/tool/GrammarParserInterpreter.java:401

		return trees;
	}

	/** Derive a new parser from an old one that has knowledge of the grammar.
	 *  The Grammar object is used to correctly compute outer alternative
	 *  numbers for parse tree nodes. A parser of the same type is created
	 *  for subclasses of {@link ParserInterpreter}.
	 */
	public static ParserInterpreter deriveTempParserInterpreter(Grammar g, Parser originalParser, TokenStream tokens) {
		ParserInterpreter parser;
		if (originalParser instanceof ParserInterpreter) {
			Class<? extends ParserInterpreter> c = originalParser.getClass().asSubclass(ParserInterpreter.class);
			try {
				Constructor<? extends ParserInterpreter> ctor = c.getConstructor(Grammar.class, ATN.class, TokenStream.class);
				parser = ctor.newInstance(g, originalParser.getATN(), originalParser.getTokenStream());
			}
			catch (Exception e) {
				throw new IllegalArgumentException("can't create parser to match incoming "+originalParser.getClass().getSimpleName(), e);
			}
		}
		else { // must've been a generated parser
//			IntegerList serialized = ATNSerializer.getSerialized(originalParser.getATN(), g.getLanguage());
//			ATN deserialized = new ATNDeserializer().deserialize(serialized.toArray());
			parser = new ParserInterpreter(originalParser.getGrammarFileName(),
										   originalParser.getVocabulary(),
										   Arrays.asList(originalParser.getRuleNames()),
					                       originalParser.getATN(),
										   tokens);
		}

		parser.setInputStream(tokens);

		// Make sure that we don't get any error messages from using this temporary parser
		parser.setErrorHandler(new BailErrorStrategy());
		parser.removeErrorListeners();
		parser.removeParseListeners();

View on GitHub (pinned to 7d5770395b)