// File: Falldog[P]dcinja/src/include/inja/inja.hpp
// Function: inja::Parser::parse_expression(inja::Template&, inja::Token::Kind)
bool parse_expression(Template &tmpl, Token::Kind closing) {
    while (tok.kind != closing && tok.kind != Token::Kind::Eof) {
      // Literals
      switch (tok.kind) {
      case Token::Kind::String: {
        if (current_brace_level == 0 && current_bracket_level == 0) {
          json_literal_start = tok.text;
          add_json_literal(tmpl.content.c_str());
        }

      } break;
      case Token::Kind::Number: {
        if (current_brace_level == 0 && current_bracket_level == 0) {
          json_literal_start = tok.text;
          add_json_literal(tmpl.content.c_str());
        }

      } break;
      case Token::Kind::LeftBracket: {
        if (current_brace_level == 0 && current_bracket_level == 0) {
          json_literal_start = tok.text;
        }
        current_bracket_level += 1;

      } break;
      case Token::Kind::LeftBrace: {
        if (current_brace_level == 0 && current_bracket_level == 0) {
          json_literal_start = tok.text;
        }
        current_brace_level += 1;

      } break;
      case Token::Kind::RightBracket: {
        if (current_bracket_level == 0) {
          throw_parser_error("unexpected ']'");
        }

        current_bracket_level -= 1;
        if (current_brace_level == 0 && current_bracket_level == 0) {
          add_json_literal(tmpl.content.c_str());
        }

      } break;
      case Token::Kind::RightBrace: {
        if (current_brace_level == 0) {
          throw_parser_error("unexpected '}'");
        }

        current_brace_level -= 1;
        if (current_brace_level == 0 && current_bracket_level == 0) {
          add_json_literal(tmpl.content.c_str());
        }

      } break;
      case Token::Kind::Id: {
        get_peek_token();

        // Json Literal
        if (tok.text == static_cast<decltype(tok.text)>("true") || tok.text == static_cast<decltype(tok.text)>("false") || tok.text == static_cast<decltype(tok.text)>("null")) {
          if (current_brace_level == 0 && current_bracket_level == 0) {
            json_literal_start = tok.text;
            add_json_literal(tmpl.content.c_str());
          }

	      // Operator
        } else if (tok.text == "and" || tok.text == "or" || tok.text == "in" || tok.text == "not") {
          goto parse_operator;

        // Functions
        } else if (peek_tok.kind == Token::Kind::LeftParen) {
          operator_stack.emplace(std::make_shared<FunctionNode>(static_cast<std::string>(tok.text), tok.text.data() - tmpl.content.c_str()));
          function_stack.emplace(operator_stack.top().get(), current_paren_level);       

        // Variables
        } else {
          current_expression_list->rpn_output.emplace_back(std::make_shared<JsonNode>(static_cast<std::string>(tok.text), tok.text.data() - tmpl.content.c_str()));
        }

      // Operators
      } break;
      case Token::Kind::Equal:
      case Token::Kind::NotEqual:
      case Token::Kind::GreaterThan:
      case Token::Kind::GreaterEqual:
      case Token::Kind::LessThan:
      case Token::Kind::LessEqual:
      case Token::Kind::Plus:
      case Token::Kind::Minus:
      case Token::Kind::Times:
      case Token::Kind::Slash:
      case Token::Kind::Power:
      case Token::Kind::Percent:
      case Token::Kind::Dot: {

  parse_operator:
        FunctionStorage::Operation operation;
        switch (tok.kind) {
        case Token::Kind::Id: {
          if (tok.text == "and") {
            operation = FunctionStorage::Operation::And;
          } else if (tok.text == "or") {
            operation = FunctionStorage::Operation::Or;
          } else if (tok.text == "in") {
            operation = FunctionStorage::Operation::In;
          } else if (tok.text == "not") {
            operation = FunctionStorage::Operation::Not;
          } else {
            throw_parser_error("unknown operator in parser.");
          }
        } break;
        case Token::Kind::Equal: {
          operation = FunctionStorage::Operation::Equal;
        } break;
        case Token::Kind::NotEqual: {
          operation = FunctionStorage::Operation::NotEqual;
        } break;
        case Token::Kind::GreaterThan: {
          operation = FunctionStorage::Operation::Greater;
        } break;
        case Token::Kind::GreaterEqual: {
          operation = FunctionStorage::Operation::GreaterEqual;
        } break;
        case Token::Kind::LessThan: {
          operation = FunctionStorage::Operation::Less;
        } break;
        case Token::Kind::LessEqual: {
          operation = FunctionStorage::Operation::LessEqual;
        } break;
        case Token::Kind::Plus: {
          operation = FunctionStorage::Operation::Add;
        } break;
        case Token::Kind::Minus: {
          operation = FunctionStorage::Operation::Subtract;
        } break;
        case Token::Kind::Times: {
          operation = FunctionStorage::Operation::Multiplication;
        } break;
        case Token::Kind::Slash: {
          operation = FunctionStorage::Operation::Division;
        } break;
        case Token::Kind::Power: {
          operation = FunctionStorage::Operation::Power;
        } break;
        case Token::Kind::Percent: {
          operation = FunctionStorage::Operation::Modulo;
        } break;
        case Token::Kind::Dot: {
          operation = FunctionStorage::Operation::AtId;
        } break;
        default: {
          throw_parser_error("unknown operator in parser.");
        }
        }
        auto function_node = std::make_shared<FunctionNode>(operation, tok.text.data() - tmpl.content.c_str());

        while (!operator_stack.empty() && ((operator_stack.top()->precedence > function_node->precedence) || (operator_stack.top()->precedence == function_node->precedence && function_node->associativity == FunctionNode::Associativity::Left)) && (operator_stack.top()->operation != FunctionStorage::Operation::ParenLeft)) {
          current_expression_list->rpn_output.emplace_back(operator_stack.top());
          operator_stack.pop();
        }

        operator_stack.emplace(function_node);

      } break;
      case Token::Kind::Comma: {
        if (current_brace_level == 0 && current_bracket_level == 0) {
          if (function_stack.empty()) {
            throw_parser_error("unexpected ','");
          }

          function_stack.top().first->number_args += 1;
        }

      } break;
      case Token::Kind::Colon: {
        if (current_brace_level == 0 && current_bracket_level == 0) {
          throw_parser_error("unexpected ':'");
        }

      } break;
      case Token::Kind::LeftParen: {
        current_paren_level += 1;
        operator_stack.emplace(std::make_shared<FunctionNode>(FunctionStorage::Operation::ParenLeft, tok.text.data() - tmpl.content.c_str()));

        get_peek_token();
        if (peek_tok.kind == Token::Kind::RightParen) {
          if (!function_stack.empty() && function_stack.top().second == current_paren_level - 1) {
            function_stack.top().first->number_args = 0;
          }
        }

      } break;
      case Token::Kind::RightParen: {
        current_paren_level -= 1;
        while (!operator_stack.empty() && operator_stack.top()->operation != FunctionStorage::Operation::ParenLeft) {
          current_expression_list->rpn_output.emplace_back(operator_stack.top());
          operator_stack.pop();
        }

        if (!operator_stack.empty() && operator_stack.top()->operation == FunctionStorage::Operation::ParenLeft) {
          operator_stack.pop();
        }

        if (!function_stack.empty() && function_stack.top().second == current_paren_level) {
          auto func = function_stack.top().first;
          auto function_data = function_storage.find_function(func->name, func->number_args);
          if (function_data.operation == FunctionStorage::Operation::None) {
            throw_parser_error("unknown function " + func->name);
          }
          func->operation = function_data.operation;
          if (function_data.operation == FunctionStorage::Operation::Callback) {
            func->callback = function_data.callback;
          }

          if (operator_stack.empty()) {
            throw_parser_error("internal error at function " + func->name);
          }

          current_expression_list->rpn_output.emplace_back(operator_stack.top());
          operator_stack.pop();
          function_stack.pop();
        }
      }
      default:
        break;
      }

      get_next_token();
    }

    while (!operator_stack.empty()) {
      current_expression_list->rpn_output.emplace_back(operator_stack.top());
      operator_stack.pop();
    }

    return true;
  }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x4f0, %rsp            # imm = 0x4F0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x3c8(%rbp)
