// File: kram[P]kram/./src/parser/parser.cpp
// Function: Parser::lookahead(Instruction*, ON)
Instruction* Parser::lookahead(Instruction* prev, ON on) {
	this->advance();

	lexer::Token* next = this->get_token();

	// PushClass
	// IO::Println("123")
	//   ^^
	// IO.Println("123")
	//   ^
	if (on != ON::MATH_NEG) {
		if (next->type == lexer::Type::OPERATOR && (next->sub == lexer::Type::OPERATOR_DOT || next->sub == lexer::Type::OPERATOR_DOUBLE_COLON)) {
			return this->push_class(prev);
		}
	}

	// Call
	// IO::Println("123")
	//            ^
	if (next->type == lexer::Type::OPERATOR && next->sub == lexer::Type::OPERATOR_PAREN_L) {
		return this->call(prev, on);
	}

	// Assignment
	// num := 100
	//     ^^
	if (next->type == lexer::Type::OPERATOR && next->sub == lexer::Type::OPERATOR_COLON_EQ) {
		return this->assign(prev);
	}

	// Set
	// num = 100
	//     ^
	//
	// Parameter with default value
	// fn (a = 100)
	//
	if (next->type == lexer::Type::OPERATOR && next->sub == lexer::Type::OPERATOR_EQ) {
		if (on == ON::FUNCTION_PARAMETER_LIST) {
			return this->function_parameter_with_default_value(prev);
		} else {
			return this->set(prev);
		}
	}

	// Create new variable of type
	// num : Number
	//     ^
	if (next->type == lexer::Type::OPERATOR && next->sub == lexer::Type::OPERATOR_COLON) {
		return this->assign_with_type(prev);
	}

	if (on != ON::MATH_CONTINUATION && on != ON::MATH_NEG) {
		if (next->type == lexer::Type::OPERATOR) {
			if (this->startOperators.find(next->sub) != this->startOperators.end()) {
				return this->math(prev);
			}
		}
	}

	// List extraction
	// li[123]
	//   ^
	if (next->type == lexer::Type::OPERATOR && next->sub == lexer::Type::OPERATOR_SQUARE_PAREN_LEFT) {
		return this->oper_list_extraction(prev);
	}

	this->reverse();

	return prev;
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x38(%rsp)
movq %rsi, 0x30(%rsp)
movl %edx, 0x2c(%rsp)
movq 0x38(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x21220
movq 0x8(%rsp), %rdi
callq 0x21200
movq %rax, 0x20(%rsp)
cmpl $0x2, 0x2c(%rsp)
je 0x21462
movq 0x20(%rsp), %rax
cmpl $0x11, (%rax)
jne 0x21460
movq 0x20(%rsp), %rax
cmpl $0x25, 0x4(%rax)
je 0x21447
movq 0x20(%rsp), %rax
cmpl $0x14, 0x4(%rax)
jne 0x21460
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x21600
movq %rax, 0x40(%rsp)
jmp 0x215f3
jmp 0x21462
movq 0x20(%rsp), %rax
cmpl $0x11, (%rax)
jne 0x21494
movq 0x20(%rsp), %rax
cmpl $0x26, 0x4(%rax)
jne 0x21494
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
movl 0x2c(%rsp), %edx
callq 0x217e0
movq %rax, 0x40(%rsp)
jmp 0x215f3
movq 0x20(%rsp), %rax
cmpl $0x11, (%rax)
jne 0x214c2
movq 0x20(%rsp), %rax
cmpl $0x2a, 0x4(%rax)
jne 0x214c2
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x21cf0
movq %rax, 0x40(%rsp)
jmp 0x215f3
movq 0x20(%rsp), %rax
cmpl $0x11, (%rax)
jne 0x21510
movq 0x20(%rsp), %rax
cmpl $0x16, 0x4(%rax)
jne 0x21510
cmpl $0x4, 0x2c(%rsp)
jne 0x214f7
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x21dd0
movq %rax, 0x40(%rsp)
jmp 0x215f3
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x22180
movq %rax, 0x40(%rsp)
jmp 0x215f3
movq 0x20(%rsp), %rax
cmpl $0x11, (%rax)
jne 0x2153e
movq 0x20(%rsp), %rax
cmpl $0x13, 0x4(%rax)
jne 0x2153e
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x22260
movq %rax, 0x40(%rsp)
jmp 0x215f3
cmpl $0x1, 0x2c(%rsp)
je 0x215b4
cmpl $0x2, 0x2c(%rsp)
je 0x215b4
movq 0x20(%rsp), %rax
cmpl $0x11, (%rax)
jne 0x215b2
movq 0x8(%rsp), %rdi
addq $0x60, %rdi
movq 0x20(%rsp), %rsi
addq $0x4, %rsi
callq 0x26d50
movq 0x8(%rsp), %rdi
movq %rax, 0x18(%rsp)
addq $0x60, %rdi
callq 0x26d80
movq %rax, 0x10(%rsp)
leaq 0x18(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x26d30
testb $0x1, %al
jne 0x2159a
jmp 0x215b0
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x225b0
movq %rax, 0x40(%rsp)
jmp 0x215f3
jmp 0x215b2
jmp 0x215b4
movq 0x20(%rsp), %rax
cmpl $0x11, (%rax)
jne 0x215df
movq 0x20(%rsp), %rax
cmpl $0x2e, 0x4(%rax)
jne 0x215df
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x225e0
movq %rax, 0x40(%rsp)
jmp 0x215f3
movq 0x8(%rsp), %rdi
callq 0x229d0
movq 0x30(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rax
addq $0x48, %rsp
retq
nopl (%rax)