[clang-tools-extra] 72864d9 - [pseudo] Use box-drawing chars to prettify debug dumps. NFC

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 25 06:17:46 PDT 2022


Author: Sam McCall
Date: 2022-03-25T14:17:38+01:00
New Revision: 72864d9bfec929b2427981d99c2ac67ff5fcfe19

URL: https://github.com/llvm/llvm-project/commit/72864d9bfec929b2427981d99c2ac67ff5fcfe19
DIFF: https://github.com/llvm/llvm-project/commit/72864d9bfec929b2427981d99c2ac67ff5fcfe19.diff

LOG: [pseudo] Use box-drawing chars to prettify debug dumps. NFC

Added: 
    

Modified: 
    clang-tools-extra/pseudo/lib/Forest.cpp
    clang-tools-extra/pseudo/unittests/ForestTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/pseudo/lib/Forest.cpp b/clang-tools-extra/pseudo/lib/Forest.cpp
index 41b9be8a8d30f..6948422a23a6e 100644
--- a/clang-tools-extra/pseudo/lib/Forest.cpp
+++ b/clang-tools-extra/pseudo/lib/Forest.cpp
@@ -46,15 +46,23 @@ std::string ForestNode::dumpRecursive(const Grammar &G,
       };
   CountVisits(this);
 
+  // The box-drawing characters that should be added as a child is rendered.
+  struct LineDecoration {
+    std::string Prefix;         // Prepended to every line.
+    llvm::StringRef First;      // added to the child's line.
+    llvm::StringRef Subsequent; // added to descendants' lines.
+  };
+
   // We print a "#<id>" for nonterminal forest nodes that are being dumped
   // multiple times.
   llvm::DenseMap<const ForestNode *, size_t> ReferenceIds;
   std::string Result;
   constexpr Token::Index KEnd = std::numeric_limits<Token::Index>::max();
-  std::function<void(const ForestNode *, unsigned, Token::Index,
-                     llvm::Optional<SymbolID>)>
-      Dump = [&](const ForestNode *P, unsigned Level, Token::Index End,
-                 llvm::Optional<SymbolID> ElidedParent) {
+  std::function<void(const ForestNode *, Token::Index, llvm::Optional<SymbolID>,
+                     LineDecoration &LineDec)>
+      Dump = [&](const ForestNode *P, Token::Index End,
+                 llvm::Optional<SymbolID> ElidedParent,
+                 LineDecoration LineDec) {
         llvm::ArrayRef<const ForestNode *> Children;
         auto EndOfElement = [&](size_t ChildIndex) {
           return ChildIndex + 1 == Children.size()
@@ -72,18 +80,19 @@ std::string ForestNode::dumpRecursive(const Grammar &G,
               if (Children[I]->startTokenIndex() == P->startTokenIndex() &&
                   EndOfElement(I) == End) {
                 return Dump(
-                    Children[I], Level, End,
-                    /*ElidedParent=*/ElidedParent.getValueOr(P->symbol()));
+                    Children[I], End,
+                    /*ElidedParent=*/ElidedParent.getValueOr(P->symbol()),
+                    LineDec);
               }
           }
         }
 
-        // FIXME: pretty ascii trees
         if (End == KEnd)
           Result += llvm::formatv("[{0,3}, end) ", P->startTokenIndex());
         else
           Result += llvm::formatv("[{0,3}, {1,3}) ", P->startTokenIndex(), End);
-        Result.append(2 * Level, ' ');
+        Result += LineDec.Prefix;
+        Result += LineDec.First;
         if (ElidedParent.hasValue()) {
           Result += G.symbolName(*ElidedParent);
           Result += "~";
@@ -99,12 +108,23 @@ std::string ForestNode::dumpRecursive(const Grammar &G,
         }
         Result.push_back('\n');
 
-        ++Level;
-        for (size_t I = 0; I < Children.size(); ++I)
-          Dump(Children[I], Level,
-               P->kind() == Sequence ? EndOfElement(I) : End, llvm::None);
+        auto OldPrefixSize = LineDec.Prefix.size();
+        LineDec.Prefix += LineDec.Subsequent;
+        for (size_t I = 0; I < Children.size(); ++I) {
+          if (I == Children.size() - 1) {
+            LineDec.First = "└─";
+            LineDec.Subsequent = "  ";
+          } else {
+            LineDec.First = "├─";
+            LineDec.Subsequent = "│ ";
+          }
+          Dump(Children[I], P->kind() == Sequence ? EndOfElement(I) : End,
+               llvm::None, LineDec);
+        }
+        LineDec.Prefix.resize(OldPrefixSize);
       };
-  Dump(this, 0, KEnd, llvm::None);
+  LineDecoration LineDec;
+  Dump(this, KEnd, llvm::None, LineDec);
   return Result;
 }
 

