[Python] PLY Error: Symbol 'NOT' used, but not defined as a token or a rule

Discussão em 'Python' iniciado por Stack, Janeiro 3, 2025.

  1. Stack

    Stack Membro Participativo

    I'm encountering an issue with PLY (Python Lex-Yacc) where it's failing to recognize a token in the parser that I've defined. This error is preventing the parser from being built.

    • I'm using PLY 3.11 (the latest available on PyPI)
    • I'm using Python 3.13

    When trying to build the parser, I receive the following error:

    ERROR: C:\Users\###\Desktop\Scratch\scrybe\src\scrybe\scriptparser\parser.py:236: Symbol 'NOT' used, but not defined as a token or a rule
    WARNING: Token 'COMMENT' defined, but not used
    WARNING: Token 'NEWLINE' defined, but not used
    WARNING: Token 'UMINUS' defined, but not used
    WARNING: There are 3 unused tokens
    Traceback (most recent call last):
    ...
    parser = yacc.yacc()
    File "C:\Program Files\Python313\Lib\site-packages\ply\yacc.py", line 3432, in yacc
    raise YaccError('Unable to build parser')
    ply.yacc.YaccError: Unable to build parser


    Here is the relevant code for my lexer:

    reserved = {
    ...
    "this": "THIS",
    "not": "NOT",
    "and": "AND",
    ...
    }

    tokens.extend(reserved.values())

    ...

    def t_SYMBOL(token):
    r"\b[a-zA-Z_]\w*\b"
    token.type = reserved.get(token.value, "VARIABLE")
    return token


    Here is my precedence table in parser.py:

    precedence = (
    ...
    ("left", "AND"),
    ("right", "NOT"),
    ("left", "IN"),
    ...
    )


    And here is the code from my parser which generates the error:

    def p_logical_operation(prod):
    """logical_operation : expression LESSTHAN expression
    | expression GREATERTHAN expression
    | expression LESSTHANEQUAL expression
    | expression GREATERTHANEQUAL expression
    | expression EQUALTO expression
    | expression NOTEQUALTO expression
    | expression AND expression
    | expression OR expression
    | expression IN expression
    | NOT expression"""
    prod[0] = {
    "lexpos": prod.lexpos(1) if len(prod) == 3 else prod[1]["lexpos"] if isinstance(prod[1], dict) else prod.lexpos(2),
    "type": "logical operation",
    "condition": prod[2] if len(prod) == 4 else prod[1],
    }
    if len(prod) == 4:
    prod[0].update({
    "comparand 1": prod[1],
    "comparand 2": prod[3]
    })
    else:
    prod[0].update({"comparand": prod[2]})


    I've confirmed that the lexer is producing the expected tokens when run separately on a piece of test input.

    Question: Why is PLY unable to recognize the 'NOT' token despite it being defined in the reserved dictionary, especially given that I can replace it with any other reserved keyword and have it work fine? How can I resolve this issue and successfully build the parser? Any help or insights would be greatly appreciated.

    Continue reading...

Compartilhe esta Página