Can you help me understand the difference between the a % b
parser and its expanded a >> *(b >> a)
form in Boost.Spirit? Even though the reference manual states that they are equivalent,
The list operator,
a % b
, is a binary operator that matches a list of one or more repetitions ofa
separated by occurrences ofb
. This is equivalent toa >> *(b >> a)
.
the following program produces different results depending on which is used:
#include <iostream>
#include <string>
#include <vector>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
struct Record {
int id;
std::vector<int> values;
};
BOOST_FUSION_ADAPT_STRUCT(Record,
(int, id)
(std::vector<int>, values)
)
int main() {
namespace qi = boost::spirit::qi;
const auto str = std::string{"1: 2, 3, 4"};
const auto rule1 = qi::int_ >> ':' >> (qi::int_ % ',') >> qi::eoi;
const auto rule2 = qi::int_ >> ':' >> (qi::int_ >> *(',' >> qi::int_)) >> qi::eoi;
Record record1;
if (qi::phrase_parse(str.begin(), str.end(), rule1, qi::space, record1)) {
std::cout << record1.id << ": ";
for (const auto& value : record1.values) { std::cout << value << ", "; }
std::cout << '\n';
} else {
std::cerr << "syntax error\n";
}
Record record2;
if (qi::phrase_parse(str.begin(), str.end(), rule2, qi::space, record2)) {
std::cout << record2.id << ": ";
for (const auto& value : record2.values) { std::cout << value << ", "; }
std::cout << '\n';
} else {
std::cerr << "syntax error\n";
}
}
1: 2, 3, 4,
1: 2,
rule1
and rule2
are different only in that rule1
uses the list operator ((qi::int_ % ',')
) and rule2
uses its expanded form ((qi::int_ >> *(',' >> qi::int_))
). However, rule1
produced 1: 2, 3, 4,
(as expected) and rule2
produced 1: 2,
. I cannot understand the result of rule2
: 1) why is it different from that of rule1
and 2) why were 3
and 4
not included in record2.values
even though phrase_parse
returned true somehow?
(int, int, vector<int>)
rather than(int, vector<int>)
. I'm guessingvector<int>
is compatible with a singleint_
and then the repeatedint_
s (within the*(…)
) are ignored when storing values. – Propagandistb
has an attribute (not the case in your example), it is ignored ina%b
but not ina >>*(b >> a)
.a >> *(omit[b] >> a)
would be closer (but with the same problems shown in sehe's answer). – Tarsus