// File: kram[P]kram/./src/parser/parser.cpp
// Function: Parser::math(Instruction*, ON)
Instruction* Parser::math(Instruction* prev, ON on) {

	// Get the current token
	lexer::Token* current = this->get_token();

	// Create a new instruction
	Instruction* math = new Instruction(Ins::MATH);

	// Set the mathematical operator, eg + or -
	math->type = current->sub;

	math->left = std::vector<Instruction*> { prev };

	if (on == ON::DEFAULT) {
		math->right = std::vector<Instruction*> { this->symbol_next(ON::MATH_CONTINUATION) };
	} else {
		math->right = std::vector<Instruction*> { this->symbol_next(ON::MATH_NEG) };
	}

	// Verify that the ordering (infix_priority()) is correct
	if (prev->instruction == Ins::MATH) {

		// The ordering is wrong, and we need to correct this
		// [a, *, [b, +, c]] -> [[a, *, b], +, c]
		// This part is a little bit well, confusing and tight. But hey, it is a side-project after all.
		if (Parser::infix_priority(math->type) > Parser::infix_priority(prev->type)) {

			Instruction* res = new Instruction(Ins::MATH);
			Instruction* right = new Instruction(Ins::MATH);

			right->left = prev->right;
			right->right = math->right;

			res->left = prev->left;
			res->right = std::vector<Instruction*> { right };

			res->type = prev->type;
			right->type = math->type;

			return this->lookahead(res, ON::DEFAULT);
		}
	}

	return this->lookahead(math, ON::DEFAULT);
}

