def compare_trees(
    actual_tree: ast.AST, file: str, verbose: bool, include_attributes: bool = False,
) -> int:
    with open(file) as f:
        expected_tree = _peg_parser.parse_string(f.read(), oldparser=True)

    expected_text = ast_dump(expected_tree, include_attributes=include_attributes)
    actual_text = ast_dump(actual_tree, include_attributes=include_attributes)
    if actual_text == expected_text:
        if verbose:
            print("Tree for {file}:")
            print(show_parse.format_tree(actual_tree, include_attributes))
        return 0

    print(f"Diffing ASTs for {file} ...")

    expected = show_parse.format_tree(expected_tree, include_attributes)
    actual = show_parse.format_tree(actual_tree, include_attributes)

    if verbose:
        print("Expected for {file}:")
        print(expected)
        print("Actual for {file}:")
        print(actual)
        print(f"Diff for {file}:")

    diff = show_parse.diff_trees(expected_tree, actual_tree, include_attributes)
    for line in diff:
        print(line)

    return 1
def verify_ast_generation(source: str, stmt: str, tmp_path: PurePath) -> None:
    grammar = parse_string(source, GrammarParser)
    extension = generate_parser_c_extension(grammar, tmp_path)

    expected_ast = ast.parse(stmt)
    actual_ast = extension.parse_string(stmt, mode=1)
    assert ast_dump(expected_ast) == ast_dump(actual_ast)
示例#3
0
def test_correct_but_known_to_fail_ast_generation_on_source_files(
        parser_extension: Any, source: str) -> None:
    actual_ast = parser_extension.parse_string(source, mode=1)
    expected_ast = ast.parse(source)
    assert ast_dump(actual_ast, include_attributes=True) == ast_dump(
        expected_ast,
        include_attributes=True), f"Wrong AST generation for source: {source}"
示例#4
0
def format_tree(tree: ast.AST, verbose: bool = False) -> str:
    with tempfile.NamedTemporaryFile("w+") as tf:
        tf.write(ast_dump(tree, include_attributes=verbose))
        tf.write("\n")
        tf.flush()
        cmd = f"black -q {tf.name}"
        sts = os.system(cmd)
        if sts:
            raise RuntimeError(f"Command {cmd!r} failed with status 0x{sts:x}")
        tf.seek(0)
        return tf.read()
def test_c_parser(tmp_path: PurePath) -> None:
    grammar_source = """
    start[mod_ty]: a=stmt* $ { Module(a, NULL, p->arena) }
    stmt[stmt_ty]: a=expr_stmt { a }
    expr_stmt[stmt_ty]: a=expression NEWLINE { _Py_Expr(a, EXTRA) }
    expression[expr_ty]: ( l=expression '+' r=term { _Py_BinOp(l, Add, r, EXTRA) }
                         | l=expression '-' r=term { _Py_BinOp(l, Sub, r, EXTRA) }
                         | t=term { t }
                         )
    term[expr_ty]: ( l=term '*' r=factor { _Py_BinOp(l, Mult, r, EXTRA) }
                   | l=term '/' r=factor { _Py_BinOp(l, Div, r, EXTRA) }
                   | f=factor { f }
                   )
    factor[expr_ty]: ('(' e=expression ')' { e }
                     | a=atom { a }
                     )
    atom[expr_ty]: ( n=NAME { n }
                   | n=NUMBER { n }
                   | s=STRING { s }
                   )
    """
    grammar = parse_string(grammar_source, GrammarParser)
    extension = generate_parser_c_extension(grammar, tmp_path)

    expressions = [
        "4+5",
        "4-5",
        "4*5",
        "1+4*5",
        "1+4/5",
        "(1+1) + (1+1)",
        "(1+1) - (1+1)",
        "(1+1) * (1+1)",
        "(1+1) / (1+1)",
    ]

    for expr in expressions:
        the_ast = extension.parse_string(expr, mode=1)
        expected_ast = ast.parse(expr)
        assert ast_dump(the_ast) == ast_dump(expected_ast)
def test_with_stmt_with_paren(tmp_path: PurePath) -> None:
    grammar_source = """
    start[mod_ty]: a=[statements] ENDMARKER { Module(a, NULL, p->arena) }
    statements[asdl_seq*]: a=statement+ {  _PyPegen_seq_flatten(p, a) }
    statement[asdl_seq*]: a=compound_stmt {  _PyPegen_singleton_seq(p, a) }
    compound_stmt[stmt_ty]: with_stmt
    with_stmt[stmt_ty]: (
        a='with' '(' b=','.with_item+ ')' ':' c=block {
            _Py_With(b, _PyPegen_singleton_seq(p, c), NULL, EXTRA) }
    )
    with_item[withitem_ty]: (
        e=NAME o=['as' t=NAME { t }] { _Py_withitem(e, _PyPegen_set_expr_context(p, o, Store), p->arena) }
    )
    block[stmt_ty]: a=pass_stmt NEWLINE { a } | NEWLINE INDENT a=pass_stmt DEDENT { a }
    pass_stmt[stmt_ty]: a='pass' { _Py_Pass(EXTRA) }
    """
    stmt = "with (\n    a as b,\n    c as d\n): pass"
    grammar = parse_string(grammar_source, GrammarParser)
    extension = generate_parser_c_extension(grammar, tmp_path)
    the_ast = extension.parse_string(stmt, mode=1)
    assert ast_dump(the_ast).startswith(
        "Module(body=[With(items=[withitem(context_expr=Name(id='a', ctx=Load()), optional_vars=Name(id='b', ctx=Store())), "
        "withitem(context_expr=Name(id='c', ctx=Load()), optional_vars=Name(id='d', ctx=Store()))]"
    )
示例#7
0
def test_correct_ast_generation_without_pos_info(parser_extension: Any,
                                                 source: str) -> None:
    actual_ast = parser_extension.parse_string(source, mode=1)
    expected_ast = ast.parse(source)
    assert ast_dump(actual_ast) == ast_dump(
        expected_ast), f"Wrong AST generation for source: {source}"