From 3b4892071d3667e39ea5dbf181ff3446db3df2a2 Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Tue, 16 Jul 2024 17:54:32 -0400 Subject: [PATCH] libexpr: make "or"-as-variable less bogus The previous place where OR_KW was inserted into the grammar to allow expressions like "map or [...]" led to a number of weird outcomes. By moving it to expr_simple, expressions using "or" as a variable are now parsed consistently with the rest of the language. Conflicts are prevented by telling Bison that OR_KW has higher precedence than '.'. --- src/libexpr/parser.y | 10 ++++++---- tests/unit/libexpr/trivial.cc | 10 ++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 452d265bc..6974c66f5 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -158,6 +158,9 @@ static void setDocPosition(const LexerState & lexerState, ExprLambda * lambda, P %nonassoc '?' %nonassoc NEGATE +%precedence '.' +%precedence OR_KW + %% start: expr { state->result = $1; }; @@ -248,10 +251,6 @@ expr_select { $$ = new ExprSelect(CUR_POS, $1, std::move(*$3), nullptr); delete $3; } | expr_simple '.' attrpath OR_KW expr_select { $$ = new ExprSelect(CUR_POS, $1, std::move(*$3), $5); delete $3; } - | /* Backwards compatibility: because Nixpkgs has a rarely used - function named ‘or’, allow stuff like ‘map or [...]’. */ - expr_simple OR_KW - { $$ = new ExprCall(CUR_POS, $1, {new ExprVar(CUR_POS, state->s.or_)}); } | expr_simple ; @@ -263,6 +262,9 @@ expr_simple else $$ = new ExprVar(CUR_POS, state->symbols.create($1)); } + | /* Backwards compatibility: because Nixpkgs has a rarely used + function named ‘or’, allow stuff like ‘map or [...]’. */ + OR_KW { $$ = new ExprVar(CUR_POS, state->s.or_); } | INT_LIT { $$ = new ExprInt($1); } | FLOAT_LIT { $$ = new ExprFloat($1); } | '"' string_parts '"' { $$ = $2; } diff --git a/tests/unit/libexpr/trivial.cc b/tests/unit/libexpr/trivial.cc index 61ea71a0f..fcd8e0f1a 100644 --- a/tests/unit/libexpr/trivial.cc +++ b/tests/unit/libexpr/trivial.cc @@ -190,7 +190,13 @@ namespace nix { ASSERT_THAT(*b->value, IsIntEq(1)); } - TEST_F(TrivialExpressionTest, orCantBeUsed) { - ASSERT_THROW(eval("let or = 1; in or"), Error); + TEST_F(TrivialExpressionTest, orCanBeUsed) { + auto v = eval("let or = 1; in or"); + ASSERT_THAT(v, IsIntEq(1)); + } + + TEST_F(TrivialExpressionTest, orHasCorrectPrecedence) { + auto v = eval("let inherit (builtins) add; or = 2; in add 1 or"); + ASSERT_THAT(v, IsIntEq(3)); } } /* namespace nix */