// File: /workspace/github_cpp_makefile_star2_O2/kiven-li[P]xbytes/xbytes.cpp
// Function: xbytes::xbytes::find_follow_set()
void xbytes::find_follow_set()
{
	for(int i = 0; i < symbols.size(); ++i)
	{
		if(symbols[i]->type == ST_TERMINAL)
		{
			symbols[i]->follow_set.push_back(symbols[i]);
		}
	}

	while(true)
	{
		int change_count = 0;
		for(int x = 0; x < rules.size(); ++x)
		{
			rule* r = rules[x];
			int k = r->rights.size();
			if(k == 0) continue;

			for(int i = 0; i < k; ++i)
			{
				symbol* s = r->rights[i];
				if(s->type == ST_TERMINAL) 
				{
					//终结符前面是非终结符，则加入到前面的FOLLOW中
					if(i > 0 && r->rights[i-1]->type == ST_NONTERMINAL)
					{
						change_count += merge_symbol_set(r->rights[i-1]->follow_set, s->follow_set);
					}						
					continue;
				}

				//两个相邻的非终结符，后一个的FIRST是前一个的FOLLOW
				if(i > 0 && r->rights[i-1]->type == ST_NONTERMINAL)
				{
					change_count += merge_symbol_set(r->rights[i-1]->follow_set, s->first_set);
				}

				//if Yi+1 ... Yk 都可为空的 then
				//FOLLOW[Yi] = FOLLOW[Yi] U FOLLOW[X]
				bool is_all_follow_nullable = true;
				for(int j = i + 1; j < k; ++j)
				{
					if(!r->rights[j]->is_nullable)
					{
						is_all_follow_nullable = false;
						break;
					}
				}
				if(is_all_follow_nullable)
				{
					change_count += merge_symbol_set(s->follow_set, r->left->follow_set);
				}

				//if Yi+1 .. Yj-1 都可为空的 then
				//FOLLOW[Yi] = FOLLOW[Yi] U FIRST[Yj]
				for(int j = i + 1; j < k; ++j)
				{
					if(i+1 > j-1) continue;
					if(!r->rights[j-1]->is_nullable) break;
					change_count += merge_symbol_set(s->follow_set, r->rights[j]->first_set);
				}
			}
		}

		if(!change_count) break;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdi, %r15
xorl %ebx, %ebx
xorl %r14d, %r14d
movq 0x8(%r15), %rsi
movq 0x10(%r15), %rax
subq %rsi, %rax
sarq $0x3, %rax
cmpq %r14, %rax
jbe 0x3a39
movq (%rsi,%rbx), %rdi
cmpl $0x1, 0x48(%rdi)
jne 0x3a30
addq %rbx, %rsi
addq $0x88, %rdi
callq 0x7050
incq %r14
addq $0x8, %rbx
jmp 0x3a03
xorl %edx, %edx
xorl %edi, %edi
movq %r15, -0x50(%rbp)
movq 0x20(%r15), %rax
movq 0x28(%r15), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %rdx, %rcx
jbe 0x3bcd
movq (%rax,%rdx,8), %rbx
movq 0x38(%rbx), %rcx
subq 0x30(%rbx), %rcx
shrq $0x3, %rcx
testl %ecx, %ecx
je 0x3be6
movq %rdx, -0x58(%rbp)
movslq %ecx, %r14
movl $0x0, %r12d
cmovgl %ecx, %r12d
xorl %r13d, %r13d
pushq $0x1
popq %rax
movq %rax, -0x40(%rbp)
movq %rcx, %r15
movq %r14, -0x48(%rbp)
movq %r12, -0x38(%rbp)
cmpq %r12, %r13
je 0x3bde
movq 0x30(%rbx), %rax
movq (%rax,%r13,8), %r8
cmpl $0x1, 0x48(%r8)
jne 0x3aeb
testq %r13, %r13
je 0x3bc1
movq -0x8(%rax,%r13,8), %rsi
cmpl $0x2, 0x48(%rsi)
jne 0x3bc1
movl $0x88, %eax
addq %rax, %rsi
addq %rax, %r8
movq %r8, %rdx
movl %edi, %r14d
callq 0x4ac6
movl %r14d, %edi
movq -0x48(%rbp), %r14
addl %eax, %edi
jmp 0x3bc1
testq %r13, %r13
je 0x3b19
movq -0x8(%rax,%r13,8), %rsi
cmpl $0x2, 0x48(%rsi)
jne 0x3b19
addq $0x88, %rsi
leaq 0x70(%r8), %rdx
movl %edi, -0x2c(%rbp)
movq %r8, %r12
callq 0x4ac6
movq %r12, %r8
movl -0x2c(%rbp), %edi
addl %eax, %edi
movq -0x40(%rbp), %rax
movslq %eax, %r12
cmpl %r15d, %eax
jge 0x3b38
movq 0x30(%rbx), %rcx
movq (%rcx,%rax,8), %rcx
incq %rax
cmpb $0x0, 0x68(%rcx)
jne 0x3b20
jmp 0x3b5d
movl $0x88, %eax
leaq (%r8,%rax), %rsi
movq 0x8(%rbx), %rdx
addq %rax, %rdx
movl %edi, -0x2c(%rbp)
movq %r8, -0x60(%rbp)
callq 0x4ac6
movq -0x60(%rbp), %r8
movl -0x2c(%rbp), %edi
addl %eax, %edi
addq $0x88, %r8
movq %r13, -0x68(%rbp)
cmpq %r14, %r12
jge 0x3bbd
leaq -0x1(%r12), %rax
cmpq %rax, %r13
jge 0x3bb8
movq 0x30(%rbx), %rax
movq -0x8(%rax,%r12,8), %rcx
cmpb $0x1, 0x68(%rcx)
jne 0x3bbd
movq (%rax,%r12,8), %rdx
addq $0x70, %rdx
movq %r8, %rsi
movq %r15, %r14
movl %edi, %r15d
movq %rbx, %r13
movq %r8, %rbx
callq 0x4ac6
movq %rbx, %r8
movq %r13, %rbx
movq -0x68(%rbp), %r13
movl %r15d, %edi
movq %r14, %r15
movq -0x48(%rbp), %r14
addl %eax, %edi
incq %r12
jmp 0x3b68
movq -0x38(%rbp), %r12
incq %r13
incq -0x40(%rbp)
jmp 0x3a97
xorl %edx, %edx
testl %edi, %edi
movl $0x0, %edi
jne 0x3a41
jmp 0x3bee
movq -0x50(%rbp), %r15
movq -0x58(%rbp), %rdx
incq %rdx
jmp 0x3a41
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop