Esempio n. 1
0
def parse_let_family(tp: ast.Tuple) -> ast.Node:
    if len(tp.elements) < 3:
        raise ParseError(
            f'{tp.elements[0]}: bad syntax, no expression in body')
    elem = tp.elements[1]
    if not isinstance(elem, ast.Tuple):
        raise ParseError(
            f'{tp.elements[0]}: bad syntax, expected bindings, given: {elem}')
    bindings: List[Node] = elem.elements
    patterns: List[ast.Name] = []
    exprs: List[Node] = []
    for i, binding in enumerate(bindings):
        if isinstance(binding, ast.Tuple):
            if len(binding.elements) == 2:
                if isinstance(binding.elements[0], ast.Name):
                    patterns.append(binding.elements[0])
                    exprs.append(parse_node(binding.elements[1]))
                    continue
        raise ParseError(
            f'{tp.elements[0]}: bad syntax, not an identifer and expression for a binding {binding}'
        )
    body = ast.Block(parse_list(tp.elements[2:]))
    name = tp.elements[0]
    if not isinstance(name, ast.Name):
        raise ParseError(f'expected a Name, given {name}')
    if name.identifier == constants.LET:
        return ast.Let(patterns, exprs, body)
    elif name.identifier == constants.LET_STAR:
        return ast.LetStar(patterns, exprs, body)
    elif name.identifier == constants.LET_REC:
        return ast.LetRec(patterns, exprs, body)
    else:
        raise ParseError(f'{tp.elements[0]}: should not be here')
Esempio n. 2
0
    def let(self):
        self.lexer.match("let")
        name = self.lexer.match_type(TokenType.Ident)
        self.lexer.match("=")
        value = self.expr()

        return ast.Let(name, value)
Esempio n. 3
0
 def p_inner_lets_initialized(self, parse):
     '''
     nested_lets : ID COLON TYPE ASSIGN expression IN expression
                 | nested_lets COMMA ID COLON TYPE ASSIGN expression
     '''
     parse[0] = AST.Let(instance=parse[1],
                        return_type=parse[3],
                        expression=parse[5],
                        body=parse[7])
Esempio n. 4
0
 def p_inner_lets_simple(self, parse):
     '''
     nested_lets : ID COLON TYPE IN expression
                 | nested_lets COMMA ID COLON TYPE
     '''
     parse[0] = AST.Let(instance=parse[1],
                        return_type=parse[3],
                        expression=None,
                        body=parse[5])
Esempio n. 5
0
 def p_expression_let_initialized(self, parse):
     '''
     let_expression : LET ID COLON TYPE ASSIGN expression IN expression
                    | nested_lets COMMA LET ID COLON TYPE ASSIGN expression
     '''
     parse[0] = AST.Let(instance=parse[2],
                        return_type=parse[4],
                        expression=parse[6],
                        body=parse[8])
Esempio n. 6
0
 def p_expression_let_simple(self, parse):
     '''
     let_expression : LET ID COLON TYPE IN expression
                    | nested_lets COMMA LET ID COLON TYPE
     '''
     parse[0] = AST.Let(instance=parse[2],
                        return_type=parse[4],
                        expression=None,
                        body=parse[6])
Esempio n. 7
0
 def let_stmt(self) -> ast.Let:
     toks = TokenList()
     toks.add(self.peek()) # Add 'let' token itself for correct begin
     var_names, var_types = self.let_lhs() # Writes variable names to symbol table
     if not toks.add(self.match(token.ASSIGN)):
         raise ParseException("Empty let statements are not supported. Always assign a value!")
     expr : typing.Union[ast.ExpressionList, ast.AssignOp] = self.assignment()
     toks.add(self.match(token.SEMICOLON))
     return ast.Let(toks, var_names, var_types, expr, self.symbol_tree.take_snapshot())
Esempio n. 8
0
    def parse_let(self, token, frame):
        """Parse Let expression"""
        if len(frame) < 2:
            _malformed(token)
        # Resolve first as return val versus args
        letres = None
        letargs = None
        letexpr = None

        if isinstance(frame[0], ast.Symbol):
            letres = frame.pop(0)
        else:
            sp = token.getsourcepos()
            lsym = "let_" + str(sp.lineno) + "_" + str(sp.colno)
            letres = ast.Symbol(lsym,
                                Token("LET_RES", lsym, token.getsourcepos()),
                                self.input)

        if isinstance(frame[0], ast.CollectionAst):
            letargs = frame.pop(0)
        else:
            _panic(
                "{}:{} Let expects local argument pair(s) signature [...] {}",
                token)

        if letargs.ctype != CollTypes.LIST:
            _panic(
                "{}:{} Invalid let argument pair(s) type. Should be [...] {}",
                token)

        if len(frame) < 1:
            _panic("{}:{} Missing Let expression {}", token)

        letexpr = [frame.pop(0)]
        letargs = ast.LetPairs(letargs, token, self.input)
        _check_no_declarations(token, letexpr, self._decl_set)
        frame.insert(0, ast.Let(letres, letargs, letexpr, token, self.input))
        return frame
Esempio n. 9
0
 def p_expression_let_list(self, parse):
     """
      let_expression : LET formal_list IN expression
     """
     parse[0] = AST.Let(declarations=parse[2], body=parse[4])
Esempio n. 10
0
    def statement(self):
        if self.match("let"):
            line = self.pop().line

            ty = self.type()
            if self.match_val("="):
                name = ty[1]
                ty = None
                #this is where more complete type parsing would happen
                #for the time being, just error out
            elif self.match("ident"):
                name = self.pop().val
            else:
                raise ValueError(
                    f"expected type in var declaration on line {line}, saw {self.tl[0].val}"
                )
            self.consume(
                "=",
                f"expected '=' in let declaration on line {line}, saw {self.tl[0].val}"
            )
            ex = self.expr()
            if ty != None:
                return ast.Let(name, (ty, None), ex)
            else:
                return ast.Let(name, None, ex)

        elif self.match("var"):
            line = self.pop().line
            ty = self.type()
            if self.match_val("="):
                name = ty[0]
                ty = None
                #this is where more complete type parsing would happen
                #for the time being, just error out
            elif self.match("ident"):
                name = self.pop().val
            else:
                raise ValueError(
                    f"expected type in var declaration on line {line}, saw {self.tl[0].val}"
                )

            self.consume(
                "=",
                f"expected '=' in var declaration on line {line}, saw {self.tl[0].val}"
            )
            ex = self.expr()
            return ast.Var(name, ty, ex)
        elif self.match("if"):
            line = self.pop().line
            ex = self.expr()
            thenstmnts = self.statementlist("if statement", line)
            if not self.match("else"):
                elsestmnts = None
            else:
                line = self.pop().line
                elsestmnts = self.statementlist("else statement", line)
            return ast.If(ex, thenstmnts, elsestmnts)
        elif self.match('return'):
            self.pop()
            returning = self.expr()
            return ast.Return(returning)
        elif self.match('while'):
            line = self.pop().line
            condition = self.expr()
            body = self.statementlist("while body", line)
            return ast.While(condition, body)
        else:
            lhs = self.expr()
            if self.match_val('=') or self.match_val('+=') or self.match_val(
                    '-=') or self.match_val('*=') or self.match_val(
                        '/=') or self.match_val('%='):
                op = self.pop().val
                rhs = self.expr()
                if (op[0] != '='):
                    rhs = ast.Binary(lhs, op[0], rhs)
                return ast.Assign(lhs, rhs)
            else:
                return lhs