Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python reconstructor list comprehension error #1500

Open
ellieyhcheng opened this issue Dec 24, 2024 · 0 comments
Open

Python reconstructor list comprehension error #1500

ellieyhcheng opened this issue Dec 24, 2024 · 0 comments

Comments

@ellieyhcheng
Copy link

Describe the bug

Using the official Lark Python parser and using the PythonReconstructor from the examples, list comprehension produces AssertionError when the code is valid Python code.

E.g. The inputs "[a for a in range(10)]" produces the error

AssertionError: (NonTerminal('comprehension{test_or_star_expr}'), Tree(Token('RULE', 'comprehension'), [Tree('var', [Tree(Token('RULE', 'name'), [Token('NAME', 'a')])]), Tree(Token('RULE', 'comp_fors'), [Tree(Token('RULE', 'comp_for'), [Tree('var', [Tree(Token('RULE', 'name'), [Token('NAME', 'a')])]), Tree('funccall', [Tree('var', [Tree(Token('RULE', 'name'), [Token('NAME', 'range')])]), Tree(Token('RULE', 'arguments'), [Tree(Token('RULE', 'number'), [Token('DEC_NUMBER', '10')])])])])])]))

To Reproduce

The reproduction test script is the code from the example but given the input "[a for a in range(10)]"

This is the full script:

from lark import Token, Lark
from lark.reconstruct import Reconstructor
from lark.indenter import PythonIndenter

# Official Python grammar by Lark
python_parser3 = Lark.open_from_package(
    "lark",
    "python.lark",
    ["grammars"],
    parser="lalr",
    postlex=PythonIndenter(),
    start="file_input",
    maybe_placeholders=False,  # Necessary for reconstructor
)

SPACE_AFTER = set(',+-*/~@<>="|:')
SPACE_BEFORE = (SPACE_AFTER - set(",:")) | set("'")


def special(sym):
    return Token("SPECIAL", sym.name)


def postproc(items):
    stack = ["\n"]
    actions = []
    last_was_whitespace = True
    for item in items:
        if isinstance(item, Token) and item.type == "SPECIAL":
            actions.append(item.value)
        else:
            if actions:
                assert actions[0] == "_NEWLINE" and "_NEWLINE" not in actions[1:], actions

                for a in actions[1:]:
                    if a == "_INDENT":
                        stack.append(stack[-1] + " " * 4)
                    else:
                        assert a == "_DEDENT"
                        stack.pop()
                actions.clear()
                yield stack[-1]
                last_was_whitespace = True
            if not last_was_whitespace:
                if item[0] in SPACE_BEFORE:
                    yield " "
            yield item
            last_was_whitespace = item[-1].isspace()
            if not last_was_whitespace:
                if item[-1] in SPACE_AFTER:
                    yield " "
                    last_was_whitespace = True
    yield "\n"


class PythonReconstructor:
    def __init__(self, parser):
        self._recons = Reconstructor(parser, {"_NEWLINE": special, "_DEDENT": special, "_INDENT": special})

    def reconstruct(self, tree):
        return self._recons.reconstruct(tree, postproc)


python_reconstructor = PythonReconstructor(python_parser3)

self_contents = "[a for a in range(10)]"

tree = python_parser3.parse(self_contents + "\n")
output = python_reconstructor.reconstruct(tree)

tree_new = python_parser3.parse(output)
print(tree.pretty())
print(tree_new.pretty())
# assert tree.pretty() == tree_new.pretty()
assert tree == tree_new

Running the script produces the described error. Here's the full trace:

Traceback (most recent call last):
  File "/Users/ellieyhc/Documents/test/venv/lib/python3.12/site-packages/lark/visitors.py", line 115, in _call_userfunc
    f = getattr(self, tree.data)
        ^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'WriteTokensTransformer' object has no attribute 'list_comprehension'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/ellieyhc/Documents/test/test.py", line 69, in <module>
    output = python_reconstructor.reconstruct(tree)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ellieyhc/Documents/test/test.py", line 61, in reconstruct
    return self._recons.reconstruct(tree, postproc)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ellieyhc/Documents/test/venv/lib/python3.12/site-packages/lark/reconstruct.py", line 102, in reconstruct
    for item in x:
                ^
  File "/Users/ellieyhc/Documents/test/test.py", line 28, in postproc
    for item in items:
                ^^^^^
  File "/Users/ellieyhc/Documents/test/venv/lib/python3.12/site-packages/lark/reconstruct.py", line 92, in _reconstruct
    yield from self._reconstruct(item)
  File "/Users/ellieyhc/Documents/test/venv/lib/python3.12/site-packages/lark/reconstruct.py", line 92, in _reconstruct
    yield from self._reconstruct(item)
  File "/Users/ellieyhc/Documents/test/venv/lib/python3.12/site-packages/lark/reconstruct.py", line 88, in _reconstruct
    res = self.write_tokens.transform(unreduced_tree)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ellieyhc/Documents/test/venv/lib/python3.12/site-packages/lark/visitors.py", line 286, in transform
    return self._transform_tree(tree)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ellieyhc/Documents/test/venv/lib/python3.12/site-packages/lark/visitors.py", line 280, in _transform_tree
    return self._call_userfunc(tree)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ellieyhc/Documents/test/venv/lib/python3.12/site-packages/lark/visitors.py", line 117, in _call_userfunc
    return self.__default__(tree.data, children, tree.meta)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ellieyhc/Documents/test/venv/lib/python3.12/site-packages/lark/reconstruct.py", line 58, in __default__
    assert NonTerminal(x.data) == sym, (sym, x)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: (NonTerminal('comprehension{test_or_star_expr}'), Tree(Token('RULE', 'comprehension'), [Tree('var', [Tree(Token('RULE', 'name'), [Token('NAME', 'a')])]), Tree(Token('RULE', 'comp_fors'), [Tree(Token('RULE', 'comp_for'), [Tree('var', [Tree(Token('RULE', 'name'), [Token('NAME', 'a')])]), Tree('funccall', [Tree('var', [Tree(Token('RULE', 'name'), [Token('NAME', 'range')])]), Tree(Token('RULE', 'arguments'), [Tree(Token('RULE', 'number'), [Token('DEC_NUMBER', '10')])])])])])]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant