Actions are one option to process parsed values. Another option is to pass objects to boost::spirit::qi::parse()
or boost::spirit::qi::phrase_parse()
that will be used to store parsed values. These objects are called attributes. Their types must match the parsers’ types.
You have already used attributes in the previous section. Parameters passed to actions are attributes, too. Every parser has an attribute. For example, the parser boost::spirit::qi::int_ has an attribute of type int
. In the following examples, attributes aren’t passed as parameters to functions. Instead, parsed values are stored in attributes and can be processed after boost::spirit::qi::parse()
or boost::spirit::qi::phrase_parse()
return.
int
value in an attribute#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
std::string s;
std::getline(std::cin, s);
auto it = s.begin();
int i;
if (qi::phrase_parse(it, s.end(), qi::int_, ascii::space, i))
std::cout << i << '\n';
}
Example 11.11 uses the parser boost::spirit::qi::int_. The parsed int
value is stored in the variable i. i is passed as another parameter to boost::spirit::qi::phrase_parse()
and, thus, becomes an attribute of the parser boost::spirit::qi::int_.
If you start Example 11.11 and enter a digit, the digit will be written to the standard output stream.
int
values in an attribute#include <boost/spirit/include/qi.hpp>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <iostream>
using namespace boost::spirit;
int main()
{
std::string s;
std::getline(std::cin, s);
auto it = s.begin();
std::vector<int> v;
if (qi::phrase_parse(it, s.end(), qi::int_ % ',', ascii::space, v))
{
std::ostream_iterator<int> out{std::cout, ";"};
std::copy(v.begin(), v.end(), out);
}
}
Example 11.12 uses a parser that is defined with qi::int_ % ','
. The parser accepts any number of integers delimited by commas. As usual spaces are ignored.
Because the parser can return multiple int
values, the attribute’s type must support storing multiple int
values. The example passes a vector. If you start the example and enter multiple integers delimited by commas, the integers are written to the standard output stream delimited by semicolons.
Instead of a vector, you can also pass containers of other types, such as std::list
.
The Boost.Spirit documentation describes which attribute types must be used with which operators.