// File: SeanLee97[P]LL1-Parser/scan.cpp
// Function: scan()
token scan() {
    image_index = 0;

    while (isspace(cur_char)) {
        cur_char = cin.get();
        cur_col++;
        if (cur_char == '\n') {
            cur_line++;
            cur_col = 0;
        }
    }
    tok_line = cur_line;  tok_col = cur_col;

    if (cur_char == EOF) {                     // end of file
        return make_token(tok_eof);
    }

    if (isalpha(cur_char)) {                   // identifier
        do {
            nextchar();
        } while (isdigit(cur_char) || isalpha(cur_char) || cur_char == '_');

        token_image[image_index] = 0;

        for (int w = first_rw; w <= last_rw; w++) {
            if (!strcmp(token_image, &token_names[w][3])) {
                return make_token(tok_num(w));
            }
        }
        return make_token(ident);
    }

    else if (isdigit(cur_char)) {              // literal
        tok_num tok = lit_int;
        do {
            nextchar();
        } while (isdigit(cur_char));
        if (cur_char == '.') {
            nextchar();
            if (!isdigit(cur_char)) {
                return make_token(tok_error);
            }
            tok = lit_real;
            do {
                nextchar();
            } while (isdigit(cur_char));
        }
        return make_token(tok);

    } else switch (cur_char) {                 // misc. other cases
        case ':':
            nextchar();
            if (cur_char != '=') {
                return make_token(colon);
            } else {
                nextchar();
                return make_token(becomes);
            }
            break;
        case '<':
            nextchar();
            if (cur_char != '=') {
                return make_token(op_lt);
            } else {
                nextchar();
                return make_token(op_le);
            }
            break;
        case '>':
            nextchar();
            if (cur_char != '=') {
                return make_token(op_gt);
            } else {
                nextchar();
                return make_token(op_ge);
            }
            break;
        case '=':
            nextchar();
            if (cur_char != '=') {
                return make_token(tok_error);
            } else {
                nextchar();
                return make_token(op_eq);
            }
            break;
        case '!':
            nextchar();
            if (cur_char != '=') {
                return make_token(tok_error);
            } else {
                nextchar();
                return make_token(op_ne);
            }
            break;
        case '+': nextchar(); return make_token(op_add);
        case '-': nextchar(); return make_token(op_sub);
        case '*': nextchar(); return make_token(op_mul);
        case '/': nextchar(); return make_token(op_div);
        case '(': nextchar(); return make_token(lparen);
        case ')': nextchar(); return make_token(rparen);
        case '[': nextchar(); return make_token(lbrac);
        case ']': nextchar(); return make_token(rbrac);
        case ',': nextchar(); return make_token(comma);
        case ';': nextchar(); return make_token(semic);
        default:  nextchar(); return make_token(tok_error);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x20(%rbp)
movq %rdi, %rax
movq %rax, -0x18(%rbp)
movq %rdi, -0x8(%rbp)
movl $0x0, 0x15533(%rip)     # 0x19354
movl 0x15501(%rip), %edi     # 0x19328
callq 0x3050
cmpl $0x0, %eax
je 0x3e76
movq 0x151a8(%rip), %rdi     # 0x18fe0
callq 0x32a0
movl %eax, 0x154e5(%rip)     # 0x19328
movl 0x1550f(%rip), %eax     # 0x19358
addl $0x1, %eax
movl %eax, 0x15506(%rip)     # 0x19358
cmpl $0xa, 0x154cf(%rip)     # 0x19328
jne 0x3e74
movl 0x154cb(%rip), %eax     # 0x1932c
addl $0x1, %eax
movl %eax, 0x154c2(%rip)     # 0x1932c
movl $0x0, 0x154e4(%rip)     # 0x19358
jmp 0x3e21
movl 0x154b0(%rip), %eax     # 0x1932c
movl %eax, 0x154da(%rip)     # 0x1935c
movl 0x154d0(%rip), %eax     # 0x19358
movl %eax, 0x154d2(%rip)     # 0x19360
cmpl $-0x1, 0x15493(%rip)    # 0x19328
jne 0x3eaa
movq -0x20(%rbp), %rdi
movl $0x1, %esi
callq 0x4250
jmp 0x4241
movl 0x15478(%rip), %edi     # 0x19328
callq 0x3350
cmpl $0x0, %eax
je 0x3f7b
jmp 0x3ec0
callq 0x4380
movl 0x1545d(%rip), %edi     # 0x19328
callq 0x31f0
movl %eax, %ecx
movb $0x1, %al
cmpl $0x0, %ecx
movb %al, -0x21(%rbp)
jne 0x3f00
movl 0x15446(%rip), %edi     # 0x19328
callq 0x3350
movl %eax, %ecx
movb $0x1, %al
cmpl $0x0, %ecx
movb %al, -0x21(%rbp)
jne 0x3f00
cmpl $0x5f, 0x1542e(%rip)    # 0x19328
sete %al
movb %al, -0x21(%rbp)
movb -0x21(%rbp), %al
testb $0x1, %al
jne 0x3ec0
movslq 0x15446(%rip), %rcx     # 0x19354
leaq 0x1545b(%rip), %rax     # 0x19370
movb $0x0, (%rax,%rcx)
movl $0x3, -0xc(%rbp)
cmpl $0xb, -0xc(%rbp)
jg 0x3f68
movslq -0xc(%rbp), %rcx
leaq 0x152ef(%rip), %rax     # 0x19220
movq (%rax,%rcx,8), %rsi
addq $0x3, %rsi
leaq 0x15430(%rip), %rdi     # 0x19370
callq 0x3300
cmpl $0x0, %eax
jne 0x3f5b
movq -0x20(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0x4250
jmp 0x4241
jmp 0x3f5d
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0x3f20
movq -0x20(%rbp), %rdi
movl $0x2, %esi
callq 0x4250
jmp 0x4241
movl 0x153a7(%rip), %edi     # 0x19328
callq 0x31f0
cmpl $0x0, %eax
je 0x4007
movl $0xc, -0x10(%rbp)
callq 0x4380
movl 0x1538b(%rip), %edi     # 0x19328
callq 0x31f0
cmpl $0x0, %eax
jne 0x3f92
cmpl $0x2e, 0x1537a(%rip)    # 0x19328
jne 0x3ff6
callq 0x4380
movl 0x1536d(%rip), %edi     # 0x19328
callq 0x31f0
cmpl $0x0, %eax
jne 0x3fd8
movq -0x20(%rbp), %rdi
movl $0x20, %esi
callq 0x4250
jmp 0x4241
movl $0xd, -0x10(%rbp)
callq 0x4380
movl 0x1533e(%rip), %edi     # 0x19328
callq 0x31f0
cmpl $0x0, %eax
jne 0x3fdf
jmp 0x3ff6
movq -0x20(%rbp), %rdi
movl -0x10(%rbp), %esi
callq 0x4250
jmp 0x4241
movl 0x1531b(%rip), %eax     # 0x19328
addl $-0x21, %eax
movl %eax, %ecx
movq %rcx, -0x30(%rbp)
subl $0x3c, %eax
ja 0x422e
movq -0x30(%rbp), %rax
leaq 0xcfda(%rip), %rcx      # 0x11004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
callq 0x4380
cmpl $0x3d, 0x152e9(%rip)    # 0x19328
je 0x4054
movq -0x20(%rbp), %rdi
movl $0x18, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x1f, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
cmpl $0x3d, 0x152b0(%rip)    # 0x19328
je 0x408d
movq -0x20(%rbp), %rdi
movl $0x19, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x1b, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
cmpl $0x3d, 0x15277(%rip)    # 0x19328
je 0x40c6
movq -0x20(%rbp), %rdi
movl $0x1a, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x1c, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
cmpl $0x3d, 0x1523e(%rip)    # 0x19328
je 0x40ff
movq -0x20(%rbp), %rdi
movl $0x20, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x1d, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
cmpl $0x3d, 0x15205(%rip)    # 0x19328
je 0x4138
movq -0x20(%rbp), %rdi
movl $0x20, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x1e, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0xe, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0xf, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x10, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x11, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x12, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x13, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x14, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x15, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x16, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x17, %esi
callq 0x4250
jmp 0x4241
callq 0x4380
movq -0x20(%rbp), %rdi
movl $0x20, %esi
callq 0x4250
movq -0x18(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax,%rax)