// File: /workspace/github_cpp_makefile_star2_O2/rfotino[P]consolite-assembler/src/parser.cpp
// Function: Parser::firstPass()
bool Parser::firstPass() {
  _tokenizer->reset();
  if (_tokenizer->hasError()) {
    return false;
  }

  bool error = false;
  unsigned line = 0;
  unsigned byte_pos = 0;
  std::vector<Token> tokens;
  while (true) {
    // Get the next line of tokens
    _tokenizer->getLineOfTokens(tokens);
    line++;
    // If there is an error or the tokenizer is
    // empty, break out of the loop
    if (_tokenizer->isEmpty()) {
      line--;
      break;
    }
    if (_tokenizer->hasError()) {
      error = true;
      std::cerr << "Error reading from input file on line "
                << line << "." << std::endl;
      break;
    }
    // If it's an empty line, do nothing
    if (0 == tokens.size()) {
      continue;
    }
    // If there's an unknown token, that's an error
    bool has_unknown = false;
    for (auto token = tokens.begin(); token != tokens.end(); token++) {
      if (UNKNOWN == token->getType()) {
        error = true;
        has_unknown = true;
        std::cerr << "Error: Unknown token '" << token->getData()
                  << "' on line " << line << "." << std::endl;
        break;
      }
    }
    // If there's an unknown token don't validate any further
    if (has_unknown) {
      continue;
    }
    // Validate based on lead token
    switch (tokens[0].getType()) {
    case OPCODE:
      // Validate further based on specific opcode
      if (_validateInstruction(tokens, line)) {
        byte_pos += 4;
      } else {
        error = true;
      }
      break;
    case REGISTER:
      error = true;
      std::cerr << "Error: REG '" << tokens[0].getData()
                << "' not allowed at start of instruction on line " << line
                << "." << std::endl;
      break;
    case DATA:
      // Make sure all tokens on this line are data, and
      // add their sizes to the byte offset at this point
      for (auto token = tokens.begin(); token != tokens.end(); token++) {
        if (DATA == token->getType()) {
          byte_pos += token->getSize();
        } else {
          error = true;
          std::cerr << "Error: Unknown token '" << token->getData()
               << "', expected DATA on line " << line
               << "." << std::endl;
          break;
        }
      }
      // Pad data to 4 bytes so that instructions that
      // follow are aligned correctly
      while (0 != byte_pos % 4) {
        byte_pos++;
      }
      break;
    case LABELDECL:
      {
        const std::string label = tokens[0].getData();
        if (1 == tokens.size()) {
          if (_labels.find(label) == _labels.end()) {
            _labels[label] = byte_pos;
          } else {
            error = true;
            std::cerr << "Error: Duplicate LABEL '" << label
                      << "' on line " << line << "." << std::endl;
          }
        } else {
          error = true;
          std::cerr << "Error: Invalid syntax, LABEL '" << label
                    << "' must be by itself on line " << line
                    << "." << std::endl;
        }
      }
      break;
    case LABELREF:
    case UNKNOWN:
      error = true;
      std::cerr << "Error: Unknown token '" << tokens[0].getData()
                << "' on line " << line << "." << std::endl;
      break;
    }
  }

  if (!error) {
    // Check that all of the label references have a corresponding
    // label. If not, that is another error.
    for (auto ref = _labelRefs.begin(); ref != _labelRefs.end(); ref++) {
      std::string ref_label = ref->first;
      unsigned ref_line = ref->second;
      if (_labels.find(ref_label) == _labels.end()) {
        error = true;
        std::cerr << "Error: Could not find LABEL for reference '"
                  << ref_label << "' on line " << ref_line
                  << "." << std::endl;
      }
    }
    // Check if the total size of the output will be too large,
    // which would be another error.
    if (MAX_OUTPUT_SIZE < byte_pos) {
      error = true;
      std::cerr << "Error: Output would be " << byte_pos
                << " bytes, which is larger than the maximum output size of "
                << MAX_OUTPUT_SIZE << " bytes." << std::endl;
    }
  }

  return !error;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdi, %rbx
movq (%rdi), %rdi
callq 0x45be
movq (%rbx), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x20(%rdi,%rax)
movl $0x0, %r12d
jne 0x5ffb
movq $0x0, 0x10(%rsp)
leaq 0xc(%rsp), %rbp
andl $0x0, (%rbp)
xorps %xmm0, %xmm0
leaq 0x40(%rsp), %r13
movaps %xmm0, (%r13)
andq $0x0, 0x10(%r13)
leaq 0x8(%rbx), %rax
movq %rax, 0x18(%rsp)
leaq 0x10(%rbx), %rax
movq %rax, 0x60(%rsp)
leaq 0x1653(%rip), %rax      # 0x7166
movq %rax, 0x58(%rsp)
xorl %r12d, %r12d
movq %r13, %rsi
callq 0x44c0
incl 0xc(%rsp)
movq (%rbx), %rdi
callq 0x63ae
testb %al, %al
jne 0x5eb9
movq (%rbx), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x20(%rdi,%rax)
jne 0x5f63
movq 0x40(%rsp), %r14
movq 0x48(%rsp), %rax
cmpq %r14, %rax
je 0x5b1b
movq %rbp, %r15
movq %r14, %rbp
cmpq %rax, %rbp
je 0x5b76
cmpl $0x5, (%rbp)
je 0x5c04
addq $0x28, %rbp
jmp 0x5b61
movl (%r14), %ecx
cmpq $0x5, %rcx
ja 0x5db9
leaq 0x15fa(%rip), %rdx      # 0x7184
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
movq %r15, %rbp
jmpq *%rcx
movq 0x5453(%rip), %rdi      # 0xaff0
leaq 0x1720(%rip), %rsi      # 0x72c4
callq 0x2180
leaq 0x20(%rsp), %r15
movq %rax, %r14
movq 0x40(%rsp), %rsi
addq $0x8, %rsi
movq %r15, %rdi
callq 0x2210
movq %r14, %rdi
movq %r15, %rsi
callq 0x2170
movq %rax, %rdi
leaq 0x1704(%rip), %rsi      # 0x72db
callq 0x2180
movl 0xc(%rsp), %esi
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
leaq 0x1574(%rip), %rsi      # 0x7166
callq 0x2180
movq %rax, %rdi
callq 0x20e0
jmp 0x5da6
movq 0x53e5(%rip), %rdi      # 0xaff0
leaq 0x16b2(%rip), %rsi      # 0x72c4
callq 0x2180
movq %rax, %r14
addq $0x8, %rbp
leaq 0x20(%rsp), %r12
movq %r12, %rdi
movq %rbp, %rsi
callq 0x2210
movq %r14, %rdi
movq %r12, %rsi
callq 0x2170
movq %r15, %rbp
movq %rax, %rdi
leaq 0x1695(%rip), %rsi      # 0x72db
callq 0x2180
movl 0xc(%rsp), %esi
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
leaq 0x1505(%rip), %rsi      # 0x7166
callq 0x2180
movq %rax, %rdi
callq 0x20e0
leaq 0x20(%rsp), %rdi
jmp 0x5da9
leaq 0x20(%rsp), %r15
cmpq %rax, %r14
je 0x5e88
cmpl $0x2, (%r14)
jne 0x5e1b
movq 0x10(%rsp), %rcx
addl 0x10(%r14), %ecx
movq %rcx, 0x10(%rsp)
addq $0x28, %r14
jmp 0x5c7d
addq $0x8, %r14
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x2210
movq 0x48(%rsp), %rax
subq 0x40(%rsp), %rax
cmpq $0x28, %rax
jne 0x5dbe
movq 0x18(%rsp), %rdi
movq %r15, %rsi
callq 0x678a
cmpq 0x60(%rsp), %rax
je 0x5ea0
movq 0x5305(%rip), %rdi      # 0xaff0
leaq 0x164a(%rip), %rsi      # 0x733c
callq 0x2180
movq %rax, %rdi
movq %r15, %rsi
callq 0x2170
leaq 0x15d2(%rip), %rsi      # 0x72db
jmp 0x5de3
movq %rbx, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x52bc
movq 0x10(%rsp), %rdx
leal 0x4(%rdx), %ecx
testb %al, %al
cmovel %edx, %ecx
movzbl %r12b, %r12d
pushq $0x1
popq %rax
cmovel %eax, %r12d
movl %ecx, %eax
movq %rax, 0x10(%rsp)
jmp 0x5db1
movq 0x52ac(%rip), %rdi      # 0xaff0
leaq 0x159b(%rip), %rsi      # 0x72e6
callq 0x2180
leaq 0x20(%rsp), %r15
movq %rax, %r14
movq 0x40(%rsp), %rsi
addq $0x8, %rsi
movq %r15, %rdi
callq 0x2210
movq %r14, %rdi
movq %r15, %rsi
callq 0x2170
movq %rax, %rdi
leaq 0x1575(%rip), %rsi      # 0x72f3
callq 0x2180
movl 0xc(%rsp), %esi
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
leaq 0x13cd(%rip), %rsi      # 0x7166
callq 0x2180
movq %rax, %rdi
callq 0x20e0
movq %r15, %rdi
callq 0x20c0
movb $0x1, %r12b
movq (%rbx), %rdi
jmp 0x5b1b
movq %r15, %rbp
jmp 0x5db1
movq 0x522b(%rip), %rdi      # 0xaff0
leaq 0x1589(%rip), %rsi      # 0x7355
callq 0x2180
movq %rax, %rdi
movq %r15, %rsi
callq 0x2170
leaq 0x1591(%rip), %rsi      # 0x7374
movq %rax, %rdi
callq 0x2180
movl 0xc(%rsp), %esi
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
leaq 0x1365(%rip), %rsi      # 0x7166
callq 0x2180
movb $0x1, %r12b
movq %rax, %rdi
callq 0x20e0
movq %r15, %rdi
callq 0x20c0
jmp 0x5db1
movq 0x51ce(%rip), %rdi      # 0xaff0
leaq 0x149b(%rip), %rsi      # 0x72c4
callq 0x2180
movq %rax, %r12
addq $0x8, %r14
movq %r15, %rdi
movq %r14, %rsi
callq 0x2210
movq %r12, %rdi
movq %r15, %rsi
callq 0x2170
movq %rax, %rdi
leaq 0x14cd(%rip), %rsi      # 0x7322
callq 0x2180
movl 0xc(%rsp), %esi
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
leaq 0x12f6(%rip), %rsi      # 0x7166
callq 0x2180
movq %rax, %rdi
callq 0x20e0
movq %r15, %rdi
callq 0x20c0
movb $0x1, %r12b
movq 0x10(%rsp), %rcx
movl %ecx, %eax
negl %eax
andl $0x3, %eax
addl %eax, %ecx
movq %rcx, 0x10(%rsp)
jmp 0x5db1
movq 0x18(%rsp), %rdi
movq %r15, %rsi
callq 0x63c8
movq 0x10(%rsp), %rcx
movl %ecx, (%rax)
jmp 0x5e11
decl 0xc(%rsp)
testb $0x1, %r12b
jne 0x5fed
movq 0x38(%rbx), %r15
leaq 0x20(%rsp), %r13
leaq 0x128f(%rip), %r14      # 0x7166
cmpq 0x40(%rbx), %r15
je 0x5f84
movq %r13, %rdi
movq %r15, %rsi
callq 0x2210
movl 0x20(%r15), %ebp
movq 0x18(%rsp), %rdi
movq %r13, %rsi
callq 0x678a
cmpq 0x60(%rsp), %rax
jne 0x5f52
movq 0x50e5(%rip), %rdi      # 0xaff0
leaq 0x147f(%rip), %rsi      # 0x7391
callq 0x2180
movq %rax, %rdi
movq %r13, %rsi
callq 0x2170
movq %rax, %rdi
leaq 0x13af(%rip), %rsi      # 0x72db
callq 0x2180
movq %rax, %rdi
movq %rbp, %rsi
callq 0x2100
movq %rax, %rdi
movq %r14, %rsi
callq 0x2180
movb $0x1, %r12b
movq %rax, %rdi
callq 0x20e0
movq %r13, %rdi
callq 0x20c0
addq $0x28, %r15
jmp 0x5ed7
movq 0x5086(%rip), %rdi      # 0xaff0
leaq 0x132c(%rip), %rsi      # 0x729d
callq 0x2180
movl 0xc(%rsp), %esi
movq %rax, %rdi
callq 0x2100
jmp 0x5fd5
cmpl $0x10000, 0x10(%rsp)    # imm = 0x10000
jbe 0x5fed
movq 0x505b(%rip), %rdi      # 0xaff0
leaq 0x1421(%rip), %rsi      # 0x73bd
callq 0x2180
movl 0x10(%rsp), %esi
movq %rax, %rdi
callq 0x2100
leaq 0x1421(%rip), %rsi      # 0x73d5
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
movl $0x10000, %esi          # imm = 0x10000
callq 0x22a0
leaq 0x143e(%rip), %rcx      # 0x740e
movq %rcx, 0x58(%rsp)
movq %rax, %rdi
movq 0x58(%rsp), %rsi
callq 0x2180
movb $0x1, %r12b
movq %rax, %rdi
callq 0x20e0
xorb $0x1, %r12b
leaq 0x40(%rsp), %rdi
callq 0x642e
andb $0x1, %r12b
movl %r12d, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x6042
jmp 0x6042
jmp 0x6033
jmp 0x6042
jmp 0x6042
jmp 0x6042
jmp 0x6033
jmp 0x6042
jmp 0x6033
jmp 0x6033
jmp 0x6042
jmp 0x6042
jmp 0x6033
jmp 0x6033
jmp 0x6042
jmp 0x6042
jmp 0x6033
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x20c0
jmp 0x6045
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x642e
movq %rbx, %rdi
callq 0x22b0
nop