From be4ce7ae61b3a1eaa3c714fd1789f28652201ea0 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Tue, 30 Jul 2019 15:15:11 +0200
Subject: [PATCH] Add tests for ASTNodeExpressionBuilder

Also performed slight cosmetic changes in ASTNodeExpressionBuilder::_buildExpression
---
 src/language/ASTNodeExpressionBuilder.cpp |   8 +-
 tests/test_ASTNodeExpressionBuilder.cpp   | 743 +++++++++++++++++++++-
 2 files changed, 723 insertions(+), 28 deletions(-)

diff --git a/src/language/ASTNodeExpressionBuilder.cpp b/src/language/ASTNodeExpressionBuilder.cpp
index c1a1fb8ac..756d40245 100644
--- a/src/language/ASTNodeExpressionBuilder.cpp
+++ b/src/language/ASTNodeExpressionBuilder.cpp
@@ -336,6 +336,10 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n)
     n.m_node_processor = std::make_unique<NoProcess>();
   } else if (n.is<language::literal>()) {
     n.m_node_processor = std::make_unique<NoProcess>();
+  } else if (n.is<language::true_kw>()) {
+    n.m_node_processor = std::make_unique<NoProcess>();
+  } else if (n.is<language::false_kw>()) {
+    n.m_node_processor = std::make_unique<NoProcess>();
 
   } else if (n.is<language::name>()) {
     n.m_node_processor = std::make_unique<NameExpression>(n);
@@ -382,10 +386,6 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n)
     n.m_node_processor = std::make_unique<BreakExpression>();
   } else if (n.is<language::continue_kw>()) {
     n.m_node_processor = std::make_unique<ContinueExpression>();
-  } else if (n.is<language::true_kw>()) {
-    n.m_node_processor = std::make_unique<NoProcess>();
-  } else if (n.is<language::false_kw>()) {
-    n.m_node_processor = std::make_unique<NoProcess>();
   } else {
     std::ostringstream error_message;
     error_message << "undefined node type '" << rang::fgB::red << n.name() << rang::fg::reset << "'";
diff --git a/tests/test_ASTNodeExpressionBuilder.cpp b/tests/test_ASTNodeExpressionBuilder.cpp
index b7a6c82a1..f1ca3f8ab 100644
--- a/tests/test_ASTNodeExpressionBuilder.cpp
+++ b/tests/test_ASTNodeExpressionBuilder.cpp
@@ -14,6 +14,8 @@
 
 #include <ASTPrinter.hpp>
 
+#include <PEGGrammar.hpp>
+
 #include <Demangle.hpp>
 
 #define CHECK_AST(data, expected_output)                                                            \
@@ -41,7 +43,7 @@
 
 TEST_CASE("ASTNodeExpressionBuilder", "[language]")
 {
-  SECTION("nothing to convert")
+  SECTION("empty file")
   {
     std::string_view data = R"(
 )";
@@ -53,71 +55,764 @@ TEST_CASE("ASTNodeExpressionBuilder", "[language]")
     CHECK_AST(data, result);
   }
 
-  SECTION("string affectation")
+  SECTION("values")
   {
-    SECTION("from bool")
+    SECTION("integer")
     {
       std::string_view data = R"(
-string s = true;
+3;
 )";
 
       std::string result = R"(
 (root:ASTNodeList)
- `-(language::eq_op:AffectationToStringProcessor<language::eq_op, bool>)
-     +-(language::name:s:NameExpression)
-     `-(language::true_kw:NoProcess)
+ `-(language::integer:3:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("real")
+    {
+      std::string_view data = R"(
+2.3e-5;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::real:2.3e-5:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("literal")
+    {
+      std::string_view data = R"(
+"foo";
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::literal:"foo":NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("true")
+    {
+      std::string_view data = R"(
+true;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::true_kw:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("false")
+    {
+      std::string_view data = R"(
+false;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::false_kw:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("bloc")
+  {
+    std::string_view data = R"(
+{
+ 1;
+}
+)";
+
+    std::string result = R"(
+(root:ASTNodeList)
+ `-(language::bloc:ASTNodeList)
+     `-(language::integer:1:NoProcess)
+)";
+
+    CHECK_AST(data, result);
+  }
+
+  SECTION("name")
+  {
+    std::string_view data = R"(
+N i;
+i;
+)";
+
+    std::string result = R"(
+(root:ASTNodeList)
+ `-(language::name:i:NameExpression)
+)";
+
+    CHECK_AST(data, result);
+  }
+
+  SECTION("affectations")
+  {
+    SECTION("operator=")
+    {
+      std::string_view data = R"(
+N i = 1;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
+     +-(language::name:i:NameExpression)
+     `-(language::integer:1:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("operator*=")
+    {
+      std::string_view data = R"(
+N i = 1;
+i *= 3;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
+ |   +-(language::name:i:NameExpression)
+ |   `-(language::integer:1:NoProcess)
+ `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, unsigned long, long>)
+     +-(language::name:i:NameExpression)
+     `-(language::integer:3:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("operator/=")
+    {
+      std::string_view data = R"(
+R x = 1;
+x /= 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>)
+ |   +-(language::name:x:NameExpression)
+ |   `-(language::integer:1:NoProcess)
+ `-(language::divideeq_op:AffectationProcessor<language::divideeq_op, double, long>)
+     +-(language::name:x:NameExpression)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("operator+=")
+    {
+      std::string_view data = R"(
+N i = 1;
+i += 3.;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
+ |   +-(language::name:i:NameExpression)
+ |   `-(language::integer:1:NoProcess)
+ `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, unsigned long, double>)
+     +-(language::name:i:NameExpression)
+     `-(language::real:3.:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("operator-=")
+    {
+      std::string_view data = R"(
+Z z = 1;
+z -= 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>)
+ |   +-(language::name:z:NameExpression)
+ |   `-(language::integer:1:NoProcess)
+ `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, long, long>)
+     +-(language::name:z:NameExpression)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("unary operators")
+  {
+    SECTION("unary minus")
+    {
+      std::string_view data = R"(
+-1;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>)
+     `-(language::integer:1:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("unary not")
+    {
+      std::string_view data = R"(
+not 1;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::unary_not:UnaryExpressionProcessor<language::unary_not, bool, long>)
+     `-(language::integer:1:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("pre-increment operator")
+    {
+      std::string_view data = R"(
+Z a=1;
+++a;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>)
+ |   +-(language::name:a:NameExpression)
+ |   `-(language::integer:1:NoProcess)
+ `-(language::unary_plusplus:IncDecExpressionProcessor<language::unary_plusplus, long, long>)
+     `-(language::name:a:NameExpression)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("pre-decrement operator")
+    {
+      std::string_view data = R"(
+Z a=1;
+--a;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>)
+ |   +-(language::name:a:NameExpression)
+ |   `-(language::integer:1:NoProcess)
+ `-(language::unary_minusminus:IncDecExpressionProcessor<language::unary_minusminus, long, long>)
+     `-(language::name:a:NameExpression)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("post-increment operator")
+    {
+      std::string_view data = R"(
+Z a=1;
+a++;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>)
+ |   +-(language::name:a:NameExpression)
+ |   `-(language::integer:1:NoProcess)
+ `-(language::post_plusplus:IncDecExpressionProcessor<language::post_plusplus, long, long>)
+     `-(language::name:a:NameExpression)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("post-decrement operator")
+    {
+      std::string_view data = R"(
+Z a=1;
+a--;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>)
+ |   +-(language::name:a:NameExpression)
+ |   `-(language::integer:1:NoProcess)
+ `-(language::post_minusminus:IncDecExpressionProcessor<language::post_minusminus, long, long>)
+     `-(language::name:a:NameExpression)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("binary operators")
+  {
+    SECTION("multiply")
+    {
+      std::string_view data = R"(
+1*2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("divide")
+    {
+      std::string_view data = R"(
+1/2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
 )";
 
       CHECK_AST(data, result);
     }
 
-    SECTION("from int")
+    SECTION("plus")
     {
       std::string_view data = R"(
-string s = 0;
+1+2;
 )";
 
       std::string result = R"(
 (root:ASTNodeList)
- `-(language::eq_op:AffectationToStringProcessor<language::eq_op, long>)
-     +-(language::name:s:NameExpression)
-     `-(language::integer:0:NoProcess)
+ `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
 )";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("minus")
+    {
+      std::string_view data = R"(
+1-2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("or")
+    {
+      std::string_view data = R"(
+1 or 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::or_op:BinaryExpressionProcessor<language::or_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("and")
+    {
+      std::string_view data = R"(
+1 and 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::and_op:BinaryExpressionProcessor<language::and_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("xor")
+    {
+      std::string_view data = R"(
+1 xor 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::xor_op:BinaryExpressionProcessor<language::xor_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("lesser")
+    {
+      std::string_view data = R"(
+1 < 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("lesser or equal")
+    {
+      std::string_view data = R"(
+1 <= 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("greater")
+    {
+      std::string_view data = R"(
+1 > 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
       CHECK_AST(data, result);
     }
 
-    SECTION("from unsigned")
+    SECTION("greater or equal")
     {
       std::string_view data = R"(
-N n = 0;
-string s = n;
+1 >= 2;
 )";
 
       std::string result = R"(
+(root:ASTNodeList)
+ `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("equal")
+    {
+      std::string_view data = R"(
+1 == 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("different")
+    {
+      std::string_view data = R"(
+1 != 2;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, long, long>)
+     +-(language::integer:1:NoProcess)
+     `-(language::integer:2:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("ostream objects")
+  {
+    SECTION("cout")
+    {
+      std::string_view data = R"(
+cout;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::cout_kw:OStreamObject)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("cerr")
+    {
+      std::string_view data = R"(
+cerr;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::cerr_kw:OStreamObject)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("clog")
+    {
+      std::string_view data = R"(
+clog;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::clog_kw:OStreamObject)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("statements")
+  {
+    SECTION("if")
+    {
+      std::string_view data = R"(
+if(true);
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::if_statement:IfStatement)
+     +-(language::true_kw:NoProcess)
+     `-(language::statement_bloc:ASTNodeList)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("do while")
+    {
+      std::string_view data = R"(
+do; while(true);
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::do_while_statement:DoWhileStatement)
+     +-(language::statement_bloc:ASTNodeList)
+     `-(language::true_kw:NoProcess)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("while")
+    {
+      std::string_view data = R"(
+while(true);
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::while_statement:WhileStatement)
+     +-(language::true_kw:NoProcess)
+     `-(language::statement_bloc:ASTNodeList)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("for")
+    {
+      SECTION("for_statement")
+      {
+        std::string_view data = R"(
+for(N i=0; i<10; ++i);
+)";
+
+        std::string result = R"(
+(root:ASTNodeList)
+ `-(language::for_statement:ForStatement)
+     +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
+     |   +-(language::name:i:NameExpression)
+     |   `-(language::integer:0:NoProcess)
+     +-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, unsigned long, long>)
+     |   +-(language::name:i:NameExpression)
+     |   `-(language::integer:10:NoProcess)
+     +-(language::unary_plusplus:IncDecExpressionProcessor<language::unary_plusplus, unsigned long, unsigned long>)
+     |   `-(language::name:i:NameExpression)
+     `-(language::for_statement_bloc:ASTNodeList)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("no init")
+      {
+        std::string_view data = R"(
+N i=0;
+for(; i<10; ++i);
+)";
+
+        std::string result = R"(
 (root:ASTNodeList)
  +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
- |   +-(language::name:n:NameExpression)
+ |   +-(language::name:i:NameExpression)
  |   `-(language::integer:0:NoProcess)
- `-(language::eq_op:AffectationToStringProcessor<language::eq_op, unsigned long>)
-     +-(language::name:s:NameExpression)
-     `-(language::name:n:NameExpression)
+ `-(language::for_statement:ForStatement)
+     +-(language::for_init:NoProcess)
+     +-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, unsigned long, long>)
+     |   +-(language::name:i:NameExpression)
+     |   `-(language::integer:10:NoProcess)
+     +-(language::unary_plusplus:IncDecExpressionProcessor<language::unary_plusplus, unsigned long, unsigned long>)
+     |   `-(language::name:i:NameExpression)
+     `-(language::for_statement_bloc:ASTNodeList)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("no test")
+      {
+        std::string_view data = R"(
+for(N i=0; ; ++i);
+)";
+
+        std::string result = R"(
+(root:ASTNodeList)
+ `-(language::for_statement:ForStatement)
+     +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
+     |   +-(language::name:i:NameExpression)
+     |   `-(language::integer:0:NoProcess)
+     +-(language::for_test:NoProcess)
+     +-(language::unary_plusplus:IncDecExpressionProcessor<language::unary_plusplus, unsigned long, unsigned long>)
+     |   `-(language::name:i:NameExpression)
+     `-(language::for_statement_bloc:ASTNodeList)
 )";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("no post instruction")
+      {
+        std::string_view data = R"(
+for(N i=0; i<10;);
+)";
+
+        std::string result = R"(
+(root:ASTNodeList)
+ `-(language::for_statement:ForStatement)
+     +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
+     |   +-(language::name:i:NameExpression)
+     |   `-(language::integer:0:NoProcess)
+     +-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, unsigned long, long>)
+     |   +-(language::name:i:NameExpression)
+     |   `-(language::integer:10:NoProcess)
+     +-(language::for_post:NoProcess)
+     `-(language::for_statement_bloc:ASTNodeList)
+)";
+
+        CHECK_AST(data, result);
+      }
+    }
+  }
+
+  SECTION("jumps instruction")
+  {
+    SECTION("break")
+    {
+      std::string_view data = R"(
+break;
+)";
+
+      std::string result = R"(
+(root:ASTNodeList)
+ `-(language::break_kw:BreakExpression)
+)";
+
       CHECK_AST(data, result);
     }
 
-    SECTION("from real")
+    SECTION("continue")
     {
       std::string_view data = R"(
-string s = 0.;
+continue;
 )";
 
       std::string result = R"(
 (root:ASTNodeList)
- `-(language::eq_op:AffectationToStringProcessor<language::eq_op, double>)
-     +-(language::name:s:NameExpression)
-     `-(language::real:0.:NoProcess)
+ `-(language::continue_kw:ContinueExpression)
 )";
+
       CHECK_AST(data, result);
     }
   }
+
+  SECTION("unexpected node type")
+  {
+    std::string_view data = R"(
+1;
+)";
+
+    string_input input{data, "test.pgs"};
+    auto ast = ASTBuilder::build(input);
+    ASTNodeDataTypeBuilder{*ast};
+
+    // One is sure that language::ignored is not treated so its a good candidate
+    // for this test
+    ast->children[0]->id = typeid(language::ignored);
+    REQUIRE_THROWS_AS(ASTNodeExpressionBuilder{*ast}, parse_error);
+  }
 }
-- 
GitLab