diff --git a/src/language/ASTSymbolInitializationChecker.cpp b/src/language/ASTSymbolInitializationChecker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2763db1ad83b27ef7ee128a89fc077ea66a71ce7 --- /dev/null +++ b/src/language/ASTSymbolInitializationChecker.cpp @@ -0,0 +1,47 @@ +#include <ASTSymbolInitializationChecker.hpp> + +#include <SymbolTable.hpp> + +#include <PEGGrammar.hpp> + +void +ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node) +{ + if (node.is<language::declaration>()) { + const std::string& symbol = node.children[1]->string(); + auto [i_symbol, found] = node.m_symbol_table->find(symbol); + Assert(found, "unexpected error, should have been detected through declaration checking"); + if (node.children.size() == 3) { + this->_checkSymbolInitialization(*node.children[2]); + i_symbol->second.setIsInitialized(); + } + } else if (node.is<language::eq_op>()) { + // first checks for right hand side + this->_checkSymbolInitialization(*node.children[1]); + // then marks left hand side as initialized + const std::string& symbol = node.children[0]->string(); + auto [i_symbol, found] = node.m_symbol_table->find(symbol); + Assert(found, "unexpected error, should have been detected through declaration checking"); + i_symbol->second.setIsInitialized(); + } else if (node.is<language::name>()) { + auto [i_symbol, found] = node.m_symbol_table->find(node.string()); + Assert(found, "unexpected error, should have been detected through declaration checking"); + if (not i_symbol->second.isInitialized()) { + std::ostringstream error_message; + error_message << "uninitialized symbol '" << rang::fg::red << node.string() << rang::fg::reset << '\''; + throw parse_error(error_message.str(), std::vector{node.begin()}); + } + } + + if ((not node.is<language::declaration>()) and (not node.is<language::eq_op>())) { + for (auto& child : node.children) { + this->_checkSymbolInitialization(*child); + } + } +} + +ASTSymbolInitializationChecker::ASTSymbolInitializationChecker(ASTNode& root_node) +{ + Assert(root_node.is_root()); + this->_checkSymbolInitialization(root_node); +} diff --git a/src/language/ASTSymbolInitializationChecker.hpp b/src/language/ASTSymbolInitializationChecker.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7723e68c5261dffdeb7418dac6469816d4f96bf2 --- /dev/null +++ b/src/language/ASTSymbolInitializationChecker.hpp @@ -0,0 +1,15 @@ +#ifndef AST_SYMBOL_INITIALIZATION_CHECKER_HPP +#define AST_SYMBOL_INITIALIZATION_CHECKER_HPP + +#include <ASTNode.hpp> + +class ASTSymbolInitializationChecker +{ + private: + void _checkSymbolInitialization(ASTNode& node); + + public: + ASTSymbolInitializationChecker(ASTNode& root_node); +}; + +#endif // AST_SYMBOL_INITIALIZATION_CHECKER_HPP diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt index c0104ce7ef335e5779fec8a111a526a838ca63ce..6f9d049434b12ccbca3919d8dfcda247e853c23e 100644 --- a/src/language/CMakeLists.txt +++ b/src/language/CMakeLists.txt @@ -14,6 +14,7 @@ add_library( ASTNodeUnaryOperatorExpressionBuilder.cpp ASTPrinter.cpp ASTSymbolTableBuilder.cpp + ASTSymbolInitializationChecker.cpp PugsParser.cpp) #include_directories(${PUGS_SOURCE_DIR}/utils) diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp index fcd2261c291207a8e7c2f8c7e606fa09e196b9dc..bdc4b87034e98e6cf1ebe5dca4621d4d7570812e 100644 --- a/src/language/PugsParser.cpp +++ b/src/language/PugsParser.cpp @@ -23,6 +23,7 @@ #include <ASTNodeExpressionBuilder.hpp> +#include <ASTSymbolInitializationChecker.hpp> #include <ASTSymbolTableBuilder.hpp> #include <ASTPrinter.hpp> @@ -67,66 +68,6 @@ print_dot(std::ostream& os, const ASTNode& n) os << "}\n"; } -namespace internal -{ -void -check_symbol_initialization(const ASTNode& n, std::shared_ptr<SymbolTable>& symbol_table) -{ - if (n.is<language::bloc>() or n.is<language::for_statement>()) { - if (!n.children.empty()) { - std::shared_ptr bloc_symbol_table = std::make_shared<SymbolTable>(symbol_table); - for (auto& child : n.children) { - check_symbol_initialization(*child, bloc_symbol_table); - } - } - } else { - if (n.is<language::declaration>()) { - const std::string& symbol = n.children[1]->string(); - auto [i_symbol, success] = symbol_table->add(symbol); - Assert(success, "unexpected error, should have been detected through declaration checking"); - if (n.children.size() == 3) { - check_symbol_initialization(*n.children[2], symbol_table); - i_symbol->second.setIsInitialized(); - } - } else if (n.is<language::eq_op>()) { - // first checks for right hand side - check_symbol_initialization(*n.children[1], symbol_table); - // then marks left hand side as initialized - const std::string& symbol = n.children[0]->string(); - auto [i_symbol, found] = symbol_table->find(symbol); - Assert(found, "unexpected error, should have been detected through declaration checking"); - i_symbol->second.setIsInitialized(); - } else if (n.is<language::name>()) { - auto [i_symbol, found] = symbol_table->find(n.string()); - Assert(found, "unexpected error, should have been detected through declaration checking"); - if (not i_symbol->second.isInitialized()) { - std::ostringstream error_message; - error_message << "uninitialized symbol '" << rang::fg::red << n.string() << rang::fg::reset << '\''; - throw parse_error(error_message.str(), std::vector{n.begin()}); - } - } - - if ((not n.is<language::declaration>()) and (not n.is<language::eq_op>())) { - for (auto& child : n.children) { - check_symbol_initialization(*child, symbol_table); - } - } - } -} -} // namespace internal - -void -check_symbol_initialization(const ASTNode& n) -{ - std::cerr << rang::fgB::yellow << "warning:" << rang::fg::reset - << " symbol initialization checking not finished" - "if and loops statements are not correctly evaluated\n"; - Assert(n.is_root()); - std::shared_ptr symbol_table = std::make_shared<SymbolTable>(); - internal::check_symbol_initialization(n, symbol_table); - std::cout << " - checked symbols initialization\n"; -} - namespace internal { void @@ -418,7 +359,8 @@ parser(const std::string& filename) ASTSymbolTableBuilder{*root_node}; - language::check_symbol_initialization(*root_node); + ASTSymbolInitializationChecker{*root_node}; + { std::string dot_filename{"parse_tree.dot"}; std::ofstream fout(dot_filename);