mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-06 06:58:46 +00:00
186 lines
5.2 KiB
C++
186 lines
5.2 KiB
C++
#include "../include/basic_builders.hpp"
|
|
|
|
#include "basic_nodes.hpp"
|
|
|
|
namespace builders {
|
|
|
|
namespace utils {
|
|
std::optional<char> to_escape_symbol(char symbol) {
|
|
switch (symbol) {
|
|
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 's':
|
|
return ' ';
|
|
default:
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
} // namespace utils
|
|
|
|
nodes::Node buildNode(parser::ParseTree::Node parser_node) {
|
|
return nodes::Node(parser_node.get_start_point(),
|
|
parser_node.get_end_point());
|
|
}
|
|
|
|
// --- literals
|
|
|
|
nodes::Literal buildFloatNumberLiteral(parser::ParseTree::Node parser_node) {
|
|
return nodes::Literal(buildNode(parser_node),
|
|
std::stod(parser_node.get_value()));
|
|
}
|
|
|
|
nodes::Literal buildNumberLiteral(parser::ParseTree::Node parser_node) {
|
|
return nodes::Literal(buildNode(parser_node),
|
|
std::stoll(parser_node.get_value()));
|
|
}
|
|
|
|
nodes::Literal buildStringLiteral(parser::ParseTree::Node parser_node) {
|
|
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(buildNode(parser_node), literal);
|
|
}
|
|
|
|
nodes::Literal buildCharLiteral(parser::ParseTree::Node parser_node) {
|
|
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(buildNode(parser_node), ch);
|
|
}
|
|
|
|
nodes::Literal buildBoolLiteral(parser::ParseTree::Node parser_node) {
|
|
std::string literal = parser_node.get_value();
|
|
|
|
return nodes::Literal(buildNode(parser_node),
|
|
literal == "true" ? true : false);
|
|
}
|
|
|
|
nodes::Literal buildUnitLiteral(parser::ParseTree::Node parser_node) {
|
|
return nodes::Literal(buildNode(parser_node), nodes::unit{});
|
|
}
|
|
|
|
nodes::Literal buildNullLiteral(parser::ParseTree::Node parser_node) {
|
|
return nodes::Literal(buildNode(parser_node), nodes::null{});
|
|
}
|
|
|
|
// --- identifiers
|
|
|
|
nodes::Identifier buildSimpleName(parser::ParseTree::Node parser_node) {
|
|
return nodes::Identifier(buildNode(parser_node),
|
|
nodes::Identifier::SIMPLE_NAME,
|
|
parser_node.get_value());
|
|
}
|
|
|
|
nodes::Identifier buildSimpleType(parser::ParseTree::Node parser_node) {
|
|
return nodes::Identifier(buildNode(parser_node),
|
|
nodes::Identifier::SIMPLE_TYPE,
|
|
parser_node.get_value());
|
|
}
|
|
|
|
nodes::Identifier buildTypeclass(parser::ParseTree::Node parser_node) {
|
|
return nodes::Identifier(buildNode(parser_node), nodes::Identifier::TYPECLASS,
|
|
parser_node.get_value());
|
|
}
|
|
|
|
nodes::Identifier buildArgumentName(parser::ParseTree::Node parser_node) {
|
|
return nodes::Identifier(buildNode(parser_node),
|
|
nodes::Identifier::ARGUMENT_NAME,
|
|
parser_node.get_value());
|
|
}
|
|
|
|
nodes::Identifier buildArgumentType(parser::ParseTree::Node parser_node) {
|
|
return nodes::Identifier(buildNode(parser_node),
|
|
nodes::Identifier::ARGUMENT_TYPE,
|
|
parser_node.get_value());
|
|
}
|
|
|
|
// Annotations are used as strings
|
|
std::string buildAnnotation(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 buildOperator(parser::ParseTree::Node parser_node) {
|
|
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(buildNode(parser_node), nodes::Identifier::OPERATOR,
|
|
identifier);
|
|
}
|
|
|
|
nodes::Identifier buildPlaceholder(parser::ParseTree::Node parser_node) {
|
|
return nodes::Identifier(buildNode(parser_node),
|
|
nodes::Identifier::PLACEHOLDER, "_");
|
|
}
|
|
|
|
} // namespace builders
|