Header lexy/dsl/context_counter.hpp
A counter that can be manipulated during parsing.
Rule DSL lexy::dsl::context_counter
lexy/dsl/context_counter.hpp
namespace 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 <int Value>
constexpr branch-rule auto is() const;
constexpr branch-rule auto is_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.hpp
template <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
Id
inside 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.hpp
constexpr rule auto inc() const;
constexpr rule auto dec() const;
.inc()
, .dec()
return rules that increment/decrement counter.
- Requires
A counter with the name
Id
has 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
Id
of the current context:.inc()
increments it by one..dec()
decrements it by one.
- Errors
None.
- Values
None.
Rules .push()
, .pop()
lexy/dsl/context_counter.hpp
constexpr 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
Id
has been created in the current context, i.e..create()
has been parsed earlier.- Parsing
Parses
r
and counts the number of code units consumed byr
. As a side effect, it modifies the counter with nameId
of 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 ifr
has failed.- Values
All errors produced by parsing
r
.
Caution | The count includes any whitespace characters. |
Branch rules .is()
, .is_zero()
lexy/dsl/context_counter.hpp
template <int Value>
constexpr branch-rule auto is() const;
constexpr branch-rule auto is_zero() const
{
return is<0>();
}
.is()
and .is_zero()
return branch rules that check the value of the counter.
- Requires
A counter with the name
Id
has been created in the current context, i.e..create()
has been parsed earlier.- Parsing
Matches everything, without consuming anything.
- Branch parsing
Backtracks unless the value of the boolean with name
Id
of the current context isValue
(.is()
) or0
(.is_zero()
). Then matches everything without consuming anything.- Errors
None.
- Values
None.
Rule .value()
lexy/dsl/context_counter.hpp
constexpr rule auto value() const;
.value()
is a rule that returns the value of the counter.
- Requires
A counter with the name
Id
has 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 nameId
of the current context.
Rule DSL lexy::dsl::equal_counts
lexy/dsl/context_counter.hpp
namespace 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) > 1
All 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_counts
at the unchanged reader position. It then recovers without having consumed any input.- Values
None.
n
a
, then n
b
, then n
c
struct 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;
}();
};