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