// File: philpoore[P]Math/./src/Parser.cpp
// Function: Parser::parseExpr(int)
AstExpr* Parser::parseExpr(int precedence_level) {
    AstExpr* left;
    consumeWhiteSpace();
    if (peekIs(TOKEN_EOF) || peekIs(TOKEN_RCURLY)) {
        return nullptr;
    } else if (peekIs(TOKEN_LPAREN)) {
        expect(TOKEN_LPAREN);
        left = parseExpr();
        expect(TOKEN_RPAREN, "Unmatched parentheses");
    } else {
        left = parseSubExpr();
    }

    while (true) {
        consumeWhiteSpace();
        Token t = peek();
        if (t.type == TOKEN_SEMI) {
            break;
        }
        if (!t.isBinOp()) {
            break;
        }

        int p = precedence(Token_to_bin_op(t.type));

        if (p <= precedence_level) {
            break;
        }

        Token bin_op_token = consume();
        AstBinaryOp* bin_op = new AstBinaryOp(bin_op_token.type);

        bin_op->left = left;
        bin_op->right = parseExpr(p);
        assert(bin_op->right != nullptr);
        left = (AstExpr*)bin_op;
    }
    return left;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x180, %rsp            # imm = 0x180
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x158(%rbp)
callq 0x8dc0
movq -0x158(%rbp), %rdi
movl $0x112, %esi            # imm = 0x112
callq 0x8a20
testb $0x1, %al
jne 0x9c7e
movq -0x158(%rbp), %rdi
movl $0x10d, %esi            # imm = 0x10D
callq 0x8a20
testb $0x1, %al
jne 0x9c7e
jmp 0x9c8b
movq $0x0, -0x8(%rbp)
jmp 0xa002
movq -0x158(%rbp), %rdi
movl $0x10a, %esi            # imm = 0x10A
callq 0x8a20
testb $0x1, %al
jne 0x9ca5
jmp 0x9e06
leaq -0x71(%rbp), %rdi
movq %rdi, -0x160(%rbp)
callq 0x4500
movq -0x160(%rbp), %rdx
leaq 0xc830(%rip), %rsi      # 0x164f3
leaq -0x70(%rbp), %rdi
callq 0xbcf0
jmp 0x9cce
movq -0x158(%rbp), %rsi
leaq -0x50(%rbp), %rdi
movl $0x10a, %edx            # imm = 0x10A
leaq -0x70(%rbp), %rcx
callq 0x8ab0
jmp 0x9ce9
leaq -0x50(%rbp), %rdi
callq 0xcb70
leaq -0x70(%rbp), %rdi
callq 0x4200
leaq -0x71(%rbp), %rdi
callq 0x4340
movq -0x158(%rbp), %rdi
movl $0xffffd8f1, %esi       # imm = 0xFFFFD8F1
callq 0x9c30
movq %rax, -0x20(%rbp)
leaq -0xd9(%rbp), %rdi
movq %rdi, -0x168(%rbp)
callq 0x4500
movq -0x168(%rbp), %rdx
leaq 0xc6c6(%rip), %rsi      # 0x16400
leaq -0xd8(%rbp), %rdi
callq 0xbcf0
jmp 0x9d48
movq -0x158(%rbp), %rsi
leaq -0xb8(%rbp), %rdi
movl $0x10b, %edx            # imm = 0x10B
leaq -0xd8(%rbp), %rcx
callq 0x8ab0
jmp 0x9d69
leaq -0xb8(%rbp), %rdi
callq 0xcb70
leaq -0xd8(%rbp), %rdi
callq 0x4200
leaq -0xd9(%rbp), %rdi
callq 0x4340
jmp 0x9e16
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9dbb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x4200
leaq -0x71(%rbp), %rdi
callq 0x4340
jmp 0xa00f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9df5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x4200
leaq -0xd9(%rbp), %rdi
callq 0x4340
jmp 0xa00f
movq -0x158(%rbp), %rdi
callq 0xa710
movq %rax, -0x20(%rbp)
jmp 0x9e18
jmp 0x9e1a
movq -0x158(%rbp), %rdi
callq 0x8dc0
movq -0x158(%rbp), %rsi
leaq -0x110(%rbp), %rdi
xorl %edx, %edx
callq 0x88d0
cmpl $0x110, -0x110(%rbp)    # imm = 0x110
jne 0x9e56
movl $0x3, -0x114(%rbp)
jmp 0x9fc1
leaq -0x110(%rbp), %rdi
callq 0x5830
testb $0x1, %al
jne 0x9e75
movl $0x3, -0x114(%rbp)
jmp 0x9fc1
movl -0x110(%rbp), %edi
callq 0x7460
movl %eax, %edi
callq 0x7400
movl %eax, -0x118(%rbp)
movl -0x118(%rbp), %eax
cmpl -0x14(%rbp), %eax
jg 0x9ea7
movl $0x3, -0x114(%rbp)
jmp 0x9fc1
movq -0x158(%rbp), %rsi
leaq -0x148(%rbp), %rdi
callq 0x8a60
jmp 0x9ebc
movl $0x18, %edi
callq 0x42f0
movq %rax, -0x170(%rbp)
jmp 0x9ecf
movq -0x170(%rbp), %rdi
movl -0x148(%rbp), %esi
callq 0xd0f0
jmp 0x9ee3
movq -0x158(%rbp), %rdi
movq -0x170(%rbp), %rax
movq %rax, -0x150(%rbp)
movq -0x20(%rbp), %rcx
movq -0x150(%rbp), %rax
movq %rcx, 0x8(%rax)
movl -0x118(%rbp), %esi
callq 0x9c30
movq %rax, -0x178(%rbp)
jmp 0x9f1b
movq -0x178(%rbp), %rcx
movq -0x150(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x150(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0x9f3d
jmp 0x9fa0
leaq 0xc509(%rip), %rdi      # 0x1644d
leaq 0xc51b(%rip), %rsi      # 0x16466
movl $0x104, %edx            # imm = 0x104
leaq 0xc520(%rip), %rcx      # 0x16477
callq 0x4220
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9fec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9fe0
movq -0x170(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
movl $0x18, %esi
callq 0x4300
jmp 0x9fe0
movq -0x150(%rbp), %rax
movq %rax, -0x20(%rbp)
leaq -0x148(%rbp), %rdi
callq 0xcb70
movl $0x0, -0x114(%rbp)
leaq -0x110(%rbp), %rdi
callq 0xcb70
movl -0x114(%rbp), %eax
testl %eax, %eax
je 0x9fdb
jmp 0x9fd9
jmp 0x9ffa
jmp 0x9e1a
leaq -0x148(%rbp), %rdi
callq 0xcb70
leaq -0x110(%rbp), %rdi
callq 0xcb70
jmp 0xa00f
movq -0x20(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x180, %rsp            # imm = 0x180
popq %rbp
retq
movq -0x80(%rbp), %rdi
callq 0x44f0
nopl (%rax,%rax)