From 9b0c7f9db3e31d3d1043f6f1ca45f3c11dad7cc8 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Fri, 31 Jan 2020 18:36:27 +0100 Subject: [PATCH] Prepare component affectation - grammar is ready (list case is not treated) - improve (old) variable case treatment - slight clean-up in ASTBuilder --- src/language/ASTBuilder.cpp | 160 ++++++++++-------- src/language/PEGGrammar.hpp | 4 +- .../node_processor/AffectationProcessor.hpp | 59 ++++--- 3 files changed, 131 insertions(+), 92 deletions(-) diff --git a/src/language/ASTBuilder.cpp b/src/language/ASTBuilder.cpp index 869b708e0..686a7208b 100644 --- a/src/language/ASTBuilder.cpp +++ b/src/language/ASTBuilder.cpp @@ -9,8 +9,6 @@ using namespace TAO_PEGTL_NAMESPACE; #include <SymbolTable.hpp> -using namespace language; - struct ASTBuilder::rearrange : parse_tree::apply<ASTBuilder::rearrange> { template <typename... States> @@ -61,18 +59,19 @@ struct ASTBuilder::simplify_unary : parse_tree::apply<ASTBuilder::simplify_unary transform(std::unique_ptr<ASTNode>& n, States&&... st) { if (n->children.size() == 1) { - if (n->is_type<unary_expression>() or n->is_type<type_expression>()) { + if (n->is_type<language::unary_expression>() or n->is_type<language::type_expression>() or + n->is_type<language::name_subscript_expression>()) { n = std::move(n->children.back()); transform(n, st...); - } else if (n->is_type<unary_minus>()) { + } else if (n->is_type<language::unary_minus>()) { auto& child = n->children[0]; - if (child->is_type<unary_minus>()) { + if (child->is_type<language::unary_minus>()) { n = std::move(child->children[0]); transform(n, st...); } - } else if (n->is_type<unary_not>()) { + } else if (n->is_type<language::unary_not>()) { auto& child = n->children[0]; - if (child->is_type<unary_not>()) { + if (child->is_type<language::unary_not>()) { n = std::move(child->children[0]); transform(n, st...); } @@ -104,7 +103,14 @@ struct ASTBuilder::simplify_unary : parse_tree::apply<ASTBuilder::simplify_unary n = std::move(unary_operator); transform(n->children[0], st...); - } else if (n->children[1]->is_type<language::subscript_expression>()) { + } + } + } + + if ((n->is_type<language::unary_expression>()) or (n->is_type<language::name_subscript_expression>())) { + const size_t child_nb = n->children.size(); + if (child_nb > 1) { + if (n->children[1]->is_type<language::subscript_expression>()) { auto expression = std::move(n->children[0]); for (size_t i = 0; i < child_nb - 1; ++i) { n->children[i] = std::move(n->children[i + 1]); @@ -229,69 +235,81 @@ struct ASTBuilder::simplify_stream_statement : parse_tree::apply<ASTBuilder::sim template <typename Rule> using selector = parse_tree::selector< Rule, - parse_tree::store_content::on<import_instruction, - module_name, - true_kw, - false_kw, - integer, - real, - literal, - name, - B_set, - N_set, - Z_set, - R_set, - tuple_expression, - vector_type, - string_type, - cout_kw, - cerr_kw, - clog_kw, - declaration, - let_declaration, - type_mapping, - function_definition, - if_statement, - do_while_statement, - while_statement, - for_statement, - function_evaluation, - break_kw, - continue_kw>, - ASTBuilder::rearrange:: - on<logical_or, logical_and, bitwise_xor, equality, compare, sum, product, affectation, expression>, - ASTBuilder::simplify_unary:: - on<unary_minus, unary_plus, unary_not, subscript_expression, type_expression, unary_expression>, - parse_tree::remove_content::on<plus_op, - minus_op, - multiply_op, - divide_op, - lesser_op, - lesser_or_eq_op, - greater_op, - greater_or_eq_op, - eqeq_op, - not_eq_op, - and_op, - or_op, - xor_op, - eq_op, - multiplyeq_op, - divideeq_op, - pluseq_op, - minuseq_op, - unary_plusplus, - unary_minusminus, - post_minusminus, - post_plusplus>, - ASTBuilder::simplify_for_statement_block::on<for_statement_block>, - parse_tree::discard_empty::on<ignored, semicol, block>, - ASTBuilder::simplify_node_list::on<name_list, function_argument_list, expression_list>, - ASTBuilder::simplify_statement_block::on<statement_block>, - ASTBuilder::simplify_for_init::on<for_init>, - ASTBuilder::simplify_for_test::on<for_test>, - ASTBuilder::simplify_for_post::on<for_post>, - ASTBuilder::simplify_stream_statement::on<ostream_statement>>; + parse_tree::store_content::on<language::import_instruction, + language::module_name, + language::true_kw, + language::false_kw, + language::integer, + language::real, + language::literal, + language::name, + language::B_set, + language::N_set, + language::Z_set, + language::R_set, + language::tuple_expression, + language::vector_type, + language::string_type, + language::cout_kw, + language::cerr_kw, + language::clog_kw, + language::declaration, + language::let_declaration, + language::type_mapping, + language::function_definition, + language::if_statement, + language::do_while_statement, + language::while_statement, + language::for_statement, + language::function_evaluation, + language::break_kw, + language::continue_kw>, + ASTBuilder::rearrange::on<language::logical_or, + language::logical_and, + language::bitwise_xor, + language::equality, + language::compare, + language::sum, + language::product, + language::affectation, + language::expression>, + ASTBuilder::simplify_unary::on<language::unary_minus, + language::unary_plus, + language::unary_not, + language::subscript_expression, + language::type_expression, + language::unary_expression, + language::name_subscript_expression>, + parse_tree::remove_content::on<language::plus_op, + language::minus_op, + language::multiply_op, + language::divide_op, + language::lesser_op, + language::lesser_or_eq_op, + language::greater_op, + language::greater_or_eq_op, + language::eqeq_op, + language::not_eq_op, + language::and_op, + language::or_op, + language::xor_op, + language::eq_op, + language::multiplyeq_op, + language::divideeq_op, + language::pluseq_op, + language::minuseq_op, + language::unary_plusplus, + language::unary_minusminus, + language::post_minusminus, + language::post_plusplus>, + ASTBuilder::simplify_for_statement_block::on<language::for_statement_block>, + parse_tree::discard_empty::on<language::ignored, language::semicol, language::block>, + ASTBuilder::simplify_node_list::on<language::name_list, language::function_argument_list, language::expression_list>, + ASTBuilder::simplify_statement_block::on<language::statement_block>, + ASTBuilder::simplify_for_init::on<language::for_init>, + ASTBuilder::simplify_for_test::on<language::for_test>, + ASTBuilder::simplify_for_post::on<language::for_post>, + ASTBuilder::simplify_stream_statement::on<language::ostream_statement>>; template <typename InputT> std::unique_ptr<ASTNode> diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index 5e87e8500..2baa69521 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -224,9 +224,11 @@ struct expression_list : seq< open_parent, sor< tuple_expression, expression >, struct affect_op : sor< eq_op, multiplyeq_op, divideeq_op, pluseq_op, minuseq_op > {}; +struct name_subscript_expression : seq< NAME, plus< subscript_expression > >{}; + struct name_list; -struct affectation : seq< sor< NAME, name_list >, if_must< affect_op, sor< expression_list, expression > > >{}; +struct affectation : seq< sor< name_subscript_expression, NAME, name_list >, if_must< affect_op, sor< expression_list, expression > > >{}; struct declaration : if_must< TYPE_EXPRESSION, sor< NAME, name_list>, opt< if_must< seq< one< '=' >, ignored >, sor< expression_list, expression > > > >{}; diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index a84e42c76..4080f3fc8 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -63,7 +63,7 @@ template <typename OperatorT, typename ValueT, typename DataT> class AffectationExecutor final : public IAffectationExecutor { private: - DataVariant* m_lhs{nullptr}; + ValueT& m_lhs; static inline const bool _is_defined{[] { if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) { @@ -75,7 +75,7 @@ class AffectationExecutor final : public IAffectationExecutor }()}; public: - AffectationExecutor(ASTNode& node, DataVariant* lhs) : m_lhs(lhs) + AffectationExecutor(ASTNode& node, ValueT& lhs) : m_lhs(lhs) { // LCOV_EXCL_START if constexpr (not _is_defined) { @@ -91,27 +91,27 @@ class AffectationExecutor final : public IAffectationExecutor if constexpr (std::is_same_v<ValueT, std::string>) { if constexpr (std::is_same_v<OperatorT, language::eq_op>) { if constexpr (std::is_same_v<std::string, DataT>) { - *m_lhs = rhs; + m_lhs = std::get<DataT>(rhs); } else { - *m_lhs = std::to_string(std::get<DataT>(rhs)); + m_lhs = std::to_string(std::get<DataT>(rhs)); } } else { static_assert(std::is_same_v<OperatorT, language::pluseq_op>, "unexpected operator type"); if constexpr (std::is_same_v<std::string, DataT>) { - std::get<std::string>(*m_lhs) += std::get<std::string>(rhs); + m_lhs += std::get<std::string>(rhs); } else { - std::get<std::string>(*m_lhs) += std::to_string(std::get<DataT>(rhs)); + m_lhs += std::to_string(std::get<DataT>(rhs)); } } } else { if constexpr (std::is_same_v<OperatorT, language::eq_op>) { if constexpr (std::is_same_v<ValueT, DataT>) { - *m_lhs = rhs; + m_lhs = std::get<DataT>(rhs); } else { - *m_lhs = static_cast<ValueT>(std::get<DataT>(rhs)); + m_lhs = static_cast<ValueT>(std::get<DataT>(rhs)); } } else { - AffOp<OperatorT>().eval(std::get<ValueT>(*m_lhs), std::get<DataT>(rhs)); + AffOp<OperatorT>().eval(m_lhs, std::get<DataT>(rhs)); } } } @@ -124,8 +124,7 @@ class AffectationProcessor final : public INodeProcessor private: ASTNode& m_node; - using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>; - std::unique_ptr<AffectationExecutorT> m_affectation_executor; + std::unique_ptr<IAffectationExecutor> m_affectation_executor; public: DataVariant @@ -138,11 +137,21 @@ class AffectationProcessor final : public INodeProcessor AffectationProcessor(ASTNode& node) : m_node{node} { - const std::string& symbol = m_node.children[0]->string(); - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); - Assert(found); + if (node.children[0]->is_type<language::name>()) { + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + DataVariant& value = i_symbol->attributes().value(); + + if (not std::holds_alternative<ValueT>(value)) { + value = ValueT{}; + } - m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, &i_symbol->attributes().value()); + using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>; + m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ValueT>(value)); + } else { + throw parse_error("unexpected error: invalid lhs", std::vector{node.children[0]->begin()}); + } } }; @@ -230,12 +239,22 @@ class ListAffectationProcessor final : public INodeProcessor void add(ASTNode& lhs_node) { - const std::string& symbol = lhs_node.string(); - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->end()); - Assert(found); + using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>; + + if (lhs_node.is_type<language::name>()) { + const std::string& symbol = lhs_node.string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->end()); + Assert(found); + DataVariant& value = i_symbol->attributes().value(); - m_affectation_executor_list.emplace_back( - std::make_unique<AffectationExecutor<OperatorT, ValueT, DataT>>(m_node, &i_symbol->attributes().value())); + if (not std::holds_alternative<ValueT>(value)) { + value = ValueT{}; + } + + m_affectation_executor_list.emplace_back(std::make_unique<AffectationExecutorT>(m_node, std::get<ValueT>(value))); + } else { + throw parse_error("not yet implemented", std::vector{lhs_node.begin()}); + } } DataVariant -- GitLab