Exemple #1
0
    def variable_declaration(self):
        """variable_declaration : ID (COMMA ID)* COLON type_spec
        VAR
            a : INTEGER;
            b : REAL;
        """

        var_nodes = [ast.Var(self.current_token)]
        self.eat(TokenType.ID)

        # while contain ',' just like var a,b,c : INTEGER;
        while self.current_token.type == TokenType.COMMA:
            self.eat(TokenType.COMMA)
            var_nodes.append(ast.Var(self.current_token))
            self.eat(TokenType.ID)
        # :
        self.eat(TokenType.COLON)

        # type special int or float
        type_node = self.type_spec()
        # [a, INTEGER], [b, INTEGER] [c, float]
        var_declarations = [
            ast.VarDecl(var_node, type_node) for var_node in var_nodes
        ]
        return var_declarations
Exemple #2
0
    def formal_parameters(self):
        """ formal_parameters : ID (COMMA ID)* COLON type_spec

        procedure's params, just like Foo(a, b : int)
        current process is a, b : int
        """
        param_nodes = []
        param_tokens = [self.current_token]
        self.eat(TokenType.ID)
        # while contain ','
        while self.current_token.type == TokenType.COMMA:
            self.eat(TokenType.COMMA)
            # add all ID
            param_tokens.append(self.current_token)
            self.eat(TokenType.ID)
        # eat ':'
        self.eat(TokenType.COLON)

        # start params type
        type_node = self.type_spec()
        for param_token in param_tokens:
            var = ast.Var(param_token)
            param_node = ast.Param(var, type_node)
            param_nodes.append(param_node)
        return param_nodes
Exemple #3
0
def p_cond(p):
    """cond : VAR LT NUM
            | VAR LE NUM
            | VAR EQ NUM
            | VAR NE NUM
            | VAR GT NUM
            | VAR GE NUM"""
    p[0] = comparison_dict[p[2]](ast.Var(p[1]), ast.Num(p[3]))
Exemple #4
0
    def parse_funcliteral(self, cur):
        name = None
        if self.cur.type == "id":
            name = ast.Value(self.cur.value)
            self.consume()

        args = self.funcargs()

        block = self.block()

        func = ast.Func(name, args, block).set_origin(cur)

        if name:
            v = ast.Var(str(name.value))
            self.addVar(v)
            return ast.Assign(v, func).set_origin(cur)
        else:
            return func
Exemple #5
0
    def parse_objectliteral(self, cur):
        obj = []

        if self.maybe("}"):
            return ast.Value(cur, EspDict())

        while not self.maybe("}"):
            tok = self.cur
            if tok.type in {"val", "id", "op"}:
                key = ast.Value(tok.value)
            elif tok.type == "kw":
                if tok.value in {"get", "set"}:
                    raise NotImplementedError("get/set")
                key = ast.Value(tok.value)
            elif tok.type == "punc":
                if tok.value == "[":
                    raise NotImplementedError("Computed properties")
                raise self.error(tok, "Unexpected punctuation")
            else:
                raise self.error(tok, f"Unknown token {tok!r}")

            key = key.set_origin(tok)

            self.consume()

            if self.peek("("):
                # Object method
                functok = self.cur
                args = self.funcargs()
                value = ast.Func(key, args, self.block()).set_origin(functok)
            elif self.maybe(":"):
                # Normal property
                value = self.expr()
            else:
                # NOTE: Doesn't work for computed properties
                value = ast.Var(key.value)

            obj.append((key, value))

            # Should commas be optional?
            self.maybe(",")

        return ast.ObjectLiteral(obj).set_origin(cur)
Exemple #6
0
 def parse_atom(self):
     token = self.get_token
     if token.tag == Token.LPAREN:
         e = self.parse_expr()
         self.expect(Token.RPAREN)
         return e
     elif token.tag == Token.NUMBER:
         return E.ArithLit(token.value)
     elif token.tag == Token.ID:
         # variable or funcall
         if self.peek.tag == Token.LPAREN:
             name = token.value
             self.expect(Token.LPAREN)
             args = self.parse_args()
             return E.FunCall(name, args)
         else:
             return E.Var(token.value)
     else:
         msg = f"Unexpected token: {token.tag}\n" \
             "Expected expression, namely one of LPAREN, " \
             "NUMBER or ID"
         raise ParseError(token, msg)
Exemple #7
0
 def variable(self):
     """variable : ID
     """
     node = ast.Var(self.current_token)
     self.eat(TokenType.ID)
     return node
Exemple #8
0
    def atom(self):
        if self.cur is None:
            return None

        cur = self.cur
        val = cur.value
        ct = cur.type

        # Exceptions which shouldn't be consumed
        if ct == "punc" and val in {")", ";", "}", "]"}:
            return None
        elif ct == "kw" and val in {"case", "else"}:
            return None

        self.consume()

        if ct == "val":
            return ast.Value(cur.value).set_origin(cur)
        elif ct == "str":
            return self.process_string(cur)

        elif ct == "id":
            v = ast.Var(cur.value).set_origin(cur)

            # Check string call
            s = self.maybe(type="str")
            if s:
                return ast.Call(v, [self.process_string(s)]).set_origin(s)

            return v
        elif ct == "punc":
            if val == "(":
                if self.maybe(")"):
                    return ast.Tuple([]).set_origin(cur)

                x = self.semichain()
                self.expect(")")
                return semiAsExpr(x)
            elif val == "{":
                return self.parse_objectliteral(cur)
            elif val == "[":
                return self.parse_listliteral(cur)
            #elif val == ")": pass
            #elif val == "}": pass
            # TODO: dot functions
            else:
                raise NotImplementedError(val)
        elif ct == "op":
            return self.parse_unary(cur)
        elif ct == "kw":
            if val == "if":
                return self.parse_if(cur)
            elif val == "proto":
                return self.parse_proto(cur)

            elif val == "import":
                return self.parse_import(cur)
            elif val == "loop":
                return self.parse_loop(cur)

            elif val == "while":
                cond, bl, th, el = self.parse_while()

                # Not account for el
                return ast.Loop(ast.Block(
                    [ast.If(cond, bl, ast.Branch("break"))]),
                                el=el).set_origin(cur)

            elif val == "for":
                return self.parse_for(cur)

            elif val == "switch":
                return self.parse_switch(cur)

            elif val in {"break", "continue", "redo"}:
                return ast.Branch(val).set_origin(cur)
                # Todo: targeted branches

            elif val in {"var", "const"}:
                return semiAsExpr(self.parse_declgroup(cur))

            elif val == "function":
                return self.parse_funcliteral(cur)

            elif val == "try":
                raise NotImplementedError("try")

            else:
                raise self.error(f"Unimplemented keyword {val}")

        raise self.error(f"Unknown token {val}")
Exemple #9
0
    def parse_declvar(self, mut):
        name = self.expect(type="id")
        v = ast.Var(name.value, mut).set_origin(name)
        self.addVar(v)

        return v
Exemple #10
0
    def parse_proto(self, cur):
        # TODO: anonymous proto

        name = self.maybe(type="id")

        if self.maybe("is"):
            parent = self.relaxid()
        else:
            parent = None

        self.expect("{")

        pub = []
        priv = []
        stat = []

        while not self.maybe("}"):
            qual = self.maybe({"public", "var", "private", "static"})
            member = self.maybe(type="id")

            if self.maybe("("):
                params = self.listing(",", self.lvalue)
                self.expect(")")

                body = self.block()

                members = [
                    ast.Func(member.value, params, body).set_origin(member)
                ]
            else:
                members = [ast.Var(member.value).set_origin(member)]

                while self.maybe(","):
                    mem = self.maybe(type="id")
                    if mem is None:
                        raise RuntimeError("None name")

                    members.append(ast.Var(mem, mem.value))

            if not qual or qual.value in {"public", "var"}:
                pub += members
            elif qual.value == "private":
                priv += members
            elif qual.value == "static":
                stat += members
            else:
                raise RuntimeError("Shouldn't happen")

            while self.maybe(";"):
                pass

        name = name.value if name else None

        p = ast.Proto(name, parent, pub, priv, stat).set_origin(cur)

        if name is None:
            return p
        else:
            v = ast.Var(name, mutable=False)
            self.addVar(v)
            return ast.Assign(cur, v, p)
Exemple #11
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
Exemple #12
0
def p_expr_4(p):
    """expr : VAR"""
    p[0] = ast.Var(p[1])
Exemple #13
0
def p_comm_2(p):
    """comm : VAR ASSIGN expr"""
    p[0] = ast.Assign(ast.Var(p[1]), p[3])