// File: /workspace/github_cpp_makefile_star2_O3/KJTang[P]SimpleCompiler/Lexer.cpp
// Function: Lexer::lexToken()
Token Lexer::lexToken() {
    char curChar = lexingStr[lexingPos++];
    // shift space and '\n'
    while (curChar == ' ' || curChar == '\n') {
        curChar = lexingStr[lexingPos++];
    }
    // identifier
    // def: start with [a-zA-Z_], follow by [a-zA-Z_0-9]
    if (isalpha(curChar) || curChar == '_') {
        std::string identifierName;
        identifierName += curChar;
        curChar = lexingStr[lexingPos++];
        while (isalnum(curChar) || curChar == '_') {
            identifierName += curChar;
            curChar = lexingStr[lexingPos++];
        }
        --lexingPos;
        if (identifierName == "if") {
            tokens.push_back(std::make_pair(Token::KEYWORD_IF, identifierName));
            return Token::KEYWORD_IF;
        } else if (identifierName == "else") {
            tokens.push_back(std::make_pair(Token::KEYWORD_ELSE, identifierName));
            return Token::KEYWORD_ELSE;
        } else if (identifierName == "while") {
            tokens.push_back(std::make_pair(Token::KEYWORD_WHILE, identifierName));
            return Token::KEYWORD_WHILE;
        } else if (identifierName == "int") {
            tokens.push_back(std::make_pair(Token::TYPE_INT, identifierName));
            return Token::TYPE_INT;
        } else if (identifierName == "return") {
            tokens.push_back(std::make_pair(Token::KEYWORD_RET, identifierName));
            return Token::KEYWORD_RET;
        }
        tokens.push_back(std::make_pair(Token::IDENTIFIER, identifierName));
        return Token::IDENTIFIER;
    }
    // number
    // def: start with [0-9.], follow by [0-9.]
    // number only has 'double' type
    if (isdigit(curChar) || curChar == '.') {
        std::string numberStr;
        numberStr += curChar;
        curChar = lexingStr[lexingPos++];
        while (isdigit(curChar) || curChar == '.') {
            numberStr += curChar;
            curChar = lexingStr[lexingPos++];
        }
        --lexingPos;
        tokens.push_back(std::make_pair(Token::NUMBER, numberStr));
        return Token::NUMBER;
    }
    switch (curChar) {
        // end of file
        case '\0': {
            tokens.push_back(std::make_pair(Token::END_OF_FILE, "\0"));
            return Token::END_OF_FILE;
        }
        case '>': {
            if (lexingStr[lexingPos] == '=') {
                tokens.push_back(std::make_pair(Token::OP_GTE, ">="));
                ++lexingPos;
                return Token::OP_GTE;
            }
            goto ASCII;
        }
        case '<': {
            if (lexingStr[lexingPos] == '=') {
                tokens.push_back(std::make_pair(Token::OP_LTE, "<="));
                ++lexingPos;
                return Token::OP_LTE;
            }
            goto ASCII;
        }
        case '=': {
            if (lexingStr[lexingPos] == '=') {
                tokens.push_back(std::make_pair(Token::OP_EQU, "=="));
                ++lexingPos;
                return Token::OP_EQU;
            }
            goto ASCII;
        }
        case '!': {
            if (lexingStr[lexingPos] == '=') {
                tokens.push_back(std::make_pair(Token::OP_NE, "!="));
                ++lexingPos;
                return Token::OP_NE;
            }
            goto ASCII;
        }
        // comment
        // def: start with "//", will comment one line
        case '/': {
            if (lexingStr[lexingPos] == '/') {
                do {
                    curChar = lexingStr[lexingPos++];
                } while (curChar != '\0' && curChar != '\n');
                if (curChar != '\0') {
                    return this->lexToken();
                } else {
                    tokens.push_back(std::make_pair(Token::END_OF_FILE, "\0"));
                    return Token::END_OF_FILE;
                }
            }
            // if not '//', jump to ascii
            goto ASCII;
        }
        // ascii
        default: {
            ASCII:
            tokens.push_back(std::make_pair((Token)curChar, std::string(1, curChar)));
            return (Token)curChar;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdi, %rbx
movabsq $0x100000000, %r13      # imm = 0x100000000
movq (%rdi), %rdx
movl 0x20(%rdi), %r15d
movq %rdx, -0x78(%rbp)
movslq %r15d, %r12
leal 0x1(%r12), %r15d
leaq (%rdx,%r12), %rax
shlq $0x20, %r12
addq %r13, %r12
movl %r15d, 0x20(%rbx)
movzbl (%rax), %r14d
cmpl $0x20, %r14d
je 0x5298
cmpl $0xa, %r14d
jne 0x52a0
incl %r15d
incq %rax
jmp 0x5281
movsbl %r14b, %edi
movq %rdi, -0x80(%rbp)
callq 0x32e0
movq -0x80(%rbp), %rcx
cmpb $0x5f, %cl
je 0x5455
testl %eax, %eax
jne 0x5455
cmpb $0x2e, %r14b
je 0x5595
leal -0x30(%rcx), %eax
cmpl $0x9, %eax
jbe 0x5595
cmpb $0x2f, %r14b
jne 0x5366
sarq $0x20, %r12
movq -0x78(%rbp), %rdx
cmpb $0x2f, (%rdx,%r12)
jne 0x571f
movslq %r15d, %rax
addq %rdx, %rax
incl %r15d
movl %r15d, 0x20(%rbx)
movzbl (%rax), %ecx
cmpl $0xa, %ecx
je 0x5271
incq %rax
testl %ecx, %ecx
jne 0x52fb
addq $0x28, %rbx
leaq -0x48(%rbp), %rdi
movl $0xffffffff, -0x8(%rdi) # imm = 0xFFFFFFFF
leaq 0x9e1c(%rip), %rsi      # 0xf147
leaq -0x70(%rbp), %rdx
callq 0x30e0
leaq -0x50(%rbp), %rsi
movq %rbx, %rdi
callq 0x5a16
leaq -0x38(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x5352
callq 0x31c0
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movzbl %r14b, %eax
cmpl $0x3b, %eax
jle 0x53e7
cmpl $0x3c, %eax
je 0x566d
cmpl $0x3d, %eax
movq -0x78(%rbp), %rdx
je 0x56ca
cmpl $0x3e, %eax
jne 0x571f
sarq $0x20, %r12
cmpb $0x3d, (%rdx,%r12)
jne 0x571f
leaq 0x28(%rbx), %r14
leaq -0x48(%rbp), %rdi
movl $0x2, -0x8(%rdi)
leaq 0x9d6e(%rip), %rsi      # 0xf121
leaq -0x70(%rbp), %rdx
callq 0x30e0
leaq -0x50(%rbp), %rsi
movq %r14, %rdi
callq 0x5a16
leaq -0x38(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x53da
callq 0x31c0
incl 0x20(%rbx)
movl $0x2, %eax
jmp 0x5357
testl %eax, %eax
je 0x57b2
cmpl $0x21, %eax
movq -0x78(%rbp), %rax
jne 0x571f
sarq $0x20, %r12
cmpb $0x3d, (%rax,%r12)
jne 0x571f
leaq 0x28(%rbx), %r14
leaq -0x48(%rbp), %rdi
movl $0x5, -0x8(%rdi)
leaq 0x9d09(%rip), %rsi      # 0xf12a
leaq -0x70(%rbp), %rdx
callq 0x30e0
leaq -0x50(%rbp), %rsi
movq %r14, %rdi
callq 0x5a16
leaq -0x38(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x5448
callq 0x31c0
incl 0x20(%rbx)
movl $0x5, %eax
jmp 0x5357
leaq -0x60(%rbp), %r12
movq %r12, -0x10(%r12)
movq $0x0, -0x8(%r12)
movb $0x0, (%r12)
leaq -0x70(%rbp), %rdi
movl %ecx, %esi
callq 0x31a0
movslq 0x20(%rbx), %r13
leal 0x1(%r13), %eax
movl %eax, 0x20(%rbx)
movq (%rbx), %rax
movsbl (%rax,%r13), %r14d
movl %r14d, %edi
callq 0x31f0
cmpl $0x5f, %r14d
je 0x549c
testl %eax, %eax
je 0x54d1
leaq -0x70(%rbp), %r15
movsbl %r14b, %esi
movq %r15, %rdi
callq 0x31a0
movslq 0x20(%rbx), %r13
leal 0x1(%r13), %eax
movl %eax, 0x20(%rbx)
movq (%rbx), %rax
movsbl (%rax,%r13), %r14d
movl %r14d, %edi
callq 0x31f0
cmpl $0x5f, %r14d
je 0x54a0
testl %eax, %eax
jne 0x54a0
movl %r13d, 0x20(%rbx)
leaq 0x9c2c(%rip), %rsi      # 0xf108
leaq -0x70(%rbp), %rdi
callq 0x30a0
testl %eax, %eax
je 0x57e2
leaq 0x9c17(%rip), %rsi      # 0xf10b
leaq -0x70(%rbp), %rdi
callq 0x30a0
testl %eax, %eax
je 0x582d
leaq 0x9c04(%rip), %rsi      # 0xf110
leaq -0x70(%rbp), %rdi
callq 0x30a0
testl %eax, %eax
je 0x5878
leaq 0x9bf2(%rip), %rsi      # 0xf116
leaq -0x70(%rbp), %rdi
callq 0x30a0
testl %eax, %eax
je 0x58c3
leaq 0x9bde(%rip), %rsi      # 0xf11a
leaq -0x70(%rbp), %rdi
callq 0x30a0
leaq -0x48(%rbp), %rdi
testl %eax, %eax
je 0x590b
movl $0x0, -0x8(%rdi)
leaq -0x38(%rbp), %r14
movq %r14, -0x10(%r14)
movq -0x70(%rbp), %rsi
movq -0x68(%rbp), %rdx
addq %rsi, %rdx
callq 0x42b0
addq $0x28, %rbx
leaq -0x50(%rbp), %rsi
movq %rbx, %rdi
callq 0x5a16
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x558e
callq 0x31c0
xorl %eax, %eax
jmp 0x594d
leaq -0x60(%rbp), %r15
movq %r15, -0x10(%r15)
movq $0x0, -0x8(%r15)
movb $0x0, (%r15)
leaq -0x70(%rbp), %rdi
movl %ecx, %esi
callq 0x31a0
movslq 0x20(%rbx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x20(%rbx)
movq (%rbx), %rcx
movsbl (%rcx,%rax), %ecx
cmpl $0x2e, %ecx
setne %dl
leal -0x30(%rcx), %esi
cmpl $0xa, %esi
setae %sil
testb %sil, %dl
jne 0x5611
leaq -0x70(%rbp), %r14
movsbl %cl, %esi
movq %r14, %rdi
callq 0x31a0
movslq 0x20(%rbx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x20(%rbx)
movq (%rbx), %rcx
movsbl (%rcx,%rax), %ecx
cmpl $0x2e, %ecx
sete %dl
movl %ecx, %esi
addl $-0x30, %esi
cmpl $0xa, %esi
setb %sil
orb %dl, %sil
jne 0x55de
movl %eax, 0x20(%rbx)
leaq -0x48(%rbp), %rdi
movl $0x1, -0x8(%rdi)
leaq -0x38(%rbp), %r14
movq %r14, -0x10(%r14)
movq -0x70(%rbp), %rsi
movq -0x68(%rbp), %rdx
addq %rsi, %rdx
callq 0x42b0
addq $0x28, %rbx
leaq -0x50(%rbp), %rsi
movq %rbx, %rdi
callq 0x5a16
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x5655
callq 0x31c0
movq -0x70(%rbp), %rdi
cmpq %r15, %rdi
je 0x5663
callq 0x31c0
movl $0x1, %eax
jmp 0x5357
sarq $0x20, %r12
movq -0x78(%rbp), %rax
cmpb $0x3d, (%rax,%r12)
jne 0x571f
leaq 0x28(%rbx), %r14
leaq -0x48(%rbp), %rdi
movl $0x3, -0x8(%rdi)
leaq 0x9a8e(%rip), %rsi      # 0xf124
leaq -0x70(%rbp), %rdx
callq 0x30e0
leaq -0x50(%rbp), %rsi
movq %r14, %rdi
callq 0x5a16
leaq -0x38(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x56bd
callq 0x31c0
incl 0x20(%rbx)
movl $0x3, %eax
jmp 0x5357
sarq $0x20, %r12
cmpb $0x3d, (%rdx,%r12)
jne 0x571f
leaq 0x28(%rbx), %r14
leaq -0x48(%rbp), %rdi
movl $0x4, -0x8(%rdi)
leaq 0x9a3c(%rip), %rsi      # 0xf127
leaq -0x70(%rbp), %rdx
callq 0x30e0
leaq -0x50(%rbp), %rsi
movq %r14, %rdi
callq 0x5a16
leaq -0x38(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x5712
callq 0x31c0
incl 0x20(%rbx)
movl $0x4, %eax
jmp 0x5357
leaq -0x60(%rbp), %r15
movq %r15, -0x10(%r15)
leaq -0x70(%rbp), %rdi
movl $0x1, %esi
movq %rcx, %r12
movl %r12d, %edx
callq 0x3240
addq $0x28, %rbx
leaq -0x38(%rbp), %r14
movl %r12d, -0x18(%r14)
movq %r14, -0x10(%r14)
movq -0x70(%rbp), %rax
cmpq %r15, %rax
je 0x5762
movq %rax, -0x48(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x576a
movups (%r15), %xmm0
movups %xmm0, (%r14)
movq -0x68(%rbp), %rax
leaq -0x50(%rbp), %rsi
movq %rax, 0x10(%rsi)
movq %r15, -0x70(%rbp)
movq $0x0, -0x68(%rbp)
movb $0x0, -0x60(%rbp)
movq %rbx, %rdi
callq 0x5a16
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x579c
callq 0x31c0
movq -0x70(%rbp), %rdi
cmpq %r15, %rdi
je 0x57aa
callq 0x31c0
movq %r12, %rax
jmp 0x5357
addq $0x28, %rbx
leaq -0x48(%rbp), %rdi
movl $0xffffffff, -0x8(%rdi) # imm = 0xFFFFFFFF
leaq 0x997f(%rip), %rsi      # 0xf147
leaq -0x70(%rbp), %rdx
callq 0x30e0
leaq -0x50(%rbp), %rsi
movq %rbx, %rdi
callq 0x5a16
jmp 0x5340
leaq -0x48(%rbp), %rdi
movl $0x6, -0x8(%rdi)
leaq -0x38(%rbp), %r14
movq %r14, -0x10(%r14)
movq -0x70(%rbp), %rsi
movq -0x68(%rbp), %rdx
addq %rsi, %rdx
callq 0x42b0
addq $0x28, %rbx
leaq -0x50(%rbp), %rsi
movq %rbx, %rdi
callq 0x5a16
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x5823
callq 0x31c0
movl $0x6, %eax
jmp 0x594d
leaq -0x48(%rbp), %rdi
movl $0x7, -0x8(%rdi)
leaq -0x38(%rbp), %r14
movq %r14, -0x10(%r14)
movq -0x70(%rbp), %rsi
movq -0x68(%rbp), %rdx
addq %rsi, %rdx
callq 0x42b0
addq $0x28, %rbx
leaq -0x50(%rbp), %rsi
movq %rbx, %rdi
callq 0x5a16
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x586e
callq 0x31c0
movl $0x7, %eax
jmp 0x594d
leaq -0x48(%rbp), %rdi
movl $0x8, -0x8(%rdi)
leaq -0x38(%rbp), %r14
movq %r14, -0x10(%r14)
movq -0x70(%rbp), %rsi
movq -0x68(%rbp), %rdx
addq %rsi, %rdx
callq 0x42b0
addq $0x28, %rbx
leaq -0x50(%rbp), %rsi
movq %rbx, %rdi
callq 0x5a16
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x58b9
callq 0x31c0
movl $0x8, %eax
jmp 0x594d
leaq -0x48(%rbp), %rdi
movl $0xa, -0x8(%rdi)
leaq -0x38(%rbp), %r14
movq %r14, -0x10(%r14)
movq -0x70(%rbp), %rsi
movq -0x68(%rbp), %rdx
addq %rsi, %rdx
callq 0x42b0
addq $0x28, %rbx
leaq -0x50(%rbp), %rsi
movq %rbx, %rdi
callq 0x5a16
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x5904
callq 0x31c0
movl $0xa, %eax
jmp 0x594d
movl $0x9, -0x8(%rdi)
leaq -0x38(%rbp), %r14
movq %r14, -0x10(%r14)
movq -0x70(%rbp), %rsi
movq -0x68(%rbp), %rdx
addq %rsi, %rdx
callq 0x42b0
addq $0x28, %rbx
leaq -0x50(%rbp), %rsi
movq %rbx, %rdi
callq 0x5a16
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x5948
callq 0x31c0
movl $0x9, %eax
movq -0x70(%rbp), %rdi
cmpq %r12, %rdi
je 0x5357
movq %rax, %rbx
callq 0x31c0
movq %rbx, %rax
jmp 0x5357
jmp 0x597e
jmp 0x59e8
jmp 0x597e
jmp 0x59e8
jmp 0x597e
jmp 0x59e8
jmp 0x597e
jmp 0x59e8
jmp 0x597e
jmp 0x59e8
movq %rax, %rbx
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x59eb
callq 0x31c0
jmp 0x59eb
jmp 0x59e8
jmp 0x59bd
jmp 0x59bd
jmp 0x59bd
jmp 0x59bd
jmp 0x59bd
jmp 0x59a5
jmp 0x59cf
jmp 0x59cf
jmp 0x59e8
movq %rax, %rbx
movq -0x48(%rbp), %rdi
cmpq %r14, %rdi
je 0x59d2
callq 0x31c0
jmp 0x59d2
movq %rax, %rbx
jmp 0x59e0
movq %rax, %rbx
leaq -0x38(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
jne 0x59db
jmp 0x59e0
movq %rax, %rbx
movq -0x70(%rbp), %rdi
cmpq %r15, %rdi
je 0x59e0
callq 0x31c0
movq %rbx, %rdi
callq 0x3330
movq %rax, %rbx
movq -0x70(%rbp), %rdi
cmpq %r12, %rdi
jne 0x59db
jmp 0x59e0