From 9cb762ebb551620297aba703cd8cfda9f5401827 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Thu, 4 Jul 2019 12:40:56 +0200 Subject: [PATCH] Create ASTSymbolTableBuilder replaces build_symbol_table_and_check_declarations function in view of code clean-up --- src/language/ASTSymbolTableBuilder.cpp | 56 +++++++++++++ src/language/ASTSymbolTableBuilder.hpp | 24 ++++++ src/language/CMakeLists.txt | 1 + src/language/PugsParser.cpp | 106 +++++++++++++------------ 4 files changed, 136 insertions(+), 51 deletions(-) create mode 100644 src/language/ASTSymbolTableBuilder.cpp create mode 100644 src/language/ASTSymbolTableBuilder.hpp diff --git a/src/language/ASTSymbolTableBuilder.cpp b/src/language/ASTSymbolTableBuilder.cpp new file mode 100644 index 000000000..ab817f3b5 --- /dev/null +++ b/src/language/ASTSymbolTableBuilder.cpp @@ -0,0 +1,56 @@ +#include <ASTSymbolTableBuilder.hpp> +#include <SymbolTable.hpp> + +#include <PEGGrammar.hpp> + +namespace language +{ +void +ASTSymbolTableBuilder::buildSymbolTable(Node& 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); + n.m_symbol_table = bloc_symbol_table; + for (auto& child : n.children) { + this->buildSymbolTable(*child, bloc_symbol_table); + } + } + } else { + n.m_symbol_table = symbol_table; + if (n.has_content()) { + if (n.is<language::declaration>()) { + const std::string& symbol = n.children[1]->string(); + auto [i_symbol, success] = symbol_table->add(symbol); + if (not success) { + std::ostringstream error_message; + error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << '\'' << " was already defined!"; + throw parse_error(error_message.str(), std::vector{n.begin()}); + } + } else if (n.is<language::name>()) { + auto [i_symbol, found] = symbol_table->find(n.string()); + if (not found) { + std::ostringstream error_message; + error_message << "undefined symbol '" << rang::fg::red << n.string() << rang::fg::reset << '\''; + throw parse_error(error_message.str(), std::vector{n.begin()}); + } + } + } + + for (auto& child : n.children) { + this->buildSymbolTable(*child, symbol_table); + } + } +} + +ASTSymbolTableBuilder::ASTSymbolTableBuilder(Node& node) +{ + Assert(node.is_root()); + std::shared_ptr symbol_table = std::make_shared<SymbolTable>(); + + node.m_symbol_table = symbol_table; + + this->buildSymbolTable(node, symbol_table); + std::cout << " - checked symbols declaration\n"; +} +} // namespace language diff --git a/src/language/ASTSymbolTableBuilder.hpp b/src/language/ASTSymbolTableBuilder.hpp new file mode 100644 index 000000000..4a8cf9c91 --- /dev/null +++ b/src/language/ASTSymbolTableBuilder.hpp @@ -0,0 +1,24 @@ +#ifndef AST_SYMBOL_TABLE_BUILDER_HPP +#define AST_SYMBOL_TABLE_BUILDER_HPP + +#include <ASTNode.hpp> + +namespace language +{ +class SymbolTable; + +class ASTSymbolTableBuilder +{ + private: + void buildSymbolTable(Node& node, std::shared_ptr<SymbolTable>& symbol_table); + + public: + ASTSymbolTableBuilder(Node& root_node); + + ASTSymbolTableBuilder(const ASTSymbolTableBuilder&) = delete; + + ~ASTSymbolTableBuilder() = default; +}; +} // namespace language + +#endif // AST_SYMBOL_TABLE_BUILDER_HPP diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt index 8cf155b46..c0104ce7e 100644 --- a/src/language/CMakeLists.txt +++ b/src/language/CMakeLists.txt @@ -13,6 +13,7 @@ add_library( ASTNodeIncDecExpressionBuilder.cpp ASTNodeUnaryOperatorExpressionBuilder.cpp ASTPrinter.cpp + ASTSymbolTableBuilder.cpp PugsParser.cpp) #include_directories(${PUGS_SOURCE_DIR}/utils) diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp index db2f4f593..69c945a9d 100644 --- a/src/language/PugsParser.cpp +++ b/src/language/PugsParser.cpp @@ -23,6 +23,8 @@ #include <ASTNodeExpressionBuilder.hpp> +#include <ASTSymbolTableBuilder.hpp> + #include <ASTPrinter.hpp> namespace language @@ -65,56 +67,56 @@ print_dot(std::ostream& os, const Node& n) os << "}\n"; } -namespace internal -{ -void -build_symbol_table_and_check_declarations(Node& 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); - n.m_symbol_table = bloc_symbol_table; - for (auto& child : n.children) { - build_symbol_table_and_check_declarations(*child, bloc_symbol_table); - } - } - } else { - n.m_symbol_table = symbol_table; - if (n.has_content()) { - if (n.is<language::declaration>()) { - const std::string& symbol = n.children[1]->string(); - auto [i_symbol, success] = symbol_table->add(symbol); - if (not success) { - std::ostringstream error_message; - error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << '\'' << " was already defined!"; - throw parse_error(error_message.str(), std::vector{n.begin()}); - } - } else if (n.is<language::name>()) { - auto [i_symbol, found] = symbol_table->find(n.string()); - if (not found) { - std::ostringstream error_message; - error_message << "undefined symbol '" << rang::fg::red << n.string() << rang::fg::reset << '\''; - throw parse_error(error_message.str(), std::vector{n.begin()}); - } - } - } - - for (auto& child : n.children) { - build_symbol_table_and_check_declarations(*child, symbol_table); - } - } -} -} // namespace internal - -void -build_symbol_table_and_check_declarations(Node& n) -{ - Assert(n.is_root()); - std::shared_ptr symbol_table = std::make_shared<SymbolTable>(); - n.m_symbol_table = symbol_table; - internal::build_symbol_table_and_check_declarations(n, symbol_table); - std::cout << " - checked symbols declaration\n"; -} +// namespace internal +// { +// void +// build_symbol_table_and_check_declarations(Node& 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); +// n.m_symbol_table = bloc_symbol_table; +// for (auto& child : n.children) { +// build_symbol_table_and_check_declarations(*child, bloc_symbol_table); +// } +// } +// } else { +// n.m_symbol_table = symbol_table; +// if (n.has_content()) { +// if (n.is<language::declaration>()) { +// const std::string& symbol = n.children[1]->string(); +// auto [i_symbol, success] = symbol_table->add(symbol); +// if (not success) { +// std::ostringstream error_message; +// error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << '\'' << " was already +// defined!"; throw parse_error(error_message.str(), std::vector{n.begin()}); +// } +// } else if (n.is<language::name>()) { +// auto [i_symbol, found] = symbol_table->find(n.string()); +// if (not found) { +// std::ostringstream error_message; +// error_message << "undefined symbol '" << rang::fg::red << n.string() << rang::fg::reset << '\''; +// throw parse_error(error_message.str(), std::vector{n.begin()}); +// } +// } +// } + +// for (auto& child : n.children) { +// build_symbol_table_and_check_declarations(*child, symbol_table); +// } +// } +// } +// } // namespace internal + +// void +// build_symbol_table_and_check_declarations(Node& n) +// { +// Assert(n.is_root()); +// std::shared_ptr symbol_table = std::make_shared<SymbolTable>(); +// n.m_symbol_table = symbol_table; +// internal::build_symbol_table_and_check_declarations(n, symbol_table); +// std::cout << " - checked symbols declaration\n"; +// } namespace internal { @@ -463,7 +465,9 @@ parser(const std::string& filename) root_node = buildAST(input); std::cout << " - AST is built ...... [done]\n"; - language::build_symbol_table_and_check_declarations(*root_node); + language::ASTSymbolTableBuilder{*root_node}; + + // language::build_symbol_table_and_check_declarations(*root_node); language::check_symbol_initialization(*root_node); { std::string dot_filename{"parse_tree.dot"}; -- GitLab