// File: AutomataLab[P]JSONSki/src/JSONPathParser.cpp
// Function: JSONPathParser::updateQueryAutomaton(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, QueryAutomaton&)
void JSONPathParser::updateQueryAutomaton(string query, QueryAutomaton &qa) {
    int length = query.size();
    int lexer_state = 0;
    int query_state = START_STATE;
    char buffer[MAX_KEY_LENGTH];
    for (int i = 0; i < length; ++i) {
        char ch = query[i];
        switch (lexer_state) {
            case 0: { // begin of the path
                if (ch == '.') {
                    lexer_state = 1;
                } else if (ch == '[') {
                    lexer_state = 2;
                    qa.updateStateTransInfo(query_state, false, NONE, ARRAY, NULL, query_state + 1);
                    // cout<<"("<<query_state<<", false, NONE, ARRAY, NULL, "<<(query_state + 1)<<")"<<endl;
                    ++query_state;
                }
                break;
            }
            case 1: { // in object
                int key_end = 0;
                while (ch != '.' && ch != '[') {
                    buffer[key_end++] = ch;
                    if (i + 1 == length) break;
                    ch = query[++i];
                }
                buffer[key_end] = '\0';
                if (i + 1 < length) {
                    if (ch == '[') {
                        lexer_state = 2;
                        // current query state -> expected key-array pair
                        qa.updateStateTransInfo(query_state, false, ARRAY, NONE, buffer, query_state + 1);
                        // cout<<"("<<query_state<<", false, ARRAY, NONE, "<<buffer<<", "<<(query_state + 1)<<")"<<endl;
                        // state transition for [
                        qa.updateStateTransInfo(query_state + 1, false, NONE, NONE, NULL, query_state + 2);
                        // cout<<"("<<(query_state + 1)<<", false, NONE, NONE, NULL, "<<(query_state + 2)<<")"<<endl;
                        query_state += 2;
                        // break;
                    } else if (ch == '.') {
                        lexer_state = 1;
                        qa.updateStateTransInfo(query_state, false, OBJECT, NONE, buffer, query_state + 1);
                        // cout<<"("<<query_state<<", false, OBJECT, NONE, "<<buffer<<", "<<(query_state + 1)<<")"<<endl;
                        ++query_state;
                        // break;
                    } 
                } else {
                    // output info
                    qa.updateStateTransInfo(query_state, false, PRIMITIVE, NONE, buffer, query_state + 1);
                    // cout<<"("<<query_state<<", false, PRIMITIVE, NONE, "<<buffer<<", "<<(query_state + 1)<<")"<<endl;
                    qa.updateStateTransInfo(query_state + 1, true, NONE, NONE, NULL, query_state + 1);
                    // cout<<"("<<(query_state + 1)<<", true, NONE, NONE, NULL, "<<(query_state + 1)<<")"<<endl;
                }
                break;
            }
            case 2: { // in array
                int start_idx = 0;
                int end_idx = -1;
                int index_end = 0;
                bool has_colon = false;
                while (ch != ']') {
                    if (ch == ':') {
                        buffer[index_end] = '\0';
                        start_idx = atoi(buffer);
                        end_idx = INT_MAX;
                        index_end = 0;
                        has_colon = true;
                    }
                    else if (ch >= '0' && ch <= '9') {
                        buffer[index_end++] = ch;
                    }
                    if (i + 1 == length) break;
                    ch = query[++i];
                }
                if (has_colon == false && index_end > 0) {
                    buffer[index_end] = '\0';
                    start_idx = atoi(buffer);
                    end_idx = start_idx + 1;
                } else if (index_end > 0) {
                    buffer[index_end] = '\0';
                    end_idx = atoi(buffer);
                }
                if (end_idx > -1) {
                    qa.addIndexConstraints(query_state, start_idx, end_idx);
                    // cout<<"index constraints "<<start_idx<<" "<<end_idx<<" current state "<<query_state<<endl;
                }
                if (i + 1 < length) {
                    ch = query[++i];
                    if (ch == '.') {
                        lexer_state = 1;
                        qa.updateStateTransInfo(query_state, false, NONE, OBJECT, NULL, query_state + 1);
                        // cout<<"("<<query_state<<", false, NONE, OBJECT, NULL, "<<(query_state + 1)<<")"<<endl;
                    } else if (ch == '[') {
                        cout<<"additional ["<<endl;
                        lexer_state = 2;
                        qa.updateStateTransInfo(query_state, false, NONE, ARRAY, NULL, query_state + 1);
                        // cout<<"("<<query_state<<", false, NONE, ARRAY, NULL, "<<(query_state + 1)<<")"<<endl;
                        ++query_state;
                    }
                } else {
                    qa.updateStateTransInfo(query_state, true, NONE, PRIMITIVE, NULL, query_state);
                    // cout<<"("<<query_state<<", false, NONE, PRIMITIVE, NULL, "<<(query_state + 1)<<")"<<endl;
                }
                break;
            }
        }
    }
}

