Exemplo n.º 1
0
    def parse_type(self, type_token: Token = None):
        current = self.tr.current if type_token is None else type_token
        if current.token_type == TokenType.BLOCK_OPEN:  # List type
            return ListType(self.parse_balanced_brackets(current, self.parse_type, Token(TokenType.BLOCK_CLOSE, ']')))\
                .with_code_range(current.code_range)
        elif current.token_type == TokenType.PAREN_OPEN:  # Tuple type

            def f():
                try:
                    t1 = self.parse_type()
                except:
                    self.tr.skip_to(
                        Token(TokenType.COMMA,
                              ','))  # Skip to comma for error recovery
                    t1 = Error()
                self.tr.require_type(TokenType.COMMA)
                t2 = self.parse_type()
                code_range = CodeRange(t1.code_range.start, t2.code_range.end)
                return Tuple(t1, t2).with_code_range(code_range)

            return self.parse_balanced_brackets(
                current, f, Token(TokenType.PAREN_CLOSE, ')'))
        elif current.token_type == TokenType.IDENTIFIER:  # Type var
            if type_token is None:
                self.tr.read()
            return TypeVarType(current.value,
                               None).with_code_range(current.code_range)
        else:
            if type_token is None:
                self.tr.read()
            return self.parse_basic_type(current)
Exemplo n.º 2
0
    def parse_block(self):  # TODO order of var decls and stmts
        def f():
            start_range = self.tr.current_code_range()
            statements = []
            while self.tr.current_token_type() != TokenType.CURLY_CLOSE:
                stmt = self.parse_statement()
                statements.append(stmt)
            code_range = CodeRange(start_range.start,
                                   self.tr.current_code_range().end)
            return Block(statements).with_code_range(code_range)

        return self.parse_balanced_brackets(Token(TokenType.CURLY_OPEN,
                                                  '{'), f,
                                            Token(TokenType.CURLY_CLOSE, '}'))
Exemplo n.º 3
0
    def parse_fun_decl(self):
        try:
            token = self.tr.require_type(TokenType.IDENTIFIER)
        except:
            self.errors.append(ExpectedIdentError(self.tr.current))
            raise ParseError()
        name = Text(token.value).with_code_range(token.code_range)

        def parse_args():
            args = []
            while self.tr.current_token_type() != TokenType.PAREN_CLOSE:
                if len(args) > 0:
                    try:
                        self.tr.require_type(TokenType.COMMA)
                    except:
                        self.errors.append(
                            ExpectedSymbolError(',', self.tr.current))
                        raise ParseError()
                try:
                    t = self.tr.require_type(TokenType.IDENTIFIER)
                except:
                    self.errors.append(ExpectedIdentError(self.tr.current))
                    raise ParseError()
                args.append(Text(t.value).with_code_range(t.code_range))
            return FunArgNames(args)

        args = self.parse_balanced_brackets(Token(TokenType.PAREN_OPEN, '('),
                                            parse_args,
                                            Token(TokenType.PAREN_CLOSE, ')'))
        if self.tr.current_token_type() == TokenType.DOUBLECOLON:
            self.tr.read()
            fun_type = self.parse_fun_type()
        else:
            fun_type = None
        block = self.parse_block()
        try:
            assert isinstance(block, Error) or len(block.statements) > 0
        except:
            self.errors.append(
                EmptyFunctionBodyError(name.value, name.code_range))
        return FunDecl(name, args, fun_type, block,
                       None).with_code_range(name.code_range)
Exemplo n.º 4
0
 def f():
     try:
         t1 = self.parse_type()
     except:
         self.tr.skip_to(
             Token(TokenType.COMMA,
                   ','))  # Skip to comma for error recovery
         t1 = Error()
     self.tr.require_type(TokenType.COMMA)
     t2 = self.parse_type()
     code_range = CodeRange(t1.code_range.start, t2.code_range.end)
     return Tuple(t1, t2).with_code_range(code_range)
Exemplo n.º 5
0
 def parse_return_type(self):
     current = self.tr.current
     if current.token_type == TokenType.KEYWORD and current.value == 'Void':
         self.tr.read()
         return VoidReturn().with_code_range(current.code_range)
     else:
         try:
             t = self.parse_type()
         except:
             t = Error()
             self.tr.skip_to(
                 Token(TokenType.CURLY_OPEN,
                       '{'))  # try skipping to { and continue parsing
         return ValueReturn(t).with_code_range(
             CodeRange(current.code_range.start,
                       self.tr.current_code_range().end))
Exemplo n.º 6
0
 def parse_fun_type(self):
     start = self.tr.current_code_range().start
     args = []
     try:
         while self.tr.current_token_type() != TokenType.ARROW:
             args.append(self.parse_type())
     except:
         args.append(Error())
         current = self.tr.current
         self.tr.skip_to(Token(
             TokenType.ARROW,
             '->'))  # when error, try skipping to arrow and continue parse
     try:
         self.tr.require_type(TokenType.ARROW)
     except:
         self.errors.append(ExpectedSymbolError('->', current))
         raise ParseError()
     return_type = self.parse_return_type()
     code_range = CodeRange(start, self.tr.current_code_range().end)
     return FunctionType(FunArgs(args),
                         return_type).with_code_range(code_range)