Search code examples
pythonpython-3.xyacclexply

Python-Lex-Yacc symbol is unreachable


I'm trying to work with ply, but I keep getting these errors:

WARNING: C:\Users\...\Documents\Kino\Kino-Source-Code\complier.py:84: Rule 'divide' defined, but not used
WARNING: C:\Users\...\complier.py:99: Rule 'vars' defined, but not used
WARNING: C:\Users\...\complier.py:122: Rule 'multiply' defined, but not used
WARNING: C:\Users\...\complier.py:144: Rule 'say' defined, but not used
WARNING: There are 4 unused rules
WARNING: Symbol 'divide' is unreachable
WARNING: Symbol 'vars' is unreachable
WARNING: Symbol 'multiply' is unreachable
WARNING: Symbol 'say' is unreachable

Somehow the rules are 1) defined but not used, and 2) are unreachable. I've tried everything I can think of, but it won't work! Here is my code:

from ply import lex, yacc
import rich
import math

ERROR = False
reserved = {
    'say' : "SAY",

}

tokens = [
    'MULTIPLY',
    'QUOTE',
    'SPACE',
    'EQUAL',
    'QTEXT',
    'VARIABLES',
    'DIVIDE'
] + list(reserved.values())

meta = [

]
 
variables = {

}

t_DIVIDE = r"[A-Za-z0-9]+/[A-Za-z0-9]+"
t_MULTIPLY = r"\w_ ?\*\w_ ?"
t_SAY = "say"
t_QUOTE = r"\"" 
t_SPACE = r"\s"
t_QTEXT = r"\".+_ ?\""
t_EQUAL = r"\w+_ ?=\w+_ ?"
t_VARIABLES = r"\w+"

def t_error(t):
    global ERROR
    rich.print(f"[bold red]Illegal character {t.value[0]!r} on line {t.lexer.lineno}[/bold red]")
    t.lexer.skip(1)
    ERROR = True

t_ignore = '\n'

lexer = lex.lex()

def p_divide(t):
    """
    divide : DIVIDE
    """
    try:
        tmp = t[1].split("/")
        for x, i in enumerate(tmp):
            tmp[x] = float(i)
        t.value = tmp[0] / tmp[1]
        print(tmp[0] / tmp[1])
        return t.value
    except ValueError:
        rich.print("[bold red]Multiplying a non number[/bold red]\n[bold blue]Error Ignored, this may cause your program to malfunction, please fix[/bold blue]")


def p_vars_set(t):
    """
    vars : EQUAL
    """
    name = ""
    value = ""
    stripped = str(t[1]).split("=")
    name = stripped[0]
    value = stripped[1]
    variables[name] = value


def p_vars(t):
    """
    vars : VARIABLES
    """
    tmp = t[1]
    for i in t:
        print(i)
    t.value = variables[str(tmp)]
    #return t.value


def p_multiply(t):
    """
    multiply : MULTIPLY
    """
    try:
        tmp = str(t).split("*")
        for i in tmp:
            int(i)
        #t.value = NUM
        return t.value
    except ValueError:
        try:
            if "true" in t:
                print("1")
            if "false" in t:
                print("2")
            else:
                print("0")
        except:
            pass


def p_say_onlyText(t):
    """
    say : SAY QUOTE QTEXT QUOTE
        | SAY SPACE QTEXT 
    """
    l = len(t)
    start = False
    for i in (t):
        if str(i).startswith('"'):
            to_print = str(i).strip('"')
            print(to_print)


def p_error(t):
    global ERROR
    ERROR = True
    if t is None:  # lexer error
        return
    print(f"Syntax Error: {t.value!r}")

parser = yacc.yacc(debug=False, write_tables=False)

if __name__ == "__main__":
    rich.print("[yellow]Hello From The Alter Community[/yellow]")
    try:
       while True:
           i = input(">>")
           parser.parse(i)
    except IndexError:
        rich.print("[bold red]No File Specifed[/bold red]")
        rich.print("[bold blue]Program exited with code 5[/bold blue]")
        exit(5)
    except FileNotFoundError:
        rich.print("[bold red]File Not Found[/bold red]")
        rich.print("[bold blue]Program exited with code 5[/bold blue]")
        exit(5)
    if ERROR == True:
        rich.print("[bold red]Errors![/bold red]")
        rich.print("[bold blue]Program exited with code 1[/bold blue]")
    else:
        rich.print("[bold green]No Errors![/bold green]")
        rich.print("[bold blue]Program exited with code 0[/bold blue]")

Somehow, the bool function at the top is the only function that is reachable, and any function below that is not.


Solution

  • These errors are usually the result of not starting at the beginning.

    In Ply, as in many parser generators, the first defined non-terminal is expected to be the grammar's top-level symbol: that is, the non-terminal which derives all valid inputs.

    If for whatever reason you don't want to put the top-level symbol first, you can specify the start symbol with start. See the Ply Manual for details.