diff --git a/native/libcst/src/parser/grammar.rs b/native/libcst/src/parser/grammar.rs index 14622c1a9..5e23357d3 100644 --- a/native/libcst/src/parser/grammar.rs +++ b/native/libcst/src/parser/grammar.rs @@ -1004,7 +1004,7 @@ parser! { make_slice(l, col, u, rest) } / e:starred_expression() { make_index_from_arg(e) } - / v:expression() { make_index(v) } + / v:named_expression() { make_index(v) } rule atom() -> Expression<'input, 'a> = n:name() { Expression::Name(Box::new(n)) } diff --git a/native/libcst/src/tokenizer/core/mod.rs b/native/libcst/src/tokenizer/core/mod.rs index 7c0f0788e..d470a78a7 100644 --- a/native/libcst/src/tokenizer/core/mod.rs +++ b/native/libcst/src/tokenizer/core/mod.rs @@ -114,12 +114,8 @@ pub enum TokType { Dedent, Async, Await, - // TODO; add support for these - #[allow(dead_code)] FStringStart, - #[allow(dead_code)] FStringString, - #[allow(dead_code)] FStringEnd, EndMarker, } diff --git a/native/libcst/src/tokenizer/core/string_types.rs b/native/libcst/src/tokenizer/core/string_types.rs index 8f9e0cf0f..d14d13f5b 100644 --- a/native/libcst/src/tokenizer/core/string_types.rs +++ b/native/libcst/src/tokenizer/core/string_types.rs @@ -98,11 +98,10 @@ impl FStringNode { } pub fn close_parentheses(&mut self) { - self.parentheses_count -= 1; - if self.parentheses_count == 0 { - // No parentheses means that the format spec is also finished. - self.format_spec_count = 0; + if self.is_in_format_spec() { + self.format_spec_count -= 1; } + self.parentheses_count -= 1; } pub fn allow_multiline(&self) -> bool { diff --git a/native/libcst/src/tokenizer/tests.rs b/native/libcst/src/tokenizer/tests.rs index 4e8ce4d3e..08d26e555 100644 --- a/native/libcst/src/tokenizer/tests.rs +++ b/native/libcst/src/tokenizer/tests.rs @@ -814,3 +814,29 @@ fn test_inconsistent_indentation_at_eof() { ]) ) } + +#[test] +fn test_nested_f_string_specs() { + let config = TokConfig { + split_fstring: true, + ..default_config() + }; + assert_eq!( + tokenize_all("f'{_:{_:}{_}}'", &config), + Ok(vec![ + (TokType::FStringStart, "f'"), + (TokType::Op, "{"), + (TokType::Name, "_"), + (TokType::Op, ":"), + (TokType::Op, "{"), + (TokType::Name, "_"), + (TokType::Op, ":"), + (TokType::Op, "}"), + (TokType::Op, "{"), + (TokType::Name, "_"), + (TokType::Op, "}"), + (TokType::Op, "}"), + (TokType::FStringEnd, "'") + ]) + ) +} diff --git a/native/libcst/tests/fixtures/super_strings.py b/native/libcst/tests/fixtures/super_strings.py index d993f5abd..824572793 100644 --- a/native/libcst/tests/fixtures/super_strings.py +++ b/native/libcst/tests/fixtures/super_strings.py @@ -30,3 +30,5 @@ f'\{{\}}' f"regexp_like(path, '.*\{file_type}$')" f"\lfoo" + +f"{_:{_:}{a}}" \ No newline at end of file diff --git a/native/libcst/tests/fixtures/wonky_walrus.py b/native/libcst/tests/fixtures/wonky_walrus.py index d0916ab80..d506b169b 100644 --- a/native/libcst/tests/fixtures/wonky_walrus.py +++ b/native/libcst/tests/fixtures/wonky_walrus.py @@ -10,4 +10,6 @@ if f := x(): pass f(y:=1) -f(x, y := 1 ) \ No newline at end of file +f(x, y := 1 ) + +_[_:=10] \ No newline at end of file