
Kim Kuen Tang wrote:
Hi all,
considering the following expression created with proto:
"3 *var_+5=2;
.. The tree would be : = / \ + 2 / \ * 5 / \ 3 var_
Here the term "var_" is somewhat a placeholder.
I wonder wheter it is possible now to change the structure of the tree. That is i want to define a grammar that is able to produce another expression like this.
"var_=(2-5)/3;"
In tree:
= / \ var_ div / \ - 3 / \ 2 5
With this expression i can now define a context that return the final result of the right hand side. But is this possible in proto with the existing functions?
Yes.
This situation is somewhat different from the examples in the documentation. Here i dont want to replace the child node. The whole structure of the input tree should be transformed in another one.
A general equation solver will be challenging to write, but should be possible. You'll need to familiarize yourself with Proto grammars and transforms. Here is a toy example to get you started. Hope it helps. #include <iostream> #include <boost/proto/proto.hpp> namespace mpl = boost::mpl; namespace proto = boost::proto; namespace fusion = boost::fusion; using proto::_; struct placeholder { friend std::ostream &operator <<(std::ostream &sout, placeholder) { return sout << "var_"; } }; proto::terminal<placeholder>::type const var_ = {{}}; // Work around annoyng msvc compiler bugs ... #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) #define _left(x) call<proto::_left(x)> #define _right(x) call<proto::_right(x)> #define _make_minus(x,y) call<proto::_make_minus(x,y)> #define _make_assign(x,y) call<proto::_make_assign(x,y)> #endif struct Solve : proto::or_< // Solved: proto::assign<proto::terminal<placeholder>, _> // Rewrite "var_ + x = y" to "var_ = y - x" , proto::when< proto::assign< proto::plus<proto::terminal<placeholder>, _> , _ > , proto::_make_assign( proto::_left(proto::_left) , proto::_make_minus( proto::_right , proto::_right(proto::_left) ) ) > > {}; int main() { proto::display_expr( var_ + 1 = 2 ); proto::display_expr( Solve()( var_ + 1 = 2 ) ); } It displays the following:
assign( plus( terminal(var_) , terminal(1) ) , terminal(2) ) assign( terminal(var_) , minus( terminal(2) , terminal(1) ) )
HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com