{"record":{"id":"7285ccd02e3d7494","repo":"oracle/graal","slug":"out-of-tokens-looking-for-s","errorCode":null,"errorMessage":"Out of tokens looking for %s","messagePattern":"Out of tokens looking for (.+?)","errorType":"validation","errorClass":"RuleParseError","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/core/match/processor/MatchProcessor.java","lineNumber":147,"sourceCode":"\n            matchDescriptor = parseExpression();\n            if (!done()) {\n                throw new RuleParseError(\"didn't consume all tokens\");\n            }\n            capturedNames.add(0, \"root\");\n            capturedTypes.add(0, matchDescriptor.nodeType);\n        }\n\n        String next() {\n            return tokens[current++];\n        }\n\n        String peek(String name) {\n            if (current >= tokens.length) {\n                if (name == null) {\n                    throw new RuleParseError(\"Out of tokens\");\n                }\n                throw new RuleParseError(\"Out of tokens looking for %s\", name);\n            }\n            return tokens[current];\n        }\n\n        boolean done() {\n            return current == tokens.length;\n        }\n\n        private MatchDescriptor parseExpression() {\n            if (peek(\"(\").equals(\"(\")) {\n                next();\n                MatchDescriptor descriptor = parseType(true);\n                for (int n = 0; n < descriptor.nodeType.inputs.size(); n++) {\n                    if (peek(\"(\").equals(\"(\")) {\n                        descriptor.inputs[n] = parseExpression();\n                    } else {\n                        descriptor.inputs[n] = parseType(false);\n                    }","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/core/match/processor/MatchProcessor.java#L129-L165","documentation":"Thrown by RuleParser.peek(name) when tokens run out while the parser was specifically expecting something (a node type, a name, ')', etc.). Unlike the plain 'Out of tokens' variant, it names what was being looked for, which pinpoints the missing element of the match pattern.","triggerScenarios":"Rules such as \"Add(x, \" (looking for ')' or a node type/name), \"Add(x = \" (looking for a captured name after '='), or any construct left half-finished. Every peek(String) call site passes its expectation, e.g. peek(\"node type or name\"), peek(\")\"), peek(\"=\").","commonSituations":"Interrupted edits to @MatchRule strings; renaming nodes and dropping a token; copy-paste that loses the tail of a long pattern.","solutions":["Supply the token named in the message — usually a closing ')' or the node type/name it says it was looking for.","Re-balance parentheses by counting opens/closes in the rule string.","Use the message's 'looking for %s' field literally: it tells you the exact grammar element to append."],"exampleFix":"// before\n@MatchRule(\"Add(x = \")\n\n// after\n@MatchRule(\"Add(x = value, y)\")","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"Compile-time error only. Parse the 'looking for %s' field from the javac diagnostic in developer tooling to auto-suggest the missing token.","preventionTips":["Read the 'looking for' hint: it names the exact missing grammar element (usually ')').","Count '(' vs ')' in every edited rule.","Prefer short rules; use composition via multiple methods over giant patterns."],"tags":["graalvm","match-rules","annotation-processing","compile-time"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}