// Assembly:
subq $0x178, %rsp            # imm = 0x178
movq %rdi, 0x168(%rsp)
movq %rsi, 0x160(%rsp)
movl %edx, 0x15c(%rsp)
movq 0x168(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x21200
movq %rax, 0x150(%rsp)
movl $0x80, %edi
callq 0x32e0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x40(%rsp)
movl $0x4, %esi
callq 0x26dd0
jmp 0x23719
movq 0x40(%rsp), %rax
movq %rax, 0x148(%rsp)
movq 0x150(%rsp), %rax
movl 0x4(%rax), %ecx
movq 0x148(%rsp), %rax
movl %ecx, 0x30(%rax)
movq 0x160(%rsp), %rax
movq %rax, 0x108(%rsp)
leaq 0x108(%rsp), %rax
movq %rax, 0x110(%rsp)
movq $0x1, 0x118(%rsp)
leaq 0x107(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x16cc0
movq 0x30(%rsp), %rcx
movq 0x110(%rsp), %rsi
movq 0x118(%rsp), %rdx
leaq 0x120(%rsp), %rdi
callq 0x26e70
jmp 0x2379e
movq 0x148(%rsp), %rdi
addq $0x38, %rdi
leaq 0x120(%rsp), %rsi
callq 0x26e30
leaq 0x120(%rsp), %rdi
callq 0x5560
leaq 0x107(%rsp), %rdi
callq 0x7010
cmpl $0x0, 0x15c(%rsp)
jne 0x238ef
movq 0x38(%rsp), %rdi
movl $0x1, %esi
callq 0x22b50
movq %rax, 0xd0(%rsp)
leaq 0xd0(%rsp), %rax
movq %rax, 0xd8(%rsp)
movq $0x1, 0xe0(%rsp)
leaq 0xcf(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x16cc0
movq 0x28(%rsp), %rcx
movq 0xd8(%rsp), %rsi
movq 0xe0(%rsp), %rdx
leaq 0xe8(%rsp), %rdi
callq 0x26e70
jmp 0x23848
movq 0x148(%rsp), %rdi
addq $0x50, %rdi
leaq 0xe8(%rsp), %rsi
callq 0x26e30
leaq 0xe8(%rsp), %rdi
callq 0x5560
leaq 0xcf(%rsp), %rdi
callq 0x7010
jmp 0x239b3
movq 0x40(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
callq 0x32b0
jmp 0x23bf3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0x107(%rsp), %rdi
callq 0x7010
jmp 0x23bf3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0xcf(%rsp), %rdi
callq 0x7010
jmp 0x23bf3
movq 0x38(%rsp), %rdi
movl $0x2, %esi
callq 0x22b50
movq %rax, 0x98(%rsp)
leaq 0x98(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq $0x1, 0xa8(%rsp)
leaq 0x97(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x16cc0
movq 0x20(%rsp), %rcx
movq 0xa0(%rsp), %rsi
movq 0xa8(%rsp), %rdx
leaq 0xb0(%rsp), %rdi
callq 0x26e70
jmp 0x23958
movq 0x148(%rsp), %rdi
addq $0x50, %rdi
leaq 0xb0(%rsp), %rsi
callq 0x26e30
leaq 0xb0(%rsp), %rdi
callq 0x5560
leaq 0x97(%rsp), %rdi
callq 0x7010
jmp 0x239b3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0x97(%rsp), %rdi
callq 0x7010
jmp 0x23bf3
movq 0x160(%rsp), %rax
cmpl $0x4, (%rax)
jne 0x23bc7
movq 0x148(%rsp), %rax
movl 0x30(%rax), %edi
callq 0x23120
movl %eax, 0x1c(%rsp)
movq 0x160(%rsp), %rax
movl 0x30(%rax), %edi
callq 0x23120
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jle 0x23bc5
movl $0x80, %edi
callq 0x32e0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x10(%rsp)
movl $0x4, %esi
callq 0x26dd0
jmp 0x23a17
movq 0x10(%rsp), %rax
movq %rax, 0x88(%rsp)
movl $0x80, %edi
callq 0x32e0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x8(%rsp)
movl $0x4, %esi
callq 0x26dd0
jmp 0x23a45
movq 0x8(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x160(%rsp), %rsi
addq $0x50, %rsi
movq 0x80(%rsp), %rdi
addq $0x38, %rdi
callq 0x17000
movq 0x148(%rsp), %rsi
addq $0x50, %rsi
movq 0x80(%rsp), %rdi
addq $0x50, %rdi
callq 0x17000
movq 0x160(%rsp), %rsi
addq $0x38, %rsi
movq 0x88(%rsp), %rdi
addq $0x38, %rdi
callq 0x17000
movq 0x80(%rsp), %rax
movq %rax, 0x50(%rsp)
leaq 0x50(%rsp), %rax
movq %rax, 0x58(%rsp)
movq $0x1, 0x60(%rsp)
leaq 0x4f(%rsp), %rdi
movq %rdi, (%rsp)
callq 0x16cc0
movq (%rsp), %rcx
movq 0x58(%rsp), %rsi
movq 0x60(%rsp), %rdx
leaq 0x68(%rsp), %rdi
callq 0x26e70
jmp 0x23af1
movq 0x88(%rsp), %rdi
addq $0x50, %rdi
leaq 0x68(%rsp), %rsi
callq 0x26e30
leaq 0x68(%rsp), %rdi
callq 0x5560
leaq 0x4f(%rsp), %rdi
callq 0x7010
movq 0x38(%rsp), %rdi
movq 0x160(%rsp), %rax
movl 0x30(%rax), %ecx
movq 0x88(%rsp), %rax
movl %ecx, 0x30(%rax)
movq 0x148(%rsp), %rax
movl 0x30(%rax), %ecx
movq 0x80(%rsp), %rax
movl %ecx, 0x30(%rax)
movq 0x88(%rsp), %rsi
xorl %edx, %edx
callq 0x213f0
movq %rax, 0x170(%rsp)
jmp 0x23be3
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
callq 0x32b0
jmp 0x23bf3
movq 0x8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
callq 0x32b0
jmp 0x23bf3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0x4f(%rsp), %rdi
callq 0x7010
jmp 0x23bf3
jmp 0x23bc7
movq 0x38(%rsp), %rdi
movq 0x148(%rsp), %rsi
xorl %edx, %edx
callq 0x213f0
movq %rax, 0x170(%rsp)
movq 0x170(%rsp), %rax
addq $0x178, %rsp            # imm = 0x178
retq
movq 0x140(%rsp), %rdi
callq 0x3490