@@ -46,15 +46,23 @@ std::string ForestNode::dumpRecursive(const Grammar &G,
4646 };
4747 CountVisits (this );
4848
49+ // The box-drawing characters that should be added as a child is rendered.
50+ struct LineDecoration {
51+ std::string Prefix; // Prepended to every line.
52+ llvm::StringRef First; // added to the child's line.
53+ llvm::StringRef Subsequent; // added to descendants' lines.
54+ };
55+
4956 // We print a "#<id>" for nonterminal forest nodes that are being dumped
5057 // multiple times.
5158 llvm::DenseMap<const ForestNode *, size_t > ReferenceIds;
5259 std::string Result;
5360 constexpr Token::Index KEnd = std::numeric_limits<Token::Index>::max ();
54- std::function<void (const ForestNode *, unsigned , Token::Index,
55- llvm::Optional<SymbolID>)>
56- Dump = [&](const ForestNode *P, unsigned Level, Token::Index End,
57- llvm::Optional<SymbolID> ElidedParent) {
61+ std::function<void (const ForestNode *, Token::Index, llvm::Optional<SymbolID>,
62+ LineDecoration &LineDec)>
63+ Dump = [&](const ForestNode *P, Token::Index End,
64+ llvm::Optional<SymbolID> ElidedParent,
65+ LineDecoration LineDec) {
5866 llvm::ArrayRef<const ForestNode *> Children;
5967 auto EndOfElement = [&](size_t ChildIndex) {
6068 return ChildIndex + 1 == Children.size ()
@@ -72,18 +80,19 @@ std::string ForestNode::dumpRecursive(const Grammar &G,
7280 if (Children[I]->startTokenIndex () == P->startTokenIndex () &&
7381 EndOfElement (I) == End) {
7482 return Dump (
75- Children[I], Level, End,
76- /* ElidedParent=*/ ElidedParent.getValueOr (P->symbol ()));
83+ Children[I], End,
84+ /* ElidedParent=*/ ElidedParent.getValueOr (P->symbol ()),
85+ LineDec);
7786 }
7887 }
7988 }
8089
81- // FIXME: pretty ascii trees
8290 if (End == KEnd)
8391 Result += llvm::formatv (" [{0,3}, end) " , P->startTokenIndex ());
8492 else
8593 Result += llvm::formatv (" [{0,3}, {1,3}) " , P->startTokenIndex (), End);
86- Result.append (2 * Level, ' ' );
94+ Result += LineDec.Prefix ;
95+ Result += LineDec.First ;
8796 if (ElidedParent.hasValue ()) {
8897 Result += G.symbolName (*ElidedParent);
8998 Result += " ~" ;
@@ -99,12 +108,23 @@ std::string ForestNode::dumpRecursive(const Grammar &G,
99108 }
100109 Result.push_back (' \n ' );
101110
102- ++Level;
103- for (size_t I = 0 ; I < Children.size (); ++I)
104- Dump (Children[I], Level,
105- P->kind () == Sequence ? EndOfElement (I) : End, llvm::None);
111+ auto OldPrefixSize = LineDec.Prefix .size ();
112+ LineDec.Prefix += LineDec.Subsequent ;
113+ for (size_t I = 0 ; I < Children.size (); ++I) {
114+ if (I == Children.size () - 1 ) {
115+ LineDec.First = " └─" ;
116+ LineDec.Subsequent = " " ;
117+ } else {
118+ LineDec.First = " ├─" ;
119+ LineDec.Subsequent = " │ " ;
120+ }
121+ Dump (Children[I], P->kind () == Sequence ? EndOfElement (I) : End,
122+ llvm::None, LineDec);
123+ }
124+ LineDec.Prefix .resize (OldPrefixSize);
106125 };
107- Dump (this , 0 , KEnd, llvm::None);
126+ LineDecoration LineDec;
127+ Dump (this , KEnd, llvm::None, LineDec);
108128 return Result;
109129}
110130
0 commit comments