Header lexy/dsl/context_counter.hpp
A counter that can be manipulated during parsing.
Rule DSL lexy::dsl::context_counter
lexy/dsl/context_counter.hppnamespace lexy::dsl
{
struct context_counter-dsl // note: not a rule itself
{
template <int InitialValue = 0>
constexpr rule auto create() const;
constexpr rule auto inc() const;
constexpr rule auto dec() const;
constexpr rule auto push(rule auto r) const;
constexpr rule auto pop(rule auto r) const;
template <typename Pred>
constexpr branch-rule auto is() const;
template <int Value>
constexpr branch-rule auto is() const;
constexpr branch-rule auto is_zero() const;
template <int Value>
constexpr branch-rule auto is_not() const;
constexpr branch-rule auto is_not_zero() const;
constexpr rule auto value() const;
};
template <typename Id>
constexpr context_counter-dsl context_counter;
}context_counter is not a rule, but a DSL for specifying rules that manipulate a counter of the current context.
n a, then n b without recursionstruct production
{
struct mismatch
{};
static constexpr auto rule = [] {
// Declare a counter - it is not created yet!
auto counter = dsl::context_counter<production>;
// Parse a sequence of 'a' and add the number to it.
auto a = counter.push(dsl::while_(dsl::lit_c<'a'>));
// Parse a sequence of 'b' and subtract the number from it.
auto b = counter.pop(dsl::while_(dsl::lit_c<'b'>));
// Create the counter initialized to zero,
// parse the two, and require its back to zero.
return counter.create() + a + b + dsl::must(counter.is_zero()).error<mismatch>;
}();
};Rule .create()
lexy/dsl/context_counter.hpptemplate <int InitialValue = 0>
constexpr rule auto create() const;.create() returns a rule that creates the counter.
- Parsing
Matches everything, without consuming anything. As a side effect, it creates a counter with name
Idinside the current context. If a context variable (of any) type with that name already exists, it is shadowed. This counter is initialized toInitialValue; it’s underlying type isint.- Errors
None.
- Values
None.
Rules .inc(), .dec()
lexy/dsl/context_counter.hppconstexpr rule auto inc() const;
constexpr rule auto dec() const;.inc(), .dec() return rules that increment/decrement counter.
- Requires
A counter with the name
Idhas been created in the current context, i.e..create()has been parsed earlier.- Parsing
Matches everything, without consuming anything. As a side effect, it modifies the counter with name
Idof the current context:.inc()increments it by one..dec()decrements it by one.
- Errors
None.
- Values
None.
Rules .push(), .pop()
lexy/dsl/context_counter.hppconstexpr rule auto push(rule auto r) const;
constexpr rule auto pop(rule auto r) const;.push(), .pop() return rules that add/subtract the counter.
- Requires
A counter with the name
Idhas been created in the current context, i.e..create()has been parsed earlier.- Parsing
Parses
rand counts the number of code units consumed byr. As a side effect, it modifies the counter with nameIdof the current context:.push()adds the number of code units to it..pop()subtracts the number of code units from it.
- Errors
All errors raised by parsing
r. The rule then fails ifrhas failed.- Values
All errors produced by parsing
r.
Caution | The count includes any whitespace characters. |
Branch rule .is() and variants
lexy/dsl/context_counter.hpptemplate <typename Pred>
constexpr branch-rule auto is() const;
template <int Value>
constexpr branch-rule auto is() const
{
return is<equal-to-Value>();
}
constexpr branch-rule auto is_zero() const
{
return is<0>();
}
template <int Value>
constexpr branch-rule auto is_not() const
{
return is<not-equal-to-Value>();
}
constexpr branch-rule auto is_not_zero() const
{
return is_not<0>();
}.is() and variants return branch rules that check the value of the counter.
- Requires
A counter with the name
Idhas been created in the current context, i.e..create()has been parsed earlier.Predis a default-constructible function object that can be called with anintand returns abool.
- Parsing
Matches everything, without consuming anything.
- Branch parsing
Backtracks unless the value of the counter with name
Idof the current context matches the predicatePred, as if doingPred()(value). Then matches everything without consuming anything.- Errors
None.
- Values
None.
Rule .value()
lexy/dsl/context_counter.hppconstexpr rule auto value() const;.value() is a rule that returns the value of the counter.
- Requires
A counter with the name
Idhas been created in the current context, i.e..create()has been parsed earlier.- Parsing
Matches everything, without consuming anything.
- Errors
None.
- Values
The current value of the counter (an
int) with nameIdof the current context.
Rule DSL lexy::dsl::equal_counts
lexy/dsl/context_counter.hppnamespace lexy::dsl
{
constexpr branch-rule auto equal_counts(context_counter-dsl... counters);
}equal_counts is a branch rule that checks whether all counters have the same value.
- Requires
sizeof…(counters) > 1All counters have been created in the current context, i.e.
.create()has been parsed earlier.
- Parsing
Matches everything, without consuming anything. Only succeeds if all counters have the same value in the current context.
- Branch parsing
Backtracks unless all counters have the same value in the current context; no error is raised. Matches everything, without consuming anything.
- Errors
A generic error with the tag
lexy::unequal_countsat the unchanged reader position. It then recovers without having consumed any input.- Values
None.
n a, then n b, then n cstruct production
{
static constexpr auto rule = [] {
// Parse 'a's and count them.
auto ac = dsl::context_counter<struct ac_id>;
auto a = ac.create() + ac.push(dsl::while_(dsl::lit_c<'a'>));
// Parse 'b's and count them.
auto bc = dsl::context_counter<struct bc_id>;
auto b = bc.create() + bc.push(dsl::while_(dsl::lit_c<'b'>));
// Parse 'c's and count them.
auto cc = dsl::context_counter<struct cc_id>;
auto c = cc.create() + cc.push(dsl::while_(dsl::lit_c<'c'>));
// Check that they're equal.
auto check = dsl::equal_counts(ac, bc, cc);
return a + b + c + check;
}();
};