0

i’m trying to parse a binary data using spirit x3 and i’ve come across a problem, that I could not find a way to parse length dependent data structure, something like [uint32-counter][counter-length data].

Is it possible to pass attribute from one parser (x3::little_dword) to something like x3::repeat(???)[byte_]?

Igor G
  • 1
  • At least show what you have tried this far and what should be the actual expected behavior. – makallio85 Oct 26 '16 at 04:04
  • http://stackoverflow.com/questions/33624149/boost-spirit-x3-cannot-compile-repeat-directive-with-variable-factor – llonesmiz Oct 26 '16 at 04:33
  • @makallio85 , i've seen that question. with_<> approach, it didn't compile for me, probably due old boost (1.61 in debian): unsigned int i; auto r = x3::parse(start, in.end(), x3::with(std::ref(i))[x3::byte_]); with.hpp:60:33: error: invalid initialization of non-const reference of type ‘boost::spirit::x3::context(this->val, context) As to “what should be the actual expected behavior”: x3::repeat directive should support any parser with integral synthesized attribute for counter argument :) – Igor G Oct 26 '16 at 17:07

1 Answers1

0

You can use semantic actions to store the expected list length and the number of list items parsed and then fail the parser of the repeated item one entry before the last. Untested code:

unsigned expected_length;
unsigned current_length;
auto store_length   = [&](auto& ctx) { expected_length = _attr(ctx); _pass(ctx) = (expected_length > 0); };
auto check_for_last = [&](auto& ctx) { _pass(ctx) = (++current_length < expected_length); };
auto last_item      = [&](auto& ctx) { _pass(ctx) = (current_length == expected_length); }

auto r = little_dword[store_length] >> +(my_item[check_for_last]) >> my_item[last_item];

This rule cannot be nested or the local variables will be overwritten.

haphi
  • 74
  • 4