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(
PugsLanguage
ASTBuilder.cpp
ASTDotPrinter.cpp
ASTNodeAffectationExpressionBuilder.cpp
ASTNodeBinaryOperatorExpressionBuilder.cpp
ASTNodeDataType.cpp
ASTNodeDataTypeBuilder.cpp
ASTNodeDataTypeChecker.cpp
ASTNodeAffectationExpressionBuilder.cpp
ASTNodeBinaryOperatorExpressionBuilder.cpp
ASTNodeExpressionBuilder.cpp
ASTNodeIncDecExpressionBuilder.cpp
ASTNodeUnaryOperatorExpressionBuilder.cpp
ASTNodeValueBuilder.cpp
ASTPrinter.cpp
ASTSymbolTableBuilder.cpp
ASTSymbolInitializationChecker.cpp
......
......@@ -22,8 +22,6 @@
#include <ASTNodeDataTypeBuilder.hpp>
#include <ASTNodeDataTypeChecker.hpp>
#include <EscapedString.hpp>
#include <ASTNodeExpressionBuilder.hpp>
#include <ASTSymbolInitializationChecker.hpp>
......@@ -32,63 +30,10 @@
#include <ASTDotPrinter.hpp>
#include <ASTPrinter.hpp>
namespace language
{
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
#include <ASTNodeValueBuilder.hpp>
void
build_node_values(ASTNode& n)
namespace language
{
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
{
void
......@@ -179,7 +124,7 @@ parser(const std::string& filename)
ASTNodeDataTypeBuilder{*root_node};
ASTNodeDataTypeChecker{*root_node};
language::build_node_values(*root_node);
ASTNodeValueBuilder{*root_node};
language::check_break_or_continue_placement(*root_node);
......
......@@ -5,11 +5,12 @@ add_executable (unit_tests
test_main.cpp
test_Array.cpp
test_ArrayUtils.cpp
test_ASTDotPrinter.cpp
test_ASTBuilder.cpp
test_ASTDotPrinter.cpp
test_ASTNodeDataType.cpp
test_ASTNodeDataTypeBuilder.cpp
test_ASTNodeDataTypeChecker.cpp
test_ASTNodeValueBuilder.cpp
test_ASTPrinter.cpp
test_ASTSymbolTableBuilder.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