// File: Falldog[P]dcinja/src/include/inja/inja.hpp
// Function: inja::Lexer::scan()
Token scan() {
    tok_start = pos;

  again:
    if (tok_start >= m_in.size()) {
      return make_token(Token::Kind::Eof);
    }

    switch (state) {
    default:
    case State::Text: {
      // fast-scan to first open character
      size_t open_start = m_in.substr(pos).find_first_of(config.open_chars);
      if (open_start == nonstd::string_view::npos) {
        // didn't find open, return remaining text as text token
        pos = m_in.size();
        return make_token(Token::Kind::Text);
      }
      pos += open_start;

      // try to match one of the opening sequences, and get the close
      nonstd::string_view open_str = m_in.substr(pos);
      bool must_lstrip = false;
      if (inja::string_view::starts_with(open_str, config.expression_open)) {
        if (inja::string_view::starts_with(open_str, config.expression_open_force_lstrip)) {
          state = State::ExpressionStartForceLstrip;
          must_lstrip = true;
        } else {
          state = State::ExpressionStart;
        }
      } else if (inja::string_view::starts_with(open_str, config.statement_open)) {
        if (inja::string_view::starts_with(open_str, config.statement_open_no_lstrip)) {
          state = State::StatementStartNoLstrip;
        } else if (inja::string_view::starts_with(open_str, config.statement_open_force_lstrip )) {
          state = State::StatementStartForceLstrip;
          must_lstrip = true;
        } else {
          state = State::StatementStart;
          must_lstrip = config.lstrip_blocks;
        }
      } else if (inja::string_view::starts_with(open_str, config.comment_open)) {
        state = State::CommentStart;
        must_lstrip = config.lstrip_blocks;
      } else if ((pos == 0 || m_in[pos - 1] == '\n') && inja::string_view::starts_with(open_str, config.line_statement)) {
        state = State::LineStart;
      } else {
        pos += 1; // wasn't actually an opening sequence
        goto again;
      }

      nonstd::string_view text = string_view::slice(m_in, tok_start, pos);
      if (must_lstrip) {
        text = clear_final_line_if_whitespace(text);
      }

      if (text.empty()) {
        goto again; // don't generate empty token
      }
      return Token(Token::Kind::Text, text);
    }
    case State::ExpressionStart: {
      state = State::ExpressionBody;
      pos += config.expression_open.size();
      return make_token(Token::Kind::ExpressionOpen);
    }
    case State::ExpressionStartForceLstrip: {
      state = State::ExpressionBody;
      pos += config.expression_open_force_lstrip.size();
      return make_token(Token::Kind::ExpressionOpen);
    }
    case State::LineStart: {
      state = State::LineBody;
      pos += config.line_statement.size();
      return make_token(Token::Kind::LineStatementOpen);
    }
    case State::StatementStart: {
      state = State::StatementBody;
      pos += config.statement_open.size();
      return make_token(Token::Kind::StatementOpen);
    }
    case State::StatementStartNoLstrip: {
      state = State::StatementBody;
      pos += config.statement_open_no_lstrip.size();
      return make_token(Token::Kind::StatementOpen);
    }
    case State::StatementStartForceLstrip: {
      state = State::StatementBody;
      pos += config.statement_open_force_lstrip.size();
      return make_token(Token::Kind::StatementOpen);
    }
    case State::CommentStart: {
      state = State::CommentBody;
      pos += config.comment_open.size();
      return make_token(Token::Kind::CommentOpen);
    }
    case State::ExpressionBody:
      return scan_body(config.expression_close, Token::Kind::ExpressionClose, config.expression_close_force_rstrip);
    case State::LineBody:
      return scan_body("\n", Token::Kind::LineStatementClose);
    case State::StatementBody:
      return scan_body(config.statement_close, Token::Kind::StatementClose, config.statement_close_force_rstrip, config.trim_blocks);
    case State::CommentBody: {
      // fast-scan to comment close
      size_t end = m_in.substr(pos).find(config.comment_close);
      if (end == nonstd::string_view::npos) {
        pos = m_in.size();
        return make_token(Token::Kind::Eof);
      }
      // return the entire comment in the close token
      state = State::Text;
      pos += end + config.comment_close.size();
      Token tok = make_token(Token::Kind::CommentClose);
      if (config.trim_blocks) {
        skip_whitespaces_and_first_newline();
      }
      return tok;
    }
    }
  }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x240, %rsp            # imm = 0x240
