foonathan / lexy

C++ parsing DSL
https://lexy.foonathan.net
Boost Software License 1.0
991 stars 66 forks source link

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

Closed bengsparks closed 11 months ago

bengsparks commented 11 months ago

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?

foonathan commented 11 months ago

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):

I'll make it more clear.

bengsparks commented 11 months ago

Many thanks for quick answer!