// File: 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
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x23, (%rax)
je 0x7ed0
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq $0x0, -0x8(%rbp)
jmp 0x84bb
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x4100
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
jge 0x7f01
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq $0x0, -0x8(%rbp)
jmp 0x84bb
movl -0x1c(%rbp), %eax
addl $-0x2, %eax
movl %eax, %ecx
movq %rcx, -0xf0(%rbp)
subl $0x9, %eax
ja 0x84a5
movq -0xf0(%rbp), %rax
leaq 0xa641(%rip), %rcx      # 0x12568
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x21, %edi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x7ac0
movq %rax, -0x8(%rbp)
jmp 0x84bb
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq $0x0, -0x30(%rbp)
movq -0x28(%rbp), %rax
movl (%rax), %edi
callq 0x7ba0
testb $0x1, %al
jne 0x7f89
movq -0x10(%rbp), %rdi
callq 0x7620
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rsi
movl $0x22, %edi
xorl %eax, %eax
movl %eax, %edx
callq 0x7ac0
movq %rax, -0x8(%rbp)
jmp 0x84bb
movq -0x10(%rbp), %rdi
callq 0x7e00
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
jne 0x7fcd
movq -0x18(%rbp), %rax
movl 0x18(%rax), %esi
leaq 0xc049(%rip), %rdi      # 0x1400f
movb $0x0, %al
callq 0x4cd0
movl -0x1c(%rbp), %ecx
movl $0x24, %edi
movl $0x23, %eax
cmpl $0x4, %ecx
cmovel %eax, %edi
movq -0x38(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x7ac0
movq %rax, -0x8(%rbp)
jmp 0x84bb
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0x40(%rbp)
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq $0x0, -0x48(%rbp)
movq -0x40(%rbp), %rax
movl (%rax), %edi
callq 0x7ba0
testb $0x1, %al
jne 0x8035
movq -0x10(%rbp), %rdi
callq 0x7620
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rsi
movl $0x25, %edi
xorl %eax, %eax
movl %eax, %edx
callq 0x7ac0
movq %rax, -0x8(%rbp)
jmp 0x84bb
movl $0x26, %edi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x7ac0
movq %rax, -0x8(%rbp)
jmp 0x84bb
movl $0x27, %edi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x7ac0
movq %rax, -0x8(%rbp)
jmp 0x84bb
movl $0x28, %edi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x7ac0
movq %rax, -0x8(%rbp)
jmp 0x84bb
movq -0x10(%rbp), %rdi
callq 0x7620
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0x58(%rbp)
movb $0x0, -0x5a(%rbp)
movl $0x2, %edi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x7ac0
movq %rax, -0x68(%rbp)
movq $0x0, -0x70(%rbp)
movq -0x58(%rbp), %rax
cmpl $0x4, (%rax)
jne 0x814d
jmp 0x80e4
movq -0x10(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5310
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
cmpl $0x5, (%rax)
jne 0x8100
jmp 0x8148
movq -0x10(%rbp), %rdi
callq 0x7c70
movq %rax, -0x80(%rbp)
cmpq $0x0, -0x80(%rbp)
jne 0x8130
movq -0x78(%rbp), %rax
movl 0x18(%rax), %esi
movq -0x18(%rbp), %rax
movl 0x18(%rax), %edx
leaq 0xbf2b(%rip), %rdi      # 0x14054
movb $0x0, %al
callq 0x4cd0
movq -0x68(%rbp), %rsi
movq -0x80(%rbp), %rdx
movl $0x2, %edi
callq 0x7ac0
movq %rax, -0x68(%rbp)
jmp 0x80e4
jmp 0x8255
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
cmpl $0x2, (%rax)
je 0x818f
movq -0x88(%rbp), %rax
movl 0x18(%rax), %esi
leaq 0xbf39(%rip), %rdi      # 0x140c1
movb $0x0, %al
callq 0x4cd0
jmp 0x8191
movq -0x10(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5310
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
cmpl $0x1, (%rax)
je 0x81bd
movq -0x90(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x81c6
movb $0x1, -0x5a(%rbp)
jmp 0x8253
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0x98(%rbp)
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq -0x98(%rbp), %rsi
leaq -0x59(%rbp), %rdi
callq 0x8700
testb $0x1, %al
jne 0x81fa
jmp 0x81fc
jmp 0x8253
movq -0x10(%rbp), %rdi
callq 0x7c70
movq %rax, -0xa0(%rbp)
cmpq $0x0, -0xa0(%rbp)
jne 0x8235
movq -0x98(%rbp), %rax
movl 0x18(%rax), %esi
movq -0x18(%rbp), %rax
movl 0x18(%rax), %edx
leaq 0xbe26(%rip), %rdi      # 0x14054
movb $0x0, %al
callq 0x4cd0
movq -0x68(%rbp), %rsi
movq -0xa0(%rbp), %rdx
movl $0x2, %edi
callq 0x7ac0
movq %rax, -0x68(%rbp)
jmp 0x8191
jmp 0x8255
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rsi
leaq -0x59(%rbp), %rdi
callq 0x8700
testb $0x1, %al
jne 0x827e
jmp 0x843a
movb $0x0, -0x5a(%rbp)
movl $0x2, %edi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x7ac0
movq %rax, -0x70(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
cmpl $0x4, (%rax)
jne 0x8330
jmp 0x82b5
movq -0x10(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5310
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rax
cmpl $0x5, (%rax)
jne 0x82d7
jmp 0x832b
movq -0x10(%rbp), %rdi
callq 0x7c70
movq %rax, -0xc0(%rbp)
cmpq $0x0, -0xc0(%rbp)
jne 0x8310
movq -0xa8(%rbp), %rax
movl 0x18(%rax), %esi
movq -0x18(%rbp), %rax
movl 0x18(%rax), %edx
leaq 0xbe0d(%rip), %rdi      # 0x14116
movb $0x0, %al
callq 0x4cd0
movq -0x70(%rbp), %rsi
movq -0xc0(%rbp), %rdx
movl $0x2, %edi
callq 0x7ac0
movq %rax, -0x70(%rbp)
jmp 0x82b5
jmp 0x8438
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
cmpl $0x2, (%rax)
je 0x8372
movq -0xc8(%rbp), %rax
movl 0x18(%rax), %esi
leaq 0xbe1f(%rip), %rdi      # 0x1418a
movb $0x0, %al
callq 0x4cd0
jmp 0x8374
movq -0x10(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5310
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rax
cmpl $0x1, (%rax)
je 0x83a0
movq -0xd0(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x83a9
movb $0x1, -0x5a(%rbp)
jmp 0x8436
movq -0x10(%rbp), %rdi
callq 0x5160
movq %rax, -0xd8(%rbp)
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq -0xd8(%rbp), %rsi
leaq -0x59(%rbp), %rdi
callq 0x8700
testb $0x1, %al
jne 0x83dd
jmp 0x83df
jmp 0x8436
movq -0x10(%rbp), %rdi
callq 0x7c70
movq %rax, -0xe0(%rbp)
cmpq $0x0, -0xe0(%rbp)
jne 0x8418
movq -0xd8(%rbp), %rax
movl 0x18(%rax), %esi
movq -0x18(%rbp), %rax
movl 0x18(%rax), %edx
leaq 0xbd05(%rip), %rdi      # 0x14116
movb $0x0, %al
callq 0x4cd0
movq -0x70(%rbp), %rsi
movq -0xe0(%rbp), %rdx
movl $0x2, %edi
callq 0x7ac0
movq %rax, -0x70(%rbp)
jmp 0x8374
jmp 0x8438
jmp 0x8448
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
testb $0x1, -0x5a(%rbp)
je 0x845c
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq -0x68(%rbp), %rsi
movq -0x70(%rbp), %rdx
movl $0x2a, %edi
callq 0x7ac0
movq %rax, -0xe8(%rbp)
movq -0x50(%rbp), %rsi
movq -0xe8(%rbp), %rdx
movl $0x29, %edi
callq 0x7ac0
movq %rax, -0x8(%rbp)
jmp 0x84bb
movq -0x18(%rbp), %rax
movl 0x18(%rax), %esi
leaq 0xbd3e(%rip), %rdi      # 0x141dc
movb $0x0, %al
callq 0x4cd0
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x5260
movq $0x0, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xf0, %rsp
popq %rbp
retq
nopl (%rax,%rax)