[ T_OP_REG_NE ] = L("reg_ne"),
};
+/*
+ * These operations are N-ary. i.e. we can concatenate all of
+ * their arguments together.
+ */
+static const bool nary_ops[T_TOKEN_LAST] = {
+ [T_LAND] = true,
+ [T_LOR] = true,
+};
/*
* Allow for BEDMAS ordering. Gross ordering is first number,
goto done;
}
- if ((op == T_OP_REG_EQ) || (op == T_OP_REG_NE)) {
- }
-
/*
* By default we don't parse enums on the RHS, and we're also flexible about what we see on the
* RHS.
default:
break;
}
+
/*
* We now parse the RHS, allowing a (perhaps different) cast on the RHS.
*/
func = xlat_func_find(binary_ops[op].str, binary_ops[op].len);
fr_assert(func != NULL);
+ /*
+ * If it's an n-ary operation, AND the LHS is the correct function, then just add "rhs" to the
+ * "lhs" children.
+ */
+ if (nary_ops[op] && (lhs->type == XLAT_FUNC) && (lhs->call.func->token == op)) {
+ xlat_exp_t **last;
+ fr_assert(lhs->call.func == func);
+
+ node = xlat_groupify_node(lhs, rhs);
+ last = &lhs->child;
+
+ /*
+ * Find the last child.
+ */
+ while (*last) last = &(*last)->next;
+
+ *last = node;
+ xlat_flags_merge(&node->flags, &rhs->flags);
+ xlat_flags_merge(&lhs->flags, &node->flags);
+ goto redo;
+ }
+
/*
* @todo - purify the node.
*
/*
* Create the function node, with the LHS / RHS arguments.
+ *
+ * @todo - node->fmt is NULL. Do we care about it at all?
*/
MEM(node = xlat_exp_alloc(ctx, XLAT_FUNC, fr_tokens[op], strlen(fr_tokens[op])));
node->call.func = func;