// File: /workspace/github_cpp_makefile_star2_O2/pfnet-research[P]pml/src/parser.cpp
// Function: next_token(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, unsigned long)
token_t next_token(std::string const& input, size_t pos) {
    using kind_t = token_t::kind_t;

    pos = skip_spaces(input, pos);

    if (pos >= input.size()) {
        return token_t {
            token_t::kind_t::Eof, pos, ""
        };
    }

    if (std::isdigit(input[pos]) || (input[pos] == '-' && std::isdigit(input[pos+1]))) {
        size_t len = 1;
        while (std::isdigit(input[pos + len]) && pos + len < input.size())
            ++len;
        return token_t {
            kind_t::Int, pos, input.substr(pos, len)
        };
    }

    std::unordered_map<std::string, kind_t> string_token = {
        {"->", kind_t::Arrow},
        {"=>", kind_t::FatArrow},
        {"==", kind_t::DoubleEq},
        {"!=", kind_t::Neq},
        {"<=", kind_t::Leq},
        {">=", kind_t::Geq},
        {"\\/", kind_t::Or},
        {"/\\", kind_t::And}
    };
    for (auto const& pair : string_token) {
        if (pair.first == input.substr(pos, pair.first.size()))
            return token_t {pair.second, pos, pair.first};
    }

    std::unordered_map<char, token_t::kind_t> char_token = {
        {'=', kind_t::Eq},
        {'+', kind_t::Plus},
        {'-', kind_t::Minus},
        {'*', kind_t::Star},
        {'/', kind_t::Slash},
        {',', kind_t::Comma},
        {'&', kind_t::Amp},
        {'\\', kind_t::BackSlash},
        {'|', kind_t::Bar},
        {':', kind_t::Colon},
        {'{', kind_t::LBrace},
        {'}', kind_t::RBrace},
        {'(', kind_t::LParen},
        {')', kind_t::RParen}
    };
    auto found_ch = char_token.find(input[pos]);
    if (found_ch != char_token.end()) {
        return token_t {
            found_ch->second, pos, std::string{found_ch->first}
        };
    }

    size_t len = ident_len(input, pos);
    if (len != 0) {
        std::unordered_map<std::string, token_t::kind_t> keywords = {
            {"let", kind_t::Let},
            {"letfun", kind_t::LetFun},
            {"in", kind_t::In},
            {"if", kind_t::If},
            {"else", kind_t::Else},
            {"then", kind_t::Then},
            {"rand", kind_t::Rand},
            {"true", kind_t::True},
            {"false", kind_t::False},
            {"Prob", kind_t::Prob},
            {"not", kind_t::Not},
            {"dummy", kind_t::Dummy}
        };
        std::string lexime = input.substr(pos, len);
        auto found_keyword = keywords.find(lexime);
        if (found_keyword != keywords.end()) {
            return token_t { found_keyword->second, pos, lexime };
        } else {
            return token_t { kind_t::Ident, pos,  lexime};
        }
    }

    throw std::runtime_error{"unknown token at " + std::to_string(pos) + " : " + input.substr(pos, 5) + ".."};
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x348, %rsp            # imm = 0x348
movq %rsi, %r15
movq %rdi, %rbx
movq %rsi, %rdi
movq %rdx, %rsi
callq 0x152f5
movq %rax, %r14
movq 0x8(%r15), %rax
cmpq %rax, %r14
jae 0x15400
movq (%r15), %rdx
movsbl (%rdx,%r14), %ecx
leal -0x30(%rcx), %esi
cmpl $0xa, %esi
jae 0x1542a
addq %r14, %rdx
pushq $0x1
popq %rsi
leaq (%r14,%rsi), %rdi
leaq 0x1(%rsi), %rcx
cmpq %rax, %rdi
jae 0x153dc
movsbl (%rdx,%rsi), %edi
addl $-0x30, %edi
movq %rcx, %rsi
cmpl $0xa, %edi
jb 0x153c0
movl $0x7, (%rbx)
movq %r14, 0x8(%rbx)
movq %rbx, %rdi
addq $0x10, %rdi
decq %rcx
movq %r15, %rsi
movq %r14, %rdx
callq 0x9310
jmp 0x1593a
movl $0x25, (%rbx)
movq %r14, 0x8(%rbx)
movq %rbx, %rdi
addq $0x10, %rdi
leaq 0x23081(%rip), %rsi     # 0x38499
leaq 0x130(%rsp), %rdx
callq 0xeb2e
jmp 0x1593a
cmpb $0x2d, %cl
jne 0x15441
movsbl 0x1(%rdx,%r14), %ecx
addl $-0x30, %ecx
cmpl $0x9, %ecx
jbe 0x153ba
leaq 0xf8(%rsp), %rdx
movl $0xb, (%rdx)
leaq 0x24190(%rip), %rsi     # 0x395e6
leaq 0x130(%rsp), %r12
movq %r12, %rdi
callq 0x1aab8
leaq 0x158(%rsp), %rbp
leaq 0x80(%rsp), %rdx
movl $0xc, (%rdx)
leaq 0x23d45(%rip), %rsi     # 0x391c8
movq %rbp, %rdi
callq 0x1aab8
leaq 0x180(%rsp), %rbp
leaq 0x60(%rsp), %rdx
movl $0x13, (%rdx)
leaq 0x24153(%rip), %rsi     # 0x395f8
movq %rbp, %rdi
callq 0x1aab8
leaq 0x1a8(%rsp), %rbp
leaq 0x40(%rsp), %rdx
movl $0x14, (%rdx)
leaq 0x23cfd(%rip), %rsi     # 0x391c4
movq %rbp, %rdi
callq 0x1aab8
leaq 0x1d0(%rsp), %rbp
leaq 0xd8(%rsp), %rdx
movl $0x16, (%rdx)
leaq 0x2333f(%rip), %rsi     # 0x3882b
movq %rbp, %rdi
callq 0x1aab8
leaq 0x1f8(%rsp), %rbp
leaq 0xb8(%rsp), %rdx
movl $0x17, (%rdx)
leaq 0x2331d(%rip), %rsi     # 0x3882e
movq %rbp, %rdi
callq 0x1aab8
leaq 0x220(%rsp), %rbp
leaq 0x30(%rsp), %rdx
movl $0x21, (%rdx)
leaq 0x240b6(%rip), %rsi     # 0x395e9
movq %rbp, %rdi
callq 0x1aab8
leaq 0x248(%rsp), %rbp
leaq 0x2c(%rsp), %rdx
movl $0x22, (%rdx)
leaq 0x24097(%rip), %rsi     # 0x395ec
movq %rbp, %rdi
callq 0x1aab8
movq %rbx, 0x18(%rsp)
leaq 0x270(%rsp), %rdx
leaq 0x20(%rsp), %rax
movq %rax, (%rsp)
leaq 0x310(%rsp), %rdi
leaq 0x130(%rsp), %rsi
leaq 0x28(%rsp), %r8
leaq 0x24(%rsp), %r9
movq %rdx, 0x10(%rsp)
xorl %ecx, %ecx
callq 0x1f1fe
movl $0x118, %ebx            # imm = 0x118
leaq (%rsp,%rbx), %rdi
addq $0x130, %rdi            # imm = 0x130
callq 0x9130
addq $-0x28, %rbx
cmpq $-0x28, %rbx
jne 0x1559e
leaq 0x320(%rsp), %rbx
leaq 0x130(%rsp), %r12
movq (%rbx), %rbx
testq %rbx, %rbx
je 0x15623
movq 0x10(%rbx), %rcx
movq %r12, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x9310
leaq 0x8(%rbx), %rbp
movq %rbp, %rdi
movq %r12, %rsi
callq 0xa5de
movl %eax, %r13d
movq %r12, %rdi
callq 0x9130
testb %r13b, %r13b
je 0x155c8
movl 0x28(%rbx), %eax
movq 0x18(%rsp), %rbx
movl %eax, (%rbx)
movq %r14, 0x8(%rbx)
movq %rbx, %rdi
addq $0x10, %rdi
movq %rbp, %rsi
callq 0x93a0
jmp 0x1592d
leaq 0x23f2a(%rip), %rsi     # 0x39554
pushq $0x1c
popq %rcx
leaq 0x130(%rsp), %rax
movq %rax, %rdi
rep  movsl (%rsi), %es:(%rdi)
leaq 0x1a0(%rsp), %rdx
leaq 0x40(%rsp), %rcx
movq %rcx, (%rsp)
leaq 0xf8(%rsp), %rdi
leaq 0x80(%rsp), %r8
leaq 0x60(%rsp), %r9
movq %rax, %rsi
xorl %ecx, %ecx
callq 0x1f712
movq (%r15), %rsi
addq %r14, %rsi
leaq 0xf8(%rsp), %rdi
callq 0x1fb1c
movq 0x18(%rsp), %rbx
testq %rax, %rax
je 0x156af
movl 0xc(%rax), %ecx
movl %ecx, (%rbx)
movq %r14, 0x8(%rbx)
movb 0x8(%rax), %al
leaq 0x20(%rbx), %rcx
movq %rcx, 0x10(%rbx)
movb %al, 0x20(%rbx)
movq $0x1, 0x18(%rbx)
movb $0x0, 0x21(%rbx)
jmp 0x15920
movq %r15, %rdi
movq %r14, %rsi
callq 0x15329
testq %rax, %rax
je 0x1594f
movq %rax, %r12
leaq 0x60(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x2700c(%rip), %rsi     # 0x3c6e1
leaq 0x130(%rsp), %r13
movq %r13, %rdi
callq 0x1aada
leaq 0x158(%rsp), %rbp
leaq 0x40(%rsp), %rdx
movl $0x1, (%rdx)
leaq 0x23ec5(%rip), %rsi     # 0x395c4
movq %rbp, %rdi
callq 0x1aafc
leaq 0x180(%rsp), %rbp
leaq 0xd8(%rsp), %rdx
movl $0x2, (%rdx)
leaq 0x23ea7(%rip), %rsi     # 0x395cb
movq %rbp, %rdi
callq 0x1aab8
leaq 0x1a8(%rsp), %rbp
leaq 0xb8(%rsp), %rdx
movl $0x3, (%rdx)
leaq 0x23e85(%rip), %rsi     # 0x395ce
movq %rbp, %rdi
callq 0x1aab8
leaq 0x1d0(%rsp), %rbp
leaq 0x30(%rsp), %rdx
movl $0x4, (%rdx)
leaq 0x23e6b(%rip), %rsi     # 0x395d6
movq %rbp, %rdi
callq 0x1ab1e
leaq 0x1f8(%rsp), %rbp
leaq 0x2c(%rsp), %rdx
movl $0x5, (%rdx)
leaq 0x23e44(%rip), %rsi     # 0x395d1
movq %rbp, %rdi
callq 0x1ab1e
leaq 0x220(%rsp), %rbp
leaq 0x28(%rsp), %rdx
movl $0x6, (%rdx)
leaq 0x26f42(%rip), %rsi     # 0x3c6f1
movq %rbp, %rdi
callq 0x1ab1e
leaq 0x248(%rsp), %rbp
leaq 0x24(%rsp), %rdx
movl $0x8, (%rdx)
leaq 0x28dba(%rip), %rsi     # 0x3e58b
movq %rbp, %rdi
callq 0x1ab1e
leaq 0x20(%rsp), %rdx
movl $0x9, (%rdx)
leaq 0x26cd4(%rip), %rsi     # 0x3c4bf
leaq 0x270(%rsp), %rdi
callq 0x1ab40
leaq 0x298(%rsp), %rbx
leaq 0x3c(%rsp), %rdx
movl $0x23, (%rdx)
leaq 0x23ddd(%rip), %rsi     # 0x395ef
movq %rbx, %rdi
callq 0x1ab1e
leaq 0x2c0(%rsp), %rbx
leaq 0x38(%rsp), %rdx
movl $0x24, (%rdx)
leaq 0x23dc0(%rip), %rsi     # 0x395f4
movq %rbx, %rdi
callq 0x1aada
leaq 0x2e8(%rsp), %rbx
leaq 0x34(%rsp), %rdx
movl $0x26, (%rdx)
leaq 0x23db4(%rip), %rsi     # 0x3960a
movq %rbx, %rdi
callq 0x1ab40
leaq 0x310(%rsp), %rdx
leaq 0xd(%rsp), %rax
movq %rax, (%rsp)
leaq 0x80(%rsp), %rdi
leaq 0x130(%rsp), %rsi
leaq 0xf(%rsp), %r8
leaq 0xe(%rsp), %r9
xorl %ecx, %ecx
callq 0x1f1fe
movl $0x1b8, %ebx            # imm = 0x1B8
leaq (%rsp,%rbx), %rdi
addq $0x130, %rdi            # imm = 0x130
callq 0x9130
addq $-0x28, %rbx
cmpq $-0x28, %rbx
jne 0x15895
leaq 0x130(%rsp), %rdi
movq %r15, %rsi
movq %r14, %rdx
movq %r12, %rcx
callq 0x9310
leaq 0x80(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x1fb3a
movq 0x18(%rsp), %rbx
testq %rax, %rax
je 0x158e9
movl 0x28(%rax), %eax
jmp 0x158ec
pushq $0xa
popq %rax
movl %eax, (%rbx)
movq %r14, 0x8(%rbx)
movq %rbx, %rdi
addq $0x10, %rdi
leaq 0x130(%rsp), %rsi
callq 0x93a0
leaq 0x130(%rsp), %rdi
callq 0x9130
leaq 0x80(%rsp), %rdi
callq 0x1b2de
leaq 0xf8(%rsp), %rdi
callq 0x1b438
leaq 0x310(%rsp), %rdi
callq 0x1b2de
movq %rbx, %rax
addq $0x348, %rsp            # imm = 0x348
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x10
popq %rdi
callq 0x9150
movq %rax, %r12
leaq 0xd8(%rsp), %rdi
movq %r14, %rsi
callq 0x1ab62
leaq 0x23c9f(%rip), %rsi     # 0x39610
leaq 0x40(%rsp), %rdi
leaq 0xd8(%rsp), %rdx
callq 0xb97b
leaq 0x235be(%rip), %rdx     # 0x38f48
leaq 0x60(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0xeb69
leaq 0xb8(%rsp), %rdi
pushq $0x5
popq %rcx
movq %r15, %rsi
movq %r14, %rdx
callq 0x9310
leaq 0x80(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0xb8(%rsp), %rdx
callq 0xeb88
leaq 0x239f1(%rip), %rdx     # 0x393c1
leaq 0x130(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0xeb69
movb $0x1, %bpl
leaq 0x130(%rsp), %rsi
movq %r12, %rdi
callq 0x9480
xorl %ebp, %ebp
movq 0x465ef(%rip), %rsi     # 0x5bff0
movq 0x46588(%rip), %rdx     # 0x5bf90
movq %r12, %rdi
callq 0x94b0
movq %rax, %rbx
leaq 0x130(%rsp), %rdi
callq 0x9130
jmp 0x15a28
movq %rax, %rbx
movb $0x1, %bpl
leaq 0x80(%rsp), %rdi
callq 0x9130
jmp 0x15a3d
movq %rax, %rbx
movb $0x1, %bpl
leaq 0xb8(%rsp), %rdi
callq 0x9130
jmp 0x15a52
movq %rax, %rbx
movb $0x1, %bpl
leaq 0x60(%rsp), %rdi
callq 0x9130
jmp 0x15a64
movq %rax, %rbx
movb $0x1, %bpl
leaq 0x40(%rsp), %rdi
callq 0x9130
jmp 0x15a76
movq %rax, %rbx
movb $0x1, %bpl
leaq 0xd8(%rsp), %rdi
callq 0x9130
testb %bpl, %bpl
jne 0x15a90
jmp 0x15b40
movq %rax, %rbx
movq %r12, %rdi
callq 0x9210
jmp 0x15b40
movq %rax, %rbx
jmp 0x15b2c
movq %rbx, 0x10(%rsp)
movq %rax, %rbx
movl $0x1b8, %r14d           # imm = 0x1B8
leaq (%rsp,%r14), %rdi
addq $0x130, %rdi            # imm = 0x130
callq 0x9130
addq $-0x28, %r14
cmpq $-0x28, %r14
jne 0x15ab3
movb $0x1, %al
jmp 0x15ae1
jmp 0x15ad5
jmp 0x15ad5
movq %rbx, 0x10(%rsp)
jmp 0x15adc
movq %rax, %rbx
xorl %eax, %eax
movq 0x10(%rsp), %rbp
jmp 0x15af9
jmp 0x15af4
jmp 0x15af4
jmp 0x15af4
jmp 0x15af4
jmp 0x15af4
jmp 0x15af4
movq %rax, %rbx
xorl %eax, %eax
cmpq %rbp, %r13
sete %cl
testb %al, %al
jne 0x15b40
testb %cl, %cl
jne 0x15b40
addq $-0x28, %rbp
movq %rbp, %rdi
callq 0x9130
cmpq %r13, %rbp
jne 0x15b07
jmp 0x15b40
jmp 0x15b3d
movq %rax, %rbx
leaq 0x130(%rsp), %rdi
callq 0x9130
leaq 0x80(%rsp), %rdi
callq 0x1b2de
jmp 0x15b40
jmp 0x15baf
movq %rax, %rbx
leaq 0xf8(%rsp), %rdi
callq 0x1b438
jmp 0x15bb2
jmp 0x15baf
movq %rax, %rbx
movl $0x118, %r14d           # imm = 0x118
leaq (%rsp,%r14), %rdi
addq $0x130, %rdi            # imm = 0x130
callq 0x9130
addq $-0x28, %r14
cmpq $-0x28, %r14
jne 0x15b5a
movb $0x1, %al
jmp 0x15b89
jmp 0x15b84
jmp 0x15b84
jmp 0x15b84
jmp 0x15b84
jmp 0x15b84
jmp 0x15b84
movq %rax, %rbx
xorl %eax, %eax
cmpq %rbp, %r12
sete %cl
testb %al, %al
jne 0x15bbf
testb %cl, %cl
jne 0x15bbf
addq $-0x28, %rbp
movq %rbp, %rdi
callq 0x9130
cmpq %r12, %rbp
jne 0x15b97
jmp 0x15bbf
movq %rax, %rbx
jmp 0x15bbf
movq %rax, %rbx
leaq 0x310(%rsp), %rdi
callq 0x1b2de
movq %rbx, %rdi
callq 0x94d0