Make a Lisp
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.

145 lines
2.9 KiB

2 years ago
/*
* Copyright (C) 2023 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#include <iterator> // std::next
#include <string>
#include "ruc/format/format.h"
2 years ago
#include "ast.h"
#include "error.h"
#include "lexer.h"
2 years ago
#include "printer.h"
#include "types.h"
namespace blaze {
Printer::Printer()
2 years ago
{
}
Printer::~Printer()
{
}
// -----------------------------------------
std::string Printer::print(ASTNode* node)
2 years ago
{
if (Error::the().hasAnyError()) {
init();
printError();
return m_print;
}
return printNoErrorCheck(node);
}
std::string Printer::printNoErrorCheck(ASTNode* node)
{
init();
if (node == nullptr) {
return {};
2 years ago
}
printImpl(node);
return m_print;
}
// -----------------------------------------
void Printer::init()
{
m_first_node = true;
m_previous_node_is_list = false;
m_print = "";
2 years ago
}
void Printer::printImpl(ASTNode* node)
2 years ago
{
auto printSpacing = [this]() -> void {
if (!m_first_node && !m_previous_node_is_list) {
m_print += ' ';
2 years ago
}
};
if (is<List>(node)) {
printSpacing();
m_print += '(';
m_first_node = false;
m_previous_node_is_list = true;
auto nodes = static_cast<List*>(node)->nodes();
for (size_t i = 0; i < nodes.size(); ++i) {
printImpl(nodes[i]);
m_previous_node_is_list = false;
}
m_print += ')';
}
else if (is<Vector>(node)) {
printSpacing();
m_print += '[';
m_first_node = false;
m_previous_node_is_list = true;
auto nodes = static_cast<Vector*>(node)->nodes();
for (size_t i = 0; i < nodes.size(); ++i) {
printImpl(nodes[i]);
m_previous_node_is_list = false;
}
m_print += ']';
}
else if (is<HashMap>(node)) {
printSpacing();
m_print += "{";
m_first_node = false;
m_previous_node_is_list = true;
auto elements = static_cast<HashMap*>(node)->elements();
for (auto it = elements.begin(); it != elements.end(); ++it) {
m_print += format("{} ", it->first.front() == 0x7f ? ":" + it->first.substr(1) : it->first); // 127
printImpl(it->second);
if (it != elements.end() && std::next(it) != elements.end()) {
m_print += ' ';
}
}
m_previous_node_is_list = false;
m_print += '}';
}
2 years ago
else if (is<String>(node)) {
2 years ago
// TODO: Implement string readably printing
2 years ago
printSpacing();
m_print += format("{}", static_cast<String*>(node)->data());
2 years ago
}
else if (is<Keyword>(node)) {
printSpacing();
m_print += format(":{}", static_cast<Keyword*>(node)->keyword().substr(1));
}
2 years ago
else if (is<Number>(node)) {
printSpacing();
m_print += format("{}", static_cast<Number*>(node)->number());
2 years ago
}
else if (is<Symbol>(node)) {
printSpacing();
m_print += format("{}", static_cast<Symbol*>(node)->symbol());
2 years ago
}
}
void Printer::printError()
{
m_print = "Error: ";
if (Error::the().hasTokenError()) {
Token error = Error::the().tokenError();
m_print += format("{}", error.symbol);
}
else if (Error::the().hasOtherError()) {
std::string error = Error::the().otherError();
m_print += format("{}", error);
}
}
2 years ago
} // namespace blaze