antlr/antlr4 · error · ReferenceError

listener

Error message

listener

What it means

Parser.addParseListener raises ReferenceError('listener') when called with listener=None. Parse listeners receive enterRule/exitRule/visitErrorNode callbacks during the walk performed at parse time; None is rejected because iterating listeners would otherwise crash later with a less diagnosable AttributeError.

Source

Thrown at runtime/Python3/src/antlr4/Parser.py:196

    # <em>deterministic</em>, i.e. for identical input the calls to listener
    # methods will be the same.</p>
    #
    # <ul>
    # <li>Alterations to the grammar used to generate code may change the
    # behavior of the listener calls.</li>
    # <li>Alterations to the command line options passed to ANTLR 4 when
    # generating the parser may change the behavior of the listener calls.</li>
    # <li>Changing the version of the ANTLR Tool used to generate the parser
    # may change the behavior of the listener calls.</li>
    # </ul>
    #
    # @param listener the listener to add
    #
    # @throws NullPointerException if {@code} listener is {@code null}
    #
    def addParseListener(self, listener:ParseTreeListener):
        if listener is None:
            raise ReferenceError("listener")
        if self._parseListeners is None:
            self._parseListeners = []
        self._parseListeners.append(listener)

    #
    # Remove {@code listener} from the list of parse listeners.
    #
    # <p>If {@code listener} is {@code null} or has not been added as a parse
    # listener, self method does nothing.</p>
    # @param listener the listener to remove
    #
    def removeParseListener(self, listener:ParseTreeListener):
        if self._parseListeners is not None:
            self._parseListeners.remove(listener)
            if len(self._parseListeners)==0:
                    self._parseListeners = None

    # Remove all parse listeners.

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Instantiate and pass a real ParseTreeListener subclass implementing enterEveryRule/exitEveryRule as needed
  2. Guard optional listeners: if listener is not None: parser.addParseListener(listener)
  3. Note that removeParseListener(None) is a no-op by design — only the add path validates; audit accordingly

Example fix

# before
parser.addParseListener(listener)  # listener is None unless debug

# after
if listener is not None:
    parser.addParseListener(listener)
Defensive patterns

Strategy: validation

Validate before calling

# Python: only add a listener that exists
if listener is not None:
    parser.addParseListener(listener)

Type guard

# Python
from antlr4.ParseTreeListener import ParseTreeListener
def is_parse_listener(obj) -> bool:
    return isinstance(obj, ParseTreeListener)

Try / catch

try:
    parser.addParseListener(listener)
except ReferenceError as ex:
    if str(ex) == "listener":
        pass  # nothing to add; continue without listener
    else:
        raise

Prevention

When it happens

Trigger: Passing a variable that was never assigned a listener instance; conditional listener setup ('listener = None; if debug: listener = ...' then unconditional addParseListener(listener)); refactor leftovers where the listener argument was dropped from a function signature but the call remained.

Common situations: Optional-listener configurations in application bootstrap; test harnesses adding a listener only in verbose mode; copy-pasted quickstart code with a placeholder None.

Related errors


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