fixes, expression printers

This commit is contained in:
ProgramSnail 2023-07-24 21:23:18 +03:00
parent 3669084f55
commit bf49f4030c
9 changed files with 349 additions and 101 deletions

View file

@ -7,40 +7,109 @@ namespace printers {
class Printer {
public:
Printer(std::ostream &output, size_t tab_width,
Printer(std::ostream &output, size_t tab_width, size_t width_limit,
bool print_words_instead_of_symbols)
: output_(output), tab_width_(tab_width),
: output_(output), tab_width_(tab_width), width_limit_(width_limit),
print_words_instead_of_symbols_(print_words_instead_of_symbols),
current_column_(0) {}
current_position_(0), current_indentation_level_(0) {}
template <typename T> void print(const T &value) { output_ << value; }
void new_line() {
print('\n');
print_spaces(current_column_ * tab_width_);
void print_converted(const std::string &value) {
for (auto &ch : value) {
output_ << to_printable_symbol(ch);
current_position_ += to_printable_symbol(ch).size();
}
}
void indent() { ++current_column_; }
// value shouldn't contain '\n', '\t', etc.
void print(const std::string &value) {
output_ << value;
current_position_ += value.size();
}
void deindent() { --current_column_; }
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_; }
void deindent() { --current_indentation_level_; }
void tab() { print_spaces(tab_width_); }
void space() { print_spaces(1); }
bool print_words_instead_of_symbols() {
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<int64_t>(width_limit_) -
static_cast<int64_t>(current_position_),
static_cast<int64_t>(0));
}
bool print_words_instead_of_symbols() const {
return print_words_instead_of_symbols_;
}
size_t get_current_position() { return current_position_; }
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_ = 2;
size_t tab_width_ = 0;
size_t width_limit_ = 0;
bool print_words_instead_of_symbols_ = false;
size_t current_column_ = 0;
size_t current_position_ = 0;
size_t current_indentation_level_ = 0;
};
void print_literal(const nodes::Literal &literal, Printer &printer);

View file

@ -528,6 +528,20 @@ public:
return std::nullopt;
}
std::variant<Match, Condition, Loop, Container, Return, NameDefinition,
Access, LoopControl, ModifierExpression, NameExpression,
Constructor, Lambda, Literal> *
get_any() {
return &expression_;
}
const std::variant<Match, Condition, Loop, Container, Return, NameDefinition,
Access, LoopControl, ModifierExpression, NameExpression,
Constructor, Lambda, Literal> *
get_any() const {
return &expression_;
}
bool is_scoped() const { return is_scoped_; }
private:

View file

@ -9,6 +9,8 @@ void print_expression(const nodes::Expression &expression,
// --- flow control
void print_case(const nodes::Match::Case &expression, Printer &printer);
void print_match(const nodes::Match &expression, printers::Printer &printer);
void print_condition(const nodes::Condition &expression,

View file

@ -58,9 +58,9 @@ public:
is_on_heap_(is_on_heap), is_optional_(is_optional),
is_result_(is_result) {}
std::string *get_name() { return name_.get(); }
Identifier *get_name() { return &name_; }
const std::string *get_name() const { return name_.get(); }
const Identifier *get_name() const { return &name_; }
size_t get_parametrs_size() const { return parameters_.size(); }

View file

@ -26,6 +26,10 @@ std::optional<char> to_escape_symbol(char ch) {
return '\t';
case 'v':
return '\v';
case '\'':
return '\'';
case '\"':
return '\"';
case 's':
return ' ';
default:

View file

@ -2,56 +2,29 @@
#include "error_handling.hpp"
#include <string>
namespace printers {
namespace utils {
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 "\\s";
default:
return std::string(1, ch);
}
}
} // namespace utils
void print_literal(const nodes::Literal &literal, Printer &printer) {
switch (literal.get_any()->index()) {
case 0: // double
// print in parseable form ??
printer.print(literal.get<double>().value());
printer.print(std::to_string(*literal.get<double>().value()));
return;
case 1: // long long
printer.print(literal.get<long long>().value());
printer.print(std::to_string(*literal.get<long long>().value()));
return;
case 2: // std::string
printer.print("\"\"");
// more efficient approach ??
for (auto &ch : *literal.get<std::string>().value()) {
printer.print(utils::to_printable_symbol(ch));
}
printer.print("\"\"");
printer.print("\"");
printer.print_converted(
*literal.get<std::string>()
.value()); // special symbols are converted inside
printer.print("\"");
return;
case 3: // char
printer.print("\'\'");
printer.print(utils::to_printable_symbol(*literal.get<char>().value()));
printer.print_converted(std::string(1, *literal.get<char>().value()));
printer.print("\'\'");
return;
case 4: // bool
@ -72,11 +45,11 @@ void print_literal(const nodes::Literal &literal, Printer &printer) {
}
void print_identifier(const nodes::Identifier &identifier, Printer &printer) {
printer.print(identifier.get());
printer.print(*identifier.get());
}
void print_annotation(const std::string &annotation, Printer &printer) {
printer.print('@');
printer.print("@");
printer.print(annotation);
}

View file

@ -16,94 +16,109 @@ build_expression(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage) {
tokens::Type type = tokens::string_to_type(parser_node.get_type());
auto maybe_parenthesis = parser_node.next_sibling();
bool is_scoped =
(!maybe_parenthesis.is_null() && maybe_parenthesis.get_value() == "(");
switch (type) {
// --- flow control
case tokens::Type::MATCH:
return expression_storage.add_expression(nodes::Expression(
build_match(parser_node, expression_storage, type_storage)));
build_match(parser_node, expression_storage, type_storage), is_scoped));
case tokens::Type::CONDITION:
return expression_storage.add_expression(nodes::Expression(
build_condition(parser_node, expression_storage, type_storage)));
build_condition(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::LOOP:
return expression_storage.add_expression(nodes::Expression(
build_loop(parser_node, expression_storage, type_storage)));
build_loop(parser_node, expression_storage, type_storage), is_scoped));
// --- operators
case tokens::Type::COMMA_EXPRESSION:
return expression_storage.add_expression(nodes::Expression(
build_comma_expression(parser_node, expression_storage, type_storage)));
build_comma_expression(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::OPERATOR_EXPRESSION:
return expression_storage.add_expression(
nodes::Expression(build_operator_expression(
parser_node, expression_storage, type_storage)));
parser_node, expression_storage, type_storage),
is_scoped));
// --- containers
case tokens::Type::BLOCK:
return expression_storage.add_expression(nodes::Expression(
build_block(parser_node, expression_storage, type_storage)));
build_block(parser_node, expression_storage, type_storage), is_scoped));
case tokens::Type::ARRAY:
return expression_storage.add_expression(nodes::Expression(
build_array(parser_node, expression_storage, type_storage)));
build_array(parser_node, expression_storage, type_storage), is_scoped));
// --- modifiers
case tokens::Type::RETURN:
return expression_storage.add_expression(nodes::Expression(
build_return(parser_node, expression_storage, type_storage)));
build_return(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::NAME_DEFINITION:
return expression_storage.add_expression(
nodes::Expression(build_name_definition(parser_node)));
nodes::Expression(build_name_definition(parser_node), is_scoped));
case tokens::Type::ARRAY_ACCESS:
return expression_storage.add_expression(nodes::Expression(
build_array_access(parser_node, expression_storage, type_storage)));
build_array_access(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::TUPLE_ACCESS:
return expression_storage.add_expression(nodes::Expression(
build_tuple_access(parser_node, expression_storage, type_storage)));
build_tuple_access(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::LOOP_CONTROL:
return expression_storage.add_expression(
nodes::Expression(build_loop_control(parser_node)));
nodes::Expression(build_loop_control(parser_node), is_scoped));
case tokens::Type::REFERENCE_EXPRESSION:
return expression_storage.add_expression(
nodes::Expression(build_reference_expression(
parser_node, expression_storage, type_storage)));
parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::SUFFIX_EXPRESSION:
return expression_storage.add_expression(
nodes::Expression(build_suffix_expression(
parser_node, expression_storage, type_storage)));
return expression_storage.add_expression(nodes::Expression(
build_suffix_expression(parser_node, expression_storage, type_storage),
is_scoped));
// --- other
case tokens::Type::NAME_EXPRESSION:
return expression_storage.add_expression(nodes::Expression(
build_name_expression(parser_node, expression_storage, type_storage)));
build_name_expression(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
case tokens::Type::SIMPLE_NAME_IDENTIFIER:
case tokens::Type::PLACEHOLDER:
return expression_storage.add_expression(
nodes::Expression(nodes::NameExpression(
build_node(parser_node), build_identifier(parser_node))));
nodes::Expression(nodes::NameExpression(build_node(parser_node),
build_identifier(parser_node)),
is_scoped));
case tokens::Type::CONSTRUCTOR:
return expression_storage.add_expression(nodes::Expression(
build_constructor(parser_node, expression_storage, type_storage)));
build_constructor(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::LAMBDA:
return expression_storage.add_expression(nodes::Expression(
build_lambda(parser_node, expression_storage, type_storage)));
build_lambda(parser_node, expression_storage, type_storage),
is_scoped));
// --- literals
case tokens::Type::FLOAT_NUMBER_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_float_number_literal(parser_node)));
nodes::Expression(build_float_number_literal(parser_node), is_scoped));
case tokens::Type::NUMBER_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_number_literal(parser_node)));
nodes::Expression(build_number_literal(parser_node), is_scoped));
case tokens::Type::STRING_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_string_literal(parser_node)));
nodes::Expression(build_string_literal(parser_node), is_scoped));
case tokens::Type::CHAR_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_char_literal(parser_node)));
nodes::Expression(build_char_literal(parser_node), is_scoped));
case tokens::Type::BOOL_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_bool_literal(parser_node)));
nodes::Expression(build_bool_literal(parser_node), is_scoped));
case tokens::Type::UNIT_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_unit_literal(parser_node)));
nodes::Expression(build_unit_literal(parser_node), is_scoped));
case tokens::Type::NULL_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_null_literal(parser_node)));
nodes::Expression(build_null_literal(parser_node), is_scoped));
default:
error_handling::handle_parsing_error("Unexprected expression node type",
parser_node);
@ -370,7 +385,7 @@ nodes::Access build_tuple_access(parser::ParseTree::Node parser_node,
build_expression(parser_node.nth_named_child(0), expression_storage,
type_storage),
expression_storage.add_expression(nodes::Expression(
build_number_literal(parser_node.nth_named_child(1)))));
build_number_literal(parser_node.nth_named_child(1)), false)));
}
// 'break' | 'continue'

View file

@ -7,23 +7,194 @@
namespace printers {
void print_expression(const nodes::Expression &expression,
printers::Printer &printer) {} // IN PROGRESS
printers::Printer &printer) {
if (expression.is_scoped()) {
printer.print("(");
}
switch (expression.get_any()->index()) {
// --- flow control
case 0: // Match
print_match(*expression.get<nodes::Match>().value(), printer);
break;
case 1: // Condition
print_condition(*expression.get<nodes::Condition>().value(), printer);
break;
case 2: // Loop
print_loop(*expression.get<nodes::Loop>().value(), printer);
break;
// --- containers
case 3: // Container
print_container(*expression.get<nodes::Container>().value(), printer);
break;
// --- modifiers
case 4: // Return
print_return(*expression.get<nodes::Return>().value(), printer);
break;
case 5: // NameDefinition
print_name_definition(*expression.get<nodes::NameDefinition>().value(),
printer);
break;
case 6: // Access
print_access(*expression.get<nodes::Access>().value(), printer);
break;
case 7: // LoopControl
print_loop_control(*expression.get<nodes::LoopControl>().value(), printer);
break;
case 8: // ModifierExpression
print_modifier_expression(
*expression.get<nodes::ModifierExpression>().value(), printer);
break;
// --- other
case 9: // NameExpression
print_name_expression(*expression.get<nodes::NameExpression>().value(),
printer);
break;
case 10: // Constructor
print_constructor(*expression.get<nodes::Constructor>().value(), printer);
break;
case 11: // Lambda
print_lambda(*expression.get<nodes::Lambda>().value(), printer);
break;
// --- literal
case 12: // Literal
print_literal(*expression.get<nodes::Literal>().value(), printer);
break;
}
if (expression.is_scoped()) {
printer.print(")");
}
}
// --- flow control
void print_case(const nodes::Match::Case &expression, Printer &printer) {
switch (expression.case_type()) {
case nodes::Match::Case::PATTERN_VALUE:
printer.print(":=");
break;
case nodes::Match::Case::VALUE_PATTERN:
printer.print("=:");
break;
}
printer.space();
print_expression(*expression.get_value(), printer);
if (expression.get_condition().has_value()) {
printer.print(printer.print_words_instead_of_symbols() ? " if " : " ?? ");
print_expression(*expression.get_condition().value(), printer);
}
if (expression.get_expression().has_value()) {
printer.print(printer.print_words_instead_of_symbols() ? " do " : " => ");
print_expression(*expression.get_expression().value(), printer);
}
} // IN PROGRESS
void print_match(const nodes::Match &expression, printers::Printer &printer) {
print_expression(*expression.get_value(), printer);
printer.space();
size_t indentation = printer.get_current_position();
for (size_t i = 0; i < expression.cases_size(); ++i) {
print_case(*expression.get_case(i), printer);
if (i + 1 < expression.cases_size()) {
printer.new_line(indentation);
}
}
} // IN PROGRESS
void print_condition(const nodes::Condition &expression,
printers::Printer &printer) {} // IN PROGRESS
printers::Printer &printer) {
for (size_t i = 0; i < expression.cases_size(); ++i) {
if (i == 0) {
printer.print(printer.print_words_instead_of_symbols() ? "if " : "?? ");
} else {
printer.print(printer.print_words_instead_of_symbols() ? "elif " : "!! ");
}
print_expression(*expression.get_case(i).first, printer);
printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> ");
print_expression(*expression.get_case(i).second, printer);
}
if (expression.get_else_case().has_value()) {
printer.print(printer.print_words_instead_of_symbols() ? "else " : "!!=> ");
print_expression(*expression.get_else_case().value(), printer);
}
}
void print_loop(const nodes::Loop &expression, printers::Printer &printer) {
printer.print(printer.print_words_instead_of_symbols() ? "for " : "@");
switch (expression.get_type()) {
case nodes::Loop::LOOP:
printer.space();
break;
case nodes::Loop::WHILE:
printer.space();
print_expression(*expression.get_condition().value(), printer);
printer.space();
break;
case nodes::Loop::FOR:
printer.space();
print_expression(*expression.get_variable().value(), printer);
printer.print(" : ");
print_expression(*expression.get_interval().value(), printer);
printer.space();
break;
}
printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> ");
print_expression(*expression.get_expression(), printer);
printer.print(";");
} // IN PROGRESS
// --- containers
void print_container(const nodes::Container &expression,
printers::Printer &printer) {} // IN PROGRESS
printers::Printer &printer) {
bool is_array = expression.get_type() == nodes::Container::ARRAY;
if (is_array) {
printer.print("[[");
} else {
printer.print("{");
printer.indent();
printer.new_indent_line();
}
for (size_t i = 0; i < expression.expressions_size(); ++i) {
print_expression(*expression.get_expression(i), printer);
if (is_array) {
printer.space();
} else {
printer.print(";");
printer.new_indent_line();
}
}
if (is_array) {
printer.print("]]");
} else {
printer.deindent();
printer.print("}");
printer.new_indent_line();
}
} // IN PROGRESS
// --- modifiers
@ -78,10 +249,10 @@ void print_access(const nodes::Access &expression, printers::Printer &printer) {
switch (expression.get_type()) {
case nodes::Access::ARRAY:
printer.print('[');
printer.print("[");
break;
case nodes::Access::TUPLE:
printer.print('.');
printer.print(".");
break;
default:
break;
@ -91,7 +262,7 @@ void print_access(const nodes::Access &expression, printers::Printer &printer) {
switch (expression.get_type()) {
case nodes::Access::ARRAY:
printer.print(']');
printer.print("]");
break;
case nodes::Access::TUPLE:
break;
@ -151,10 +322,10 @@ void print_modifier_expression(const nodes::ModifierExpression &expression,
switch (expression.get_modifier()) {
case nodes::Modifier::OR_FALSE:
printer.print('?');
printer.print("?");
break;
case nodes::Modifier::OR_RETURN:
printer.print('!');
printer.print("!");
break;
default:
break;
@ -168,13 +339,13 @@ void print_name_expression(const nodes::NameExpression &expression,
if (expression.is_operator_call() || expression.is_point_call()) {
print_expression(*expression.get_argument_value(0), printer);
if (expression.is_point_call()) {
printer.print('.');
printer.print(".");
} else {
printer.space();
}
} else if (expression.get_prefix().has_value()) {
print_type(*expression.get_prefix().value(), printer);
printer.print('.');
printer.print(".");
}
print_identifier(*expression.get_name(), printer);
@ -216,7 +387,7 @@ void print_lambda(const nodes::Lambda &expression, printers::Printer &printer) {
printer.space();
}
printer.print(printer.print_words_instead_of_symbols() ? "do " : "-> ");
printer.print(printer.print_words_instead_of_symbols() ? "do " : "=> ");
print_expression(*expression.get_expression(), printer);

View file

@ -6,25 +6,25 @@ namespace printers {
void print_type(const nodes::Type &type, printers::Printer &printer) {
if (type.is_on_heap()) {
printer.print('^');
printer.print("^");
}
printer.print(type.get_name());
print_identifier(*type.get_name(), printer);
if (type.is_optional()) {
printer.print('?');
printer.print("?");
}
if (type.is_result()) {
printer.print('!');
printer.print("!");
}
printer.print('[');
printer.print("[");
for (size_t i = 0; i < type.get_parametrs_size(); ++i) {
print_type(*type.get_parameter(i), printer);
printer.space();
}
printer.print(']');
printer.print("]");
}
void print_tuple_type(const nodes::TupleType &type,
@ -53,7 +53,7 @@ void print_variant_type(const nodes::VariantType &type,
print_tuple_type(*type.get(i), printer);
if (i + 1 < type.size()) {
printer.new_line();
printer.new_indent_line();
}
}
} // IN PROGRESS