eolian_cxx: rework context code, also more flexible scope indentation generator

Summary:
Context management classes now store constant copies of the tags they
are supposed to hold. So, they are immutable objects now.
Functions that manipulate context create new object copies as needed.
`constexpr` was added for class constructor and functions.

Indentation generator now used four space by default.
Also, the amount of desired spaces can now be specified at call site.

Added helper methods to return 'indented' and 'unindented' version of a
given indentation generator object.

Test Plan: ninja test

Reviewers: felipealmeida, lauromoura

Reviewed By: lauromoura

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D8467
This commit is contained in:
Vitor Sousa 2019-03-22 18:34:29 -03:00
parent a4ae92d8dd
commit 2b86e84b56
2 changed files with 65 additions and 28 deletions

View File

@ -5,33 +5,50 @@ namespace efl { namespace eolian { namespace grammar {
struct context_null {};
template <typename Tag, typename Tail = context_null>
template <typename Tag, typename Tail = context_null>
struct context_cons
{
Tag tag;
Tail const& tail;
};
template <typename Tag>
struct context_cons<Tag, context_null>
{
Tag tag;
context_null tail;
typename std::remove_reference<Tag>::type const tag;
typename std::remove_reference<Tail>::type const tail;
};
template <typename NewTag, typename Tag, typename Tail>
context_cons<NewTag, context_cons<Tag, Tail>>
context_add_tag(NewTag tag, context_cons<Tag, Tail> const& context)
constexpr context_cons<NewTag, context_cons<Tag, Tail>>
context_add_tag(NewTag const& tag, context_cons<Tag, Tail> const& context)
{
return context_cons<NewTag, context_cons<Tag, Tail>>{tag, context};
}
template <typename NewTag>
context_cons<NewTag, context_null>
context_add_tag(NewTag tag, context_null context)
constexpr context_cons<NewTag, context_null>
context_add_tag(NewTag const& tag, context_null context)
{
return context_cons<NewTag, context_null>{tag, context};
}
template <typename Tag, typename SameTag, typename Tail>
constexpr context_cons<SameTag, Tail>
context_replace_tag(Tag const& tag, context_cons<SameTag, Tail> const& context
, typename std::enable_if<std::is_same<Tag, SameTag>::value>::type* = nullptr)
{
return {tag, context.tail};
}
template <typename Tag, typename OtherTag, typename Tail>
constexpr context_cons<OtherTag, Tail>
context_replace_tag(Tag const& tag, context_cons<OtherTag, Tail> const& context
, typename std::enable_if<!std::is_same<Tag, OtherTag>::value>::type* = nullptr)
{
return {context.tag, context_replace_tag(tag, context.tail)};
}
template <typename Tag>
constexpr context_null
context_replace_tag(Tag const& tag, context_null const&)
{
static_assert(std::is_same<Tag, context_null>::value, "Tag type not available in this generation context");
return tag;
}
template <typename Tag, typename Context>
struct tag_check;
template <typename Tag, typename Tail>
@ -42,25 +59,26 @@ template <typename Tag, typename OtherTag, typename Context>
struct tag_check<Tag, context_cons<OtherTag, Context>> : tag_check<Tag, Context> {};
template <typename Tag, typename SameTag, typename Tail>
Tag const& context_find_tag(context_cons<SameTag, Tail> const& context
constexpr Tag const& context_find_tag(context_cons<SameTag, Tail> const& context
, typename std::enable_if<std::is_same<Tag, SameTag>::value>::type* = nullptr)
{
return context.tag;
}
template <typename Tag, typename OtherTag, typename Tail>
Tag const& context_find_tag(context_cons<OtherTag, Tail> const& context
constexpr Tag const& context_find_tag(context_cons<OtherTag, Tail> const& context
, typename std::enable_if<!std::is_same<Tag, OtherTag>::value>::type* = nullptr)
{
return context_find_tag<Tag>(context.tail);
}
template <typename Tag, typename OtherTag, typename Tail>
Tag const& context_find_tag(context_null const&)
template <typename Tag>
constexpr Tag const& context_find_tag(context_null const& context)
{
throw std::logic_error("Context for generation not available");
static_assert(std::is_same<Tag, context_null>::value, "Tag type not available in this generation context");
return context;
}
} } }
#endif

View File

@ -8,22 +8,36 @@ namespace efl { namespace eolian { namespace grammar {
struct scope_tab_generator
{
scope_tab_generator(int n)
: n(n) {}
constexpr scope_tab_generator(int n, int m = 4)
: n(n)
, m(m)
{}
constexpr scope_tab_generator(scope_tab_generator const&) = default;
scope_tab_generator& operator=(scope_tab_generator const&) = default;
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::unused_type, Context const&) const
{
for(int i = 0; i != n; ++i)
{
*sink++ = ' ';
*sink++ = ' ';
*sink++ = ' ';
for(int j = 0; j != m; ++j)
*sink++ = ' ';
}
return true;
}
constexpr scope_tab_generator inc(int nplus = 1) const
{
return {n+nplus, m};
}
constexpr scope_tab_generator dec(int nminus = 1) const
{
return {n-nminus, m};
}
int n;
int m;
};
template <>
@ -33,9 +47,14 @@ struct is_generator<scope_tab_generator> : std::true_type {};
struct scope_tab_terminal
{
scope_tab_generator operator()(int n) const
scope_tab_generator operator()(int n, int m = 4) const
{
return scope_tab_generator(n);
return {n, m};
}
operator scope_tab_generator() const
{
return {1};
}
} const scope_tab = {};