Select Git revision
ASTBuilder.cpp
ASTBuilder.cpp 10.05 KiB
#include <ASTBuilder.hpp>
using namespace TAO_PEGTL_NAMESPACE;
#include <ASTNode.hpp>
#include <PEGGrammar.hpp>
#include <pegtl/contrib/parse_tree.hpp>
using namespace language;
struct ASTBuilder::rearrange : parse_tree::apply<ASTBuilder::rearrange>
{
template <typename... States>
static void
transform(std::unique_ptr<Node>& n, States&&... st)
{
if (n->children.size() == 1) {
n = std::move(n->children.back());
} else {
// First we rearrange tree
{
n->remove_content();
auto& children = n->children;
auto rhs = std::move(children.back());
children.pop_back();
auto op = std::move(children.back());
children.pop_back();
op->children.emplace_back(std::move(n));
op->children.emplace_back(std::move(rhs));
n = std::move(op);
transform(n->children.front(), st...);
}
// Then we eventually simplify operations
{
if (n->is<language::minus_op>()) {
Assert(n->children.size() == 2);
auto& rhs = n->children[1];
if (rhs->is<language::unary_minus>()) {
rhs->remove_content();
n->id = typeid(language::plus_op);
rhs = std::move(rhs->children[0]);
}
} else if (n->is<language::plus_op>()) {
Assert(n->children.size() == 2);
auto& rhs = n->children[1];
if (rhs->is<language::unary_minus>()) {
rhs->remove_content();
n->id = typeid(language::minus_op);
rhs = std::move(rhs->children[0]);
}
}
}
}
}
};
struct ASTBuilder::simplify_unary : parse_tree::apply<ASTBuilder::simplify_unary>
{
template <typename... States>
static void
transform(std::unique_ptr<Node>& n, States&&... st)
{
if (n->children.size() == 1) {
if (n->is<unary_expression>()) {
n->remove_content();
n = std::move(n->children.back());
transform(n, st...);
} else if (n->is<unary_minus>()) {
auto& child = n->children[0];
if (child->is<unary_minus>()) {
n->remove_content();
child->remove_content();
n = std::move(child->children[0]);
transform(n, st...);
}
} else if (n->is<unary_not>()) {
auto& child = n->children[0];
if (child->is<unary_not>()) {
n->remove_content();
child->remove_content();
n = std::move(child->children[0]);
transform(n, st...);
}
}
} else if (n->children.size() == 2) {
if (n->children[0]->is<language::unary_plus>()) {
n->remove_content();
n = std::move(n->children[1]);
transform(n, st...);
} else if (n->children[0]->is<language::unary_minus>() or n->children[0]->is<language::unary_not>() or
n->children[0]->is<language::unary_minusminus>() or n->children[0]->is<language::unary_plusplus>()) {
n->remove_content();
auto expression = std::move(n->children[1]);
auto unary_operator = std::move(n->children[0]);
unary_operator->children.emplace_back(std::move(expression));
n = std::move(unary_operator);
n->remove_content();
transform(n, st...);
} else if (n->children[1]->is<language::post_minusminus>() or n->children[1]->is<language::post_plusplus>()) {
n->remove_content();
auto expression = std::move(n->children[0]);
auto unary_operator = std::move(n->children[1]);
unary_operator->children.emplace_back(std::move(expression));
n = std::move(unary_operator);
n->remove_content();
transform(n, st...);
}
}
}
};
struct ASTBuilder::simplify_statement_bloc : parse_tree::apply<ASTBuilder::simplify_statement_bloc>
{
template <typename... States>
static void
transform(std::unique_ptr<Node>& n, States&&... st)
{
if (n->children.size() == 1) {
if (not n->children[0]->is<language::declaration>()) {
n->remove_content();
n = std::move(n->children.back());
transform(n, st...);
} else {
n->id = typeid(language::bloc);
}
}
}
};
struct ASTBuilder::simplify_for_statement_bloc : parse_tree::apply<ASTBuilder::simplify_for_statement_bloc>
{
template <typename... States>
static void
transform(std::unique_ptr<Node>& n, States&&... st)
{
if (n->children.size() == 1) {
n->remove_content();
n = std::move(n->children.back());
transform(n, st...);
}
}
};
struct ASTBuilder::simplify_for_init : parse_tree::apply<ASTBuilder::simplify_for_init>
{
template <typename... States>
static void
transform(std::unique_ptr<Node>& n, States&&...)
{
Assert(n->children.size() <= 1);
if (n->children.size() == 1) {
n->remove_content();
n = std::move(n->children.back());
}
}
};
struct ASTBuilder::simplify_for_test : parse_tree::apply<ASTBuilder::simplify_for_test>
{
template <typename... States>
static void
transform(std::unique_ptr<Node>& n, States&&...)
{
Assert(n->children.size() <= 1);
if (n->children.size() == 1) {
n->remove_content();
n = std::move(n->children.back());
}
}
};
struct ASTBuilder::simplify_for_post : parse_tree::apply<ASTBuilder::simplify_for_post>
{
template <typename... States>
static void
transform(std::unique_ptr<Node>& n, States&&...)
{
Assert(n->children.size() <= 1);
if (n->children.size() == 1) {
n->remove_content();
n = std::move(n->children.back());
}
}
};
struct ASTBuilder::simplify_stream_statement : parse_tree::apply<ASTBuilder::simplify_stream_statement>
{
template <typename... States>
static void
transform(std::unique_ptr<Node>& n, States&&...)
{
for (size_t i = 1; i < n->children.size(); ++i) {
n->children[0]->children.emplace_back(std::move(n->children[i]));
}
n->remove_content();
n = std::move(n->children[0]);
}
};
template <typename Rule>
using selector =
parse_tree::selector<Rule,
parse_tree::store_content::on<true_kw,
false_kw,
integer,
real,
literal,
name,
B_set,
N_set,
Z_set,
R_set,
string_type,
cout_kw,
cerr_kw,
clog_kw,
declaration,
if_statement,
do_while_statement,
while_statement,
for_statement,
break_kw,
continue_kw>,
ASTBuilder::rearrange::on<product, affectation, expression>,
ASTBuilder::simplify_unary::on<unary_minus, unary_plus, unary_not, unary_expression>,
parse_tree::remove_content::on<plus_op,
minus_op,
multiply_op,
divide_op,
lesser_op,
lesser_or_eq_op,
greater_op,
greater_or_eq_op,
eqeq_op,
not_eq_op,
and_op,
or_op,
xor_op,
bitand_op,
bitor_op,
eq_op,
multiplyeq_op,
divideeq_op,
pluseq_op,
minuseq_op,
bit_andeq_op,
bit_xoreq_op,
bit_oreq_op,
unary_plusplus,
unary_minusminus,
post_minusminus,
post_plusplus>,
ASTBuilder::simplify_for_statement_bloc::on<for_statement_bloc>,
parse_tree::discard_empty::on<ignored, semicol, bloc>,
ASTBuilder::simplify_statement_bloc::on<statement_bloc>,
ASTBuilder::simplify_for_init::on<for_init>,
ASTBuilder::simplify_for_test::on<for_test>,
ASTBuilder::simplify_for_post::on<for_post>,
ASTBuilder::simplify_stream_statement::on<ostream_statement>>;
template <typename InputT>
std::unique_ptr<language::Node>
ASTBuilder::build(InputT& input)
{
return parse_tree::parse<language::grammar, language::Node, selector, nothing, language::errors>(input);
}
template std::unique_ptr<language::Node> ASTBuilder::build(read_input<>& input);
template std::unique_ptr<language::Node> ASTBuilder::build(string_input<>& input);