#include "basic_builders.hpp" #include "basic_nodes.hpp" #include "error_handling.hpp" #include "tokens.hpp" #include "tree_sitter_wrapper.hpp" namespace builders { namespace utils { std::optional to_escape_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 's': return ' '; default: return std::nullopt; } } } // namespace utils nodes::Modifier build_modifier(parser::ParseTree::Node parser_node) { std::string modifier = parser_node.get_value(); if (modifier == "?") { return nodes::Modifier::OR_FALSE; } else if (modifier == "!") { return nodes::Modifier::OR_RETURN; } else if (modifier == "->" || modifier == "out") { return nodes::Modifier::OUT; } else if (modifier == "<-" || modifier == "in") { return nodes::Modifier::IN; } else if (modifier == "<>" || modifier == "ref") { return nodes::Modifier::REF; } return nodes::Modifier::NONE; } nodes::Node build_node(parser::ParseTree::Node parser_node) { return nodes::Node(parser_node.get_start_point(), parser_node.get_end_point()); } // --- literals nodes::Literal build_float_number_literal(parser::ParseTree::Node parser_node) { return nodes::Literal(build_node(parser_node), std::stod(parser_node.get_value())); } nodes::Literal build_number_literal(parser::ParseTree::Node parser_node) { return nodes::Literal(build_node(parser_node), std::stoll(parser_node.get_value())); } nodes::Literal build_string_literal(parser::ParseTree::Node parser_node) { std::string literal = parser_node.get_value(); // remove " from both sides ("string") literal = literal.substr(1, literal.size() - 2); // replace escape sequences with escape characters bool is_escape_symbol = false; size_t j = 0; for (size_t i = 0; i < literal.size(); ++i, ++j) { if (literal[i] == '\\' && !is_escape_symbol) { is_escape_symbol = true; } else { if (is_escape_symbol) { --j; auto maybe_escape_symbol = utils::to_escape_symbol(literal[i]); if (maybe_escape_symbol.has_value()) { literal[j] = maybe_escape_symbol.value(); } else { literal[j] = literal[i]; } } else { if (j != i) { literal[j] = literal[i]; } } } } literal.resize(j); return nodes::Literal(build_node(parser_node), literal); } nodes::Literal build_char_literal(parser::ParseTree::Node parser_node) { std::string literal = parser_node.get_value(); // remove '' from both sides (''x'') literal = literal.substr(2, literal.size() - 4); char ch = '\0'; // replace escape sequence with escape character if (literal[0] == '\\') { auto maybe_escape_symbol = utils::to_escape_symbol(literal.back()); if (maybe_escape_symbol.has_value()) { ch = maybe_escape_symbol.value(); } else { ch = literal.back(); } } else { ch = literal.back(); } return nodes::Literal(build_node(parser_node), ch); } nodes::Literal build_bool_literal(parser::ParseTree::Node parser_node) { std::string literal = parser_node.get_value(); return nodes::Literal(build_node(parser_node), literal == "true" ? true : false); } nodes::Literal build_unit_literal(parser::ParseTree::Node parser_node) { return nodes::Literal(build_node(parser_node), nodes::unit{}); } nodes::Literal build_null_literal(parser::ParseTree::Node parser_node) { return nodes::Literal(build_node(parser_node), nodes::null{}); } // --- identifiers nodes::Identifier build_identifier(parser::ParseTree::Node parser_node) { tokens::Type type = tokens::string_to_type(parser_node.get_type()); switch (type) { case tokens::Type::PLACEHOLDER: return build_placeholder(parser_node); case tokens::Type::SIMPLE_NAME_IDENTIFIER: return build_simple_name(parser_node); case tokens::Type::SIMPLE_TYPE_IDENTIFIER: return build_simple_type(parser_node); case tokens::Type::TYPECLASS_IDENTIFIER: return build_typeclass(parser_node); case tokens::Type::ARGUMENT_NAME_IDENTIFIER: return build_argument_name(parser_node); case tokens::Type::ARGUMENT_TYPE_IDENTIFIER: return build_argument_type(parser_node); case tokens::Type::OPERATOR: case tokens::Type::OPERATOR_TAIL1: case tokens::Type::OPERATOR_TAIL2: case tokens::Type::OPERATOR_TAIL3: return build_operator(parser_node); // [used as string] // case tokens::Type::ANNOTATION_IDENTIFIER: // return build_annotation(parser_node); default: error_handling::handle_parsing_error("Unexprected identifier node type", parser_node); } error_handling::handle_general_error("Unreachable"); exit(1); // unreachable } nodes::Identifier build_simple_name(parser::ParseTree::Node parser_node) { return nodes::Identifier(build_node(parser_node), nodes::Identifier::SIMPLE_NAME, parser_node.get_value()); } nodes::Identifier build_simple_type(parser::ParseTree::Node parser_node) { return nodes::Identifier(build_node(parser_node), nodes::Identifier::SIMPLE_TYPE, parser_node.get_value()); } nodes::Identifier build_typeclass(parser::ParseTree::Node parser_node) { return nodes::Identifier(build_node(parser_node), nodes::Identifier::TYPECLASS, parser_node.get_value()); } nodes::Identifier build_argument_name(parser::ParseTree::Node parser_node) { return nodes::Identifier(build_node(parser_node), nodes::Identifier::ARGUMENT_NAME, parser_node.get_value()); } nodes::Identifier build_argument_type(parser::ParseTree::Node parser_node) { return nodes::Identifier(build_node(parser_node), nodes::Identifier::ARGUMENT_TYPE, parser_node.get_value()); } // Annotations are used as strings std::string build_annotation(parser::ParseTree::Node parser_node) { std::string identifier = parser_node.get_value(); // identifier.size() > 0 by parsing convention identifier = identifier.substr(1, identifier.size() - 1); return identifier; } nodes::Identifier build_operator(parser::ParseTree::Node parser_node) { std::string identifier = parser_node.get_value(); // --- points needed for proper printing // if (identifier.size() > 0 && identifier.front() != '.') { // // for not point only identifiers // while (identifier.size() > 0 && identifier.back() == '.') { // identifier.pop_back(); // } // } // --- return nodes::Identifier(build_node(parser_node), nodes::Identifier::OPERATOR, identifier); } nodes::Identifier build_placeholder(parser::ParseTree::Node parser_node) { return nodes::Identifier(build_node(parser_node), nodes::Identifier::PLACEHOLDER, "_"); } // --- empty lines nodes::EmptyLines build_empty_lines(parser::ParseTree::Node parser_node) { return nodes::EmptyLines(build_node(parser_node), parser_node.get_value_length() - 1); } } // namespace builders