// File: /workspace/github_cpp_makefile_star2_O2/protonpopsicle[P]lang/src/compiler/Lexer.cpp
// Function: Lexer::scan()
Token Lexer::scan() {
    // skip white space & comments
    for (;; read()) {
        if (peek == ' ' || peek == '\t') {
            continue;
        }
        // increment line number by either LF or CRLF
        else if (peek == '\n' || peek == '\r' && read('\n')) {
            line++;
        }
        else if (peek == '/' && read('/')) {
            for (;; read()) {
                if (peek == '\n' || peek == '\r' && read('\n')) {
                    line++;
                    break;
                }
            }
        }
        else break;
    }
    // handle composite tokens
    switch (peek) {
        case '<': if (read('=')) return Token(LE);  return Token('<');
        case '>': if (read('=')) return Token(GE);  return Token('>');
        case '=': if (read('=')) return Token(EQ);  return Token('=');
        case '!': if (read('=')) return Token(NE);  return Token('!');
        case '&': if (read('&')) return Token(AND); return Token('&');
        case '|': if (read('|')) return Token(OR);  return Token('|');
    }
    // handle numeric literals
    if (peek >= '0' && peek <= '9') {
        int x = 0;
        do {
            x = 10 * x + peek - '0'; // peek - '0' converts peek char to int
            read();
        } while (peek >= '0' && peek <= '9');
        return Token(NUM, x);
        /*
        if (peek != '.') {
            return Token(NUM, x);
        }
        float x = i;
        float d = 10;
        for(;;) {
            read();
            if (peek < '0' || peek > '9') break;
            x = x + (peek - '0') / d;
            d = d * 10;
        }
        return Token(REAL, x);
        */
    }
    // handle reserved words and identifiers
    if (peek >= 'A' && peek <= 'Z' || peek >= 'a' && peek <= 'z') {
        std::string word;
        do {
            word += peek;
            read();
        } while (peek >= '0' && peek <= '9' || peek >= 'a' && peek <= 'z' ||
                 peek >= 'a' && peek <= 'z');
        // check if word is already mapped
        // if so it's a keyword, otherwise it's an identifier
        wordTable::iterator iter = keywords.find(word);
        if (iter != keywords.end()) {
            return Token(iter->second, word); // iter->second points to this keyword's tag
        }
        return Token(ID, word);
    }
    // handle string literals
    if (peek == '"') {
        std::string q;
        for (;;) {
            read();
            if (peek != '"') {
                q += peek;
            }
            else {
                read();
                break;
            }
        }
        return Token(QUOTE, q);
    }
    // if peek satisfies none of the above
    // return token with peek char as tag
    unsigned char c = peek;
    peek = ' '; // clear peek
    return Token(c);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x88, %rsp
movq %rsi, %r14
movq %rdi, %rbx
pushq $0xa
popq %rbp
pushq $0x2f
popq %r15
movzbl 0x38(%r14), %eax
cmpl $0x9, %eax
je 0x38bb
cmpl $0xa, %eax
je 0x38b7
cmpl $0x20, %eax
je 0x38bb
cmpl $0xd, %eax
jne 0x38c9
movq %r14, %rdi
movl %ebp, %esi
callq 0x384c
testb %al, %al
je 0x38c5
incl 0x3c(%r14)
movq %r14, %rdi
callq 0x383a
jmp 0x3890
movb 0x38(%r14), %al
cmpb $0x2f, %al
jne 0x3909
movq %r14, %rdi
movl %r15d, %esi
callq 0x384c
testb %al, %al
je 0x3905
movzbl 0x38(%r14), %eax
cmpl $0xd, %eax
je 0x38ed
cmpl $0xa, %eax
jne 0x38fb
jmp 0x38b7
movq %r14, %rdi
movl %ebp, %esi
callq 0x384c
testb %al, %al
jne 0x38b7
movq %r14, %rdi
callq 0x383a
jmp 0x38dc
movb 0x38(%r14), %al
cmpb $0x21, %al
je 0x3a17
movzbl %al, %esi
cmpl $0x26, %esi
je 0x39f7
cmpl $0x7c, %esi
je 0x3955
cmpl $0x3d, %esi
je 0x3995
cmpl $0x3e, %esi
je 0x3975
cmpl $0x3c, %esi
jne 0x39b5
pushq $0x3d
popq %rsi
movq %r14, %rdi
callq 0x384c
testb %al, %al
je 0x3a4c
movq %rbx, %rdi
movl $0x12c, %esi            # imm = 0x12C
jmp 0x3af4
pushq $0x7c
popq %rsi
movq %r14, %rdi
callq 0x384c
testb %al, %al
je 0x3a37
movq %rbx, %rdi
movl $0x131, %esi            # imm = 0x131
jmp 0x3af4
pushq $0x3d
popq %rsi
movq %r14, %rdi
callq 0x384c
testb %al, %al
je 0x3a3e
movq %rbx, %rdi
movl $0x12d, %esi            # imm = 0x12D
jmp 0x3af4
pushq $0x3d
popq %rsi
movq %r14, %rdi
callq 0x384c
testb %al, %al
je 0x3a45
movq %rbx, %rdi
movl $0x12e, %esi            # imm = 0x12E
jmp 0x3af4
leal -0x30(%rax), %ecx
cmpb $0x9, %cl
ja 0x3a53
xorl %ebp, %ebp
imull $0xa, %ebp, %ecx
movzbl %al, %eax
leal (%rcx,%rax), %ebp
addl $-0x30, %ebp
movq %r14, %rdi
callq 0x383a
movb 0x38(%r14), %al
leal -0x30(%rax), %ecx
cmpb $0xa, %cl
jb 0x39c3
movq %rbx, %rdi
movl $0x100, %esi            # imm = 0x100
movl %ebp, %edx
callq 0x4748
jmp 0x3af9
pushq $0x26
popq %rsi
movq %r14, %rdi
callq 0x384c
testb %al, %al
je 0x3aea
movq %rbx, %rdi
movl $0x130, %esi            # imm = 0x130
jmp 0x3af4
pushq $0x3d
popq %rsi
movq %r14, %rdi
callq 0x384c
testb %al, %al
je 0x3aee
movq %rbx, %rdi
movl $0x12f, %esi            # imm = 0x12F
jmp 0x3af4
pushq $0x7c
jmp 0x3af0
pushq $0x3e
jmp 0x3af0
pushq $0x3d
jmp 0x3af0
pushq $0x3c
jmp 0x3af0
movl %eax, %ecx
andb $-0x21, %cl
addb $-0x41, %cl
cmpb $0x19, %cl
ja 0x3b0a
leaq 0x18(%rsp), %rcx
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
movb $0x0, (%rcx)
leaq 0x8(%rsp), %r15
movsbl %al, %esi
movq %r15, %rdi
callq 0x2140
movq %r14, %rdi
callq 0x383a
movb 0x38(%r14), %al
leal -0x30(%rax), %ecx
cmpb $0xa, %cl
setb %cl
leal -0x61(%rax), %edx
cmpb $0x1a, %dl
setb %dl
orb %cl, %dl
jne 0x3a7a
leaq 0x8(%rsp), %rsi
movq %r14, %rdi
callq 0x3ea4
addq $0x8, %r14
cmpq %r14, %rax
je 0x3b78
movzwl 0x40(%rax), %ebp
leaq 0x68(%rsp), %r14
leaq 0x8(%rsp), %rsi
movq %r14, %rdi
callq 0x2200
movswl %bp, %esi
movq %rbx, %rdi
movq %r14, %rdx
callq 0x4760
jmp 0x3b9a
pushq $0x26
jmp 0x3af0
pushq $0x21
popq %rsi
movq %rbx, %rdi
callq 0x472e
movq %rbx, %rax
addq $0x88, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
cmpb $0x22, %al
jne 0x3b41
leaq 0x18(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0x8(%rsp), %r15
movq %r14, %rdi
callq 0x383a
movb 0x38(%r14), %al
cmpb $0x22, %al
je 0x3b48
movsbl %al, %esi
movq %r15, %rdi
callq 0x2140
jmp 0x3b24
movb $0x20, 0x38(%r14)
jmp 0x3af1
movq %r14, %rdi
callq 0x383a
leaq 0x28(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x2200
leaq 0x28(%rsp), %rdx
movq %rbx, %rdi
movl $0x101, %esi            # imm = 0x101
callq 0x4760
leaq 0x28(%rsp), %rdi
jmp 0x3b9d
leaq 0x48(%rsp), %r14
leaq 0x8(%rsp), %rsi
movq %r14, %rdi
callq 0x2200
movq %rbx, %rdi
movl $0x102, %esi            # imm = 0x102
movq %r14, %rdx
callq 0x4760
movq %r14, %rdi
callq 0x20c0
leaq 0x8(%rsp), %rdi
callq 0x20c0
jmp 0x3af9
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
jmp 0x3bcf
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
jmp 0x3bcf
jmp 0x3bda
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x20c0
jmp 0x3bdd
jmp 0x3bda
jmp 0x3bda
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x20c0
movq %rbx, %rdi
callq 0x2290
nop