Re: X3: Using dynamic Repetition Parser Directives
Seth <[email protected]>
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
On 31-01-16 20:33, Mike Gresens wrote:
> Was just the original code from
>
> https://stackoverflow.com/questions/33624149/boost-spirit-x3-cannot-compile-repeat-directive-with-variable-factor/33627991#33627991
>
> replacing std::vector<int> by std::string and x3::int_ by x3::char_
>
> Would like to provide you buildable code, but currently this code seems to
> be completely broken:
>
> #include <boost/spirit/home/x3.hpp>
> #include <boost/spirit/home/x3/binary.hpp>
> #include <string>
> #include <memory>
> #include <iostream>
>
> namespace x3 = boost::spirit::x3;
>
> namespace hessian {
>
> typedef std::string string_t;
>
> namespace parser {
> namespace detail {
>
> //string ::= s b1 b0 <utf8-data> string
> // ::= S b1 b0 <utf8-data>
> // ::= [x00-x1f] <utf8-data>
>
> // NOTE: The length means number of UTF16 characters but the content is
> given in UTF8 characters!
>
> struct length_tag;
> const auto length_action = [](auto& ctx)
> {
> *x3::get<length_tag>(ctx) = x3::_attr(ctx);
> };
> const auto more_action = [](auto &ctx)
> {
> x3::_pass(ctx) = *x3::get<length_tag>(ctx) > x3::_val(ctx).size();
> };
> const auto done_action = [](auto &ctx)
> {
> x3::_pass(ctx) = *x3::get<length_tag>(ctx) == x3::_val(ctx).size();
> };
> const auto push_action = [](auto &ctx)
> {
> x3::_val(ctx).push_back(x3::_attr(ctx));
> };
>
> const x3::rule<class string_rule, string_t> string_rule("string");
> const x3::rule<class string1_rule, string_t> string1_rule;
> const x3::rule<class string2_rule, string_t> string2_rule;
>
> const auto length_rule = x3::omit[x3::big_word [length_action] ];
> const auto content_rule = x3::lexeme[ *(x3::eps [more_action] >> x3::char_
> [push_action]) >> x3::eps [done_action] ];
>
> const auto string_rule_def =
> x3::with<length_tag>(std::make_shared<std::size_t>())[string1_rule |
> string2_rule];
> const auto string1_rule_def = x3::lit('S') >> length_rule >> content_rule;
> const auto string2_rule_def = x3::lit('s') >> length_rule >> content_rule >>
> string_rule;
>
> BOOST_SPIRIT_DEFINE(string_rule, string1_rule, string2_rule);
>
> }
>
> using detail::string_rule;
>
> }
> }
>
> void test_string()
> {
> const std::string text("s\x00\x07hello, S\x00\x05world"s);
> try
> {
> hessian::string_t attr;
> std::cout << x3::parse(text.begin(), text.end(), x3::eps >
> hessian::parser::string_rule, attr) << std::endl;
> std::cout << attr << std::endl;
> }
> catch (const x3::expectation_failure<std::string::const_iterator>&
> exception)
> {
> std::cout << exception.what() << " " << exception.which() << " " <<
> std::string(exception.where(), text.end()) << std::endl;
> }
> }
>
> Error is always: fatal error: template instantiation depth exceeds maximum
> of 2048
>
Here's my take on things:
With debug: http://coliru.stacked-crooked.com/a/40b87b1c08e92806
Without debug: http://coliru.stacked-crooked.com/a/420ba52e76dfeeff
That said, I think you're far better off writing a custom parser here.
#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/binary.hpp>
#include <string>
#include <memory>
namespace x3 = boost::spirit::x3;
namespace hessian {
typedef std::string string_t;
namespace parser {
namespace detail {
// string ::= s b1 b0 <utf8-data> string
// ::= S b1 b0 <utf8-data>
// ::= [x00-x1f] <utf8-data>
// NOTE: The length means number of UTF16 characters but the
content is given in UTF8 characters!
struct length_tag;
struct state { size_t expected, actual; };
const auto length_action = [](auto &ctx) {
state& s = x3::get<length_tag>(ctx);
s = { x3::_attr(ctx), 0 };
};
const auto more_action = [](auto &ctx) {
state& s = x3::get<length_tag>(ctx);
x3::_pass(ctx) = (s.expected > s.actual);
};
const auto done_action = [](auto &ctx) {
state& s = x3::get<length_tag>(ctx);
x3::_pass(ctx) = (s.expected == s.actual);
};
const auto push_action = [](auto &ctx) { // FIXME handle UTF8
state& s = x3::get<length_tag>(ctx);
x3::_val(ctx).push_back(x3::_attr(ctx));
s.actual += 1;
};
const auto length = x3::omit[x3::big_word[length_action]];
const auto content = x3::lexeme[*(x3::eps[more_action] >>
x3::char_[push_action]) >> x3::eps[done_action]];
template <typename T> struct mutable_wrapper {
T mutable value;
operator T&() const { return value; }
};
const auto string_s = 's' >> length >> content;
const auto string_S = 'S' >> x3::eps >> length >> content;
const auto string
= x3::rule<struct string_class, std::string> { "string" }
= x3::with<length_tag>(mutable_wrapper<state>{})[*string_s
>> string_S];
}
auto const& rule = detail::string;
}
}
#include <iomanip>
std::string as_hex(std::string const& what) {
std::ostringstream oss;
oss << std::hex << std::setfill('0');
for (uint8_t ch : what) {
if (std::isprint(ch)) oss << ch;
else oss << "\\x" << std::setw(2) << int{ch};
}
return oss.str();
}
void test_string() {
const std::string text("s\x00\x07hello, S\x00\x05world", 18);
try {
hessian::string_t attr;
auto f = text.begin(), l = text.end();
bool ok = x3::parse(f, l, x3::eps > hessian::parser::rule,
attr);
if (ok)
std::cout << "Parsed: '" << as_hex(attr) << "'\n";
else
std::cout << "Failed\n";
if(f!=l)
std::cout << "Remaining: '" << as_hex({f,l}) << "'\n";
} catch (const
x3::expectation_failure<std::string::const_iterator> &exception) {
std::cout << exception.what() << " " << exception.which() <<
" " << std::string(exception.where(), text.end())
<< std::endl;
}
}
int main()
{
test_string();
}
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general