#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()); switch (type) { // --- flow control case tokens::Type::MATCH: return expression_storage.add_expression(nodes::Expression( build_match(parser_node, expression_storage, type_storage))); case tokens::Type::CONDITION: return expression_storage.add_expression(nodes::Expression( build_condition(parser_node, expression_storage, type_storage))); case tokens::Type::LOOP: return expression_storage.add_expression(nodes::Expression( build_loop(parser_node, expression_storage, type_storage))); // --- operators case tokens::Type::COMMA_EXPRESSION: return expression_storage.add_expression(nodes::Expression( build_comma_expression(parser_node, expression_storage, type_storage))); case tokens::Type::OPERATOR_EXPRESSION: return expression_storage.add_expression( nodes::Expression(build_operator_expression( parser_node, expression_storage, type_storage))); // --- containers case tokens::Type::BLOCK: return expression_storage.add_expression(nodes::Expression( build_block(parser_node, expression_storage, type_storage))); case tokens::Type::ARRAY: return expression_storage.add_expression(nodes::Expression( build_array(parser_node, expression_storage, type_storage))); // --- modifiers case tokens::Type::RETURN: return expression_storage.add_expression(nodes::Expression( build_return(parser_node, expression_storage, type_storage))); case tokens::Type::NAME_DEFINITION: return expression_storage.add_expression( nodes::Expression(build_name_definition(parser_node))); case tokens::Type::ARRAY_ACCESS: return expression_storage.add_expression(nodes::Expression( build_array_access(parser_node, expression_storage, type_storage))); case tokens::Type::TUPLE_ACCESS: return expression_storage.add_expression(nodes::Expression( build_tuple_access(parser_node, expression_storage, type_storage))); case tokens::Type::LOOP_CONTROL: return expression_storage.add_expression( nodes::Expression(build_loop_control(parser_node))); case tokens::Type::REFERENCE_EXPRESSION: return expression_storage.add_expression( nodes::Expression(build_reference_expression( parser_node, expression_storage, type_storage))); case tokens::Type::SUFFIX_EXPRESSION: return expression_storage.add_expression( nodes::Expression(build_suffix_expression( parser_node, expression_storage, type_storage))); // --- other case tokens::Type::NAME_EXPRESSION: return expression_storage.add_expression(nodes::Expression( build_name_expression(parser_node, expression_storage, type_storage))); 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)))); case tokens::Type::CONSTRUCTOR: return expression_storage.add_expression(nodes::Expression( build_constructor(parser_node, expression_storage, type_storage))); case tokens::Type::LAMBDA: return expression_storage.add_expression(nodes::Expression( build_lambda(parser_node, expression_storage, type_storage))); // --- literals case tokens::Type::FLOAT_NUMBER_LITERAL: return expression_storage.add_expression( nodes::Expression(build_float_number_literal(parser_node))); case tokens::Type::NUMBER_LITERAL: return expression_storage.add_expression( nodes::Expression(build_number_literal(parser_node))); case tokens::Type::STRING_LITERAL: return expression_storage.add_expression( nodes::Expression(build_string_literal(parser_node))); case tokens::Type::CHAR_LITERAL: return expression_storage.add_expression( nodes::Expression(build_char_literal(parser_node))); case tokens::Type::BOOL_LITERAL: return expression_storage.add_expression( nodes::Expression(build_bool_literal(parser_node))); case tokens::Type::UNIT_LITERAL: return expression_storage.add_expression( nodes::Expression(build_unit_literal(parser_node))); case tokens::Type::NULL_LITERAL: return expression_storage.add_expression( nodes::Expression(build_null_literal(parser_node))); 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 condition_node; std::optional 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(), expression_node.has_value() ? build_expression(expression_node.value(), expression_storage, type_storage) : std::optional()); } // expression case+ nodes::Match build_match(parser::ParseTree::Node parser_node, nodes::ExpressionStorage &expression_storage, nodes::TypeStorage &type_storage) { std::vector 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> 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()); } // ('@' | '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, 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, 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 expressions; auto current_node = parser_node.nth_named_child(0).next_named_sibling(); 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))))); } // '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, nodes::ExpressionProxy>> &arguments) { auto current_node = first_parse_node; std::optional 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, nodes::ExpressionProxy>> arguments; std::optional prefix; bool is_point_call = false; auto name_node = parser_node.child_by_field_name("name"); std::optional 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(), 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, 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 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