diff options
| author | Eduardo Caldas <ecaldas@google.com> | 2020-08-04 17:33:36 +0000 | 
|---|---|---|
| committer | Eduardo Caldas <ecaldas@google.com> | 2020-08-10 10:32:28 +0000 | 
| commit | a90c78ac52615d256142ecd64fbedabb612dc73f (patch) | |
| tree | c1044fffd5dfea8e86add3eb3f9c0db051b1108b /clang/lib/Tooling/Syntax/Tree.cpp | |
| parent | dbcfbffc7ae46cc7b84257787681676144a1bd5f (diff) | |
| download | llvm-a90c78ac52615d256142ecd64fbedabb612dc73f.zip llvm-a90c78ac52615d256142ecd64fbedabb612dc73f.tar.gz llvm-a90c78ac52615d256142ecd64fbedabb612dc73f.tar.bz2 | |
[SyntaxTree] Implement the List construct.
We defined a List construct to help with the implementation of list-like
grammar rules. This is a first implementation of this API.
Differential Revision: https://reviews.llvm.org/D85295
Diffstat (limited to 'clang/lib/Tooling/Syntax/Tree.cpp')
| -rw-r--r-- | clang/lib/Tooling/Syntax/Tree.cpp | 107 | 
1 files changed, 107 insertions, 0 deletions
| diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index 6f9ee40..6070d16 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -268,3 +268,110 @@ syntax::Node *syntax::Tree::findChild(NodeRole R) {    }    return nullptr;  } + +std::vector<syntax::List::ElementAndDelimiter<syntax::Node>> +syntax::List::getElementsAsNodesAndDelimiters() { +  if (!firstChild()) +    return {}; + +  auto children = std::vector<syntax::List::ElementAndDelimiter<Node>>(); +  syntax::Node *elementWithoutDelimiter = nullptr; +  for (auto *C = firstChild(); C; C = C->nextSibling()) { +    switch (C->role()) { +    case syntax::NodeRole::List_element: { +      if (elementWithoutDelimiter) { +        children.push_back({elementWithoutDelimiter, nullptr}); +      } +      elementWithoutDelimiter = C; +      break; +    } +    case syntax::NodeRole::List_delimiter: { +      children.push_back({elementWithoutDelimiter, cast<syntax::Leaf>(C)}); +      elementWithoutDelimiter = nullptr; +      break; +    } +    default: +      llvm_unreachable( +          "A list can have only elements and delimiters as children."); +    } +  } + +  switch (getTerminationKind()) { +  case syntax::List::TerminationKind::Separated: { +    children.push_back({elementWithoutDelimiter, nullptr}); +    break; +  } +  case syntax::List::TerminationKind::Terminated: +  case syntax::List::TerminationKind::MaybeTerminated: { +    if (elementWithoutDelimiter) { +      children.push_back({elementWithoutDelimiter, nullptr}); +    } +    break; +  } +  } + +  return children; +} + +// Almost the same implementation of `getElementsAsNodesAndDelimiters` but +// ignoring delimiters +std::vector<syntax::Node *> syntax::List::getElementsAsNodes() { +  if (!firstChild()) +    return {}; + +  auto children = std::vector<syntax::Node *>(); +  syntax::Node *elementWithoutDelimiter = nullptr; +  for (auto *C = firstChild(); C; C = C->nextSibling()) { +    switch (C->role()) { +    case syntax::NodeRole::List_element: { +      if (elementWithoutDelimiter) { +        children.push_back(elementWithoutDelimiter); +      } +      elementWithoutDelimiter = C; +      break; +    } +    case syntax::NodeRole::List_delimiter: { +      children.push_back(elementWithoutDelimiter); +      elementWithoutDelimiter = nullptr; +      break; +    } +    default: +      llvm_unreachable("A list has only elements or delimiters."); +    } +  } + +  switch (getTerminationKind()) { +  case syntax::List::TerminationKind::Separated: { +    children.push_back(elementWithoutDelimiter); +    break; +  } +  case syntax::List::TerminationKind::Terminated: +  case syntax::List::TerminationKind::MaybeTerminated: { +    if (elementWithoutDelimiter) { +      children.push_back(elementWithoutDelimiter); +    } +    break; +  } +  } + +  return children; +} + +// The methods below can't be implemented without information about the derived +// list. These methods will be implemented by switching on the derived list's +// `NodeKind` + +clang::tok::TokenKind syntax::List::getDelimiterTokenKind() { +  llvm_unreachable("There are no subclasses of List, thus " +                   "getDelimiterTokenKind() cannot be called"); +} + +syntax::List::TerminationKind syntax::List::getTerminationKind() { +  llvm_unreachable("There are no subclasses of List, thus getTerminationKind() " +                   "cannot be called"); +} + +bool syntax::List::canBeEmpty() { +  llvm_unreachable( +      "There are no subclasses of List, thus canBeEmpty() cannot be called"); +} | 
