Пример #1
0
def test_and_expr_function_parses_and_expression_successfully():
    # TODO: More complex examples
    result0 = Parser.from_code("5²").and_expr()
    result1 = Parser.from_code("0xff&3&4").and_expr()
    result2 = Parser.from_code("5&5>>3").and_expr()
    result3 = Parser.from_code("5²<<-4&-5-+3").and_expr()

    assert result0 == UnaryExpr(Integer(0), Operator(1))
    assert result1 == BinaryExpr(
        BinaryExpr(Integer(0), Operator(1), Integer(2)), Operator(3), Integer(4)
    )
    assert result2 == BinaryExpr(
        Integer(0), Operator(1), BinaryExpr(Integer(2), Operator(3), Integer(4))
    )
    assert result3 == BinaryExpr(
        BinaryExpr(
            UnaryExpr(Integer(0), Operator(1)),
            Operator(2),
            UnaryExpr(Integer(4), Operator(3)),
        ),
        Operator(5),
        BinaryExpr(
            UnaryExpr(Integer(7), Operator(6)),
            Operator(8),
            UnaryExpr(Integer(10), Operator(9))
        )
    )
Пример #2
0
def test_or_expr_function_parses_or_expression_successfully():
    # TODO: More complex examples
    result0 = Parser.from_code("5²").or_expr()
    result1 = Parser.from_code("0xff|3|4").or_expr()
    result2 = Parser.from_code("5|5||3").or_expr()
    result3 = Parser.from_code("5²||-4|-5<<+3").or_expr()

    assert result0 == UnaryExpr(Integer(0), Operator(1))
    assert result1 == BinaryExpr(
        BinaryExpr(Integer(0), Operator(1), Integer(2)), Operator(3), Integer(4)
    )
    assert result2 == BinaryExpr(
        Integer(0), Operator(1), BinaryExpr(Integer(2), Operator(3), Integer(4))
    )
    assert result3 == BinaryExpr(
        BinaryExpr(
            UnaryExpr(Integer(0), Operator(1)),
            Operator(2),
            UnaryExpr(Integer(4), Operator(3)),
        ),
        Operator(5),
        BinaryExpr(
            UnaryExpr(Integer(7), Operator(6)),
            Operator(8),
            UnaryExpr(Integer(10), Operator(9))
        )
    )
Пример #3
0
def test_shift_expr_function_parses_shift_expression_successfully():
    # TODO: More complex examples
    result0 = Parser.from_code("5²").shift_expr()
    result1 = Parser.from_code("0xff>>3<<4").shift_expr()
    result2 = Parser.from_code("5>>5*3").shift_expr()
    result3 = Parser.from_code("5²+-4<<-5*+3").shift_expr()

    assert result0 == UnaryExpr(Integer(0), Operator(1))
    assert result1 == BinaryExpr(
        BinaryExpr(Integer(0), Operator(1), Integer(2)), Operator(3), Integer(4)
    )
    assert result2 == BinaryExpr(
        Integer(0), Operator(1), BinaryExpr(Integer(2), Operator(3), Integer(4))
    )
    assert result3 == BinaryExpr(
        BinaryExpr(
            UnaryExpr(Integer(0), Operator(1)),
            Operator(2),
            UnaryExpr(Integer(4), Operator(3)),
        ),
        Operator(5),
        BinaryExpr(
            UnaryExpr(Integer(7), Operator(6)),
            Operator(8),
            UnaryExpr(Integer(10), Operator(9))
        )
    )
Пример #4
0
def test_newline_parses_newlines_successfully():
    result0 = Parser.from_code("\n").newline()
    result1 = Parser.from_code("\r\n").newline()
    result2 = Parser.from_code("\r").newline()

    assert result0 == Newline(0)
    assert result1 == Newline(0)
    assert result2 == Newline(0)
Пример #5
0
def test_prefixed_string_parses_prefixed_string_literals_successfully():
    result0 = Parser.from_code("u'hello\t there'").prefixed_string()
    result1 = Parser.from_code('rf" This is a new world"').prefixed_string()
    result2 = Parser.from_code("r'''\n This is a new world\n'''").prefixed_string()
    result3 = Parser.from_code('rf"""\n This is a new world\n"""').prefixed_string()

    assert result0 == PrefixedString(0)
    assert result1 == PrefixedString(0)
    assert result2 == PrefixedString(0)
    assert result3 == PrefixedString(0)
Пример #6
0
def test_byte_string_parses_byte_string_literals_successfully():
    result0 = Parser.from_code("b'hello\t there'").byte_string()
    result1 = Parser.from_code('rb" This is a new world"').byte_string()
    result2 = Parser.from_code("b'''\n This is a new world\n'''").byte_string()
    result3 = Parser.from_code('rb"""\n This is a new world\n"""').byte_string()

    assert result0 == ByteString(0)
    assert result1 == ByteString(0)
    assert result2 == ByteString(0)
    assert result3 == ByteString(0)
Пример #7
0
def test_not_test_function_parses_not_test_successfully():
    # TODO: More complex examples
    result0 = Parser.from_code("5²").not_test()
    result1 = Parser.from_code("0xff&3&4").not_test()
    result2 = Parser.from_code("5&5>>3").not_test()
    result3 = Parser.from_code("5²<<-4&-5-+3").not_test()

    print('', result0, result1, result2, result3, sep="\n\n>>>> ")

    assert result0 == UnaryExpr(Integer(0), Operator(1))
Пример #8
0
def test_imag_float_parses_imaginary_float_literals_successfully():
    result0 = Parser.from_code(".05im").imag_float()
    result1 = Parser.from_code("0.0_55im").imag_float()
    result2 = Parser.from_code("1_00.00_50im").imag_float()
    result3 = Parser.from_code("1.e-5_00im").imag_float()
    result4 = Parser.from_code("1_00.1_00e-1_00im").imag_float()

    assert result0 == ImagFloat(0)
    assert result1 == ImagFloat(0)
    assert result2 == ImagFloat(0)
    assert result3 == ImagFloat(0)
    assert result4 == ImagFloat(0)
Пример #9
0
def test_integer_parses_integer_literals_successfully():
    result0 = Parser.from_code("5_000").integer()
    result1 = Parser.from_code("0001").integer()
    result2 = Parser.from_code("0b11_00").integer()
    result3 = Parser.from_code("0o217").integer()
    result4 = Parser.from_code("0xffEE_210").integer()

    assert result0 == Integer(0)
    assert result1 == Integer(0)
    assert result2 == Integer(0)
    assert result3 == Integer(0)
    assert result4 == Integer(0)
Пример #10
0
def test_power_expr_function_parses_power_expression_successfully():
    # TODO: More complex examples
    result0 = Parser.from_code("5^6").power_expr()
    result1 = Parser.from_code("5²").power_expr()
    result2 = Parser.from_code("5").power_expr()
    result3 = Parser.from_code("√5²").power_expr()
    result4 = Parser.from_code("√5^5").power_expr()

    assert result0 == BinaryExpr(Integer(0), Operator(1), Integer(2))
    assert result1 == UnaryExpr(Integer(0), Operator(1))
    assert result2 == Integer(0)
    assert result3 == UnaryExpr(UnaryExpr(Integer(1), Operator(2)), Operator(0))
    assert result4 == UnaryExpr(
        BinaryExpr(Integer(1), Operator(2), Integer(3)), Operator(0)
    )
Пример #11
0
def test_parser_backtracks_on_fail_successfully():
    parser0 = Parser.from_code("1hello")
    result0 = parser0.identifier()

    # TODO: Try more complex parser functions

    assert parser0.cursor == -1
    assert result0 is None
Пример #12
0
def test_unary_expr_function_parses_root_expression_successfully():
    # TODO: More complex examples
    result0 = Parser.from_code("-6").unary_expr()
    result1 = Parser.from_code("-5²").unary_expr()
    result2 = Parser.from_code("~√5²").unary_expr()
    result3 = Parser.from_code("-√5^5").unary_expr()
    result4 = Parser.from_code("-~+5_00").unary_expr()

    assert result0 == UnaryExpr(Integer(1), Operator(0))
    assert result1 == UnaryExpr(UnaryExpr(Integer(1), Operator(2)), Operator(0))
    assert result2 == UnaryExpr(
        UnaryExpr(UnaryExpr(Integer(2), Operator(3)), Operator(1)), Operator(0)
    )
    assert result3 == UnaryExpr(
        UnaryExpr(BinaryExpr(Integer(2), Operator(3), Integer(4)), Operator(1)),
        Operator(0),
    )
    assert result4 == UnaryExpr(
        UnaryExpr(UnaryExpr(Integer(3), Operator(2)), Operator(1)), Operator(0)
    )
