Select Git revision
ASTPrinter.cpp
ASTPrinter.cpp 2.76 KiB
#include <ASTPrinter.hpp>
#include <EscapedString.hpp>
#include <PEGGrammar.hpp>
namespace language
{
void
ASTPrinter::_print(std::ostream& os, const ASTNode& node) const
{
os << '(' << rang::fgB::yellow;
if (node.is_root()) {
os << "root";
} else {
os << node.name();
}
os << rang::fg::reset;
if (node.is<language::name>() or node.is<language::literal>() or node.is<language::integer>() or
node.is<language::real>()) {
os << ':' << rang::fgB::green << node.string() << rang::fg::reset;
}
if (m_info & static_cast<InfoBaseType>(Info::data_type)) {
os << ':';
os << dataTypeName(node.m_data_type) << rang::fg::reset;
}
if (m_info & static_cast<InfoBaseType>(Info::data_value)) {
os << ':';
os << rang::fgB::cyan;
std::visit(
[&](const auto& value) {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, std::monostate>) {
os << "--";
} else if constexpr (std::is_same_v<T, std::string>) {
os << '\"' << escapeString(value) << '\"';
} else {
os << value;
}
},
node.m_value);
}
os << rang::fg::reset << ")\n";
if (not node.children.empty()) {
_print(os, node.children);
}
}
template <typename NodeVector>
void
ASTPrinter::_print(std::ostream& os, const NodeVector& node_list) const
{
for (size_t i_child = 0; i_child < node_list.size(); ++i_child) {
if (i_child != node_list.size() - 1) {
os << rang::fgB::green << prefix << T_junction << rang::fg::reset;
} else {
os << rang::fgB::green << prefix << L_junction << rang::fg::reset;
}
auto& child = *(node_list[i_child]);
if (not child.children.empty()) {
last_prefix_size.push_back(prefix.size());
if (i_child != node_list.size() - 1) {
prefix += pipe_space;
} else {
prefix += space_space;
}
_print(os, *(node_list[i_child]));
prefix.resize(last_prefix_size[last_prefix_size.size() - 1]);
last_prefix_size.pop_back();
} else {
_print(os, *(node_list[i_child]));
}
}
}
std::ostream&
operator<<(std::ostream& os, const ASTPrinter& ast_printer)
{
ast_printer._print(os, ast_printer.m_node);
return os;
}
ASTPrinter::ASTPrinter(const ASTNode& node, Format format, std::initializer_list<Info> initializer_list) : m_node{node}
{
if (format == Format::pretty) {
T_junction = " \u251c\u2500\u2500";
L_junction = " \u2514\u2500\u2500";
pipe_space = " \u2502 ";
space_space = " ";
} else {
Assert(format == Format::raw);
T_junction = " +-";
L_junction = " `-";
pipe_space = " | ";
space_space = " ";
}
m_info = 0;
for (auto i : initializer_list) {
m_info |= static_cast<InfoBaseType>(i);
}
}
} // namespace language