// File: 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
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x48(%rbp)
movl $0x0, -0xc(%rbp)
movq -0x48(%rbp), %rdi
movslq -0xc(%rbp), %rax
movq %rax, -0x50(%rbp)
addq $0x8, %rdi
callq 0xc4d0
movq %rax, %rcx
movq -0x50(%rbp), %rax
cmpq %rcx, %rax
jae 0x6481
movq -0x48(%rbp), %rdi
addq $0x8, %rdi
movslq -0xc(%rbp), %rsi
callq 0xc4f0
movq (%rax), %rax
cmpl $0x1, 0x48(%rax)
jne 0x6471
movq -0x48(%rbp), %rdi
addq $0x8, %rdi
movslq -0xc(%rbp), %rsi
callq 0xc4f0
movq -0x48(%rbp), %rdi
movq (%rax), %rax
addq $0x88, %rax
movq %rax, -0x58(%rbp)
addq $0x8, %rdi
movslq -0xc(%rbp), %rsi
callq 0xc4f0
movq -0x58(%rbp), %rdi
movq %rax, %rsi
callq 0xc690
jmp 0x6473
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0x63fb
jmp 0x6483
movl $0x0, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movq -0x48(%rbp), %rdi
movslq -0x14(%rbp), %rax
movq %rax, -0x60(%rbp)
addq $0x20, %rdi
callq 0xc510
movq %rax, %rcx
movq -0x60(%rbp), %rax
cmpq %rcx, %rax
jae 0x66f7
movq -0x48(%rbp), %rdi
addq $0x20, %rdi
movslq -0x14(%rbp), %rsi
callq 0xc530
movq (%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
callq 0xc4d0
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
jne 0x64e9
jmp 0x66e9
movl $0x0, -0x28(%rbp)
movl -0x28(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x66e7
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
movslq -0x28(%rbp), %rsi
callq 0xc4f0
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x1, 0x48(%rax)
jne 0x6582
cmpl $0x0, -0x28(%rbp)
jle 0x657d
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0xc4f0
movq (%rax), %rax
cmpl $0x2, 0x48(%rax)
jne 0x657d
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0xc4f0
movq -0x48(%rbp), %rdi
movq (%rax), %rsi
addq $0x88, %rsi
movq -0x30(%rbp), %rdx
addq $0x88, %rdx
callq 0x8450
addl -0x10(%rbp), %eax
movl %eax, -0x10(%rbp)
jmp 0x66d9
cmpl $0x0, -0x28(%rbp)
jle 0x65de
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0xc4f0
movq (%rax), %rax
cmpl $0x2, 0x48(%rax)
jne 0x65de
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0xc4f0
movq -0x48(%rbp), %rdi
movq (%rax), %rsi
addq $0x88, %rsi
movq -0x30(%rbp), %rdx
addq $0x70, %rdx
callq 0x8450
addl -0x10(%rbp), %eax
movl %eax, -0x10(%rbp)
movb $0x1, -0x31(%rbp)
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
movl -0x38(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x6620
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
movslq -0x38(%rbp), %rsi
callq 0xc4f0
movq (%rax), %rax
testb $0x1, 0x68(%rax)
jne 0x6613
movb $0x0, -0x31(%rbp)
jmp 0x6620
jmp 0x6615
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x65eb
testb $0x1, -0x31(%rbp)
je 0x664f
movq -0x48(%rbp), %rdi
movq -0x30(%rbp), %rsi
addq $0x88, %rsi
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rdx
addq $0x88, %rdx
callq 0x8450
addl -0x10(%rbp), %eax
movl %eax, -0x10(%rbp)
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x66d7
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl -0x3c(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jle 0x6672
jmp 0x66cc
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
movl -0x3c(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0xc4f0
movq (%rax), %rax
testb $0x1, 0x68(%rax)
jne 0x6693
jmp 0x66d7
movq -0x30(%rbp), %rax
addq $0x88, %rax
movq %rax, -0x68(%rbp)
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
movslq -0x3c(%rbp), %rsi
callq 0xc4f0
movq -0x48(%rbp), %rdi
movq -0x68(%rbp), %rsi
movq (%rax), %rdx
addq $0x70, %rdx
callq 0x8450
addl -0x10(%rbp), %eax
movl %eax, -0x10(%rbp)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x6658
jmp 0x66d9
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x64f0
jmp 0x66e9
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x6491
cmpl $0x0, -0x10(%rbp)
jne 0x66ff
jmp 0x6704
jmp 0x6483
addq $0x70, %rsp
popq %rbp
retq
nopw (%rax,%rax)