// File: JameyWoo[P]csmile/scan.cpp
// Function: getToken()
Token getToken() {        // 获取token, 主函数里循环调用
    string currentToken;  // 当前token
    string token_value;
    int line;
    StateType state = START;
    bool save;  // save 表示是否保存该字符
    while (state != DONE) {
        char c = getNextChar(line);
        save   = true;                                               // 默认不返回
        if ((c == ' ') || (c == '\t') || (c == '\n')) save = false;  // ! 修复<, >后面接空格的bug
        switch (state) {
            case START:
                if (isdigit(c))
                    state = INNUM;
                else if (isalpha(c) || c == '_')
                    state = INID;
                else if ((c == ' ') || (c == '\t') || (c == '\n'))  // 这条还是不能少
                    save = false;
                else if (c == '<') {
                    state = COMPARE1;
                } else if (c == '>') {
                    state = COMPARE2;
                } else if (c == '/') {
                    state = INCOMMENT;
                } else if (c == '-') {
                    state = INNEGATIVE;
                } else if (c == '=') {
                    state = INASSIGN;
                } else if (c == '!') {  // 不等于判断
                    state = INNE;
                } else if (c == EOF) {
                    save         = false;
                    state        = DONE;
                    currentToken = "EndFile";
                } else {
                    state = DONE;  // 下面的都是单个字符出现的, 统一状态DONE
                    switch (c) {
                        case '(':
                            currentToken = "LeftBracket";
                            break;
                        case ')':
                            currentToken = "RightBracket";
                            break;
                        case '{':
                            currentToken = "LeftBigBkt";
                            break;
                        case '}':
                            currentToken = "RightBigBkt";
                            break;
                        case ';':
                            currentToken = "Semicolon";
                            break;
                        case '+':
                            currentToken = "PMOP";
                            break;
                        // - 有些特殊, 他可能是负数的开始
                        case '*':
                            currentToken = "MDOP";
                            break;
                        case ',':
                            currentToken = "Comma";
                            break;
                        default:
                            currentToken = "ErrorToken";
                    }
                }
                break;  // ! 由于没有写break引发的惨案...
            case INNUM:
                if (not isdigit(c)) {
                    rollback();
                    state        = DONE;
                    currentToken = "Num";
                    save         = false;  // rollback了不保存
                }
                break;
            case INID:
                if (not(isalpha(c) or isdigit(c) or c == '_')) {  // 如果不是字母和数字
                    rollback();
                    save         = false;
                    state        = DONE;
                    currentToken = "Id";
                }
                break;
            case INASSIGN:
                if (c == '=') {
                    state        = DONE;
                    currentToken = "CompareOp";
                } else {
                    rollback();
                    save         = false;
                    state        = DONE;
                    currentToken = "Assign";
                }
                break;
            case INCOMMENT:
                if (c == '*') {
                    state = INCOMMENT2;
                } else {
                    save = false;
                    rollback();
                    state        = DONE;
                    currentToken = "MDOP";
                }
                break;
            case INCOMMENT2:
                if (c != '*') {
                    state = INCOMMENT2;
                    save  = true;  // 让注释的空格保存下来
                    if (c == EOF) {
                        state        = DONE;
                        currentToken = "ErrorToken";
                    }
                } else
                    state = INCOMMENT3;
                break;
            case INCOMMENT3:
                if (c == '/') {
                    state        = DONE;
                    currentToken = "Comment";
                } else {
                    state = INCOMMENT2;
                }
                break;
            case COMPARE1:                        // 检测到<之后到这个状态来
                if (not(c == '=' || c == '>')) {  // <= 或者 <> 不等于
                    rollback();
                    save = false;
                }
                state        = DONE;
                currentToken = "CompareOp";
                break;
            case COMPARE2:
                if (c != '=') {
                    rollback();

                    save = false;
                }
                state        = DONE;
                currentToken = "CompareOp";
                break;
            case INNEGATIVE:
                if (isdigit(c)) {
                    state = INNUM;
                } else {
                    rollback();
                    save         = false;
                    state        = DONE;
                    currentToken = "PMOP";
                }
                break;
            case INNE:
                if (c == '=') {  // 不等于
                    state        = DONE;
                    currentToken = "CompareOp";
                } else {
                    currentToken = "ErrorToken";
                    state        = DONE;
                }
                break;
            case DONE:
            default:
                currentToken = "ErrorToken";
        }
        if (save) token_value += c;
    }
    if (count(reversedWords.begin(), reversedWords.end(), token_value) != 0)  // 判断Id是否为保留字
        currentToken = token_value;
    Token token;
    token.setToken(currentToken, token_value, line + 1);  // 行号从1开始
    tokens.push_back(token);                              // 保存token
    if (token.type == "Comment") return getToken();       // 忽略注释
    return token;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x150, %rsp            # imm = 0x150
movq %rdi, -0x118(%rbp)
movq %rdi, %rax
movq %rax, -0x110(%rbp)
movq %rdi, -0x8(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x33b0
leaq -0x48(%rbp), %rdi
callq 0x33b0
movl $0x0, -0x50(%rbp)
cmpl $0x4, -0x50(%rbp)
je 0x5a15
leaq -0x4c(%rbp), %rdi
callq 0x5350
movb %al, -0x119(%rbp)
jmp 0x54b4
movb -0x119(%rbp), %al
movb %al, -0x52(%rbp)
movb $0x1, -0x51(%rbp)
movsbl -0x52(%rbp), %eax
cmpl $0x20, %eax
je 0x54dc
movsbl -0x52(%rbp), %eax
cmpl $0x9, %eax
je 0x54dc
movsbl -0x52(%rbp), %eax
cmpl $0xa, %eax
jne 0x54f3
movb $0x0, -0x51(%rbp)
jmp 0x54f3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x5bcc
movl -0x50(%rbp), %eax
movq %rax, -0x128(%rbp)
subq $0xb, %rax
ja 0x59e5
movq -0x128(%rbp), %rax
leaq 0x1bb33(%rip), %rcx     # 0x21048
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movsbl -0x52(%rbp), %edi
callq 0x3250
cmpl $0x0, %eax
je 0x5538
movl $0x2, -0x50(%rbp)
jmp 0x5778
movsbl -0x52(%rbp), %edi
callq 0x3420
cmpl $0x0, %eax
jne 0x554f
movsbl -0x52(%rbp), %eax
cmpl $0x5f, %eax
jne 0x555b
movl $0x3, -0x50(%rbp)
jmp 0x5776
movsbl -0x52(%rbp), %eax
cmpl $0x20, %eax
je 0x5576
movsbl -0x52(%rbp), %eax
cmpl $0x9, %eax
je 0x5576
movsbl -0x52(%rbp), %eax
cmpl $0xa, %eax
jne 0x557f
movb $0x0, -0x51(%rbp)
jmp 0x5774
movsbl -0x52(%rbp), %eax
cmpl $0x3c, %eax
jne 0x5594
movl $0x8, -0x50(%rbp)
jmp 0x5772
movsbl -0x52(%rbp), %eax
cmpl $0x3e, %eax
jne 0x55a9
movl $0x9, -0x50(%rbp)
jmp 0x5770
movsbl -0x52(%rbp), %eax
cmpl $0x2f, %eax
jne 0x55be
movl $0x5, -0x50(%rbp)
jmp 0x576e
movsbl -0x52(%rbp), %eax
cmpl $0x2d, %eax
jne 0x55d3
movl $0xa, -0x50(%rbp)
jmp 0x576c
movsbl -0x52(%rbp), %eax
cmpl $0x3d, %eax
jne 0x55e8
movl $0x1, -0x50(%rbp)
jmp 0x576a
movsbl -0x52(%rbp), %eax
cmpl $0x21, %eax
jne 0x55fd
movl $0xb, -0x50(%rbp)
jmp 0x5768
movsbl -0x52(%rbp), %eax
cmpl $-0x1, %eax
jne 0x5628
movb $0x0, -0x51(%rbp)
movl $0x4, -0x50(%rbp)
leaq 0x1ba6d(%rip), %rsi     # 0x21085
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x5623
jmp 0x5766
movl $0x4, -0x50(%rbp)
movsbl -0x52(%rbp), %eax
movl %eax, -0x12c(%rbp)
subl $0x28, %eax
je 0x56aa
jmp 0x5640
movl -0x12c(%rbp), %eax
subl $0x29, %eax
je 0x56c1
jmp 0x564d
movl -0x12c(%rbp), %eax
subl $0x2a, %eax
je 0x5728
jmp 0x565e
movl -0x12c(%rbp), %eax
subl $0x2b, %eax
je 0x5714
jmp 0x566f
movl -0x12c(%rbp), %eax
subl $0x2c, %eax
je 0x573c
jmp 0x5680
movl -0x12c(%rbp), %eax
subl $0x3b, %eax
je 0x5700
jmp 0x568d
movl -0x12c(%rbp), %eax
subl $0x7b, %eax
je 0x56d8
jmp 0x569a
movl -0x12c(%rbp), %eax
subl $0x7d, %eax
je 0x56ec
jmp 0x5750
leaq 0x1b9ff(%rip), %rsi     # 0x210b0
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x56bc
jmp 0x5764
leaq 0x1b9f4(%rip), %rsi     # 0x210bc
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x56d3
jmp 0x5764
leaq 0x1b9fc(%rip), %rsi     # 0x210db
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x56ea
jmp 0x5764
leaq 0x1b9f3(%rip), %rsi     # 0x210e6
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x56fe
jmp 0x5764
leaq 0x1b9c2(%rip), %rsi     # 0x210c9
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x5712
jmp 0x5764
leaq 0x1b98b(%rip), %rsi     # 0x210a6
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x5726
jmp 0x5764
leaq 0x1b97c(%rip), %rsi     # 0x210ab
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x573a
jmp 0x5764
leaq 0x1b9af(%rip), %rsi     # 0x210f2
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x574e
jmp 0x5764
leaq 0x1b9d0(%rip), %rsi     # 0x21127
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x5762
jmp 0x5764
jmp 0x5766
jmp 0x5768
jmp 0x576a
jmp 0x576c
jmp 0x576e
jmp 0x5770
jmp 0x5772
jmp 0x5774
jmp 0x5776
jmp 0x5778
jmp 0x59f9
movsbl -0x52(%rbp), %edi
callq 0x3250
cmpl $0x0, %eax
jne 0x57ad
callq 0x5440
movl $0x4, -0x50(%rbp)
leaq 0x1b8ef(%rip), %rsi     # 0x2108d
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x57a9
movb $0x0, -0x51(%rbp)
jmp 0x59f9
movsbl -0x52(%rbp), %edi
callq 0x3420
cmpl $0x0, %eax
jne 0x57fb
movsbl -0x52(%rbp), %edi
callq 0x3250
cmpl $0x0, %eax
jne 0x57fb
movsbl -0x52(%rbp), %eax
cmpl $0x5f, %eax
je 0x57fb
callq 0x5440
movb $0x0, -0x51(%rbp)
movl $0x4, -0x50(%rbp)
leaq 0x1b9be(%rip), %rsi     # 0x211ac
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x57f9
jmp 0x57fb
jmp 0x59f9
movsbl -0x52(%rbp), %eax
cmpl $0x3d, %eax
jne 0x5824
movl $0x4, -0x50(%rbp)
leaq 0x1b87a(%rip), %rsi     # 0x21091
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x5822
jmp 0x5848
callq 0x5440
movb $0x0, -0x51(%rbp)
movl $0x4, -0x50(%rbp)
leaq 0x1b9f3(%rip), %rsi     # 0x2122e
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x5846
jmp 0x5848
jmp 0x59f9
movsbl -0x52(%rbp), %eax
cmpl $0x2a, %eax
jne 0x585f
movl $0x6, -0x50(%rbp)
jmp 0x5883
movb $0x0, -0x51(%rbp)
callq 0x5440
movl $0x4, -0x50(%rbp)
leaq 0x1b835(%rip), %rsi     # 0x210ab
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x5881
jmp 0x5883
jmp 0x59f9
movsbl -0x52(%rbp), %eax
cmpl $0x2a, %eax
je 0x58c2
movl $0x6, -0x50(%rbp)
movb $0x1, -0x51(%rbp)
movsbl -0x52(%rbp), %eax
cmpl $-0x1, %eax
jne 0x58c0
movl $0x4, -0x50(%rbp)
leaq 0x1b874(%rip), %rsi     # 0x21127
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x58be
jmp 0x58c0
jmp 0x58c9
movl $0x7, -0x50(%rbp)
jmp 0x59f9
movsbl -0x52(%rbp), %eax
cmpl $0x2f, %eax
jne 0x58f2
movl $0x4, -0x50(%rbp)
leaq 0x1b7ee(%rip), %rsi     # 0x210d3
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x58f0
jmp 0x58f9
movl $0x6, -0x50(%rbp)
jmp 0x59f9
movsbl -0x52(%rbp), %eax
cmpl $0x3d, %eax
je 0x5919
movsbl -0x52(%rbp), %eax
cmpl $0x3e, %eax
je 0x5919
callq 0x5440
movb $0x0, -0x51(%rbp)
movl $0x4, -0x50(%rbp)
leaq 0x1b76a(%rip), %rsi     # 0x21091
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x5932
jmp 0x59f9
movsbl -0x52(%rbp), %eax
cmpl $0x3d, %eax
je 0x5949
callq 0x5440
movb $0x0, -0x51(%rbp)
movl $0x4, -0x50(%rbp)
leaq 0x1b73a(%rip), %rsi     # 0x21091
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x5962
jmp 0x59f9
movsbl -0x52(%rbp), %edi
callq 0x3250
cmpl $0x0, %eax
je 0x597e
movl $0x2, -0x50(%rbp)
jmp 0x59a2
callq 0x5440
movb $0x0, -0x51(%rbp)
movl $0x4, -0x50(%rbp)
leaq 0x1b711(%rip), %rsi     # 0x210a6
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x59a0
jmp 0x59a2
jmp 0x59f9
movsbl -0x52(%rbp), %eax
cmpl $0x3d, %eax
jne 0x59c8
movl $0x4, -0x50(%rbp)
leaq 0x1b6d6(%rip), %rsi     # 0x21091
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x59c6
jmp 0x59e1
leaq 0x1b758(%rip), %rsi     # 0x21127
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x59da
movl $0x4, -0x50(%rbp)
jmp 0x59f9
jmp 0x59e5
leaq 0x1b73b(%rip), %rsi     # 0x21127
leaq -0x28(%rbp), %rdi
callq 0x33a0
jmp 0x59f7
jmp 0x59f9
testb $0x1, -0x51(%rbp)
je 0x5a10
movsbl -0x52(%rbp), %esi
leaq -0x48(%rbp), %rdi
callq 0x31a0
jmp 0x5a0e
jmp 0x5a10
jmp 0x5499
leaq 0x28b0c(%rip), %rdi     # 0x2e528
movq %rdi, -0x140(%rbp)
callq 0x5ef0
movq -0x140(%rbp), %rdi
movq %rax, -0x70(%rbp)
callq 0x5f20
movq %rax, -0x78(%rbp)
movq -0x70(%rbp), %rdi
movq -0x78(%rbp), %rsi
leaq -0x48(%rbp), %rdx
callq 0x5ea0
movq %rax, -0x138(%rbp)
jmp 0x5a56
movq -0x138(%rbp), %rax
cmpq $0x0, %rax
je 0x5a74
leaq -0x28(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x3050
jmp 0x5a72
jmp 0x5a74
leaq -0xc0(%rbp), %rdi
callq 0x4e90
leaq -0xe0(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0x3120
jmp 0x5a92
leaq -0x100(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x3120
jmp 0x5aa4
movl -0x4c(%rbp), %ecx
incl %ecx
leaq -0xc0(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
leaq -0x100(%rbp), %rdx
callq 0x5f50
jmp 0x5ac5
leaq -0x100(%rbp), %rdi
callq 0x34e8
leaq -0xe0(%rbp), %rdi
callq 0x34e8
leaq 0x28a14(%rip), %rdi     # 0x2e4f8
leaq -0xc0(%rbp), %rsi
callq 0x5fa0
jmp 0x5af2
leaq 0x1b5da(%rip), %rsi     # 0x210d3
leaq -0xc0(%rbp), %rdi
callq 0x5e70
movb %al, -0x141(%rbp)
jmp 0x5b0d
movb -0x141(%rbp), %al
testb $0x1, %al
jne 0x5b19
jmp 0x5b75
movq -0x118(%rbp), %rdi
callq 0x5460
jmp 0x5b27
movl $0x1, -0x104(%rbp)
jmp 0x5b92
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x5bc0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x5b67
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x34e8
leaq -0xe0(%rbp), %rdi
callq 0x34e8
jmp 0x5bc0
movq -0x118(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x6010
movl $0x1, -0x104(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x4ec0
leaq -0x48(%rbp), %rdi
callq 0x34e8
leaq -0x28(%rbp), %rdi
callq 0x34e8
movq -0x110(%rbp), %rax
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
leaq -0xc0(%rbp), %rdi
callq 0x4ec0
leaq -0x48(%rbp), %rdi
callq 0x34e8
leaq -0x28(%rbp), %rdi
callq 0x34e8
movq -0x60(%rbp), %rdi
callq 0x3470
nopw (%rax,%rax)