diff  --git a/clang-tools-extra/pseudo/unittests/ForestTest.cpp b/clang-tools-extra/pseudo/unittests/ForestTest.cpp
index b9bd08d78288a..a734a8f7f8616 100644
--- a/clang-tools-extra/pseudo/unittests/ForestTest.cpp
+++ b/clang-tools-extra/pseudo/unittests/ForestTest.cpp
@@ -71,19 +71,20 @@ TEST_F(ForestTest, DumpBasic) {
                                             ruleFor("id-expression"), {&T[2]});
 
   const auto *Add =
-      &Arena.createSequence(symbol("add-expression"), ruleFor("add-expression"), {Left, &T[1], Right});
+      &Arena.createSequence(symbol("add-expression"), ruleFor("add-expression"),
+                            {Left, &T[1], Right});
   EXPECT_EQ(Add->dumpRecursive(*G, true),
             "[  0, end) add-expression := id-expression + id-expression\n"
-            "[  0,   1)   id-expression~IDENTIFIER := tok[0]\n"
-            "[  1,   2)   + := tok[1]\n"
-            "[  2, end)   id-expression~IDENTIFIER := tok[2]\n");
+            "[  0,   1) ├─id-expression~IDENTIFIER := tok[0]\n"
+            "[  1,   2) ├─+ := tok[1]\n"
+            "[  2, end) └─id-expression~IDENTIFIER := tok[2]\n");
   EXPECT_EQ(Add->dumpRecursive(*G, false),
             "[  0, end) add-expression := id-expression + id-expression\n"
-            "[  0,   1)   id-expression := IDENTIFIER\n"
-            "[  0,   1)     IDENTIFIER := tok[0]\n"
-            "[  1,   2)   + := tok[1]\n"
-            "[  2, end)   id-expression := IDENTIFIER\n"
-            "[  2, end)     IDENTIFIER := tok[2]\n");
+            "[  0,   1) ├─id-expression := IDENTIFIER\n"
+            "[  0,   1) │ └─IDENTIFIER := tok[0]\n"
+            "[  1,   2) ├─+ := tok[1]\n"
+            "[  2, end) └─id-expression := IDENTIFIER\n"
+            "[  2, end)   └─IDENTIFIER := tok[2]\n");
 }
 
 TEST_F(ForestTest, DumpAmbiguousAndRefs) {
@@ -115,14 +116,14 @@ TEST_F(ForestTest, DumpAmbiguousAndRefs) {
       &Arena.createAmbiguous(symbol("type"), {Alternative1, Alternative2});
   EXPECT_EQ(Type->dumpRecursive(*G),
             "[  0, end) type := <ambiguous>\n"
-            "[  0, end)   class-type := shared-type\n"
-            "[  0, end)     class-type := shared-type\n"
-            "[  0, end)       shared-type := IDENTIFIER #1\n"
-            "[  0, end)         IDENTIFIER := tok[0]\n"
-            "[  0, end)   enum-type := shared-type\n"
-            "[  0, end)     enum-type := shared-type\n"
-            "[  0, end)       shared-type := IDENTIFIER =#1\n"
-            "[  0, end)         IDENTIFIER := tok[0]\n");
+            "[  0, end) ├─class-type := shared-type\n"
+            "[  0, end) │ └─class-type := shared-type\n"
+            "[  0, end) │   └─shared-type := IDENTIFIER #1\n"
+            "[  0, end) │     └─IDENTIFIER := tok[0]\n"
+            "[  0, end) └─enum-type := shared-type\n"
+            "[  0, end)   └─enum-type := shared-type\n"
+            "[  0, end)     └─shared-type := IDENTIFIER =#1\n"
+            "[  0, end)       └─IDENTIFIER := tok[0]\n");
 }
 
 } // namespace


        


More information about the cfe-commits mailing list