// File: /workspace/github_cpp_makefile_star2_O3/taurheim[P]AgNES/parser.cpp
// Function: Parser::statement()
ASTNode * Parser::statement() {
    /*
        "if" "(" <expression> ")" <statement> [ "else" <statement> ]
        | "while" "(" <expression> ")" <statement>
        | "for" "(" <assignment> ")" ";" <expression> ";" <assignment> ")" <statement>
        | "return" [<expression>] ";"
        | <assignment> ";"
        | <identifier> "(" [ <expression> {"," <expression> } ] ")" ";"
        | "{" {<statement>} "}"
        | ";"
    */
    StatementNode * node = new StatementNode();

    switch(t.type) {
        case T_NES_WAITFORFRAME: {
            next();
            node->type = STMT_NES_WAITFORFRAME;
            expect(T_SEMI);
            break;
        }
        case T_NES_SETSPRITEX: {
            next();
            node->type = STMT_NES_SETSPRITEX;
            node->children.push_back(identifier());
            expect(T_SEMI);
            break;
        }
        case T_NES_SETSPRITEY: {
            next();
            node->type = STMT_NES_SETSPRITEY;
            node->children.push_back(identifier());
            expect(T_SEMI);
            break;
        }
        case T_WHILE: {
            node->type = STMT_WHILE;
            next();
            expect(T_LPAREN);
            node->children.push_back(expression());
            expect(T_RPAREN);
            node->children.push_back(statement());
            break;
        }
        case T_IF: {
            node->type = STMT_IF;
            next();
            expect(T_LPAREN);
            node->children.push_back(expression());
            expect(T_RPAREN);
            node->children.push_back(statement());
            if (t.type == T_ELSE) {
                next();
                node->children.push_back(statement());
            }
            break;
        }
        case T_LCURLY: {
            node->type = STMT_BLOCK;
            next();
            while (t.type != T_RCURLY) {
                node->children.push_back(statement());
            }
            expect(T_RCURLY);
            break;
        }
        case T_RETURN: {
            node->type = STMT_RETURN;
            next();
            if (t.type != T_SEMI) {
                node->children.push_back(expression());
            }
            expect(T_SEMI);
            break;
        }
        case T_SEMI: {
            node->type = STMT_EMPTY;
            next();
            break;
        }
        case T_IDENT:
        {
            // Can be either an assignment or a function call
            // Check second character - if it's a "(" then it's a function call
            TokenType decider = lookahead(1);
            if (decider == T_LPAREN) {
                // Function call
                node->type = STMT_FUNCTIONCALL;
                node->children.push_back(identifier());
                expect(T_LPAREN);

                // First arg
                if(t.type != T_RPAREN) {
                    node->children.push_back(expression());
                }

                // 2.. args
                while (t.type != T_RPAREN) {
                    expect(T_COMMA);
                    node->children.push_back(expression());
                }

                expect(T_RPAREN);
                expect(T_SEMI);
            } else {
                // Assignment
                node->type = STMT_ASSIGN;
                node->children.push_back(assignment());
            }
            break;
        }
        default:
        {
            reject("statement not recognized.");
        }
    }

    return node;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x20, %rsp
movq %rdi, %r14
movl $0x28, %edi
callq 0x3290
movq %rax, %rbx
leaq 0x8(%rax), %r15
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
movq $0x0, 0x18(%rax)
movl $0x9, (%rax)
movl 0x18(%r14), %eax
cmpl $0x12, %eax
jg 0x93f9
leal -0x3(%rax), %ecx
cmpl $0x6, %ecx
ja 0x944a
leaq 0x8f28(%rip), %rax      # 0x12304
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movl $0x7, 0x20(%rbx)
movq %r14, %rdi
callq 0x899a
jmp 0x95f6
cmpl $0x1e, %eax
jg 0x9424
cmpl $0x13, %eax
je 0x9563
cmpl $0x1e, %eax
jne 0x9798
movq %r14, %rdi
callq 0x899a
movl $0x8, 0x20(%rbx)
jmp 0x95e4
cmpl $0x1f, %eax
je 0x95a9
cmpl $0x20, %eax
jne 0x9798
movq %r14, %rdi
callq 0x899a
movl $0xa, 0x20(%rbx)
jmp 0x95b8
cmpl $0x12, %eax
jne 0x9798
movl $0x0, 0x20(%rbx)
movq %r14, %rdi
callq 0x899a
leaq -0x40(%rbp), %r12
movl $0x4, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x8f9a
movq %r14, %rdi
callq 0x99be
movq %rax, (%r12)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x967f
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x968b
movq %r14, %rdi
movl $0x1, %esi
callq 0x8d78
cmpl $0x4, %eax
jne 0x9606
movl $0x5, 0x20(%rbx)
movq %r14, %rdi
callq 0x9154
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x96d2
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x96de
movl $0x6, 0x20(%rbx)
movq %r14, %rdi
callq 0x899a
cmpl $0x7, 0x18(%r14)
je 0x9530
leaq -0x40(%rbp), %r12
movq %r14, %rdi
callq 0x938c
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x951e
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x9529
movq %r15, %rdi
movq %r12, %rdx
callq 0xadac
cmpl $0x7, 0x18(%r14)
jne 0x94fe
leaq -0x40(%rbp), %rsi
movl $0x7, (%rsi)
jmp 0x95ee
movl $0x3, 0x20(%rbx)
movq %r14, %rdi
callq 0x899a
cmpl $0x3, 0x18(%r14)
je 0x95e4
movq %r14, %rdi
callq 0x99be
jmp 0x95c0
movl $0x2, 0x20(%rbx)
movq %r14, %rdi
callq 0x899a
leaq -0x40(%rbp), %r12
movl $0x4, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x8f9a
movq %r14, %rdi
callq 0x99be
movq %rax, (%r12)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x9617
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x9623
movq %r14, %rdi
callq 0x899a
movl $0x9, 0x20(%rbx)
movq %r14, %rdi
callq 0x9154
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x95d8
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x95e4
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xadac
leaq -0x40(%rbp), %rsi
movl $0x3, (%rsi)
movq %r14, %rdi
callq 0x8f9a
movq %rbx, %rax
addq $0x20, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movl $0x4, 0x20(%rbx)
movq %r14, %rdi
callq 0x9c5e
jmp 0x9679
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xadac
movl $0x5, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x8f9a
movq %r14, %rdi
callq 0x938c
movq %rax, (%r12)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x9656
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x9662
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xadac
cmpl $0x14, 0x18(%r14)
jne 0x95f6
movq %r14, %rdi
callq 0x899a
movq %r14, %rdi
callq 0x938c
movq %rax, -0x40(%rbp)
jmp 0x96aa
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xadac
movl $0x5, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x8f9a
movq %r14, %rdi
callq 0x938c
movq %rax, (%r12)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x96c1
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x95f6
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xadac
jmp 0x95f6
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xadac
leaq -0x40(%rbp), %rsi
movl $0x4, (%rsi)
movq %r14, %rdi
callq 0x8f9a
cmpl $0x5, 0x18(%r14)
je 0x9772
movq %r14, %rdi
callq 0x99be
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x9717
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x9723
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xadac
cmpl $0x5, 0x18(%r14)
je 0x9772
leaq -0x40(%rbp), %r12
movl $0xa, -0x40(%rbp)
movq %r14, %rdi
movq %r12, %rsi
callq 0x8f9a
movq %r14, %rdi
callq 0x99be
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x9760
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x976b
movq %r15, %rdi
movq %r12, %rdx
callq 0xadac
cmpl $0x5, 0x18(%r14)
jne 0x972e
leaq -0x40(%rbp), %r15
movl $0x5, (%r15)
movq %r14, %rdi
movq %r15, %rsi
callq 0x8f9a
movl $0x3, (%r15)
leaq -0x40(%rbp), %rsi
jmp 0x95ee
leaq -0x30(%rbp), %r15
movq %r15, -0x10(%r15)
leaq 0x8cbf(%rip), %rsi      # 0x12466
leaq 0x8cd1(%rip), %rdx      # 0x1247f
leaq -0x40(%rbp), %rbx
movq %rbx, %rdi
callq 0x82f0
movq %r14, %rdi
movq %rbx, %rsi
callq 0x8ad6
movq %rax, %rbx
movq -0x40(%rbp), %rdi
cmpq %r15, %rdi
je 0x97d6
callq 0x3250
movq %rbx, %rdi
callq 0x3420