mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-25 16:28:46 +00:00
folder structure refactoring
This commit is contained in:
parent
ef88e6af86
commit
78c696b99a
30 changed files with 40 additions and 22 deletions
294
src/builders/basic_builders.cpp
Normal file
294
src/builders/basic_builders.cpp
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
#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<char> 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::OPTIONAL;
|
||||
} else if (modifier == "!") {
|
||||
return nodes::Modifier::RESULT;
|
||||
} else if (modifier == "<-" || modifier == "in") {
|
||||
return nodes::Modifier::IN;
|
||||
} else if (modifier == "<>" || modifier == "ref") {
|
||||
return nodes::Modifier::REF;
|
||||
} else if (modifier == "--" || modifier == "const") {
|
||||
return nodes::Modifier::CONST;
|
||||
} else if (modifier == "->" || modifier == "out") {
|
||||
return nodes::Modifier::OUT;
|
||||
} else if (modifier == "<-|<>" || modifier == "in|ref") {
|
||||
return nodes::Modifier::IN_OR_REF;
|
||||
} else if (modifier == "<-|--" || modifier == "in|const") {
|
||||
return nodes::Modifier::IN_OR_CONST;
|
||||
} else if (modifier == "<>|->" || modifier == "ref|out") {
|
||||
return nodes::Modifier::REF_OR_OUT;
|
||||
} else if (modifier == "--|->" || modifier == "const|out") {
|
||||
return nodes::Modifier::CONST_OR_OUT;
|
||||
} else if (modifier == "<>|--" || modifier == "ref|const") {
|
||||
return nodes::Modifier::REF_OR_CONST;
|
||||
} else if (modifier == "<-|->" || modifier == "in|out") {
|
||||
return nodes::Modifier::IN_OR_OUT;
|
||||
} else if (modifier == "<-|<>|->" || modifier == "in|ref|out") {
|
||||
return nodes::Modifier::IN_OR_REF_OR_OUT;
|
||||
} else if (modifier == "<-|--|->" || modifier == "in|const|out") {
|
||||
return nodes::Modifier::IN_OR_CONST_OR_OUT;
|
||||
} else if (modifier == "<-|<>|--" || modifier == "in|ref|const") {
|
||||
return nodes::Modifier::IN_OR_REF_OR_CONST;
|
||||
} else if (modifier == "<>|--|->" || modifier == "ref|const|out") {
|
||||
return nodes::Modifier::REF_OR_CONST_OR_OUT;
|
||||
} else if (modifier == "<-|<>|--|->" || modifier == "in|ref|const|out") {
|
||||
return nodes::Modifier::IN_OR_REF_OR_CONST_OR_OUT;
|
||||
} else {
|
||||
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, "_");
|
||||
}
|
||||
|
||||
// --- extra
|
||||
|
||||
nodes::Extra build_extra(parser::ParseTree::Node parser_node) {
|
||||
return nodes::Extra(build_node(parser_node), parser_node.get_value());
|
||||
}
|
||||
|
||||
// --- empty lines
|
||||
|
||||
nodes::EmptyLines build_empty_lines(parser::ParseTree::Node parser_node) {
|
||||
std::string empty_lines = parser_node.get_value();
|
||||
|
||||
size_t empty_lines_count = 0;
|
||||
|
||||
for (auto &ch : empty_lines) {
|
||||
if (ch == '\n') {
|
||||
++empty_lines_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty_lines_count == 0) {
|
||||
error_handling::handle_parsing_error("Empty lines node with zero new lines",
|
||||
parser_node);
|
||||
}
|
||||
|
||||
return nodes::EmptyLines(build_node(parser_node), empty_lines_count - 1);
|
||||
}
|
||||
|
||||
} // namespace builders
|
||||
55
src/builders/doc_builders.cpp
Normal file
55
src/builders/doc_builders.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#include "doc_builders.hpp"
|
||||
#include "basic_builders.hpp"
|
||||
#include "doc_nodes.hpp"
|
||||
#include "error_handling.hpp"
|
||||
|
||||
namespace builders {
|
||||
|
||||
// TODO: check, that all annotations are exist in function definition
|
||||
nodes::SymbolDocs build_symbol_docs(
|
||||
std::optional<parser::ParseTree::Node> description_parser_node,
|
||||
const std::vector<parser::ParseTree::Node> &annotation_parser_nodes,
|
||||
const std::unordered_set<std::string> &annotations) {
|
||||
|
||||
std::optional<std::string> description;
|
||||
|
||||
if (description_parser_node.has_value()) {
|
||||
description = description_parser_node.value().get_value();
|
||||
|
||||
// remove newline delimeters (": " at each new line
|
||||
size_t j = 0;
|
||||
for (size_t i = 2; i < description.value().size(); ++i, ++j) {
|
||||
if (j != i) { // always true
|
||||
description.value()[j] = description.value()[i];
|
||||
}
|
||||
|
||||
if (description.value()[i] == '\n') {
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
description.value().resize(j);
|
||||
}
|
||||
|
||||
nodes::SymbolDocs docs = description.has_value()
|
||||
? nodes::SymbolDocs(description.value())
|
||||
: nodes::SymbolDocs();
|
||||
|
||||
for (auto &annotation_parser_node : annotation_parser_nodes) {
|
||||
std::string annotation =
|
||||
build_annotation(annotation_parser_node.nth_named_child(0));
|
||||
|
||||
if (annotations.count(annotation) == 0) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Annotation \"" + annotation +
|
||||
"\" doesn't present in corresponding symbol",
|
||||
annotation_parser_node);
|
||||
}
|
||||
|
||||
docs.add_annotation_info(
|
||||
annotation, annotation_parser_node.nth_named_child(1).get_value());
|
||||
}
|
||||
|
||||
return docs;
|
||||
}
|
||||
|
||||
} // namespace builders
|
||||
543
src/builders/expression_builders.cpp
Normal file
543
src/builders/expression_builders.cpp
Normal file
|
|
@ -0,0 +1,543 @@
|
|||
#include "expression_builders.hpp"
|
||||
|
||||
#include "basic_builders.hpp"
|
||||
#include "basic_nodes.hpp"
|
||||
#include "error_handling.hpp"
|
||||
#include "expression_nodes.hpp"
|
||||
#include "tokens.hpp"
|
||||
#include "type_builders.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
|
||||
namespace builders {
|
||||
|
||||
nodes::ExpressionProxy
|
||||
build_expression(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
||||
|
||||
auto maybe_parenthesis = parser_node.previous_sibling();
|
||||
bool is_scoped =
|
||||
(!maybe_parenthesis.is_null() && !maybe_parenthesis.is_named() &&
|
||||
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), is_scoped));
|
||||
case tokens::Type::CONDITION:
|
||||
return expression_storage.add_expression(nodes::Expression(
|
||||
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), is_scoped));
|
||||
// --- operators
|
||||
case tokens::Type::COMMA_EXPRESSION:
|
||||
return expression_storage.add_expression(nodes::Expression(
|
||||
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),
|
||||
is_scoped));
|
||||
// --- containers
|
||||
case tokens::Type::BLOCK:
|
||||
return expression_storage.add_expression(nodes::Expression(
|
||||
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), is_scoped));
|
||||
// --- modifiers
|
||||
case tokens::Type::RETURN:
|
||||
return expression_storage.add_expression(nodes::Expression(
|
||||
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), is_scoped));
|
||||
case tokens::Type::ARRAY_ACCESS:
|
||||
return expression_storage.add_expression(nodes::Expression(
|
||||
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),
|
||||
is_scoped));
|
||||
case tokens::Type::LOOP_CONTROL:
|
||||
return expression_storage.add_expression(
|
||||
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),
|
||||
is_scoped));
|
||||
case tokens::Type::SUFFIX_EXPRESSION:
|
||||
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),
|
||||
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)),
|
||||
is_scoped));
|
||||
case tokens::Type::CONSTRUCTOR:
|
||||
return expression_storage.add_expression(nodes::Expression(
|
||||
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),
|
||||
is_scoped));
|
||||
// --- literals
|
||||
case tokens::Type::FLOAT_NUMBER_LITERAL:
|
||||
return expression_storage.add_expression(
|
||||
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), is_scoped));
|
||||
case tokens::Type::STRING_LITERAL:
|
||||
return expression_storage.add_expression(
|
||||
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), is_scoped));
|
||||
case tokens::Type::BOOL_LITERAL:
|
||||
return expression_storage.add_expression(
|
||||
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), is_scoped));
|
||||
case tokens::Type::NULL_LITERAL:
|
||||
return expression_storage.add_expression(
|
||||
nodes::Expression(build_null_literal(parser_node), is_scoped));
|
||||
case tokens::Type::EXTRA:
|
||||
return expression_storage.add_expression(
|
||||
nodes::Expression(build_extra(parser_node), is_scoped));
|
||||
case tokens::Type::EMPTY_LINES:
|
||||
return expression_storage.add_expression(
|
||||
nodes::Expression(build_empty_lines(parser_node), is_scoped));
|
||||
default:
|
||||
error_handling::handle_parsing_error("Unexprected expression node type",
|
||||
parser_node);
|
||||
}
|
||||
error_handling::handle_general_error("Unreachable");
|
||||
exit(1); // unreachable
|
||||
}
|
||||
|
||||
// --- flow control
|
||||
|
||||
// (':=' | '=:') expression (('??' | 'if') expression)? (_do_ expression)?
|
||||
nodes::Match::Case build_case(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::string case_type = parser_node.nth_child(0).get_value();
|
||||
|
||||
std::optional<parser::ParseTree::Node> condition_node;
|
||||
std::optional<parser::ParseTree::Node> expression_node;
|
||||
|
||||
auto current_node = parser_node.nth_named_child(1);
|
||||
|
||||
if (!current_node.is_null()) {
|
||||
if (parser_node.child_by_field_name("condition").is_null()) {
|
||||
expression_node = current_node;
|
||||
} else {
|
||||
condition_node = current_node;
|
||||
current_node = current_node.next_named_sibling();
|
||||
if (!current_node.is_null()) {
|
||||
expression_node = current_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodes::Match::Case(
|
||||
build_node(parser_node),
|
||||
case_type == ":=" ? nodes::Match::Case::PATTERN_VALUE
|
||||
: nodes::Match::Case::VALUE_PATTERN,
|
||||
build_expression(parser_node.nth_named_child(0), expression_storage,
|
||||
type_storage),
|
||||
condition_node.has_value()
|
||||
? build_expression(condition_node.value(), expression_storage,
|
||||
type_storage)
|
||||
: std::optional<nodes::ExpressionProxy>(),
|
||||
expression_node.has_value()
|
||||
? build_expression(expression_node.value(), expression_storage,
|
||||
type_storage)
|
||||
: std::optional<nodes::ExpressionProxy>());
|
||||
}
|
||||
|
||||
// expression case+
|
||||
nodes::Match build_match(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::vector<nodes::Match::Case> cases;
|
||||
|
||||
auto current_node = parser_node.nth_named_child(1);
|
||||
while (!current_node.is_null()) {
|
||||
cases.push_back(build_case(current_node, expression_storage, type_storage));
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return nodes::Match(build_node(parser_node),
|
||||
build_expression(parser_node.nth_named_child(0),
|
||||
expression_storage, type_storage),
|
||||
std::move(cases));
|
||||
}
|
||||
|
||||
// ('??' | 'if') expression _do_ expression (('!!' | 'elif') expression _do_
|
||||
// expression)* (('!!=>', 'else') expression)?
|
||||
nodes::Condition build_condition(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
size_t named_child_count = parser_node.named_child_count();
|
||||
|
||||
std::vector<std::pair<nodes::ExpressionProxy, nodes::ExpressionProxy>> cases;
|
||||
|
||||
auto current_node = parser_node.nth_named_child(0);
|
||||
auto next_node = current_node.next_named_sibling();
|
||||
|
||||
while (!current_node.is_null() && !next_node.is_null()) {
|
||||
cases.push_back(
|
||||
{build_expression(current_node, expression_storage, type_storage),
|
||||
build_expression(next_node, expression_storage, type_storage)});
|
||||
current_node = next_node.next_named_sibling();
|
||||
if (current_node.is_null()) {
|
||||
break;
|
||||
}
|
||||
next_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return nodes::Condition(
|
||||
build_node(parser_node), std::move(cases),
|
||||
named_child_count % 2 == 1
|
||||
? build_expression(parser_node.nth_named_child(named_child_count - 1),
|
||||
expression_storage, type_storage)
|
||||
: std::optional<nodes::ExpressionProxy>());
|
||||
}
|
||||
|
||||
// ('@' | 'for') (expression | expression ':' expression)? _do_ expression
|
||||
nodes::Loop build_loop(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
size_t named_child_count = parser_node.named_child_count();
|
||||
|
||||
if (named_child_count == 1) { // body
|
||||
return nodes::Loop(build_node(parser_node),
|
||||
build_expression(parser_node.nth_named_child(0),
|
||||
expression_storage, type_storage));
|
||||
} else if (named_child_count == 2) { // condition, body
|
||||
return nodes::Loop(build_node(parser_node),
|
||||
build_expression(parser_node.nth_named_child(0),
|
||||
expression_storage, type_storage),
|
||||
build_expression(parser_node.nth_named_child(1),
|
||||
expression_storage, type_storage));
|
||||
} else if (named_child_count == 3) { // variable, interval, body
|
||||
return nodes::Loop(build_node(parser_node),
|
||||
build_expression(parser_node.nth_named_child(0),
|
||||
expression_storage, type_storage),
|
||||
build_expression(parser_node.nth_named_child(1),
|
||||
expression_storage, type_storage),
|
||||
build_expression(parser_node.nth_named_child(2),
|
||||
expression_storage, type_storage));
|
||||
} else {
|
||||
error_handling::handle_parsing_error(
|
||||
"Unexprected named expression amount in loop", parser_node);
|
||||
}
|
||||
|
||||
error_handling::handle_general_error("Unreachable");
|
||||
exit(1); // unreachable
|
||||
}
|
||||
|
||||
// --- operators
|
||||
|
||||
// expression ',' expression
|
||||
nodes::NameExpression
|
||||
build_comma_expression(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::vector<std::pair<std::optional<std::string>, nodes::ExpressionProxy>>
|
||||
arguments;
|
||||
|
||||
arguments.emplace_back(std::nullopt,
|
||||
build_expression(parser_node.nth_named_child(0),
|
||||
expression_storage, type_storage));
|
||||
|
||||
arguments.emplace_back(std::nullopt,
|
||||
build_expression(parser_node.nth_named_child(1),
|
||||
expression_storage, type_storage));
|
||||
|
||||
return nodes::NameExpression(
|
||||
build_node(parser_node),
|
||||
nodes::Identifier(
|
||||
build_node(parser_node), // can't find more precise location
|
||||
nodes::Identifier::SIMPLE_NAME, ","),
|
||||
std::move(arguments), std::nullopt, false, true);
|
||||
}
|
||||
|
||||
// expression operator expression
|
||||
nodes::NameExpression
|
||||
build_operator_expression(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
auto name_node = parser_node.child_by_field_name("name");
|
||||
|
||||
std::vector<std::pair<std::optional<std::string>, nodes::ExpressionProxy>>
|
||||
arguments;
|
||||
|
||||
arguments.emplace_back(std::nullopt,
|
||||
build_expression(name_node.previous_named_sibling(),
|
||||
expression_storage, type_storage));
|
||||
|
||||
arguments.emplace_back(std::nullopt,
|
||||
build_expression(name_node.next_named_sibling(),
|
||||
expression_storage, type_storage));
|
||||
|
||||
return nodes::NameExpression(build_node(parser_node),
|
||||
build_operator(name_node), std::move(arguments),
|
||||
std::nullopt, false, true);
|
||||
}
|
||||
|
||||
// --- continers
|
||||
|
||||
nodes::Container
|
||||
build_container(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage,
|
||||
nodes::Container::ContainerType container_type) {
|
||||
std::vector<nodes::ExpressionProxy> expressions;
|
||||
|
||||
auto current_node = parser_node.nth_named_child(0);
|
||||
|
||||
while (!current_node.is_null()) {
|
||||
expressions.push_back(
|
||||
build_expression(current_node, expression_storage, type_storage));
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return nodes::Container(build_node(parser_node), container_type,
|
||||
std::move(expressions));
|
||||
}
|
||||
|
||||
// '{' (expression ';')* '}'
|
||||
nodes::Container build_block(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return build_container(parser_node, expression_storage, type_storage,
|
||||
nodes::Container::BLOCK);
|
||||
}
|
||||
|
||||
// '[[' expression+ ']]'
|
||||
nodes::Container build_array(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return build_container(parser_node, expression_storage, type_storage,
|
||||
nodes::Container::ARRAY);
|
||||
}
|
||||
|
||||
// --- modifiers
|
||||
|
||||
// ('return' | 'bring') expression
|
||||
nodes::Return build_return(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::string modifier = parser_node.nth_child(0).get_value();
|
||||
|
||||
return nodes::Return(build_node(parser_node),
|
||||
modifier == "return" ? nodes::Return::RETURN
|
||||
: nodes::Return::BRING,
|
||||
build_expression(parser_node.nth_named_child(0),
|
||||
expression_storage, type_storage));
|
||||
}
|
||||
|
||||
// _var_let_ (simple_name_identifier | placeholder)
|
||||
nodes::NameDefinition
|
||||
build_name_definition(parser::ParseTree::Node parser_node) {
|
||||
std::string modifier = parser_node.nth_child(0).get_value();
|
||||
|
||||
auto name_node = parser_node.nth_named_child(0);
|
||||
|
||||
return nodes::NameDefinition(build_node(parser_node),
|
||||
(modifier == "%" || modifier == "let")
|
||||
? nodes::NameDefinition::LET
|
||||
: nodes::NameDefinition::VAR,
|
||||
build_identifier(name_node));
|
||||
} // IN PROGRESS
|
||||
|
||||
// expression '[' expression ']'
|
||||
nodes::Access build_array_access(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return nodes::Access(build_node(parser_node), nodes::Access::ARRAY,
|
||||
build_expression(parser_node.nth_named_child(0),
|
||||
expression_storage, type_storage),
|
||||
build_expression(parser_node.nth_named_child(1),
|
||||
expression_storage, type_storage));
|
||||
}
|
||||
|
||||
// expression '.' number_literal
|
||||
nodes::Access build_tuple_access(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return nodes::Access(
|
||||
build_node(parser_node), nodes::Access::TUPLE,
|
||||
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)), false)));
|
||||
}
|
||||
|
||||
// 'break' | 'continue'
|
||||
nodes::LoopControl build_loop_control(parser::ParseTree::Node parser_node) {
|
||||
return nodes::LoopControl(build_node(parser_node),
|
||||
parser_node.get_value() == "break"
|
||||
? nodes::LoopControl::BREAK
|
||||
: nodes::LoopControl::CONTINUE);
|
||||
}
|
||||
|
||||
nodes::ModifierExpression
|
||||
build_modifier_expression(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage,
|
||||
size_t modifier_position) {
|
||||
|
||||
return nodes::ModifierExpression(
|
||||
build_node(parser_node),
|
||||
build_modifier(parser_node.nth_child(modifier_position)),
|
||||
build_expression(parser_node.nth_named_child(0), expression_storage,
|
||||
type_storage));
|
||||
}
|
||||
|
||||
// _reference_ expression
|
||||
nodes::ModifierExpression
|
||||
build_reference_expression(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return build_modifier_expression(parser_node, expression_storage,
|
||||
type_storage, 0);
|
||||
}
|
||||
|
||||
// expression ('?' | '!')
|
||||
nodes::ModifierExpression
|
||||
build_suffix_expression(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return build_modifier_expression(parser_node, expression_storage,
|
||||
type_storage, parser_node.child_count() - 1);
|
||||
}
|
||||
|
||||
// --- other
|
||||
|
||||
void build_arguments_until_end(
|
||||
parser::ParseTree::Node first_parse_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage,
|
||||
std::vector<std::pair<std::optional<std::string>, nodes::ExpressionProxy>>
|
||||
&arguments) {
|
||||
|
||||
auto current_node = first_parse_node;
|
||||
|
||||
std::optional<std::string> last_annotation;
|
||||
while (!current_node.is_null()) {
|
||||
if (tokens::string_to_type(current_node.get_type()) ==
|
||||
tokens::Type::ANNOTATION_IDENTIFIER) {
|
||||
last_annotation = build_annotation(current_node);
|
||||
} else {
|
||||
arguments.emplace_back(
|
||||
std::move(last_annotation),
|
||||
build_expression(current_node, expression_storage, type_storage));
|
||||
last_annotation = std::nullopt;
|
||||
}
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
}
|
||||
|
||||
// (type '.' simple_name | expression '.' simple_name | name | '(' operator
|
||||
// ')') (annotation? expression)*
|
||||
nodes::NameExpression
|
||||
build_name_expression(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::vector<std::pair<std::optional<std::string>, nodes::ExpressionProxy>>
|
||||
arguments;
|
||||
|
||||
std::optional<nodes::Type> prefix;
|
||||
|
||||
bool is_point_call = false;
|
||||
|
||||
auto name_node = parser_node.child_by_field_name("name");
|
||||
|
||||
std::optional<parser::ParseTree::Node> prefix_node;
|
||||
|
||||
auto current_node = name_node.previous_named_sibling();
|
||||
if (!current_node.is_null()) {
|
||||
if (tokens::string_to_type(current_node.get_type()) == tokens::Type::TYPE) {
|
||||
prefix_node = current_node;
|
||||
} else {
|
||||
is_point_call = true;
|
||||
arguments.emplace_back(
|
||||
std::nullopt,
|
||||
build_expression(current_node, expression_storage, type_storage));
|
||||
}
|
||||
}
|
||||
|
||||
build_arguments_until_end(name_node.next_named_sibling(), expression_storage,
|
||||
type_storage, arguments);
|
||||
|
||||
return nodes::NameExpression(
|
||||
build_node(parser_node), build_identifier(name_node),
|
||||
std::move(arguments),
|
||||
prefix_node.has_value() ? build_type(prefix_node.value(), type_storage)
|
||||
: std::optional<nodes::TypeProxy>(),
|
||||
is_point_call, false);
|
||||
}
|
||||
|
||||
// type (annotation? expression)*
|
||||
nodes::Constructor
|
||||
build_constructor(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::vector<std::pair<std::optional<std::string>, nodes::ExpressionProxy>>
|
||||
arguments;
|
||||
|
||||
build_arguments_until_end(
|
||||
parser_node.child_by_field_name("type").next_named_sibling(),
|
||||
expression_storage, type_storage, arguments);
|
||||
|
||||
return nodes::Constructor(
|
||||
build_node(parser_node),
|
||||
build_type(parser_node.child_by_field_name("type"), type_storage),
|
||||
std::move(arguments));
|
||||
}
|
||||
|
||||
// '\\' argument_name* _do_ expression
|
||||
nodes::Lambda build_lambda(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::vector<nodes::Identifier> arguments;
|
||||
|
||||
auto current_node =
|
||||
parser_node.nth_child(1); // next to '\\', not null ('=>' should present)
|
||||
|
||||
while (current_node.is_named()) { // until _do_
|
||||
arguments.emplace_back(build_identifier(current_node));
|
||||
current_node = current_node.next_sibling();
|
||||
}
|
||||
|
||||
// skip '=>'
|
||||
current_node = current_node.next_named_sibling();
|
||||
|
||||
return nodes::Lambda(
|
||||
build_node(parser_node), std::move(arguments),
|
||||
build_expression(current_node, expression_storage, type_storage));
|
||||
}
|
||||
|
||||
} // namespace builders
|
||||
462
src/builders/statement_builders.cpp
Normal file
462
src/builders/statement_builders.cpp
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
#include "statement_builders.hpp"
|
||||
|
||||
#include "basic_builders.hpp"
|
||||
#include "basic_nodes.hpp"
|
||||
#include "doc_builders.hpp"
|
||||
#include "doc_nodes.hpp"
|
||||
#include "error_handling.hpp"
|
||||
#include "expression_builders.hpp"
|
||||
#include "statement_nodes.hpp"
|
||||
#include "tokens.hpp"
|
||||
#include "tree_sitter_wrapper.hpp"
|
||||
#include "type_builders.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace builders {
|
||||
|
||||
// statement+
|
||||
std::vector<nodes::Statement>
|
||||
build_source_file(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree) {
|
||||
std::vector<nodes::Statement> statements;
|
||||
|
||||
std::optional<nodes::Identifier> last_defined_type_name;
|
||||
|
||||
auto current_node = parser_node.nth_named_child(0);
|
||||
while (!current_node.is_null()) {
|
||||
statements.push_back(build_statement(current_node, last_defined_type_name,
|
||||
expression_storage, type_storage,
|
||||
name_tree));
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return statements;
|
||||
}
|
||||
|
||||
// import | type_definition | function_definition | typeclass_definition
|
||||
nodes::Statement
|
||||
build_statement(parser::ParseTree::Node parser_node,
|
||||
std::optional<nodes::Identifier> &last_defined_type_name,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage, names::NameTree &name_tree) {
|
||||
tokens::Type type = tokens::string_to_type(parser_node.get_type());
|
||||
|
||||
std::optional<std::string> statement_name;
|
||||
std::optional<nodes::Statement> statement;
|
||||
|
||||
switch (type) {
|
||||
case tokens::Type::IMPORT:
|
||||
statement = nodes::Statement(build_import(parser_node));
|
||||
statement_name = *statement.value()
|
||||
.get<nodes::Import>()
|
||||
.value()
|
||||
->get_module_name()
|
||||
->get();
|
||||
break;
|
||||
case tokens::Type::TYPE_DEFINITION:
|
||||
statement =
|
||||
nodes::Statement(build_type_definition(parser_node, type_storage));
|
||||
last_defined_type_name =
|
||||
*statement.value().get<nodes::TypeDefinition>().value()->get_name();
|
||||
statement_name = *statement.value()
|
||||
.get<nodes::TypeDefinition>()
|
||||
.value()
|
||||
->get_name()
|
||||
->get();
|
||||
break;
|
||||
case tokens::Type::FUNCTION_DEFINITION:
|
||||
statement = nodes::Statement(build_function_definition(
|
||||
parser_node, last_defined_type_name, expression_storage, type_storage));
|
||||
statement_name = *statement.value()
|
||||
.get<nodes::FunctionDefinition>()
|
||||
.value()
|
||||
->get_full_name()
|
||||
->get();
|
||||
break;
|
||||
case tokens::Type::EXTRA:
|
||||
statement = nodes::Statement(build_extra(parser_node));
|
||||
break;
|
||||
case tokens::Type::EMPTY_LINES:
|
||||
statement = nodes::Statement(build_empty_lines(parser_node));
|
||||
break;
|
||||
default:
|
||||
error_handling::handle_parsing_error("Unexprected statement node type",
|
||||
parser_node);
|
||||
}
|
||||
|
||||
if (!statement.has_value()) {
|
||||
error_handling::handle_general_error("Unreachable");
|
||||
}
|
||||
|
||||
if (statement_name.has_value()) {
|
||||
auto statement_copy = statement.value();
|
||||
if (name_tree
|
||||
.insert_combine(statement_name.value(), std::move(statement_copy))
|
||||
.second != nodes::CombineResult::OK) {
|
||||
// TODO: more detailed errors
|
||||
error_handling::handle_parsing_error(
|
||||
"Can't combine statements with same name", parser_node);
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(statement.value());
|
||||
}
|
||||
|
||||
// ('::' | 'import') simple_name ('=' simple_name)? (':' identifier*)?
|
||||
nodes::Import build_import(parser::ParseTree::Node parser_node) {
|
||||
|
||||
auto name_node = parser_node.child_by_field_name("name");
|
||||
auto module_node = parser_node.child_by_field_name("module");
|
||||
if (module_node.is_null()) {
|
||||
module_node = name_node;
|
||||
}
|
||||
|
||||
std::vector<nodes::Identifier> symbols;
|
||||
|
||||
auto current_node = module_node.next_named_sibling();
|
||||
while (!current_node.is_null()) {
|
||||
symbols.push_back(build_identifier(current_node));
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return nodes::Import(build_node(parser_node), build_identifier(name_node),
|
||||
build_identifier(module_node), std::move(symbols));
|
||||
}
|
||||
|
||||
// '?' expression
|
||||
nodes::Constraint build_constraint(parser::ParseTree::Node parser_node,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
return nodes::Constraint(build_node(parser_node),
|
||||
build_expression(parser_node.nth_named_child(0),
|
||||
expression_storage, type_storage));
|
||||
}
|
||||
|
||||
parser::ParseTree::Node collect_symbol_doc_nodes(
|
||||
parser::ParseTree::Node start_parser_node,
|
||||
std::optional<parser::ParseTree::Node> &description_node,
|
||||
std::vector<parser::ParseTree::Node> &annotation_nodes) {
|
||||
auto current_node = start_parser_node;
|
||||
|
||||
description_node = std::nullopt;
|
||||
annotation_nodes.clear();
|
||||
|
||||
if (current_node.is_null()) {
|
||||
return current_node;
|
||||
}
|
||||
|
||||
if (tokens::string_to_type(current_node.get_type()) ==
|
||||
tokens::Type::DEFINITION_INFO) {
|
||||
description_node = current_node;
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
while (!current_node.is_null() &&
|
||||
tokens::string_to_type(current_node.get_type()) ==
|
||||
tokens::Type::ANNOTATION_INFO) {
|
||||
annotation_nodes.push_back(current_node);
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return current_node;
|
||||
}
|
||||
|
||||
// definition_info? annotation_info* '^'? (simple_type | typeclass)
|
||||
// (argument_type* '=' variant_type)? ';'
|
||||
nodes::TypeDefinition build_type_definition(parser::ParseTree::Node parser_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
bool is_on_heap = parser_node.nth_child(0).get_value() == "^";
|
||||
|
||||
std::optional<parser::ParseTree::Node> description_node;
|
||||
std::vector<parser::ParseTree::Node> annotation_nodes;
|
||||
|
||||
auto name_node = collect_symbol_doc_nodes(parser_node.nth_named_child(0),
|
||||
description_node, annotation_nodes);
|
||||
|
||||
nodes::Identifier name = build_identifier(name_node);
|
||||
|
||||
bool is_typeclass = (name.get_type() == nodes::Identifier::TYPECLASS);
|
||||
|
||||
//
|
||||
|
||||
if (is_typeclass && !annotation_nodes.empty()) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Typeclass definition can't have annotation documentation",
|
||||
parser_node);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::vector<nodes::Identifier> typeclasses;
|
||||
std::vector<nodes::Identifier> arguments;
|
||||
|
||||
std::optional<parser::ParseTree::Node> type_node;
|
||||
|
||||
auto current_node = name_node.next_named_sibling();
|
||||
while (!current_node.is_null()) {
|
||||
switch (tokens::string_to_type(current_node.get_type())) {
|
||||
case tokens::Type::TYPECLASS_IDENTIFIER:
|
||||
typeclasses.push_back(build_identifier(current_node));
|
||||
break;
|
||||
case tokens::Type::ARGUMENT_TYPE_IDENTIFIER:
|
||||
arguments.push_back(build_identifier(current_node));
|
||||
break;
|
||||
case tokens::Type::VARIANT_TYPE:
|
||||
if (type_node.has_value()) {
|
||||
error_handling::handle_parsing_error(
|
||||
"More then one type node in type definition", parser_node);
|
||||
}
|
||||
type_node = current_node;
|
||||
break;
|
||||
default:
|
||||
error_handling::handle_parsing_error(
|
||||
"Unexprected node type in type definition", parser_node);
|
||||
}
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
if (!type_node.has_value() && !annotation_nodes.empty()) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Type declaration can't contain annotation documentation", parser_node);
|
||||
}
|
||||
|
||||
if (is_typeclass) {
|
||||
if (!arguments.empty()) {
|
||||
error_handling::handle_parsing_error("Typeclass can't have arguments",
|
||||
parser_node);
|
||||
}
|
||||
|
||||
if (type_node.has_value()) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Typeclass can't be type (contain constructors / fields)",
|
||||
type_node.value());
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<nodes::VariantType> type =
|
||||
type_node.has_value()
|
||||
? build_variant_type(type_node.value(), type_storage)
|
||||
: std::optional<nodes::VariantType>();
|
||||
|
||||
std::unordered_set<std::string> annotations;
|
||||
|
||||
// collect annotations from type
|
||||
if (type.has_value()) {
|
||||
for (size_t i = 0; i < type.value().size(); ++i) {
|
||||
auto constructor_annotations = type.value().get(i)->get_all_annotations();
|
||||
for (auto &annotation : constructor_annotations) {
|
||||
annotations.insert(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodes::TypeDefinition(
|
||||
build_node(parser_node),
|
||||
build_symbol_docs(description_node, annotation_nodes, annotations),
|
||||
is_on_heap, std::move(name), std::move(typeclasses), std::move(arguments),
|
||||
std::move(type));
|
||||
}
|
||||
|
||||
// definition_info? annotation_info* (constraint ';')* '.'? (simple_name
|
||||
// | '(' operator ')') (annotation? _reference_? argument_name '?'?)* (:
|
||||
// (annotation? _reference_ type)+)?
|
||||
// ('=' (block | expression ';') | ';')
|
||||
nodes::FunctionDefinition build_function_definition(
|
||||
parser::ParseTree::Node parser_node,
|
||||
const std::optional<nodes::Identifier> &last_defined_type_name,
|
||||
nodes::ExpressionStorage &expression_storage,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
|
||||
std::optional<parser::ParseTree::Node> description_node;
|
||||
std::vector<parser::ParseTree::Node> annotation_nodes;
|
||||
|
||||
std::vector<nodes::Constraint> constraints;
|
||||
|
||||
auto current_node = collect_symbol_doc_nodes(
|
||||
parser_node.nth_named_child(0), description_node, annotation_nodes);
|
||||
|
||||
while (!current_node.is_null() &&
|
||||
tokens::string_to_type(current_node.get_type()) ==
|
||||
tokens::Type::CONSTRAINT) {
|
||||
constraints.push_back(
|
||||
build_constraint(current_node, expression_storage, type_storage));
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
auto name_node = current_node;
|
||||
|
||||
bool is_method = false;
|
||||
std::optional<nodes::Identifier> name_prefix;
|
||||
|
||||
current_node = name_node.previous_sibling();
|
||||
if (!current_node.is_null() && !current_node.is_named() &&
|
||||
current_node.get_value() == ".") {
|
||||
is_method = true;
|
||||
|
||||
if (!last_defined_type_name.has_value()) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Can't define method without associated type", parser_node);
|
||||
}
|
||||
|
||||
name_prefix = last_defined_type_name.value();
|
||||
}
|
||||
|
||||
nodes::Modifier return_modifier = nodes::Modifier::NONE;
|
||||
|
||||
current_node = name_node.next_sibling();
|
||||
if (!current_node.is_null() && !current_node.is_named()) {
|
||||
return_modifier = build_modifier(current_node);
|
||||
|
||||
// only optional, result allowed
|
||||
if (!utils::is_suffix_modifier(return_modifier)) {
|
||||
return_modifier = nodes::Modifier::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<nodes::FunctionDefinition::Argument> arguments;
|
||||
std::vector<nodes::FunctionDefinition::Argument> argument_types;
|
||||
|
||||
std::optional<parser::ParseTree::Node> expression_node;
|
||||
|
||||
current_node = name_node.next_named_sibling();
|
||||
|
||||
bool at_least_one_argument_annotation_found = false;
|
||||
|
||||
size_t current_type_id = 0;
|
||||
|
||||
std::optional<std::string> last_annotation;
|
||||
nodes::Modifier last_before_modifier = nodes::Modifier::NONE;
|
||||
nodes::Modifier last_after_modifier = nodes::Modifier::NONE;
|
||||
while (!current_node.is_null()) {
|
||||
// update last before modifier
|
||||
auto maybe_reference_node = current_node.previous_sibling();
|
||||
if (!maybe_reference_node.is_null() && !maybe_reference_node.is_named()) {
|
||||
last_before_modifier = build_modifier(maybe_reference_node);
|
||||
|
||||
// only out, in, ref allowed
|
||||
if (utils::is_suffix_modifier(last_before_modifier)) {
|
||||
last_before_modifier = nodes::Modifier::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (tokens::string_to_type(current_node.get_type())) {
|
||||
case tokens::Type::ANNOTATION_IDENTIFIER:
|
||||
last_annotation = build_annotation(current_node);
|
||||
break;
|
||||
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
||||
// update last after modifier
|
||||
maybe_reference_node = current_node.next_sibling();
|
||||
if (!maybe_reference_node.is_null() && !maybe_reference_node.is_named()) {
|
||||
last_after_modifier = build_modifier(maybe_reference_node);
|
||||
|
||||
// only optional, result allowed
|
||||
if (!utils::is_suffix_modifier(last_after_modifier)) {
|
||||
last_after_modifier = nodes::Modifier::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// update conditions
|
||||
if (last_annotation.has_value()) {
|
||||
at_least_one_argument_annotation_found = true;
|
||||
}
|
||||
|
||||
arguments.push_back(nodes::FunctionDefinition::Argument(
|
||||
last_annotation, build_identifier(current_node), last_before_modifier,
|
||||
last_after_modifier));
|
||||
|
||||
last_annotation = std::nullopt;
|
||||
break;
|
||||
case tokens::Type::TYPE:
|
||||
if (current_type_id >= arguments.size()) {
|
||||
arguments.push_back(nodes::FunctionDefinition::Argument(
|
||||
last_annotation, build_type(current_node, type_storage),
|
||||
last_before_modifier));
|
||||
} else {
|
||||
if (!arguments[current_type_id].add_type(
|
||||
last_annotation, build_type(current_node, type_storage),
|
||||
last_before_modifier)) {
|
||||
error_handling::handle_parsing_error(
|
||||
"It is impossible to use argument modifiers (annotations, "
|
||||
"references, "
|
||||
"optional markers, result markers) when types explicitely "
|
||||
"defined. Use type annotations instead.",
|
||||
current_node);
|
||||
}
|
||||
}
|
||||
|
||||
last_annotation = std::nullopt;
|
||||
|
||||
++current_type_id;
|
||||
break;
|
||||
default:
|
||||
if (expression_node.has_value()) {
|
||||
error_handling::handle_parsing_error(
|
||||
"More then one expression found in function definition",
|
||||
parser_node);
|
||||
}
|
||||
expression_node = current_node;
|
||||
break;
|
||||
}
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
if (current_type_id > 0 && current_type_id < arguments.size()) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Less types then arguments in function definition", parser_node);
|
||||
}
|
||||
|
||||
if (current_type_id == 0 && !expression_node.has_value()) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Can't declare function without types (types or function body should "
|
||||
"be added)",
|
||||
parser_node);
|
||||
}
|
||||
|
||||
// automatic annotations
|
||||
bool are_annotations_same_to_names =
|
||||
(!at_least_one_argument_annotation_found && current_type_id == 0);
|
||||
|
||||
if (are_annotations_same_to_names) {
|
||||
for (size_t i = 0; i < arguments.size(); ++i) {
|
||||
std::string new_annotation = *arguments[i].get_name().value()->get();
|
||||
if (!arguments[i].add_annotation(
|
||||
new_annotation.substr(1, new_annotation.size() - 1))) {
|
||||
error_handling::handle_parsing_error(
|
||||
"no annotations provided ( => all annotations same to names), but "
|
||||
"can't add name annotation",
|
||||
current_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> annotations_set;
|
||||
for (auto &argument : arguments) {
|
||||
if (argument.get_annotation().has_value()) {
|
||||
if (!annotations_set.insert(*argument.get_annotation().value()).second) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Two or more same annotations found in function definition",
|
||||
parser_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodes::FunctionDefinition(
|
||||
build_node(parser_node),
|
||||
build_symbol_docs(description_node, annotation_nodes, annotations_set),
|
||||
std::move(constraints), return_modifier, is_method, name_prefix,
|
||||
build_identifier(name_node), std::move(arguments),
|
||||
are_annotations_same_to_names,
|
||||
expression_node.has_value()
|
||||
? build_expression(expression_node.value(), expression_storage,
|
||||
type_storage)
|
||||
: std::optional<nodes::ExpressionProxy>());
|
||||
}
|
||||
|
||||
} // namespace builders
|
||||
80
src/builders/type_builders.cpp
Normal file
80
src/builders/type_builders.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#include "type_builders.hpp"
|
||||
#include "basic_builders.hpp"
|
||||
#include "basic_nodes.hpp"
|
||||
#include "tokens.hpp"
|
||||
|
||||
namespace builders {
|
||||
|
||||
// '^'? type_identifer '?'? ('[' type+ ']')?
|
||||
nodes::TypeProxy build_type(parser::ParseTree::Node parse_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::vector<nodes::TypeProxy> parameters;
|
||||
|
||||
auto name_node = parse_node.child_by_field_name("name");
|
||||
|
||||
auto current_node = parse_node.nth_child(0);
|
||||
bool is_on_heap = (!current_node.is_null() && !current_node.is_named() &&
|
||||
current_node.get_value() == "^");
|
||||
|
||||
nodes::Modifier modifier = nodes::Modifier::NONE;
|
||||
|
||||
current_node = name_node.next_sibling();
|
||||
// update last after modifier
|
||||
if (!current_node.is_null() && !current_node.is_named()) {
|
||||
modifier = build_modifier(current_node);
|
||||
|
||||
// only optional, result allowed
|
||||
if (!utils::is_suffix_modifier(modifier)) {
|
||||
modifier = nodes::Modifier::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
current_node = name_node.next_named_sibling();
|
||||
while (!current_node.is_null()) {
|
||||
parameters.push_back(build_type(current_node, type_storage));
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return type_storage.add_type(
|
||||
nodes::Type(build_node(parse_node), build_identifier(name_node),
|
||||
std::move(parameters), is_on_heap, modifier));
|
||||
}
|
||||
|
||||
// '&'? annotation? type ('&' annotation? type)*
|
||||
nodes::TupleType build_tuple_type(parser::ParseTree::Node parse_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::vector<std::pair<std::optional<std::string>, nodes::TypeProxy>> fields;
|
||||
|
||||
auto current_node = parse_node.nth_named_child(0);
|
||||
|
||||
std::optional<std::string> last_annotation;
|
||||
while (!current_node.is_null()) {
|
||||
if (tokens::string_to_type(current_node.get_type()) ==
|
||||
tokens::Type::ANNOTATION_IDENTIFIER) {
|
||||
last_annotation = build_annotation(current_node);
|
||||
} else {
|
||||
fields.emplace_back(std::move(last_annotation),
|
||||
build_type(current_node, type_storage));
|
||||
last_annotation = std::nullopt;
|
||||
}
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return nodes::TupleType(build_node(parse_node), std::move(fields));
|
||||
}
|
||||
|
||||
// '|'? tuple_type ('|' tuple_type)*
|
||||
nodes::VariantType build_variant_type(parser::ParseTree::Node parse_node,
|
||||
nodes::TypeStorage &type_storage) {
|
||||
std::vector<nodes::TupleType> constructors;
|
||||
|
||||
auto current_node = parse_node.nth_named_child(0);
|
||||
while (!current_node.is_null()) {
|
||||
constructors.push_back(build_tuple_type(current_node, type_storage));
|
||||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
return nodes::VariantType(build_node(parse_node), std::move(constructors));
|
||||
}
|
||||
|
||||
} // namespace builders
|
||||
Loading…
Add table
Add a link
Reference in a new issue