lang/src/basic_builders.cpp

244 lines
7.1 KiB
C++
Raw Normal View History

2023-07-23 19:40:27 +03:00
#include "basic_builders.hpp"
2023-07-20 14:38:44 +03:00
#include "basic_nodes.hpp"
2023-07-23 19:40:27 +03:00
#include "error_handling.hpp"
#include "tokens.hpp"
#include "tree_sitter_wrapper.hpp"
2023-07-20 14:38:44 +03:00
namespace builders {
namespace utils {
std::optional<char> to_escape_symbol(char ch) {
switch (ch) {
2023-07-20 14:38:44 +03:00
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';
2023-07-24 21:23:18 +03:00
case '\'':
return '\'';
case '\"':
return '\"';
2023-07-20 14:38:44 +03:00
case 's':
return ' ';
default:
return std::nullopt;
}
}
} // namespace utils
2023-07-23 19:40:27 +03:00
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;
2023-07-23 19:40:27 +03:00
} 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) {
2023-07-20 14:38:44 +03:00
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),
2023-07-20 14:38:44 +03:00
std::stod(parser_node.get_value()));
}
nodes::Literal build_number_literal(parser::ParseTree::Node parser_node) {
return nodes::Literal(build_node(parser_node),
2023-07-20 14:38:44 +03:00
std::stoll(parser_node.get_value()));
}
nodes::Literal build_string_literal(parser::ParseTree::Node parser_node) {
2023-07-20 14:38:44 +03:00
std::string literal = parser_node.get_value();
// remove " from both sides ("string")
literal.pop_back();
literal = literal.substr(1, literal.size() - 1);
// 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);
2023-07-20 14:38:44 +03:00
}
nodes::Literal build_char_literal(parser::ParseTree::Node parser_node) {
2023-07-20 14:38:44 +03:00
std::string literal = parser_node.get_value();
// remove '' from both sides (''x'')
literal.pop_back();
literal.pop_back();
literal = literal.substr(1, literal.size() - 2);
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);
2023-07-20 14:38:44 +03:00
}
nodes::Literal build_bool_literal(parser::ParseTree::Node parser_node) {
2023-07-20 14:38:44 +03:00
std::string literal = parser_node.get_value();
return nodes::Literal(build_node(parser_node),
2023-07-20 14:38:44 +03:00
literal == "true" ? true : false);
}
nodes::Literal build_unit_literal(parser::ParseTree::Node parser_node) {
return nodes::Literal(build_node(parser_node), nodes::unit{});
2023-07-20 14:38:44 +03:00
}
nodes::Literal build_null_literal(parser::ParseTree::Node parser_node) {
return nodes::Literal(build_node(parser_node), nodes::null{});
2023-07-20 14:38:44 +03:00
}
// --- identifiers
2023-07-23 19:40:27 +03:00
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]
2023-07-23 19:40:27 +03:00
// 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),
2023-07-20 14:38:44 +03:00
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),
2023-07-20 14:38:44 +03:00
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,
2023-07-20 14:38:44 +03:00
parser_node.get_value());
}
nodes::Identifier build_argument_name(parser::ParseTree::Node parser_node) {
return nodes::Identifier(build_node(parser_node),
2023-07-20 14:38:44 +03:00
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),
2023-07-20 14:38:44 +03:00
nodes::Identifier::ARGUMENT_TYPE,
parser_node.get_value());
}
// Annotations are used as strings
std::string build_annotation(parser::ParseTree::Node parser_node) {
2023-07-20 14:38:44 +03:00
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) {
2023-07-20 14:38:44 +03:00
std::string identifier = parser_node.get_value();
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,
2023-07-20 14:38:44 +03:00
identifier);
}
nodes::Identifier build_placeholder(parser::ParseTree::Node parser_node) {
return nodes::Identifier(build_node(parser_node),
2023-07-20 14:38:44 +03:00
nodes::Identifier::PLACEHOLDER, "_");
}
} // namespace builders