From 97ce1f54497b3b39ba9e1b710f69a0cbb71af7bd Mon Sep 17 00:00:00 2001 From: Jon Meow <46229924+jonmeow@users.noreply.github.com> Date: Thu, 9 Dec 2021 08:10:36 -0800 Subject: [PATCH] Fix handling of closing scopes in FindNextof (#977) --- toolchain/lexer/token_kind.h | 4 ++-- .../386740becc4c02670666928a4699c330b2fe1152 | Bin 0 -> 343 bytes .../937ffb0f00790f35ae9b578df0bcfa40b06fd2e8 | Bin 0 -> 556 bytes .../eddd593ed1b3ecde2f2b4ddf2ba4a4fbb83a6028 | Bin 0 -> 27 bytes toolchain/parser/parse_tree_test.cpp | 16 ++++++++++++++++ toolchain/parser/parser_impl.cpp | 2 ++ 6 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 toolchain/parser/fuzzer_corpus/386740becc4c02670666928a4699c330b2fe1152 create mode 100644 toolchain/parser/fuzzer_corpus/937ffb0f00790f35ae9b578df0bcfa40b06fd2e8 create mode 100644 toolchain/parser/fuzzer_corpus/eddd593ed1b3ecde2f2b4ddf2ba4a4fbb83a6028 diff --git a/toolchain/lexer/token_kind.h b/toolchain/lexer/token_kind.h index 3828add4420f..a0c0bf6f1a67 100644 --- a/toolchain/lexer/token_kind.h +++ b/toolchain/lexer/token_kind.h @@ -64,12 +64,12 @@ class TokenKind { // The token kind must be an opening symbol. [[nodiscard]] auto GetClosingSymbol() const -> TokenKind; - // Test whether this kind of token is an closing symbol for a group. + // Test whether this kind of token is a closing symbol for a group. [[nodiscard]] auto IsClosingSymbol() const -> bool; // Returns the associated opening symbol for a closing symbol. // - // The token kind must be an closing symbol. + // The token kind must be a closing symbol. [[nodiscard]] auto GetOpeningSymbol() const -> TokenKind; // Test whether this kind of token is a keyword. diff --git a/toolchain/parser/fuzzer_corpus/386740becc4c02670666928a4699c330b2fe1152 b/toolchain/parser/fuzzer_corpus/386740becc4c02670666928a4699c330b2fe1152 new file mode 100644 index 0000000000000000000000000000000000000000..e4b750f75fd147f5cea219727ff807c58c9a8e66 GIT binary patch literal 343 zcmWe*kTSl({=3=c^YmG_{u#cWuC$Jei<=7wEKJO~$`XsXxb*e8xNNz&w6(Q$b(6U? zxEvfofJ+wxfOK(jRoCjF%H#pL$siMu0jd%RPtg`gYXUKt0aZ~2rj4LHBsqv8qRa$o xMm7_~udxMs2ne)54%5YIKFB!;z@=3T@-y5*kY+GP*Tlra%*?9$}?Q!7eR zi}Ij~Y6v(4W*DYJKn5TzgBVwfVHwOCbVq;#02B}?!2u5kBw@HBs8J9KVe@eFCM;=a F0{{|Kh;#q| literal 0 HcmV?d00001 diff --git a/toolchain/parser/fuzzer_corpus/eddd593ed1b3ecde2f2b4ddf2ba4a4fbb83a6028 b/toolchain/parser/fuzzer_corpus/eddd593ed1b3ecde2f2b4ddf2ba4a4fbb83a6028 new file mode 100644 index 0000000000000000000000000000000000000000..7a07a324e14b3fd30ba07493648c9a6a9e457ccd GIT binary patch literal 27 gcmZQzC`&A|wXt>6(2cg&(M`0o1%g;zT^$`w09y_QSpWb4 literal 0 HcmV?d00001 diff --git a/toolchain/parser/parse_tree_test.cpp b/toolchain/parser/parse_tree_test.cpp index f66a41569206..5ebd99c839ae 100644 --- a/toolchain/parser/parse_tree_test.cpp +++ b/toolchain/parser/parse_tree_test.cpp @@ -1159,5 +1159,21 @@ TEST_F(ParseTreeTest, PrintingAsYAML) { {"text", ""}}})); } +TEST_F(ParseTreeTest, ParenMatchRegression) { + // A regression test that the search for the closing `)` doesn't end early on + // the closing `}` when it skips over the nested scope. + TokenizedBuffer tokens = GetTokenizedBuffer("var = (foo {})"); + ParseTree tree = ParseTree::Parse(tokens, consumer); + EXPECT_TRUE(tree.HasErrors()); + EXPECT_THAT( + tree, MatchParseTreeNodes( + {MatchVariableDeclaration( + HasError, MatchVariableInitializer( + "=", MatchParenExpression( + HasError, MatchNameReference("foo"), + MatchParenExpressionEnd()))), + MatchFileEnd()})); +} + } // namespace } // namespace Carbon diff --git a/toolchain/parser/parser_impl.cpp b/toolchain/parser/parser_impl.cpp index 8aaad3280ea8..b634affb29b8 100644 --- a/toolchain/parser/parser_impl.cpp +++ b/toolchain/parser/parser_impl.cpp @@ -347,6 +347,8 @@ auto ParseTree::Parser::FindNextOf( } else if (kind.IsOpeningSymbol()) { new_position = TokenizedBuffer::TokenIterator(tokens_.GetMatchedClosingToken(token)); + // Advance past the closing token. + ++new_position; } else { ++new_position; }