// File: jaldhar[P]Lets-Build-a-Simple-Interpreter/calc2.cc
// Function: Interpreter::expression()
long Interpreter::expression() {

    // set current token to the first token taken from the input
    _current_token = get_next_token();

    // we expect the current token to be an integer
    Token left = _current_token;
    eat(TOKENTYPE::INTEGER);

    long result = left.value;
    // loop while we still have tokens
    while(_current_token.type != TOKENTYPE::ENDOFFILE) {
        // we expect the current token to be an operator token
        switch(_current_token.type) {
        case TOKENTYPE::MINUS:
            eat(TOKENTYPE::MINUS);
            result = subtract(result);
            break;
        case TOKENTYPE::PLUS:
            eat(TOKENTYPE::PLUS);
            result = add(result);
            break;
        case TOKENTYPE::TIMES:
            eat(TOKENTYPE::TIMES);
            result = multiply(result);
            break;
        case TOKENTYPE::DIVIDE:
            eat(TOKENTYPE::DIVIDE);
            result = divide(result);
            break;
        case TOKENTYPE::ENDOFFILE:
            break;
        default:
            ostringstream out;
            out << "Error parsing input. Wanted operator, got: "
                << _current_token.type;
            throw(out.str().c_str());
        }
    }

    return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x210, %rsp            # imm = 0x210
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x1e8(%rbp)
callq 0x28c0
movq -0x1e8(%rbp), %rdi
movl %eax, -0x18(%rbp)
movq %rdx, -0x10(%rbp)
movq -0x18(%rbp), %rax
movq %rax, 0x18(%rdi)
movq -0x10(%rbp), %rax
movq %rax, 0x20(%rdi)
movq 0x18(%rdi), %rax
movq %rax, -0x28(%rbp)
movq 0x20(%rdi), %rax
movq %rax, -0x20(%rbp)
movl $0x1, %esi
callq 0x2c10
movq -0x20(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x1e8(%rbp), %rax
cmpl $0x0, 0x18(%rax)
je 0x2898
movq -0x1e8(%rbp), %rax
movl 0x18(%rax), %eax
movq %rax, -0x1f0(%rbp)
subq $0x5, %rax
ja 0x277f
movq -0x1f0(%rbp), %rax
leaq 0x1953(%rip), %rcx      # 0x401c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x1e8(%rbp), %rdi
movl $0x3, %esi
callq 0x2c10
movq -0x1e8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x2d90
movq %rax, -0x30(%rbp)
jmp 0x2893
movq -0x1e8(%rbp), %rdi
movl $0x2, %esi
callq 0x2c10
movq -0x1e8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x2dd0
movq %rax, -0x30(%rbp)
jmp 0x2893
movq -0x1e8(%rbp), %rdi
movl $0x4, %esi
callq 0x2c10
movq -0x1e8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x2e10
movq %rax, -0x30(%rbp)
jmp 0x2893
movq -0x1e8(%rbp), %rdi
movl $0x5, %esi
callq 0x2c10
movq -0x1e8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x2e50
movq %rax, -0x30(%rbp)
jmp 0x2893
jmp 0x2893
leaq -0x1a8(%rbp), %rdi
movq %rdi, -0x200(%rbp)
callq 0x2220
movq -0x200(%rbp), %rdi
leaq 0x18c9(%rip), %rsi      # 0x4069
callq 0x2180
movq %rax, -0x1f8(%rbp)
jmp 0x27ae
movq -0x1f8(%rbp), %rdi
movq -0x1e8(%rbp), %rsi
addq $0x18, %rsi
callq 0x2450
jmp 0x27c7
movb $0x1, -0x1d9(%rbp)
movl $0x8, %edi
callq 0x20c0
movq %rax, -0x208(%rbp)
leaq -0x1d8(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x2190
jmp 0x27f4
leaq -0x1d8(%rbp), %rdi
callq 0x20a0
movq -0x208(%rbp), %rdi
movq %rax, (%rdi)
movb $0x0, -0x1d9(%rbp)
movq 0x3798(%rip), %rsi      # 0x5fb0
xorl %eax, %eax
movl %eax, %edx
callq 0x22a0
jmp 0x28b1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1b0(%rbp)
movl %eax, -0x1b4(%rbp)
jmp 0x2885
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1b0(%rbp)
movl %eax, -0x1b4(%rbp)
jmp 0x286c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1b0(%rbp)
movl %eax, -0x1b4(%rbp)
leaq -0x1d8(%rbp), %rdi
callq 0x20e0
testb $0x1, -0x1d9(%rbp)
jne 0x2877
jmp 0x2883
movq -0x208(%rbp), %rdi
callq 0x2120
jmp 0x2885
leaq -0x1a8(%rbp), %rdi
callq 0x2070
jmp 0x28a5
jmp 0x268f
movq -0x30(%rbp), %rax
addq $0x210, %rsp            # imm = 0x210
popq %rbp
retq
movq -0x1b0(%rbp), %rdi
callq 0x22b0
nopw %cs:(%rax,%rax)