{"record":{"id":"3cfc23e52cef26c8","repo":"antlr/antlr4","slug":"cannot-consume-eof","errorCode":null,"errorMessage":"cannot consume EOF","messagePattern":"cannot consume EOF","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"runtime/Java/src/org/antlr/v4/runtime/ANTLRInputStream.java","lineNumber":130,"sourceCode":"   \t\t}\n   \t\tfinally {\n   \t\t\tr.close();\n   \t\t}\n   \t}\n\n\t/** Reset the stream so that it's in the same state it was\n\t *  when the object was created *except* the data array is not\n\t *  touched.\n\t */\n\tpublic void reset() {\n\t\tp = 0;\n\t}\n\n    @Override\n    public void consume() {\n\t\tif (p >= n) {\n\t\t\tassert LA(1) == IntStream.EOF;\n\t\t\tthrow new IllegalStateException(\"cannot consume EOF\");\n\t\t}\n\n\t\t//System.out.println(\"prev p=\"+p+\", c=\"+(char)data[p]);\n        if ( p < n ) {\n            p++;\n\t\t\t//System.out.println(\"p moves to \"+p+\" (c='\"+(char)data[p]+\"')\");\n        }\n    }\n\n    @Override\n    public int LA(int i) {\n\t\tif ( i==0 ) {\n\t\t\treturn 0; // undefined\n\t\t}\n\t\tif ( i<0 ) {\n\t\t\ti++; // e.g., translate LA(-1) to use offset i=0; then data[p+0-1]\n\t\t\tif ( (p+i-1) < 0 ) {\n\t\t\t\treturn IntStream.EOF; // invalid; no char before first char","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Java/src/org/antlr/v4/runtime/ANTLRInputStream.java#L112-L148","documentation":"RuleTagToken represents a rule reference tag (e.g. <expr>) inside a compiled pattern; its constructor requires the rule name because the token's text, and its matching behavior against the ATN's bypass tokens, are derived from that name. A null or empty ruleName would make the token unmatchable and its getText meaningless, so IllegalArgumentException is thrown at construction.","triggerScenarios":"Constructing RuleTagToken(null, type, label) or RuleTagToken(\"\", ...) directly; indirectly hard to reach because ParseTreePatternMatcher validates rule names against the grammar before creating RuleTagToken.","commonSituations":"Extending the pattern-matching API or writing tests that hand-assemble token streams containing rule tags; serialization code that rebuilds tokens from strings and passes an empty name when the source field was absent.","solutions":["Pass the grammar's rule name exactly as declared (e.g. new RuleTagToken(\"expr\", bypassType, null)).","Prefer letting ParseTreePatternMatcher.compile create rule tags for you.","Validate non-empty name at the boundary where tokens are reconstructed from external data."],"exampleFix":"// before\nRuleTagToken t = new RuleTagToken(nameFromJson, bypassType, label); // may be \"\"\n\n// after\nif (nameFromJson == null || nameFromJson.isEmpty()) throw new IllegalArgumentException(\"rule name required\");\nRuleTagToken t = new RuleTagToken(nameFromJson, bypassType, label);","handlingStrategy":"validation","validationCode":"if (ruleName == null || ruleName.isEmpty()) {\n    throw new IllegalArgumentException(\"ruleName required for RuleTagToken\");\n}\nreturn new RuleTagToken(ruleName, bypassTokenType, label);","typeGuard":"boolean isValidRuleName(String n) { return n != null && !n.isEmpty(); }","tryCatchPattern":null,"preventionTips":["Validate rule names at data boundaries (JSON/config) before constructing tokens.","Prefer ParseTreePatternMatcher.compile to create rule tags.","Use grammar rule names verbatim; no renaming at construction time."],"tags":["antlr","java","parse-tree-pattern","null-argument","validation"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}