// File: taurheim[P]AgNES/parser.cpp
// Function: Parser::expression()
ASTNode * Parser::expression() {
    /*
        "-" <expression>
        | "!" <expression>
        | "(" <expression> ")"
        | <number>
        | <character>
        | <string>
        | <identifier> "(" [ <expression> { "," <expression> }] ")" 
        | <identifier>  "[" <expression> "]"
        | <identifier>
        | <expression> <binaryOperation> <expression>
    */
    ASTNode * node = new ASTNode(AST_EXPRESSION);

    switch(t.type) {
        case T_INTVALUE: {
            ASTNode * numberNode = number();
            if (t.type == T_PLUS || t.type == T_MINUS) {
                ASTNode * expressionNode = new ASTNode(AST_EXPRESSION);
                expressionNode->children.push_back(numberNode);
                node->children.push_back(expressionNode);
            } else {
                node->children.push_back(numberNode);
            }
            break;
        }
        case T_CHARVALUE: {
            ASTNode * charNode = character();
            node->children.push_back(charNode);
            break;
        }
        case T_IDENT: {
            ASTNode * identNode = identifier();
            if (t.type == T_PLUS || t.type == T_MINUS) {
                ASTNode * expressionNode = new ASTNode(AST_EXPRESSION);
                expressionNode->children.push_back(identNode);
                node->children.push_back(expressionNode);
            } else {
                node->children.push_back(identNode);
            }
            break;
        }
        case T_LPAREN: {
            expect(T_LPAREN);
            node->children.push_back(expression());
            expect(T_RPAREN);
            break;
        }
        default: {
            reject("Expression expected T_IDENT or T_INTVALUE");
        }
    }

    if(t.type == T_PLUS || t.type == T_MINUS) {
        node->children.push_back(op());
        node->children.push_back(expression());
    } else if (t.type == T_LPAREN) {
        // Function call
    }

    return node;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xa8(%rbp)
movl $0x20, %edi
callq 0x3300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xa0(%rbp)
movl $0xb, %esi
callq 0x14270
jmp 0x12a0d
movq -0xa8(%rbp), %rax
movq -0xa0(%rbp), %rcx
movq %rcx, -0x10(%rbp)
movl 0x18(%rax), %eax
addl $-0x4, %eax
movl %eax, %ecx
movq %rcx, -0xb0(%rbp)
subl $0xd, %eax
ja 0x12c54
movq -0xb0(%rbp), %rax
leaq 0x1193b(%rip), %rcx     # 0x24380
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0xa0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
callq 0x32c0
jmp 0x12d80
movq -0xa8(%rbp), %rdi
callq 0x12950
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movq %rcx, -0x28(%rbp)
cmpl $0x1, 0x18(%rax)
je 0x12a98
movq -0xa8(%rbp), %rax
cmpl $0x2, 0x18(%rax)
jne 0x12b07
movl $0x20, %edi
callq 0x3300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xb8(%rbp)
movl $0xb, %esi
callq 0x14270
jmp 0x12abb
movq -0xb8(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
addq $0x8, %rdi
leaq -0x28(%rbp), %rsi
callq 0x142a0
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
leaq -0x30(%rbp), %rsi
callq 0x142a0
jmp 0x12b18
movq -0xb8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
callq 0x32c0
jmp 0x12d80
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
leaq -0x28(%rbp), %rsi
callq 0x142a0
jmp 0x12ca7
movq -0xa8(%rbp), %rdi
callq 0x12f60
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
leaq -0x38(%rbp), %rsi
callq 0x142a0
jmp 0x12ca7
movq -0xa8(%rbp), %rdi
callq 0x11e50
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movq %rcx, -0x40(%rbp)
cmpl $0x1, 0x18(%rax)
je 0x12b70
movq -0xa8(%rbp), %rax
cmpl $0x2, 0x18(%rax)
jne 0x12bdf
movl $0x20, %edi
callq 0x3300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xc0(%rbp)
movl $0xb, %esi
callq 0x14270
jmp 0x12b93
movq -0xc0(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rdi
addq $0x8, %rdi
leaq -0x40(%rbp), %rsi
callq 0x142a0
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
leaq -0x48(%rbp), %rsi
callq 0x142a0
jmp 0x12bf0
movq -0xc0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
callq 0x32c0
jmp 0x12d80
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
leaq -0x40(%rbp), %rsi
callq 0x142a0
jmp 0x12ca7
movq -0xa8(%rbp), %rdi
movl $0x4, -0x4c(%rbp)
leaq -0x4c(%rbp), %rsi
callq 0x11bc0
movq -0xa8(%rbp), %rdi
movq -0x10(%rbp), %rax
addq $0x8, %rax
movq %rax, -0xc8(%rbp)
callq 0x129d0
movq -0xc8(%rbp), %rdi
movq %rax, -0x58(%rbp)
leaq -0x58(%rbp), %rsi
callq 0x14310
movq -0xa8(%rbp), %rdi
movl $0x5, -0x5c(%rbp)
leaq -0x5c(%rbp), %rsi
callq 0x11bc0
jmp 0x12ca7
leaq -0x81(%rbp), %rdi
movq %rdi, -0xd0(%rbp)
callq 0x3530
movq -0xd0(%rbp), %rdx
leaq 0x118aa(%rip), %rsi     # 0x2451f
leaq -0x80(%rbp), %rdi
callq 0x33f0
jmp 0x12c80
movq -0xa8(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x11650
jmp 0x12c92
leaq -0x80(%rbp), %rdi
callq 0x31d0
leaq -0x81(%rbp), %rdi
callq 0x3350
movq -0xa8(%rbp), %rax
cmpl $0x1, 0x18(%rax)
je 0x12cc5
movq -0xa8(%rbp), %rax
cmpl $0x2, 0x18(%rax)
jne 0x12d62
movq -0xa8(%rbp), %rdi
movq -0x10(%rbp), %rax
addq $0x8, %rax
movq %rax, -0xe0(%rbp)
callq 0x12fe0
movq -0xe0(%rbp), %rdi
movq %rax, -0x90(%rbp)
leaq -0x90(%rbp), %rsi
callq 0x14310
movq -0xa8(%rbp), %rdi
movq -0x10(%rbp), %rax
addq $0x8, %rax
movq %rax, -0xd8(%rbp)
callq 0x129d0
movq -0xd8(%rbp), %rdi
movq %rax, -0x98(%rbp)
leaq -0x98(%rbp), %rsi
callq 0x14310
jmp 0x12d73
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
jmp 0x12d54
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x31d0
leaq -0x81(%rbp), %rdi
callq 0x3350
jmp 0x12d80
movq -0xa8(%rbp), %rax
cmpl $0x4, 0x18(%rax)
jne 0x12d71
jmp 0x12d71
jmp 0x12d73
movq -0x10(%rbp), %rax
addq $0xe0, %rsp
popq %rbp
retq
movq -0x18(%rbp), %rdi
callq 0x3520
nopl (%rax)