// File: /workspace/github_cpp_makefile_star2_O1/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 0x94c5
leal -0x3(%rax), %ecx
cmpl $0x6, %ecx
ja 0x9516
leaq 0x8e5c(%rip), %rax      # 0x12304
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movl $0x7, 0x20(%rbx)
movq %r14, %rdi
callq 0x8a04
jmp 0x96c2
cmpl $0x1e, %eax
jg 0x94f0
cmpl $0x13, %eax
je 0x962f
cmpl $0x1e, %eax
jne 0x9864
movq %r14, %rdi
callq 0x8a04
movl $0x8, 0x20(%rbx)
jmp 0x96b0
cmpl $0x1f, %eax
je 0x9675
cmpl $0x20, %eax
jne 0x9864
movq %r14, %rdi
callq 0x8a04
movl $0xa, 0x20(%rbx)
jmp 0x9684
cmpl $0x12, %eax
jne 0x9864
movl $0x0, 0x20(%rbx)
movq %r14, %rdi
callq 0x8a04
leaq -0x40(%rbp), %r12
movl $0x4, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x903c
movq %r14, %rdi
callq 0x9aa6
movq %rax, (%r12)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x974b
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x9757
movq %r14, %rdi
movl $0x1, %esi
callq 0x8dee
cmpl $0x4, %eax
jne 0x96d2
movl $0x5, 0x20(%rbx)
movq %r14, %rdi
callq 0x920e
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x979e
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x97aa
movl $0x6, 0x20(%rbx)
movq %r14, %rdi
callq 0x8a04
cmpl $0x7, 0x18(%r14)
je 0x95fc
leaq -0x40(%rbp), %r12
movq %r14, %rdi
callq 0x9458
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x95ea
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x95f5
movq %r15, %rdi
movq %r12, %rdx
callq 0xaf02
cmpl $0x7, 0x18(%r14)
jne 0x95ca
leaq -0x40(%rbp), %rsi
movl $0x7, (%rsi)
jmp 0x96ba
movl $0x3, 0x20(%rbx)
movq %r14, %rdi
callq 0x8a04
cmpl $0x3, 0x18(%r14)
je 0x96b0
movq %r14, %rdi
callq 0x9aa6
jmp 0x968c
movl $0x2, 0x20(%rbx)
movq %r14, %rdi
callq 0x8a04
leaq -0x40(%rbp), %r12
movl $0x4, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x903c
movq %r14, %rdi
callq 0x9aa6
movq %rax, (%r12)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x96e3
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x96ef
movq %r14, %rdi
callq 0x8a04
movl $0x9, 0x20(%rbx)
movq %r14, %rdi
callq 0x920e
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x96a4
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x96b0
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xaf02
leaq -0x40(%rbp), %rsi
movl $0x3, (%rsi)
movq %r14, %rdi
callq 0x903c
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 0x9d44
jmp 0x9745
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xaf02
movl $0x5, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x903c
movq %r14, %rdi
callq 0x9458
movq %rax, (%r12)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x9722
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x972e
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xaf02
cmpl $0x14, 0x18(%r14)
jne 0x96c2
movq %r14, %rdi
callq 0x8a04
movq %r14, %rdi
callq 0x9458
movq %rax, -0x40(%rbp)
jmp 0x9776
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xaf02
movl $0x5, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x903c
movq %r14, %rdi
callq 0x9458
movq %rax, (%r12)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x978d
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x96c2
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xaf02
jmp 0x96c2
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xaf02
leaq -0x40(%rbp), %rsi
movl $0x4, (%rsi)
movq %r14, %rdi
callq 0x903c
cmpl $0x5, 0x18(%r14)
je 0x97ef
movq %r14, %rdi
callq 0x9aa6
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x97e3
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x97ef
leaq -0x40(%rbp), %rdx
movq %r15, %rdi
callq 0xaf02
cmpl $0x5, 0x18(%r14)
je 0x983e
leaq -0x40(%rbp), %r12
movl $0xa, -0x40(%rbp)
movq %r14, %rdi
movq %r12, %rsi
callq 0x903c
movq %r14, %rdi
callq 0x9aa6
movq %rax, -0x40(%rbp)
movq 0x10(%rbx), %rsi
cmpq 0x18(%rbx), %rsi
je 0x982c
movq %rax, (%rsi)
addq $0x8, 0x10(%rbx)
jmp 0x9837
movq %r15, %rdi
movq %r12, %rdx
callq 0xaf02
cmpl $0x5, 0x18(%r14)
jne 0x97fa
leaq -0x40(%rbp), %r15
movl $0x5, (%r15)
movq %r14, %rdi
movq %r15, %rsi
callq 0x903c
movl $0x3, (%r15)
leaq -0x40(%rbp), %rsi
jmp 0x96ba
leaq -0x30(%rbp), %r15
movq %r15, -0x10(%r15)
leaq 0x8bf3(%rip), %rsi      # 0x12466
leaq 0x8c05(%rip), %rdx      # 0x1247f
leaq -0x40(%rbp), %rbx
movq %rbx, %rdi
callq 0x8354
movq %r14, %rdi
movq %rbx, %rsi
callq 0x8b40
movq %rax, %rbx
movq -0x40(%rbp), %rdi
cmpq %r15, %rdi
je 0x98a2
callq 0x3250
movq %rbx, %rdi
callq 0x3420