reference.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. http://spirit.sourceforge.net/
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. // this code is not supposed to be executed, so the asserts are for
  8. // demonstration purposes only
  9. // boostinspect:naassert_macro
  10. //[reference_includes
  11. #include <boost/spirit/include/support_utree.hpp>
  12. #include <boost/spirit/include/qi.hpp>
  13. #include <boost/spirit/include/phoenix_core.hpp>
  14. #include <boost/spirit/include/phoenix_operator.hpp>
  15. #include <boost/fusion/include/adapt_struct.hpp>
  16. #include <boost/assert.hpp>
  17. #include <boost/predef/other/endian.h>
  18. #include <iostream>
  19. #include <string>
  20. #include <cstdlib>
  21. //]
  22. //[reference_test
  23. template <typename P>
  24. void test_parser(
  25. char const* input, P const& p, bool full_match = true)
  26. {
  27. using boost::spirit::qi::parse;
  28. char const* f(input);
  29. char const* l(f + strlen(f));
  30. if (parse(f, l, p) && (!full_match || (f == l)))
  31. std::cout << "ok" << std::endl;
  32. else
  33. std::cout << "fail" << std::endl;
  34. }
  35. template <typename P>
  36. void test_phrase_parser(
  37. char const* input, P const& p, bool full_match = true)
  38. {
  39. using boost::spirit::qi::phrase_parse;
  40. using boost::spirit::qi::ascii::space;
  41. char const* f(input);
  42. char const* l(f + strlen(f));
  43. if (phrase_parse(f, l, p, space) && (!full_match || (f == l)))
  44. std::cout << "ok" << std::endl;
  45. else
  46. std::cout << "fail" << std::endl;
  47. }
  48. //]
  49. //[reference_test_attr
  50. template <typename P, typename T>
  51. void test_parser_attr(
  52. char const* input, P const& p, T& attr, bool full_match = true)
  53. {
  54. using boost::spirit::qi::parse;
  55. char const* f(input);
  56. char const* l(f + strlen(f));
  57. if (parse(f, l, p, attr) && (!full_match || (f == l)))
  58. std::cout << "ok" << std::endl;
  59. else
  60. std::cout << "fail" << std::endl;
  61. }
  62. template <typename P, typename T>
  63. void test_phrase_parser_attr(
  64. char const* input, P const& p, T& attr, bool full_match = true)
  65. {
  66. using boost::spirit::qi::phrase_parse;
  67. using boost::spirit::qi::ascii::space;
  68. char const* f(input);
  69. char const* l(f + strlen(f));
  70. if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l)))
  71. std::cout << "ok" << std::endl;
  72. else
  73. std::cout << "fail" << std::endl;
  74. }
  75. //]
  76. //[reference_print_info
  77. struct printer
  78. {
  79. typedef boost::spirit::utf8_string string;
  80. void element(string const& tag, string const& value, int depth) const
  81. {
  82. for (int i = 0; i < (depth*4); ++i) // indent to depth
  83. std::cout << ' ';
  84. std::cout << "tag: " << tag;
  85. if (value != "")
  86. std::cout << ", value: " << value;
  87. std::cout << std::endl;
  88. }
  89. };
  90. void print_info(boost::spirit::info const& what)
  91. {
  92. using boost::spirit::basic_info_walker;
  93. printer pr;
  94. basic_info_walker<printer> walker(pr, what.tag, 0);
  95. boost::apply_visitor(walker, what.value);
  96. }
  97. //]
  98. //[reference_test_real_policy
  99. ///////////////////////////////////////////////////////////////////////////////
  100. // These policies can be used to parse thousand separated
  101. // numbers with at most 2 decimal digits after the decimal
  102. // point. e.g. 123,456,789.01
  103. ///////////////////////////////////////////////////////////////////////////////
  104. template <typename T>
  105. struct ts_real_policies : boost::spirit::qi::ureal_policies<T>
  106. {
  107. // 2 decimal places Max
  108. template <typename Iterator, typename Attribute>
  109. static bool
  110. parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr,
  111. int& frac_digits)
  112. {
  113. Iterator savef = first;
  114. bool r = boost::spirit::qi::
  115. extract_uint<T, 10, 1, 2, true>::call(first, last, attr);
  116. if (r) {
  117. // Optimization note: don't compute frac_digits if T is
  118. // an unused_type. This should be optimized away by the compiler.
  119. if (!boost::is_same<T, boost::spirit::unused_type>::value)
  120. frac_digits = static_cast<int>(std::distance(savef, first));
  121. }
  122. return r;
  123. }
  124. // No exponent
  125. template <typename Iterator>
  126. static bool
  127. parse_exp(Iterator&, Iterator const&)
  128. {
  129. return false;
  130. }
  131. // No exponent
  132. template <typename Iterator, typename Attribute>
  133. static bool
  134. parse_exp_n(Iterator&, Iterator const&, Attribute&)
  135. {
  136. return false;
  137. }
  138. // Thousands separated numbers
  139. template <typename Iterator, typename Accumulator>
  140. static bool
  141. parse_n(Iterator& first, Iterator const& last, Accumulator& result)
  142. {
  143. using boost::spirit::qi::uint_parser;
  144. namespace qi = boost::spirit::qi;
  145. uint_parser<unsigned, 10, 1, 3> uint3;
  146. uint_parser<unsigned, 10, 3, 3> uint3_3;
  147. if (parse(first, last, uint3, result))
  148. {
  149. Accumulator n;
  150. Iterator iter = first;
  151. while (qi::parse(iter, last, ',') && qi::parse(iter, last, uint3_3, n))
  152. {
  153. result = result * 1000 + n;
  154. first = iter;
  155. }
  156. return true;
  157. }
  158. return false;
  159. }
  160. };
  161. //]
  162. //[reference_test_bool_policy
  163. ///////////////////////////////////////////////////////////////////////////////
  164. // These policies can be used to parse "eurt" (i.e. "true" spelled backwards)
  165. // as `false`
  166. ///////////////////////////////////////////////////////////////////////////////
  167. struct backwards_bool_policies : boost::spirit::qi::bool_policies<>
  168. {
  169. // we want to interpret a 'true' spelled backwards as 'false'
  170. template <typename Iterator, typename Attribute>
  171. static bool
  172. parse_false(Iterator& first, Iterator const& last, Attribute& attr)
  173. {
  174. namespace qi = boost::spirit::qi;
  175. if (qi::detail::string_parse("eurt", first, last, qi::unused))
  176. {
  177. namespace traits = boost::spirit::traits;
  178. traits::assign_to(false, attr); // result is false
  179. return true;
  180. }
  181. return false;
  182. }
  183. };
  184. //]
  185. //[reference_qi_complex
  186. // a simple complex number representation z = a + bi
  187. struct complex
  188. {
  189. complex (double a = 0.0, double b = 0.0)
  190. : a(a), b(b)
  191. {}
  192. double a;
  193. double b;
  194. };
  195. //]
  196. //[reference_qi_stream_complex
  197. // define streaming operator for the type complex
  198. std::istream&
  199. operator>> (std::istream& is, complex& z)
  200. {
  201. char lbrace = '\0', comma = '\0', rbrace = '\0';
  202. is >> lbrace >> z.a >> comma >> z.b >> rbrace;
  203. if (lbrace != '{' || comma != ',' || rbrace != '}')
  204. is.setstate(std::ios_base::failbit);
  205. return is;
  206. }
  207. //]
  208. //[reference_qi_auto_complex
  209. /*`The following construct is required to allow the `complex` data structure
  210. to be utilized as a __fusion__ sequence. This is required as we will
  211. emit output for this data structure with a __qi__ sequence:
  212. `'{' >> qi::double_ >> ',' >> qi::double_ >> '}'`.
  213. */
  214. BOOST_FUSION_ADAPT_STRUCT(
  215. complex,
  216. (double, a)
  217. (double, b)
  218. )
  219. /*`We add a specialization for the create_parser customization point
  220. defining a custom output format for the complex type. Generally, any
  221. specialization for create_parser is expected to return the proto
  222. expression to be used to match input for the type the customization
  223. point has been specialized for.
  224. */
  225. /*`We need to utilize `proto::deep_copy` as the expression contains literals
  226. (the `'{'`, `','`, and `'}'`) which normally get embedded in the proto
  227. expression by reference only. The deep copy converts the proto tree to
  228. hold this by value. The deep copy operation can be left out for simpler
  229. proto expressions (not containing references to temporaries). Alternatively
  230. you could use the `proto::make_expr` facility to build the required
  231. proto expression.
  232. */
  233. namespace boost { namespace spirit { namespace traits
  234. {
  235. template <>
  236. struct create_parser<complex>
  237. {
  238. typedef proto::result_of::deep_copy<
  239. BOOST_TYPEOF('{' >> qi::double_ >> ',' >> qi::double_ >> '}')
  240. >::type type;
  241. static type call()
  242. {
  243. return proto::deep_copy(
  244. '{' >> qi::double_ >> ',' >> qi::double_ >> '}');
  245. }
  246. };
  247. }}}
  248. //]
  249. //[reference_qi_auxiliary_attr_cast_data1
  250. // this is just a test structure we want to use in place of an int
  251. struct int_data
  252. {
  253. int i;
  254. };
  255. // we provide a custom attribute transformation to allow its use as an int
  256. namespace boost { namespace spirit { namespace traits
  257. {
  258. // in this case we just expose the embedded 'int' as the attribute instance
  259. // to use, allowing to leave the function 'post()' empty
  260. template <>
  261. struct transform_attribute<int_data, int, qi::domain>
  262. {
  263. typedef int& type;
  264. static int& pre(int_data& d) { return d.i; }
  265. static void post(int_data& val, int const& attr) {}
  266. static void fail(int_data&) {}
  267. };
  268. }}}
  269. //]
  270. namespace client
  271. {
  272. using boost::spirit::qi::grammar;
  273. using boost::spirit::qi::rule;
  274. using boost::spirit::ascii::space_type;
  275. //[reference_grammar_definition
  276. /*`Basic grammar usage:
  277. */
  278. struct num_list : grammar<char const*, space_type>
  279. {
  280. num_list() : base_type(start)
  281. {
  282. using boost::spirit::int_;
  283. num = int_;
  284. start = num >> *(',' >> num);
  285. }
  286. rule<char const*, space_type> start, num;
  287. };
  288. //]
  289. }
  290. int
  291. main()
  292. {
  293. {
  294. //[reference_using_declarations_lit_char
  295. using boost::spirit::qi::lit;
  296. using boost::spirit::ascii::char_;
  297. //]
  298. //[reference_char_literals
  299. test_parser("x", 'x'); // plain literal
  300. test_parser("x", lit('x')); // explicit literal
  301. test_parser("x", char_('x')); // ascii::char_
  302. //]
  303. //[reference_char_range
  304. char ch;
  305. test_parser_attr("5", char_('0','9'), ch); // ascii::char_ range
  306. std::cout << ch << std::endl; // prints '5'
  307. //]
  308. //[reference_char_set
  309. test_parser_attr("5", char_("0-9"), ch); // ascii::char_ set
  310. std::cout << ch << std::endl; // prints '5'
  311. //]
  312. //[reference_char_phoenix
  313. namespace phx = boost::phoenix;
  314. test_parser("x", phx::val('x')); // direct
  315. test_parser("5",
  316. char_(phx::val('0'),phx::val('9'))); // ascii::char_ range
  317. //]
  318. }
  319. {
  320. //[reference_using_declarations_lit_string
  321. using boost::spirit::qi::lit;
  322. using boost::spirit::ascii::string;
  323. //]
  324. //[reference_string_literals
  325. test_parser("boost", "boost"); // plain literal
  326. test_parser("boost", lit("boost")); // explicit literal
  327. test_parser("boost", string("boost")); // ascii::string
  328. //]
  329. }
  330. {
  331. using boost::spirit::qi::lit;
  332. using boost::spirit::ascii::string;
  333. //[reference_string_std_string
  334. std::string s("boost");
  335. test_parser("boost", s); // direct
  336. test_parser("boost", lit(s)); // explicit
  337. test_parser("boost", string(s)); // ascii::string
  338. //]
  339. }
  340. {
  341. using boost::spirit::qi::lit;
  342. using boost::spirit::ascii::string;
  343. //[reference_string_phoenix
  344. namespace phx = boost::phoenix;
  345. test_parser("boost", phx::val("boost")); // direct
  346. test_parser("boost", lit(phx::val("boost"))); // explicit
  347. test_parser("boost", string(phx::val("boost"))); // ascii::string
  348. //]
  349. }
  350. {
  351. //[reference_using_declarations_symbols
  352. using boost::spirit::qi::symbols;
  353. //]
  354. //[reference_symbols_with_data
  355. symbols<char, int> sym;
  356. sym.add
  357. ("Apple", 1)
  358. ("Banana", 2)
  359. ("Orange", 3)
  360. ;
  361. int i;
  362. test_parser_attr("Banana", sym, i);
  363. std::cout << i << std::endl;
  364. //]
  365. }
  366. {
  367. //[reference_using_declarations_lexeme
  368. using boost::spirit::qi::lexeme;
  369. using boost::spirit::qi::lit;
  370. using boost::spirit::ascii::digit;
  371. //]
  372. //[reference_lexeme
  373. /*`The use of lexeme here will prevent skipping in between the
  374. digits and the sign making inputs such as `"1 2 345"` erroneous.*/
  375. test_phrase_parser("12345", lexeme[ -(lit('+') | '-') >> +digit ]);
  376. //]
  377. }
  378. // as
  379. {
  380. //[reference_using_declarations_as
  381. using boost::spirit::utree;
  382. using boost::spirit::utree_type;
  383. using boost::spirit::utf8_symbol_type;
  384. using boost::spirit::qi::as;
  385. using boost::spirit::qi::as_string;
  386. using boost::spirit::qi::char_;
  387. //]
  388. //[reference_as
  389. /*`To properly handle string concatenation with __utree__, we
  390. make use of `as_string[]`. We also use `as<T>` to explicitly create
  391. a __utree__ symbol node.*/
  392. utree ut;
  393. typedef as<utf8_symbol_type> as_symbol_type;
  394. as_symbol_type const as_symbol = as_symbol_type();
  395. test_parser_attr("foo", as_string[*char_], ut);
  396. std::cout << ut << std::endl; // will output >"foo"<
  397. BOOST_ASSERT(ut.which() == utree_type::string_type);
  398. ut.clear();
  399. test_parser_attr("foo", as<std::string>()[*char_], ut);
  400. std::cout << ut << std::endl; // will output >"foo"<
  401. BOOST_ASSERT(ut.which() == utree_type::string_type);
  402. ut.clear();
  403. test_parser_attr("foo", as_symbol[*char_], ut);
  404. std::cout << ut << std::endl; // will output >foo<
  405. BOOST_ASSERT(ut.which() == utree_type::symbol_type);
  406. ut.clear();
  407. test_parser_attr("foo", as<utf8_symbol_type>()[*char_], ut);
  408. std::cout << ut << std::endl; // will output >foo<
  409. BOOST_ASSERT(ut.which() == utree_type::symbol_type);
  410. //]
  411. }
  412. {
  413. //[reference_using_declarations_no_skip
  414. using boost::spirit::qi::no_skip;
  415. using boost::spirit::qi::char_;
  416. //]
  417. //[reference_no_skip
  418. /*`The use of no_skip here will prevent skipping of whitespace in front
  419. and in between the characters of the string `' abc '`.*/
  420. std::string str;
  421. test_phrase_parser_attr("' abc '",
  422. '\'' >> no_skip[+~char_('\'')] >> '\'', str);
  423. std::cout << str << std::endl; // will output: > abc <
  424. //]
  425. }
  426. {
  427. //[reference_using_declarations_hold
  428. using boost::spirit::qi::hold;
  429. using boost::spirit::qi::int_;
  430. using boost::spirit::qi::attr;
  431. //]
  432. //[reference_hold
  433. /*`The use of `hold[]` here will make sure the changes to the attribute
  434. caused by the (failing) first alternative will not be visible after
  435. the whole parsing succeeded. */
  436. std::vector<int> v;
  437. test_phrase_parser_attr("123",
  438. hold[int_ >> ':' >> int_] | int_ >> attr(0), v);
  439. std::cout << v[0] << "," << v[1] << std::endl; // will output: >123,0<
  440. //]
  441. }
  442. {
  443. //[reference_using_declarations_no_case
  444. using boost::spirit::ascii::no_case;
  445. using boost::spirit::ascii::char_;
  446. using boost::spirit::ascii::alnum;
  447. using boost::spirit::qi::symbols;
  448. //]
  449. //[reference_no_case
  450. test_parser("X", no_case[char_('x')]);
  451. test_parser("6", no_case[alnum]);
  452. //]
  453. //[reference_symbols_with_no_case
  454. symbols<char, int> sym;
  455. sym.add
  456. ("apple", 1) // symbol strings are added in lowercase...
  457. ("banana", 2)
  458. ("orange", 3)
  459. ;
  460. int i;
  461. // ...because sym is used for case-insensitive parsing
  462. test_parser_attr("Apple", no_case[ sym ], i);
  463. std::cout << i << std::endl;
  464. test_parser_attr("ORANGE", no_case[ sym ], i);
  465. std::cout << i << std::endl;
  466. //]
  467. }
  468. {
  469. //[reference_using_declarations_omit
  470. using boost::spirit::qi::omit;
  471. using boost::spirit::qi::int_;
  472. using boost::spirit::ascii::char_;
  473. //]
  474. //[reference_omit
  475. /*`This parser ignores the first two characters
  476. and extracts the succeeding `int`:*/
  477. int i;
  478. test_parser_attr("xx345", omit[char_ >> char_] >> int_, i);
  479. std::cout << i << std::endl; // should print 345
  480. //]
  481. }
  482. {
  483. //[reference_using_declarations_matches
  484. using boost::spirit::qi::matches;
  485. using boost::spirit::qi::int_;
  486. //]
  487. //[reference_matches
  488. /*`This parser tries to match an `int` and returns `true` a its
  489. attribute as it succeeded matching: */
  490. bool result = false;
  491. test_parser_attr("345", matches[int_], result);
  492. std::cout << std::boolalpha << result << std::endl; // should print: true
  493. /*`This parser tries to match an `int` as well and returns `false` as
  494. its attribute as it fails matching: */
  495. result = true;
  496. test_parser_attr("abc", matches[int_], result);
  497. std::cout << std::boolalpha << result << std::endl; // should print: false
  498. //]
  499. }
  500. {
  501. //[reference_using_declarations_raw
  502. using boost::spirit::qi::raw;
  503. using boost::spirit::ascii::alpha;
  504. using boost::spirit::ascii::alnum;
  505. //]
  506. //[reference_raw
  507. //`This parser matches and extracts C++ identifiers:
  508. std::string id;
  509. test_parser_attr("James007", raw[(alpha | '_') >> *(alnum | '_')], id);
  510. std::cout << id << std::endl; // should print James007
  511. //]
  512. }
  513. {
  514. //[reference_using_declarations_repeat
  515. using boost::spirit::qi::repeat;
  516. using boost::spirit::qi::lit;
  517. using boost::spirit::qi::uint_parser;
  518. using boost::spirit::qi::_1;
  519. using boost::spirit::ascii::char_;
  520. namespace phx = boost::phoenix;
  521. //]
  522. //[reference_repeat
  523. //`A parser for a file name with a maximum of 255 characters:
  524. test_parser("batman.jpeg", repeat(1, 255)[char_("a-zA-Z_./")]);
  525. /*`A parser for a specific bitmap file format which has exactly 4096 RGB color information.
  526. (for the purpose of this example, we will be testing only 3 RGB color information.)
  527. */
  528. uint_parser<unsigned, 16, 6, 6> rgb;
  529. std::vector<unsigned> colors;
  530. test_parser_attr("ffffff0000003f3f3f", repeat(3)[rgb], colors);
  531. std::cout
  532. << std::hex
  533. << colors[0] << ','
  534. << colors[1] << ','
  535. << colors[2] << std::endl;
  536. /*`A 256 bit binary string (1..256 1s or 0s). (For the purpose of this example,
  537. we will be testing only 16 bits.)
  538. */
  539. test_parser("1011101011110010", repeat(16)[lit('1') | '0']);
  540. //]
  541. std::cout << std::dec; // reset to decimal
  542. //[reference_repeat_pascal
  543. /*`This trivial example cannot be practically defined in traditional EBNF.
  544. Although some EBNF variants allow more powerful repetition constructs other
  545. than the Kleene Star, we are still limited to parsing fixed strings.
  546. The nature of EBNF forces the repetition factor to be a constant.
  547. On the other hand, Spirit allows the repetition factor to be variable at
  548. run time. We could write a grammar that accepts the input string above.
  549. Example using phoenix:
  550. */
  551. std::string str;
  552. int n;
  553. test_parser_attr("\x0bHello World",
  554. char_[phx::ref(n) = _1] >> repeat(phx::ref(n))[char_], str);
  555. std::cout << n << ',' << str << std::endl; // will print "11,Hello World"
  556. //]
  557. }
  558. {
  559. //[reference_using_declarations_skip
  560. using boost::spirit::qi::skip;
  561. using boost::spirit::qi::int_;
  562. using boost::spirit::ascii::space;
  563. //]
  564. //[reference_skip
  565. /*`Explicitly specify a skip parser. This parser parses comma
  566. delimited numbers, ignoring spaces.*/
  567. test_parser("1, 2, 3, 4, 5", skip(space)[int_ >> *(',' >> int_)]);
  568. //]
  569. }
  570. // attr()
  571. {
  572. //[reference_using_declarations_attr
  573. namespace phx = boost::phoenix;
  574. using boost::spirit::qi::attr;
  575. //]
  576. //[reference_attr
  577. std::string str;
  578. test_parser_attr("", attr("boost"), str);
  579. std::cout << str << std::endl; // will print 'boost'
  580. double d;
  581. test_parser_attr("", attr(1.0), d);
  582. std::cout << d << std::endl; // will print '1.0'
  583. //]
  584. //[reference_attr_phoenix
  585. d = 0.0;
  586. double d1 = 1.2;
  587. test_parser_attr("", attr(phx::ref(d1)), d);
  588. std::cout << d << std::endl; // will print '1.2'
  589. //]
  590. }
  591. // attr_cast
  592. {
  593. //[reference_qi_using_declarations_attr_cast
  594. using boost::spirit::qi::int_;
  595. //]
  596. //[reference_qi_attr_cast1
  597. int_data d = { 0 };
  598. test_parser_attr("1", boost::spirit::qi::attr_cast(int_), d);
  599. std::cout << d.i << std::endl;
  600. //]
  601. }
  602. // eol
  603. {
  604. //[reference_using_declarations_eol
  605. using boost::spirit::qi::eol;
  606. //]
  607. //[reference_eol
  608. test_parser("\n", eol);
  609. //]
  610. }
  611. // eoi
  612. {
  613. //[reference_using_declarations_eoi
  614. using boost::spirit::qi::eoi;
  615. //]
  616. //[reference_eoi
  617. test_parser("", eoi);
  618. //]
  619. }
  620. // eps
  621. {
  622. //[reference_using_declarations_eps
  623. using boost::spirit::qi::eps;
  624. using boost::spirit::qi::int_;
  625. using boost::spirit::qi::_1;
  626. namespace phx = boost::phoenix;
  627. //]
  628. //[reference_eps
  629. //`Basic `eps`:
  630. test_parser("", eps); // always matches
  631. //]
  632. //[reference_eps_if
  633. /*`This example simulates the "classic" `if_p` parser. Here, `int_` will be
  634. tried only if the condition, `c`, is true.
  635. */
  636. bool c = true; // a flag
  637. test_parser("1234", eps(phx::ref(c) == true) >> int_);
  638. //]
  639. //[reference_eps_while
  640. /*`This example simulates the "classic" `while_p` parser. Here, the kleene loop
  641. will exit once the condition, `c`, becomes true. Notice that the condition, `c`,
  642. is turned to `false` when we get to parse `4`.
  643. */
  644. test_phrase_parser("1 2 3 4",
  645. *(eps(phx::ref(c) == true) >> int_[phx::ref(c) = (_1 == 4)]));
  646. //]
  647. }
  648. // lazy
  649. {
  650. //[reference_using_declarations_lazy
  651. using boost::spirit::qi::lazy;
  652. using boost::spirit::ascii::string;
  653. using boost::phoenix::val;
  654. //]
  655. //[reference_lazy
  656. /*` Here, the phoenix::val expression creates a function
  657. that returns its argument when invoked. The lazy expression
  658. defers the invocation of this function at parse time. Then,
  659. this parser (string parser) is called into action. All this
  660. takes place at parse time.
  661. */
  662. test_parser("Hello", lazy(val(string("Hello"))));
  663. //` The above is equivalent to:
  664. test_parser("Hello", string("Hello"));
  665. //]
  666. }
  667. // char class
  668. {
  669. //[reference_using_declarations_char_class
  670. using boost::spirit::ascii::alnum;
  671. using boost::spirit::ascii::blank;
  672. using boost::spirit::ascii::digit;
  673. using boost::spirit::ascii::lower;
  674. //]
  675. //[reference_char_class
  676. test_parser("1", alnum);
  677. test_parser(" ", blank);
  678. test_parser("1", digit);
  679. test_parser("a", lower);
  680. //]
  681. }
  682. // uint
  683. {
  684. //[reference_using_declarations_uint
  685. using boost::phoenix::val;
  686. using boost::spirit::qi::lit;
  687. using boost::spirit::qi::uint_;
  688. using boost::spirit::qi::uint_parser;
  689. //]
  690. //[reference_uint
  691. // unsigned int
  692. test_parser("12345", uint_);
  693. test_parser("12345", uint_(12345));
  694. test_parser("12345", uint_(val(12345)));
  695. // literals
  696. test_parser("12345", lit(12345));
  697. test_parser("12345", lit(val(12345)));
  698. //]
  699. //[reference_thousand_separated
  700. //`Thousand separated number parser:
  701. uint_parser<unsigned, 10, 1, 3> uint3_p; // 1..3 digits
  702. uint_parser<unsigned, 10, 3, 3> uint3_3_p; // exactly 3 digits
  703. test_parser("12,345,678", uint3_p >> *(',' >> uint3_3_p));
  704. //]
  705. }
  706. // int
  707. {
  708. //[reference_using_declarations_int
  709. using boost::phoenix::val;
  710. using boost::spirit::qi::lit;
  711. using boost::spirit::qi::int_;
  712. //]
  713. //[reference_int
  714. // signed int
  715. test_parser("+12345", int_);
  716. test_parser("-12345", int_);
  717. test_parser("+12345", int_(12345));
  718. test_parser("-12345", int_(-12345));
  719. test_parser("+12345", int_(val(12345)));
  720. test_parser("-12345", int_(val(-12345)));
  721. // literals
  722. test_parser("+12345", lit(12345));
  723. test_parser("-12345", lit(-12345));
  724. test_parser("+12345", lit(val(12345)));
  725. test_parser("-12345", lit(val(-12345)));
  726. //]
  727. }
  728. // real
  729. {
  730. //[reference_using_declarations_real
  731. using boost::phoenix::val;
  732. using boost::spirit::qi::double_;
  733. using boost::spirit::qi::real_parser;
  734. using boost::spirit::qi::lit;
  735. //]
  736. //[reference_real
  737. // double
  738. test_parser("+12345e6", double_);
  739. test_parser("-12345e6", double_);
  740. test_parser("+12345e6", double_(12345e6));
  741. test_parser("-12345e6", double_(-123456e6));
  742. test_parser("+12345e6", double_(val(12345e6)));
  743. test_parser("-12345e6", double_(val(-123456e6)));
  744. // literals
  745. test_parser("+12345e6", lit(12345e6));
  746. test_parser("-12345e6", lit(-123456e6));
  747. test_parser("+12345e6", lit(val(12345e6)));
  748. test_parser("-12345e6", lit(val(-123456e6)));
  749. //]
  750. //[reference_custom_real
  751. real_parser<double, ts_real_policies<double> > ts_real;
  752. test_parser("123,456,789.01", ts_real);
  753. test_parser("123,456,789.01", ts_real(123456789.01));
  754. //]
  755. }
  756. // bool_
  757. {
  758. //[reference_using_declarations_bool
  759. using boost::phoenix::val;
  760. using boost::spirit::qi::bool_;
  761. using boost::spirit::qi::bool_parser;
  762. using boost::spirit::qi::lit;
  763. //]
  764. //[reference_bool
  765. // bool
  766. test_parser("true", bool_);
  767. test_parser("false", bool_);
  768. test_parser("true", bool_(true));
  769. test_parser("false", bool_(false));
  770. test_parser("true", bool_(val(true)));
  771. test_parser("false", bool_(val(false)));
  772. // literals
  773. test_parser("true", lit(true));
  774. test_parser("false", lit(false));
  775. test_parser("true", lit(val(true)));
  776. test_parser("false", lit(val(false)));
  777. //]
  778. //[reference_custom_bool
  779. bool_parser<bool, backwards_bool_policies> backwards_bool;
  780. test_parser("true", backwards_bool);
  781. test_parser("eurt", backwards_bool);
  782. test_parser("true", backwards_bool(true));
  783. test_parser("eurt", backwards_bool(false));
  784. //]
  785. }
  786. // sequence
  787. {
  788. //[reference_using_declarations_sequence
  789. using boost::spirit::ascii::char_;
  790. using boost::spirit::qi::_1;
  791. using boost::spirit::qi::_2;
  792. namespace bf = boost::fusion;
  793. //]
  794. //[reference_sequence
  795. //`Simple usage:
  796. test_parser("xy", char_ >> char_);
  797. //`Extracting the attribute tuple (using __fusion__):
  798. bf::vector<char, char> attr;
  799. test_parser_attr("xy", char_ >> char_, attr);
  800. std::cout << bf::at_c<0>(attr) << ',' << bf::at_c<1>(attr) << std::endl;
  801. //`Extracting the attribute vector (using __stl__):
  802. std::vector<char> vec;
  803. test_parser_attr("xy", char_ >> char_, vec);
  804. std::cout << vec[0] << ',' << vec[1] << std::endl;
  805. //`Extracting the attributes using __qi_semantic_actions__ (using __phoenix__):
  806. test_parser("xy", (char_ >> char_)[std::cout << _1 << ',' << _2 << std::endl]);
  807. //]
  808. }
  809. // sequential_or
  810. {
  811. //[reference_using_declarations_sequential_or
  812. using boost::spirit::qi::int_;
  813. //]
  814. //[reference_sequential_or
  815. //`Correctly parsing a number with optional fractional digits:
  816. test_parser("123.456", int_ || ('.' >> int_)); // full
  817. test_parser("123", int_ || ('.' >> int_)); // just the whole number
  818. test_parser(".456", int_ || ('.' >> int_)); // just the fraction
  819. /*`A naive but incorrect solution would try to do this using optionals (e.g.):
  820. int_ >> -('.' >> int_) // will not match ".456"
  821. -int_ >> ('.' >> int_) // will not match "123"
  822. -int_ >> -('.' >> int_) // will match empty strings! Ooops.
  823. */
  824. //]
  825. }
  826. // alternative
  827. {
  828. //[reference_using_declarations_alternative
  829. using boost::spirit::ascii::string;
  830. using boost::spirit::qi::int_;
  831. using boost::spirit::qi::_1;
  832. using boost::variant;
  833. //]
  834. //[reference_alternative
  835. //`Simple usage:
  836. test_parser("Hello", string("Hello") | int_);
  837. test_parser("123", string("Hello") | int_);
  838. //`Extracting the attribute variant (using __boost_variant__):
  839. variant<std::string, int> attr;
  840. test_parser_attr("Hello", string("Hello") | int_, attr);
  841. /*`This should print `"Hello"`. Note: There are better ways to extract the value
  842. from the variant. See __boost_variant__ visitation. This code is solely
  843. for demonstration.
  844. */
  845. if (boost::get<int>(&attr))
  846. std::cout << boost::get<int>(attr) << std::endl;
  847. else
  848. std::cout << boost::get<std::string>(attr) << std::endl;
  849. /*`Extracting the attributes using __qi_semantic_actions__ with __phoenix__
  850. (this should print `123`):
  851. */
  852. test_parser("123", (string("Hello") | int_)[std::cout << _1 << std::endl]);
  853. //]
  854. }
  855. // permutation
  856. {
  857. //[reference_using_declarations_permutation
  858. using boost::spirit::ascii::char_;
  859. //]
  860. //[reference_permutation
  861. //`Parse a string containing DNA codes (ACTG)
  862. test_parser("ACTGGCTAGACT", *(char_('A') ^ 'C' ^ 'T' ^ 'G'));
  863. //]
  864. }
  865. // expect
  866. {
  867. //[reference_using_declarations_expect
  868. using boost::spirit::ascii::char_;
  869. using boost::spirit::qi::expectation_failure;
  870. //]
  871. //[reference_expect
  872. /*`The code below uses an expectation operator to throw an __qi_expectation_failure__
  873. with a deliberate parsing error when `"o"` is expected and `"i"` is what is
  874. found in the input. The `catch` block prints the information related to the
  875. error. Note: This is low level code that demonstrates the /bare-metal/. Typically,
  876. you use an __qi_error_handler__ to deal with the error.
  877. */
  878. try
  879. {
  880. test_parser("xi", char_('x') > char_('o')); // should throw an exception
  881. }
  882. catch (expectation_failure<char const*> const& x)
  883. {
  884. std::cout << "expected: "; print_info(x.what_);
  885. std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl;
  886. }
  887. /*`The code above will print:[teletype]
  888. expected: tag: literal-char, value: o
  889. got: "i"``[c++]``
  890. */
  891. //]
  892. }
  893. // expectd
  894. {
  895. //[reference_using_declarations_expectd
  896. using boost::spirit::ascii::char_;
  897. using boost::spirit::qi::expect;
  898. using boost::spirit::qi::expectation_failure;
  899. //]
  900. //[reference_expectd
  901. /*`The code below uses an expectation operator to throw an __qi_expectation_failure__
  902. with a deliberate parsing error when `"o"` is expected and `"x"` is what is
  903. found in the input. The `catch` block prints the information related to the
  904. error. Note: This is low level code that demonstrates the /bare-metal/. Typically,
  905. you use an __qi_error_handler__ to deal with the error.
  906. */
  907. try
  908. {
  909. test_parser("xi", expect[char_('o')]); // should throw an exception
  910. }
  911. catch (expectation_failure<char const*> const& x)
  912. {
  913. std::cout << "expected: "; print_info(x.what_);
  914. std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl;
  915. }
  916. /*`The code above will print:[teletype]
  917. expected: tag: literal-char, value: o
  918. got: "x"``[c++]``
  919. */
  920. //]
  921. }
  922. // and-predicate
  923. {
  924. //[reference_and_predicate
  925. //`Some using declarations:
  926. using boost::spirit::lit;
  927. /*`Basic look-ahead example: make sure that the last character is a
  928. semicolon, but don't consume it, just peek at the next character:
  929. */
  930. test_phrase_parser("Hello ;", lit("Hello") >> &lit(';'), false);
  931. //]
  932. }
  933. // not-predicate
  934. {
  935. //[reference_not_predicate
  936. //`Some using declarations:
  937. using boost::spirit::ascii::char_;
  938. using boost::spirit::ascii::alpha;
  939. using boost::spirit::qi::lit;
  940. using boost::spirit::qi::symbols;
  941. /*`Here's an alternative to the `*(r - x) >> x` idiom using the
  942. not-predicate instead. This parses a list of characters terminated
  943. by a ';':
  944. */
  945. test_parser("abcdef;", *(!lit(';') >> char_) >> ';');
  946. /*`The following parser ensures that we match distinct keywords
  947. (stored in a symbol table). To do this, we make sure that the
  948. keyword does not follow an alpha or an underscore:
  949. */
  950. symbols<char, int> keywords;
  951. keywords = "begin", "end", "for";
  952. // This should fail:
  953. test_parser("beginner", keywords >> !(alpha | '_'));
  954. // This is ok:
  955. test_parser("end ", keywords >> !(alpha | '_'), false);
  956. // This is ok:
  957. test_parser("for()", keywords >> !(alpha | '_'), false);
  958. //]
  959. }
  960. // difference
  961. {
  962. //[reference_difference
  963. //`Some using declarations:
  964. using boost::spirit::ascii::char_;
  965. /*`Parse a C/C++ style comment:
  966. */
  967. test_parser("/*A Comment*/", "/*" >> *(char_ - "*/") >> "*/");
  968. //]
  969. }
  970. // kleene
  971. {
  972. //[reference_kleene
  973. //`Some using declarations:
  974. using boost::spirit::qi::int_;
  975. /*`Parse a comma separated list of numbers and put them in a vector:
  976. */
  977. std::vector<int> attr;
  978. test_phrase_parser_attr(
  979. "111, 222, 333, 444, 555", int_ >> *(',' >> int_), attr);
  980. std::cout
  981. << attr[0] << ',' << attr[1] << ',' << attr[2] << ','
  982. << attr[3] << ',' << attr[4]
  983. << std::endl;
  984. //]
  985. }
  986. // plus
  987. {
  988. //[reference_plus
  989. //`Some using declarations:
  990. using boost::spirit::ascii::alpha;
  991. using boost::spirit::qi::lexeme;
  992. /*`Parse one or more strings containing one or more alphabetic
  993. characters and put them in a vector:
  994. */
  995. std::vector<std::string> attr;
  996. test_phrase_parser_attr("yaba daba doo", +lexeme[+alpha], attr);
  997. std::cout << attr[0] << ',' << attr[1] << ',' << attr[2] << std::endl;
  998. //]
  999. }
  1000. // optional
  1001. {
  1002. //[reference_optional
  1003. //`Some using declarations:
  1004. using boost::spirit::ascii::char_;
  1005. using boost::spirit::qi::lexeme;
  1006. using boost::spirit::qi::int_;
  1007. using boost::fusion::vector;
  1008. using boost::fusion::at_c;
  1009. using boost::optional;
  1010. /*`Parse a person info with name (in quotes) optional age [footnote
  1011. James Bond is shy about his age :-)] and optional sex, all
  1012. separated by comma.
  1013. */
  1014. vector<std::string, optional<int>, optional<char> > attr;
  1015. test_phrase_parser_attr(
  1016. "\"James Bond\", M"
  1017. , lexeme['"' >> +(char_ - '"') >> '"'] // name
  1018. >> -(',' >> int_) // optional age
  1019. >> -(',' >> char_) // optional sex
  1020. , attr);
  1021. // Should print: James Bond,M
  1022. std::cout << at_c<0>(attr); // print name
  1023. if (at_c<1>(attr)) // print optional age
  1024. std::cout << ',' << *at_c<1>(attr);
  1025. if (at_c<2>(attr)) // print optional sex
  1026. std::cout << ',' << *at_c<2>(attr);
  1027. std::cout << std::endl;
  1028. //]
  1029. }
  1030. // list
  1031. {
  1032. //[reference_list
  1033. //`Some using declarations:
  1034. using boost::spirit::qi::int_;
  1035. /*`Parse a comma separated list of numbers and put them in a vector:
  1036. */
  1037. std::vector<int> attr;
  1038. test_phrase_parser_attr(
  1039. "111, 222, 333, 444, 555", int_ % ',', attr);
  1040. std::cout
  1041. << attr[0] << ',' << attr[1] << ',' << attr[2] << ','
  1042. << attr[3] << ',' << attr[4]
  1043. << std::endl;
  1044. //]
  1045. }
  1046. // stream
  1047. {
  1048. //[reference_qi_stream
  1049. //`Using declarations and variables:
  1050. using boost::spirit::qi::stream;
  1051. using boost::spirit::qi::stream_parser;
  1052. /*`Parse a simple string using the operator>>(istream&, std::string&);
  1053. */
  1054. std::string str;
  1055. test_parser_attr("abc", stream, str);
  1056. std::cout << str << std::endl; // prints: abc
  1057. /*`Parse our complex type using the operator>>(istream&, complex&);
  1058. */
  1059. complex c;
  1060. test_parser_attr("{1.0,2.5}", stream_parser<char, complex>(), c);
  1061. std::cout << c.a << "," << c.b << std::endl; // prints: 1.0,2.5
  1062. //]
  1063. }
  1064. ///////////////////////////////////////////////////////////////////////////
  1065. // auto module
  1066. {
  1067. //[reference_qi_using_declarations_auto
  1068. using boost::spirit::qi::auto_;
  1069. //]
  1070. //[reference_qi_auto
  1071. /*`Parse a simple integer using the generated parser component `int_`:
  1072. */
  1073. int i = 0;
  1074. test_parser_attr("123", auto_, i);
  1075. std::cout << i << std::endl; // prints: 123
  1076. /*`Parse an instance of the `complex` data type as defined above using
  1077. the parser as generated by the defined customization point:
  1078. */
  1079. complex c;
  1080. test_parser_attr("{1.2,2.4}", auto_, c);
  1081. std::cout << c.a << "," << c.b << std::endl; // prints: 1.2,2.4
  1082. //]
  1083. }
  1084. // native binary
  1085. {
  1086. //[reference_qi_native_binary
  1087. //`Using declarations and variables:
  1088. using boost::spirit::qi::byte_;
  1089. using boost::spirit::qi::word;
  1090. using boost::spirit::qi::dword;
  1091. using boost::spirit::qi::qword;
  1092. boost::uint8_t uc;
  1093. boost::uint16_t us;
  1094. boost::uint32_t ui;
  1095. //<-
  1096. #ifdef BOOST_HAS_LONG_LONG
  1097. //->
  1098. boost::uint64_t ul;
  1099. //<-
  1100. #endif
  1101. #if BOOST_ENDIAN_LITTLE_BYTE
  1102. //->
  1103. //`Basic usage of the native binary parsers for little endian platforms:
  1104. test_parser_attr("\x01", byte_, uc); assert(uc == 0x01);
  1105. test_parser_attr("\x01\x02", word, us); assert(us == 0x0201);
  1106. test_parser_attr("\x01\x02\x03\x04", dword, ui); assert(ui == 0x04030201);
  1107. //<-
  1108. #ifdef BOOST_HAS_LONG_LONG
  1109. //->
  1110. test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul);
  1111. assert(ul == 0x0807060504030201LL);
  1112. //<-
  1113. #endif
  1114. //->
  1115. test_parser("\x01", byte_(0x01));
  1116. test_parser("\x01\x02", word(0x0201));
  1117. test_parser("\x01\x02\x03\x04", dword(0x04030201));
  1118. //<-
  1119. #ifdef BOOST_HAS_LONG_LONG
  1120. //->
  1121. test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
  1122. qword(0x0807060504030201LL));
  1123. //<-
  1124. #endif
  1125. #else
  1126. //->
  1127. //`Basic usage of the native binary parsers for big endian platforms:
  1128. test_parser_attr("\x01", byte_, uc); assert(uc == 0x01);
  1129. test_parser_attr("\x01\x02", word, us); assert(us == 0x0102);
  1130. test_parser_attr("\x01\x02\x03\x04", dword, ui); assert(ui == 0x01020304);
  1131. //<-
  1132. #ifdef BOOST_HAS_LONG_LONG
  1133. //->
  1134. test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul);
  1135. assert(0x0102030405060708LL);
  1136. //<-
  1137. #endif
  1138. //->
  1139. test_parser("\x01", byte_(0x01));
  1140. test_parser("\x01\x02", word(0x0102));
  1141. test_parser("\x01\x02\x03\x04", dword(0x01020304));
  1142. //<-
  1143. #ifdef BOOST_HAS_LONG_LONG
  1144. //->
  1145. test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
  1146. qword(0x0102030405060708LL));
  1147. //<-
  1148. #endif
  1149. #endif
  1150. //->
  1151. //]
  1152. }
  1153. // little binary
  1154. {
  1155. //[reference_qi_little_binary
  1156. //`Using declarations and variables:
  1157. using boost::spirit::qi::little_word;
  1158. using boost::spirit::qi::little_dword;
  1159. using boost::spirit::qi::little_qword;
  1160. boost::uint16_t us;
  1161. boost::uint32_t ui;
  1162. //<-
  1163. #ifdef BOOST_HAS_LONG_LONG
  1164. //->
  1165. boost::uint64_t ul;
  1166. //<-
  1167. #endif
  1168. //->
  1169. //`Basic usage of the little endian binary parsers:
  1170. test_parser_attr("\x01\x02", little_word, us); assert(us == 0x0201);
  1171. test_parser_attr("\x01\x02\x03\x04", little_dword, ui); assert(ui == 0x04030201);
  1172. //<-
  1173. #ifdef BOOST_HAS_LONG_LONG
  1174. //->
  1175. test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", little_qword, ul);
  1176. assert(ul == 0x0807060504030201LL);
  1177. //<-
  1178. #endif
  1179. //->
  1180. test_parser("\x01\x02", little_word(0x0201));
  1181. test_parser("\x01\x02\x03\x04", little_dword(0x04030201));
  1182. //<-
  1183. #ifdef BOOST_HAS_LONG_LONG
  1184. //->
  1185. test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
  1186. little_qword(0x0807060504030201LL));
  1187. //<-
  1188. #endif
  1189. //->
  1190. //]
  1191. }
  1192. // big binary
  1193. {
  1194. //[reference_qi_big_binary
  1195. //`Using declarations and variables:
  1196. using boost::spirit::qi::big_word;
  1197. using boost::spirit::qi::big_dword;
  1198. using boost::spirit::qi::big_qword;
  1199. boost::uint16_t us;
  1200. boost::uint32_t ui;
  1201. //<-
  1202. #ifdef BOOST_HAS_LONG_LONG
  1203. //->
  1204. boost::uint64_t ul;
  1205. //<-
  1206. #endif
  1207. //->
  1208. //`Basic usage of the big endian binary parsers:
  1209. test_parser_attr("\x01\x02", big_word, us); assert(us == 0x0102);
  1210. test_parser_attr("\x01\x02\x03\x04", big_dword, ui); assert(ui == 0x01020304);
  1211. //<-
  1212. #ifdef BOOST_HAS_LONG_LONG
  1213. //->
  1214. test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", big_qword, ul);
  1215. assert(0x0102030405060708LL);
  1216. //<-
  1217. #endif
  1218. //->
  1219. test_parser("\x01\x02", big_word(0x0102));
  1220. test_parser("\x01\x02\x03\x04", big_dword(0x01020304));
  1221. //<-
  1222. #ifdef BOOST_HAS_LONG_LONG
  1223. //->
  1224. test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
  1225. big_qword(0x0102030405060708LL));
  1226. //<-
  1227. #endif
  1228. //->
  1229. //]
  1230. }
  1231. // rule
  1232. {
  1233. //[reference_rule
  1234. //`Some using declarations:
  1235. using boost::spirit::qi::rule;
  1236. using boost::spirit::qi::int_;
  1237. using boost::spirit::qi::locals;
  1238. using boost::spirit::qi::_1;
  1239. using boost::spirit::qi::_a;
  1240. using boost::spirit::ascii::alpha;
  1241. using boost::spirit::ascii::char_;
  1242. using boost::spirit::ascii::space_type;
  1243. /*`Basic rule:
  1244. */
  1245. rule<char const*> r;
  1246. r = int_;
  1247. test_parser("123", r);
  1248. /*`Rule with synthesized attribute:
  1249. */
  1250. rule<char const*, int()> ra;
  1251. ra = int_;
  1252. int i;
  1253. test_parser_attr("123", ra, i);
  1254. assert(i == 123);
  1255. /*`Rule with skipper and synthesized attribute:
  1256. */
  1257. rule<char const*, std::vector<int>(), space_type> rs;
  1258. rs = *int_;
  1259. std::vector<int> v;
  1260. test_phrase_parser_attr("123 456 789", rs, v);
  1261. assert(v[0] == 123);
  1262. assert(v[1] == 456);
  1263. assert(v[2] == 789);
  1264. /*`Rule with one local variable:
  1265. */
  1266. rule<char const*, locals<char> > rl;
  1267. rl = alpha[_a = _1] >> char_(_a); // get two identical characters
  1268. test_parser("aa", rl); // pass
  1269. test_parser("ax", rl); // fail
  1270. //]
  1271. }
  1272. // grammar
  1273. {
  1274. using client::num_list;
  1275. //[reference_grammar_using
  1276. //`Some using declarations:
  1277. using boost::spirit::ascii::space_type;
  1278. using boost::spirit::int_;
  1279. using boost::spirit::qi::grammar;
  1280. using boost::spirit::qi::rule;
  1281. //]
  1282. //[reference_grammar
  1283. //`How to use the example grammar:
  1284. num_list nlist;
  1285. test_phrase_parser("123, 456, 789", nlist);
  1286. //]
  1287. }
  1288. return 0;
  1289. }