Пример #1
0
    def test_let_statements(self) -> None:
        source: str = '''
            variable x = 5;
            variable y = 10;
            variable foo = 20;
            variable bar = verdadero;
        '''
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self.assertEqual(len(program.statements), 4)

        expected_identifiers_and_values: List[Tuple[str,Any]] = [
            ('x',5),
            ('y',10),
            ('foo',20),
            ('bar',True),
        ]

        for statement, (expected_identifier, expected_value) in zip(program.statements, expected_identifiers_and_values):
            self.assertEqual(statement.token_literan(), 'variable')
            self.assertIsInstance(statement, LetStatement)

            let_statement = cast(LetStatement,statement)

            assert let_statement.name is not None
            self._test_identifier(let_statement.name, expected_identifier)

            assert let_statement.value is not None
            self._test_literal_expression(let_statement.value, expected_value)
    def test_function_parameters(self) -> None:
        tests = [
            {
                'input': 'procedimiento() {};',
                'expected_params': []
            },
            {
                'input': 'procedimiento(x) {};',
                'expected_params': ['x']
            },
            {
                'input': 'procedimiento(x, y, z) {};',
                'expected_params': ['x', 'y', 'z']
            },
        ]

        for test in tests:
            lexer: Lexer = Lexer(test['input'])  # type: ignore
            parser: Parser = Parser(lexer)

            program: Program = parser.parse_program()

            function = cast(
                Function,
                cast(ExpressionStatement, program.statements[0]).expression)

            self.assertEquals(len(function.parameters),
                              len(test['expected_params']))

            for idx, param in enumerate(test['expected_params']):
                self._test_literal_expression(function.parameters[idx], param)
Пример #3
0
    def test_operator_precedence(self) ->None:
        test_sources: List[Tuple[str, str, int]] = [
            ('-a * b;','((-a) * b)',1),
            ('!-a;','(!(-a))',1),
            ('a + b / c;','(a + (b / c))',1),
            ('3 + 4; -5 * 5;','(3 + 4)((-5) * 5)',2),
            
            ('verdadero;falso;verdadero;','(verdadero)(falso)(verdadero)',3),
            ('!verdadero;!falso;verdadero;','(!(verdadero))(!(falso))(verdadero)',3),
            ('verdadero + verdadero;','((verdadero) + (verdadero))',1),
            ('5 / 9 * 10','((5 / 9) * 10)',1),
            ('5 / 9 * 10; verdadero + verdadero;','((5 / 9) * 10)((verdadero) + (verdadero))',2),
            ('3 < 5 == verdadero','((3 < 5) == (verdadero))',1),
            ('1 + (2 + 3) + 4;', '((1 + (2 + 3)) + 4)', 1),
            ('(5 + 5) * 2;', '((5 + 5) * 2)', 1),
            ('2 / (5 + 5);', '(2 / (5 + 5))', 1),
            ('-(5 + 5);', '(-(5 + 5))', 1),
            ('a + suma(b * c) + d;', '((a + suma((b * c))) + d)', 1),
            ('suma(a, b, 1, 2 * 3, 4 + 5, suma(6, 7 * 8));',
             'suma(a, b, 1, (2 * 3), (4 + 5), suma(6, (7 * 8)))', 1),
            ('suma(a + b + c * d / f + g);', 'suma((((a + b) + ((c * d) / f)) + g))', 1),
        ]

        for source, expected_result, expected_statement_count in test_sources:
            lexer: Lexer = Lexer(source)
            parser: Parser = Parser(lexer)
            program: Program = parser.parse_program()

            self._test_program_statement(parser, program, expected_statement_count)
            self.assertEquals(str(program), expected_result)
