// File: /workspace/github_c_makefile_star2_O2/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, %r15
movq %rdx, (%rsp)
testq %rdx, %rdx
je 0x342ab
movq %rdx, %rbx
jmp 0x342bf
movq %rsp, %rbx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x32929
movq %rax, %r15
movq (%rbx), %rbx
leaq 0x8(%rsp), %r12
pushq $0x9
popq %rbp
pushq $0xa
popq %r14
testq %rbx, %rbx
je 0x34475
movq (%r15), %rdi
movl %edi, %eax
andl $0x3f, %eax
cmpl $0x12, %eax
jne 0x34487
movl 0x10(%r15), %eax
cmpl $0x28, %eax
je 0x343e7
cmpl $0x2e, %eax
je 0x343a7
cmpl $0x104, %eax            # imm = 0x104
je 0x3438b
cmpl $0x101, %eax            # imm = 0x101
je 0x34368
cmpl $0x103, %eax            # imm = 0x103
je 0x34368
cmpl $0x5b, %eax
jne 0x34487
movl %ebp, %esi
callq 0x328b4
movq %rax, %r13
movq (%r15), %rdi
pushq $0x5
popq %rsi
callq 0x328b4
movl $0x2a, 0x4(%r13)
movq %rax, 0x20(%r13)
movl $0x2b, 0x4(%rax)
movq %rbx, 0x20(%rax)
movq 0x8(%r15), %rdi
leaq 0x28(%rax), %rsi
callq 0x33661
movq %rax, %rdi
pushq $0x5d
popq %rsi
leaq 0xfd36(%rip), %rdx      # 0x44099
jmp 0x34461
movl %r14d, %esi
callq 0x328b4
movl 0x10(%r15), %ecx
movl %ecx, 0x4(%rax)
movq %rbx, 0x20(%rax)
movq %rax, (%rsp)
movq 0x8(%r15), %r15
movq %rax, %rbx
jmp 0x342cb
movl %ebp, %esi
callq 0x328b4
movl $0x2a, 0x4(%rax)
movq %rbx, 0x20(%rax)
movq %rax, (%rsp)
movq (%r15), %rdi
movq %rax, %rbx
pushq $0x8
popq %rsi
callq 0x328b4
movl $0x2e, 0x4(%rax)
movq %rbx, 0x20(%rax)
movq 0x8(%r15), %r15
movq (%r15), %rdi
movl %edi, %ecx
andl $0x3f, %ecx
cmpl $0x3, %ecx
jne 0x34479
movq 0x10(%r15), %rcx
movq %rcx, 0x28(%rax)
movq 0x8(%r15), %r15
movq %rax, (%rsp)
movq %rax, %rbx
jmp 0x342cb
pushq $0x14
popq %rsi
callq 0x328b4
movq %rax, %r13
movl $0x28, 0x4(%rax)
movq %rbx, 0x20(%rax)
movq 0x8(%r15), %rbx
movq %rax, %r15
addq $0x28, %r15
movl (%rbx), %eax
andl $0x3f, %eax
cmpl $0x12, %eax
jne 0x34418
cmpl $0x29, 0x10(%rbx)
je 0x34454
andq $0x0, 0x8(%rsp)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x335c4
movq %rax, %rbx
movq 0x8(%rsp), %rsi
testq %rsi, %rsi
je 0x34454
movq %r15, %rdi
callq 0x1fae9
movl (%rbx), %eax
andl $0x3f, %eax
cmpl $0x12, %eax
jne 0x34454
cmpl $0x2c, 0x10(%rbx)
jne 0x34454
movq 0x8(%rbx), %rbx
jmp 0x34408
movq %rbx, %rdi
pushq $0x29
popq %rsi
leaq 0xfd1e(%rip), %rdx      # 0x4417f
callq 0x17480
movq %rax, %r15
movq %r13, (%rsp)
movq %r13, %rbx
jmp 0x342cb
xorl %ebx, %ebx
jmp 0x34487
leaq 0xfc04(%rip), %rsi      # 0x44084
xorl %eax, %eax
callq 0x1120e
movq 0x10(%rsp), %rax
movq %rbx, (%rax)
movq %r15, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq