x3 beginner semantic actions

Patrick Welche <[email protected]> Tue, 24 Apr 2018 15:48:13 +0100
Newsgroups gmane.comp.parsers.spirit.general
Message-ID <20180424144813.GA19902@quark>
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?)


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
coin.cpp (text/plain, 1.5 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::_attr(ctx)=0;
		};
	auto addhead = [&](auto& ctx){
		boost::spirit::x3::_val(ctx)++;
		};
	auto addtail = [&](auto& ctx){
		boost::spirit::x3::_val(ctx)--;
		};
	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
			= +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;
}