// File: /workspace/github_cpp_makefile_star2_O2/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, %r12      # imm = 0x100000000
movq (%rdi), %rdx
movl 0x20(%rdi), %r13d
movq %rdx, -0x78(%rbp)
movslq %r13d, %r15
leal 0x1(%r15), %r13d
leaq (%rdx,%r15), %rax
shlq $0x20, %r15
addq %r12, %r15
movl %r13d, 0x20(%rbx)
movzbl (%rax), %r14d
cmpl $0x20, %r14d
je 0x4e8f
cmpl $0xa, %r14d
jne 0x4e97
incl %r13d
incq %rax
jmp 0x4e78
movsbl %r14b, %edi
movq %rdi, -0x80(%rbp)
callq 0x3300
movq -0x80(%rbp), %rcx
cmpb $0x5f, %cl
je 0x4fb3
testl %eax, %eax
jne 0x4fb3
cmpb $0x2e, %r14b
je 0x5059
leal -0x30(%rcx), %eax
cmpl $0x9, %eax
jbe 0x5059
cmpb $0x2f, %r14b
jne 0x4f50
sarq $0x20, %r15
movq -0x78(%rbp), %rdx
cmpb $0x2f, (%rdx,%r15)
jne 0x5236
movslq %r13d, %rax
addq %rdx, %rax
incl %r13d
movl %r13d, 0x20(%rbx)
movzbl (%rax), %ecx
cmpl $0xa, %ecx
je 0x4e69
incq %rax
testl %ecx, %ecx
jne 0x4eee
leaq -0x48(%rbp), %rsi
orl $-0x1, (%rsi)
addq $0x28, %rbx
leaq 0x7205(%rip), %rax      # 0xc11f
movq %rax, 0x8(%rsi)
leaq -0x70(%rbp), %r14
movq %r14, %rdi
callq 0x54b4
movq %rbx, %rdi
movq %r14, %rsi
callq 0x54d8
leaq -0x68(%rbp), %rdi
callq 0x33a8
pushq $-0x1
popq %rax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movzbl %r14b, %eax
cmpl $0x3e, %eax
je 0x51e4
cmpl $0x21, %eax
movq -0x78(%rbp), %rdx
je 0x50ee
cmpl $0x3c, %eax
je 0x5140
cmpl $0x3d, %eax
je 0x5192
testl %eax, %eax
jne 0x5236
leaq -0x48(%rbp), %rsi
orl $-0x1, (%rsi)
addq $0x28, %rbx
leaq 0x7189(%rip), %rax      # 0xc11f
movq %rax, 0x8(%rsi)
leaq -0x70(%rbp), %r14
movq %r14, %rdi
callq 0x54b4
movq %rbx, %rdi
movq %r14, %rsi
callq 0x54d8
jmp 0x4f35
leaq -0x38(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq -0x48(%rbp), %rdi
movl %ecx, %esi
callq 0x3190
leaq -0x48(%rbp), %r14
movslq 0x20(%rbx), %r12
leal 0x1(%r12), %eax
movl %eax, 0x20(%rbx)
movq (%rbx), %rax
movsbl (%rax,%r12), %r15d
movl %r15d, %edi
callq 0x31f0
cmpl $0x5f, %r15d
je 0x4ff8
testl %eax, %eax
je 0x5006
movsbl %r15b, %esi
movq %r14, %rdi
callq 0x3190
jmp 0x4fd2
movl %r12d, 0x20(%rbx)
leaq 0x70cf(%rip), %rsi      # 0xc0e0
leaq -0x48(%rbp), %rdi
callq 0x54a3
testb %al, %al
je 0x52bf
leaq -0x68(%rbp), %r14
movl $0x6, -0x8(%r14)
leaq -0x48(%rbp), %rsi
movq %r14, %rdi
callq 0x3290
addq $0x28, %rbx
leaq -0x70(%rbp), %rsi
movq %rbx, %rdi
callq 0x54d8
movq %r14, %rdi
callq 0x33a8
pushq $0x6
jmp 0x53e3
leaq -0x38(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq -0x48(%rbp), %rdi
movl %ecx, %esi
callq 0x3190
leaq -0x48(%rbp), %r14
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 0x50ab
movsbl %cl, %esi
movq %r14, %rdi
callq 0x3190
jmp 0x5078
movl %eax, 0x20(%rbx)
leaq -0x68(%rbp), %r14
movl $0x1, -0x8(%r14)
leaq -0x48(%rbp), %rsi
movq %r14, %rdi
callq 0x3290
addq $0x28, %rbx
leaq -0x70(%rbp), %rsi
movq %rbx, %rdi
callq 0x54d8
movq %r14, %rdi
callq 0x33a8
leaq -0x48(%rbp), %rdi
callq 0x33a8
pushq $0x1
jmp 0x4f40
sarq $0x20, %r15
cmpb $0x3d, (%rdx,%r15)
jne 0x5236
leaq 0x28(%rbx), %r14
leaq -0x48(%rbp), %rsi
movl $0x5, (%rsi)
leaq 0x6ff0(%rip), %rax      # 0xc102
movq %rax, 0x8(%rsi)
leaq -0x70(%rbp), %r15
movq %r15, %rdi
callq 0x54b4
movq %r14, %rdi
movq %r15, %rsi
callq 0x54d8
leaq -0x68(%rbp), %rdi
callq 0x33a8
incl 0x20(%rbx)
pushq $0x5
jmp 0x4f40
sarq $0x20, %r15
cmpb $0x3d, (%rdx,%r15)
jne 0x5236
leaq 0x28(%rbx), %r14
leaq -0x48(%rbp), %rsi
movl $0x3, (%rsi)
leaq 0x6f98(%rip), %rax      # 0xc0fc
movq %rax, 0x8(%rsi)
leaq -0x70(%rbp), %r15
movq %r15, %rdi
callq 0x54b4
movq %r14, %rdi
movq %r15, %rsi
callq 0x54d8
leaq -0x68(%rbp), %rdi
callq 0x33a8
incl 0x20(%rbx)
pushq $0x3
jmp 0x4f40
sarq $0x20, %r15
cmpb $0x3d, (%rdx,%r15)
jne 0x5236
leaq 0x28(%rbx), %r14
leaq -0x48(%rbp), %rsi
movl $0x4, (%rsi)
leaq 0x6f49(%rip), %rax      # 0xc0ff
movq %rax, 0x8(%rsi)
leaq -0x70(%rbp), %r15
movq %r15, %rdi
callq 0x54b4
movq %r14, %rdi
movq %r15, %rsi
callq 0x54d8
leaq -0x68(%rbp), %rdi
callq 0x33a8
incl 0x20(%rbx)
pushq $0x4
jmp 0x4f40
sarq $0x20, %r15
movq -0x78(%rbp), %rax
cmpb $0x3d, (%rax,%r15)
jne 0x5236
leaq 0x28(%rbx), %r14
leaq -0x48(%rbp), %rsi
movl $0x2, (%rsi)
leaq 0x6ef1(%rip), %rax      # 0xc0f9
movq %rax, 0x8(%rsi)
leaq -0x70(%rbp), %r15
movq %r15, %rdi
callq 0x54b4
movq %r14, %rdi
movq %r15, %rsi
callq 0x54d8
leaq -0x68(%rbp), %rdi
callq 0x33a8
incl 0x20(%rbx)
pushq $0x2
jmp 0x4f40
leaq -0x38(%rbp), %r14
movq %r14, -0x10(%r14)
leaq -0x48(%rbp), %rdi
pushq $0x1
popq %rsi
movq %rcx, %r15
movl %r15d, %edx
callq 0x3220
addq $0x28, %rbx
leaq -0x58(%rbp), %rax
movl %r15d, -0x18(%rax)
movq %rax, -0x10(%rax)
movq -0x48(%rbp), %rcx
movq %r15, %r12
cmpq %r14, %rcx
je 0x527a
movq %rcx, -0x68(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x58(%rbp)
jmp 0x5281
movups (%r14), %xmm0
movups %xmm0, (%rax)
leaq -0x68(%rbp), %r15
movq -0x40(%rbp), %rax
movq %rax, 0x8(%r15)
movq %r14, -0x48(%rbp)
andq $0x0, -0x40(%rbp)
movb $0x0, -0x38(%rbp)
leaq -0x70(%rbp), %rsi
movq %rbx, %rdi
callq 0x54d8
movq %r15, %rdi
callq 0x33a8
leaq -0x48(%rbp), %rdi
callq 0x33a8
movq %r12, %rax
jmp 0x4f41
leaq 0x6e1d(%rip), %rsi      # 0xc0e3
leaq -0x48(%rbp), %rdi
callq 0x54a3
testb %al, %al
je 0x530a
leaq -0x68(%rbp), %r14
movl $0x7, -0x8(%r14)
leaq -0x48(%rbp), %rsi
movq %r14, %rdi
callq 0x3290
addq $0x28, %rbx
leaq -0x70(%rbp), %rsi
movq %rbx, %rdi
callq 0x54d8
movq %r14, %rdi
callq 0x33a8
pushq $0x7
jmp 0x53e3
leaq 0x6dd7(%rip), %rsi      # 0xc0e8
leaq -0x48(%rbp), %rdi
callq 0x54a3
testb %al, %al
je 0x5355
leaq -0x68(%rbp), %r14
movl $0x8, -0x8(%r14)
leaq -0x48(%rbp), %rsi
movq %r14, %rdi
callq 0x3290
addq $0x28, %rbx
leaq -0x70(%rbp), %rsi
movq %rbx, %rdi
callq 0x54d8
movq %r14, %rdi
callq 0x33a8
pushq $0x8
jmp 0x53e3
leaq 0x6d92(%rip), %rsi      # 0xc0ee
leaq -0x48(%rbp), %rdi
callq 0x54a3
testb %al, %al
je 0x539d
leaq -0x68(%rbp), %r14
movl $0xa, -0x8(%r14)
leaq -0x48(%rbp), %rsi
movq %r14, %rdi
callq 0x3290
addq $0x28, %rbx
leaq -0x70(%rbp), %rsi
movq %rbx, %rdi
callq 0x54d8
movq %r14, %rdi
callq 0x33a8
pushq $0xa
jmp 0x53e3
leaq 0x6d4e(%rip), %rsi      # 0xc0f2
leaq -0x48(%rbp), %rdi
callq 0x54a3
leaq -0x68(%rbp), %r14
testb %al, %al
je 0x53f5
movl $0x9, -0x8(%r14)
leaq -0x48(%rbp), %rsi
movq %r14, %rdi
callq 0x3290
addq $0x28, %rbx
leaq -0x70(%rbp), %rsi
movq %rbx, %rdi
callq 0x54d8
movq %r14, %rdi
callq 0x33a8
pushq $0x9
popq %rbx
leaq -0x48(%rbp), %rdi
callq 0x33a8
movq %rbx, %rax
jmp 0x4f41
andl $0x0, -0x8(%r14)
leaq -0x48(%rbp), %rsi
movq %r14, %rdi
callq 0x3290
addq $0x28, %rbx
leaq -0x70(%rbp), %rsi
movq %rbx, %rdi
callq 0x54d8
movq %r14, %rdi
callq 0x33a8
xorl %ebx, %ebx
jmp 0x53e4
jmp 0x5444
jmp 0x546f
jmp 0x5444
jmp 0x546f
jmp 0x5444
jmp 0x546f
jmp 0x5444
jmp 0x546f
jmp 0x5444
jmp 0x546f
jmp 0x5464
jmp 0x5464
jmp 0x5464
jmp 0x5464
jmp 0x5444
jmp 0x546f
jmp 0x5464
movq %rax, %rbx
movq %r14, %rdi
jmp 0x5458
jmp 0x546f
jmp 0x546f
jmp 0x546f
movq %rax, %rbx
movq %r15, %rdi
callq 0x33a8
jmp 0x5472
movq %rax, %rbx
jmp 0x547b
movq %rax, %rbx
leaq -0x68(%rbp), %rdi
jmp 0x5476
jmp 0x546f
movq %rax, %rbx
leaq -0x48(%rbp), %rdi
callq 0x33a8
movq %rbx, %rdi
callq 0x3350
nop