Beispiel #1
0
    def _unary(cls, tok: Token) -> Node:
        # unary = ("+" | "-") unary | primary
        if Tokenizer.equal(tok, "+"):
            return cls._unary(unwrap_optional(tok.next))

        if Tokenizer.equal(tok, "-"):
            return Node(NodeKind.ND_NEG, lhs=cls._unary(unwrap_optional(tok.next)))

        return cls._primary(tok)
Beispiel #2
0
    def _primary(cls, tok: Token) -> Node:
        # primary = "(" expr ")" | ident | num
        if Tokenizer.equal(tok, "("):
            node = cls._expr(unwrap_optional(tok.next))
            cls._rest = unwrap_optional(Tokenizer.skip(cls._rest, ")"))
            return node

        if tok.kind == TokenKind.TK_IDENT:
            node = Node(NodeKind.ND_VAR, name=cls._prog[tok.loc])
            cls._rest = unwrap_optional(tok.next)
            return node
        if tok.kind == TokenKind.TK_NUM:
            node = Node(NodeKind.ND_NUM, val=tok.val)
            cls._rest = unwrap_optional(tok.next)
            return node

        raise TokenError(tok, cls._prog, "expected an expression")
Beispiel #3
0
 def _assign(cls, tok: Token) -> Node:
     # assign = equality ("=" assign)?
     node = cls._equality(tok)
     if Tokenizer.equal(cls._rest, "="):
         node = Node(
             NodeKind.ND_ASSIGN,
             lhs=node,
             rhs=cls._assign(unwrap_optional(cls._rest.next)),
         )
     return node
Beispiel #4
0
    def _mul(cls, tok: Token) -> Node:
        # mul = unary ("*" unary | "/" unary)*
        node = cls._unary(tok)

        while True:
            if Tokenizer.equal(cls._rest, "/"):
                node = Node(
                    NodeKind.ND_DIV,
                    lhs=node,
                    rhs=cls._unary(unwrap_optional(cls._rest.next)),
                )
                continue
            if Tokenizer.equal(cls._rest, "*"):
                node = Node(
                    NodeKind.ND_MUL,
                    lhs=node,
                    rhs=cls._unary(unwrap_optional(cls._rest.next)),
                )
                continue

            return node
Beispiel #5
0
    def _equality(cls, tok: Token) -> Node:
        # equality = relational ("==" relational | "!=" relational)*
        node = cls._relational(tok)

        while True:
            if Tokenizer.equal(cls._rest, "=="):
                node = Node(
                    NodeKind.ND_EQ,
                    lhs=node,
                    rhs=cls._relational(unwrap_optional(cls._rest.next)),
                )
                continue

            if Tokenizer.equal(cls._rest, "!="):
                node = Node(
                    NodeKind.ND_NE,
                    lhs=node,
                    rhs=cls._relational(unwrap_optional(cls._rest.next)),
                )
                continue

            return node
Beispiel #6
0
    def _add(cls, tok: Token) -> Node:
        # add = mul ("+" mul | "-" mul)*``
        node = cls._mul(tok)

        while True:
            if Tokenizer.equal(cls._rest, "+"):
                node = Node(
                    NodeKind.ND_ADD,
                    lhs=node,
                    rhs=cls._mul(unwrap_optional(cls._rest.next)),
                )
                continue

            if Tokenizer.equal(cls._rest, "-"):
                node = Node(
                    NodeKind.ND_SUB,
                    lhs=node,
                    rhs=cls._mul(unwrap_optional(cls._rest.next)),
                )
                continue

            return node
