forked from NUDT-compiler/nudt-compiler-cpp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
2.1 KiB
72 lines
2.1 KiB
#include "frontend/SyntaxTreePrinter.h"
|
|
|
|
#include <string>
|
|
|
|
namespace {
|
|
|
|
std::string GetTokenName(const antlr4::Token* tok, antlr4::Parser* parser) {
|
|
if (!tok || !parser) {
|
|
return "UNKNOWN";
|
|
}
|
|
const int token_type = tok->getType();
|
|
const auto& vocab = parser->getVocabulary();
|
|
std::string token_name(vocab.getSymbolicName(token_type));
|
|
if (token_name.empty()) {
|
|
token_name = std::string(vocab.getLiteralName(token_type));
|
|
}
|
|
if (token_name.empty()) {
|
|
token_name = std::to_string(token_type);
|
|
}
|
|
return token_name;
|
|
}
|
|
|
|
std::string RuleName(antlr4::ParserRuleContext* rule, antlr4::Parser* parser) {
|
|
if (!rule || !parser) {
|
|
return "unknown";
|
|
}
|
|
const int idx = rule->getRuleIndex();
|
|
const auto& names = parser->getRuleNames();
|
|
if (idx >= 0 && idx < static_cast<int>(names.size())) {
|
|
return names[static_cast<size_t>(idx)];
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
void PrintSyntaxTreeImpl(antlr4::tree::ParseTree* node, antlr4::Parser* parser,
|
|
std::ostream& os, const std::string& prefix,
|
|
bool is_last, bool is_root) {
|
|
if (!node) {
|
|
return;
|
|
}
|
|
|
|
std::string label;
|
|
if (auto* terminal = dynamic_cast<antlr4::tree::TerminalNode*>(node)) {
|
|
label = GetTokenName(terminal->getSymbol(), parser) + ": " + terminal->getText();
|
|
} else if (auto* rule = dynamic_cast<antlr4::ParserRuleContext*>(node)) {
|
|
label = RuleName(rule, parser);
|
|
} else {
|
|
label = "unknown";
|
|
}
|
|
|
|
if (is_root) {
|
|
os << label << "\n";
|
|
} else {
|
|
os << prefix << (is_last ? "`-- " : "|-- ") << label << "\n";
|
|
}
|
|
|
|
const std::string child_prefix =
|
|
is_root ? "" : prefix + (is_last ? " " : "| ");
|
|
const size_t child_count = node->children.size();
|
|
for (size_t i = 0; i < child_count; ++i) {
|
|
PrintSyntaxTreeImpl(node->children[i], parser, os, child_prefix,
|
|
i + 1 == child_count, false);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void PrintSyntaxTree(antlr4::tree::ParseTree* tree, antlr4::Parser* parser,
|
|
std::ostream& os) {
|
|
PrintSyntaxTreeImpl(tree, parser, os, "", true, true);
|
|
}
|