// File: /workspace/github_c_makefile_star2_O1/lucvoo[P]sparse-dev/expression.c
// Function: postfix_expression
static struct token *postfix_expression(struct token *token, struct expression **tree, struct expression *cast_init_expr)
{
	struct expression *expr = cast_init_expr;

	if (!expr)
		token = primary_expression(token, &expr);

	while (expr && token_type(token) == TOKEN_SPECIAL) {
		switch (token->special) {
		case '[': {			/* Array dereference */
			struct expression *deref = alloc_expression(token->pos, EXPR_PREOP);
			struct expression *add = alloc_expression(token->pos, EXPR_BINOP);

			deref->op = '*';
			deref->unop = add;

			add->op = '+';
			add->left = expr;
			token = parse_expression(token->next, &add->right);
			token = expect(token, ']', "at end of array dereference");
			expr = deref;
			continue;
		}
		case SPECIAL_INCREMENT:		/* Post-increment */
		case SPECIAL_DECREMENT:	{	/* Post-decrement */
			struct expression *post = alloc_expression(token->pos, EXPR_POSTOP);
			post->op = token->special;
			post->unop = expr;
			expr = post;
			token = token->next;
			continue;
		}
		case SPECIAL_DEREFERENCE: {	/* Structure pointer member dereference */
			/* "x->y" is just shorthand for "(*x).y" */
			struct expression *inner = alloc_expression(token->pos, EXPR_PREOP);
			inner->op = '*';
			inner->unop = expr;
			expr = inner;
		}
		/* Fall through!! */
		case '.': {			/* Structure member dereference */
			struct expression *deref = alloc_expression(token->pos, EXPR_DEREF);
			deref->op = '.';
			deref->deref = expr;
			token = token->next;
			if (token_type(token) != TOKEN_IDENT) {
				sparse_error(token->pos, "Expected member name");
				break;
			}
			deref->member = token->ident;
			token = token->next;
			expr = deref;
			continue;
		}

		case '(': {			/* Function call */
			struct expression *call = alloc_expression(token->pos, EXPR_CALL);
			call->op = '(';
			call->fn = expr;
			token = expression_list(token->next, &call->args);
			token = expect(token, ')', "in function call");
			expr = call;
			continue;
		}

		default:
			break;
		}
		break;
	}
	*tree = expr;
	return token;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, 0x10(%rsp)
movq %rdi, %rbp
movq %rdx, (%rsp)
testq %rdx, %rdx
jne 0x3b66d
movq %rsp, %rsi
movq %rbp, %rdi
callq 0x39991
movq %rax, %rbp
movq (%rsp), %r13
testq %r13, %r13
je 0x3b8cf
leaq 0x8(%rsp), %r15
movq (%rbp), %rbx
movl %ebx, %eax
andl $0x3f, %eax
cmpl $0x12, %eax
jne 0x3b8cf
movl 0x10(%rbp), %eax
cmpl $0x100, %eax            # imm = 0x100
jg 0x3b735
cmpl $0x28, %eax
je 0x3b803
cmpl $0x2e, %eax
je 0x3b77d
cmpl $0x5b, %eax
jne 0x3b8cf
xorl %edi, %edi
callq 0x30029
movq %rax, %r14
movl (%rax), %eax
orl $0x9, %eax
movq %rbx, 0x8(%r14)
andl $0xffff0009, %eax       # imm = 0xFFFF0009
movl %eax, (%r14)
movq (%rbp), %rbx
xorl %edi, %edi
callq 0x30029
movl (%rax), %ecx
orl $0x5, %ecx
movq %rbx, 0x8(%rax)
andl $0xffff0005, %ecx       # imm = 0xFFFF0005
movl %ecx, (%rax)
movl $0x2a, 0x4(%r14)
movq %rax, 0x20(%r14)
movl $0x2b, 0x4(%rax)
movq %r13, 0x20(%rax)
movq 0x8(%rbp), %rdi
leaq 0x28(%rax), %rsi
callq 0x3a9cd
movq %rax, %rdi
movl $0x5d, %esi
leaq 0x107b5(%rip), %rdx     # 0x4bed9
callq 0x195d7
movq %rax, %rbp
movq %r14, (%rsp)
jmp 0x3b8c2
cmpl $0x101, %eax            # imm = 0x101
je 0x3b7d4
cmpl $0x103, %eax            # imm = 0x103
je 0x3b7d4
cmpl $0x104, %eax            # imm = 0x104
jne 0x3b8cf
xorl %edi, %edi
callq 0x30029
movl (%rax), %ecx
orl $0x9, %ecx
movq %rbx, 0x8(%rax)
andl $0xffff0009, %ecx       # imm = 0xFFFF0009
movl %ecx, (%rax)
movl $0x2a, 0x4(%rax)
movq %r13, 0x20(%rax)
movq %rax, (%rsp)
movq (%rbp), %rbx
xorl %edi, %edi
callq 0x30029
movl (%rax), %ecx
orl $0x8, %ecx
movq %rbx, 0x8(%rax)
andl $0xffff0008, %ecx       # imm = 0xFFFF0008
movl %ecx, (%rax)
movl $0x2e, 0x4(%rax)
movq (%rsp), %rcx
movq %rcx, 0x20(%rax)
movq 0x8(%rbp), %rbp
movq (%rbp), %rdi
movl %edi, %ebx
andl $0x3f, %ebx
cmpq $0x3, %rbx
jne 0x3b8af
movq 0x10(%rbp), %rcx
movq %rcx, 0x28(%rax)
movq 0x8(%rbp), %rbp
movq %rax, (%rsp)
jmp 0x3b8bd
xorl %edi, %edi
callq 0x30029
movl (%rax), %ecx
orl $0xa, %ecx
movq %rbx, 0x8(%rax)
andl $0xffff000a, %ecx       # imm = 0xFFFF000A
movl %ecx, (%rax)
movl 0x10(%rbp), %ecx
movl %ecx, 0x4(%rax)
movq %r13, 0x20(%rax)
movq %rax, (%rsp)
movq 0x8(%rbp), %rbp
jmp 0x3b8c2
xorl %edi, %edi
callq 0x30029
movq %rax, %r12
movl (%rax), %eax
orl $0x14, %eax
movq %rbx, 0x8(%r12)
andl $0xffff0014, %eax       # imm = 0xFFFF0014
movl %eax, (%r12)
movl $0x28, 0x4(%r12)
movq %r13, 0x20(%r12)
movq 0x8(%rbp), %rbp
movq %r12, %r14
addq $0x28, %r14
movl (%rbp), %eax
andl $0x3f, %eax
cmpl $0x12, %eax
jne 0x3b84a
cmpl $0x29, 0x10(%rbp)
je 0x3b892
movq $0x0, 0x8(%rsp)
movq %rbp, %rdi
movq %r15, %rsi
callq 0x3a91c
movq %rax, %rbp
movq 0x8(%rsp), %rsi
testq %rsi, %rsi
je 0x3b88c
movq %r14, %rdi
callq 0x2285b
movl (%rbp), %eax
andl $0x3f, %eax
cmpl $0x12, %eax
jne 0x3b88c
cmpl $0x2c, 0x10(%rbp)
jne 0x3b88c
movq 0x8(%rbp), %rbp
movb $0x1, %al
jmp 0x3b88e
xorl %eax, %eax
testb %al, %al
jne 0x3b839
movq %rbp, %rdi
movl $0x29, %esi
leaq 0x1071e(%rip), %rdx     # 0x4bfbf
callq 0x195d7
movq %rax, %rbp
movq %r12, (%rsp)
jmp 0x3b8c2
leaq 0x1060e(%rip), %rsi     # 0x4bec4
xorl %eax, %eax
callq 0x11a38
cmpl $0x3, %ebx
jne 0x3b8cf
movq (%rsp), %r13
testq %r13, %r13
jne 0x3b67f
movq (%rsp), %rax
movq 0x10(%rsp), %rcx
movq %rax, (%rcx)
movq %rbp, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq