antlr/antlr4 · error · StartRuleDoesNotConsumeFullPattern

StartRuleDoesNotConsumeFullPattern

Error message

StartRuleDoesNotConsumeFullPattern

What it means

StartRuleDoesNotConsumeFullPattern is raised during ParseTreePatternMatcher.compileTreePattern() when the pattern string still has tokens left after the start rule finishes parsing. Tree patterns must be a complete, valid sentence of the start rule; trailing garbage means the pattern is malformed relative to the grammar.

Source

Thrown at runtime/Python3/src/antlr4/tree/ParseTreePatternMatcher.py:181

        tokenSrc = ListTokenSource(tokenList)
        tokens = CommonTokenStream(tokenSrc)
        from ..ParserInterpreter import ParserInterpreter
        parserInterp = ParserInterpreter(self.parser.grammarFileName, self.parser.tokenNames,
                                self.parser.ruleNames, self.parser.getATNWithBypassAlts(),tokens)
        tree = None
        try:
            parserInterp.setErrorHandler(BailErrorStrategy())
            tree = parserInterp.parse(patternRuleIndex)
        except ParseCancellationException as e:
            raise e.cause
        except RecognitionException as e:
            raise e
        except Exception as e:
            raise CannotInvokeStartRule(e)

        # Make sure tree pattern compilation checks for a complete parse
        if tokens.LA(1)!=Token.EOF:
            raise StartRuleDoesNotConsumeFullPattern()

        from ..tree.ParseTreePattern import ParseTreePattern
        return ParseTreePattern(self, pattern, patternRuleIndex, tree)

    #
    # Recursively walk {@code tree} against {@code patternTree}, filling
    # {@code match.}{@link ParseTreeMatch#labels labels}.
    #
    # @return the first node encountered in {@code tree} which does not match
    # a corresponding node in {@code patternTree}, or {@code null} if the match
    # was successful. The specific node returned depends on the matching
    # algorithm used by the implementation, and may be overridden.
    #
    def matchImpl(self, tree:ParseTree, patternTree:ParseTree, labels:dict):
        if tree is None:
            raise Exception("tree cannot be null")
        if patternTree is None:
            raise Exception("patternTree cannot be null")

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Rewrite the pattern so it is exactly one full sentence of the chosen start rule
  2. Pass the correct patternRuleIndex that actually derives the whole pattern
  3. Test the pattern by feeding the equivalent concrete text to the grammar and confirming it parses to EOF

Example fix

# before: trailing ';' not allowed by 'expr' start rule
pattern = parser.compilePattern('<expr> ;', ruleIndex=exprRuleIndex)

# after
pattern = parser.compilePattern('<expr>', ruleIndex=exprRuleIndex)
Defensive patterns

Strategy: try-catch

Validate before calling

tokens = lexer.tokenize_equivalent(pattern)  # parse pattern text with the grammar first
# confirm a full parse reaches EOF before compiling

Try / catch

try:
    p = matcher.compileTreePattern(pattern, ruleIndex)
except StartRuleDoesNotConsumeFullPattern:
    # report and adjust pattern/rule index
    raise

Prevention

When it happens

Trigger: Calling parser.compilePattern(pattern, ruleIndex) or matcher.compileTreePattern(pattern, patternRuleIndex) with a pattern that does not fully match the start rule, e.g. '<expr> + extra ;' when the start rule 'statement' does not accept the trailing tokens.

Common situations: Pattern written against a different grammar version, a pattern longer than the start rule allows, or forgetting that tags must still fit the rule's structure.

Related errors


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