-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
optional sequence returns #67
Comments
Yeah, that doesn't work, but again, that's what rules are for. You can create a rule like: bp::rule<struct ps_tag, std::vector<P>> ps = "ps";
auto ps_def = (bp::char_ >> bp::int_) % ',') | bp::eps; And that will work fine I think. Rules exist explicitly for this purpose -- to fix the attribute type to something other than the default. |
According to the docs, that would actually be three lines: bp::rule<struct ps_tag, std::vector<P>> ps = "ps";
auto ps_def = ((bp::char_ >> bp::int_) % ',') | bp::eps;
BOOST_PARSER_DEFINE_RULE(ps); And I find it quite problematic. My whole parser looks like this: This will now break when I need to inject the rule definitions. And I have two of them. BTW, is there a way to define a generic rule? That is, can I specify a rule that applies my pattern (parse |
I told you earlier the problems I have with the attribute combination logic in Spirit. I don't really think making your example stick to 15 lines instead of 20 is a very strong counter-argument. Also, the Boost.Parser version could lose 29 lines of ADAPTed_STRUCTs.
Well, a rule is just a variable, and you can make variable templates. The fact that the tag type needs to depend on the template parameter is a small wrinkle, but something like this: template<typename P>
struct my_rule_tag {};
template<typename P, typename Attr>
bp::rule<my_rule_tag<P>, std::vector<Attr>> my_rule = "my_rule";
template<typename P, typename Attr>
constexpr auto my_rule_def = (P{} % ',') | bp::attr(std::vector<Attr>{}); ... might work, but you'll have to write out the function overloads that would normally be generated by template<typename P>
constexpr auto no_attr_repeated_p = omit[*p]; |
I acknowledge your goal of having simple attribute merge rules. I am therefore exploring other options. Parametrized rule may not be possible. But a directive looks like something that is already parametrized by the parser. Is it possible to provide a tool for defining custom directives? |
Maybe? This is just not something that comes up very often. In fact, I've never needed such functionality in years and years of using Spirit to write dozens of parsers. However, I think if I had a compelling use case, I could be persuaded. |
Ok, so the regression of Boost.Parser relative to Boost.Spirit is that for the parser that needs to parse "zero-or-more occurrences of comma-separated items", I no longer can define it at function or block scope. The only way for me is to use a rule, but a rule can only be defined at namespace scope. In my program, as long as I were using Boost.Spirit, i was able to encapsulate my parser in a single function body. |
Yes, that's correct, except for the characterization of "regression". It's more like choosing a slightly different set of trade-offs. Some things to note, though. Rules and parsers are constant data. Are you really that sensitive to where you define your constants? I tend to have lots of namespace-scope contants, and it never caused me any aggravation. I care about where code is when it affects my ability to do local reasoning. With code that describes constants... not so much. Also, so far you've been treating rules as this weird thing that you have to put up with. Most people who use Spirit (and later Parser) have, and will continue to, use rules all the time. I encourage you to embrace them as well. Except for the smallest parsers, rules are essential for organizing things, and writing good tests in particular. |
My reservation is not towards rules in general, but towards their interface in Boost.Parser. I will describe it in a separate issue. |
Going back to the zero-or-more-element separated sequence, the workaround with
attr
proposed in #60 doesn't work in more complex cases. The following, a bit unfair, example compares the Boost.Spirit solution with-(p % s)
and Boost.Parser solution with(p % s) | attr(A{})
, wehrep
parses a tuple.The problem is that when I use my aggregate type
A
, then attributevariant<tuple<M1, M2>, A>
is not merged to justA
(ortuple<M1, M2>
). In other words,A
andtuple<M1, M2>
are not treated as "same" or "equivalent".Maybe this could be changed? If not, I ask you to reconsider #63. Or maybe there is a way to define one's own directive? I find the use of a rule -- involving the use of macros and multiple definitions -- too big a solution for so common a problem.
The text was updated successfully, but these errors were encountered: