#pragma once #include "basic_nodes.hpp" #include namespace printers { class Printer { public: Printer(std::ostream &output, size_t tab_width, size_t width_limit, bool print_words_instead_of_symbols) : output_(output), tab_width_(tab_width), width_limit_(width_limit), print_words_instead_of_symbols_(print_words_instead_of_symbols), current_position_(0), current_indentation_level_(0) {} void print_converted(const std::string &value) { for (auto &ch : value) { output_ << to_printable_symbol(ch); current_position_ += to_printable_symbol(ch).size(); } } // value shouldn't contain '\n', '\t', etc. void print(const std::string &value) { output_ << value; current_position_ += value.size(); } void column_down() { size_t current_position = current_position_; end_line(); print_spaces(current_position); } void new_indent_line() { end_line(); print_spaces(current_indentation_level_ * tab_width_); } void new_line(size_t indentation) { end_line(); print_spaces(indentation); } void indent() { current_indentation_level_ += tab_width_; } void deindent() { current_indentation_level_ -= tab_width_; } void tab() { print_spaces(tab_width_); } void space() { print_spaces(1); } size_t current_position() const { return current_position_; } size_t width_limit() const { return width_limit_; } size_t width_left() const { return std::max(static_cast(width_limit_) - static_cast(current_position_), static_cast(0)); } bool print_words_instead_of_symbols() const { return print_words_instead_of_symbols_; } size_t get_current_position() const { return current_position_; } size_t get_current_indentation_level() const { return current_indentation_level_; } size_t set_current_indentation_level(size_t indentation_level) { current_indentation_level_ = indentation_level; } private: void end_line() { output_ << "\n"; current_position_ = 0; } void print_spaces(size_t n) { print(std::string(n, ' ')); } static std::string to_printable_symbol(char ch) { switch (ch) { case '\a': return "\\a"; case '\b': return "\\b"; case '\e': return "\\e"; case '\f': return "\\f"; case '\n': return "\\n"; case '\r': return "\\r"; case '\t': return "\\t"; case '\v': return "\\v"; case '\'': return "\\\'"; case '\"': return "\\\""; // case ' ': // return "\\s"; default: return std::string(1, ch); } } private: std::ostream &output_; size_t tab_width_ = 0; size_t width_limit_ = 0; bool print_words_instead_of_symbols_ = false; size_t current_position_ = 0; size_t current_indentation_level_ = 0; }; void print_literal(const nodes::Literal &literal, Printer &printer); void print_identifier(const nodes::Identifier &identifier, Printer &printer); void print_annotation(const std::string &annotation, Printer &printer); } // namespace printers