// File: /workspace/github_cpp_makefile_star2_O2/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 $0x30, %rsp
movq %rdi, %r14
pushq $0x28
popq %rdi
callq 0x3250
movq %rax, %rbx
leaq 0x8(%rax), %r15
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
andq $0x0, 0x18(%rax)
movl $0x9, (%rax)
movl 0x18(%r14), %eax
leal -0x3(%rax), %ecx
cmpl $0x6, %ecx
jbe 0x8aff
cmpl $0x12, %eax
je 0x8c1e
cmpl $0x13, %eax
je 0x8cb7
cmpl $0x20, %eax
je 0x8c0d
cmpl $0x1f, %eax
je 0x8c80
cmpl $0x1e, %eax
jne 0x8d5f
movq %r14, %rdi
callq 0x8342
movl $0x8, 0x20(%rbx)
jmp 0x8b50
leaq 0x7802(%rip), %rax      # 0x10308
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movl $0x7, 0x20(%rbx)
movq %r14, %rdi
callq 0x8342
jmp 0x8df0
movl $0x3, 0x20(%rbx)
movq %r14, %rdi
callq 0x8342
cmpl $0x3, 0x18(%r14)
je 0x8b50
movq %r14, %rdi
callq 0x8f68
leaq -0x48(%rbp), %rsi
movq %rax, (%rsi)
movq %r15, %rdi
callq 0xa5a2
leaq -0x48(%rbp), %rsi
movl $0x3, (%rsi)
jmp 0x8de8
movl $0x6, 0x20(%rbx)
movq %r14, %rdi
callq 0x8342
leaq -0x48(%rbp), %r12
cmpl $0x7, 0x18(%r14)
je 0x8b92
movq %r14, %rdi
callq 0x8a82
movq %rax, -0x48(%rbp)
movq %r15, %rdi
movq %r12, %rsi
callq 0xa5a2
jmp 0x8b72
leaq -0x48(%rbp), %rsi
movl $0x7, (%rsi)
jmp 0x8de8
pushq $0x1
popq %rsi
movq %r14, %rdi
callq 0x85e6
cmpl $0x4, %eax
jne 0x8d3c
movl $0x5, 0x20(%rbx)
movq %r14, %rdi
callq 0x88aa
leaq -0x48(%rbp), %r12
movq %rax, (%r12)
movq %r15, %rdi
movq %r12, %rsi
callq 0xa5a2
movl $0x4, (%r12)
leaq -0x48(%rbp), %rsi
movq %r14, %rdi
callq 0x875c
cmpl $0x5, 0x18(%r14)
je 0x8d9a
movq %r14, %rdi
callq 0x8f68
leaq -0x48(%rbp), %rsi
movq %rax, (%rsi)
movq %r15, %rdi
jmp 0x8d95
movq %r14, %rdi
callq 0x8342
movl $0xa, 0x20(%rbx)
jmp 0x8c8f
andl $0x0, 0x20(%rbx)
movq %r14, %rdi
callq 0x8342
leaq -0x48(%rbp), %r12
movl $0x4, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x875c
movq %r14, %rdi
callq 0x8f68
movq %rax, (%r12)
movq %r15, %rdi
movq %r12, %rsi
callq 0xa5a2
movl $0x5, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x875c
movq %r14, %rdi
callq 0x8a82
movq %rax, (%r12)
leaq -0x48(%rbp), %rsi
jmp 0x8d52
movq %r14, %rdi
callq 0x8342
movl $0x9, 0x20(%rbx)
movq %r14, %rdi
callq 0x88aa
leaq -0x48(%rbp), %r12
movq %rax, (%r12)
movq %r15, %rdi
movq %r12, %rsi
callq 0xa5a2
movl $0x3, (%r12)
jmp 0x8de4
movl $0x2, 0x20(%rbx)
movq %r14, %rdi
callq 0x8342
leaq -0x48(%rbp), %r12
movl $0x4, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x875c
movq %r14, %rdi
callq 0x8f68
movq %rax, (%r12)
movq %r15, %rdi
movq %r12, %rsi
callq 0xa5a2
movl $0x5, (%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0x875c
movq %r14, %rdi
callq 0x8a82
movq %rax, (%r12)
leaq -0x48(%rbp), %rsi
movq %r15, %rdi
callq 0xa5a2
cmpl $0x14, 0x18(%r14)
jne 0x8df0
movq %r14, %rdi
callq 0x8342
movq %r14, %rdi
callq 0x8a82
jmp 0x8d4b
movl $0x4, 0x20(%rbx)
movq %r14, %rdi
callq 0x90f4
leaq -0x48(%rbp), %rsi
movq %rax, (%rsi)
movq %r15, %rdi
callq 0xa5a2
jmp 0x8df0
leaq 0x770b(%rip), %rsi      # 0x10471
leaq -0x48(%rbp), %rbx
leaq -0x21(%rbp), %rdx
movq %rbx, %rdi
callq 0x3110
movq %r14, %rdi
movq %rbx, %rsi
callq 0x841c
movq %rax, %rbx
leaq -0x48(%rbp), %rdi
callq 0x3140
movq %rbx, %rdi
callq 0x33e0
callq 0xa5a2
cmpl $0x5, 0x18(%r14)
je 0x8dc7
movl $0xa, -0x48(%rbp)
movq %r14, %rdi
movq %r12, %rsi
callq 0x875c
movq %r14, %rdi
callq 0x8f68
movq %rax, -0x48(%rbp)
movq %r15, %rdi
movq %r12, %rsi
jmp 0x8d95
leaq -0x48(%rbp), %r15
movl $0x5, (%r15)
movq %r14, %rdi
movq %r15, %rsi
callq 0x875c
movl $0x3, (%r15)
leaq -0x48(%rbp), %rsi
movq %r14, %rdi
callq 0x875c
movq %rbx, %rax
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq