foonathan/lexy

`$BRANCH_RULE + dsl::position` is not treated as a branch rule?

bengsparks opened this issue · 2 comments

TL;DR: + dsl::position does not seem to retain branch rule status.

I have been tracking locations of rules using dsl::position.
Parsing something like ident:Hello can be implemented as:

struct name {
    static constexpr auto rule = LEXY_LIT("ident:") >> dsl::identifier(dsl::ascii::alpha_underscore);
};
static_assert(lexy::is_branch_rule<decltype(name::rule)>);

Extracting the start position can be done with the following without losing the branch rule status.

struct start_pos_name {
    static constexpr auto rule = dsl::position(dsl::p<name>);  
};
static_assert(lexy::is_branch_rule<decltype(start_pos_name::rule)>);

due to dsl::position(...) supporting branch rules

Extracting the end position should be done with constexpr branch operator+(branch br, rule auto then), as dsl::position by itself counts as a rule, and the operator+ should therefore retain the branch rule status:

struct start_end_pos_name {
    static constexpr auto rule = dsl::position(dsl::p<name>) + dsl::position;
};
static_assert(lexy::is_branch_rule<decltype(start_end_pos_name::rule)>);

However, this last static_assert fails.
Am I doing something wrong, or is this a bug? How can we best extract end positions?

The documentation isn't entirely clear. The operator+ is for the result of an operator>>, not just any branch. You want >>, not +.

Given a branch rule br (e.g. dsl::position(dsl::p<name>)) and an arbitrary rule r (e.g. dsl::position):

  • br >> r is another branch rule.
  • (br >> r) + r is another branch rule (equivalent to br >> r + r).
  • br + r is not a branch rule.

I'll make it more clear.

Many thanks for quick answer!