Boost logo

Boost Users :

Subject: Re: [Boost-users] [Proto]: How to use complex grammars in a domain/extension
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2010-09-21 05:55:11


Roland Bock wrote:
> On 09/21/2010 08:54 AM, Joel Falcou wrote:
>> On 20/09/10 22:57, Roland Bock wrote:
>>> typedef proto::terminal<proto::_>::type terminal;
>>>
>>> struct addition:
>>> proto::or_
>>> <
>>> terminal,
>>> proto::plus<addition, addition>
>>> >
>>> {};
>>
>> terminal is a terminal type, not a terminal grammar:
>>
>> struct addition :
>> proto::or_< proto::terminal<proto::_>
>> , proto::plus<addition,addition>
>> > {};
> That did not make a difference:
>
> // -----------------------------------------------------------------
<snip>

Solved the mistery. here is the code, explanation comes afterward:

#include<boost/proto/proto.hpp>

using namespace boost;

typedef proto::terminal<int>::type terminal;

struct addition:
    proto::or_
    <
       proto::plus<addition, addition>,
       proto::terminal<proto::_>
>
{};

struct equation:
    proto::or_
    <
        proto::equal_to<addition, addition>
>
{};

template<class Expr>
struct extension;

struct my_domain:
    proto::domain
    <
         proto::pod_generator< extension>,
         // we need both grammars in our domain grammar
         proto::or_<equation, addition>,
         proto::default_domain
>
{};

template<class Expr>
struct extension
{
     BOOST_PROTO_EXTENDS(
         Expr
       , extension<Expr>
       , my_domain
     )
};

template <typename Grammar, typename Expr>
void matches(Expr const&)
{
     std::cout << std::boolalpha
         << proto::matches<Expr, Grammar>::value << "\n";
}

int main()
{
     extension<terminal> i;
     extension<terminal> j;

     matches<equation>(i); // 1) false
     matches<equation>(i == j); // 2) true
     matches<equation>(i == i + i); // 3) true
     matches<equation>(i + i == i); // 4) true
     matches<equation>(i + i == i + i); // 5) true
     matches<equation>(i + i); // 6) false
}

Ok, what happened, why does this work, and why didn't the previous attempt
work:

the equation grammar obviously doesn't match case 1) and 6). And that is
exactly why proto didn't generate any operator+ overload.
In order for a proto overload to be created the following conditions must be
true:

1) the operands must be in a compatible domain
2) the left hand operand and the right hand operand must match the grammar
specified in the domain
3) the resulting expression must match the grammar specified in the domain.

In our example 1) is always true. 2) and 3) are not true for expressions
like 1) and 6). That means, that any binary operator gets disabled whenever
the LHS or the RHS is a terminal<_>. because of the equation grammar,
terminals or additions can not stand alone, that is why operator creation
failed. Makes sense!
In order to enable the operators, we just say, our domain can have addition
_or_ equation. That's it, operator+ and operator== get enabled.
We can still detect invalid expression with proto::matches!

So, everything works as expected!

>
>
> Regards,
>
> Roland


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net