Ejemplo n.º 1
0
 def test_precedence(self):
     buf = """
     fn prec() -> int {
       2 + 3 * 2 + 2 / 8;
     }
     """
     exprs = [
         ast.Function(
             "prec",
             [],
             [
                 ast.ExprStatement(
                     ast.BinaryOp(
                         ast.BinaryOp(
                             ast.Number(2),
                             ast.BinaryOp(ast.Number(3), ast.Number(2),
                                          Token(TokenType.MULTIPLY, "*")),
                             Token(TokenType.ADD, "+"),
                         ),
                         ast.BinaryOp(ast.Number(2), ast.Number(8),
                                      Token(TokenType.DIVIDE, "/")),
                         Token(TokenType.ADD, "+"),
                     ))
             ],
             ast.Type(ast.TypeKind.INT),
         )
     ]
     self._test_parse_impl(buf, exprs)
Ejemplo n.º 2
0
 def _const_decl():
     self._expect(Token('IDENTIFIER', None))
     record.name = self.current_token.value
     self._forward()
     self._expect(Token(None, '='))
     self._forward()
     self._expect(Token('NUMBER', None))
     record.value = int(self.current_token.value)
     self.table.enter(record)
     self._forward()
Ejemplo n.º 3
0
 def _procedure():
     record = Record('procedure', None, None, self.current_level)
     while self.current_token.value == 'procedure':
         self._forward()
         self._expect(Token('IDENTIFIER', None))
         record.name = self.current_token.value
         self.table.enter(record)
         self._forward()
         self._expect(Token(None, ';'))
         self._forward()
         self._block(3)
         self._expect(Token(None, ';'))
         self._forward()
Ejemplo n.º 4
0
 def test_while_loop(self):
     buf = """
     fn loopTest(int x) -> int {
       while (x < 5) {
         print("blah");
       }
       return 0;
     }
     """
     exprs = [
         ast.Function(
             "loopTest",
             [("x", ast.Type(ast.TypeKind.INT))],
             [
                 ast.WhileLoop(
                     ast.BinaryOp(ast.VariableRef("x"), ast.Number(5),
                                  Token(TokenType.LESS_THAN, "<")),
                     [
                         ast.ExprStatement(
                             ast.FunctionCall("print",
                                              [ast.String("blah")]))
                     ],
                 ),
                 ast.ReturnStatement(ast.Number(0)),
             ],
             ast.Type(ast.TypeKind.INT),
         )
     ]
     self._test_parse_impl(buf, exprs)
Ejemplo n.º 5
0
 def test_if_statements(self):
     buf = """
     fn foo() -> string {
       if (3 == 3) {
         return "foo";
       }
       return "bar";
     }
     """
     exprs = [
         ast.Function(
             "foo",
             [],
             [
                 ast.IfStatement(
                     ast.BinaryOp(ast.Number(3), ast.Number(3),
                                  Token(TokenType.EQUALS, "==")),
                     [ast.ReturnStatement(ast.String("foo"))],
                     list(),
                 ),
                 ast.ReturnStatement(ast.String("bar")),
             ],
             ast.Type(ast.TypeKind.STRING),
         )
     ]
     self._test_parse_impl(buf, exprs)
Ejemplo n.º 6
0
 def _var_decl():
     nonlocal dx
     self._expect(Token('IDENTIFIER', None))
     record.name = self.current_token.value
     record.address = dx
     dx += 1
     self.table.enter(record)
     self._forward()
Ejemplo n.º 7
0
 def _program(self):
     """ The following is rec-descent parser.
     Each handler will move forward 1 token before return, therefore self.current_token is assigned at
     the beginning of each function.
     """
     self._forward()
     self.table.enter(Record())
     self._block(3)
     self._expect(Token(None, '.'))
Ejemplo n.º 8
0
 def _factor(self):
     if self.current_token.type == 'IDENTIFIER':
         record = self.table.get(self.current_token.value)
         if record.type == 'const':
             self.pcode.gen(OpCode.LIT, 0, record.value)
         elif record.type == 'var':
             self.pcode.gen(OpCode.LOD, self.current_level - record.level,
                            record.address)
         elif record.type == 'procedure':
             raise ParserError('Wrong variable type')
         self._forward()
     elif self.current_token.type == 'NUMBER':
         self.pcode.gen(OpCode.LIT, 0, int(self.current_token.value))
         self._forward()
     else:
         self._expect(Token(None, '('))
         self._forward()
         self._expression()
         self._expect(Token(None, ')'))
         self._forward()
Ejemplo n.º 9
0
        def _var():
            def _var_decl():
                nonlocal dx
                self._expect(Token('IDENTIFIER', None))
                record.name = self.current_token.value
                record.address = dx
                dx += 1
                self.table.enter(record)
                self._forward()

            record = Record('var', None, None, self.current_level)
            self._expect(Token(None, 'var'))
            self._forward()
            while True:
                _var_decl()
                if self.current_token.value == ',':
                    self._forward()
                else:
                    break
            self._expect(Token(None, ';'))
            self._forward()
            return dx
Ejemplo n.º 10
0
 def test_dot_operator(self):
     buf = """
     print(foo.bar);
     """
     tokens = [
         Token(TokenType.IDENTIFIER, "print"),
         Token(TokenType.L_BRACKET, "("),
         Token(TokenType.IDENTIFIER, "foo"),
         Token(TokenType.DOT, "."),
         Token(TokenType.IDENTIFIER, "bar"),
         Token(TokenType.R_BRACKET, ")"),
         Token(TokenType.SEMICOLON, ";"),
         Token(TokenType.EOF, str()),
     ]
     self._test_lex_impl(buf, tokens)
Ejemplo n.º 11
0
        def _const():
            def _const_decl():
                self._expect(Token('IDENTIFIER', None))
                record.name = self.current_token.value
                self._forward()
                self._expect(Token(None, '='))
                self._forward()
                self._expect(Token('NUMBER', None))
                record.value = int(self.current_token.value)
                self.table.enter(record)
                self._forward()

            record = Record('const', None, None, 0)
            self._expect(Token(None, 'const'))
            self._forward()
            while True:
                _const_decl()
                if self.current_token.value == ',':
                    self._forward()
                else:
                    break
            self._expect(Token(None, ';'))
            self._forward()
Ejemplo n.º 12
0
 def _condition(self):
     if self.current_token.value == 'odd':
         self._forward()
         self._expression()
         self.pcode.gen(OpCode.OPR, 0, 6)
     else:
         self._expression()
         self._expect(Token('RELATIONAL_OPERATOR', None))
         op = self.current_token.value
         self._forward()
         self._expression()
         if op == '=':
             self.pcode.gen(OpCode.OPR, 0, 7)
         elif op == '<>':
             self.pcode.gen(OpCode.OPR, 0, 8)
         elif op == '<':
             self.pcode.gen(OpCode.OPR, 0, 9)
         elif op == '>=':
             self.pcode.gen(OpCode.OPR, 0, 10)
         elif op == '>':
             self.pcode.gen(OpCode.OPR, 0, 11)
         elif op == '<=':
             self.pcode.gen(OpCode.OPR, 0, 12)
Ejemplo n.º 13
0
    def _statement(self):
        if self.current_token.type == 'IDENTIFIER':
            record = self.table.get(self.current_token.value, 'var')
            self._forward()
            self._expect(Token(None, ':='))
            self._forward()
            self._expression()
            self.pcode.gen(OpCode.STO, self.current_level - record.level,
                           record.address)

        elif self.current_token.value == 'if':
            self._forward()
            self._condition()
            self._expect(Token(None, 'then'))
            self._forward()
            code1 = len(self.pcode)
            self.pcode.gen(OpCode.JPC, 0, 0)
            self._statement()  # then statement
            code2 = len(self.pcode)
            self.pcode.gen(OpCode.JMP, 0, 0)
            if self.current_token.value == 'else':
                self._forward()
                self.pcode[code1].a = len(self.pcode)
                self._statement()  # else statement
            else:
                self.pcode[code1].a = len(self.pcode)
            self.pcode[code2].a = len(self.pcode)

        elif self.current_token.value == 'while':
            code1 = len(self.pcode)
            self._forward()
            self._condition()
            code2 = len(self.pcode)
            self.pcode.gen(OpCode.JPC, 0, 0)
            self._expect(Token(None, 'do'))
            self._forward()
            self._statement()
            self.pcode.gen(OpCode.JMP, 0, code1)
            self.pcode[code2].a = len(self.pcode)

        elif self.current_token.value == 'call':
            self._forward()
            self._expect(Token('IDENTIFIER', None))
            record = self.table.get(self.current_token.value, 'procedure')
            self.pcode.gen(OpCode.CAL, self.current_level - record.level,
                           record.address)
            self._forward()

        elif self.current_token.value == 'begin':
            self._forward()
            self._statement()
            while self.current_token.value == ';':
                self._forward()
                self._statement()
            self._expect(Token(None, 'end'))
            self._forward()

        elif self.current_token.value == 'repeat':
            self._forward()
            code1 = len(self.pcode)
            self._statement()
            while self.current_token.value == ';':
                self._forward()
                self._statement()
            self._expect(Token(None, 'until'))
            self._forward()
            self._condition()
            self.pcode.gen(OpCode.JPC, 0, code1)

        elif self.current_token.value == 'read':
            self._forward()
            self._expect(Token(None, '('))
            self._forward()
            while True:
                self._expect(Token('IDENTIFIER', None))
                record = self.table.get(self.current_token.value, 'var')
                self.pcode.gen(OpCode.RED, self.current_level - record.level,
                               record.address)
                self._forward()
                if self.current_token.value != ',':
                    break
                else:
                    self._forward()
            self._expect(Token(None, ')'))
            self._forward()

        elif self.current_token.value == 'write':
            self._forward()
            self._expect(Token(None, '('))
            self._forward()
            while True:
                self._expression()
                self.pcode.gen(OpCode.WRT, 0, 0)
                if self.current_token.value != ',':
                    break
                else:
                    self._forward()
            self._expect(Token(None, ')'))
            self._forward()
Ejemplo n.º 14
0
    def test_lexer_on_inputfile(self):
        path = self.__get_path("example.nl")
        with open(path, "r") as f:
            lexer = Lexer(inFile=f)
        expected_tokens = [
            Token('ID', 'x', 1),
            Token('ASSIGN', '=', 1),
            Token('NUMBER', 4, 1),
            Token('SEMICOLON', ';', 1),
            Token('FUNC', 'func', 2),
            Token('ID', 'random', 2),
            Token('LPAREN', '(', 2),
            Token('RPAREN', ')', 2),
            Token('INT', 'int', 2),
            Token('LBRACE', '{', 2),
            Token('RETURN', 'return', 3),
            Token('NUMBER', '5', 3),
            Token('SEMICOLON', ';', 3),
            Token('RBRACE', '}', 4)
        ]

        for i in range(0, len(lexer.tokens)):
            self.assertEqual(expected_tokens[i], lexer.tokens[i])
Ejemplo n.º 15
0
 def test_control_flow(self):
     buf = """
     if (x == 3) {
       let y = 3;
     }
     """
     tokens = [
         Token(TokenType.IF, "if"),
         Token(TokenType.L_BRACKET, "("),
         Token(TokenType.IDENTIFIER, "x"),
         Token(TokenType.EQUALS, "=="),
         Token(TokenType.NUMBER_LITERAL, "3"),
         Token(TokenType.R_BRACKET, ")"),
         Token(TokenType.L_BRACE, "{"),
         Token(TokenType.LET, "let"),
         Token(TokenType.IDENTIFIER, "y"),
         Token(TokenType.ASSIGN, "="),
         Token(TokenType.NUMBER_LITERAL, "3"),
         Token(TokenType.SEMICOLON, ";"),
         Token(TokenType.R_BRACE, "}"),
         Token(TokenType.EOF, str()),
     ]
     self._test_lex_impl(buf, tokens)
Ejemplo n.º 16
0
 def test_function_w_args(self):
     buf = """
     fn foo(int one, string two) -> int {
       print("blah");
     };
     """
     tokens = [
         Token(TokenType.FUNCTION, "fn"),
         Token(TokenType.IDENTIFIER, "foo"),
         Token(TokenType.L_BRACKET, "("),
         Token(TokenType.INT, "int"),
         Token(TokenType.IDENTIFIER, "one"),
         Token(TokenType.COMMA, ","),
         Token(TokenType.STRING, "string"),
         Token(TokenType.IDENTIFIER, "two"),
         Token(TokenType.R_BRACKET, ")"),
         Token(TokenType.ARROW, "->"),
         Token(TokenType.INT, "int"),
         Token(TokenType.L_BRACE, "{"),
         Token(TokenType.IDENTIFIER, "print"),
         Token(TokenType.L_BRACKET, "("),
         Token(TokenType.STRING_LITERAL, "blah"),
         Token(TokenType.R_BRACKET, ")"),
         Token(TokenType.SEMICOLON, ";"),
         Token(TokenType.R_BRACE, "}"),
         Token(TokenType.SEMICOLON, ";"),
         Token(TokenType.EOF, str()),
     ]
     self._test_lex_impl(buf, tokens)
Ejemplo n.º 17
0
 def test_struct(self):
     buf = """
     struct Foo {
       int id = 3;
       string name;
       fn foo() -> int {
         return 3;
       }
     };
     """
     tokens = [
         Token(TokenType.STRUCTURE, "struct"),
         Token(TokenType.IDENTIFIER, "Foo"),
         Token(TokenType.L_BRACE, "{"),
         Token(TokenType.INT, "int"),
         Token(TokenType.IDENTIFIER, "id"),
         Token(TokenType.ASSIGN, "="),
         Token(TokenType.NUMBER_LITERAL, "3"),
         Token(TokenType.SEMICOLON, ";"),
         Token(TokenType.STRING, "string"),
         Token(TokenType.IDENTIFIER, "name"),
         Token(TokenType.SEMICOLON, ";"),
         Token(TokenType.FUNCTION, "fn"),
         Token(TokenType.IDENTIFIER, "foo"),
         Token(TokenType.L_BRACKET, "("),
         Token(TokenType.R_BRACKET, ")"),
         Token(TokenType.ARROW, "->"),
         Token(TokenType.INT, "int"),
         Token(TokenType.L_BRACE, "{"),
         Token(TokenType.RETURN, "return"),
         Token(TokenType.NUMBER_LITERAL, "3"),
         Token(TokenType.SEMICOLON, ";"),
         Token(TokenType.R_BRACE, "}"),
         Token(TokenType.R_BRACE, "}"),
         Token(TokenType.SEMICOLON, ";"),
         Token(TokenType.EOF, str()),
     ]
     self._test_lex_impl(buf, tokens)