// File: /workspace/github_cpp_makefile_star2_O2/exrd[P]neteruhsp/neteruhsp/neteruhsp.cc
// Function: neteruhsp::parse_control_safe(neteruhsp::parse_context_t&)
ast_node_t* parse_control_safe( parse_context_t& c )
{
	const auto ident = read_token( c );
	if ( ident->tag_ != TOKEN_IDENTIFIER )
	{
		unread_token( c );
		return nullptr;
	}

	const auto keyword = query_keyword( ident->content_ );
	if ( keyword < 0 )
	{
		unread_token( c );
		return nullptr;
	}

	switch( keyword )
	{
		case KEYWORD_END:
			return create_ast_node( NODE_END );
		case KEYWORD_RETURN:
		{
			const auto next = read_token( c );
			unread_token( c );

			ast_node_t* expr =nullptr;
			if ( !is_eos_like_token( next->tag_ ) )
			{
				expr = parse_expression( c );
			}
			return create_ast_node( NODE_RETURN, expr );
		}
		case KEYWORD_GOTO:
		case KEYWORD_GOSUB:
		{
			const auto label = parse_label_safe( c );
			if ( label == nullptr )
			{
				raise_error( "gotoまたはgosubにはラベルの指定が必須です@@ %d行目", ident->appear_line_ );
			}
			return create_ast_node( keyword==KEYWORD_GOTO ? NODE_GOTO : NODE_GOSUB, label );
		}
		case KEYWORD_REPEAT:
		{
			const auto next = read_token( c );
			unread_token( c );

			ast_node_t* expr =nullptr;
			if ( !is_eos_like_token( next->tag_ ) )
			{
				expr = parse_expression( c );
			}
			return create_ast_node( NODE_REPEAT, expr );
		}
		case KEYWORD_LOOP:
			return create_ast_node( NODE_LOOP );
		case KEYWORD_CONTINUE:
			return create_ast_node( NODE_CONTINUE );
		case KEYWORD_BREAK:
			return create_ast_node( NODE_BREAK );
		case KEYWORD_IF:
		{
			const auto expr = parse_expression( c );

			const auto next = read_token( c );

			const auto is_else_token = []( const token_t* n )
			{
				if ( n->tag_==TOKEN_IDENTIFIER && query_keyword(n->content_)==KEYWORD_ELSE )
				{ return true; }
				return false;
			};

			bool repair_token =false;

			ast_node_t* true_statements = create_ast_node( NODE_BLOCK_STATEMENTS );
			ast_node_t* false_statements = nullptr;
			if ( next->tag_ == TOKEN_LBRACE )
			{
				for( ; ; )
				{
					const auto pp = prev_token( c );
					if ( pp->tag_ == TOKEN_RBRACE )
					{
						// RBRACEは食われてた
						break;
					}
					const auto statement = parse_statement( c );
					if ( statement == nullptr )
					{
						raise_error( "if文の解析中、解析できないステートメントに到達しました@@ %d行目、%d行目から", pp->appear_line_, ident->appear_line_ );
					}
					true_statements = create_ast_node( NODE_BLOCK_STATEMENTS, true_statements, statement );
				}
			}
			else
			{
				unread_token( c );
				{
					const auto nn = read_token( c );
					if ( nn->tag_ != TOKEN_EOS )
					{
						raise_error( "if文の解析中：ifの条件式の後は { か : しか置けません@@ %d行目", nn->appear_line_ );
					}
				}

				for( ; ; )
				{
					const auto pp = prev_token( c );
					if ( pp->tag_==TOKEN_EOL || pp->tag_==TOKEN_EOF )
					{
						// EOLまたはEOFは食われてた
						repair_token =true;
						break;
					}
					const auto nn = read_token( c );
					unread_token( c );
					if ( is_else_token( nn ) )
					{ break; }

					const auto statement = parse_statement( c );
					if ( statement == nullptr )
					{
						raise_error( "if文の解析中、解析できないステートメントに到達しました@@ %d行目、%d行目から", nn->appear_line_, ident->appear_line_ );
					}
					true_statements = create_ast_node( NODE_BLOCK_STATEMENTS, true_statements, statement );
				}
			}

			// elseはあるか？
			const auto nn = read_token( c );
			if ( is_else_token( nn ) )
			{
				repair_token = false;
				false_statements = create_ast_node( NODE_BLOCK_STATEMENTS );

				const auto nextf = read_token( c );
				if ( nextf->tag_ == TOKEN_LBRACE )
				{
					for( ; ; )
					{
						const auto ppf = prev_token( c );
						if ( ppf->tag_ == TOKEN_RBRACE )
						{
							// RBRACEは食われてた
							break;
						}
						const auto statement = parse_statement( c );
						if ( statement == nullptr )
						{
							raise_error( "ifのelse文の解析中、解析できないステートメントに到達しました@@ %d行目、%d行目から", nn->appear_line_, ident->appear_line_ );
						}
						false_statements = create_ast_node( NODE_BLOCK_STATEMENTS, false_statements, statement );
					}
				}
				else
				{
					unread_token( c );
					{
						const auto nnf = read_token( c );
						if ( nnf->tag_ != TOKEN_EOS )
						{
							raise_error( "ifのelse文の解析中：elseの後は { か : しか置けません@@ %d行目", nnf->appear_line_ );
						}
					}

					for( ; ; )
					{
						const auto pp = prev_token( c );
						if ( pp->tag_==TOKEN_EOL || pp->tag_==TOKEN_EOF )
						{
							// EOLまたはEOFは食われてた
							repair_token = true;
							break;
						}
						const auto nnf = read_token( c );
						unread_token( c );
						if ( is_else_token( nnf ) )
						{ break; }

						const auto statement = parse_statement( c );
						if ( statement == nullptr )
						{
							raise_error( "ifのelse文の解析中、解析できないステートメントに到達しました@@ %d行目、%d行目から", nnf->appear_line_, ident->appear_line_ );
						}
						false_statements = create_ast_node( NODE_BLOCK_STATEMENTS, false_statements, statement );
					}
				}
			}
			else
			{
				unread_token( c );
			}

			// EOLを食いすぎてしまった場合用
			if ( repair_token )
			{
				unread_token( c );
			}

			ast_node_t* dispatcher = create_ast_node( NODE_IF_DISPATCHER, true_statements, false_statements );
			return create_ast_node( NODE_IF, expr, dispatcher );
		}
		case KEYWORD_ELSE:
			raise_error( "ハンドルされないelseを検出しました@@ %d行目", ident->appear_line_ );
			break;
	}

	unread_token( c );
	return nullptr;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
callq 0x3416
cmpl $0x23, (%rax)
jne 0x4b31
movq %rax, %r14
movq 0x8(%rax), %rdi
callq 0x2bc2
testl %eax, %eax
js 0x4b31
movl %eax, %r15d
leal -0x2(%r15), %eax
cmpl $0x9, %eax
ja 0x4b31
leaq 0x68ae(%rip), %rcx      # 0xb3b0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rbx, %rdi
callq 0x4a8b
testq %rax, %rax
je 0x4e28
xorl %edi, %edi
cmpl $0x4, %r15d
setne %dil
addl $0x23, %edi
movq %rax, %rsi
jmp 0x4c56
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x345a
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
callq 0x3416
movq %rax, %r14
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x345a
movl (%r14), %eax
cmpl $0x6, %eax
jae 0x4c39
pushq $0x27
popq %rcx
btl %eax, %ecx
jae 0x4c39
xorl %esi, %esi
jmp 0x4c44
pushq $0x21
jmp 0x4bc5
movq %rbx, %rdi
callq 0x3416
movq %rax, %r14
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x345a
movl (%r14), %eax
cmpl $0x6, %eax
jae 0x4c48
pushq $0x27
popq %rcx
btl %eax, %ecx
jae 0x4c48
xorl %esi, %esi
jmp 0x4c53
pushq $0x28
jmp 0x4bc5
pushq $0x26
jmp 0x4bc5
pushq $0x27
popq %rdi
xorl %esi, %esi
jmp 0x4c56
movq %rbx, %rdi
callq 0x5071
movq %rax, (%rsp)
movq %rbx, %rdi
callq 0x3416
movq %rax, %r15
pushq $0x2
popq %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x48d0
movq %rax, %r12
cmpl $0x4, (%r15)
jne 0x4c6b
pushq $0x2
popq %r13
xorl %ebp, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x34ac
cmpl $0x5, (%rax)
je 0x4ce4
movq %rax, %r15
movq %rbx, %rdi
callq 0x4994
testq %rax, %rax
je 0x4dfc
movl %r13d, %edi
movq %r12, %rsi
movq %rax, %rdx
callq 0x48d0
movq %rax, %r12
jmp 0x4bfd
movq %rbx, %rdi
callq 0x5071
movq %rax, %rsi
pushq $0x25
jmp 0x4c55
movq %rbx, %rdi
callq 0x5071
movq %rax, %rsi
pushq $0x22
popq %rdi
xorl %edx, %edx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x48d0
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x345a
movq %rbx, %rdi
callq 0x3416
cmpl $0x2, (%rax)
jne 0x4e42
pushq $0x1
popq %r13
movq %rbx, %rdi
xorl %esi, %esi
callq 0x34ac
cmpl $0x2, (%rax)
setb %bpl
jb 0x4ce4
movq %rbx, %rdi
callq 0x3416
movq %rax, %r15
movq %rbx, %rdi
movq %r13, %rsi
callq 0x345a
movq %r15, %rdi
callq 0x4f54
testb %al, %al
jne 0x4ce4
movq %rbx, %rdi
callq 0x4994
testq %rax, %rax
je 0x4dfc
pushq $0x2
popq %rdi
movq %r12, %rsi
movq %rax, %rdx
callq 0x48d0
movq %rax, %r12
jmp 0x4c8b
movq %rbx, %rdi
callq 0x3416
movq %rax, %r15
movq %rax, %rdi
callq 0x4f54
testb %al, %al
je 0x4d51
pushq $0x2
popq %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x48d0
movq %rax, %r13
movq %rbx, %rdi
callq 0x3416
cmpl $0x4, (%rax)
jne 0x4d8c
movq %r15, %rbp
pushq $0x2
popq %r15
movq %rbx, %rdi
xorl %esi, %esi
callq 0x34ac
cmpl $0x5, (%rax)
je 0x4d6f
movq %rbx, %rdi
callq 0x4994
testq %rax, %rax
je 0x4e0d
movl %r15d, %edi
movq %r13, %rsi
movq %rax, %rdx
callq 0x48d0
movq %rax, %r13
jmp 0x4d1e
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x345a
xorl %r13d, %r13d
testb %bpl, %bpl
je 0x4d6f
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x345a
pushq $0x2a
popq %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0x48d0
pushq $0x29
popq %rdi
movq (%rsp), %rsi
movq %rax, %rdx
jmp 0x4c58
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x345a
movq %rbx, %rdi
callq 0x3416
cmpl $0x2, (%rax)
jne 0x4e4e
pushq $0x1
popq %rbp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x34ac
cmpl $0x2, (%rax)
jb 0x4d64
movq %rbx, %rdi
callq 0x3416
movq %rax, %r15
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x345a
movq %r15, %rdi
callq 0x4f54
testb %al, %al
jne 0x4d6f
movq %rbx, %rdi
callq 0x4994
testq %rax, %rax
je 0x4e12
pushq $0x2
popq %rdi
movq %r13, %rsi
movq %rax, %rdx
callq 0x48d0
movq %rax, %r13
jmp 0x4dab
movl 0x18(%r15), %esi
movl 0x18(%r14), %edx
leaq 0x7fcb(%rip), %rdi      # 0xcdd6
jmp 0x4e21
movl 0x18(%rbp), %esi
jmp 0x4e16
movl 0x18(%r15), %esi
movl 0x18(%r14), %edx
leaq 0x8077(%rip), %rdi      # 0xce98
xorl %eax, %eax
callq 0x326e
movl 0x18(%r14), %esi
leaq 0x7f5e(%rip), %rdi      # 0xcd91
jmp 0x4e58
movl 0x18(%r14), %esi
leaq 0x811e(%rip), %rdi      # 0xcf5e
jmp 0x4e58
movl 0x18(%rax), %esi
leaq 0x7ff7(%rip), %rdi      # 0xce43
jmp 0x4e58
movl 0x18(%rax), %esi
leaq 0x80b4(%rip), %rdi      # 0xcf0c
xorl %eax, %eax
callq 0x326e