Beispiel #7
0
    def _relational(cls, tok: Token) -> Node:
        # relational = add ("<" add | "<=" add | ">" add | ">=" add)*
        node = cls._add(tok)

        while True:
            if Tokenizer.equal(cls._rest, "<"):
                node = Node(
                    NodeKind.ND_LT,
                    lhs=node,
                    rhs=cls._add(unwrap_optional(cls._rest.next)),
                )
                continue

            if Tokenizer.equal(cls._rest, "<="):
                node = Node(
                    NodeKind.ND_LE,
                    lhs=node,
                    rhs=cls._add(unwrap_optional(cls._rest.next)),
                )
                continue

            if Tokenizer.equal(cls._rest, ">"):
                node = Node(
                    NodeKind.ND_LT,
                    lhs=cls._add(unwrap_optional(cls._rest.next)),
                    rhs=node,
                )
                continue

            if Tokenizer.equal(cls._rest, ">="):
                node = Node(
                    NodeKind.ND_LE,
                    lhs=cls._add(unwrap_optional(cls._rest.next)),
                    rhs=node,
                )
                continue

            return node
Beispiel #8
0
    def _gen_expr(cls, node: Node):
        if node.kind == NodeKind.ND_NUM:
            print(f"  mov ${node.val}, %rax")
            return
        elif node.kind == NodeKind.ND_VAR:
            cls._gen_addr(unwrap_optional(node))
            print("  mov (%rax), %rax")
            return
        elif node.kind == NodeKind.ND_ASSIGN:
            cls._gen_addr(unwrap_optional(node.lhs))
            cls._push()
            cls._gen_expr(unwrap_optional(node.rhs))
            cls._pop("%rdi")
            print("  mov %rax, (%rdi)")
            return
        elif node.kind == NodeKind.ND_NEG:
            cls._gen_expr(unwrap_optional(node.lhs))
            print("  neg %rax")
            return

        cls._gen_expr(unwrap_optional(node.rhs))
        cls._push()
        cls._gen_expr(unwrap_optional(node.lhs))
        cls._pop("%rdi")

        if node.kind == NodeKind.ND_ADD:
            print("  add %rdi, %rax")
        elif node.kind == NodeKind.ND_SUB:
            print("  sub %rdi, %rax")
        elif node.kind == NodeKind.ND_MUL:
            print("  imul %rdi, %rax")
        elif node.kind == NodeKind.ND_DIV:
            print("  cqo")
            print("  idiv %rdi")
        elif (node.kind == NodeKind.ND_EQ or node.kind == NodeKind.ND_NE
              or node.kind == NodeKind.ND_LT or node.kind == NodeKind.ND_LE):
            print("  cmp %rdi, %rax")
            if node.kind == NodeKind.ND_EQ:
                print("  sete %al")
            elif node.kind == NodeKind.ND_NE:
                print("  setne %al")
            elif node.kind == NodeKind.ND_LT:
                print("  setl %al")
            elif node.kind == NodeKind.ND_LE:
                print("  setle %al")
            print("  movzb %al, %rax")
        else:
            raise PyccError("invalid expression")
Beispiel #9
0
    def parse(cls, tok: Token, prog: str) -> Node:
        """Parses the tokens into an AST.

        Arg:
            tok: The head of the token list.
            prog: The program to be parsed.

        Returns:
            The root node of the AST.
        """

        cls._prog = prog
        cls._rest = tok

        head = Node(NodeKind.ND_EXPR_STMT)  # dummy node
        cur = head

        while cls._rest.kind != TokenKind.TK_EOF:
            cur.next = cls._stmt(cls._rest)
            cur = cur.next

        return unwrap_optional(head.next)
Beispiel #10
0
 def _expr_stmt(cls, tok: Token) -> Node:
     # expr-stmt = expr ";"
     node = Node(NodeKind.ND_EXPR_STMT, lhs=cls._expr(tok))
     cls._rest = unwrap_optional(Tokenizer.skip(cls._rest, ";"))
     return node
Beispiel #11
0
 def _gen_stmt(cls, node: Node):
     if node.kind == NodeKind.ND_EXPR_STMT:
         cls._gen_expr(unwrap_optional(node.lhs))
     else:
         raise PyccError("invalid statement")