@@ -158,6 +158,18 @@ class Parser::Impl {
158158 node_arena_,
159159 ParseIdAssignRhs (Make<Identifier>(tok.text ), after_id.text ));
160160 break ;
161+ case TokenType::kComma : { // toplevel unpack assignment
162+ List *started_list = Make<List>(List::Type::kTuple );
163+ started_list->Append (node_arena_, Make<Identifier>(tok.text ));
164+ // List ends with assignment.
165+ Token assign;
166+ List *const lhs = ParseList (
167+ started_list, [&]() { return ParseOptionalIdentifier (); },
168+ TokenType::kAssign , &assign);
169+ statement_list->Append (node_arena_,
170+ ParseNodeAssignRhs (lhs, tok.text , assign.text ));
171+ break ;
172+ }
161173 case TokenType::kOpenParen :
162174 statement_list->Append (node_arena_, ParseFunCall (tok));
163175 break ;
@@ -204,10 +216,10 @@ class Parser::Impl {
204216 }
205217
206218 // Parse expressions produced by element_parse up to and including end_tok
207- // is reached.
219+ // is reached. If save_last_tok is non-null, last token will be stored there
208220 using ListElementParse = std::function<Node *()>;
209221 List *ParseList (List *result, const ListElementParse &element_parse,
210- TokenType end_tok) {
222+ TokenType end_tok, Token *save_last_tok = nullptr ) {
211223 LOG_ENTER ();
212224 // Opening list-token (e.g. '[', '(', '{') already consumed.
213225 Token upcoming = scanner_->Peek ();
@@ -223,7 +235,8 @@ class Parser::Impl {
223235 return result;
224236 }
225237 }
226- scanner_->Next (); // consume end_tok
238+ const Token closing_list = scanner_->Next (); // consume end_tok
239+ if (save_last_tok) *save_last_tok = closing_list;
227240 return result;
228241 }
229242
0 commit comments