1212#include < string>
1313#include < cstring>
1414#include < iostream>
15+ #include < vector>
1516#include " test.hpp"
1617
1718namespace x3 = boost::spirit::x3;
9091 using boost::spirit::x3::rule;
9192 using boost::spirit::x3::int_;
9293 using boost::spirit::x3::lit;
94+ using boost::spirit::x3::lexeme;
95+ using boost::spirit::x3::eol;
9396
9497 { // show that ra = rb and ra %= rb works as expected
9598 rule<class a , int > ra;
@@ -144,6 +147,8 @@ main()
144147 auto r = rule<my_rule_class, char const *>()
145148 = ' (' > int_ > ' ,' > int_ > ' )' ;
146149
150+ got_it = 0 ;
151+
147152 BOOST_TEST (test (" (123,456)" , r));
148153 BOOST_TEST (!test (" (abc,def)" , r));
149154 BOOST_TEST (!test (" (123,456]" , r));
@@ -153,6 +158,22 @@ main()
153158 BOOST_TEST (got_it == 1 );
154159 }
155160
161+ { // regression test for #833
162+ // rules which return error_handler_result::fail should trigger iterator rollback
163+
164+ auto string_literal = rule<my_rule_class, std::string>()
165+ = lexeme[' "' > *~char_ (" \"\n\r " ) > ' "' ];
166+ auto r = rule<class r_id , std::vector<std::string>>()
167+ = *string_literal > eol;
168+
169+ got_it = 0 ;
170+
171+ BOOST_TEST (test (" \" abc\"\n " , r));
172+ BOOST_TEST_THROWS (test (" \" abc\n " , r), x3::expectation_failure<char const *>);
173+
174+ BOOST_TEST (got_it == 1 );
175+ }
176+
156177 { // on_success gets pre-skipped iterator
157178 auto r = rule<on_success_gets_preskipped_iterator, char const *>()
158179 = lit (" b" );
0 commit comments