movq -0x3c8(%rbp), %rax
movl 0x48(%rax), %ecx
xorl %eax, %eax
cmpl -0x14(%rbp), %ecx
movb %al, -0x3c9(%rbp)
je 0x3508c
movq -0x3c8(%rbp), %rax
cmpl $0x22, 0x48(%rax)
setne %al
movb %al, -0x3c9(%rbp)
movb -0x3c9(%rbp), %al
testb $0x1, %al
jne 0x3509b
jmp 0x36657
movq -0x3c8(%rbp), %rax
movl 0x48(%rax), %eax
addl $-0x9, %eax
movl %eax, %ecx
movq %rcx, -0x3d8(%rbp)
subl $0x17, %eax
ja 0x36644
movq -0x3d8(%rbp), %rax
leaq 0x8b034(%rip), %rcx     # 0xc00fc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x90(%rax)
jne 0x3512c
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x3512c
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, 0x98(%rax)
movq 0x58(%rax), %rcx
movq %rcx, 0xa0(%rax)
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
callq 0xb1f0
movq -0x3c8(%rbp), %rdi
movq %rax, %rsi
callq 0x5da60
jmp 0x36646
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x90(%rax)
jne 0x3518c
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x3518c
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, 0x98(%rax)
movq 0x58(%rax), %rcx
movq %rcx, 0xa0(%rax)
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
callq 0xb1f0
movq -0x3c8(%rbp), %rdi
movq %rax, %rsi
callq 0x5da60
jmp 0x36646
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x90(%rax)
jne 0x351d0
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x351d0
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, 0x98(%rax)
movq 0x58(%rax), %rcx
movq %rcx, 0xa0(%rax)
movq -0x3c8(%rbp), %rax
movq 0x88(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x88(%rax)
jmp 0x36646
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x90(%rax)
jne 0x3522d
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x3522d
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, 0x98(%rax)
movq 0x58(%rax), %rcx
movq %rcx, 0xa0(%rax)
movq -0x3c8(%rbp), %rax
movq 0x90(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x90(%rax)
jmp 0x36646
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x352e0
leaq -0x39(%rbp), %rdi
movq %rdi, -0x3e0(%rbp)
callq 0xba70
movq -0x3e0(%rbp), %rdx
leaq 0x90e30(%rip), %rsi     # 0xc60ae
leaq -0x38(%rbp), %rdi
callq 0x10b90
jmp 0x35289
movq -0x3c8(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x330f0
jmp 0x3529b
leaq -0x38(%rbp), %rdi
callq 0xbb98
leaq -0x39(%rbp), %rdi
callq 0xb600
jmp 0x352e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x352d2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xbb98
leaq -0x39(%rbp), %rdi
callq 0xb600
jmp 0x366ca
movq -0x3c8(%rbp), %rax
movq 0x88(%rax), %rcx
subq $0x1, %rcx
movq %rcx, 0x88(%rax)
cmpq $0x0, 0x90(%rax)
jne 0x35330
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x35330
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
callq 0xb1f0
movq -0x3c8(%rbp), %rdi
movq %rax, %rsi
callq 0x5da60
jmp 0x36646
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x90(%rax)
jne 0x353ca
leaq -0x71(%rbp), %rdi
movq %rdi, -0x3e8(%rbp)
callq 0xba70
movq -0x3e8(%rbp), %rdx
leaq 0x90d55(%rip), %rsi     # 0xc60bd
leaq -0x70(%rbp), %rdi
callq 0x10b90
jmp 0x35373
movq -0x3c8(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x330f0
jmp 0x35385
leaq -0x70(%rbp), %rdi
callq 0xbb98
leaq -0x71(%rbp), %rdi
callq 0xb600
jmp 0x353ca
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x353bc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0xbb98
leaq -0x71(%rbp), %rdi
callq 0xb600
jmp 0x366ca
movq -0x3c8(%rbp), %rax
movq 0x90(%rax), %rcx
subq $0x1, %rcx
movq %rcx, 0x90(%rax)
cmpq $0x0, 0x90(%rax)
jne 0x3541a
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x3541a
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
callq 0xb1f0
movq -0x3c8(%rbp), %rdi
movq %rax, %rsi
callq 0x5da60
jmp 0x36646
movq -0x3c8(%rbp), %rdi
callq 0x5dc00
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0x88(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0x80(%rbp)
leaq -0x98(%rbp), %rdi
leaq 0x90c79(%rip), %rsi     # 0xc60cc
callq 0x31e20
movq -0x88(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0x98(%rbp), %rdx
movq -0x90(%rbp), %rcx
callq 0x3a5e0
testb $0x1, %al
jne 0x3552a
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0xa8(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0xa0(%rbp)
leaq -0xb8(%rbp), %rdi
leaq 0x8ce3c(%rip), %rsi     # 0xc22e5
callq 0x31e20
movq -0xa8(%rbp), %rdi
movq -0xa0(%rbp), %rsi
movq -0xb8(%rbp), %rdx
movq -0xb0(%rbp), %rcx
callq 0x3a5e0
testb $0x1, %al
jne 0x3552a
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0xc8(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0xc0(%rbp)
leaq -0xd8(%rbp), %rdi
leaq 0x8f57a(%rip), %rsi     # 0xc4a78
callq 0x31e20
movq -0xc8(%rbp), %rdi
movq -0xc0(%rbp), %rsi
movq -0xd8(%rbp), %rdx
movq -0xd0(%rbp), %rcx
callq 0x3a5e0
testb $0x1, %al
jne 0x3552a
jmp 0x3558a
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x90(%rax)
jne 0x35585
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x35585
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, 0x98(%rax)
movq 0x58(%rax), %rcx
movq %rcx, 0xa0(%rax)
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
callq 0xb1f0
movq -0x3c8(%rbp), %rdi
movq %rax, %rsi
callq 0x5da60
jmp 0x359bd
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0xe8(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0xe0(%rbp)
leaq -0xf8(%rbp), %rdi
leaq 0x934b6(%rip), %rsi     # 0xc8a6b
callq 0x31e20
movq -0xe8(%rbp), %rdi
movq -0xe0(%rbp), %rsi
movq -0xf8(%rbp), %rdx
movq -0xf0(%rbp), %rcx
callq 0x5dc60
testb $0x1, %al
jne 0x356e8
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0x108(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0x100(%rbp)
leaq -0x118(%rbp), %rdi
leaq 0x8d0fc(%rip), %rsi     # 0xc270a
callq 0x31e20
movq -0x108(%rbp), %rdi
movq -0x100(%rbp), %rsi
movq -0x118(%rbp), %rdx
movq -0x110(%rbp), %rcx
callq 0x5dc60
testb $0x1, %al
jne 0x356e8
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0x128(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0x120(%rbp)
leaq -0x138(%rbp), %rdi
leaq 0x8d076(%rip), %rsi     # 0xc26dd
callq 0x31e20
movq -0x128(%rbp), %rdi
movq -0x120(%rbp), %rsi
movq -0x138(%rbp), %rdx
movq -0x130(%rbp), %rcx
callq 0x5dc60
testb $0x1, %al
jne 0x356e8
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0x148(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0x140(%rbp)
leaq -0x158(%rbp), %rdi
leaq 0x90a15(%rip), %rsi     # 0xc60d1
callq 0x31e20
movq -0x148(%rbp), %rdi
movq -0x140(%rbp), %rsi
movq -0x158(%rbp), %rdx
movq -0x150(%rbp), %rcx
callq 0x5dc60
testb $0x1, %al
jne 0x356e8
jmp 0x356ed
jmp 0x359c4
movq -0x3c8(%rbp), %rax
cmpl $0x15, 0x60(%rax)
jne 0x35886
movq -0x3c8(%rbp), %rax
movq %rax, %rcx
addq $0x108, %rcx            # imm = 0x108
movq %rcx, -0x400(%rbp)
addq $0x50, %rax
movq %rax, -0x3f8(%rbp)
leaq -0x189(%rbp), %rdi
movq %rdi, -0x3f0(%rbp)
callq 0xba70
movq -0x3f8(%rbp), %rsi
movq -0x3f0(%rbp), %rdx
leaq -0x188(%rbp), %rdi
callq 0x31e70
jmp 0x35750
movq -0x3c8(%rbp), %rdi
addq $0x50, %rdi
callq 0x332c0
movq %rax, -0x408(%rbp)
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
callq 0xb1f0
movq %rax, %rcx
movq -0x408(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x198(%rbp)
leaq -0x168(%rbp), %rdi
leaq -0x188(%rbp), %rsi
leaq -0x198(%rbp), %rdx
callq 0x5dd10
jmp 0x357a4
movq -0x400(%rbp), %rdi
leaq -0x168(%rbp), %rsi
callq 0x5dce0
jmp 0x357b9
leaq -0x168(%rbp), %rdi
callq 0x31b20
leaq -0x188(%rbp), %rdi
callq 0xbb98
leaq -0x189(%rbp), %rdi
callq 0xb600
movq -0x3c8(%rbp), %rdi
movq %rdi, %rax
addq $0xb8, %rax
movq %rax, -0x410(%rbp)
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq %rax, %rdi
callq 0x5dde0
movq -0x3c8(%rbp), %rdx
movq -0x410(%rbp), %rdi
movq %rax, -0x1a0(%rbp)
addq $0x80, %rdx
leaq -0x1a0(%rbp), %rsi
callq 0x5dd90
jmp 0x359b9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x35875
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x35869
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x168(%rbp), %rdi
callq 0x31b20
leaq -0x188(%rbp), %rdi
callq 0xbb98
leaq -0x189(%rbp), %rdi
callq 0xb600
jmp 0x366ca
movq -0x3c8(%rbp), %rax
movq 0xb0(%rax), %rcx
addq $0x10, %rcx
movq %rcx, -0x428(%rbp)
addq $0x50, %rax
movq %rax, -0x420(%rbp)
leaq -0x1d1(%rbp), %rdi
movq %rdi, -0x418(%rbp)
callq 0xba70
movq -0x420(%rbp), %rsi
movq -0x418(%rbp), %rdx
leaq -0x1d0(%rbp), %rdi
callq 0x31e70
jmp 0x358d9
movq -0x3c8(%rbp), %rdi
addq $0x50, %rdi
callq 0x332c0
movq %rax, -0x430(%rbp)
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
callq 0xb1f0
movq %rax, %rcx
movq -0x430(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x1e0(%rbp)
leaq -0x1b0(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
leaq -0x1e0(%rbp), %rdx
callq 0x5de80
jmp 0x3592d
movq -0x428(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
callq 0x5de00
jmp 0x35942
leaq -0x1b0(%rbp), %rdi
callq 0x5df00
leaq -0x1d0(%rbp), %rdi
callq 0xbb98
leaq -0x1d1(%rbp), %rdi
callq 0xb600
jmp 0x359b9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x359a8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x3599c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0x5df00
leaq -0x1d0(%rbp), %rdi
callq 0xbb98
leaq -0x1d1(%rbp), %rdi
callq 0xb600
jmp 0x366ca
jmp 0x359bb
jmp 0x359bd
jmp 0x36646
jmp 0x359c4
movq -0x3c8(%rbp), %rax
movl 0x48(%rax), %eax
addl $-0x9, %eax
movl %eax, %ecx
movq %rcx, -0x438(%rbp)
subl $0x17, %eax
ja 0x35cec
movq -0x438(%rbp), %rax
leaq 0x8a76b(%rip), %rcx     # 0xc015c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0x1f8(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0x1f0(%rbp)
leaq -0x208(%rbp), %rdi
leaq 0x93046(%rip), %rsi     # 0xc8a6b
callq 0x31e20
movq -0x1f8(%rbp), %rdi
movq -0x1f0(%rbp), %rsi
movq -0x208(%rbp), %rdx
movq -0x200(%rbp), %rcx
callq 0x5dc60
testb $0x1, %al
jne 0x35a51
jmp 0x35a60
movl $0x1, -0x1e4(%rbp)
jmp 0x35c2d
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0x218(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0x210(%rbp)
leaq -0x228(%rbp), %rdi
leaq 0x8cc7f(%rip), %rsi     # 0xc270a
callq 0x31e20
movq -0x218(%rbp), %rdi
movq -0x210(%rbp), %rsi
movq -0x228(%rbp), %rdx
movq -0x220(%rbp), %rcx
callq 0x5dc60
testb $0x1, %al
jne 0x35ab7
jmp 0x35ac6
movl $0x2, -0x1e4(%rbp)
jmp 0x35c2b
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0x238(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0x230(%rbp)
leaq -0x248(%rbp), %rdi
leaq 0x8cbec(%rip), %rsi     # 0xc26dd
callq 0x31e20
movq -0x238(%rbp), %rdi
movq -0x230(%rbp), %rsi
movq -0x248(%rbp), %rdx
movq -0x240(%rbp), %rcx
callq 0x5dc60
testb $0x1, %al
jne 0x35b1d
jmp 0x35b2c
movl $0x3, -0x1e4(%rbp)
jmp 0x35c29
movq -0x3c8(%rbp), %rax
movq 0x50(%rax), %rcx
movq %rcx, -0x258(%rbp)
movq 0x58(%rax), %rax
movq %rax, -0x250(%rbp)
leaq -0x268(%rbp), %rdi
leaq 0x9057a(%rip), %rsi     # 0xc60d1
callq 0x31e20
movq -0x258(%rbp), %rdi
movq -0x250(%rbp), %rsi
movq -0x268(%rbp), %rdx
movq -0x260(%rbp), %rcx
callq 0x5dc60
testb $0x1, %al
jne 0x35b83
jmp 0x35b92
movl $0x0, -0x1e4(%rbp)
jmp 0x35c27
leaq -0x289(%rbp), %rdi
movq %rdi, -0x440(%rbp)
callq 0xba70
movq -0x440(%rbp), %rdx
leaq 0x90522(%rip), %rsi     # 0xc60d5
leaq -0x288(%rbp), %rdi
callq 0x10b90
jmp 0x35bc1
movq -0x3c8(%rbp), %rdi
leaq -0x288(%rbp), %rsi
callq 0x330f0
jmp 0x35bd6
leaq -0x288(%rbp), %rdi
callq 0xbb98
leaq -0x289(%rbp), %rdi
callq 0xb600
jmp 0x35c27
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x35c16
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x288(%rbp), %rdi
callq 0xbb98
leaq -0x289(%rbp), %rdi
callq 0xb600
jmp 0x366ca
jmp 0x35c29
jmp 0x35c2b
jmp 0x35c2d
jmp 0x35d48
movl $0x4, -0x1e4(%rbp)
jmp 0x35d48
movl $0x5, -0x1e4(%rbp)
jmp 0x35d48
movl $0x6, -0x1e4(%rbp)
jmp 0x35d48
movl $0x7, -0x1e4(%rbp)
jmp 0x35d48
movl $0x8, -0x1e4(%rbp)
jmp 0x35d48
movl $0x9, -0x1e4(%rbp)
jmp 0x35d48
movl $0xa, -0x1e4(%rbp)
jmp 0x35d48
movl $0xb, -0x1e4(%rbp)
jmp 0x35d48
movl $0xc, -0x1e4(%rbp)
jmp 0x35d48
movl $0xd, -0x1e4(%rbp)
jmp 0x35d48
movl $0xe, -0x1e4(%rbp)
jmp 0x35d48
movl $0xf, -0x1e4(%rbp)
jmp 0x35d48
movl $0x10, -0x1e4(%rbp)
jmp 0x35d48
leaq -0x2b1(%rbp), %rdi
movq %rdi, -0x448(%rbp)
callq 0xba70
movq -0x448(%rbp), %rdx
leaq 0x903c8(%rip), %rsi     # 0xc60d5
leaq -0x2b0(%rbp), %rdi
callq 0x10b90
jmp 0x35d1b
movq -0x3c8(%rbp), %rdi
leaq -0x2b0(%rbp), %rsi
callq 0x330f0
jmp 0x35d30
leaq -0x2b0(%rbp), %rdi
callq 0xbb98
leaq -0x2b1(%rbp), %rdi
callq 0xb600
movq -0x3c8(%rbp), %rdi
addq $0x48, %rdi
addq $0x8, %rdi
callq 0x332c0
movq %rax, -0x450(%rbp)
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
callq 0xb1f0
movq %rax, %rcx
movq -0x450(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x2d0(%rbp)
leaq -0x2c8(%rbp), %rdi
leaq -0x1e4(%rbp), %rsi
leaq -0x2d0(%rbp), %rdx
callq 0x5df20
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5dfa0
movb %al, -0x451(%rbp)
jmp 0x35db9
movb -0x451(%rbp), %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x452(%rbp)
jne 0x35ec2
jmp 0x35dd2
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq %rax, -0x460(%rbp)
jmp 0x35dee
movq -0x460(%rbp), %rdi
callq 0x5dfc0
movl 0x10(%rax), %eax
movl %eax, -0x464(%rbp)
leaq -0x2c8(%rbp), %rdi
callq 0x5dfc0
movq %rax, %rcx
movl -0x464(%rbp), %eax
cmpl 0x10(%rcx), %eax
ja 0x35e8d
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq %rax, -0x470(%rbp)
jmp 0x35e39
movq -0x470(%rbp), %rdi
callq 0x5dfc0
movl 0x10(%rax), %eax
movl %eax, -0x474(%rbp)
leaq -0x2c8(%rbp), %rdi
callq 0x5dfc0
movl -0x474(%rbp), %ecx
movq %rax, %rdx
xorl %eax, %eax
cmpl 0x10(%rdx), %ecx
movb %al, -0x452(%rbp)
jne 0x35ec2
leaq -0x2c8(%rbp), %rdi
callq 0x5dfc0
movq %rax, %rcx
xorl %eax, %eax
cmpl $0x0, 0x14(%rcx)
movb %al, -0x452(%rbp)
jne 0x35ec2
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq %rax, -0x480(%rbp)
jmp 0x35ea9
movq -0x480(%rbp), %rdi
callq 0x5dfc0
cmpl $0x2c, 0x18(%rax)
setne %al
movb %al, -0x452(%rbp)
movb -0x452(%rbp), %al
testb $0x1, %al
jne 0x35ed1
jmp 0x35f82
movq -0x3c8(%rbp), %rdi
movq 0xb0(%rdi), %rax
addq $0x10, %rax
movq %rax, -0x490(%rbp)
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq %rax, -0x488(%rbp)
jmp 0x35eff
movq -0x488(%rbp), %rsi
movq -0x490(%rbp), %rdi
callq 0x5dfe0
jmp 0x35f14
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5e060
jmp 0x35f29
jmp 0x35d9e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x35f54
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x2b0(%rbp), %rdi
callq 0xbb98
leaq -0x2b1(%rbp), %rdi
callq 0xb600
jmp 0x366ca
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x2c8(%rbp), %rdi
callq 0x31b20
jmp 0x366ca
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
leaq -0x2c8(%rbp), %rsi
callq 0x5e080
jmp 0x35f9e
leaq -0x2c8(%rbp), %rdi
callq 0x31b20
jmp 0x36646
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x90(%rax)
jne 0x360a9
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x360a9
movq -0x3c8(%rbp), %rdi
addq $0xb8, %rdi
callq 0x5e0b0
testb $0x1, %al
jne 0x35ff5
jmp 0x3608a
leaq -0x2f1(%rbp), %rdi
movq %rdi, -0x498(%rbp)
callq 0xba70
movq -0x498(%rbp), %rdx
leaq 0x900db(%rip), %rsi     # 0xc60f1
leaq -0x2f0(%rbp), %rdi
callq 0x10b90
jmp 0x36024
movq -0x3c8(%rbp), %rdi
leaq -0x2f0(%rbp), %rsi
callq 0x330f0
jmp 0x36039
leaq -0x2f0(%rbp), %rdi
callq 0xbb98
leaq -0x2f1(%rbp), %rdi
callq 0xb600
jmp 0x3608a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x36079
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x2f0(%rbp), %rdi
callq 0xbb98
leaq -0x2f1(%rbp), %rdi
callq 0xb600
jmp 0x366ca
movq -0x3c8(%rbp), %rdi
addq $0xb8, %rdi
callq 0x5e0d0
movq (%rax), %rax
movl 0x40(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x40(%rax)
jmp 0x36646
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x90(%rax)
jne 0x3616d
movq -0x3c8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x3616d
leaq -0x319(%rbp), %rdi
movq %rdi, -0x4a0(%rbp)
callq 0xba70
movq -0x4a0(%rbp), %rdx
leaq 0x90007(%rip), %rsi     # 0xc6100
leaq -0x318(%rbp), %rdi
callq 0x10b90
jmp 0x36107
movq -0x3c8(%rbp), %rdi
leaq -0x318(%rbp), %rsi
callq 0x330f0
jmp 0x3611c
leaq -0x318(%rbp), %rdi
callq 0xbb98
leaq -0x319(%rbp), %rdi
callq 0xb600
jmp 0x3616d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x3615c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x318(%rbp), %rdi
callq 0xbb98
leaq -0x319(%rbp), %rdi
callq 0xb600
jmp 0x366ca
jmp 0x36646
movq -0x3c8(%rbp), %rdi
movq 0x80(%rdi), %rax
incq %rax
movq %rax, 0x80(%rdi)
movq %rdi, %rax
addq $0x108, %rax            # imm = 0x108
movq %rax, -0x4b0(%rbp)
movl $0x2c, -0x334(%rbp)
addq $0x50, %rdi
callq 0x332c0
movq %rax, -0x4b8(%rbp)
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
callq 0xb1f0
movq %rax, %rcx
movq -0x4b8(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x340(%rbp)
leaq -0x330(%rbp), %rdi
movq %rdi, -0x4a8(%rbp)
leaq -0x334(%rbp), %rsi
leaq -0x340(%rbp), %rdx
callq 0x5e0f0
movq -0x4b0(%rbp), %rdi
movq -0x4a8(%rbp), %rsi
callq 0x5dce0
jmp 0x3620b
leaq -0x330(%rbp), %rdi
callq 0x31b20
movq -0x3c8(%rbp), %rdi
callq 0x5dc00
movq -0x3c8(%rbp), %rax
cmpl $0x16, 0x60(%rax)
jne 0x362b7
movq -0x3c8(%rbp), %rdi
addq $0xb8, %rdi
callq 0x5e0b0
testb $0x1, %al
jne 0x362b5
movq -0x3c8(%rbp), %rdi
addq $0xb8, %rdi
callq 0x5e0d0
movq -0x3c8(%rbp), %rcx
movq 0x8(%rax), %rax
movq 0x80(%rcx), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jne 0x362b5
movq -0x3c8(%rbp), %rdi
addq $0xb8, %rdi
callq 0x5e0d0
movq (%rax), %rax
movl $0x0, 0x40(%rax)
jmp 0x362b5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x330(%rbp), %rdi
callq 0x31b20
jmp 0x366ca
jmp 0x362b7
jmp 0x36646
movq -0x3c8(%rbp), %rax
movq 0x80(%rax), %rcx
subq $0x1, %rcx
movq %rcx, 0x80(%rax)
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5dfa0
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x4b9(%rbp)
jne 0x3631f
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq %rax, %rdi
callq 0x5dfc0
cmpl $0x2c, 0x18(%rax)
setne %al
movb %al, -0x4b9(%rbp)
movb -0x4b9(%rbp), %al
testb $0x1, %al
jne 0x3632b
jmp 0x36377
movq -0x3c8(%rbp), %rdi
movq 0xb0(%rdi), %rax
addq $0x10, %rax
movq %rax, -0x4c8(%rbp)
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq -0x4c8(%rbp), %rdi
movq %rax, %rsi
callq 0x5dfe0
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5e060
jmp 0x362d5
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5dfa0
testb $0x1, %al
jne 0x363c2
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq %rax, %rdi
callq 0x5dfc0
cmpl $0x2c, 0x18(%rax)
jne 0x363c2
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5e060
movq -0x3c8(%rbp), %rdi
addq $0xb8, %rdi
callq 0x5e0b0
testb $0x1, %al
jne 0x36642
movq -0x3c8(%rbp), %rdi
addq $0xb8, %rdi
callq 0x5e0d0
movq -0x3c8(%rbp), %rcx
movq 0x8(%rax), %rax
cmpq 0x80(%rcx), %rax
jne 0x36642
movq -0x3c8(%rbp), %rdi
addq $0xb8, %rdi
callq 0x5e0d0
movq %rax, %rcx
movq -0x3c8(%rbp), %rax
movq (%rcx), %rcx
movq %rcx, -0x348(%rbp)
movq 0x40(%rax), %rax
movq %rax, -0x4d0(%rbp)
movq -0x348(%rbp), %rdi
addq $0x20, %rdi
callq 0xb610
movq -0x4d0(%rbp), %rsi
movq %rax, -0x380(%rbp)
movq %rdx, -0x378(%rbp)
movq -0x348(%rbp), %rax
movl 0x40(%rax), %r8d
movq -0x380(%rbp), %rdx
movq -0x378(%rbp), %rcx
leaq -0x370(%rbp), %rdi
callq 0x5e170
cmpl $0x2e, -0x370(%rbp)
jne 0x364fe
movq -0x348(%rbp), %rdx
addq $0x20, %rdx
leaq 0x8fc70(%rip), %rsi     # 0xc610f
leaq -0x3a0(%rbp), %rdi
callq 0x1ce80
jmp 0x364ad
movq -0x3c8(%rbp), %rdi
leaq -0x3a0(%rbp), %rsi
callq 0x330f0
jmp 0x364c2
leaq -0x3a0(%rbp), %rdi
callq 0xbb98
jmp 0x364fe
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x36631
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x3a0(%rbp), %rdi
callq 0xbb98
jmp 0x36631
movl -0x370(%rbp), %ecx
movq -0x348(%rbp), %rax
movl %ecx, 0x18(%rax)
cmpl $0x2b, -0x370(%rbp)
jne 0x36532
leaq -0x368(%rbp), %rsi
movq -0x348(%rbp), %rdi
addq $0x48, %rdi
callq 0x5e4d0
jmp 0x36530
jmp 0x36532
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5dfa0
movb %al, -0x4d1(%rbp)
jmp 0x3654d
movb -0x4d1(%rbp), %al
testb $0x1, %al
jne 0x36559
jmp 0x365b6
movq -0x348(%rbp), %rdx
addq $0x20, %rdx
leaq 0x8fbb6(%rip), %rsi     # 0xc6121
leaq -0x3c0(%rbp), %rdi
callq 0x1ce80
jmp 0x36579
movq -0x3c8(%rbp), %rdi
leaq -0x3c0(%rbp), %rsi
callq 0x330f0
jmp 0x3658e
leaq -0x3c0(%rbp), %rdi
callq 0xbb98
jmp 0x365b6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x3c0(%rbp), %rdi
callq 0xbb98
jmp 0x36631
movq -0x3c8(%rbp), %rdi
movq 0xb0(%rdi), %rax
addq $0x10, %rax
movq %rax, -0x4e8(%rbp)
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq %rax, -0x4e0(%rbp)
jmp 0x365e4
movq -0x4e0(%rbp), %rsi
movq -0x4e8(%rbp), %rdi
callq 0x5dfe0
jmp 0x365f9
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5e060
jmp 0x3660e
movq -0x3c8(%rbp), %rdi
addq $0xb8, %rdi
callq 0x5e520
jmp 0x36623
leaq -0x370(%rbp), %rdi
callq 0x2d680
jmp 0x36642
leaq -0x370(%rbp), %rdi
callq 0x2d680
jmp 0x366ca
jmp 0x36644
jmp 0x36646
movq -0x3c8(%rbp), %rdi
callq 0x33060
jmp 0x35061
jmp 0x36659
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5dfa0
xorb $-0x1, %al
testb $0x1, %al
jne 0x36674
jmp 0x366bd
movq -0x3c8(%rbp), %rdi
movq 0xb0(%rdi), %rax
addq $0x10, %rax
movq %rax, -0x4f0(%rbp)
addq $0x108, %rdi            # imm = 0x108
callq 0x5ddc0
movq -0x4f0(%rbp), %rdi
movq %rax, %rsi
callq 0x5dfe0
movq -0x3c8(%rbp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5e060
jmp 0x36659
movb $0x1, %al
andb $0x1, %al
addq $0x4f0, %rsp            # imm = 0x4F0
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0xba60
nopw %cs:(%rax,%rax)
nopl (%rax)