// Assembly:
subq $0xc8, %rsp
movq %rdi, 0x18(%rsp)
movq %rdi, 0xc0(%rsp)
movq %rsi, 0xb8(%rsp)
callq 0xd30f0
movl %eax, 0xb4(%rsp)
movl $0x0, 0xb0(%rsp)
movl $0x1, 0xac(%rsp)
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0xb4(%rsp), %eax
jge 0x168da
movq 0x18(%rsp), %rdi
movslq 0x3c(%rsp), %rsi
callq 0xd3410
movb (%rax), %al
movb %al, 0x3b(%rsp)
movl 0xb0(%rsp), %eax
movl %eax, 0x14(%rsp)
testl %eax, %eax
je 0x163ee
jmp 0x163cd
movl 0x14(%rsp), %eax
subl $0x1, %eax
je 0x16463
jmp 0x163dc
movl 0x14(%rsp), %eax
subl $0x2, %eax
je 0x1665a
jmp 0x168c8
movsbl 0x3b(%rsp), %eax
cmpl $0x2e, %eax
jne 0x16405
movl $0x1, 0xb0(%rsp)
jmp 0x1645e
movsbl 0x3b(%rsp), %eax
cmpl $0x5b, %eax
jne 0x1645c
movl $0x2, 0xb0(%rsp)
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
movl 0xac(%rsp), %eax
addl $0x1, %eax
xorl %edx, %edx
movl $0x6c, %ecx
movl $0x66, %r8d
xorl %r9d, %r9d
movl %eax, (%rsp)
callq 0x168f0
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x1645e
jmp 0x168c8
movl $0x0, 0x34(%rsp)
movsbl 0x3b(%rsp), %ecx
xorl %eax, %eax
cmpl $0x2e, %ecx
movb %al, 0x13(%rsp)
je 0x1648a
movsbl 0x3b(%rsp), %eax
cmpl $0x5b, %eax
setne %al
movb %al, 0x13(%rsp)
movb 0x13(%rsp), %al
testb $0x1, %al
jne 0x16494
jmp 0x164dd
movb 0x3b(%rsp), %cl
movl 0x34(%rsp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x34(%rsp)
cltq
movb %cl, 0x40(%rsp,%rax)
movl 0x3c(%rsp), %eax
addl $0x1, %eax
cmpl 0xb4(%rsp), %eax
jne 0x164bd
jmp 0x164dd
movq 0x18(%rsp), %rdi
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
movslq %eax, %rsi
callq 0xd3410
movb (%rax), %al
movb %al, 0x3b(%rsp)
jmp 0x1646b
movslq 0x34(%rsp), %rax
movb $0x0, 0x40(%rsp,%rax)
movl 0x3c(%rsp), %eax
addl $0x1, %eax
cmpl 0xb4(%rsp), %eax
jge 0x165eb
movsbl 0x3b(%rsp), %eax
cmpl $0x5b, %eax
jne 0x1658e
movl $0x2, 0xb0(%rsp)
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
leaq 0x40(%rsp), %r9
movl 0xac(%rsp), %eax
addl $0x1, %eax
xorl %edx, %edx
movl $0x66, %ecx
movl $0x6c, %r8d
movl %eax, (%rsp)
callq 0x168f0
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
addl $0x1, %esi
movl 0xac(%rsp), %eax
addl $0x2, %eax
xorl %edx, %edx
movl $0x6c, %r8d
xorl %ecx, %ecx
movl %ecx, %r9d
movl %r8d, %ecx
movl %eax, (%rsp)
callq 0x168f0
movl 0xac(%rsp), %eax
addl $0x2, %eax
movl %eax, 0xac(%rsp)
jmp 0x165e9
movsbl 0x3b(%rsp), %eax
cmpl $0x2e, %eax
jne 0x165e7
movl $0x1, 0xb0(%rsp)
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
leaq 0x40(%rsp), %r9
movl 0xac(%rsp), %eax
addl $0x1, %eax
xorl %edx, %edx
movl $0x65, %ecx
movl $0x6c, %r8d
movl %eax, (%rsp)
callq 0x168f0
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x165e9
jmp 0x16655
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
leaq 0x40(%rsp), %r9
movl 0xac(%rsp), %eax
addl $0x1, %eax
xorl %edx, %edx
movl $0x67, %ecx
movl $0x6c, %r8d
movl %eax, (%rsp)
callq 0x168f0
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
addl $0x1, %esi
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl $0x1, %edx
movl $0x6c, %r8d
xorl %ecx, %ecx
movl %ecx, %r9d
movl %r8d, %ecx
movl %eax, (%rsp)
callq 0x168f0
jmp 0x168c8
movl $0x0, 0x30(%rsp)
movl $0xffffffff, 0x2c(%rsp) # imm = 0xFFFFFFFF
movl $0x0, 0x28(%rsp)
movb $0x0, 0x27(%rsp)
movsbl 0x3b(%rsp), %eax
cmpl $0x5d, %eax
je 0x16720
movsbl 0x3b(%rsp), %eax
cmpl $0x3a, %eax
jne 0x166be
movslq 0x28(%rsp), %rax
movb $0x0, 0x40(%rsp,%rax)
leaq 0x40(%rsp), %rdi
callq 0x134b0
movl %eax, 0x30(%rsp)
movl $0x7fffffff, 0x2c(%rsp) # imm = 0x7FFFFFFF
movl $0x0, 0x28(%rsp)
movb $0x1, 0x27(%rsp)
jmp 0x166eb
movsbl 0x3b(%rsp), %eax
cmpl $0x30, %eax
jl 0x166e9
movsbl 0x3b(%rsp), %eax
cmpl $0x39, %eax
jg 0x166e9
movb 0x3b(%rsp), %cl
movl 0x28(%rsp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x28(%rsp)
cltq
movb %cl, 0x40(%rsp,%rax)
jmp 0x166eb
movl 0x3c(%rsp), %eax
addl $0x1, %eax
cmpl 0xb4(%rsp), %eax
jne 0x166fd
jmp 0x16720
movq 0x18(%rsp), %rdi
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
movslq %eax, %rsi
callq 0xd3410
movb (%rax), %al
movb %al, 0x3b(%rsp)
jmp 0x16677
movb 0x27(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x1675a
cmpl $0x0, 0x28(%rsp)
jle 0x1675a
movslq 0x28(%rsp), %rax
movb $0x0, 0x40(%rsp,%rax)
leaq 0x40(%rsp), %rdi
callq 0x134b0
movl %eax, 0x30(%rsp)
movl 0x30(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x1677b
cmpl $0x0, 0x28(%rsp)
jle 0x16779
movslq 0x28(%rsp), %rax
movb $0x0, 0x40(%rsp,%rax)
leaq 0x40(%rsp), %rdi
callq 0x134b0
movl %eax, 0x2c(%rsp)
jmp 0x1677b
cmpl $-0x1, 0x2c(%rsp)
jle 0x1679e
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
movl 0x30(%rsp), %edx
movl 0x2c(%rsp), %ecx
callq 0x16a60
movl 0x3c(%rsp), %eax
addl $0x1, %eax
cmpl 0xb4(%rsp), %eax
jge 0x16895
movq 0x18(%rsp), %rdi
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
movslq %eax, %rsi
callq 0xd3410
movb (%rax), %al
movb %al, 0x3b(%rsp)
movsbl 0x3b(%rsp), %eax
cmpl $0x2e, %eax
jne 0x16818
movl $0x1, 0xb0(%rsp)
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
movl 0xac(%rsp), %eax
addl $0x1, %eax
xorl %edx, %edx
movl $0x6c, %ecx
movl $0x65, %r8d
xorl %r9d, %r9d
movl %eax, (%rsp)
callq 0x168f0
jmp 0x16893
movsbl 0x3b(%rsp), %eax
cmpl $0x5b, %eax
jne 0x16891
leaq 0x127c57(%rip), %rdi    # 0x13e480
leaq 0xec7d4(%rip), %rsi     # 0x103004
callq 0xccb00
movq %rax, %rdi
leaq 0xb5ba1(%rip), %rsi     # 0xcc3e0
callq 0xcb5f0
movl $0x2, 0xb0(%rsp)
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
movl 0xac(%rsp), %eax
addl $0x1, %eax
xorl %edx, %edx
movl $0x6c, %ecx
movl $0x66, %r8d
xorl %r9d, %r9d
movl %eax, (%rsp)
callq 0x168f0
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x16893
jmp 0x168c6
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
movl 0xac(%rsp), %eax
movl $0x1, %edx
movl $0x6c, %ecx
movl $0x67, %r8d
xorl %r9d, %r9d
movl %eax, (%rsp)
callq 0x168f0
jmp 0x168c8
jmp 0x168ca
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x16396
addq $0xc8, %rsp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)