Ticket #6050: spirit-transform-attribute-post-bool-v6.patch
File spirit-transform-attribute-post-bool-v6.patch, 37.2 KB (added by , 10 years ago) |
---|
-
boost/spirit/home/qi/action/action.hpp
70 70 { 71 71 // Do up-stream transformation, this integrates the results 72 72 // back into the original attribute value, if appropriate. 73 traits::post_transform(attr_, attr);74 return true;73 if (traits::post_transform(attr_, attr)) 74 return true; 75 75 } 76 76 77 77 // reset iterators if semantic action failed the match -
boost/spirit/home/qi/nonterminal/rule.hpp
277 277 { 278 278 if (f) 279 279 { 280 Iterator iter = first; 280 281 // do a preskip if this is an implied lexeme 281 282 if (is_same<skipper_type, unused_type>::value) 282 qi::skip_over( first, last, skipper);283 qi::skip_over(iter, last, skipper); 283 284 284 285 typedef traits::make_attribute<attr_type, Attribute> make_attribute; 285 286 … … 301 302 // fourth parameter can't be converted to a required target type 302 303 // then you are probably trying to use a rule or a grammar with 303 304 // an incompatible skipper type. 304 if (f( first, last, context, skipper))305 if (f(iter, last, context, skipper)) 305 306 { 306 307 // do up-stream transformation, this integrates the results 307 308 // back into the original attribute value, if appropriate 308 traits::post_transform(attr_param, attr_); 309 return true; 309 if (traits::post_transform(attr_param, attr_)) { 310 first = iter; 311 return true; 312 } 310 313 } 311 314 312 315 // inform attribute transformation of failed rhs … … 323 326 { 324 327 if (f) 325 328 { 329 Iterator iter = first; 326 330 // do a preskip if this is an implied lexeme 327 331 if (is_same<skipper_type, unused_type>::value) 328 qi::skip_over( first, last, skipper);332 qi::skip_over(iter, last, skipper); 329 333 330 334 typedef traits::make_attribute<attr_type, Attribute> make_attribute; 331 335 … … 347 351 // fourth parameter can't be converted to a required target type 348 352 // then you are probably trying to use a rule or a grammar with 349 353 // an incompatible skipper type. 350 if (f( first, last, context, skipper))354 if (f(iter, last, context, skipper)) 351 355 { 352 356 // do up-stream transformation, this integrates the results 353 357 // back into the original attribute value, if appropriate 354 traits::post_transform(attr_param, attr_); 355 return true; 358 if (traits::post_transform(attr_param, attr_)) { 359 first = iter; 360 return true; 361 } 356 362 } 357 363 358 364 // inform attribute transformation of failed rhs -
boost/spirit/home/qi/detail/attributes.hpp
22 22 23 23 static Transformed pre(Exposed&) { return Transformed(); } 24 24 25 static voidpost(Exposed& val, Transformed const& attr)25 static bool post(Exposed& val, Transformed const& attr) 26 26 { 27 27 traits::assign_to(attr, val); 28 return true; 28 29 } 29 30 30 31 // fail() will be called by Qi rule's if the rhs failed parsing … … 37 38 { 38 39 typedef Attribute& type; 39 40 static Attribute& pre(Attribute& val) { return val; } 40 static void post(Attribute&, Attribute const&) {}41 static bool post(Attribute&, Attribute const&) { return true; } 41 42 static void fail(Attribute&) {} 42 43 }; 43 44 … … 47 48 typedef Transformed type; 48 49 49 50 static Transformed pre(Exposed& val) { return Transformed(val); } 50 static void post(Exposed&, Transformed const&) { /* no-op */}51 static bool post(Exposed&, Transformed const&) { return true; } 51 52 52 53 // fail() will be called by Qi rule's if the rhs failed parsing 53 54 static void fail(Exposed&) {} … … 59 60 { 60 61 typedef Attribute& type; 61 62 static Attribute& pre(Attribute& val) { return val; } 62 static void post(Attribute&, Attribute const&) {}63 static bool post(Attribute&, Attribute const&) { return true; } 63 64 static void fail(Attribute&) {} 64 65 }; 65 66 … … 87 88 val = Transformed(); 88 89 return boost::get<Transformed>(val); 89 90 } 90 static void post(boost::optional<Exposed>&, Transformed const&) {}91 static bool post(boost::optional<Exposed>&, Transformed const&) { return true; } 91 92 static void fail(boost::optional<Exposed>& val) 92 93 { 93 94 val = none_t(); // leave optional uninitialized if rhs failed … … 100 101 { 101 102 typedef Attribute& type; 102 103 static Attribute& pre(Attribute& val) { return val; } 103 static void post(Attribute&, Attribute const&) {}104 static bool post(Attribute&, Attribute const&) { return true; } 104 105 static void fail(Attribute&) {} 105 106 }; 106 107 … … 110 111 { 111 112 typedef unused_type type; 112 113 static unused_type pre(unused_type) { return unused; } 113 static void post(unused_type, unused_type) {}114 static bool post(unused_type, unused_type) { return true; } 114 115 static void fail(unused_type) {} 115 116 }; 116 117 … … 160 161 161 162 /////////////////////////////////////////////////////////////////////////// 162 163 template <typename Exposed, typename Transformed> 163 voidpost_transform(Exposed& dest, Transformed const& attr)164 bool post_transform(Exposed& dest, Transformed const& attr) 164 165 { 165 166 return transform_attribute<Exposed, Transformed, qi::domain>::post(dest, attr); 166 167 } -
boost/spirit/home/qi/auxiliary/attr_cast.hpp
91 91 transform; 92 92 93 93 typename transform::type attr_ = transform::pre(attr_param); 94 Iterator iter = first; 94 95 95 if ( !compile<qi::domain>(subject).96 parse(first, last, context, skipper, attr_))96 if (compile<qi::domain>(subject) 97 .parse(iter, last, context, skipper, attr_)) 97 98 { 98 transform::fail(attr_param); 99 return false; 99 // do up-stream transformation, this mainly integrates the resu 100 // back into the original attribute value, if appropriate 101 if (traits::post_transform(attr_param, attr_)) { 102 first = iter; 103 return true; 104 } 100 105 } 101 106 102 // do up-stream transformation, this mainly integrates the results 103 // back into the original attribute value, if appropriate 104 traits::post_transform(attr_param, attr_); 105 return true; 107 transform::fail(attr_param); 108 return false; 106 109 } 107 110 108 111 template <typename Context> -
boost/spirit/home/support/adapt_adt_attributes.hpp
257 257 { 258 258 return val; 259 259 } 260 static void260 static bool 261 261 post( 262 262 fusion::extension::adt_attribute_proxy<T, N, false>& val 263 263 , Attribute const& attr) 264 264 { 265 265 val = attr; 266 return true; 266 267 } 267 268 static void 268 269 fail(fusion::extension::adt_attribute_proxy<T, N, false>&) … … 289 290 { 290 291 return val; 291 292 } 292 static void293 static bool 293 294 post( 294 295 fusion::extension::adt_attribute_proxy<T, N, Const>& 295 296 , Attribute const&) 296 297 { 298 return true; 297 299 } 298 300 static void 299 301 fail(fusion::extension::adt_attribute_proxy<T, N, Const>&) -
boost/spirit/repository/home/qi/nonterminal/subrule.hpp
213 213 // without passing values for them. 214 214 context_type context(*this, attr_); 215 215 216 if (def.binder(first, last, context, skipper)) 216 Iterator i = first; 217 218 if (def.binder(i, last, context, skipper)) 217 219 { 218 220 // do up-stream transformation, this integrates the results 219 221 // back into the original attribute value, if appropriate 220 traits::post_transform(attr, attr_); 221 return true; 222 if (traits::post_transform(attr, attr_)) { 223 first = i; 224 return true; 225 } 222 226 } 223 227 224 228 // inform attribute transformation of failed rhs … … 267 271 // passing values of incompatible types for them. 268 272 context_type context(*this, attr_, params, caller_context); 269 273 270 if (def.binder(first, last, context, skipper)) 274 Iterator i = first; 275 276 if (def.binder(i, last, context, skipper)) 271 277 { 272 278 // do up-stream transformation, this integrates the results 273 279 // back into the original attribute value, if appropriate 274 traits::post_transform(attr, attr_); 275 return true; 280 if (traits::post_transform(attr, attr_)) { 281 first = i; 282 return true; 283 } 276 284 } 277 285 278 286 // inform attribute transformation of failed rhs -
libs/spirit/example/support/utree/sexpr_parser.hpp
21 21 typedef unused_type type; 22 22 23 23 static unused_type pre (utree::nil_type&) { return unused_type(); } 24 static void post (utree::nil_type&, unused_type) {}24 static bool post (utree::nil_type&, unused_type) { return true; } 25 25 static void fail (utree::nil_type&) { } 26 26 }; 27 27 -
libs/spirit/example/qi/attr_cast.cpp
1 // Copyright (c) 2011 Alex Dubov 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 // This example demonstrates a method to conditionally propagate 7 // a parsed value to a value restricted attribute type. 8 9 #include <boost/spirit/include/qi.hpp> 10 #include <boost/spirit/include/phoenix_operator.hpp> 11 12 namespace qi = boost::spirit::qi; 13 namespace fusion = boost::fusion; 14 15 template <typename P, typename T> 16 void test_parser_attr( 17 char const* input, P const& p, T& attr, bool full_match = true) 18 { 19 using boost::spirit::qi::parse; 20 21 char const* f(input); 22 char const* l(f + strlen(f)); 23 if (parse(f, l, p, attr) && (!full_match || (f == l))) 24 std::cout << "ok" << std::endl; 25 else 26 std::cout << "fail" << std::endl; 27 } 28 29 //[reference_qi_auxiliary_attr_cast_data2 30 // Test structure we want to use in place of an int. Lets pretend we only 31 // want it to hold values strictly less that 100. 32 struct less_than_100 33 { 34 int i; 35 }; 36 37 // Counter variable we shall use later on. 38 int greater_than_100_cnt = 0; 39 40 // Custom attribute transformations for our primitive range restricted type. 41 namespace boost { namespace spirit { namespace traits 42 { 43 template <> 44 struct transform_attribute<less_than_100, int, qi::domain> 45 { 46 typedef int type; 47 48 // Any value less than 100 is still a valid int, so no problem here. 49 static type pre(less_than_100& val) { return val.i; } 50 51 // Not every int is less than 100, so we better do some checking. 52 static bool post(less_than_100& val, type const& attr) 53 { 54 if (attr < 100) 55 { 56 val.i = attr; 57 return true; 58 } 59 else 60 { 61 return false; 62 } 63 } 64 static void fail(less_than_100&) {} 65 }; 66 }}} 67 //] 68 69 namespace std 70 { 71 ostream& operator<<(ostream &os, less_than_100 val) 72 { 73 return (os << val.i); 74 } 75 76 ostream& operator<<(ostream &os, std::vector<less_than_100> const& val) 77 { 78 for (size_t cnt = 0; cnt < val.size(); ++cnt) 79 os << val[cnt] << ", "; 80 return os; 81 } 82 83 } 84 85 86 /////////////////////////////////////////////////////////////////////////////// 87 int main() 88 { 89 //[reference_qi_attr_cast2 90 using qi::int_; 91 using qi::attr_cast; 92 using qi::omit; 93 using boost::phoenix::ref; 94 95 less_than_100 d = { 0 }; 96 97 // Just like the previous example, the parser succedes. 98 test_parser_attr("1", attr_cast(int_), d); 99 std::cout << d << std::endl; 100 101 // Yet, if we try a value, larger than 100 (as defined above), the parser 102 // fails. 103 test_parser_attr("101", attr_cast(int_), d); 104 std::cout << d << std::endl; 105 106 // To demonstrate the facility even further, lets pretend we want to parse 107 // a list of numbers, storing good values into a container and counting 108 // the bad ones. We will try to convert the numbers from the comma 109 // separated list into less_than_100 values, and if a number or two happen 110 // to be out of range we will drop them using the qi::omit directive and 111 // increment our greater_than_100_cnt variable. 112 std::vector<less_than_100> v1; 113 114 test_parser_attr("10,20,105,39,114,3,121", 115 (attr_cast<less_than_100>(int_) 116 | omit[int_][ref(greater_than_100_cnt)++]) % ',', 117 v1); 118 // The below print outs should correctly report the 3 out of range values, 119 // as well as 4 correctly assigned ones. The container will still hold 120 // 7 values, with "bad" unassigned values substituted by defaul constructed 121 // ones (the specific value to substitute can be defined in 122 // transform_attribute::fail() method). 123 std::cout << "Values out of range: " << greater_than_100_cnt << std::endl; 124 std::cout << "Good values: " << v1 << std::endl; 125 //] 126 return 0; 127 } 128 // Copyright (c) 2011 Alex Dubov 129 // 130 // Distributed under the Boost Software License, Version 1.0. (See accompanying 131 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 132 133 // This example demonstrates a method to conditionally propagate 134 // a parsed value to a value restricted attribute type. 135 136 #include <boost/spirit/include/qi.hpp> 137 #include <boost/spirit/include/phoenix_operator.hpp> 138 139 namespace qi = boost::spirit::qi; 140 namespace fusion = boost::fusion; 141 142 template <typename P, typename T> 143 void test_parser_attr( 144 char const* input, P const& p, T& attr, bool full_match = true) 145 { 146 using boost::spirit::qi::parse; 147 148 char const* f(input); 149 char const* l(f + strlen(f)); 150 if (parse(f, l, p, attr) && (!full_match || (f == l))) 151 std::cout << "ok" << std::endl; 152 else 153 std::cout << "fail" << std::endl; 154 } 155 156 //[reference_qi_auxiliary_attr_cast_data2 157 // Test structure we want to use in place of an int. Lets pretend we only 158 // want it to hold values strictly less that 100. 159 struct less_than_100 160 { 161 int i; 162 }; 163 164 // Counter variable we shall use later on. 165 int greater_than_100_cnt = 0; 166 167 // Custom attribute transformations for our primitive range restricted type. 168 namespace boost { namespace spirit { namespace traits 169 { 170 template <> 171 struct transform_attribute<less_than_100, int, qi::domain> 172 { 173 typedef int type; 174 175 // Any value less than 100 is still a valid int, so no problem here. 176 static type pre(less_than_100& val) { return val.i; } 177 178 // Not every int is less than 100, so we better do some checking. 179 static bool post(less_than_100& val, type const& attr) 180 { 181 if (attr < 100) 182 { 183 val.i = attr; 184 return true; 185 } 186 else 187 { 188 return false; 189 } 190 } 191 static void fail(less_than_100&) {} 192 }; 193 }}} 194 //] 195 196 namespace std 197 { 198 ostream& operator<<(ostream &os, less_than_100 val) 199 { 200 return (os << val.i); 201 } 202 203 ostream& operator<<(ostream &os, std::vector<less_than_100> const& val) 204 { 205 for (size_t cnt = 0; cnt < val.size(); ++cnt) 206 os << val[cnt] << ", "; 207 return os; 208 } 209 210 } 211 212 213 /////////////////////////////////////////////////////////////////////////////// 214 int main() 215 { 216 //[reference_qi_attr_cast2 217 using qi::int_; 218 using qi::attr_cast; 219 using qi::omit; 220 using boost::phoenix::ref; 221 222 less_than_100 d = { 0 }; 223 224 // Just like the previous example, the parser succedes. 225 test_parser_attr("1", attr_cast(int_), d); 226 std::cout << d << std::endl; 227 228 // Yet, if we try a value, larger than 100 (as defined above), the parser 229 // fails. 230 test_parser_attr("101", attr_cast(int_), d); 231 std::cout << d << std::endl; 232 233 // To demonstrate the facility even further, lets pretend we want to parse 234 // a list of numbers, storing good values into a container and counting 235 // the bad ones. We will try to convert the numbers from the comma 236 // separated list into less_than_100 values, and if a number or two happen 237 // to be out of range we will drop them using the qi::omit directive and 238 // increment our greater_than_100_cnt variable. 239 std::vector<less_than_100> v1; 240 241 test_parser_attr("10,20,105,39,114,3,121", 242 (attr_cast<less_than_100>(int_) 243 | omit[int_][ref(greater_than_100_cnt)++]) % ',', 244 v1); 245 // The below print outs should correctly report the 3 out of range values, 246 // as well as 4 correctly assigned ones. The container will still hold 247 // 7 values, with "bad" unassigned values substituted by defaul constructed 248 // ones (the specific value to substitute can be defined in 249 // transform_attribute::fail() method). 250 std::cout << "Values out of range: " << greater_than_100_cnt << std::endl; 251 std::cout << "Good values: " << v1 << std::endl; 252 //] 253 return 0; 254 } 255 // Copyright (c) 2011 Alex Dubov 256 // 257 // Distributed under the Boost Software License, Version 1.0. (See accompanying 258 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 259 260 // This example demonstrates a method to conditionally propagate 261 // a parsed value to a value restricted attribute type. 262 263 #include <boost/spirit/include/qi.hpp> 264 #include <boost/spirit/include/phoenix_operator.hpp> 265 266 namespace qi = boost::spirit::qi; 267 namespace fusion = boost::fusion; 268 269 template <typename P, typename T> 270 void test_parser_attr( 271 char const* input, P const& p, T& attr, bool full_match = true) 272 { 273 using boost::spirit::qi::parse; 274 275 char const* f(input); 276 char const* l(f + strlen(f)); 277 if (parse(f, l, p, attr) && (!full_match || (f == l))) 278 std::cout << "ok" << std::endl; 279 else 280 std::cout << "fail" << std::endl; 281 } 282 283 //[reference_qi_auxiliary_attr_cast_data2 284 // Test structure we want to use in place of an int. Lets pretend we only 285 // want it to hold values strictly less that 100. 286 struct less_than_100 287 { 288 int i; 289 }; 290 291 // Counter variable we shall use later on. 292 int greater_than_100_cnt = 0; 293 294 // Custom attribute transformations for our primitive range restricted type. 295 namespace boost { namespace spirit { namespace traits 296 { 297 template <> 298 struct transform_attribute<less_than_100, int, qi::domain> 299 { 300 typedef int type; 301 302 // Any value less than 100 is still a valid int, so no problem here. 303 static type pre(less_than_100& val) { return val.i; } 304 305 // Not every int is less than 100, so we better do some checking. 306 static bool post(less_than_100& val, type const& attr) 307 { 308 if (attr < 100) 309 { 310 val.i = attr; 311 return true; 312 } 313 else 314 { 315 return false; 316 } 317 } 318 static void fail(less_than_100&) {} 319 }; 320 }}} 321 //] 322 323 namespace std 324 { 325 ostream& operator<<(ostream &os, less_than_100 val) 326 { 327 return (os << val.i); 328 } 329 330 ostream& operator<<(ostream &os, std::vector<less_than_100> const& val) 331 { 332 for (size_t cnt = 0; cnt < val.size(); ++cnt) 333 os << val[cnt] << ", "; 334 return os; 335 } 336 337 } 338 339 340 /////////////////////////////////////////////////////////////////////////////// 341 int main() 342 { 343 //[reference_qi_attr_cast2 344 using qi::int_; 345 using qi::attr_cast; 346 using qi::omit; 347 using boost::phoenix::ref; 348 349 less_than_100 d = { 0 }; 350 351 // Just like the previous example, the parser succedes. 352 test_parser_attr("1", attr_cast(int_), d); 353 std::cout << d << std::endl; 354 355 // Yet, if we try a value, larger than 100 (as defined above), the parser 356 // fails. 357 test_parser_attr("101", attr_cast(int_), d); 358 std::cout << d << std::endl; 359 360 // To demonstrate the facility even further, lets pretend we want to parse 361 // a list of numbers, storing good values into a container and counting 362 // the bad ones. We will try to convert the numbers from the comma 363 // separated list into less_than_100 values, and if a number or two happen 364 // to be out of range we will drop them using the qi::omit directive and 365 // increment our greater_than_100_cnt variable. 366 std::vector<less_than_100> v1; 367 368 test_parser_attr("10,20,105,39,114,3,121", 369 (attr_cast<less_than_100>(int_) 370 | omit[int_][ref(greater_than_100_cnt)++]) % ',', 371 v1); 372 // The below print outs should correctly report the 3 out of range values, 373 // as well as 4 correctly assigned ones. The container will still hold 374 // 7 values, with "bad" unassigned values substituted by defaul constructed 375 // ones (the specific value to substitute can be defined in 376 // transform_attribute::fail() method). 377 std::cout << "Values out of range: " << greater_than_100_cnt << std::endl; 378 std::cout << "Good values: " << v1 << std::endl; 379 //] 380 return 0; 381 } 382 // Copyright (c) 2011 Alex Dubov 383 // 384 // Distributed under the Boost Software License, Version 1.0. (See accompanying 385 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 386 387 // This example demonstrates a method to conditionally propagate 388 // a parsed value to a value restricted attribute type. 389 390 #include <boost/spirit/include/qi.hpp> 391 #include <boost/spirit/include/phoenix_operator.hpp> 392 393 namespace qi = boost::spirit::qi; 394 namespace fusion = boost::fusion; 395 396 template <typename P, typename T> 397 void test_parser_attr( 398 char const* input, P const& p, T& attr, bool full_match = true) 399 { 400 using boost::spirit::qi::parse; 401 402 char const* f(input); 403 char const* l(f + strlen(f)); 404 if (parse(f, l, p, attr) && (!full_match || (f == l))) 405 std::cout << "ok" << std::endl; 406 else 407 std::cout << "fail" << std::endl; 408 } 409 410 //[reference_qi_auxiliary_attr_cast_data2 411 // Test structure we want to use in place of an int. Lets pretend we only 412 // want it to hold values strictly less that 100. 413 struct less_than_100 414 { 415 int i; 416 }; 417 418 // Counter variable we shall use later on. 419 int greater_than_100_cnt = 0; 420 421 // Custom attribute transformations for our primitive range restricted type. 422 namespace boost { namespace spirit { namespace traits 423 { 424 template <> 425 struct transform_attribute<less_than_100, int, qi::domain> 426 { 427 typedef int type; 428 429 // Any value less than 100 is still a valid int, so no problem here. 430 static type pre(less_than_100& val) { return val.i; } 431 432 // Not every int is less than 100, so we better do some checking. 433 static bool post(less_than_100& val, type const& attr) 434 { 435 if (attr < 100) 436 { 437 val.i = attr; 438 return true; 439 } 440 else 441 { 442 return false; 443 } 444 } 445 static void fail(less_than_100&) {} 446 }; 447 }}} 448 //] 449 450 namespace std 451 { 452 ostream& operator<<(ostream &os, less_than_100 val) 453 { 454 return (os << val.i); 455 } 456 457 ostream& operator<<(ostream &os, std::vector<less_than_100> const& val) 458 { 459 for (size_t cnt = 0; cnt < val.size(); ++cnt) 460 os << val[cnt] << ", "; 461 return os; 462 } 463 464 } 465 466 467 /////////////////////////////////////////////////////////////////////////////// 468 int main() 469 { 470 //[reference_qi_attr_cast2 471 using qi::int_; 472 using qi::attr_cast; 473 using qi::omit; 474 using boost::phoenix::ref; 475 476 less_than_100 d = { 0 }; 477 478 // Just like the previous example, the parser succedes. 479 test_parser_attr("1", attr_cast(int_), d); 480 std::cout << d << std::endl; 481 482 // Yet, if we try a value, larger than 100 (as defined above), the parser 483 // fails. 484 test_parser_attr("101", attr_cast(int_), d); 485 std::cout << d << std::endl; 486 487 // To demonstrate the facility even further, lets pretend we want to parse 488 // a list of numbers, storing good values into a container and counting 489 // the bad ones. We will try to convert the numbers from the comma 490 // separated list into less_than_100 values, and if a number or two happen 491 // to be out of range we will drop them using the qi::omit directive and 492 // increment our greater_than_100_cnt variable. 493 std::vector<less_than_100> v1; 494 495 test_parser_attr("10,20,105,39,114,3,121", 496 (attr_cast<less_than_100>(int_) 497 | omit[int_][ref(greater_than_100_cnt)++]) % ',', 498 v1); 499 // The below print outs should correctly report the 3 out of range values, 500 // as well as 4 correctly assigned ones. The container will still hold 501 // 7 values, with "bad" unassigned values substituted by defaul constructed 502 // ones (the specific value to substitute can be defined in 503 // transform_attribute::fail() method). 504 std::cout << "Values out of range: " << greater_than_100_cnt << std::endl; 505 std::cout << "Good values: " << v1 << std::endl; 506 //] 507 return 0; 508 } -
libs/spirit/example/qi/adapt_template_struct.cpp
44 44 typedef fusion::vector<A&, B&> type; 45 45 46 46 static type pre(client::data<A, B>& val) { return type(val.a, val.b); } 47 static void post(client::data<A, B>&, fusion::vector<A&, B&> const&) {}47 static bool post(client::data<A, B>&, fusion::vector<A&, B&> const&) { return true; } 48 48 static void fail(client::data<A, B>&) {} 49 49 }; 50 50 }}} -
libs/spirit/example/qi/parse_date.cpp
54 54 // We need to initialize the attribute supplied to the rule (referenced 55 55 // by the first argument) with the values taken from the parsing 56 56 // results (referenced by the second argument). 57 static voidpost(boost::gregorian::date& d, date_parts const& v)57 static bool post(boost::gregorian::date& d, date_parts const& v) 58 58 { 59 59 d = boost::gregorian::date(fusion::at_c<0>(v), fusion::at_c<1>(v) 60 60 , fusion::at_c<2>(v)); 61 return true; 61 62 } 62 63 63 64 // The function fail() is called whenever the parsing of the right hand -
libs/spirit/example/qi/Jamfile
36 36 exe boost_array : boost_array.cpp ; 37 37 exe display_attribute_type : display_attribute_type.cpp ; 38 38 exe adapt_template_struct : adapt_template_struct.cpp ; 39 exe attr_cast : attr_cast.cpp ; 39 40 40 41 exe unescaped_string : unescaped_string.cpp ; 41 42 -
libs/spirit/example/qi/reference.cpp
292 292 { 293 293 typedef int& type; 294 294 static int& pre(int_data& d) { return d.i; } 295 static void post(int_data& val, int const& attr) {} 295 // this particular transformation is always successful 296 static bool post(int_data& val, int const& attr) { return true; } 296 297 static void fail(int_data&) {} 297 298 }; 298 299 }}} -
libs/spirit/test/qi/regression_transform_assignment.cpp
31 31 return fusion::tie(parts.second, parts.first); 32 32 } 33 33 34 static void post(foo_parts &, type const &) {}34 static bool post(foo_parts &, type const &) { return true; } 35 35 static void fail(foo_parts &) {} 36 36 }; 37 37 }}} -
libs/spirit/test/qi/attribute1.cpp
20 20 #include <boost/spirit/include/qi_operator.hpp> 21 21 #include <boost/spirit/include/qi_nonterminal.hpp> 22 22 #include <boost/spirit/include/qi_auxiliary.hpp> 23 #include <boost/spirit/include/qi_directive.hpp> 23 24 24 25 #include <iostream> 25 26 #include <vector> … … 60 61 { 61 62 typedef int type; 62 63 static int pre(test_int_data1& d) { return d.i; } 63 static void post(test_int_data1& d, int i) { d.i = i; }64 static bool post(test_int_data1& d, int i) { d.i = i; return true; } 64 65 static void fail(test_int_data1&) {} 65 66 }; 66 67 }}} … … 80 81 { 81 82 typedef int& type; 82 83 static int& pre(test_int_data2& d) { return d.i; } 83 static void post(test_int_data2&, int const&) {}84 static bool post(test_int_data2&, int const&) { return true; } 84 85 static void fail(test_int_data2&) {} 85 86 }; 86 87 }}} 87 88 88 89 /////////////////////////////////////////////////////////////////////////////// 90 struct test_int_data3 91 { 92 int i; 93 }; 94 95 // we provide a custom attribute transformation taking copy of the actual 96 // attribute value, simulating more complex type transformations which 97 // may fail due to target type limitations (in this case, restricted range). 98 namespace boost { namespace spirit { namespace traits 99 { 100 template <> 101 struct transform_attribute<test_int_data3, int, qi::domain> 102 { 103 typedef int type; 104 static int pre(test_int_data3& d) { return d.i; } 105 static bool post(test_int_data3& d, int i) 106 { 107 if (i < 5) 108 { 109 d.i = i; 110 return true; 111 } 112 else 113 { 114 return false; 115 } 116 } 117 static void fail(test_int_data3& d) 118 { 119 d.i = -1; 120 } 121 }; 122 }}} 123 124 /////////////////////////////////////////////////////////////////////////////// 89 125 int 90 126 main() 91 127 { … … 173 209 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2); 174 210 } 175 211 212 // testing controlled failure of attribute transformation 213 { 214 std::vector<test_int_data3> v; 215 // the parser is expected to fail at the second value 216 BOOST_TEST(!test_attr("3,7,2" 217 , qi::attr_cast<test_int_data3>(qi::int_) % ',', v)); 218 BOOST_TEST(v.size() == 1 && v[0].i == 3); 219 220 // the parser is expected to hit an alternative and proceed 221 v.clear(); 222 BOOST_TEST(test_attr("3,7,2" 223 , (qi::attr_cast<test_int_data3>(qi::int_) | qi::omit[qi::int_]) % ',', v)); 224 BOOST_TEST(v.size() == 3 && v[0].i == 3 && v[1].i == -1 && v[2].i == 2); 225 } 176 226 return boost::report_errors(); 177 227 } -
libs/spirit/test/qi/attribute2.cpp
60 60 { 61 61 typedef int type; 62 62 static int pre(test_int_data1& d) { return d.i; } 63 static void post(test_int_data1& d, int i) { d.i = i; }63 static bool post(test_int_data1& d, int i) { d.i = i; return true; } 64 64 static void fail(test_int_data1&) {} 65 65 }; 66 66 }}} … … 80 80 { 81 81 typedef int& type; 82 82 static int& pre(test_int_data2& d) { return d.i; } 83 static void post(test_int_data2&, int const&) {}83 static bool post(test_int_data2&, int const&) { return true; } 84 84 static void fail(test_int_data2&) {} 85 85 }; 86 86 }}} -
libs/spirit/doc/advanced/customization_points.qbk
477 477 typedef <unspecified> type; 478 478 479 479 static type pre(Exposed& val); 480 static voidpost(Exposed& val, type attr); // Qi only480 static bool post(Exposed& val, type attr); // Qi only 481 481 static void fail(Exposed&); // Qi only 482 482 }; 483 483 … … 533 533 as exposed by the metafunction `type`). This function 534 534 will be called in /Qi/ and for /Karma/.]] 535 535 [[ 536 `` voidtransform_attribute<Exposed, Transformed, Domain>::post(exposed, transformed)``]536 ``bool transform_attribute<Exposed, Transformed, Domain>::post(exposed, transformed)``] 537 537 [Do `post`-transformation after the invocation of the 538 538 right hand side component for `rule` (or the embedded 539 539 component for `attr_cast`). This takes the original 540 540 attribute as supplied by the user and the attribute 541 541 as returned from the right hand side (embedded) 542 542 component and is expected to propagate the result back 543 into the supplied attribute instance. This function 544 will be called in /Qi/ only.]] 543 into the supplied attribute instance. Can return `false` 544 if propagation can not be successfully performed, thus 545 failing the parser which invoked the transormation. This 546 function will be called in /Qi/ only.]] 545 547 [[ 546 548 ``void transform_attribute<Exposed, Transformed, Domain>::fail(exposed)``] 547 549 [Handling failing parse operations of the -
libs/spirit/doc/qi/auxiliary.qbk
217 217 218 218 [reference_qi_attr_cast1] 219 219 220 [heading Advanced Example] 221 222 Just like semantic actions, __customize_transform_attribute__ has the ability 223 to signal failure back to the parser. This may happen if there's no obvious 224 way to convert the parsed attribute value back to the exposed attribute type. 225 Common examples of such behavior are enumerations and range restricted 226 arithmetic types, but, of course, other similar use cases are also possible. 227 228 Lets expand the definitions above into a slightly more complex example: 229 230 [import ../../example/qi/attr_cast.cpp] 231 [reference_qi_auxiliary_attr_cast_data2] 232 233 Now we can attempt to parse some values which may not necessarily fit into 234 a range limited type we defined: 235 236 [reference_qi_attr_cast2] 237 238 The full cpp file for this example can be found here: [@../../example/qi/attr_cast.cpp] 239 220 240 [endsect] 221 241 222 242