// File: /workspace/github_cpp_makefile_star2_O1/ajuc[P]c--_lisp_sexp_parser/lispparser.cpp
// Function: AjucLispParser::parse(std::istream&, int&, bool)
std::shared_ptr< Expression> parse(std::istream& input, int& line_no, bool topLevel) {
	std::string buffer("");
	char c;
	
	while (input.good()) {
		input.get(c);
		if (whitespace(c)) {
			if (c == '\n') {
				line_no++;
			}
			if (buffer.empty()) {
				;//nothing to do
			} else {
				if (digit(buffer[0])) {
					return std::make_shared<Float>(buffer);
				} else if (doubleQuote(buffer[0])) {
					buffer += c;
				} else if (colon(buffer[0])) {
					return std::make_shared<Atom>(buffer.substr(1));
				} else if (alphanumeric(buffer[0])) {
					return std::make_shared<Identifier>(buffer);
				//} else {
				//	return new Identifier(buffer);
				}
			}
		} else if (digit(c)) {
			buffer += c;
		} else if (dot(c)) {
			if (buffer.empty()) {
				buffer += c;
			} else {
				if (digit(buffer[0])) {
					if (!dotIn(buffer)) {
						buffer += c;
					} else {
						SYNTAX_ERROR(line_no, "Second dot found in Float literal " << buffer + c );
					}
				} else {
					buffer += c;
				}
			}
		} else if (colon(c)) {
			if (buffer.empty()) {
				buffer += c;
			} else {
				SYNTAX_ERROR(line_no, "Colon found in the middle of token " << buffer + c );
			}
		} else if (doubleQuote(c)) {
			if (buffer.empty()) {
				buffer += c;
			} else {
				if (doubleQuote(buffer[0])) {
					buffer += c;
					return std::make_shared<String>(buffer);
				} else {
					SYNTAX_ERROR(line_no, "Double-quote found in the middle of token " << buffer + c );
				}
			}
		} else if (parenthenesis(c)) { //BEWARE - THE TRICKY PART //TODO refactor to smaller functions
			if (buffer.empty()) {
				if (openParenthenesis(c)) {
					std::vector< std::shared_ptr<Expression>> list;
					char c2;
					input.get(c2);
					while (!closeParenthenesis(c2)) {
						input.unget();
						std::shared_ptr<Expression> tmpExp = parse(input, line_no, false);
						if (tmpExp) {
						    list.push_back(tmpExp);
						} else {
						    input.unget();
						}
						input.get(c2);
					}
					if (!parenMatches(c, c2)) {
						SYNTAX_ERROR(line_no, "Parenthenesis " << c << " is closed by not matching paren : " << c2);
					}
					return std::make_shared<List>(list);
				} else {//closeParenthenesis(c)
					if (topLevel) {
					    SYNTAX_ERROR(line_no, "Found unmatched close parenthenesis " << c);
					} else {
					    return NULL;//oznacza, ze trzeba wyjsc
					}
				}
			} else {
				//end of some token
				//return c back to the ctream and return expression as a result
				//or possibly it was ending paren inside a string and we add it simply
                          
				if (digit(buffer[0])) {
					input.unget();
					return std::make_shared<Float>(buffer);
				} else if (doubleQuote(buffer[0])) {
					buffer += c; //no unget, cause it's inside a string literal
                                } else if (colon(buffer[0])) {
					input.unget();
					return std::make_shared<Atom>(buffer);
				} else if (alphanumeric(buffer[0])) {
					input.unget();
					return std::make_shared<Identifier>(buffer);
				}  else {
					SYNTAX_ERROR(line_no, "Situation impossible : buffer == " << buffer);
				}
			}
		} else if (alphanumeric(c)) {
			if (buffer.empty()) {
				buffer += c;
			} else {
				if (!digit(buffer[0])) {
					buffer += c;
				} else {
					SYNTAX_ERROR(line_no, "Non-digit found in the middle of Float literal " << buffer + c );
				}
			}
		} else {
			SYNTAX_ERROR(line_no, "Unrecognised char " << c);
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movl %ecx, -0x94(%rbp)
movq %rdx, -0x68(%rbp)
movq %rsi, %r15
movq %rdi, -0x90(%rbp)
leaq -0x78(%rbp), %rax
movq %rax, -0x10(%rax)
leaq 0x216d(%rip), %rdx      # 0x6008
leaq -0x88(%rbp), %rdi
movq %rdx, %rsi
callq 0x4bc4
leaq -0x29(%rbp), %r12
movabsq $0x100100000600, %rbx   # imm = 0x100100000600
movq %r15, %rdi
movq %r12, %rsi
callq 0x31e0
movb -0x29(%rbp), %r14b
movzbl %r14b, %r13d
cmpl $0x1f, %r13d
jg 0x3ee5
cmpl $0x9, %r13d
je 0x3ef1
cmpl $0xa, %r13d
jne 0x3f3c
movq -0x68(%rbp), %rax
incl (%rax)
jmp 0x3ef1
cmpl $0x20, %r13d
je 0x3ef1
cmpl $0x2c, %r13d
jne 0x3f3c
cmpq $0x0, -0x80(%rbp)
je 0x3eb8
movq -0x88(%rbp), %rax
movzbl (%rax), %eax
leal -0x30(%rax), %ecx
cmpb $0x9, %cl
jbe 0x409e
cmpl $0x3a, %eax
ja 0x3f2b
movl %eax, %ecx
btq %rcx, %rbx
jb 0x3eb8
cmpq $0x22, %rcx
je 0x3f44
cmpq $0x3a, %rcx
je 0x4105
movsbl %al, %edi
callq 0x3d6f
testb %al, %al
jne 0x3eb8
jmp 0x417d
leal -0x30(%r14), %eax
cmpb $0xa, %al
jae 0x3f59
movsbl %r14b, %esi
leaq -0x88(%rbp), %rdi
callq 0x3140
jmp 0x3eb8
cmpl $0x22, %r13d
je 0x3fb7
cmpl $0x3a, %r13d
je 0x3fab
cmpl $0x2e, %r13d
jne 0x3fc3
cmpq $0x0, -0x80(%rbp)
je 0x3f44
movq -0x88(%rbp), %rax
movb (%rax), %al
addb $-0x30, %al
cmpb $0x9, %al
ja 0x3f44
movl $0x1, %ecx
leaq -0x88(%rbp), %rdi
leaq 0x207b(%rip), %rsi      # 0x600f
xorl %edx, %edx
callq 0x3270
cmpq $-0x1, %rax
jne 0x452f
movb -0x29(%rbp), %r14b
jmp 0x3f44
cmpq $0x0, -0x80(%rbp)
je 0x3f44
jmp 0x44c4
cmpq $0x0, -0x80(%rbp)
je 0x3f44
jmp 0x41a2
movsbl %r14b, %edi
callq 0x3d6f
testb %al, %al
je 0x3fff
cmpq $0x0, -0x80(%rbp)
je 0x4237
movq -0x88(%rbp), %rax
movzbl (%rax), %eax
leal -0x30(%rax), %ecx
cmpb $0x9, %cl
jbe 0x42ea
cmpl $0x22, %eax
je 0x3f44
jmp 0x41ee
cmpl $0x2c, %r13d
ja 0x4012
movl %r13d, %eax
btq %rax, %rbx
jb 0x4407
cmpq $0x0, -0x80(%rbp)
je 0x3f44
movq -0x88(%rbp), %rax
movb (%rax), %al
addb $-0x30, %al
cmpb $0x9, %al
ja 0x3f44
movq -0x68(%rbp), %rax
movl (%rax), %esi
movq 0x4fb3(%rip), %rdi      # 0x8ff0
callq 0x3260
movq %rax, %rbx
leaq 0x2067(%rip), %rsi      # 0x60b3
movl $0x2, %edx
movq %rax, %rdi
callq 0x31a0
leaq 0x209d(%rip), %rsi      # 0x60fd
movl $0x2f, %edx
movq %rbx, %rdi
callq 0x31a0
movsbl -0x29(%rbp), %edx
leaq -0x50(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x4a7f
movq -0x50(%rbp), %rsi
movq -0x48(%rbp), %rdx
movq %rbx, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30c0
jmp 0x4598
leaq -0x48(%rbp), %rdi
movq $0x0, -0x8(%rdi)
leaq -0x50(%rbp), %rsi
leaq -0x60(%rbp), %rdx
leaq -0x88(%rbp), %rcx
callq 0x4d28
movq -0x50(%rbp), %rax
movq -0x90(%rbp), %rbx
movq %rax, (%rbx)
xorl %eax, %eax
movq %rax, 0x8(%rbx)
movq -0x48(%rbp), %rcx
movq %rax, -0x48(%rbp)
movq %rcx, 0x8(%rbx)
leaq -0x78(%rbp), %rax
movq -0x88(%rbp), %rdi
cmpq %rax, %rdi
je 0x40f3
callq 0x3160
movq %rbx, %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq -0x50(%rbp), %rdi
leaq -0x88(%rbp), %rsi
movl $0x1, %edx
movq $-0x1, %rcx
callq 0x3190
movq -0x90(%rbp), %rbx
leaq -0x58(%rbp), %rdi
movq $0x0, -0x8(%rdi)
leaq -0x60(%rbp), %rsi
leaq -0x2b(%rbp), %rdx
leaq -0x50(%rbp), %rcx
callq 0x4e2a
movq -0x60(%rbp), %rax
movq %rax, (%rbx)
xorl %eax, %eax
movq %rax, 0x8(%rbx)
movq -0x58(%rbp), %rcx
movq %rax, -0x58(%rbp)
movq %rcx, 0x8(%rbx)
movq %rax, -0x60(%rbp)
leaq -0x40(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x40de
callq 0x3160
jmp 0x40de
leaq -0x48(%rbp), %rdi
movq $0x0, -0x8(%rdi)
leaq -0x50(%rbp), %rsi
leaq -0x60(%rbp), %rdx
leaq -0x88(%rbp), %rcx
callq 0x4f1a
jmp 0x40be
movq -0x88(%rbp), %rax
cmpb $0x22, (%rax)
jne 0x45ab
movsbl %r14b, %esi
leaq -0x88(%rbp), %rdi
callq 0x3140
movq -0x90(%rbp), %rbx
leaq -0x48(%rbp), %rdi
movq $0x0, -0x8(%rdi)
leaq -0x50(%rbp), %rsi
leaq -0x60(%rbp), %rdx
leaq -0x88(%rbp), %rcx
callq 0x500a
jmp 0x43df
cmpl $0x3a, %eax
ja 0x43a0
movl %eax, %ecx
cmpq $0x3a, %rcx
jne 0x4396
movq %r15, %rdi
callq 0x3060
movq -0x90(%rbp), %rbx
leaq -0x48(%rbp), %rdi
movq $0x0, -0x8(%rdi)
leaq -0x50(%rbp), %rsi
leaq -0x60(%rbp), %rdx
leaq -0x88(%rbp), %rcx
callq 0x545a
jmp 0x43df
cmpl $0x28, %r13d
je 0x424d
cmpl $0x5b, %r13d
je 0x424d
cmpl $0x7b, %r13d
jne 0x43e8
xorps %xmm0, %xmm0
movaps %xmm0, -0x50(%rbp)
movq $0x0, -0x40(%rbp)
leaq -0x2a(%rbp), %rsi
movq %r15, %rdi
callq 0x31e0
movq -0x90(%rbp), %rbx
leaq -0x60(%rbp), %r12
leaq -0x2a(%rbp), %r13
leaq -0x50(%rbp), %r14
movzbl -0x2a(%rbp), %eax
cmpl $0x29, %eax
je 0x431e
cmpl $0x5d, %eax
je 0x431e
cmpl $0x7d, %eax
je 0x431e
movq %r15, %rdi
callq 0x3060
movq %r12, %rdi
movq %r15, %rsi
movq -0x68(%rbp), %rdx
xorl %ecx, %ecx
callq 0x3e67
cmpq $0x0, -0x60(%rbp)
je 0x42c7
movq %r14, %rdi
movq %r12, %rsi
callq 0x4ae4
jmp 0x42cf
movq %r15, %rdi
callq 0x3060
movq %r15, %rdi
movq %r13, %rsi
callq 0x31e0
movq -0x58(%rbp), %rdi
testq %rdi, %rdi
je 0x427b
callq 0x35ac
jmp 0x427b
movq %r15, %rdi
callq 0x3060
movq -0x90(%rbp), %rbx
leaq -0x48(%rbp), %rdi
movq $0x0, -0x8(%rdi)
leaq -0x50(%rbp), %rsi
leaq -0x60(%rbp), %rdx
leaq -0x88(%rbp), %rcx
callq 0x4d28
jmp 0x43df
movb -0x29(%rbp), %cl
movl %ecx, %edx
xorb $0x28, %dl
movl %eax, %esi
xorb $0x29, %sil
orb %dl, %sil
je 0x4352
movl %ecx, %edx
xorb $0x5b, %dl
movl %eax, %esi
xorb $0x5d, %sil
orb %dl, %sil
je 0x4352
cmpb $0x7d, %al
jne 0x4676
cmpb $0x7b, %cl
jne 0x4676
leaq -0x58(%rbp), %rdi
movq $0x0, -0x8(%rdi)
leaq -0x60(%rbp), %rsi
leaq -0x2b(%rbp), %rdx
leaq -0x50(%rbp), %rcx
callq 0x5270
movq -0x60(%rbp), %rax
movq %rax, (%rbx)
xorl %eax, %eax
movq %rax, 0x8(%rbx)
movq -0x58(%rbp), %rcx
movq %rax, -0x58(%rbp)
movq %rcx, 0x8(%rbx)
leaq -0x50(%rbp), %rdi
callq 0x49d6
jmp 0x40de
btq %rcx, %rbx
jb 0x4467
movsbl %al, %edi
callq 0x3d6f
testb %al, %al
movq -0x90(%rbp), %rbx
jne 0x4467
movq %r15, %rdi
callq 0x3060
leaq -0x48(%rbp), %rdi
movq $0x0, -0x8(%rdi)
leaq -0x50(%rbp), %rsi
leaq -0x60(%rbp), %rdx
leaq -0x88(%rbp), %rcx
callq 0x4f1a
movq -0x50(%rbp), %rax
jmp 0x40c9
cmpb $0x0, -0x94(%rbp)
movq -0x90(%rbp), %rbx
jne 0x4616
xorps %xmm0, %xmm0
movups %xmm0, (%rbx)
jmp 0x40de
movq -0x68(%rbp), %rax
movl (%rax), %esi
movq 0x4bdc(%rip), %rdi      # 0x8ff0
callq 0x3260
movq %rax, %rbx
leaq 0x1c90(%rip), %rsi      # 0x60b3
movl $0x2, %edx
movq %rax, %rdi
callq 0x31a0
leaq 0x1cf6(%rip), %rsi      # 0x612d
movl $0x12, %edx
movq %rbx, %rdi
callq 0x31a0
movb -0x29(%rbp), %al
leaq -0x50(%rbp), %rsi
movb %al, (%rsi)
movl $0x1, %edx
movq %rbx, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30c0
jmp 0x45a1
movq -0x68(%rbp), %rax
movl (%rax), %esi
movq 0x4b7c(%rip), %rdi      # 0x8ff0
callq 0x3260
movq %rax, %rbx
leaq 0x1c30(%rip), %rsi      # 0x60b3
movl $0x2, %edx
movq %rax, %rdi
callq 0x31a0
leaq 0x1c44(%rip), %rsi      # 0x60db
movl $0x21, %edx
movq %rbx, %rdi
callq 0x31a0
movq -0x88(%rbp), %rsi
movq -0x80(%rbp), %rdx
movq %rbx, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30c0
jmp 0x45a1
movq -0x68(%rbp), %rax
movl (%rax), %esi
movq 0x4b1f(%rip), %rdi      # 0x8ff0
callq 0x3260
movq %rax, %rbx
leaq 0x1bd3(%rip), %rsi      # 0x60b3
movl $0x2, %edx
movq %rax, %rdi
callq 0x31a0
leaq 0x1b40(%rip), %rsi      # 0x6034
movl $0x23, %edx
movq %rbx, %rdi
callq 0x31a0
movsbl -0x29(%rbp), %edx
leaq -0x50(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x4a7f
movq -0x50(%rbp), %rsi
movq -0x48(%rbp), %rdx
movq %rbx, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30c0
jmp 0x4598
movq -0x68(%rbp), %rax
movl (%rax), %esi
movq 0x4ab4(%rip), %rdi      # 0x8ff0
callq 0x3260
movq %rax, %rbx
leaq 0x1b68(%rip), %rsi      # 0x60b3
movl $0x2, %edx
movq %rax, %rdi
callq 0x31a0
leaq 0x1ab2(%rip), %rsi      # 0x6011
movl $0x22, %edx
movq %rbx, %rdi
callq 0x31a0
movsbl -0x29(%rbp), %edx
leaq -0x50(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x4a7f
movq -0x50(%rbp), %rsi
movq -0x48(%rbp), %rdx
movq %rbx, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30c0
leaq -0x50(%rbp), %rdi
callq 0x30b0
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x31b0
movq -0x68(%rbp), %rax
movl (%rax), %esi
movq 0x4a38(%rip), %rdi      # 0x8ff0
callq 0x3260
movq %rax, %rbx
leaq 0x1aec(%rip), %rsi      # 0x60b3
movl $0x2, %edx
movq %rax, %rdi
callq 0x31a0
leaq 0x1a7d(%rip), %rsi      # 0x6058
movl $0x2a, %edx
movq %rbx, %rdi
callq 0x31a0
movsbl -0x29(%rbp), %edx
leaq -0x50(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x4a7f
movq -0x50(%rbp), %rsi
movq -0x48(%rbp), %rdx
movq %rbx, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30c0
jmp 0x4598
movq -0x68(%rbp), %rax
movl (%rax), %esi
movq 0x49cd(%rip), %rdi      # 0x8ff0
callq 0x3260
movq %rax, %rbx
leaq 0x1a81(%rip), %rsi      # 0x60b3
movl $0x2, %edx
movq %rax, %rdi
callq 0x31a0
leaq 0x1a70(%rip), %rsi      # 0x60b6
movl $0x24, %edx
movq %rbx, %rdi
callq 0x31a0
movb -0x29(%rbp), %al
leaq -0x50(%rbp), %rsi
movb %al, (%rsi)
movl $0x1, %edx
movq %rbx, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30c0
jmp 0x45a1
movq -0x68(%rbp), %rax
movl (%rax), %esi
movq 0x496d(%rip), %rdi      # 0x8ff0
callq 0x3260
movq %rax, %rbx
leaq 0x1a21(%rip), %rsi      # 0x60b3
movl $0x2, %edx
movq %rax, %rdi
callq 0x31a0
leaq 0x19dd(%rip), %rsi      # 0x6083
movl $0xe, %edx
movq %rbx, %rdi
callq 0x31a0
movb -0x29(%rbp), %al
leaq -0x60(%rbp), %rsi
movb %al, (%rsi)
movl $0x1, %edx
movq %rbx, %rdi
callq 0x31a0
movq %rax, %rbx
leaq 0x19bf(%rip), %rsi      # 0x6092
movl $0x23, %edx
movq %rax, %rdi
callq 0x31a0
movb -0x2a(%rbp), %al
leaq -0x60(%rbp), %rsi
movb %al, (%rsi)
movl $0x1, %edx
movq %rbx, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30c0
jmp 0x45a1
jmp 0x4721
jmp 0x4761
jmp 0x473c
jmp 0x4761
jmp 0x4761
jmp 0x473c
jmp 0x4721
jmp 0x4721
jmp 0x4761
jmp 0x4761
jmp 0x4761
jmp 0x4761
jmp 0x4721
jmp 0x4761
jmp 0x4761
movq %rax, %rbx
leaq -0x40(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x4764
callq 0x3160
jmp 0x4764
jmp 0x4761
jmp 0x473c
movq %rax, %rbx
jmp 0x4752
movq %rax, %rbx
movq -0x58(%rbp), %rdi
testq %rdi, %rdi
je 0x4752
callq 0x35ac
leaq -0x50(%rbp), %rdi
callq 0x49d6
jmp 0x4764
jmp 0x4761
jmp 0x4761
movq %rax, %rbx
movq -0x88(%rbp), %rdi
leaq -0x78(%rbp), %rax
cmpq %rax, %rdi
je 0x4779
callq 0x3160
movq %rbx, %rdi
callq 0x3280