Пример #13
0
    def compile_code(code, output_type="exe", compiler_opts=CompilerOptions()):
        """
        supported_output_types = [
            "exe",
            "ll",
            "wasm",
            "ast",
            "sema",
            "lowered_ast",
            "tokens",
        ]
        """

        if output_type == "tokens":
            tokens = Lexer(code, compiler_opts).lex()
            result = json_dumps(tokens)

        elif output_type == "ast":
            ast = Parser.from_code(code, compiler_opts).parse()
            result = json_dumps(ast)

        elif output_type == "sema":
            tokens = Lexer(code, compiler_opts).lex()
            ast = Parser(tokens, compiler_opts).parse()
            semantic_info = SemanticAnalyzer(ast, tokens,
                                             compiler_opts).analyze()
            result = json_dumps(semantic_info)

        elif output_type == "ll":
            compiler_opts.target_code = "llvm"
            tokens = Lexer(code, compiler_opts).lex()
            ast = Parser(tokens, compiler_opts).parse()
            semantic_info = SemanticAnalyzer(ast, tokens,
                                             compiler_opts).analyze()
            llvm = LLVMCodegen(ast, semantic_info).generate()
            result = llvm.dumps()

        elif output_type == "wasm":
            compiler_opts.target_code = "wasm"
            tokens = Lexer(code, compiler_opts).lex()
            ast = Parser(tokens, compiler_opts).parse()
            semantic_info = SemanticAnalyzer(ast, tokens,
                                             compiler_opts).analyze()
            result = json_dumps(semantic_info)

        else:
            click.echo("Unimplemented Output Type!")
            return

        click.echo(result)
Пример #14
0
def test_mul_expr_function_parses_multiply_expression_successfully():
    # TODO: More complex examples
    result0 = Parser.from_code("-5").mul_expr()
    result1 = Parser.from_code("0xff*3//4").mul_expr()
    result2 = Parser.from_code("5%5^3").mul_expr()
    result3 = Parser.from_code("5²/-4@+3").mul_expr()

    assert result0 == UnaryExpr(Integer(1), Operator(0))
    assert result1 == BinaryExpr(
        BinaryExpr(Integer(0), Operator(1), Integer(2)), Operator(3), Integer(4)
    )
    assert result2 == BinaryExpr(
        Integer(0), Operator(1), BinaryExpr(Integer(2), Operator(3), Integer(4))
    )
    assert result3 == BinaryExpr(
        BinaryExpr(
            UnaryExpr(Integer(0), Operator(1)),
            Operator(2),
            UnaryExpr(Integer(4), Operator(3)),
        ),
        Operator(5),
        UnaryExpr(Integer(7), Operator(6)),
    )
Пример #15
0
def test_float_parses_float_literals_successfully():
    result0 = Parser.from_code(".05").float()
    result1 = Parser.from_code("0.0_55").float()
    result2 = Parser.from_code("1_00.00_50").float()
    result3 = Parser.from_code("1.e-5_00").float()
    result4 = Parser.from_code("1.").float()
    result5 = Parser.from_code("1_00.1_00e-1_00").float()

    assert result0 == Float(0)
    assert result1 == Float(0)
    assert result2 == Float(0)
    assert result3 == Float(0)
    assert result4 == Float(0)
    assert result5 == Float(0)
Пример #16
0
def test_comparison_expr_function_parses_comparison_expression_successfully():
    # TODO: More complex examples
    result0 = Parser.from_code("5²").comparison_expr()
    result1 = Parser.from_code("0xff<3>4==5<=0b101>=0o767").comparison_expr()
    result2 = Parser.from_code("5 is 5|3").comparison_expr()
    result3 = Parser.from_code("5²*-4!=-5<<+3").comparison_expr()
    result4 = Parser.from_code("5|5 not in 3").comparison_expr()
    result5 = Parser.from_code("5-5 is not 3").comparison_expr()

    assert result0 == UnaryExpr(Integer(0), Operator(1))
    assert result1 == BinaryExpr(
        BinaryExpr(
            BinaryExpr(
                BinaryExpr(
                    BinaryExpr(Integer(0), Operator(1), Integer(2)),
                    Operator(3),
                    Integer(4)
                ),
                Operator(5),
                Integer(6)
            ),
            Operator(7),
            Integer(8)
        ),
        Operator(9),
        Integer(10),
    )
    assert result2 == BinaryExpr(
        Integer(0), Operator(1), BinaryExpr(Integer(2), Operator(3), Integer(4))
    )
    assert result3 == BinaryExpr(
        BinaryExpr(
            UnaryExpr(Integer(0), Operator(1)),
            Operator(2),
            UnaryExpr(Integer(4), Operator(3)),
        ),
        Operator(5),
        BinaryExpr(
            UnaryExpr(Integer(7), Operator(6)),
            Operator(8),
            UnaryExpr(Integer(10), Operator(9))
        )
    )
    assert result4 == BinaryExpr(
        BinaryExpr(Integer(0), Operator(1), Integer(2)), Operator(3, 4), Integer(5),
    )
    assert result5 == BinaryExpr(
        BinaryExpr(Integer(0), Operator(1), Integer(2)), Operator(3, 4), Integer(5),
    )
Пример #17
0
def test_identifier_parses_identifiers_successfully():
    result = Parser.from_code("_HEoDagu123").identifier()

    assert result == Identifier(0)
Пример #18
0
def test_imag_integer_parses_imaginary_integer_literals_successfully():
    result0 = Parser.from_code("5_000im").imag_integer()
    result1 = Parser.from_code("0001im").imag_integer()

    assert result0 == ImagInteger(0)
    assert result1 == ImagInteger(0)
Пример #19
0
def test_parser_memoizes_parser_functions_results_successfully():
    # Memoize if parser successful
    parser0 = Parser.from_code("identifier")
    result0 = parser0.identifier()

    assert result0 == Identifier(0)
    assert parser0.cache == {-1: {"identifier": (Identifier(0), 0)}}

    def parse(parser, *parsers, fn=None):
        """
        A combinator function for parsing PEG sequence.
        Supports function and out argument for pulling out relevant data.
        """

        def func():
            nonlocal parser
            # Get important parser state before parsing.
            cursor, row, column = parser.cursor, *parser.get_line_info()

            func.__name__ = "p"
            result = []

            for p in parsers:
                is_a_str = type(p) == str
                ast = parser.consume_string(p) if is_a_str else p()

                if ast is None:
                    # Revert parser state
                    parser.revert(cursor, row, column)
                    break

                result.append(ast)
            else:
                if fn:
                    fn(result, parser.combinator_data)

                return result

            return None

        return func

    # Check to see if parser is memoizing subccesses and failures properly
    parser1 = Parser.from_code("u'hello' .05im _wr2t4gdbeYFS")
    parse(parser1, parser1.prefixed_string, parser1.imag_float, parser1.integer)()

    assert parser1.cache == {
        -1: {"prefixed_string": (PrefixedString(0), 0),},
        0: {"imag_float": (ImagFloat(1), 1),},
        1: {"integer": (None, 2)},
    }

    parse(parser1, parser1.prefixed_string, parser1.imag_float, parser1.identifier)()

    assert parser1.cache == {
        -1: {"prefixed_string": (PrefixedString(0), 0),},
        0: {"imag_float": (ImagFloat(1), 1),},
        1: {"integer": (None, 2), "identifier": (Identifier(2), 2)},
    }

    # Check to see if parser reuses cache instead of making repeated calls
    parser2 = Parser.from_code("u'hello' .05im _wr2t4gdbeYFS")
    imag_float = MagicMock(return_value=ImagFloat(1), __name__="imag_float")

    # These functions are needed because the decorators have wrapper functions that take
    # a parser argument.
    def memoize_imag_float_wrapper(parser):
        return Parser.memoize(imag_float)(parser)

    def backtrackable_imag_float_wrapper():
        return Parser.backtrackable(memoize_imag_float_wrapper)(parser2)

    parser2.imag_float = backtrackable_imag_float_wrapper

    # parser2.imag_float should onmly be called once here. It's chahed redult should be used
    # for subsequent calls.
    parse(parser2, parser2.prefixed_string, parser2.imag_float, parser2.integer)()
    parse(parser2, parser2.prefixed_string, parser2.imag_float, parser2.identifier)()
    parse(parser2, parser2.prefixed_string, parser2.imag_float, parser2.identifier)()

    assert len(imag_float.mock_calls) == 1