From 2e3b2a48ee8518c18393263ad840709ae6cad4ff Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Thu, 10 Feb 2022 11:09:08 -0500 Subject: [PATCH] Fix string interpolation paren cases (#4410) --- crates/nu-parser/src/parser.rs | 35 ++++++++++++++++++++++++---------- src/tests/test_parser.rs | 15 +++++++++++++++ 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 3bc9340fbb..70425b2e45 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1260,14 +1260,13 @@ pub fn parse_string_interpolation( let mut output = vec![]; let mut mode = InterpolationMode::String; let mut token_start = start; - let mut depth = 0; + let mut delimiter_stack = vec![]; let mut b = start; #[allow(clippy::needless_range_loop)] while b != end { if contents[b - start] == b'(' && mode == InterpolationMode::String { - depth = 1; mode = InterpolationMode::Expression; if token_start < b { let span = Span { @@ -1281,14 +1280,30 @@ pub fn parse_string_interpolation( ty: Type::String, custom_completion: None, }); + token_start = b; } - token_start = b; - } else if contents[b - start] == b'(' && mode == InterpolationMode::Expression { - depth += 1; - } else if contents[b - start] == b')' && mode == InterpolationMode::Expression { - match depth { - 0 => {} - 1 => { + } + if mode == InterpolationMode::Expression { + let byte = contents[b - start]; + if let Some(b'\'') = delimiter_stack.last() { + if byte == b'\'' { + delimiter_stack.pop(); + } + } else if let Some(b'"') = delimiter_stack.last() { + if byte == b'"' { + delimiter_stack.pop(); + } + } else if byte == b'\'' { + delimiter_stack.push(b'\'') + } else if byte == b'"' { + delimiter_stack.push(b'"'); + } else if byte == b'(' { + delimiter_stack.push(b')'); + } else if byte == b')' { + if let Some(b')') = delimiter_stack.last() { + delimiter_stack.pop(); + } + if delimiter_stack.is_empty() { mode = InterpolationMode::String; if token_start < b { @@ -1303,8 +1318,8 @@ pub fn parse_string_interpolation( } token_start = b + 1; + continue; } - _ => depth -= 1, } } b += 1; diff --git a/src/tests/test_parser.rs b/src/tests/test_parser.rs index d744e328ed..605b9e9f4e 100644 --- a/src/tests/test_parser.rs +++ b/src/tests/test_parser.rs @@ -197,3 +197,18 @@ fn let_env_expressions() -> TestResult { "done", ) } + +#[test] +fn string_interpolation_paren_test() -> TestResult { + run_test(r#"$"('(')(')')""#, "()") +} + +#[test] +fn string_interpolation_paren_test2() -> TestResult { + run_test(r#"$"('(')test(')')""#, "(test)") +} + +#[test] +fn string_interpolation_paren_test3() -> TestResult { + run_test(r#"$"('(')("test")test(')')""#, "(testtest)") +}