oracle/graal · error · RuleParseError
Extra tokens following match pattern: ${peek(null)}
Error message
Extra tokens following match pattern: ${peek(null)} What it means
Thrown by RuleParser.parseExpression when the first token of what should be a parenthesized expression is not '('. After the two arity checks, a well-formed expression must begin with '('; reaching the final throw means the caller asked for an expression where a bare token (a node type or name outside parentheses) appeared.
Source
Thrown at compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/core/match/processor/MatchProcessor.java:178
for (int n = 0; n < descriptor.nodeType.inputs.size(); n++) {
if (peek("(").equals("(")) {
descriptor.inputs[n] = parseExpression();
} else {
descriptor.inputs[n] = parseType(false);
}
}
for (int n = 0; n < descriptor.nodeType.inputs.size(); n++) {
if (descriptor.inputs[n] == null) {
throw new RuleParseError("not enough inputs for " + descriptor.name);
}
}
if (peek(")").equals(")")) {
next();
return descriptor;
}
throw new RuleParseError("Too many arguments to " + descriptor.nodeType.nodeClass);
}
throw new RuleParseError("Extra tokens following match pattern: " + peek(null));
}
private MatchDescriptor parseType(boolean forExpression) {
TypeDescriptor type = null;
String name = null;
if (Character.isUpperCase(peek("node type or name").charAt(0))) {
String token = next();
type = knownTypes.get(token);
if (type == null) {
throw new RuleParseError("Unknown node type: " + token);
}
if (peek("=").equals("=")) {
next();
name = next();
}
originatingElements.addAll(type.originatingElements);
} else if (Character.isLowerCase(peek("name").charAt(0))) {
name = next();View on GitHub (pinned to a66e9ccd1d)
Solutions
- Wrap the node and its inputs in parentheses: 'NodeType(input, ...)'.
- Check the token quoted after 'Extra tokens following match pattern:' — it is the one that must be inside a parenthesized expression.
- Model new rules on existing ones in the same package for correct shape.
Example fix
// before
@MatchRule("Add x y")
// after
@MatchRule("Add(x, y)") Defensive patterns
Strategy: try-catch
Try / catch
Compile-time error from the annotation processor; no runtime catch exists. CI should fail on any RuleParseError diagnostic.
Prevention
- Remember the grammar is S-expressions: every expression is '( Type inputs... )'.
- Wrap node applications in parentheses even for single-input nodes.
- Copy the shape of existing rules rather than inventing infix syntax.
When it happens
Trigger: A @MatchRule value that starts with or contains a bare type/name where the grammar requires a nested parenthesized expression, e.g. "Add x y" or using parseExpression on a top-level bare identifier. The message shows the offending token via peek(null).
Common situations: Omitting parentheses entirely when composing a rule; treating the DSL as infix rather than S-expressions; editing a rule down to a single node without wrapping context.
Related errors
- Unexpected token "%s" when looking for name or node type
- Unexpected tokens :${rule.substring(m.end(), m.regionEnd())}
- didn't consume all tokens
- Out of tokens
- Out of tokens looking for %s
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/59650c28bf7aae0c.
Report an issue: GitHub.