antlr/antlr4 · error · UnsupportedOperationException

The current recognizer does not provide a list of rule names

Error message

The current recognizer does not provide a list of rule names.

What it means

Thrown by Recognizer.getRuleIndexMap() when getRuleNames() returns null, i.e. the recognizer cannot supply the grammar's rule names. The map is required by XPath compilation and tree pattern matching, which resolve rule names to the integer indexes used in parse trees. Only generated recognizers (or interpreters constructed with a rule-name array) can provide it.

Source

Thrown at runtime/Java/src/org/antlr/v4/runtime/Recognizer.java:101

				result.put("EOF", Token.EOF);
				result = Collections.unmodifiableMap(result);
				tokenTypeMapCache.put(vocabulary, result);
			}

			return result;
		}
	}

	/**
	 * Get a map from rule names to rule indexes.
	 *
	 * <p>Used for XPath and tree pattern compilation.</p>
	 */
	public Map<String, Integer> getRuleIndexMap() {
		String[] ruleNames = getRuleNames();
		if (ruleNames == null) {
			throw new UnsupportedOperationException("The current recognizer does not provide a list of rule names.");
		}

		synchronized (ruleIndexMapCache) {
			Map<String, Integer> result = ruleIndexMapCache.get(ruleNames);
			if (result == null) {
				result = Collections.unmodifiableMap(Utils.toMap(ruleNames));
				ruleIndexMapCache.put(ruleNames, result);
			}

			return result;
		}
	}

	public int getTokenType(String tokenName) {
		Integer ttype = getTokenTypeMap().get(tokenName);
		if ( ttype!=null ) return ttype;
		return Token.INVALID_TYPE;
	}

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Pass a generated parser (e.g. MyParser) which implements getRuleNames() instead of an interpreter or base Recognizer
  2. When using ParserInterpreter, construct it from a grammar (Grammar g = ...; new ParserInterpreter(g, atn)) so rule names are available, rather than from a bare ATN
  3. If you subclass Recognizer yourself, override getRuleNames() to return the grammar's rule-name array

Example fix

// before
Recognizer rec = new LexerInterpreter("T", null, null, "T", atn); // ruleNames == null
XPath xpath = XPath.compile(path, rec); // throws

// after
Grammar g = loadGrammar("T.g4");
ParserInterpreter rec = g.newParserInterpreter(atnDeserialized);
XPath xpath = XPath.compile(path, rec);
Defensive patterns

Strategy: validation

Validate before calling

if (recognizer.getRuleNames() == null) {
    throw new IllegalStateException(
        "Recognizer provides no rule names; use a generated parser or an interpreter built from a Grammar");
}
Map<String, Integer> map = recognizer.getRuleIndexMap();

Type guard

static boolean hasRuleNames(Recognizer<?, ?> r) {
    return r != null && r.getRuleNames() != null;
}

Try / catch

try { recognizer.getRuleIndexMap(); } catch (UnsupportedOperationException e) { /* fall back to name-based tree walking without rule indexes */ }

Prevention

When it happens

Trigger: Calling XPath.compile(path, recognizer) or new TreePatternMatcher(parser) on a recognizer whose getRuleNames() returns null; using a bare Recognizer subclass or an interpreter built without rule names; calling parser.getRuleIndexMap() directly on such a recognizer.

Common situations: Running tree pattern matching or XPath queries against a ParserInterpreter/LexerInterpreter constructed from only a grammar-name/ATN; hand-rolled Recognizer subclasses used for testing; tooling that assumes every recognizer is generated code.

Related errors


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