movq %rdi, -0x218(%rbp)
movq %rdi, -0x210(%rbp)
movq %rsi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x208(%rbp)
movq 0x28(%rax), %rcx
movq %rcx, 0x20(%rax)
movq -0x208(%rbp), %rdi
movq 0x20(%rdi), %rax
movq %rax, -0x220(%rbp)
addq $0x10, %rdi
callq 0x332e0
movq %rax, %rcx
movq -0x220(%rbp), %rax
cmpq %rcx, %rax
jb 0x36a47
movq -0x208(%rbp), %rsi
movq -0x218(%rbp), %rdi
movl $0x22, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movl 0x8(%rax), %eax
movq %rax, -0x228(%rbp)
subq $0xb, %rax
ja 0x36a75
movq -0x228(%rbp), %rax
leaq 0x89750(%rip), %rcx     # 0xc01bc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x36a77
movq -0x208(%rbp), %rax
movq %rax, %rdi
addq $0x10, %rdi
movq 0x28(%rax), %rsi
movq $-0x1, %rdx
callq 0x36790
movq %rax, %rcx
movq -0x208(%rbp), %rax
movq %rcx, -0x20(%rbp)
movq %rdx, -0x18(%rbp)
movq (%rax), %rdi
addq $0x180, %rdi            # imm = 0x180
callq 0xb610
movq %rax, -0x30(%rbp)
movq %rdx, -0x28(%rbp)
movq -0x30(%rbp), %rsi
movq -0x28(%rbp), %rdx
leaq -0x20(%rbp), %rdi
xorl %eax, %eax
movl %eax, %ecx
callq 0x374a0
movq %rax, -0x10(%rbp)
cmpq $-0x1, -0x10(%rbp)
jne 0x36b0c
movq -0x208(%rbp), %rdi
addq $0x10, %rdi
callq 0x332e0
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
movq %rax, 0x28(%rsi)
xorl %edx, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movq -0x10(%rbp), %rcx
addq 0x28(%rax), %rcx
movq %rcx, 0x28(%rax)
movq %rax, %rdi
addq $0x10, %rdi
movq 0x28(%rax), %rsi
movq $-0x1, %rdx
callq 0x36790
movq %rax, %rcx
movq -0x208(%rbp), %rax
movq %rcx, -0x40(%rbp)
movq %rdx, -0x38(%rbp)
movb $0x0, -0x41(%rbp)
movq -0x40(%rbp), %rcx
movq %rcx, -0x58(%rbp)
movq -0x38(%rbp), %rcx
movq %rcx, -0x50(%rbp)
movq (%rax), %rdi
addq $0xc0, %rdi
callq 0xb610
movq %rax, -0x68(%rbp)
movq %rdx, -0x60(%rbp)
movq -0x58(%rbp), %rdi
movq -0x50(%rbp), %rsi
movq -0x68(%rbp), %rdx
movq -0x60(%rbp), %rcx
callq 0x36700
testb $0x1, %al
jne 0x36b8e
jmp 0x36c04
movq -0x208(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, -0x78(%rbp)
movq -0x38(%rbp), %rcx
movq %rcx, -0x70(%rbp)
movq (%rax), %rdi
addq $0xe0, %rdi
callq 0xb610
movq %rax, -0x88(%rbp)
movq %rdx, -0x80(%rbp)
movq -0x78(%rbp), %rdi
movq -0x70(%rbp), %rsi
movq -0x88(%rbp), %rdx
movq -0x80(%rbp), %rcx
callq 0x36700
testb $0x1, %al
jne 0x36bdd
jmp 0x36bf1
movq -0x208(%rbp), %rax
movl $0x2, 0x8(%rax)
movb $0x1, -0x41(%rbp)
jmp 0x36bff
movq -0x208(%rbp), %rax
movl $0x1, 0x8(%rax)
jmp 0x36ea9
movq -0x208(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, -0x98(%rbp)
movq -0x38(%rbp), %rcx
movq %rcx, -0x90(%rbp)
movq (%rax), %rdi
callq 0xb610
movq %rax, -0xa8(%rbp)
movq %rdx, -0xa0(%rbp)
movq -0x98(%rbp), %rdi
movq -0x90(%rbp), %rsi
movq -0xa8(%rbp), %rdx
movq -0xa0(%rbp), %rcx
callq 0x36700
testb $0x1, %al
jne 0x36c61
jmp 0x36d67
movq -0x208(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, -0xb8(%rbp)
movq -0x38(%rbp), %rcx
movq %rcx, -0xb0(%rbp)
movq (%rax), %rdi
addq $0x20, %rdi
callq 0xb610
movq %rax, -0xc8(%rbp)
movq %rdx, -0xc0(%rbp)
movq -0xb8(%rbp), %rdi
movq -0xb0(%rbp), %rsi
movq -0xc8(%rbp), %rdx
movq -0xc0(%rbp), %rcx
callq 0x36700
testb $0x1, %al
jne 0x36cbf
jmp 0x36cd2
movq -0x208(%rbp), %rax
movl $0x7, 0x8(%rax)
jmp 0x36d62
movq -0x208(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, -0xd8(%rbp)
movq -0x38(%rbp), %rcx
movq %rcx, -0xd0(%rbp)
movq (%rax), %rdi
addq $0x40, %rdi
callq 0xb610
movq %rax, -0xe8(%rbp)
movq %rdx, -0xe0(%rbp)
movq -0xd8(%rbp), %rdi
movq -0xd0(%rbp), %rsi
movq -0xe8(%rbp), %rdx
movq -0xe0(%rbp), %rcx
callq 0x36700
testb $0x1, %al
jne 0x36d30
jmp 0x36d44
movq -0x208(%rbp), %rax
movl $0x8, 0x8(%rax)
movb $0x1, -0x41(%rbp)
jmp 0x36d60
movq -0x208(%rbp), %rax
movl $0x6, 0x8(%rax)
movq (%rax), %rax
movb 0x1a1(%rax), %al
andb $0x1, %al
movb %al, -0x41(%rbp)
jmp 0x36d62
jmp 0x36ea7
movq -0x208(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, -0xf8(%rbp)
movq -0x38(%rbp), %rcx
movq %rcx, -0xf0(%rbp)
movq (%rax), %rdi
addq $0x140, %rdi            # imm = 0x140
callq 0xb610
movq %rax, -0x108(%rbp)
movq %rdx, -0x100(%rbp)
movq -0xf8(%rbp), %rdi
movq -0xf0(%rbp), %rsi
movq -0x108(%rbp), %rdx
movq -0x100(%rbp), %rcx
callq 0x36700
testb $0x1, %al
jne 0x36dc8
jmp 0x36de9
movq -0x208(%rbp), %rax
movl $0xa, 0x8(%rax)
movq (%rax), %rax
movb 0x1a1(%rax), %al
andb $0x1, %al
movb %al, -0x41(%rbp)
jmp 0x36ea5
movq -0x208(%rbp), %rax
cmpq $0x0, 0x28(%rax)
je 0x36e1a
movq -0x208(%rbp), %rax
movq %rax, %rdi
addq $0x10, %rdi
movq 0x28(%rax), %rsi
subq $0x1, %rsi
callq 0x374e0
movsbl (%rax), %eax
cmpl $0xa, %eax
jne 0x36e8b
movq -0x208(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, -0x118(%rbp)
movq -0x38(%rbp), %rcx
movq %rcx, -0x110(%rbp)
movq (%rax), %rdi
addq $0xa0, %rdi
callq 0xb610
movq %rax, -0x128(%rbp)
movq %rdx, -0x120(%rbp)
movq -0x118(%rbp), %rdi
movq -0x110(%rbp), %rsi
movq -0x128(%rbp), %rdx
movq -0x120(%rbp), %rcx
callq 0x36700
testb $0x1, %al
jne 0x36e7b
jmp 0x36e8b
movq -0x208(%rbp), %rax
movl $0x4, 0x8(%rax)
jmp 0x36ea3
movq -0x208(%rbp), %rax
movq 0x28(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x28(%rax)
jmp 0x36a00
jmp 0x36ea5
jmp 0x36ea7
jmp 0x36ea9
movq -0x208(%rbp), %rax
movq 0x10(%rax), %rcx
movq %rcx, -0x148(%rbp)
movq 0x18(%rax), %rcx
movq %rcx, -0x140(%rbp)
movq 0x20(%rax), %rdx
movq 0x28(%rax), %rcx
movq -0x148(%rbp), %rdi
movq -0x140(%rbp), %rsi
callq 0x37510
movq %rax, -0x138(%rbp)
movq %rdx, -0x130(%rbp)
testb $0x1, -0x41(%rbp)
je 0x36f4e
movq -0x138(%rbp), %rax
movq %rax, -0x168(%rbp)
movq -0x130(%rbp), %rax
movq %rax, -0x160(%rbp)
movq -0x168(%rbp), %rdi
movq -0x160(%rbp), %rsi
callq 0x375b0
movq %rax, -0x158(%rbp)
movq %rdx, -0x150(%rbp)
movq -0x158(%rbp), %rax
movq %rax, -0x138(%rbp)
movq -0x150(%rbp), %rax
movq %rax, -0x130(%rbp)
leaq -0x138(%rbp), %rdi
callq 0x37660
testb $0x1, %al
jne 0x36f60
jmp 0x36f65
jmp 0x36a00
movq -0x218(%rbp), %rdi
movq -0x138(%rbp), %rax
movq %rax, -0x178(%rbp)
movq -0x130(%rbp), %rax
movq %rax, -0x170(%rbp)
movq -0x178(%rbp), %rdx
movq -0x170(%rbp), %rcx
xorl %esi, %esi
callq 0x37680
jmp 0x3741c
movq -0x208(%rbp), %rax
movl $0x3, 0x8(%rax)
movq (%rax), %rdi
addq $0xc0, %rdi
callq 0xb440
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
addq 0x28(%rsi), %rax
movq %rax, 0x28(%rsi)
movl $0x1, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movl $0x3, 0x8(%rax)
movq (%rax), %rdi
addq $0xe0, %rdi
callq 0xb440
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
addq 0x28(%rsi), %rax
movq %rax, 0x28(%rsi)
movl $0x1, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movl $0x5, 0x8(%rax)
movq (%rax), %rdi
addq $0xa0, %rdi
callq 0xb440
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
addq 0x28(%rsi), %rax
movq %rax, 0x28(%rsi)
movl $0x3, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movl $0x9, 0x8(%rax)
movq (%rax), %rdi
callq 0xb440
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
addq 0x28(%rsi), %rax
movq %rax, 0x28(%rsi)
movl $0x5, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movl $0x9, 0x8(%rax)
movq (%rax), %rdi
addq $0x20, %rdi
callq 0xb440
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
addq 0x28(%rsi), %rax
movq %rax, 0x28(%rsi)
movl $0x5, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movl $0x9, 0x8(%rax)
movq (%rax), %rdi
addq $0x40, %rdi
callq 0xb440
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
addq 0x28(%rsi), %rax
movq %rax, 0x28(%rsi)
movl $0x5, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movl $0xb, 0x8(%rax)
movq (%rax), %rdi
addq $0x140, %rdi            # imm = 0x140
callq 0xb440
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
addq 0x28(%rsi), %rax
movq %rax, 0x28(%rsi)
movl $0x7, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movq (%rax), %rdi
addq $0x100, %rdi            # imm = 0x100
callq 0xb610
movq %rax, %rcx
movq -0x208(%rbp), %rax
movq %rcx, -0x188(%rbp)
movq %rdx, -0x180(%rbp)
movq (%rax), %rdi
addq $0x120, %rdi            # imm = 0x120
callq 0xb610
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
movq %rax, -0x198(%rbp)
movq %rdx, -0x190(%rbp)
movq -0x188(%rbp), %rdx
movq -0x180(%rbp), %rcx
movl $0x2, %r8d
leaq -0x198(%rbp), %rax
xorl %r9d, %r9d
movq (%rax), %r10
movq %r10, (%rsp)
movq 0x8(%rax), %rax
movq %rax, 0x8(%rsp)
callq 0x376b0
jmp 0x3741c
leaq -0x1a8(%rbp), %rdi
leaq 0x8b3fc(%rip), %rsi     # 0xc25fe
callq 0x31e20
leaq -0x1b8(%rbp), %rdi
callq 0x2f130
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
movq -0x1a8(%rbp), %rdx
movq -0x1a0(%rbp), %rcx
movl $0x4, %r8d
leaq -0x1b8(%rbp), %rax
xorl %r9d, %r9d
movq (%rax), %r10
movq %r10, (%rsp)
movq 0x8(%rax), %rax
movq %rax, 0x8(%rsp)
callq 0x376b0
jmp 0x3741c
movq -0x208(%rbp), %rax
movq (%rax), %rdi
addq $0x60, %rdi
callq 0xb610
movq %rax, %rcx
movq -0x208(%rbp), %rax
movq %rcx, -0x1c8(%rbp)
movq %rdx, -0x1c0(%rbp)
movq (%rax), %rdi
addq $0x80, %rdi
callq 0xb610
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
movq %rax, -0x1d8(%rbp)
movq %rdx, -0x1d0(%rbp)
movq (%rsi), %rax
movb 0x1a0(%rax), %al
movq -0x1c8(%rbp), %rdx
movq -0x1c0(%rbp), %rcx
movl $0x6, %r8d
leaq -0x1d8(%rbp), %r9
andb $0x1, %al
movq (%r9), %r10
movq %r10, (%rsp)
movq 0x8(%r9), %r9
movq %r9, 0x8(%rsp)
movzbl %al, %r9d
callq 0x376b0
jmp 0x3741c
movq -0x208(%rbp), %rax
movq %rax, %rdi
addq $0x10, %rdi
movq 0x28(%rax), %rsi
movq $-0x1, %rdx
callq 0x36790
movq %rax, %rcx
movq -0x208(%rbp), %rax
movq %rcx, -0x1f0(%rbp)
movq %rdx, -0x1e8(%rbp)
movq (%rax), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0xb610
movq %rax, -0x200(%rbp)
movq %rdx, -0x1f8(%rbp)
movq -0x200(%rbp), %rsi
movq -0x1f8(%rbp), %rdx
leaq -0x1f0(%rbp), %rdi
xorl %eax, %eax
movl %eax, %ecx
callq 0x37da0
movq %rax, -0x1e0(%rbp)
cmpq $-0x1, -0x1e0(%rbp)
jne 0x373a3
movq -0x208(%rbp), %rdi
addq $0x10, %rdi
callq 0x332e0
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
movq %rax, 0x28(%rsi)
movl $0x22, %edx
callq 0x37430
jmp 0x3741c
movq -0x208(%rbp), %rax
movl $0x0, 0x8(%rax)
movq -0x1e0(%rbp), %rcx
movq %rcx, -0x230(%rbp)
movq (%rax), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0xb440
movq -0x218(%rbp), %rdi
movq -0x208(%rbp), %rsi
movq %rax, %rcx
movq -0x230(%rbp), %rax
addq %rcx, %rax
addq 0x28(%rsi), %rax
movq %rax, 0x28(%rsi)
movl $0x8, %edx
callq 0x37430
movq -0x208(%rbp), %rax
movq (%rax), %rax
testb $0x1, 0x1a0(%rax)
je 0x3741a
movq -0x208(%rbp), %rdi
callq 0x37de0
jmp 0x3741c
movq -0x210(%rbp), %rax
addq $0x240, %rsp            # imm = 0x240
popq %rbp
retq
nopl (%rax)