// File: /workspace/github_c_makefile_star2_O3/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, %rbx
movq %rdi, %r13
movq %rdx, 0x8(%rsp)
testq %rdx, %rdx
je 0x3ab97
movq %rdx, %r14
jmp 0x3abb6
leaq 0x8(%rsp), %r14
movq %r13, %rdi
movq %r14, %rsi
callq 0x38e13
movq %rax, %r13
movq (%r14), %r14
testq %r14, %r14
je 0x3adb3
movq (%r13), %r12
movl %r12d, %eax
andl $0x3f, %eax
cmpl $0x12, %eax
jne 0x3adc5
leaq 0x10(%rsp), %r15
movl 0x10(%r13), %eax
cmpl $0x100, %eax            # imm = 0x100
jg 0x3ac52
cmpl $0x28, %eax
je 0x3ad03
cmpl $0x2e, %eax
je 0x3ac92
cmpl $0x5b, %eax
jne 0x3adc5
xorl %edi, %edi
callq 0x2f9f5
movq %rax, %rbp
movq %r12, 0x8(%rax)
movw $0x9, (%rax)
movq (%r13), %r12
xorl %edi, %edi
callq 0x2f9f5
movq %r12, 0x8(%rax)
movw $0x5, (%rax)
movl $0x2a, 0x4(%rbp)
movq %rax, 0x20(%rbp)
movl $0x2b, 0x4(%rax)
movq %r14, 0x20(%rax)
movq 0x8(%r13), %rdi
leaq 0x28(%rax), %rsi
callq 0x39d79
movq %rax, %rdi
movl $0x5d, %esi
leaq 0x101fc(%rip), %rdx     # 0x4ae49
jmp 0x3ad8e
cmpl $0x101, %eax            # imm = 0x101
je 0x3acd7
cmpl $0x103, %eax            # imm = 0x103
je 0x3acd7
cmpl $0x104, %eax            # imm = 0x104
jne 0x3adc5
xorl %edi, %edi
callq 0x2f9f5
movq %r12, 0x8(%rax)
movw $0x9, (%rax)
movl $0x2a, 0x4(%rax)
movq %r14, 0x20(%rax)
movq %rax, 0x8(%rsp)
movq (%r13), %r12
movq %rax, %r14
xorl %edi, %edi
callq 0x2f9f5
movq %rax, %rbp
movq %r12, 0x8(%rax)
movw $0x8, (%rax)
movl $0x2e, 0x4(%rax)
movq %r14, 0x20(%rax)
movq 0x8(%r13), %r13
movq (%r13), %rdi
movl %edi, %eax
andl $0x3f, %eax
cmpl $0x3, %eax
jne 0x3adb7
movq 0x10(%r13), %rax
movq %rax, 0x28(%rbp)
movq 0x8(%r13), %r13
jmp 0x3ad96
xorl %edi, %edi
callq 0x2f9f5
movq %rax, %rbp
movq %r12, 0x8(%rax)
movw $0xa, (%rax)
movl 0x10(%r13), %eax
movl %eax, 0x4(%rbp)
movq %r14, 0x20(%rbp)
movq %rbp, 0x8(%rsp)
movq 0x8(%r13), %r13
jmp 0x3ad9b
xorl %edi, %edi
callq 0x2f9f5
movq %rax, %rbp
movq %r12, 0x8(%rax)
movw $0x14, (%rax)
movl $0x28, 0x4(%rax)
movq %r14, 0x20(%rax)
movq 0x8(%r13), %r14
movq %rax, %r13
addq $0x28, %r13
movl (%r14), %eax
andl $0x3f, %eax
cmpl $0x12, %eax
jne 0x3ad3e
cmpl $0x29, 0x10(%r14)
je 0x3ad7f
movq $0x0, 0x10(%rsp)
movq %r14, %rdi
movq %r15, %rsi
callq 0x39cd0
movq %rax, %r14
movq 0x10(%rsp), %rsi
testq %rsi, %rsi
je 0x3ad7f
movq %r13, %rdi
callq 0x227b4
movl (%r14), %eax
andl $0x3f, %eax
cmpl $0x12, %eax
jne 0x3ad7f
cmpl $0x2c, 0x10(%r14)
jne 0x3ad7f
movq 0x8(%r14), %r14
jmp 0x3ad2c
movq %r14, %rdi
movl $0x29, %esi
leaq 0x101a1(%rip), %rdx     # 0x4af2f
callq 0x1950f
movq %rax, %r13
movq %rbp, 0x8(%rsp)
movq (%r13), %r12
movl %r12d, %eax
andl $0x3f, %eax
movq %rbp, %r14
cmpl $0x12, %eax
je 0x3abce
jmp 0x3adc8
xorl %ebp, %ebp
jmp 0x3adc8
leaq 0x10076(%rip), %rsi     # 0x4ae34
xorl %eax, %eax
callq 0x11a80
movq %r14, %rbp
movq %rbp, (%rbx)
movq %r13, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq