8000 IndexError when extracting optional items from a repeat · Issue #66 · dabeaz/sly · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
IndexError when extracting optional items from a repeat #66
Open
@jpsnyder

Description

@jpsnyder

First of all. Thanks for making this excellent library. I find it much more approachable, and yet more customizable and elegant than the other libraries on the market. It's a huge improvement over the PLY library. I hope to see this project grow in the future.

I'm having a small issue where I run into an IndexError when accessing an item within an optional which is within a repeat.
Please see the following simplified example.

import sly


class Lexer(sly.Lexer):
    tokens = {A, B}
    literals = {"[", "]", ","}

    A = "a"
    B = "b"


class Parser(sly.Parser):
    tokens = Lexer.tokens

    @_("'[' [ expr ] { ',' [ expr ] } ']'")
    def array(self, p):
        items = [p.expr0, *p.expr1]
        # Each None accounts for an Elision
        items = [item or ("elision", None) for item in items]
        return "array", items

    @_("A", "B")
    def expr(self, p):
        return "expr", p[0]


lexer = Lexer()
parser = Parser()
code = "[a,,a,b,,]"

tokens = list(lexer.tokenize(code))  # pulling full tokens, just so we can look at them.
print("\n".join(map(str, tokens)))
tree = parser.parse(iter(tokens))
print(repr(tree))
Token(type='[', value='[', lineno=1, index=0)
Token(type='A', value='a', lineno=1, index=1)
Token(type=',', value=',', lineno=1, index=2)
Token(type=',', value=',', lineno=1, index=3)
Token(type='A', value='a', lineno=1, index=4)
Token(type=',', value=',', lineno=1, index=5)
Token(type='B', value='b', lineno=1, index=6)
Token(type=',', value=',', lineno=1, index=7)
Token(type=',', value=',', lineno=1, index=8)
Token(type=']', value=']', lineno=1, index=9)
Traceback (most recent call last):
  File "/home/jon/.config/JetBrains/PyCharmCE2020.3/scratches/scratch_36.py", line 40, in <module>
    tree = parser.parse(iter(tokens))
  File "/home/jon/.virtualenvs/test/lib/python3.8/site-packages/sly/yacc.py", line 2082, in parse
    value = p.func(self, pslice)
  File "/home/jon/.config/JetBrains/PyCharmCE2020.3/scratches/scratch_36.py", line 18, in array
    items = [p.expr0, *p.expr1]
  File "/home/jon/.virtualenvs/test/lib/python3.8/site-packages/sly/yacc.py", line 148, in __getattr__
    return self._namemap[name](self._slice)
  File "/home/jon/.virtualenvs/test/lib/python3.8/site-packages/sly/yacc.py", line 239, in <lambda>
    namemap[k] = lambda s,i=index,n=n: ([x[n] for x in s[i].value]) if isinstance(s[i].value, list) else s[i].value[n]
  File "/home/jon/.virtualenvs/test/lib/python3.8/site-packages/sly/yacc.py", line 239, in <listcomp>
    namemap[k] = lambda s,i=index,n=n: ([x[n] for x in s[i].value]) if isinstance(s[i].value, list) else s[i].value[n]
IndexError: tuple index out of range

Process finished with exit code 1

With some debugging, I discovered this is occuring when I try to access p.expr1.
I can access it with indexing, but it seems like it is due to the second expr term being incorrectly wrapped in a tuple? Below is the workaround I implemented, but I'm curious on your take on this.

    @_("'[' [ expr ] { ',' [ expr ] } ']'")
    def array(self, p):
        items = [p.expr0]
        for item in p[2]:
            comma, expr_tuple = item
            # expr_tuple is a single element tuple for some reason
            items.append(expr_tuple[0])
        items = [item or ("elision", None) for item in items]
        return "array", items

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0