The Boost C++ Libraries

Attributes

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.

Example 11.11. Storing an 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.

Example 11.12. Storing several 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.