I would like to write a grammar (highly simplified) with:
grr := integer [ . integer ]
with
integer ::= digit { [ underline ] digit }
Since the parsed literals are needed again later (the real grammar is more complex, not everything can be converted to a number immediately) the literal must be stored completely as string (more precisely as iterator_range) in the AST for later use (with underline).
The problem now is that the literal expressions can be longer than they should be (regarding the implementation/computation etc. later). The obvious solution is the repeat
directive (here detailed for Qi repeat or very short for X3).
This is where my problems start (coliru):
for(std::string_view const s : {
// ok
"0", "10", "1_0", "012345",
// too long
"0123456",
"1_2_3_4_5_6_7_8_9_0",
// absolutely invalid
"1_2_3_4_5_6_", "_0123_456", ""
}) {
auto const cs = x3::char_("0-9");
std::string attr;
bool const ok = x3::parse(std::begin(s), std::end(s),
x3::raw[ cs >> x3::repeat(0, 5)[ ('_' >> cs) | cs] ],
attr);
cout << s << " -> " << attr
<< " (" << std::boolalpha << ok << ")"
<< "\n";
}
gives
0 -> 0 (true)
10 -> 10 (true)
1_0 -> 1_0 (true)
012345 -> 012345 (true)
0123456 -> 012345 (true)
1_2_3_4_5_6_7_8_9_0 -> 1_2_3_4_5_6 (true)
1_2_3_4_5_6_ -> 1_2_3_4_5_6 (true)
_0123_456 -> (false)
-> (false)
If the literal is too long, the parser should fail, which it does not. If it ends with an underline, it should do that too - but it doesn't. Underline at the beginning and empty literals are correctly recognized/parsed as false.
Meanwhile, I try to write the more complex parsers into a separate parser classes, but here I am e.g. missing the rule to recognize the literal ending with an underline....
Furthermore, BOOST_SPIRIT_X3_DEBUG seems to be broken all of a sudden - there is no output.
What is the solution to my problem? I'm out of ideas except absolutely low-level and complicated via iterator, counter, etc.
This problem also affects other rules to be implemented.