Re: How to use functions in the semantic actions?
Larry Evans <[email protected]> Sat, 17 Oct 2020 10:11:21 -0500
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
On 10/12/20 6:50 PM, Juan Dent wrote:
> amount =3D uint3_p[_val =3D _1]
> =
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 >> *(','
> =
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 >> uint3_3_p)[_val *=3D 100=
0][_val +=3D _1]
> =
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 >> +('.'
> =
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 >> uint1_7_p)[_val +=3D _1/=
10000.0][_val =3D
> produce_decimal_value(_val)]
> =
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ;
> =
> }
> =
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 template<typename T>
> =
> =A0=A0=A0 constexpr T produce_decimal_value(T local)
> =
> =A0=A0=A0 {
> =
> =A0=A0=A0=A0=A0=A0=A0 if (local =3D=3D 0)=A0=A0=A0=A0 // error C2451: con=
ditional expression of
> type 'const boost::phoenix::actor<Expr>' is illegal
> =
> =A0=A0=A0=A0=A0=A0=A0 {}
> =
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // need t=
o manipulate the value of _val which I
> capture here using templates
> =
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 //
> =
> =A0=A0=A0=A0=A0=A0=A0=A0return local;
> =
> =A0=A0=A0 }
> =
> =A0
> =
> How can I manipulate the value of=A0=A0 _/val in a member function of the
> grammar (i.e. produce/_decimal_value)?
> =
> I need to check when local reaches 0 in order to calculate the digits
> after the decimal point but it won=92t allow me from method of grammar cl=
ass=85
> =
> =A0
> =
> Please some direction here=85
> It=92s funny, I can manipulate the numeric vales or _val and _1 inside the
> constructor of the grammar but not from a user defined method of same
> grammar. When I try to use _val =A0as a number it throws errors=85
> =
> =A0
> =
> Regards,
> =
> Juan
> =
Using phoenix::bind gets right result in following code:
#include <iostream>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/optional/optional_io.hpp>
namespace qi=3Dboost::spirit::qi;
namespace phoenix =3D boost::phoenix;
namespace ascii =3D boost::spirit::ascii;
using result_type=3Dlong double;
namespace client
{
template <typename Iterator>
struct Base10_grammar
: qi::grammar<Iterator, result_type(), ascii::space_type >
{
static void
whole_fract
( result_type& value
, unsigned const& attr1
, std::vector<unsigned> const& attr2
, boost::optional<std::vector<unsigned int> >const& attr3
)
{
value=3Dresult_type(attr1);
result_type factor=3D1000.0;
for(unsigned part:attr2)
{
value=3Dvalue*factor+result_type(part);
}
if (attr3)
{
factor=3D1.0;
auto const& digits=3D*attr3;
for(unsigned part:digits)
{
factor*=3D0.1;
value+=3Dpart*factor;
}
}
}
Base10_grammar() : Base10_grammar::base_type(amount)
{
amount =3D
(
( uint1_3_p
>> *( ','
>> uint3_3_p
)
)
>> -( '.'
>> (*uint1_1_p)
)
)
[ phoenix::bind
( &whole_fract
, qi::_val
, qi::_1
, qi::_2
, qi::_3
)
]
;
}
qi::rule<Iterator, result_type(), ascii::space_type> amount;
qi::uint_parser<unsigned, 10, 1, 3> uint1_3_p; // 1..3 digits
qi::uint_parser<unsigned, 10, 3, 3> uint3_3_p; // exactly 3 digits
qi::uint_parser<unsigned, 10, 1, 1> uint1_1_p; // exactly 1 digit
};
}//client namespace
/////////////////////////////
// called from:
int main(int argc, char** argv)
{
std::locale loc("");
std::cout.imbue(loc);
std::string storage =3D "100,200,300.00123";
std::cout<<"storage=3D"<<storage<<"\n";
typedef client::Base10_grammar <std::string::const_iterator>
Base10_grammar;
Base10_grammar g; // Our grammar
using boost::spirit::ascii::space;
std::string::const_iterator iter =3D storage.begin();
std::string::const_iterator end =3D storage.end();
result_type value;
bool r =3D qi::phrase_parse(iter, end, g, space, value);
if (r && iter =3D=3D end)
{
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << "-------------------------\n";
std::cout <<
"value=3D"<<std::fixed<<std::setprecision(10)<<value<<"\n";
return 0;
}
else
{
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
return 1;
}
}
the std::cout output is:
storage=3D100,200,300.00123
-------------------------
Parsing succeeded
-------------------------
value=3D100,200,300.0012300000