eduucaldas updated this revision to Diff 273093.
eduucaldas added a comment.

remove union. or relation implemented as a parent-child relation


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82302/new/

https://reviews.llvm.org/D82302

Files:
  clang/include/clang/Tooling/Syntax/Nodes.h

Index: clang/include/clang/Tooling/Syntax/Nodes.h
===================================================================
--- clang/include/clang/Tooling/Syntax/Nodes.h
+++ clang/include/clang/Tooling/Syntax/Nodes.h
@@ -45,6 +45,7 @@
   BinaryOperatorExpression,
   CxxNullPtrExpression,
   IntegerLiteralExpression,
+  IdExpression,
 
   // Statements.
   UnknownStatement,
@@ -84,7 +85,10 @@
   ArraySubscript,
   TrailingReturnType,
   ParametersAndQualifiers,
-  MemberPointer
+  MemberPointer,
+  NestedNameSpecifier,
+  NameSpecifier,
+  UnqualifiedId
 };
 /// For debugging purposes.
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeKind K);
@@ -187,6 +191,108 @@
   }
 };
 
+/// A sequence of these specifiers makes a `nested-name-specifier`.
+/// e.g. the `std::` or `vector<int>::` in `std::vector<int>::size`.
+class NameSpecifier final : public Tree {
+private:
+public:
+  NameSpecifier() : Tree(NodeKind::NameSpecifier) {}
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::NameSpecifier;
+  }
+
+  // See discussion about OR relation in `UnqualifiedId`
+  NodeKind getChildKind();
+  syntax::Leaf *getIdentifier();
+  syntax::Leaf *getNamespaceName();
+  //(...)
+
+  // Should we create accessors to everything?
+  syntax::Leaf *doubleCommaToken();
+};
+
+/// Models a `nested-name-specifier`. C++ [expr.prim.id.qual]
+/// e.g. the `std::vector<int>::` in `std::vector<int>::size`.
+class NestedNameSpecifier final : public Tree {
+public:
+  NestedNameSpecifier() : Tree(NodeKind::NestedNameSpecifier) {}
+  static bool classof(const Node *N) {
+    return N->kind() <= NodeKind::NestedNameSpecifier;
+  }
+  std::vector<syntax::NameSpecifier *> specifiers();
+};
+
+// Models `operator-function-id`. To be implemented, not interesting for
+// discussion
+class OperatorFunctionId;
+// Models `identifier`. This is merely a token.
+class Identifier;
+
+/// Models an `unqualified-id`, e.g. the `size` in `std::vector<int>::size`.
+// C++ [expr.prim.id.unqual]
+// unqualified-id:
+//   identifier
+//   operator-function-id
+//   conversion-function-id
+//   literal-operator-id
+//   ~ type-name
+//   ~ decltype-specifier
+//   template-id
+class UnqualifiedId final : public Tree {
+  // As {`identifier`, `operator-function-id`, ...} appear in other parts of the
+  // grammar - `template-id` appears almost everywhere - we implement them as
+  // standalone nodes instead of derived from `unqualified-id`. We encode the
+  // relation `unqualified-id` = {`identifier` OR `operator-function-id` OR ...}
+  // through a parent-child relation and to discover which child we have we
+  // check the `NodeKind` of the child.
+private:
+public:
+  UnqualifiedId() : Tree(NodeKind::UnqualifiedId) {}
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::UnqualifiedId;
+  }
+  NodeKind getChildKind();
+
+  // The way to use the API would be to call `getChildKind()`
+  // and then use the appropriate accessor according to the kind of the child.
+  syntax::Identifier *
+  getIdentifier(); // Drawback: Identifier is merely a Token, as such we
+                   // could've use a `syntax::Leaf`
+  syntax::OperatorFunctionId *getOperatorFunctionId();
+  // (...)
+};
+
+/// Models an `id-expression`, e.g. `std::vector<int>::size`.
+/// C++ [expr.prim.id]
+/// id-expression:
+///   unqualified-id
+///   qualified-id
+/// qualified-id:
+///   nested-name-specifier template_opt unqualified-id
+/// For simplicity we use:
+/// id-expression:
+///   nested-name-specifier_opt template_opt unqualified-id
+/// That is a bit more general than the grammar rule and allows forbidden
+/// syntax. That's ok, it is not our duty to verify the syntax of the program
+class IdExpression final : public Expression {
+public:
+  IdExpression() : Expression(NodeKind::IdExpression) {}
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::IdExpression;
+  }
+  // `qualifier` and `templateKeyword` are optional children of
+  // id-expression whereas `id` is a required child.
+  // How to make this distinction clear both to the reader and to the compiler?
+  // For children that are:
+  //  * required: use reference; optional: use pointer
+  //  * required: reference; optional: optional reference
+  // We could also use attributes to document that a pointer is not null
+  syntax::NestedNameSpecifier *qualifier();
+  syntax::Leaf *templateKeyword();
+
+  syntax::UnqualifiedId *id();
+};
+
 /// C++11 'nullptr' expression.
 class CxxNullPtrExpression final : public Expression {
 public:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D82302: [Discussion... Eduardo Caldas via Phabricator via cfe-commits

Reply via email to