// File: pixlark[P]Badge/src/lexer.cc
// Function: Lexer::next_token()
Token Lexer::next_token()
{
 reset:
	if (peek() == '\0') {
		Token token = create_token(TOKEN_EOF, 1);
		return token;
	}
	
	if (isspace(peek())) {
		advance();
		goto reset;
	}

	if (peek() == '%') {
		while (peek() != '\0' && peek() != '\n') {
			advance();
		}
		goto reset;
	}
	
	if (peek() == '"') {
		size_t start = cursor;
		advance();
		
		String_Builder builder;
		while (peek() != '"') {
			builder.add(next());
		}
		advance();
		char * s = builder.final_string();
		defer { free(s); };
		
		Token token = create_token(TOKEN_STRING_LITERAL, cursor - start);
		token.values.string = Intern::intern(s); // string literals are technically symbols
		return token;
	}
	
	if (isalpha(peek()) || peek() == '_') {
		String_Builder builder;
		while (isalnum(peek()) || peek() == '_') {
			builder.add(next());
		}
		char * s = builder.final_string();
		defer { free(s); };
		
		for (int i = 0; i < RESERVED_WORDS_COUNT; i++) {
			if (strcmp(s, reserved_words[i]) == 0) {
				return create_token((Token_Kind) (RESERVED_WORDS_BEGIN + i), builder.size());
			}
		}
		
		Token token = create_token(TOKEN_SYMBOL, builder.size());
		token.values.symbol = Intern::intern(s);
		return token;
	}

	if (isdigit(peek())) {
		String_Builder builder;
		while (isdigit(peek())) {
			builder.add(next());
		}
		char * s = builder.final_string();
		defer { free(s); };
		Token token = create_token(TOKEN_INTEGER_LITERAL, builder.size());
		token.values.integer = strtol(s, NULL, 10);
		return token;
	}
	
	switch (peek()) {
	case '+':
	case '-':
	case '*':
	case '/':
	case '.':
	case ',':
	case '(':
	case ')':
	case '{':
	case '}':
	case '@':
	case '$':
	case ':':
	case '\'':
		return create_token((Token_Kind) next(), 1);
		//return Token::with_kind((Token_Kind) next());
	case '=':
		return create_token(read_double_token('=', '=', TOKEN_EQUAL), 1);
	case '!':
		return create_token(read_double_token('!', '=', TOKEN_NOT_EQUAL), 1);
	case '>':
		return create_token(read_double_token('>', '=', TOKEN_GTE), 1);
	case '<':
		return create_token(read_double_token('<', '=', TOKEN_LTE), 1);
	case ']':
		return create_token((Token_Kind) next(), 1);
	case '[':
		advance();
		if (peek() == '-') {
			// Multi-line comment
			while (true) {
				advance();
				if (peek() == '\0') {
					fatal("Unterminated multi-line comment");
				}
				if (peek() == '-') {
					advance();
					if (peek() == ']') {
						advance();
						break;
					}
				}
			}
			goto reset;
		} else {
			return create_token((Token_Kind) '[', 1);
			//return Token::with_kind((Token_Kind) '[');
		}
	default:
		fatal_assoc(Assoc_Allocator::make(source, source_length, cursor, 1, line),
					"Line %d\nMisplaced character %c (%d)", line, peek(), peek());
		/*
	case ';':
		return Token::with_kind(read_double_token(';', ';', TOKEN_DOUBLE_SEMICOLON));*/
	}
	return (Token) {}; // @linter
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1b0, %rsp            # imm = 0x1B0
movq %rdi, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x0, %eax
jne 0x2801
movq -0x118(%rbp), %rdi
movl $0x100, %esi            # imm = 0x100
movl $0x1, %edx
callq 0x2630
movq %rax, -0x10(%rbp)
movq %rdx, -0x8(%rbp)
jmp 0x307e
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %edi
callq 0x1040
cmpl $0x0, %eax
je 0x2828
movq -0x118(%rbp), %rdi
callq 0x2750
jmp 0x27ca
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x25, %eax
jne 0x2894
jmp 0x283e
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %ecx
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, -0x119(%rbp)
je 0x2875
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0xa, %eax
setne %al
movb %al, -0x119(%rbp)
movb -0x119(%rbp), %al
testb $0x1, %al
jne 0x2881
jmp 0x288f
movq -0x118(%rbp), %rdi
callq 0x2750
jmp 0x283e
jmp 0x27ca
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x22, %eax
jne 0x29e1
movq -0x118(%rbp), %rdi
movq 0x10(%rdi), %rax
movq %rax, -0x20(%rbp)
callq 0x2750
leaq -0x48(%rbp), %rdi
callq 0x1450
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x22, %eax
je 0x2918
movq -0x118(%rbp), %rdi
callq 0x26e0
movb %al, -0x11a(%rbp)
jmp 0x28f1
movb -0x11a(%rbp), %al
movsbl %al, %esi
leaq -0x48(%rbp), %rdi
callq 0x14c0
jmp 0x2905
jmp 0x28c9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x29d3
movq -0x118(%rbp), %rdi
callq 0x2750
leaq -0x48(%rbp), %rdi
callq 0x15c0
movq %rax, -0x60(%rbp)
leaq -0x60(%rbp), %rax
movq %rax, -0x78(%rbp)
leaq -0x68(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x30a0
jmp 0x2948
movq -0x118(%rbp), %rdi
movq 0x10(%rdi), %rdx
movq -0x20(%rbp), %rax
subq %rax, %rdx
movl $0x118, %esi            # imm = 0x118
callq 0x2630
movq %rdx, -0x130(%rbp)
movq %rax, -0x128(%rbp)
jmp 0x2974
movq -0x130(%rbp), %rax
movq -0x128(%rbp), %rcx
movq %rcx, -0x10(%rbp)
movq %rax, -0x8(%rbp)
movq -0x60(%rbp), %rdi
callq 0x1740
movq %rax, -0x138(%rbp)
jmp 0x299c
movq -0x138(%rbp), %rax
movq %rax, -0x8(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x30e0
leaq -0x48(%rbp), %rdi
callq 0x1490
jmp 0x307e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x30e0
leaq -0x48(%rbp), %rdi
callq 0x1490
jmp 0x308f
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %edi
callq 0x11b0
cmpl $0x0, %eax
jne 0x2a12
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x5f, %eax
jne 0x2c52
leaq -0xa0(%rbp), %rdi
callq 0x1450
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %edi
callq 0x1110
movl %eax, %ecx
movb $0x1, %al
cmpl $0x0, %ecx
movb %al, -0x139(%rbp)
jne 0x2a5c
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x5f, %eax
sete %al
movb %al, -0x139(%rbp)
movb -0x139(%rbp), %al
testb $0x1, %al
jne 0x2a68
jmp 0x2aa6
movq -0x118(%rbp), %rdi
callq 0x26e0
movb %al, -0x13a(%rbp)
jmp 0x2a7c
movb -0x13a(%rbp), %al
movsbl %al, %esi
leaq -0xa0(%rbp), %rdi
callq 0x14c0
jmp 0x2a93
jmp 0x2a1e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x2c41
leaq -0xa0(%rbp), %rdi
callq 0x15c0
movq %rax, -0xa8(%rbp)
leaq -0xa8(%rbp), %rax
movq %rax, -0xc0(%rbp)
leaq -0xb0(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x3110
jmp 0x2adc
movl $0x0, -0xc4(%rbp)
cmpl $0x11, -0xc4(%rbp)
jge 0x2bb4
movq -0xa8(%rbp), %rdi
movslq -0xc4(%rbp), %rcx
leaq 0x145f8(%rip), %rax     # 0x17100
movq (%rax,%rcx,8), %rsi
callq 0x1160
cmpl $0x0, %eax
jne 0x2b9e
movl -0xc4(%rbp), %eax
addl $0x105, %eax            # imm = 0x105
movl %eax, -0x154(%rbp)
leaq -0xa0(%rbp), %rdi
callq 0x1620
movq -0x118(%rbp), %rdi
movl -0x154(%rbp), %esi
movq %rax, %rdx
callq 0x2630
movq %rdx, -0x150(%rbp)
movq %rax, -0x148(%rbp)
jmp 0x2b5c
movq -0x150(%rbp), %rax
movq -0x148(%rbp), %rcx
movq %rcx, -0x10(%rbp)
movq %rax, -0x8(%rbp)
movl $0x1, -0xc8(%rbp)
jmp 0x2c24
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x3150
jmp 0x2c41
jmp 0x2ba0
movl -0xc4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc4(%rbp)
jmp 0x2ae6
leaq -0xa0(%rbp), %rdi
callq 0x1620
movq -0x118(%rbp), %rdi
movq %rax, %rdx
movl $0x116, %esi            # imm = 0x116
callq 0x2630
movq %rdx, -0x168(%rbp)
movq %rax, -0x160(%rbp)
jmp 0x2be4
movq -0x168(%rbp), %rax
movq -0x160(%rbp), %rcx
movq %rcx, -0x10(%rbp)
movq %rax, -0x8(%rbp)
movq -0xa8(%rbp), %rdi
callq 0x1740
movq %rax, -0x170(%rbp)
jmp 0x2c0f
movq -0x170(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0xc8(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x3150
leaq -0xa0(%rbp), %rdi
callq 0x1490
jmp 0x307e
leaq -0xa0(%rbp), %rdi
callq 0x1490
jmp 0x308f
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %edi
callq 0x10f0
cmpl $0x0, %eax
je 0x2db6
leaq -0xf0(%rbp), %rdi
callq 0x1450
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %edi
callq 0x10f0
cmpl $0x0, %eax
je 0x2cd2
movq -0x118(%rbp), %rdi
callq 0x26e0
movb %al, -0x171(%rbp)
jmp 0x2ca8
movb -0x171(%rbp), %al
movsbl %al, %esi
leaq -0xf0(%rbp), %rdi
callq 0x14c0
jmp 0x2cbf
jmp 0x2c7b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x2da5
leaq -0xf0(%rbp), %rdi
callq 0x15c0
movq %rax, -0xf8(%rbp)
leaq -0xf8(%rbp), %rax
movq %rax, -0x110(%rbp)
leaq -0x100(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x3180
jmp 0x2d08
leaq -0xf0(%rbp), %rdi
callq 0x1620
movq -0x118(%rbp), %rdi
movq %rax, %rdx
movl $0x117, %esi            # imm = 0x117
callq 0x2630
movq %rdx, -0x188(%rbp)
movq %rax, -0x180(%rbp)
jmp 0x2d38
movq -0x188(%rbp), %rax
movq -0x180(%rbp), %rcx
movq %rcx, -0x10(%rbp)
movq %rax, -0x8(%rbp)
movq -0xf8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0xa, %edx
callq 0x1170
movl %eax, -0x8(%rbp)
movl $0x1, -0xc8(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x31c0
leaq -0xf0(%rbp), %rdi
callq 0x1490
jmp 0x307e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x31c0
leaq -0xf0(%rbp), %rdi
callq 0x1490
jmp 0x308f
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
addl $-0x21, %eax
movl %eax, %ecx
movq %rcx, -0x190(%rbp)
subl $0x5c, %eax
ja 0x2ff2
movq -0x190(%rbp), %rax
leaq 0xd280(%rip), %rcx      # 0x10068
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x118(%rbp), %rdi
callq 0x26e0
movq -0x118(%rbp), %rdi
movsbl %al, %esi
movl $0x1, %edx
callq 0x2630
movq %rax, -0x10(%rbp)
movq %rdx, -0x8(%rbp)
jmp 0x307e
movq -0x118(%rbp), %rdi
movl $0x3d, %edx
movl $0x101, %ecx            # imm = 0x101
movl %edx, %esi
callq 0x31f0
movq -0x118(%rbp), %rdi
movl %eax, %esi
movl $0x1, %edx
callq 0x2630
movq %rax, -0x10(%rbp)
movq %rdx, -0x8(%rbp)
jmp 0x307e
movq -0x118(%rbp), %rdi
movl $0x21, %esi
movl $0x3d, %edx
movl $0x102, %ecx            # imm = 0x102
callq 0x31f0
movq -0x118(%rbp), %rdi
movl %eax, %esi
movl $0x1, %edx
callq 0x2630
movq %rax, -0x10(%rbp)
movq %rdx, -0x8(%rbp)
jmp 0x307e
movq -0x118(%rbp), %rdi
movl $0x3e, %esi
movl $0x3d, %edx
movl $0x103, %ecx            # imm = 0x103
callq 0x31f0
movq -0x118(%rbp), %rdi
movl %eax, %esi
movl $0x1, %edx
callq 0x2630
movq %rax, -0x10(%rbp)
movq %rdx, -0x8(%rbp)
jmp 0x307e
movq -0x118(%rbp), %rdi
movl $0x3c, %esi
movl $0x3d, %edx
movl $0x104, %ecx            # imm = 0x104
callq 0x31f0
movq -0x118(%rbp), %rdi
movl %eax, %esi
movl $0x1, %edx
callq 0x2630
movq %rax, -0x10(%rbp)
movq %rdx, -0x8(%rbp)
jmp 0x307e
movq -0x118(%rbp), %rdi
callq 0x26e0
movq -0x118(%rbp), %rdi
movsbl %al, %esi
movl $0x1, %edx
callq 0x2630
movq %rax, -0x10(%rbp)
movq %rdx, -0x8(%rbp)
jmp 0x307e
movq -0x118(%rbp), %rdi
callq 0x2750
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x2d, %eax
jne 0x2fcf
jmp 0x2f56
movq -0x118(%rbp), %rdi
callq 0x2750
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x0, %eax
jne 0x2f84
leaq 0xd5c2(%rip), %rdi      # 0x1053f
movb $0x0, %al
callq 0x1c50
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x2d, %eax
jne 0x2fc8
movq -0x118(%rbp), %rdi
callq 0x2750
movq -0x118(%rbp), %rdi
callq 0x2710
movsbl %al, %eax
cmpl $0x5d, %eax
jne 0x2fc6
movq -0x118(%rbp), %rdi
callq 0x2750
jmp 0x2fca
jmp 0x2fc8
jmp 0x2f56
jmp 0x27ca
movq -0x118(%rbp), %rdi
movl $0x5b, %esi
movl $0x1, %edx
callq 0x2630
movq %rax, -0x10(%rbp)
movq %rdx, -0x8(%rbp)
jmp 0x307e
movq -0x118(%rbp), %rax
movq (%rax), %rdi
movq 0x8(%rax), %rsi
movq 0x10(%rax), %rdx
movq 0x18(%rax), %r8
movl $0x1, %ecx
callq 0x1a80
movq -0x118(%rbp), %rdi
movl %eax, -0x1a4(%rbp)
movq 0x18(%rdi), %rax
movq %rax, -0x1a0(%rbp)
callq 0x2710
movq -0x118(%rbp), %rdi
movsbl %al, %eax
movl %eax, -0x194(%rbp)
callq 0x2710
movl -0x1a4(%rbp), %edi
movq -0x1a0(%rbp), %rdx
movl -0x194(%rbp), %ecx
movsbl %al, %r8d
leaq 0xd4fd(%rip), %rsi      # 0x1055f
movb $0x0, %al
callq 0x1f40
movl $0x0, -0x10(%rbp)
movl $0x0, -0xc(%rbp)
movl $0x0, -0x8(%rbp)
movq -0x10(%rbp), %rax
movq -0x8(%rbp), %rdx
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbp
retq
movq -0x50(%rbp), %rdi
callq 0x11c0
nopl (%rax,%rax)