// File: /workspace/github_cpp_makefile_star2_O1/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
movl $0x20, %ebp
movzbl 0x38(%r14), %eax
cmpl $0xc, %eax
jg 0x3d6e
cmpl $0x9, %eax
je 0x3d90
cmpl $0xa, %eax
je 0x3d8c
jmp 0x3d9f
cmpl $0x20, %eax
je 0x3d90
cmpl $0xd, %eax
jne 0x3d9f
movq 0x30(%r14), %rdi
callq 0x2200
cmpb $0xa, %al
cmovel %ebp, %eax
movb %al, 0x38(%r14)
jne 0x3d9f
incl 0x3c(%r14)
movq 0x30(%r14), %rdi
callq 0x2200
movb %al, 0x38(%r14)
jmp 0x3d58
cmpb $0x2f, 0x38(%r14)
jne 0x3df2
movq 0x30(%r14), %rdi
callq 0x2200
movzbl %al, %ecx
cmpl $0x2f, %ecx
cmovel %ebp, %eax
movb %al, 0x38(%r14)
jne 0x3df2
movzbl 0x38(%r14), %eax
cmpl $0xd, %eax
je 0x3dcf
cmpl $0xa, %eax
jne 0x3de3
jmp 0x3d8c
movq 0x30(%r14), %rdi
callq 0x2200
cmpb $0xa, %al
cmovel %ebp, %eax
movb %al, 0x38(%r14)
je 0x3d8c
movq 0x30(%r14), %rdi
callq 0x2200
movb %al, 0x38(%r14)
jmp 0x3dbe
movzbl 0x38(%r14), %eax
cmpl $0x3c, %eax
jg 0x3e45
cmpl $0x21, %eax
je 0x3e8a
cmpl $0x26, %eax
je 0x3f2e
cmpl $0x3c, %eax
jne 0x3ee6
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 0x404d
movl $0x12c, %esi            # imm = 0x12C
jmp 0x4067
cmpl $0x3d, %eax
je 0x3eb8
cmpl $0x3e, %eax
je 0x3f5c
cmpl $0x7c, %eax
jne 0x3ee6
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 0x4054
movl $0x131, %esi            # imm = 0x131
jmp 0x4067
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 0x3f8a
movl $0x12f, %esi            # imm = 0x12F
jmp 0x4067
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 0x3f94
movl $0x12e, %esi            # imm = 0x12E
jmp 0x4067
leal -0x30(%rax), %ecx
cmpb $0x9, %cl
ja 0x3f9e
xorl %r15d, %r15d
leal (%r15,%r15,4), %eax
movzbl 0x38(%r14), %ecx
leal (%rcx,%rax,2), %r15d
addl $-0x30, %r15d
movq 0x30(%r14), %rdi
callq 0x2200
movb %al, 0x38(%r14)
addb $-0x30, %al
cmpb $0xa, %al
jb 0x3ef5
movq %rbx, %rdi
movl $0x100, %esi            # imm = 0x100
movl %r15d, %edx
callq 0x4f4e
jmp 0x406c
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 0x405b
movl $0x130, %esi            # imm = 0x130
jmp 0x4067
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 0x4062
movl $0x12d, %esi            # imm = 0x12D
jmp 0x4067
movl $0x21, %esi
jmp 0x4067
movl $0x3d, %esi
jmp 0x4067
movl %eax, %ecx
andb $-0x21, %cl
addb $-0x41, %cl
cmpb $0x19, %cl
ja 0x407f
leaq 0x10(%rsp), %r12
movq %r12, -0x10(%r12)
movq $0x0, -0x8(%r12)
movb $0x0, (%r12)
movq %rsp, %r15
movsbl 0x38(%r14), %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
addb $-0x61, %al
cmpb $0x1a, %al
setb %al
orb %cl, %al
jne 0x3fca
movq %rsp, %rsi
movq %r14, %rdi
callq 0x448a
addq $0x8, %r14
cmpq %r14, %rax
je 0x4118
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 0x3344
movswl %bp, %esi
leaq 0x60(%rsp), %rdx
movq %rbx, %rdi
callq 0x4f6a
movq 0x60(%rsp), %rdi
jmp 0x414e
movl $0x3c, %esi
jmp 0x4067
movl $0x7c, %esi
jmp 0x4067
movl $0x26, %esi
jmp 0x4067
movl $0x3e, %esi
callq 0x4f2e
movq %rbx, %rax
addq $0x80, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
cmpb $0x22, %al
jne 0x40bc
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 0x40c9
movsbl %al, %esi
movq %r15, %rdi
callq 0x2130
jmp 0x409e
movb $0x20, 0x38(%r14)
movzwl %ax, %esi
movq %rbx, %rdi
jmp 0x4067
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 0x3344
leaq 0x20(%rsp), %rdx
movq %rbx, %rdi
movl $0x101, %esi            # imm = 0x101
callq 0x4f6a
movq 0x20(%rsp), %rdi
cmpq %r14, %rdi
je 0x415e
movq 0x30(%rsp), %rsi
jmp 0x4156
leaq 0x50(%rsp), %r14
movq %r14, -0x10(%r14)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
addq %rsi, %rdx
leaq 0x40(%rsp), %rdi
callq 0x3344
leaq 0x40(%rsp), %rdx
movq %rbx, %rdi
movl $0x102, %esi            # imm = 0x102
callq 0x4f6a
movq 0x40(%rsp), %rdi
cmpq %r14, %rdi
je 0x415e
movq (%r14), %rsi
incq %rsi
callq 0x2160
movq (%rsp), %rdi
cmpq %r12, %rdi
je 0x406c
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x2160
jmp 0x406c
movq %rax, %rbx
movq 0x40(%rsp), %rdi
cmpq %r14, %rdi
je 0x41ca
movq 0x50(%rsp), %rsi
jmp 0x41b9
movq %rax, %rbx
movq 0x20(%rsp), %rdi
cmpq %r14, %rdi
je 0x41ca
movq 0x30(%rsp), %rsi
jmp 0x41b9
jmp 0x41c7
movq %rax, %rbx
movq 0x60(%rsp), %rdi
cmpq %r14, %rdi
je 0x41ca
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x2160
jmp 0x41ca
jmp 0x41c7
jmp 0x41c7
movq %rax, %rbx
movq (%rsp), %rdi
cmpq %r12, %rdi
je 0x41e0
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x2160
movq %rbx, %rdi
callq 0x2250