lazy_parser.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*=============================================================================
  2. Copyright (c) 2003 Vaclav Vesely
  3. http://spirit.sourceforge.net/
  4. Use, modification and distribution is subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. //
  9. // This example demonstrates the lazy_p parser. You should read
  10. // "The Lazy Parser" in the documentation.
  11. //
  12. // We want to parse nested blocks of numbers like this:
  13. //
  14. // dec {
  15. // 1 2 3
  16. // bin {
  17. // 1 10 11
  18. // }
  19. // 4 5 6
  20. // }
  21. //
  22. // where the numbers in the "dec" block are wrote in the decimal system and
  23. // the numbers in the "bin" block are wrote in the binary system. We want
  24. // parser to return the overall sum.
  25. //
  26. // To achive this when base ("bin" or "dec") is parsed, in semantic action
  27. // we store a pointer to the appropriate numeric parser in the closure
  28. // variable block.int_rule. Than, when we need to parse a number we use lazy_p
  29. // parser to invoke the parser stored in the block.int_rule pointer.
  30. //
  31. //-----------------------------------------------------------------------------
  32. #include <boost/assert.hpp>
  33. #include <boost/cstdlib.hpp>
  34. #include <boost/spirit/include/phoenix1.hpp>
  35. #include <boost/spirit/include/classic_core.hpp>
  36. #include <boost/spirit/include/classic_symbols.hpp>
  37. #include <boost/spirit/include/classic_attribute.hpp>
  38. #include <boost/spirit/include/classic_dynamic.hpp>
  39. using namespace boost;
  40. using namespace BOOST_SPIRIT_CLASSIC_NS;
  41. using namespace phoenix;
  42. //-----------------------------------------------------------------------------
  43. // my grammar
  44. struct my_grammar
  45. : public grammar<my_grammar, parser_context<int> >
  46. {
  47. // grammar definition
  48. template<typename ScannerT>
  49. struct definition
  50. {
  51. typedef rule<ScannerT> rule_t;
  52. typedef stored_rule<ScannerT, parser_context<int> > number_rule_t;
  53. struct block_closure;
  54. typedef boost::spirit::classic::closure<
  55. block_closure,
  56. int,
  57. typename number_rule_t::alias_t>
  58. closure_base_t;
  59. struct block_closure : closure_base_t
  60. {
  61. typename closure_base_t::member1 sum;
  62. typename closure_base_t::member2 int_rule;
  63. };
  64. // block rule type
  65. typedef rule<ScannerT, typename block_closure::context_t> block_rule_t;
  66. block_rule_t block;
  67. rule_t block_item;
  68. symbols<number_rule_t> base;
  69. definition(my_grammar const& self)
  70. {
  71. block =
  72. base[
  73. block.sum = 0,
  74. // store a number rule in a closure member
  75. block.int_rule = arg1
  76. ]
  77. >> "{"
  78. >> *block_item
  79. >> "}"
  80. ;
  81. block_item =
  82. // use the stored rule
  83. lazy_p(block.int_rule)[block.sum += arg1]
  84. | block[block.sum += arg1]
  85. ;
  86. // bind base keywords and number parsers
  87. base.add
  88. ("bin", bin_p)
  89. ("dec", uint_p)
  90. ;
  91. }
  92. block_rule_t const& start() const
  93. {
  94. return block;
  95. }
  96. };
  97. };
  98. //-----------------------------------------------------------------------------
  99. int main()
  100. {
  101. my_grammar gram;
  102. parse_info<> info;
  103. int result;
  104. info = parse("bin{1 dec{1 2 3} 10}", gram[var(result) = arg1], space_p);
  105. BOOST_ASSERT(info.full);
  106. BOOST_ASSERT(result == 9);
  107. return exit_success;
  108. }
  109. //-----------------------------------------------------------------------------