]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
&& and || are associative, n-ary operators
authorAlan T. DeKok <aland@freeradius.org>
Mon, 7 Feb 2022 20:00:37 +0000 (15:00 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 7 Feb 2022 20:09:20 +0000 (15:09 -0500)
We'll do more operators later.

src/lib/unlang/xlat_expr.c
src/tests/unit/xlat/expr.txt

index c2bca1dd8f247953ea131e5ff38fc4e084d7e5d8..a384ab6e2f47cb1b62da4285097a4e4ae411d31f 100644 (file)
@@ -677,6 +677,14 @@ static const fr_sbuff_term_elem_t binary_ops[T_TOKEN_LAST] = {
        [ 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,
@@ -1236,9 +1244,6 @@ redo:
                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.
@@ -1324,6 +1329,7 @@ redo:
        default:
                break;
        }
+
        /*
         *      We now parse the RHS, allowing a (perhaps different) cast on the RHS.
         */
@@ -1345,6 +1351,28 @@ redo:
        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.
         *
@@ -1355,6 +1383,8 @@ redo:
 
        /*
         *      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;
index f4af852a6201347a6e71a6ad954b97ff6c34d404..2fa458c3c5e9c78803ddba588c14e4d3fe97031d 100644 (file)
@@ -77,6 +77,16 @@ match ((1 < 2) || (4 > 3))
 xlat_expr 2 || (1 > 4)
 match (2 || (1 > 4))
 
+#
+#  Repeated operations of the same type are mashed together into one list.
+#  This only happens where the operations are associative.
+#
+xlat_expr 1 < 2 || 4 > 3 || 4 == 4 || 1 < 2
+match ((1 < 2) || (4 > 3) || (4 == 4) || (1 < 2))
+
+#
+#  Other stuff
+#
 xlat_expr &Filter-Id
 match %{Filter-Id}
 
@@ -124,4 +134,4 @@ match ((1 + 2) * (3 + 4))
 
 
 count
-match 55
+match 57