From 9fae50ed4be6c7f8bd16ece9626709d78bb4b01c Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Wed, 17 Jul 2024 02:42:18 +0200 Subject: [PATCH 1/2] Add parser test for indented strings So that in the next commit we can see what changes about this test --- .../functional/lang/parse-okay-ind-string.exp | 1 + .../functional/lang/parse-okay-ind-string.nix | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/functional/lang/parse-okay-ind-string.exp create mode 100644 tests/functional/lang/parse-okay-ind-string.nix diff --git a/tests/functional/lang/parse-okay-ind-string.exp b/tests/functional/lang/parse-okay-ind-string.exp new file mode 100644 index 000000000..5f8d48688 --- /dev/null +++ b/tests/functional/lang/parse-okay-ind-string.exp @@ -0,0 +1 @@ +(let string = "str"; in [ (/some/path) ((/some/path)) (("" + /some/path)) ((/some/path + "\n end")) (string) ((string)) (("" + string)) ((string + "\n end")) ("") ("") ("end") ]) diff --git a/tests/functional/lang/parse-okay-ind-string.nix b/tests/functional/lang/parse-okay-ind-string.nix new file mode 100644 index 000000000..97c9de3cd --- /dev/null +++ b/tests/functional/lang/parse-okay-ind-string.nix @@ -0,0 +1,31 @@ +let + string = "str"; +in [ + /some/path + + ''${/some/path}'' + + '' + ${/some/path}'' + + ''${/some/path} + end'' + + string + + ''${string}'' + + '' + ${string}'' + + ''${string} + end'' + + '''' + + '' + '' + + '' + end'' +] From 0c91bb97e5579169fdac94ebfbb352ee1cc4a5ae Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Wed, 17 Jul 2024 02:43:42 +0200 Subject: [PATCH 2/2] parser: Remove empty multiline string parts earlier Makes parsing more consistent and is a super minor optimisation Co-authored-by: Robert Hensing --- src/libexpr/parser-state.hh | 13 ++++++++++++- tests/functional/lang/parse-okay-ind-string.exp | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/libexpr/parser-state.hh b/src/libexpr/parser-state.hh index 983a17a2e..d8287db9b 100644 --- a/src/libexpr/parser-state.hh +++ b/src/libexpr/parser-state.hh @@ -291,12 +291,23 @@ inline Expr * ParserState::stripIndentation(const PosIdx pos, s2 = std::string(s2, 0, p + 1); } - es2->emplace_back(i->first, new ExprString(std::move(s2))); + // Ignore empty strings for a minor optimisation and AST simplification + if (s2 != "") { + es2->emplace_back(i->first, new ExprString(std::move(s2))); + } }; for (; i != es.end(); ++i, --n) { std::visit(overloaded { trimExpr, trimString }, i->second); } + // If there is nothing at all, return the empty string directly. + // This also ensures that equivalent empty strings result in the same ast, which is helpful when testing formatters. + if (es2->size() == 0) { + auto *const result = new ExprString(""); + delete es2; + return result; + } + /* If this is a single string, then don't do a concatenation. */ if (es2->size() == 1 && dynamic_cast((*es2)[0].second)) { auto *const result = (*es2)[0].second; diff --git a/tests/functional/lang/parse-okay-ind-string.exp b/tests/functional/lang/parse-okay-ind-string.exp index 5f8d48688..82e9940a2 100644 --- a/tests/functional/lang/parse-okay-ind-string.exp +++ b/tests/functional/lang/parse-okay-ind-string.exp @@ -1 +1 @@ -(let string = "str"; in [ (/some/path) ((/some/path)) (("" + /some/path)) ((/some/path + "\n end")) (string) ((string)) (("" + string)) ((string + "\n end")) ("") ("") ("end") ]) +(let string = "str"; in [ (/some/path) ((/some/path)) ((/some/path)) ((/some/path + "\n end")) (string) ((string)) ((string)) ((string + "\n end")) ("") ("") ("end") ])