// File: /workspace/github_cpp_makefile_star2_O2/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, -0x8c(%rbp)
movq %rdx, -0x38(%rbp)
movq %rsi, %r15
movq %rdi, %rbx
leaq 0x23a2(%rip), %rsi      # 0x6008
leaq -0x80(%rbp), %r13
leaq -0x60(%rbp), %rdx
movq %r13, %rdi
callq 0x3080
leaq -0x29(%rbp), %r12
movq %r15, %rdi
movq %r12, %rsi
callq 0x31f0
movzbl -0x29(%rbp), %r14d
cmpl $0x9, %r14d
je 0x3ca8
cmpl $0x2c, %r14d
je 0x3ca8
cmpl $0x20, %r14d
je 0x3ca8
cmpl $0xa, %r14d
jne 0x3ce1
movq -0x38(%rbp), %rax
incl (%rax)
cmpq $0x0, -0x78(%rbp)
je 0x3c7a
movq -0x80(%rbp), %rax
movzbl (%rax), %eax
leal -0x30(%rax), %ecx
cmpb $0x9, %cl
jbe 0x3e2a
cmpl $0x22, %eax
je 0x3ce9
cmpl $0x3a, %eax
je 0x3e39
movsbl %al, %edi
callq 0x3ba9
testb %al, %al
je 0x3c7a
jmp 0x3e8a
leal -0x30(%r14), %eax
cmpb $0xa, %al
jae 0x3cf7
movsbl %r14b, %esi
movq %r13, %rdi
callq 0x3120
jmp 0x3c7a
cmpl $0x22, %r14d
je 0x3d44
cmpl $0x3a, %r14d
je 0x3d35
cmpl $0x2e, %r14d
jne 0x3d53
movb $0x2e, %r14b
cmpq $0x0, -0x78(%rbp)
je 0x3ce9
movq -0x80(%rbp), %rax
movb (%rax), %al
addb $-0x30, %al
cmpb $0x9, %al
ja 0x3ce9
movq %r13, %rdi
callq 0x3bf1
testb %al, %al
jne 0x4125
movb -0x29(%rbp), %r14b
jmp 0x3ce9
movb $0x3a, %r14b
cmpq $0x0, -0x78(%rbp)
je 0x3ce9
jmp 0x4082
movb $0x22, %r14b
cmpq $0x0, -0x78(%rbp)
je 0x3ce9
jmp 0x3ed2
movq %rbx, -0x88(%rbp)
movsbl %r14b, %ebx
movl %ebx, %edi
callq 0x3b4d
testb %al, %al
je 0x3d9c
cmpq $0x0, -0x78(%rbp)
je 0x3f1d
movq -0x80(%rbp), %rax
movzbl (%rax), %eax
leal -0x30(%rax), %ecx
cmpb $0x9, %cl
movq -0x88(%rbp), %rbx
jbe 0x3fd1
cmpl $0x22, %eax
je 0x3ce9
jmp 0x3efa
movl %ebx, %edi
callq 0x3ba9
testb %al, %al
je 0x40df
cmpq $0x0, -0x78(%rbp)
movq -0x88(%rbp), %rbx
je 0x3ce9
movq -0x80(%rbp), %rax
movb (%rax), %al
addb $-0x30, %al
cmpb $0x9, %al
ja 0x3ce9
movq -0x38(%rbp), %rax
movl (%rax), %esi
movq 0x6216(%rip), %rdi      # 0x9ff0
callq 0x3270
leaq 0x22cd(%rip), %rsi      # 0x60b3
movq %rax, %rdi
callq 0x3160
leaq 0x2308(%rip), %rsi      # 0x60fd
movq %rax, %rdi
callq 0x3160
movq %rax, %rbx
movsbl -0x29(%rbp), %edx
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x4542
leaq -0x60(%rbp), %rsi
movq %rbx, %rdi
callq 0x3140
movq %rax, %rdi
callq 0x30d0
jmp 0x417d
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x44e5
jmp 0x3e97
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
pushq $0x1
popq %rdx
pushq $-0x1
popq %rcx
callq 0x3180
leaq -0xa0(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x4504
leaq -0x98(%rbp), %rdi
movq -0x8(%rdi), %rax
movq %rax, (%rbx)
movq (%rdi), %rax
andq $0x0, (%rdi)
movq %rax, 0x8(%rbx)
andq $0x0, -0x8(%rdi)
callq 0x353e
leaq -0x60(%rbp), %rdi
callq 0x30b0
jmp 0x3eb7
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x4523
leaq -0x58(%rbp), %rdi
movq -0x8(%rdi), %rax
movq %rax, (%rbx)
movq (%rdi), %rax
andq $0x0, (%rdi)
movq %rax, 0x8(%rbx)
andq $0x0, -0x8(%rdi)
callq 0x353e
leaq -0x80(%rbp), %rdi
callq 0x30b0
movq %rbx, %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq -0x80(%rbp), %rax
cmpb $0x22, (%rax)
jne 0x418e
leaq -0x80(%rbp), %rdi
pushq $0x22
popq %rsi
callq 0x3120
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x457d
jmp 0x3e97
cmpl $0x3a, %eax
jne 0x3feb
movq %r15, %rdi
callq 0x3060
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x45f6
jmp 0x3e97
cmpl $0x28, %r14d
movq -0x88(%rbp), %rbx
je 0x3f3a
cmpl $0x7b, %r14d
je 0x3f3a
cmpl $0x5b, %r14d
jne 0x406a
xorps %xmm0, %xmm0
movaps %xmm0, -0x60(%rbp)
andq $0x0, -0x50(%rbp)
leaq -0x2a(%rbp), %rsi
movq %r15, %rdi
callq 0x31f0
leaq -0x98(%rbp), %r14
leaq -0xa0(%rbp), %r13
leaq -0x2a(%rbp), %r12
movzbl -0x2a(%rbp), %eax
cmpl $0x29, %eax
je 0x4015
cmpl $0x5d, %eax
je 0x4015
cmpl $0x7d, %eax
je 0x4015
movq %r15, %rdi
callq 0x3060
movq %r13, %rdi
movq %r15, %rsi
movq -0x38(%rbp), %rdx
xorl %ecx, %ecx
callq 0x3c3e
cmpq $0x0, -0xa0(%rbp)
je 0x3fb4
leaq -0x60(%rbp), %rdi
movq %r13, %rsi
callq 0x459c
jmp 0x3fbc
movq %r15, %rdi
callq 0x3060
movq %r15, %rdi
movq %r12, %rsi
callq 0x31f0
movq %r14, %rdi
callq 0x353e
jmp 0x3f64
movq %r15, %rdi
callq 0x3060
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x44e5
jmp 0x3e97
movsbl %al, %edi
callq 0x3ba9
testb %al, %al
je 0x41e8
movq %r15, %rdi
callq 0x3060
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x4523
jmp 0x3e97
movsbl -0x29(%rbp), %edi
movsbl %al, %esi
callq 0x3b77
testb %al, %al
je 0x4231
leaq -0xa0(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x45d7
leaq -0x98(%rbp), %rdi
movq -0x8(%rdi), %rax
movq %rax, (%rbx)
movq (%rdi), %rax
andq $0x0, (%rdi)
movq %rax, 0x8(%rbx)
andq $0x0, -0x8(%rdi)
callq 0x353e
leaq -0x60(%rbp), %rdi
callq 0x4482
jmp 0x3eb7
cmpb $0x0, -0x8c(%rbp)
jne 0x4295
xorps %xmm0, %xmm0
movups %xmm0, (%rbx)
jmp 0x3eb7
movq -0x38(%rbp), %rax
movl (%rax), %esi
movq 0x5f61(%rip), %rdi      # 0x9ff0
callq 0x3270
leaq 0x2018(%rip), %rsi      # 0x60b3
movq %rax, %rdi
callq 0x3160
leaq 0x1f8a(%rip), %rsi      # 0x6034
movq %rax, %rdi
callq 0x3160
movq %rax, %rbx
movsbl -0x29(%rbp), %edx
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x4542
leaq -0x60(%rbp), %rsi
movq %rbx, %rdi
callq 0x3140
movq %rax, %rdi
callq 0x30d0
jmp 0x417d
movq -0x38(%rbp), %rax
movl (%rax), %esi
movq 0x5f04(%rip), %rdi      # 0x9ff0
callq 0x3270
leaq 0x1fbb(%rip), %rsi      # 0x60b3
movq %rax, %rdi
callq 0x3160
leaq 0x2026(%rip), %rsi      # 0x612d
movq %rax, %rdi
callq 0x3160
movsbl -0x29(%rbp), %esi
movq %rax, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30d0
jmp 0x4186
movq -0x38(%rbp), %rax
movl (%rax), %esi
movq 0x5ebe(%rip), %rdi      # 0x9ff0
callq 0x3270
leaq 0x1f75(%rip), %rsi      # 0x60b3
movq %rax, %rdi
callq 0x3160
leaq 0x1ec4(%rip), %rsi      # 0x6011
movq %rax, %rdi
callq 0x3160
movq %rax, %rbx
movsbl -0x29(%rbp), %edx
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x4542
leaq -0x60(%rbp), %rsi
movq %rbx, %rdi
callq 0x3140
movq %rax, %rdi
callq 0x30d0
leaq -0x60(%rbp), %rdi
callq 0x30b0
pushq $-0x1
popq %rdi
callq 0x31b0
movq -0x38(%rbp), %rax
movl (%rax), %esi
movq 0x5e55(%rip), %rdi      # 0x9ff0
callq 0x3270
leaq 0x1f0c(%rip), %rsi      # 0x60b3
movq %rax, %rdi
callq 0x3160
leaq 0x1ea2(%rip), %rsi      # 0x6058
movq %rax, %rdi
callq 0x3160
movq %rax, %rbx
movsbl -0x29(%rbp), %edx
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x4542
leaq -0x60(%rbp), %rsi
movq %rbx, %rdi
callq 0x3140
movq %rax, %rdi
callq 0x30d0
jmp 0x417d
movq -0x38(%rbp), %rax
movl (%rax), %esi
movq 0x5dfb(%rip), %rdi      # 0x9ff0
callq 0x3270
leaq 0x1eb2(%rip), %rsi      # 0x60b3
movq %rax, %rdi
callq 0x3160
leaq 0x1ecb(%rip), %rsi      # 0x60db
movq %rax, %rdi
callq 0x3160
leaq -0x80(%rbp), %rsi
movq %rax, %rdi
callq 0x3140
movq %rax, %rdi
callq 0x30d0
jmp 0x4186
movq -0x38(%rbp), %rax
movl (%rax), %esi
movq 0x5db2(%rip), %rdi      # 0x9ff0
callq 0x3270
leaq 0x1e69(%rip), %rsi      # 0x60b3
movq %rax, %rdi
callq 0x3160
leaq 0x1e2a(%rip), %rsi      # 0x6083
movq %rax, %rdi
callq 0x3160
movsbl -0x29(%rbp), %esi
movq %rax, %rdi
callq 0x31a0
leaq 0x1e1e(%rip), %rsi      # 0x6092
movq %rax, %rdi
callq 0x3160
movsbl -0x2a(%rbp), %esi
movq %rax, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30d0
jmp 0x4186
movq -0x38(%rbp), %rax
movl (%rax), %esi
movq 0x5d4e(%rip), %rdi      # 0x9ff0
callq 0x3270
leaq 0x1e05(%rip), %rsi      # 0x60b3
movq %rax, %rdi
callq 0x3160
leaq 0x1df9(%rip), %rsi      # 0x60b6
movq %rax, %rdi
callq 0x3160
movsbl -0x29(%rbp), %esi
movq %rax, %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x30d0
jmp 0x4186
jmp 0x4319
jmp 0x432d
jmp 0x42fc
jmp 0x432d
jmp 0x432d
jmp 0x4319
jmp 0x4319
jmp 0x432d
jmp 0x432d
jmp 0x432d
jmp 0x42fc
jmp 0x432d
jmp 0x4319
jmp 0x432d
jmp 0x42fc
movq %rax, %rbx
jmp 0x430c
movq %rax, %rbx
movq %r14, %rdi
callq 0x353e
leaq -0x60(%rbp), %rdi
callq 0x4482
jmp 0x4330
jmp 0x432d
movq %rax, %rbx
leaq -0x60(%rbp), %rdi
callq 0x30b0
jmp 0x4330
jmp 0x432d
jmp 0x432d
jmp 0x432d
movq %rax, %rbx
leaq -0x80(%rbp), %rdi
callq 0x30b0
movq %rbx, %rdi
callq 0x3280