antlr/antlr4 · error · Exception
Empty Stack
Error message
Empty Stack
What it means
Lexer.popMode() raises Exception('Empty Stack') when the lexer mode stack is empty — a popMode action (or 'mode stack' manipulation in a member/embedded action) executed while still in the default mode. The mode stack is only populated by pushMode; pops must be balanced with pushes within the token stream.
Source
Thrown at runtime/Python3/src/antlr4/Lexer.py:183
#/
def skip(self):
self._type = self.SKIP
def more(self):
self._type = self.MORE
def mode(self, m:int):
self._mode = m
def pushMode(self, m:int):
if self._interp.debug:
print("pushMode " + str(m), file=self._output)
self._modeStack.append(self._mode)
self.mode(m)
def popMode(self):
if len(self._modeStack)==0:
raise Exception("Empty Stack")
if self._interp.debug:
print("popMode back to "+ self._modeStack[:-1], file=self._output)
self.mode( self._modeStack.pop() )
return self._mode
# Set the char stream and reset the lexer#/
@property
def inputStream(self):
return self._input
@inputStream.setter
def inputStream(self, input:InputStream):
self._input = None
self._tokenFactorySourcePair = (self, self._input)
self.reset()
self._input = input
self._tokenFactorySourcePair = (self, self._input)
View on GitHub (pinned to 7d5770395b)
Solutions
- Fix the grammar: every -> popMode must be reachable only from a mode entered with -> pushMode(<mode>)
- Guard pops in embedded Python actions: pop only if len(self._modeStack) > 0, else -> mode(DEFAULT_MODE) via the lexer's mode()
- Trace with lexer debug output or a lexer listener to see which token pops an empty stack, then move that rule into the correct mode section
Example fix
// grammar before STRING_START : '"' -> pushMode(STR); mode STR; STRING_END : '"' -> popMode; ESC : '\\' '"' -> popMode; // second pop on \\" pops empty stack // grammar after STRING_START : '"' -> pushMode(STR); mode STR; STRING_END : '"' -> popMode; ESC_QUOTE : '\\' '"' -> more; // stay in STR, no pop
Defensive patterns
Strategy: validation
Validate before calling
# Python: in an embedded lexer action, pop only when a mode is pushed
if len(self._modeStack) > 0:
self.popMode()
else:
self.mode(Lexer.DEFAULT_MODE) # or report a grammar bug Try / catch
try:
lexer.nextToken()
except Exception as ex:
if str(ex) == "Empty Stack":
raise SyntaxError(f"grammar bug: popMode with empty mode stack near char {lexer.column}") from ex
raise Prevention
- Audit every -> popMode and ensure its rule lives only inside a -> pushMode'd mode
- Test each lexer mode in isolation with minimal inputs that exercise close-delimiters
- Prefer -> more for escape sequences inside pushed modes instead of extra pops
When it happens
Trigger: A lexer grammar rule containing -> popMode that matches while in DEFAULT_MODE (no prior pushMode); two rules with popMode in the same mode where only one push occurred; generated-code paths where a skip/More rule with popMode fires repeatedly on the same construct.
Common situations: Lexer grammars for string interpolation or heredocs where the closing rule pops a mode but the opening rule forgot pushMode (or was skipped); editing modes and forgetting the push side; tokens reachable both inside and outside the pushed mode.
Related errors
- nextToken requires a non-null input stream.
- LexerNoViableAltException('{}')
- Invalid tokens or characters at index %d in path '%s'
- nextToken requires a non-null input stream.
- Parser can't discover a lexer to use
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/018998d453baf425.
Report an issue: GitHub.