// File: /workspace/github_cpp_makefile_star2_O3/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 %r12
pushq %rbx
subq $0x80, %rsp
movq %rsi, %r14
movq %rdi, %rbx
movb 0x38(%rsi), %al
movl $0x20, %ebp
movzbl %al, %ecx
cmpl $0xc, %ecx
jg 0x3d3f
cmpl $0x9, %ecx
je 0x3d63
cmpl $0xa, %ecx
je 0x3d5f
jmp 0x3d72
cmpl $0x20, %ecx
je 0x3d63
cmpl $0xd, %ecx
jne 0x3d72
movq 0x30(%r14), %rdi
callq 0x2200
movl %eax, %ecx
cmpb $0xa, %al
cmovel %ebp, %ecx
movb %cl, 0x38(%r14)
jne 0x3d72
incl 0x3c(%r14)
movq 0x30(%r14), %rdi
callq 0x2200
movb %al, 0x38(%r14)
jmp 0x3d2b
cmpb $0x2f, %al
jne 0x3dc3
movq 0x30(%r14), %rdi
callq 0x2200
movzbl %al, %ecx
movl %eax, %edx
cmpl $0x2f, %ecx
cmovel %ebp, %edx
movb %dl, 0x38(%r14)
jne 0x3dc3
movb $0x20, %al
cmpb $0xd, %al
je 0x3da0
movzbl %al, %eax
cmpl $0xa, %eax
jne 0x3db4
jmp 0x3d5f
movq 0x30(%r14), %rdi
callq 0x2200
cmpb $0xa, %al
cmovel %ebp, %eax
movb %al, 0x38(%r14)
je 0x3d5f
movq 0x30(%r14), %rdi
callq 0x2200
movb %al, 0x38(%r14)
jmp 0x3d92
movzbl %al, %esi
cmpl $0x3c, %esi
jg 0x3e14
cmpl $0x21, %esi
je 0x3e59
cmpl $0x26, %esi
je 0x3efd
cmpl $0x3c, %esi
jne 0x3eb5
movq 0x30(%r14), %rdi
callq 0x2200
movzbl %al, %ecx
movl $0x20, %edx
cmpl $0x3d, %ecx
cmovnel %eax, %edx
movb %dl, 0x38(%r14)
movq %rbx, %rdi
jne 0x401c
movl $0x12c, %esi            # imm = 0x12C
jmp 0x4036
cmpl $0x3d, %esi
je 0x3e87
cmpl $0x3e, %esi
je 0x3f2b
cmpl $0x7c, %esi
jne 0x3eb5
movq 0x30(%r14), %rdi
callq 0x2200
movzbl %al, %ecx
movl $0x20, %edx
cmpl $0x7c, %ecx
cmovnel %eax, %edx
movb %dl, 0x38(%r14)
movq %rbx, %rdi
jne 0x4023
movl $0x131, %esi            # imm = 0x131
jmp 0x4036
movq 0x30(%r14), %rdi
callq 0x2200
movzbl %al, %ecx
movl $0x20, %edx
cmpl $0x3d, %ecx
cmovnel %eax, %edx
movb %dl, 0x38(%r14)
movq %rbx, %rdi
jne 0x3f59
movl $0x12f, %esi            # imm = 0x12F
jmp 0x4036
movq 0x30(%r14), %rdi
callq 0x2200
movzbl %al, %ecx
movl $0x20, %edx
cmpl $0x3d, %ecx
cmovnel %eax, %edx
movb %dl, 0x38(%r14)
movq %rbx, %rdi
jne 0x3f63
movl $0x12e, %esi            # imm = 0x12E
jmp 0x4036
leal -0x30(%rax), %ecx
cmpb $0x9, %cl
ja 0x3f6d
xorl %r15d, %r15d
leal (%r15,%r15,4), %ecx
movzbl %al, %eax
leal (%rax,%rcx,2), %r15d
addl $-0x30, %r15d
movq 0x30(%r14), %rdi
callq 0x2200
movb %al, 0x38(%r14)
leal -0x30(%rax), %ecx
cmpb $0xa, %cl
jb 0x3ec4
movq %rbx, %rdi
movl $0x100, %esi            # imm = 0x100
movl %r15d, %edx
callq 0x4f12
jmp 0x403b
movq 0x30(%r14), %rdi
callq 0x2200
movzbl %al, %ecx
movl $0x20, %edx
cmpl $0x26, %ecx
cmovnel %eax, %edx
movb %dl, 0x38(%r14)
movq %rbx, %rdi
jne 0x402a
movl $0x130, %esi            # imm = 0x130
jmp 0x4036
movq 0x30(%r14), %rdi
callq 0x2200
movzbl %al, %ecx
movl $0x20, %edx
cmpl $0x3d, %ecx
cmovnel %eax, %edx
movb %dl, 0x38(%r14)
movq %rbx, %rdi
jne 0x4031
movl $0x12d, %esi            # imm = 0x12D
jmp 0x4036
movl $0x21, %esi
jmp 0x4036
movl $0x3d, %esi
jmp 0x4036
movl %eax, %ecx
andb $-0x21, %cl
addb $-0x41, %cl
cmpb $0x19, %cl
ja 0x404e
leaq 0x10(%rsp), %r12
movq %r12, -0x10(%r12)
movq $0x0, -0x8(%r12)
movb $0x0, (%r12)
movq %rsp, %r15
movsbl %al, %esi
movq %r15, %rdi
callq 0x2130
movq 0x30(%r14), %rdi
callq 0x2200
movb %al, 0x38(%r14)
leal -0x30(%rax), %ecx
cmpb $0xa, %cl
setb %cl
leal -0x61(%rax), %edx
cmpb $0x1a, %dl
setb %dl
orb %cl, %dl
jne 0x3f99
movq %rsp, %rsi
movq %r14, %rdi
callq 0x4456
addq $0x8, %r14
cmpq %r14, %rax
je 0x40e4
movzwl 0x40(%rax), %ebp
leaq 0x70(%rsp), %r14
movq %r14, -0x10(%r14)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
addq %rsi, %rdx
leaq 0x60(%rsp), %rdi
callq 0x3306
movswl %bp, %esi
leaq 0x60(%rsp), %rdx
movq %rbx, %rdi
callq 0x4f2e
movq 0x60(%rsp), %rdi
jmp 0x411a
movl $0x3c, %esi
jmp 0x4036
movl $0x7c, %esi
jmp 0x4036
movl $0x26, %esi
jmp 0x4036
movl $0x3e, %esi
callq 0x4ef2
movq %rbx, %rax
addq $0x80, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
cmpb $0x22, %al
jne 0x408b
leaq 0x10(%rsp), %r12
movq %r12, -0x10(%r12)
movq $0x0, -0x8(%r12)
movb $0x0, (%r12)
movq %rsp, %r15
movq 0x30(%r14), %rdi
callq 0x2200
movb %al, 0x38(%r14)
cmpb $0x22, %al
je 0x4095
movsbl %al, %esi
movq %r15, %rdi
callq 0x2130
jmp 0x406d
movb $0x20, 0x38(%r14)
movq %rbx, %rdi
jmp 0x4036
movq 0x30(%r14), %rdi
callq 0x2200
movb %al, 0x38(%r14)
leaq 0x30(%rsp), %r14
movq %r14, -0x10(%r14)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
addq %rsi, %rdx
leaq 0x20(%rsp), %rdi
callq 0x3306
leaq 0x20(%rsp), %rdx
movq %rbx, %rdi
movl $0x101, %esi            # imm = 0x101
callq 0x4f2e
movq 0x20(%rsp), %rdi
cmpq %r14, %rdi
je 0x412a
movq 0x30(%rsp), %rsi
jmp 0x4122
leaq 0x50(%rsp), %r14
movq %r14, -0x10(%r14)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
addq %rsi, %rdx
leaq 0x40(%rsp), %rdi
callq 0x3306
leaq 0x40(%rsp), %rdx
movq %rbx, %rdi
movl $0x102, %esi            # imm = 0x102
callq 0x4f2e
movq 0x40(%rsp), %rdi
cmpq %r14, %rdi
je 0x412a
movq (%r14), %rsi
incq %rsi
callq 0x2160
movq (%rsp), %rdi
cmpq %r12, %rdi
je 0x403b
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x2160
jmp 0x403b
movq %rax, %rbx
movq 0x40(%rsp), %rdi
cmpq %r14, %rdi
je 0x4196
movq 0x50(%rsp), %rsi
jmp 0x4185
movq %rax, %rbx
movq 0x20(%rsp), %rdi
cmpq %r14, %rdi
je 0x4196
movq 0x30(%rsp), %rsi
jmp 0x4185
jmp 0x4193
movq %rax, %rbx
movq 0x60(%rsp), %rdi
cmpq %r14, %rdi
je 0x4196
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x2160
jmp 0x4196
jmp 0x4193
jmp 0x4193
movq %rax, %rbx
movq (%rsp), %rdi
cmpq %r12, %rdi
je 0x41ac
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x2160
movq %rbx, %rdi
callq 0x2250