From: Alan T. DeKok Date: Mon, 7 Feb 2022 20:00:37 +0000 (-0500) Subject: && and || are associative, n-ary operators X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=acf7cf288590cfaf85fe3b18b3236578e38454f7;p=thirdparty%2Ffreeradius-server.git && and || are associative, n-ary operators We'll do more operators later. --- diff --git a/src/lib/unlang/xlat_expr.c b/src/lib/unlang/xlat_expr.c index c2bca1dd8f2..a384ab6e2f4 100644 --- a/src/lib/unlang/xlat_expr.c +++ b/src/lib/unlang/xlat_expr.c @@ -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; diff --git a/src/tests/unit/xlat/expr.txt b/src/tests/unit/xlat/expr.txt index f4af852a620..2fa458c3c5e 100644 --- a/src/tests/unit/xlat/expr.txt +++ b/src/tests/unit/xlat/expr.txt @@ -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