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
- Add a public constructor with signature (Grammar, ATN, TokenStream) to your ParserInterpreter subclass that calls super(...)
- 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
- Give every ParserInterpreter subclass a public (Grammar, ATN, TokenStream) constructor
- Prefer base ParserInterpreter or generated parsers when custom subclasses are not essential
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
- A lexer interpreter can only be created for a lexer or…
- A parser interpreter can only be created for a parser or…
- Unexpected data entry
- ANTLR 4 caught build errors.
- ANTLR ErrorManager panic
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)