
On Thu, Feb 22, 2024 at 4:36 PM Christian Mazakas via Boost <boost@lists.boost.org> wrote:
[snip]
### The Feedback
The differences between Spirit.X3 and Parser need to be made much more clear by the documentation, by which I mean:
* Spirit X3 has rules that do not compose well — the attributes produced by a rule can change depending on the context in which you use the rule.
I will add this to the docs as well, but I thought I'd post here an example of what I was referring to above. Here is a complete program using X3: #include <boost/spirit/home/x3.hpp> #include <iostream> #include <set> #include <string> #include <vector> namespace x3 = boost::spirit::x3; using ints_type = x3::rule<class ints, std::vector<int>>; BOOST_SPIRIT_DECLARE(ints_type); x3::rule<class ints, std::vector<int>> ints = "ints"; constexpr auto ints_def = x3::int_ % ','; BOOST_SPIRIT_DEFINE(ints); #define FIXED_ATTRIBUTE 0 int main() { std::string input = "43, 42"; auto first = input.begin(); auto const last = input.end(); #if FIXED_ATTRIBUTE std::vector<int> result; #else std::set<int> result; #endif bool success = x3::phrase_parse(first, last, ints, x3::space, result); if (success) { // We want this to print "43 42\n". for (auto x : result) { std::cout << x << ' '; } std::cout << "\n"; } return 0; } IMO, the problem with this is that, even though I specified a vector as the rule's attribute type, I can feed the rule a set (#define FIXED_ATTRIBUTE 1), and it happily populates it with the parsed values. Note that this sorts, and in this case reorders, the values. I think this looseness is important in many cases, but there's no way to turn it off in X3. In Parser the way to turn it off is to use a rule instead of a parser. My inability to disable this looseness resulted in wrong results in an X3 YAML parser I was working on. I really loved so much of the design of X3, that my frustration with this problem was a pretty big part of the motivation for writing Parser. Zach