Re: x3 beginner semantic actions
Henri Menke <[email protected]> Wed, 25 Apr 2018 11:09:06 +1200
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
On Tue, 2018-04-24 at 15:48 +0100, Patrick Welche wrote:
> In a bid to understand semantic actions a bit better, I thought I would
> try to write an x3 program to count the number of + and - (think heads
> and tails) in a sequence. The aim was to see:
>
> 1) how to deal with matching on a char, but wanting to use an int as
> attribute,
> i.e., not the expected type of attribute.
> 2) how to select which int buried inside a struct to use
> 3) how to initialise said int
>
> 1) might be doable with e.g.
>
> auto const head
> = rule<class _, int, true>
> = lit('+') // [addhead]
> ;
>
> 2) given that toss is int or int, it is just an int, so presumably
> tosses.heads always gets sent to head or tail?
>
> 3) I don't see how to not overwrite the result with the initialisation
>
> Presumably this is just the wrong way of looking at it. (I don't want to
> "cheat" and have external variables which the lambda change directly -
> or is that the only way?)
- Use eps [zerotosses] to initialize the attribute to zero. I use aggregate
initialization because this is C++14.
auto zerotosses = [&](auto& ctx){
boost::spirit::x3::_val(ctx) = {0,0};
};
- addhead and addtail should increment the heads and tails members.
auto addhead = [&](auto& ctx){
boost::spirit::x3::_val(ctx).heads++;
};
auto addtail = [&](auto& ctx){
boost::spirit::x3::_val(ctx).tails++;
};
You shouldn't use semantic actions for this at all but I guess you know that.
Use x3::symbols instead.
Cheers, Henri
>
>
> Cheers,
>
> Patrick
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Spirit-general mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/spirit-general
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general
coin.cpp
(text/x-c++src, 1.6 KB)
#define BOOST_SPIRIT_X3_DEBUG
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
struct tosses {
int heads;
int tails;
};
BOOST_FUSION_ADAPT_STRUCT(tosses, heads, tails)
int main()
{
std::string buf("++--+-++++-");
auto iter = buf.begin(), end = buf.end();
auto peek = [&](auto& ctx){
std::cout << "peek["
<< boost::spirit::x3::_attr(ctx)
<< ']' << std::endl;
};
auto zerotosses = [&](auto& ctx){
boost::spirit::x3::_val(ctx) = {0,0};
};
auto addhead = [&](auto& ctx){
boost::spirit::x3::_val(ctx).heads++;
};
auto addtail = [&](auto& ctx){
boost::spirit::x3::_val(ctx).tails++;
};
auto parser = [&]{
using namespace boost::spirit::x3;
auto const head
= lit('+') [addhead]
;
auto const tail
= lit('-') [addtail]
;
auto const toss
= head | tail
;
auto const tosses
= eps [zerotosses]
>> (+toss)
;
return rule<struct _, struct tosses> {"parser"} = skip(space) [ tosses ];
};
tosses res;
boost::spirit::x3::ascii::space_type space;
bool ok = boost::spirit::x3::phrase_parse(iter, end, parser(), space, res);
if (ok) {
std::cout << "Parse success\n";
}
else {
std::cout << "Parsing failed\n";
}
if (iter != end) {
std::cout << "Bit left over at the end: " << std::string(iter, end) << std::endl;
}
else {
std::cout << "heads: " << res.heads << std::endl
<< "tails: " << res.tails << std::endl;
}
return 0;
}