forked from OSchip/llvm-project
[pseudo] Use box-drawing chars to prettify debug dumps. NFC
This commit is contained in:
parent
f6b60b3b79
commit
72864d9bfe
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue