// File: /workspace/github_cpp_makefile_star2_O1/baziotis[P]minijava-cpp/parse.cpp
// Function: parse_stmt()
static Statement *parse_stmt() {
    // The contract is that if the caller called this function,
    // then a statement _must_ follow. In other words, the caller
    // is responsible to check whether a statement follows.
    // The caller is also responsible for checking whether
    // an UndefinedStatement was returned.
    if (!starts_statement(token.kind)) {
        syntax_error("Expected `{`, `Identifier`, `if`, `while`"
                     " or `System.out.println` to start a statement, found:",
                     " `", token, "`");
        Statement *s = new UndefinedStatement;
        s->loc = loc;
        return s;
    }

    Statement *s = NULL;
    switch (token.kind) {
    case TOK::LBRACE:
    {
        next_token();
        BlockStatement *b = new BlockStatement;
        b->loc = loc;
        b->block = parse_stmt_block();
        expect_token(TOK::RBRACE);
        s = b;
    } break;
    case TOK::ID:
    {
        next_token();
        const char *id = token.id;
        Statement *s2 = NULL;
        if (match_token(TOK::ASGN)) {
            AssignmentStatement *asgn_stmt = new AssignmentStatement;
            asgn_stmt->loc = loc;
            asgn_stmt->id = id;
            asgn_stmt->rhs = parse_expr();
            if (asgn_stmt->rhs->kind == EXPR::UNDEFINED) {
                syntax_error_no_ln("RHS expression of assignment to `", id, "` is invalid");
                skip_tokens(TOK::SEMI);
                goto Lerror;
            }
            expect_token_in_rule(TOK::SEMI, "assignment statement");
            s2 = asgn_stmt;
        } else if (match_token(TOK::LBRACKET)) {
            ArrayAssignmentStatement *arr_as = new ArrayAssignmentStatement;
            arr_as->loc = loc;
            arr_as->id = id;
            arr_as->index = parse_expr();
            expect_token_in_rule(TOK::RBRACKET, "array assignment statement");
            if (!expect_token_in_rule(TOK::ASGN, "array assignment statement")) {
                goto Lerror;
            }
            arr_as->rhs = parse_expr();
            if (arr_as->rhs->kind == EXPR::UNDEFINED) {
                syntax_error_no_ln("RHS expression of array assignment to `", id, "` is invalid");
                skip_tokens(TOK::SEMI);
                goto Lerror;
            }
            expect_token_in_rule(TOK::SEMI, "array assignment statement");
            s2 = arr_as;
        } else {
            // Make a poinsoned statement
            syntax_error("Expected either `=` or `[` following id: `", id, "`");
            goto Lerror;
        }
        s = s2;
    } break;
    case TOK::IF:
    {
        next_token();
        IfStatement *if_stmt = new IfStatement;
        if_stmt->loc = loc;
        expect_token_in_rule(TOK::LPAR, "if statement");
        if_stmt->cond = parse_expr();
        if (if_stmt->cond->kind == EXPR::UNDEFINED) {
            syntax_error_no_ln("Condition expression of `if` is invalid");
            skip_tokens(TOK::RPAR);
            goto Lerror;
        }
        expect_token_in_rule(TOK::RPAR, "if statement");
        if_stmt->then = parse_stmt();
        if (!expect_token_in_rule(TOK::ELSE, "if statement")) {
            goto Lerror;
        } 
        if_stmt->else_= parse_stmt();
        s = if_stmt;
    } break;
    case TOK::WHILE:
    {
        next_token();
        WhileStatement *while_stmt = new WhileStatement;
        while_stmt->loc = loc;
        expect_token_in_rule(TOK::LPAR, "while statement");
        while_stmt->cond = parse_expr();
        if (while_stmt->cond->kind == EXPR::UNDEFINED) {
            syntax_error_no_ln("Condition expression of `while` is invalid");
            skip_tokens(TOK::RPAR);
            goto Lerror;
        }
        expect_token_in_rule(TOK::RPAR, "while statement");
        while_stmt->body = parse_stmt();
        s = while_stmt;
    } break;
    case TOK::PRINT:
    {
        next_token();
        PrintStatement *prnt = new PrintStatement;
        prnt->loc = loc;
        expect_token_in_rule(TOK::LPAR, "System.out.println");
        prnt->to_print = parse_expr();
        if (prnt->to_print->kind == EXPR::UNDEFINED) {
            syntax_error_no_ln("Expression inside System.out.println is invalid");
            skip_tokens(TOK::SEMI);
            goto Lerror;
        }
        expect_token_in_rule(TOK::RPAR, "System.out.println");
        expect_token_in_rule(TOK::SEMI, "System.out.println");
        s = prnt;
    } break;
    default: assert(0);
    }
    assert(s);
    return s;
Lerror:
    s = new UndefinedStatement;
    s->loc = loc;
    return s;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x20, %rsp
leaq 0x127d0(%rip), %r15     # 0x19698
movl (%r15), %edx
leal -0x7(%rdx), %eax
cmpl $0x5, %eax
jae 0x6f78
jae 0x73be
leaq 0xa97c(%rip), %rcx      # 0x11860
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
callq 0x3a45
movl $0x28, %edi
movl $0x2, %esi
callq 0x23f5
movq %rax, %rbx
leaq 0x11cdd(%rip), %rax     # 0x18be8
addq $0x10, %rax
movq %rax, (%rbx)
leaq 0x10(%rbx), %r12
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rbx)
xorl %eax, %eax
movq %rax, 0x20(%rbx)
movl $0x1, 0x8(%rbx)
leaq 0x1275f(%rip), %rcx     # 0x19690
movl (%rcx), %ecx
movl %ecx, 0xc(%rbx)
movq %rax, 0x10(%rsp)
movaps %xmm0, (%rsp)
cmpl $0x1a, (%r15)
je 0x6f56
movq %rsp, %r14
movq %r14, %rdi
callq 0x6a76
cmpl $0x1a, (%r15)
jne 0x6f48
movq 0x10(%rsp), %rax
movq %rax, 0x10(%r12)
movaps (%rsp), %xmm0
movups %xmm0, (%r12)
movl $0x1a, %edi
callq 0x73dd
jmp 0x738a
movq 0x8(%r15), %rcx
leaq 0xacb7(%rip), %rdi      # 0x11c3a
leaq 0xaae6(%rip), %rsi      # 0x11a70
callq 0x6c78
movl $0x10, %edi
movl $0x2, %esi
callq 0x23f5
movq %rax, %rbx
leaq 0x11bf8(%rip), %rax     # 0x18ba0
addq $0x10, %rax
movq %rax, (%rbx)
movl $0x0, 0x8(%rbx)
leaq 0x126d3(%rip), %rax     # 0x19690
movl (%rax), %eax
movl %eax, 0xc(%rbx)
jmp 0x738f
callq 0x3a45
movl $0x18, %edi
movl $0x2, %esi
callq 0x23f5
movq %rax, %rbx
leaq 0x11d6b(%rip), %rax     # 0x18d50
addq $0x10, %rax
movq %rax, (%rbx)
movl $0x6, 0x8(%rbx)
leaq 0x12696(%rip), %rax     # 0x19690
movl (%rax), %eax
movl %eax, 0xc(%rbx)
leaq 0x9c8c(%rip), %rsi      # 0x10c92
movl $0x3, %edi
callq 0x6622
callq 0x751c
movq %rax, 0x10(%rbx)
movl 0x4(%rax), %ebp
testl %ebp, %ebp
je 0x728e
leaq 0x9c67(%rip), %r14      # 0x10c92
movl $0x19, %edi
movq %r14, %rsi
callq 0x6622
movl $0x1e, %edi
movq %r14, %rsi
callq 0x6622
jmp 0x72ea
callq 0x3a45
movl $0x28, %edi
movl $0x2, %esi
callq 0x23f5
movq %rax, %rbx
leaq 0x11c58(%rip), %rax     # 0x18cc0
addq $0x10, %rax
movq %rax, (%rbx)
movl $0x4, 0x8(%rbx)
leaq 0x12613(%rip), %rax     # 0x19690
movl (%rax), %eax
movl %eax, 0xc(%rbx)
leaq 0xaca0(%rip), %rsi      # 0x11d29
movl $0x3, %edi
callq 0x6622
callq 0x751c
movq %rax, 0x10(%rbx)
cmpl $0x0, 0x4(%rax)
je 0x72a1
leaq 0xac7c(%rip), %r14      # 0x11d29
movl $0x19, %edi
movq %r14, %rsi
callq 0x6622
callq 0x6eb5
movq %rax, 0x18(%rbx)
movl $0xd, %edi
movq %r14, %rsi
callq 0x6622
testb %al, %al
je 0x72bc
callq 0x6eb5
movq %rax, 0x20(%rbx)
movb $0x1, %al
jmp 0x72c0
callq 0x3a45
movl $0x30, %edi
movl $0x2, %esi
callq 0x23f5
movq %rax, %rbx
leaq 0x11c02(%rip), %rax     # 0x18d08
addq $0x10, %rax
movq %rax, (%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x20(%rbx)
movl $0x5, 0x8(%rbx)
leaq 0x1256e(%rip), %rax     # 0x19690
movl (%rax), %eax
movl %eax, 0xc(%rbx)
leaq 0xac30(%rip), %rsi      # 0x11d5e
movl $0x3, %edi
callq 0x6622
callq 0x751c
movq %rax, 0x10(%rbx)
movl 0x4(%rax), %ebp
testl %ebp, %ebp
je 0x72cd
leaq 0xac0b(%rip), %rsi      # 0x11d5e
movl $0x19, %edi
callq 0x6622
callq 0x6eb5
movq %rax, 0x18(%rbx)
jmp 0x72ea
callq 0x3a45
movq 0x8(%r15), %r14
cmpl $0x18, (%r15)
jne 0x71e4
callq 0x3a45
movl $0x20, %edi
movl $0x2, %esi
callq 0x23f5
movq %rax, %rbx
leaq 0x11a98(%rip), %rax     # 0x18c30
addq $0x10, %rax
movq %rax, (%rbx)
movl $0x2, 0x8(%rbx)
leaq 0x124e3(%rip), %rax     # 0x19690
movl (%rax), %eax
movl %eax, 0xc(%rbx)
movq %r14, 0x10(%rbx)
callq 0x751c
movq %rax, 0x18(%rbx)
movl 0x4(%rax), %r15d
testl %r15d, %r15d
je 0x731e
leaq 0xaaee(%rip), %rsi      # 0x11cc1
movl $0x1e, %edi
callq 0x6622
xorl %ebp, %ebp
jmp 0x734a
cmpl $0x24, (%r15)
jne 0x72f7
callq 0x3a45
movl $0x28, %edi
movl $0x2, %esi
callq 0x23f5
movq %rax, %rbx
leaq 0x11a6c(%rip), %rax     # 0x18c78
addq $0x10, %rax
movq %rax, (%rbx)
movl $0x3, 0x8(%rbx)
leaq 0x1246f(%rip), %rax     # 0x19690
movl (%rax), %eax
movl %eax, 0xc(%rbx)
movq %r14, 0x10(%rbx)
callq 0x751c
movq %rax, 0x18(%rbx)
leaq 0xaa81(%rip), %r15      # 0x11cbb
movl $0x1b, %edi
movq %r15, %rsi
callq 0x6622
movl $0x18, %edi
movq %r15, %rsi
callq 0x6622
movl $0x3, %ebp
testb %al, %al
je 0x7378
callq 0x751c
movq %rax, 0x20(%rbx)
cmpl $0x0, 0x4(%rax)
je 0x7353
leaq 0xaa40(%rip), %rsi      # 0x11cbb
movl $0x1e, %edi
callq 0x6622
xorl %ebp, %ebp
movb $0x1, %al
jmp 0x737c
leaq 0xab04(%rip), %rdi      # 0x11d99
callq 0x6775
movl $0x1e, %edi
jmp 0x72de
leaq 0xaa8e(%rip), %rdi      # 0x11d36
callq 0x6775
movl $0x19, %edi
movl $0x1, %esi
callq 0x6825
xorl %eax, %eax
xorl %ebx, %ebx
testb %al, %al
je 0x6f8f
jmp 0x738a
leaq 0xaa9a(%rip), %rdi      # 0x11d6e
callq 0x6775
movl $0x19, %edi
movl $0x1, %esi
callq 0x6825
xorl %ebx, %ebx
testl %ebp, %ebp
jne 0x738a
jmp 0x6f8f
leaq 0xaa00(%rip), %rdi      # 0x11cfe
leaq 0xa76c(%rip), %rdx      # 0x11a71
movq %r14, %rsi
callq 0x787d
movl $0xa, %edi
callq 0x2160
movl $0x3, %ebp
jmp 0x7380
leaq 0xa974(%rip), %rdi      # 0x11c99
leaq 0xaa60(%rip), %rdx      # 0x11d8c
movq %r14, %rsi
callq 0x787d
movl $0x1e, %edi
movl $0x1, %esi
callq 0x6825
movl $0x3, %ebp
xorl %ebx, %ebx
testl %r15d, %r15d
je 0x7380
xorl %ebp, %ebp
jmp 0x7382
leaq 0xa97c(%rip), %rdi      # 0x11cd6
leaq 0xaa2b(%rip), %rdx      # 0x11d8c
movq %r14, %rsi
callq 0x787d
movl $0x1e, %edi
movl $0x1, %esi
callq 0x6825
xorl %eax, %eax
xorl %ebx, %ebx
testb %al, %al
jne 0x734f
xorl %ebx, %ebx
testl %ebp, %ebp
jne 0x6f8f
testq %rbx, %rbx
je 0x739f
movq %rbx, %rax
addq $0x20, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x900f(%rip), %rdi      # 0x103b5
leaq 0xaa1c(%rip), %rsi      # 0x11dc9
leaq 0xaa1f(%rip), %rcx      # 0x11dd3
movl $0x1c6, %edx            # imm = 0x1C6
callq 0x20b0
leaq 0xb2ed(%rip), %rdi      # 0x126b2
leaq 0xa9fd(%rip), %rsi      # 0x11dc9
leaq 0xaa00(%rip), %rcx      # 0x11dd3
movl $0x1c4, %edx            # imm = 0x1C4
callq 0x20b0