+ load_exp->child = load_exp_op;
+ str = node->u.expression.u.string;
+ if (!strcmp(str, "$ctx")) {
+ load_exp_op->type = IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT;
+ node = node->u.expression.next;
+ if (!node) {
+ fprintf(stderr, "[error] Expecting identifier after \'%s\'\n", str);
+ goto error;
+ }
+ str = node->u.expression.u.string;
+ } else if (!strcmp(str, "$app")) {
+ load_exp_op->type = IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT;
+ node = node->u.expression.next;
+ if (!node) {
+ fprintf(stderr, "[error] Expecting identifier after \'%s\'\n", str);
+ goto error;
+ }
+ str = node->u.expression.u.string;
+ } else if (str[0] == '$') {
+ fprintf(stderr, "[error] Unexpected identifier \'%s\'\n", str);
+ goto error;
+ } else {
+ load_exp_op->type = IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT;
+ }
+
+ for (;;) {
+ struct filter_node *bracket_node;
+
+ prev_op = load_exp_op;
+ load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
+ if (!load_exp_op)
+ goto error;
+ prev_op->next = load_exp_op;
+ load_exp_op->type = IR_LOAD_EXPRESSION_GET_SYMBOL;
+ load_exp_op->u.symbol = strdup(str);
+ if (!load_exp_op->u.symbol)
+ goto error;
+
+ /* Explore brackets from current node. */
+ for (bracket_node = node->u.expression.next_bracket;
+ bracket_node != NULL;
+ bracket_node = bracket_node->u.expression.next_bracket) {
+ prev_op = load_exp_op;
+ if (bracket_node->type != NODE_EXPRESSION ||
+ bracket_node->u.expression.type != AST_EXP_CONSTANT) {
+ fprintf(stderr, "[error] Expecting constant index in array expression\n");
+ goto error;
+ }
+ load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
+ if (!load_exp_op)
+ goto error;
+ prev_op->next = load_exp_op;
+ load_exp_op->type = IR_LOAD_EXPRESSION_GET_INDEX;
+ load_exp_op->u.index = bracket_node->u.expression.u.constant;
+ }
+ /* Go to next chain element. */
+ node = node->u.expression.next;
+ if (!node)
+ break;
+ str = node->u.expression.u.string;