Пример #4
0
    def test_return_statements(self) -> None:

        source: str = """
            regresa  5;
            regresa foo;
            regresa verdadero;
            regresa falso;
        """

        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        expected_return_values: List[Any] = [
            5,
            'foo',
            True,
            False,
        ]

        self.assertEqual(len(program.statements), 4)

        for statement, expected_return_value in zip(
                program.statements, expected_return_values):

            self.assertEqual(statement.token_literal(), 'regresa')
            self.assertIsInstance(statement, ReturnStatement)

            return_statement = cast(ReturnStatement, statement)

            assert return_statement.return_value is not None

            self._test_literal_expression(return_statement.return_value, 
                                          expected_return_value)
Пример #5
0
    def test_if_else_expression(self) -> None:

        source: str = 'si (a > b) { x } si_no { z; x; }'

        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statements(parser, program, 1)

        # Test correct node types
        if_expression = cast(If, cast(ExpressionStatement, program.statements[0]).expression)
        self.assertIsInstance(if_expression, If)

        # Test condition
        assert if_expression.condition is not None
        
        self._test_infix_expression(cast(Expression, if_expression.condition), "a", ">", "b")

        # Test consequence
        assert if_expression.consequence is not None
        self._test_block(if_expression.consequence, 1, ["x"])

        # Test alternative
        assert if_expression.alternative is not None
        self._test_block(if_expression.alternative, 2, ["z", "x"])
Пример #6
0
    def test_infix_expression(self) -> None:
        
        source: str = """
            5 + 5;
            5 - 5;
            5 * 5;
            5 / 5;
            5 > 5;
            5 < 5;
            5 >= 5;
            5 <= 5;
            5 == 5;
            5 === 5;
            5 != 5;
            5 !== 5;
            verdadero == verdadero
            verdadero === verdadero
            falso != falso
            falso !== falso
        """

        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statements(parser, program, expected_statement_count=16)

        expected_operators_and_values: List[Tuple[Any, str, Any]] = [
            (5, "+", 5),
            (5, "-", 5),
            (5, "*", 5),
            (5, "/", 5),
            (5, ">", 5),
            (5, "<", 5),
            (5, ">=", 5),
            (5, "<=", 5),
            (5, "==", 5),
            (5, "===", 5),
            (5, "!=", 5),
            (5, "!==", 5),
            (True, "==", True),
            (True, "===", True),
            (False, "!=", False),
            (False, "!==", False),
        ]

        for statement, (expected_left, expected_operator, expected_right) in zip(
            program.statements, expected_operators_and_values):

            statement = cast(ExpressionStatement, statement)

            assert statement.expression is not None

            self.assertIsInstance(statement.expression, Infix)

            self._test_infix_expression(statement.expression,
                                        expected_left,
                                        expected_operator,
                                        expected_right)
Пример #7
0
    def test_if_expression(self) -> None:

        source: str = "si (x < y) { z }"

        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statements(parser, program, 1)

        # Test correct node types
        if_expression = cast(If, cast(ExpressionStatement, program.statements[0]).expression)
        self.assertIsInstance(if_expression, If)

        # Test condition
        assert if_expression.condition is not None
        self._test_infix_expression(cast(Expression, if_expression.condition), "x", "<", "y")

        # Test consequence
        assert if_expression.consequence is not None
        self._test_block(if_expression.consequence, 1, ["z"])

        # Test alternative
        self.assertIsNone(if_expression.alternative)
Пример #8
0
    def test_function_literal(self) -> None:

        source: str = "funcion(x, y) { x + y}"

        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statements(parser, program, 1)

        # Test correct node type
        function_literal = cast(Function, cast(ExpressionStatement,
                                                program.statements[0]).expression)

        self.assertIsInstance(function_literal, Function)

        # Test params
        self.assertEquals(len(function_literal.parameters), 2)
        self._test_literal_expression(function_literal.parameters[0], "x")
        self._test_literal_expression(function_literal.parameters[1], "y")

        # Test body
        assert function_literal.body is not None
        self.assertEquals(len(function_literal.body.statements), 1)

        body = cast(ExpressionStatement, function_literal.body.statements[0])

        assert body.expression is not None
        self._test_infix_expression(body.expression, "x", "+", "y")
Пример #9
0
    def test_function_parameters(self) -> None:

        tests = [
            {
                "input": "funcion() {};",
                "expected_params": []
            },
            {
                "input": "funcion(x) {};",
                "expected_params": ["x"]
            },
            {
                "input": "funcion(x, y, z) {};",
                "expected_params": ["x", "y", "z"]
            }
        ]

        for test in tests:

            lexer: Lexer = Lexer(test["input"]) # type: ignore
            parser: Parser = Parser(lexer)

            program: Program = parser.parse_program()

            self._test_program_statements(parser, program, 1)

            function = cast(Function, cast(ExpressionStatement,
                                        program.statements[0]).expression)

            self.assertEquals(len(function.parameters), len(test["expected_params"]))

            for idx, param in enumerate(test["expected_params"]):

                self._test_literal_expression(function.parameters[idx], param)
Пример #10
0
    def test_if_expression(self) -> None:
        source = '''
            si (x < y) { z }
        '''
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)
        program: Program = parser.parse_program()

        self._test_program_statement(parser, program)
        #Test correct node type
        if_expression = cast(If, cast(ExpressionStatement,
            program.statements[0]).expression)
        self.assertIsInstance(if_expression, If)

        #Test condition
        assert if_expression.condition is not None
        self._test_infix_expression(if_expression.condition, 'x','<','y')

        #Test consequence
        assert if_expression.consequence is not None
        self.assertIsInstance(if_expression.consequence, Block)
        self.assertEquals(len(if_expression.consequence.statements),1)
        
        consequence_statement = cast(ExpressionStatement,
            if_expression.consequence.statements[0])
        
        assert consequence_statement.expression is not None
        self._test_identifier(consequence_statement.expression, 'z')

        #Test alternative
        self.assertIsNone(if_expression.alternative)
Пример #11
0
    def test_parse_error(self) -> None:
        source: str = 'variable x 5'
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self.assertEquals(len(parser.errors), 1)
Пример #12
0
    def test_parse_program(self) -> None:
        source: str = 'variable x = 5;'
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self.assertIsNotNone(program)
        self.assertIsInstance(program, Program)
Пример #13
0
    def _evaluate_tests(self, source: str) -> Object:
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)
        program: Program = parser.parse_program()
        env: Environment = Environment()

        evaluated = evaluate(program, env)

        assert evaluated is not None
        return evaluated
Пример #14
0
    def test_identifier_expression(self) -> None:
        source: str = 'foobar;'
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statement(parser, program)

        expression_statement = cast(ExpressionStatement, program.statements[0])
        self._test_literal_expression(expression_statement.expression, 'foobar')
Пример #15
0
    def test_string_literal_expression(self) -> None:
        source: str = '"hello world!"'
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)
        program: Program = parser.parse_program()

        expression_ststement= cast(ExpressionStatement, program.statements[0])
        string_literal = cast(StringLiteral, expression_ststement.expression)

        self.assertIsInstance(string_literal, StringLiteral)
        self.assertEquals(string_literal.value, 'hello world!')
Пример #16
0
    def test_integer_expressions(self) -> None:
        source = str = '5';
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()
        #si hay un error en el parser este test no va a decir que hay un error
        self._test_program_statement(parser, program)
        
        exprassion_statement = cast(ExpressionStatement, program.statements[0])

        assert exprassion_statement.expression is not None
        self._test_literal_expression(exprassion_statement.expression, 5) 
    def test_integer_expressions(self) -> None:
        source: str = '5;'
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statements(parser, program)

        expression_statement = cast(ExpressionStatement, program.statements[0])

        assert expression_statement.expression is not None
        self._test_literal_expression(expression_statement.expression, 5)
Пример #18
0
    def test_boolean_expression(self) -> None:
        source: str = 'verdadero; falso;'
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statement(parser, program, expedted_statement_count=2)

        expected_values: List[bool] = [True,  False]

        for statement, expected_value in zip(program.statements, expected_values):
            expression_statement = cast(ExpressionStatement, statement)

            assert expression_statement is not None
            self._test_literal_expression(expression_statement.expression,
                                            expected_value)
Пример #19
0
    def test_infix_expression(self) -> None:
        source: str = '''
            5 + 5;
            5 - 5;
            5 * 5;
            5 / 5;
            5 > 5;
            5 < 5;
            5 == 5;
            5 != 5;
            falso == falso;
            verdadero != falso;
        ''' #TODO algo de booleano -- esto rompe verdadero == verdadero;

        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statement(parser, program, expedted_statement_count=10)

        expected_operators_and_values: List[Tuple[Any, str, Any]] = [
            (5,'+',5),
            (5,'-',5),
            (5,'*',5),
            (5,'/',5),
            (5,'>',5),
            (5,'<',5),
            (5,'==',5),
            (5,'!=',5),
            (False, '==', False),
            (True, '!=', False)
        ]

        for statement, (expected_left, expected_operator, expected_right) in zip(
            program.statements, expected_operators_and_values
        ):
            statement = cast(ExpressionStatement, statement)
            assert statement.expression is not None
            self.assertIsInstance(statement.expression, Infix)
            self._test_infix_expression(
                statement.expression,
                expected_left, 
                expected_operator, 
                expected_right
            )
Пример #20
0
def execute_program(scanned):
    
    lexer: Lexer = Lexer(" ".join(scanned))
    parser: Parser = Parser(lexer)

    program: Program = parser.parse_program()
    env: Environment = Environment()

    if len(parser.errors) > 0:
        _print_parse_errors(parser.errors)
        return 0

    evaluated = evaluate(program, env)

    if evaluated is not None:

        print(evaluated.inspect())

    return 1
Пример #21
0
    def test_let_statements(self) -> None:

        source: str = """
            variable x = 5;
            variable y = 10;
            variable foo = 20;
        """

        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self.assertEqual(len(program.statements), 3)

        for statement in program.statements:

            self.assertEqual(statement.token_literal(), "variable")
            self.assertIsInstance(statement, LetStatement)
Пример #22
0
def start_repl() -> None:
    scanned: List[str] = []

    while (source := input('>> ')) != 'salir()':
        scanned.append(source)
        lexer: Lexer = Lexer(' '.join(scanned))
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()
        env: Environment = Environment()

        if len(parser.errors) > 0:
            _print_parse_errors(parser.errors)
            continue

        evaluated = evaluate(program, env)

        if evaluated is not None:
            print(evaluated.inspect())
Пример #23
0
    def test_operator_precedence(self) -> None:

        # El primer string representa el programa inicial
        # El segundo string representa cuál debería ser el órden de precedencia
        # El tercer int representa cuántos statements esperamos que tenga el programa
        test_sources: List[Tuple[str, str, int]] = [
            ('-a * b;', '((-a) * b)', 1),
            ('!-a;', '(!(-a))', 1),
            ('a + b + c;', '((a + b) + c)', 1),
            ('a + b - c;', '((a + b) - c)', 1),
            ('a * b * c;', '((a * b) * c)', 1),
            ('a * b / c;', '((a * b) / c)', 1),
            ('a + b / c;', '(a + (b / c))', 1),
            ('a + b * c + d / e - f;', '(((a + (b * c)) + (d / e)) - f)', 1),
            ('3 + 4; -5 * 5;', '(3 + 4)((-5) * 5)', 2),
            ('5 > 4 == 3 < 4;', '((5 > 4) == (3 < 4))', 1),
            ('5 < 4 != 3 > 4;', '((5 < 4) != (3 > 4))', 1),
            ('3 + 4 * 5 == 3 * 1 + 4 * 5;', '((3 + (4 * 5)) == ((3 * 1) + (4 * 5)))', 1),
            ('verdadero;', 'verdadero', 1),
            ('falso;', 'falso', 1),
            ('3 > 5 == verdadero;', '((3 > 5) == verdadero)', 1),
            ('3 < 5 == falso;', '((3 < 5) == falso)', 1),

            ('1 + (2 + 3) + 4;', '((1 + (2 + 3)) + 4)', 1),
            ('(5 + 5) * 2;', '((5 + 5) * 2)', 1),
            ('2 / (5 + 5);', '(2 / (5 + 5))', 1),
            ('-(5 + 5);', '(-(5 + 5))', 1),
            ('a + suma(b * c) + d;', '((a + suma((b * c))) + d)', 1),

            ('suma(a, b, 1, 2 * 3, 4 + 5, suma(6, 7 * 8));',
             'suma(a, b, 1, (2 * 3), (4 + 5), suma(6, (7 * 8)))', 1),
            ('suma(a + b + c * d / f + g);', 'suma((((a + b) + ((c * d) / f)) + g))', 1),
        ]

        for source, expected_result, expected_statement_count in test_sources:

            lexer: Lexer = Lexer(source)
            parser: Parser = Parser(lexer)

            program: Program = parser.parse_program()
            
            self._test_program_statements(parser, program, expected_statement_count)
            self.assertEquals(str(program), expected_result)
    def test_names_in_let_statements(self) -> None:
        source: str = '''
            variable x = 5;
            variable y = 10;
            variable foo = 20;
        '''
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        names: List[str] = []
        for statement in program.statements:
            statement = cast(LetStatement, statement)
            assert statement.name is not None
            names.append(statement.name.value)

        expected_names: List[str] = ['x', 'y', 'foo']

        self.assertEquals(names, expected_names)
Пример #25
0
    def test_prefix_expression(self) -> None:
        source = '!5; -15; !falso; !verdadero'
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statement(parser, program, expedted_statement_count=4)

        for statement, (expected_operator, expected_value) in zip(
            program.statements, (['!',5],['-',15],['!',False],['!',True])
        ):
            statement = cast(ExpressionStatement, statement)
            self.assertIsInstance(statement.expression, Prefix)
        
            prefix = cast(Prefix, statement.expression)
            self.assertEquals(prefix.operator, expected_operator)

            assert prefix.right is not None
            self._test_literal_expression(prefix.right, expected_value)
Пример #26
0
    def test_call_expression(self) -> None:
        source: str = 'suma(1, 2 *3, 4+5);'
        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statement(parser, program)

        call = cast(Call, cast(ExpressionStatement,
            program.statements[0].expression))

        self.assertIsInstance(call, Call)
        self._test_identifier(call.function, 'suma')

        #Test arguments
        assert call.arguments is not None
        self.assertEquals(len(call.arguments), 3)
        self._test_literal_expression(call.arguments[0], 1)
        self._test_infix_expression(call.arguments[1], 2, '*', 3)
        self._test_infix_expression(call.arguments[2], 4, '+' , 5)
Пример #27
0
    def test_prefix_expression(self) -> None:
        
        source: str = "!5; -15; -verdadero; -falso"

        lexer: Lexer = Lexer(source)
        parser: Parser = Parser(lexer)

        program: Program = parser.parse_program()

        self._test_program_statements(parser, program, expected_statement_count=4)

        for statement, (expected_operator, expected_value) in zip(
            program.statements, [("!", 5), ("-", 15), ("-", True), ("-", False)]):

            statement = cast(ExpressionStatement, statement)
            self.assertIsInstance(statement.expression, Prefix)

            prefix = cast(Prefix, statement.expression)
            self.assertEquals(prefix.operator, expected_operator)

            assert prefix.right is not None
            self._test_literal_expression(prefix.right, expected_value)