// File: /workspace/github_c_makefile_star2_O2/sebbekarlsson[P]cola/src/lex.c
// Function: lex_get_next_token
token* lex_get_next_token(lex_state* state) {
    while (state->current_char != '\0') {
        char* str = char_to_string(state->current_char); 

        if (state->current_char == ' ' || (int)state->current_char == 10 || state->current_char == '\0') {
            lex_skip_whitespace(state);
            free(str);
            continue;
        }

        else if (state->current_char == '+') {
            lex_advance(state);
            return init_token(_OP_PLUS, str);
        }

        else if (state->current_char == '-') {
            lex_advance(state);
            return init_token(_OP_SUBTRACT, str);
        }

        else if (state->current_char == '/') {
            lex_advance(state);
            return init_token(_OP_DIVIDE, str);
        }

        else if (state->current_char == '*') {
            lex_advance(state);
            return init_token(_OP_MULTIPLY, str);
        }

        else if (state->current_char == '(') {
            lex_advance(state);
            return init_token(_LPAREN, str);
        }

        else if (state->current_char == ')') {
            lex_advance(state);
            return init_token(_RPAREN, str);
        }

        else if (state->current_char == '{') {
            lex_advance(state);
            return init_token(_LBRACE, str);
        }

        else if (state->current_char == '}') {
            lex_advance(state);
            return init_token(_RBRACE, str);
        }

        else if (state->current_char == ';') {
            lex_advance(state);
            return init_token(_SEMI, str);
        }

        else if (state->current_char == '.') {
            lex_advance(state);
            return init_token(_DOT, str);
        }

        else if (state->current_char == ',') {
            lex_advance(state);
            return init_token(_COMMA, str);
        }

        else if (state->current_char == '<') {
            lex_advance(state);
            return init_token(_LESS_THAN, str);
        }
        
        else if (state->current_char == '>') {
            lex_advance(state);
            return init_token(_LARGER_THAN, str);
        }

        else if (state->current_char == '=') {
            lex_advance(state);
            if (state->current_char == '=') {
                lex_advance(state);
                return init_token(_EQUALS_EQUALS, str);
            } else {
                lex_advance(state);
                return init_token(_EQUALS, str);
            }
        }

        else if (state->current_char == '[') {
            lex_advance(state);
            return init_token(_LBRACKET, str);
        }

        else if (state->current_char == ']') {
            lex_advance(state);
            return init_token(_RBRACKET, str);
        }

        else if (state->current_char == '"') {
            free(str);
            return init_token(_STRING, lex_parse_string(state));
        }

        else if (state->current_char == '#') {
            free(str);
            lex_advance(state);
            if (state->current_char != '!') {
                return init_token(_INTERPRETER_INSTR, lex_parse_id(state));
            }
        }

        else if (state->current_char == '\'') {
            free(str);
            return init_token(_CHAR, lex_parse_char(state));
        }

        else if (isdigit(state->current_char)) {
            free(str);
            return lex_parse_number(state);
        }

        else if (isalnum(state->current_char)) {
            free(str);
            return parse_id(state, init_token(_ID, lex_parse_id(state)));
        } else {
            printf("Unexpected token: `%s` (%d) \n", str, (int) state->current_char);
            break;
        }

        free(str);
        lex_advance(state);
    }

    return init_token(_EOF, "");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %r14
leaq 0x274f(%rip), %r15      # 0x527c
movb 0x8(%r14), %al
testb %al, %al
je 0x2c0a
movsbl %al, %edi
callq 0x4238
movq %rax, %rbx
movzbl 0x8(%r14), %eax
leal -0x20(%rax), %ecx
cmpl $0x1e, %ecx
ja 0x2b87
movslq (%r15,%rcx,4), %rcx
addq %r15, %rcx
jmpq *%rcx
movq %rbx, %rdi
callq 0x1030
movq %r14, %rdi
callq 0x2af8
cmpb $0x21, 0x8(%r14)
jne 0x2d28
movq %rbx, %rdi
callq 0x1030
movq %r14, %rdi
callq 0x2af8
jmp 0x2b2d
testl %eax, %eax
je 0x2b90
cmpl $0xa, %eax
jne 0x2ba2
movq %r14, %rdi
callq 0x2d97
movq %rbx, %rdi
callq 0x1030
jmp 0x2b2d
cmpl $0x5b, %eax
je 0x2d04
cmpl $0x5d, %eax
je 0x2d1c
cmpl $0x7b, %eax
je 0x2d10
cmpl $0x7d, %eax
jne 0x2bd1
movq %r14, %rdi
callq 0x2af8
pushq $0xf
jmp 0x2d54
movsbl %al, %r15d
callq 0x1170
movq (%rax), %rax
movslq %r15d, %rcx
movzwl (%rax,%rcx,2), %eax
btl $0xb, %eax
jb 0x2d38
testb $0x8, %al
jne 0x2d67
leaq 0x26fb(%rip), %rdi      # 0x52f8
movq %rbx, %rsi
movl %r15d, %edx
xorl %eax, %eax
callq 0x10a0
leaq 0x2704(%rip), %rsi      # 0x5315
xorl %edi, %edi
jmp 0x2d58
movq %r14, %rdi
callq 0x2af8
pushq $0x6
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0x7
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0x5
jmp 0x2d54
movq %rbx, %rdi
callq 0x1030
movq %r14, %rdi
callq 0x2dbf
pushq $0x3
jmp 0x2d32
movq %r14, %rdi
callq 0x2af8
pushq $0x17
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0x15
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
movb 0x8(%r14), %r15b
movq %r14, %rdi
callq 0x2af8
cmpb $0x3d, %r15b
jne 0x2d52
pushq $0x24
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0x16
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0xc
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0x10
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0x8
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0xd
jmp 0x2d54
movq %rbx, %rdi
callq 0x1030
movq %r14, %rdi
callq 0x2efc
pushq $0x26
jmp 0x2d32
movq %r14, %rdi
callq 0x2af8
pushq $0x14
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0x22
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0xe
jmp 0x2d54
movq %r14, %rdi
callq 0x2af8
pushq $0x23
jmp 0x2d54
movq %r14, %rdi
callq 0x2e49
pushq $0x20
popq %rdi
movq %rax, %rsi
jmp 0x2d58
movq %rbx, %rdi
callq 0x1030
movq %r14, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x2fcd
pushq $0x1b
popq %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x42a0
movq %rbx, %rdi
callq 0x1030
movq %r14, %rdi
callq 0x2e49
pushq $0x1
popq %rdi
movq %rax, %rsi
callq 0x42a0
movq %r14, %rdi
movq %rax, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x3df0