#include "frontend/SyntaxTreePrinter.h" #include 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(names.size())) { return names[static_cast(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(node)) { label = GetTokenName(terminal->getSymbol(), parser) + ": " + terminal->getText(); } else if (auto* rule = dynamic_cast(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); }