Skip to content
Snippets Groups Projects
Commit b797c9f2 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Continue clean-up. Add ASTNodeValueBuilder and its tests.

parent 3a630376
No related branches found
No related tags found
1 merge request!37Feature/language
#include <ASTNodeValueBuilder.hpp>
#include <PEGGrammar.hpp>
#include <PugsAssert.hpp>
#include <EscapedString.hpp>
void
ASTNodeValueBuilder::_buildNodeValue(ASTNode& n)
{
if (n.is<language::bloc>()) {
if (!n.children.empty()) {
for (auto& child : n.children) {
this->_buildNodeValue(*child);
}
}
n.m_data_type = ASTNodeDataType::void_t;
} else {
for (auto& child : n.children) {
this->_buildNodeValue(*child);
}
if (n.has_content()) {
if (n.is<language::real>()) {
std::stringstream ss(n.string());
double v;
ss >> v;
n.m_value = v;
} else if (n.is<language::integer>()) {
std::stringstream ss(n.string());
int64_t v;
ss >> v;
n.m_value = v;
} else if (n.is<language::literal>()) {
n.m_value = unescapeString(n.string());
} else if (n.is<language::for_test>()) {
// if AST contains a for_test statement, it means that no test were
// given to the for-loop, so its value is always true
n.m_value = true;
} else if (n.is<language::true_kw>()) {
n.m_value = true;
} else if (n.is<language::false_kw>()) {
n.m_value = false;
}
}
}
}
ASTNodeValueBuilder::ASTNodeValueBuilder(ASTNode& n)
{
Assert(n.is_root());
n.m_data_type = ASTNodeDataType::void_t;
this->_buildNodeValue(n);
std::cout << " - build node data types\n";
}
#ifndef AST_NODE_VALUE_BUILDER_HPP
#define AST_NODE_VALUE_BUILDER_HPP
#include <ASTNode.hpp>
class ASTNodeValueBuilder
{
private:
void _buildNodeValue(ASTNode& node);
public:
ASTNodeValueBuilder(ASTNode& root_node);
};
#endif // AST_NODE_VALUE_BUILDER_HPP
...@@ -7,14 +7,15 @@ add_library( ...@@ -7,14 +7,15 @@ add_library(
PugsLanguage PugsLanguage
ASTBuilder.cpp ASTBuilder.cpp
ASTDotPrinter.cpp ASTDotPrinter.cpp
ASTNodeAffectationExpressionBuilder.cpp
ASTNodeBinaryOperatorExpressionBuilder.cpp
ASTNodeDataType.cpp ASTNodeDataType.cpp
ASTNodeDataTypeBuilder.cpp ASTNodeDataTypeBuilder.cpp
ASTNodeDataTypeChecker.cpp ASTNodeDataTypeChecker.cpp
ASTNodeAffectationExpressionBuilder.cpp
ASTNodeBinaryOperatorExpressionBuilder.cpp
ASTNodeExpressionBuilder.cpp ASTNodeExpressionBuilder.cpp
ASTNodeIncDecExpressionBuilder.cpp ASTNodeIncDecExpressionBuilder.cpp
ASTNodeUnaryOperatorExpressionBuilder.cpp ASTNodeUnaryOperatorExpressionBuilder.cpp
ASTNodeValueBuilder.cpp
ASTPrinter.cpp ASTPrinter.cpp
ASTSymbolTableBuilder.cpp ASTSymbolTableBuilder.cpp
ASTSymbolInitializationChecker.cpp ASTSymbolInitializationChecker.cpp
......
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
#include <ASTNodeDataTypeBuilder.hpp> #include <ASTNodeDataTypeBuilder.hpp>
#include <ASTNodeDataTypeChecker.hpp> #include <ASTNodeDataTypeChecker.hpp>
#include <EscapedString.hpp>
#include <ASTNodeExpressionBuilder.hpp> #include <ASTNodeExpressionBuilder.hpp>
#include <ASTSymbolInitializationChecker.hpp> #include <ASTSymbolInitializationChecker.hpp>
...@@ -32,63 +30,10 @@ ...@@ -32,63 +30,10 @@
#include <ASTDotPrinter.hpp> #include <ASTDotPrinter.hpp>
#include <ASTPrinter.hpp> #include <ASTPrinter.hpp>
namespace language #include <ASTNodeValueBuilder.hpp>
{
namespace internal
{
void
build_node_values(ASTNode& n, std::shared_ptr<SymbolTable>& symbol_table)
{
if (n.is<language::bloc>()) {
if (!n.children.empty()) {
std::shared_ptr bloc_symbol_table = std::make_shared<SymbolTable>(symbol_table);
for (auto& child : n.children) {
build_node_values(*child, bloc_symbol_table);
}
}
n.m_data_type = ASTNodeDataType::void_t;
} else {
for (auto& child : n.children) {
build_node_values(*child, symbol_table);
}
if (n.has_content()) {
if (n.is<language::real>()) {
std::stringstream ss(n.string());
double v;
ss >> v;
n.m_value = v;
} else if (n.is<language::integer>()) {
std::stringstream ss(n.string());
int64_t v;
ss >> v;
n.m_value = v;
} else if (n.is<language::literal>()) {
n.m_value = unescapeString(n.string());
} else if (n.is<language::for_test>()) {
// if AST contains a for_test statement, it means that no test were
// given to the for-loop, so its value is always true
n.m_value = true;
} else if (n.is<language::true_kw>()) {
n.m_value = true;
} else if (n.is<language::false_kw>()) {
n.m_value = false;
}
}
}
}
} // namespace internal
void namespace language
build_node_values(ASTNode& n)
{ {
Assert(n.is_root());
n.m_data_type = ASTNodeDataType::void_t;
std::shared_ptr symbol_table = std::make_shared<SymbolTable>();
internal::build_node_values(n, symbol_table);
std::cout << " - build node data types\n";
}
namespace internal namespace internal
{ {
void void
...@@ -179,7 +124,7 @@ parser(const std::string& filename) ...@@ -179,7 +124,7 @@ parser(const std::string& filename)
ASTNodeDataTypeBuilder{*root_node}; ASTNodeDataTypeBuilder{*root_node};
ASTNodeDataTypeChecker{*root_node}; ASTNodeDataTypeChecker{*root_node};
language::build_node_values(*root_node); ASTNodeValueBuilder{*root_node};
language::check_break_or_continue_placement(*root_node); language::check_break_or_continue_placement(*root_node);
......
...@@ -5,11 +5,12 @@ add_executable (unit_tests ...@@ -5,11 +5,12 @@ add_executable (unit_tests
test_main.cpp test_main.cpp
test_Array.cpp test_Array.cpp
test_ArrayUtils.cpp test_ArrayUtils.cpp
test_ASTDotPrinter.cpp
test_ASTBuilder.cpp test_ASTBuilder.cpp
test_ASTDotPrinter.cpp
test_ASTNodeDataType.cpp test_ASTNodeDataType.cpp
test_ASTNodeDataTypeBuilder.cpp test_ASTNodeDataTypeBuilder.cpp
test_ASTNodeDataTypeChecker.cpp test_ASTNodeDataTypeChecker.cpp
test_ASTNodeValueBuilder.cpp
test_ASTPrinter.cpp test_ASTPrinter.cpp
test_ASTSymbolTableBuilder.cpp test_ASTSymbolTableBuilder.cpp
test_ASTSymbolInitializationChecker.cpp test_ASTSymbolInitializationChecker.cpp
......
#include <catch2/catch.hpp>
#include <ASTNodeValueBuilder.hpp>
#include <ASTBuilder.hpp>
#include <ASTNodeDataTypeBuilder.hpp>
#include <ASTSymbolTableBuilder.hpp>
#include <ASTPrinter.hpp>
#define CHECK_AST_VALUES(data, expected_output) \
{ \
static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \
static_assert(std::is_same_v<std::decay_t<decltype(expected_output)>, std::string_view>); \
\
string_input input{data, "test.pgs"}; \
auto ast = ASTBuilder::build(input); \
\
ASTSymbolTableBuilder{*ast}; \
ASTNodeDataTypeBuilder{*ast}; \
ASTNodeValueBuilder{*ast}; \
\
std::stringstream ast_output; \
ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::data_value}}; \
\
REQUIRE(ast_output.str() == expected_output); \
}
TEST_CASE("ASTNodeValuebuilder", "[language]")
{
SECTION("integer")
{
std::string_view data = R"(
01;
)";
std::string_view result = R"(
(root:--)
`-(language::integer:01:1)
)";
CHECK_AST_VALUES(data, result);
}
SECTION("real")
{
std::string_view data = R"(
1.300;
)";
std::string_view result = R"(
(root:--)
`-(language::real:1.300:1.3)
)";
CHECK_AST_VALUES(data, result);
}
SECTION("true")
{
std::string_view data = R"(
true;
)";
std::string_view result = R"(
(root:--)
`-(language::true_kw:1)
)";
CHECK_AST_VALUES(data, result);
}
SECTION("false")
{
std::string_view data = R"(
false;
)";
std::string_view result = R"(
(root:--)
`-(language::false_kw:0)
)";
CHECK_AST_VALUES(data, result);
}
SECTION("string")
{
std::string_view data = R"(
"\"foo\" or \"bar\"";
)";
std::string_view result = R"(
(root:--)
`-(language::literal:"\"foo\" or \"bar\"":"\"foo\" or \"bar\"")
)";
CHECK_AST_VALUES(data, result);
}
SECTION("for empty test")
{
std::string_view data = R"(
for(;;);
)";
std::string_view result = R"(
(root:--)
`-(language::for_statement:--)
+-(language::for_init:--)
+-(language::for_test:1)
+-(language::for_post:--)
`-(language::for_statement_bloc:--)
)";
CHECK_AST_VALUES(data, result);
}
SECTION("bloc values")
{
std::string_view data = R"(
{
1;
2.3;
}
)";
std::string_view result = R"(
(root:--)
`-(language::bloc:--)
+-(language::integer:1:1)
`-(language::real:2.3:2.3)
)";
CHECK_AST_VALUES(data, result);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment