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

Create ASTNodeDataTypeBuilder

continue clean-up
parent 0ebdb2d9
No related branches found
No related tags found
1 merge request!37Feature/language
#include <ASTNodeDataTypeBuilder.hpp>
#include <PEGGrammar.hpp>
#include <PugsAssert.hpp>
#include <SymbolTable.hpp>
void
ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
{
if (n.is<language::bloc>() or n.is<language::for_statement>()) {
for (auto& child : n.children) {
this->_buildNodeDataTypes(*child);
}
n.m_data_type = ASTNodeDataType::void_t;
} else {
if (n.has_content()) {
if (n.is<language::true_kw>() or n.is<language::false_kw>()) {
n.m_data_type = ASTNodeDataType::bool_t;
} else if (n.is<language::real>()) {
n.m_data_type = ASTNodeDataType::double_t;
} else if (n.is<language::integer>()) {
n.m_data_type = ASTNodeDataType::int_t;
} else if (n.is<language::literal>()) {
n.m_data_type = ASTNodeDataType::string_t;
} else if (n.is<language::cout_kw>() or n.is<language::cerr_kw>() or n.is<language::clog_kw>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::declaration>()) {
auto& type_node = *(n.children[0]);
ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
if (type_node.is<language::B_set>()) {
data_type = ASTNodeDataType::bool_t;
} else if (type_node.is<language::Z_set>()) {
data_type = ASTNodeDataType::int_t;
} else if (type_node.is<language::N_set>()) {
data_type = ASTNodeDataType::unsigned_int_t;
} else if (type_node.is<language::R_set>()) {
data_type = ASTNodeDataType::double_t;
} else if (type_node.is<language::string_type>()) {
data_type = ASTNodeDataType::string_t;
}
if (data_type == ASTNodeDataType::undefined_t) {
throw parse_error("unexpected error: invalid datatype", type_node.begin());
}
type_node.m_data_type = ASTNodeDataType::void_t;
n.children[1]->m_data_type = data_type;
const std::string& symbol = n.children[1]->string();
std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
auto [i_symbol, found] = symbol_table->find(symbol);
Assert(found);
i_symbol->second.setDataType(data_type);
n.m_data_type = data_type;
} else if (n.is<language::name>()) {
std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
auto [i_symbol, found] = symbol_table->find(n.string());
Assert(found);
n.m_data_type = i_symbol->second.dataType();
}
}
for (auto& child : n.children) {
this->_buildNodeDataTypes(*child);
}
if (n.is<language::break_kw>() or n.is<language::continue_kw>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::eq_op>() or n.is<language::multiplyeq_op>() or n.is<language::divideeq_op>() or
n.is<language::pluseq_op>() or n.is<language::minuseq_op>() or n.is<language::bit_andeq_op>() or
n.is<language::bit_xoreq_op>() or n.is<language::bit_oreq_op>()) {
n.m_data_type = n.children[0]->m_data_type;
} else if (n.is<language::for_statement>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::for_post>() or n.is<language::for_init>() or n.is<language::for_statement_bloc>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::for_test>()) {
n.m_data_type = ASTNodeDataType::bool_t;
} else if (n.is<language::statement_bloc>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::if_statement>() or n.is<language::while_statement>()) {
n.m_data_type = ASTNodeDataType::void_t;
if ((n.children[0]->m_data_type > ASTNodeDataType::double_t) or
(n.children[0]->m_data_type < ASTNodeDataType::bool_t)) {
const ASTNodeDataType type_0 = n.children[0]->m_data_type;
std::ostringstream message;
message << "Cannot convert data type to boolean value\n"
<< "note: incompatible operand '" << n.children[0]->string() << "' of type " << dataTypeName(type_0)
<< std::ends;
throw parse_error(message.str(), n.children[0]->begin());
}
} else if (n.is<language::do_while_statement>()) {
n.m_data_type = ASTNodeDataType::void_t;
if ((n.children[1]->m_data_type > ASTNodeDataType::double_t) or
(n.children[1]->m_data_type < ASTNodeDataType::bool_t)) {
const ASTNodeDataType type_0 = n.children[1]->m_data_type;
std::ostringstream message;
message << "Cannot convert data type to boolean value\n"
<< "note: incompatible operand '" << n.children[1]->string() << "' of type " << dataTypeName(type_0)
<< std::ends;
throw parse_error(message.str(), n.children[1]->begin());
}
} else if (n.is<language::unary_not>() or n.is<language::lesser_op>() or n.is<language::lesser_or_eq_op>() or
n.is<language::greater_op>() or n.is<language::greater_or_eq_op>() or n.is<language::eqeq_op>() or
n.is<language::not_eq_op>() or n.is<language::and_op>() or n.is<language::or_op>() or
n.is<language::xor_op>() or n.is<language::bitand_op>() or n.is<language::bitor_op>()) {
n.m_data_type = ASTNodeDataType::bool_t;
} else if (n.is<language::unary_minus>() or n.is<language::unary_plus>() or n.is<language::unary_plusplus>() or
n.is<language::unary_minusminus>()) {
n.m_data_type = n.children[0]->m_data_type;
} else if (n.is<language::plus_op>() or n.is<language::minus_op>() or n.is<language::multiply_op>() or
n.is<language::divide_op>()) {
const ASTNodeDataType type_0 = n.children[0]->m_data_type;
const ASTNodeDataType type_1 = n.children[1]->m_data_type;
n.m_data_type = dataTypePromotion(type_0, type_1);
if (n.m_data_type == ASTNodeDataType::undefined_t) {
std::ostringstream message;
message << "undefined binary operator\n"
<< "note: incompatible operand types " << n.children[0]->string() << " (" << dataTypeName(type_0)
<< ") and " << n.children[1]->string() << " (" << dataTypeName(type_1) << ')' << std::ends;
throw parse_error(message.str(), n.begin());
}
}
}
}
ASTNodeDataTypeBuilder::ASTNodeDataTypeBuilder(ASTNode& node)
{
Assert(node.is_root());
node.m_data_type = ASTNodeDataType::void_t;
this->_buildNodeDataTypes(node);
std::cout << " - build node data types\n";
}
#ifndef AST_NODE_DATA_TYPE_BUILDER_HPP
#define AST_NODE_DATA_TYPE_BUILDER_HPP
#include <ASTNode.hpp>
class ASTNodeDataTypeBuilder
{
private:
void _buildNodeDataTypes(ASTNode& node);
public:
ASTNodeDataTypeBuilder(ASTNode& root_node);
};
#endif // AST_NODE_DATA_TYPE_BUILDER_HPP
......@@ -8,6 +8,7 @@ add_library(
ASTBuilder.cpp
ASTDotPrinter.cpp
ASTNodeDataType.cpp
ASTNodeDataTypeBuilder.cpp
ASTNodeAffectationExpressionBuilder.cpp
ASTNodeBinaryOperatorExpressionBuilder.cpp
ASTNodeExpressionBuilder.cpp
......
......@@ -19,6 +19,8 @@
#include <PEGGrammar.hpp>
#include <SymbolTable.hpp>
#include <ASTNodeDataTypeBuilder.hpp>
#include <EscapedString.hpp>
#include <ASTNodeExpressionBuilder.hpp>
......@@ -31,141 +33,6 @@
namespace language
{
namespace internal
{
void
build_node_data_types(ASTNode& n)
{
if (n.is<language::bloc>() or n.is<for_statement>()) {
if (!n.children.empty()) {
for (auto& child : n.children) {
build_node_data_types(*child);
}
}
n.m_data_type = ASTNodeDataType::void_t;
} else {
if (n.has_content()) {
if (n.is<language::true_kw>() or n.is<language::false_kw>() or n.is<language::do_kw>()) {
n.m_data_type = ASTNodeDataType::bool_t;
} else if (n.is<language::real>()) {
n.m_data_type = ASTNodeDataType::double_t;
} else if (n.is<language::integer>()) {
n.m_data_type = ASTNodeDataType::int_t;
} else if (n.is<language::literal>()) {
n.m_data_type = ASTNodeDataType::string_t;
} else if (n.is<language::cout_kw>() or n.is<language::cerr_kw>() or n.is<language::clog_kw>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::declaration>()) {
auto& type_node = *(n.children[0]);
ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
if (type_node.is<language::B_set>()) {
data_type = ASTNodeDataType::bool_t;
} else if (type_node.is<language::Z_set>()) {
data_type = ASTNodeDataType::int_t;
} else if (type_node.is<language::N_set>()) {
data_type = ASTNodeDataType::unsigned_int_t;
} else if (type_node.is<language::R_set>()) {
data_type = ASTNodeDataType::double_t;
} else if (type_node.is<language::string_type>()) {
data_type = ASTNodeDataType::string_t;
}
if (data_type == ASTNodeDataType::undefined_t) {
throw parse_error("unexpected error: invalid datatype", type_node.begin());
}
type_node.m_data_type = ASTNodeDataType::void_t;
n.children[1]->m_data_type = data_type;
const std::string& symbol = n.children[1]->string();
std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
auto [i_symbol, found] = symbol_table->find(symbol);
Assert(found);
i_symbol->second.setDataType(data_type);
n.m_data_type = data_type;
} else if (n.is<language::name>()) {
std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
auto [i_symbol, found] = symbol_table->find(n.string());
Assert(found);
n.m_data_type = i_symbol->second.dataType();
}
}
for (auto& child : n.children) {
build_node_data_types(*child);
}
if (n.is<language::break_kw>() or n.is<language::continue_kw>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::eq_op>() or n.is<language::multiplyeq_op>() or n.is<language::divideeq_op>() or
n.is<language::pluseq_op>() or n.is<language::minuseq_op>() or n.is<language::bit_andeq_op>() or
n.is<language::bit_xoreq_op>() or n.is<language::bit_oreq_op>()) {
n.m_data_type = n.children[0]->m_data_type;
} else if (n.is<language::for_statement>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::for_post>() or n.is<language::for_init>() or n.is<language::for_statement_bloc>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::for_test>()) {
n.m_data_type = ASTNodeDataType::bool_t;
} else if (n.is<language::statement_bloc>()) {
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is<language::if_statement>() or n.is<language::while_statement>()) {
n.m_data_type = ASTNodeDataType::void_t;
if ((n.children[0]->m_data_type > ASTNodeDataType::double_t) or
(n.children[0]->m_data_type < ASTNodeDataType::bool_t)) {
const ASTNodeDataType type_0 = n.children[0]->m_data_type;
std::ostringstream message;
message << "Cannot convert data type to boolean value\n"
<< "note: incompatible operand '" << n.children[0]->string() << " of type ' (" << dataTypeName(type_0)
<< ')' << std::ends;
throw parse_error(message.str(), n.children[0]->begin());
}
} else if (n.is<language::do_while_statement>()) {
n.m_data_type = ASTNodeDataType::void_t;
if ((n.children[1]->m_data_type > ASTNodeDataType::double_t) or
(n.children[1]->m_data_type < ASTNodeDataType::bool_t)) {
const ASTNodeDataType type_0 = n.children[1]->m_data_type;
std::ostringstream message;
message << "Cannot convert data type to boolean value\n"
<< "note: incompatible operand '" << n.children[1]->string() << " of type ' (" << dataTypeName(type_0)
<< ')' << std::ends;
throw parse_error(message.str(), n.children[1]->begin());
}
} else if (n.is<language::unary_not>() or n.is<language::lesser_op>() or n.is<language::lesser_or_eq_op>() or
n.is<language::greater_op>() or n.is<language::greater_or_eq_op>() or n.is<language::eqeq_op>() or
n.is<language::not_eq_op>() or n.is<language::and_op>() or n.is<language::or_op>() or
n.is<language::xor_op>() or n.is<language::bitand_op>() or n.is<language::bitor_op>()) {
n.m_data_type = ASTNodeDataType::bool_t;
} else if (n.is<language::unary_minus>() or n.is<language::unary_plus>() or n.is<language::unary_plusplus>() or
n.is<language::unary_minusminus>()) {
n.m_data_type = n.children[0]->m_data_type;
} else if (n.is<language::plus_op>() or n.is<language::minus_op>() or n.is<language::multiply_op>() or
n.is<language::divide_op>()) {
const ASTNodeDataType type_0 = n.children[0]->m_data_type;
const ASTNodeDataType type_1 = n.children[1]->m_data_type;
n.m_data_type = dataTypePromotion(type_0, type_1);
if (n.m_data_type == ASTNodeDataType::undefined_t) {
std::ostringstream message;
message << "undefined binary operator\n"
<< "note: incompatible operand types " << n.children[0]->string() << " (" << dataTypeName(type_0)
<< ") and " << n.children[1]->string() << " (" << dataTypeName(type_1) << ')' << std::ends;
throw parse_error(message.str(), n.begin());
}
}
}
}
} // namespace internal
void
build_node_data_types(ASTNode& n)
{
Assert(n.is_root());
n.m_data_type = ASTNodeDataType::void_t;
internal::build_node_data_types(n);
std::cout << " - build node data types\n";
}
namespace internal
{
void
......@@ -332,7 +199,7 @@ parser(const std::string& filename)
std::cout << " AST dot file: " << dot_filename << '\n';
}
language::build_node_data_types(*root_node);
ASTNodeDataTypeBuilder{*root_node};
language::check_node_data_types(*root_node);
language::build_node_values(*root_node);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment