@@ -268,3 +268,110 @@ syntax::Node *syntax::Tree::findChild(NodeRole R) {
268
268
}
269
269
return nullptr ;
270
270
}
271
+
272
+ std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
273
+ syntax::List::getElementsAsNodesAndDelimiters () {
274
+ if (!firstChild ())
275
+ return {};
276
+
277
+ auto children = std::vector<syntax::List::ElementAndDelimiter<Node>>();
278
+ syntax::Node *elementWithoutDelimiter = nullptr ;
279
+ for (auto *C = firstChild (); C; C = C->nextSibling ()) {
280
+ switch (C->role ()) {
281
+ case syntax::NodeRole::List_element: {
282
+ if (elementWithoutDelimiter) {
283
+ children.push_back ({elementWithoutDelimiter, nullptr });
284
+ }
285
+ elementWithoutDelimiter = C;
286
+ break ;
287
+ }
288
+ case syntax::NodeRole::List_delimiter: {
289
+ children.push_back ({elementWithoutDelimiter, cast<syntax::Leaf>(C)});
290
+ elementWithoutDelimiter = nullptr ;
291
+ break ;
292
+ }
293
+ default :
294
+ llvm_unreachable (
295
+ " A list can have only elements and delimiters as children." );
296
+ }
297
+ }
298
+
299
+ switch (getTerminationKind ()) {
300
+ case syntax::List::TerminationKind::Separated: {
301
+ children.push_back ({elementWithoutDelimiter, nullptr });
302
+ break ;
303
+ }
304
+ case syntax::List::TerminationKind::Terminated:
305
+ case syntax::List::TerminationKind::MaybeTerminated: {
306
+ if (elementWithoutDelimiter) {
307
+ children.push_back ({elementWithoutDelimiter, nullptr });
308
+ }
309
+ break ;
310
+ }
311
+ }
312
+
313
+ return children;
314
+ }
315
+
316
+ // Almost the same implementation of `getElementsAsNodesAndDelimiters` but
317
+ // ignoring delimiters
318
+ std::vector<syntax::Node *> syntax::List::getElementsAsNodes () {
319
+ if (!firstChild ())
320
+ return {};
321
+
322
+ auto children = std::vector<syntax::Node *>();
323
+ syntax::Node *elementWithoutDelimiter = nullptr ;
324
+ for (auto *C = firstChild (); C; C = C->nextSibling ()) {
325
+ switch (C->role ()) {
326
+ case syntax::NodeRole::List_element: {
327
+ if (elementWithoutDelimiter) {
328
+ children.push_back (elementWithoutDelimiter);
329
+ }
330
+ elementWithoutDelimiter = C;
331
+ break ;
332
+ }
333
+ case syntax::NodeRole::List_delimiter: {
334
+ children.push_back (elementWithoutDelimiter);
335
+ elementWithoutDelimiter = nullptr ;
336
+ break ;
337
+ }
338
+ default :
339
+ llvm_unreachable (" A list has only elements or delimiters." );
340
+ }
341
+ }
342
+
343
+ switch (getTerminationKind ()) {
344
+ case syntax::List::TerminationKind::Separated: {
345
+ children.push_back (elementWithoutDelimiter);
346
+ break ;
347
+ }
348
+ case syntax::List::TerminationKind::Terminated:
349
+ case syntax::List::TerminationKind::MaybeTerminated: {
350
+ if (elementWithoutDelimiter) {
351
+ children.push_back (elementWithoutDelimiter);
352
+ }
353
+ break ;
354
+ }
355
+ }
356
+
357
+ return children;
358
+ }
359
+
360
+ // The methods below can't be implemented without information about the derived
361
+ // list. These methods will be implemented by switching on the derived list's
362
+ // `NodeKind`
363
+
364
+ clang::tok::TokenKind syntax::List::getDelimiterTokenKind () {
365
+ llvm_unreachable (" There are no subclasses of List, thus "
366
+ " getDelimiterTokenKind() cannot be called" );
367
+ }
368
+
369
+ syntax::List::TerminationKind syntax::List::getTerminationKind () {
370
+ llvm_unreachable (" There are no subclasses of List, thus getTerminationKind() "
371
+ " cannot be called" );
372
+ }
373
+
374
+ bool syntax::List::canBeEmpty () {
375
+ llvm_unreachable (
376
+ " There are no subclasses of List, thus canBeEmpty() cannot be called" );
377
+ }
0 commit comments