matching_tags.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*=============================================================================
  2. Copyright (c) 2002-2003 Joel de Guzman
  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. //
  10. // HTML/XML like tag matching grammar
  11. // Demonstrates phoenix and closures and parametric parsers
  12. // This is discussed in the "Closures" chapter in the Spirit User's Guide.
  13. //
  14. // [ JDG 6/30/2002 ]
  15. //
  16. ////////////////////////////////////////////////////////////////////////////
  17. #include <boost/spirit/include/classic_core.hpp>
  18. #include <boost/spirit/include/classic_attribute.hpp>
  19. #include <iostream>
  20. #include <string>
  21. ////////////////////////////////////////////////////////////////////////////
  22. using namespace std;
  23. using namespace BOOST_SPIRIT_CLASSIC_NS;
  24. using namespace phoenix;
  25. ////////////////////////////////////////////////////////////////////////////
  26. //
  27. // HTML/XML like tag matching grammar
  28. //
  29. ////////////////////////////////////////////////////////////////////////////
  30. struct tags_closure : BOOST_SPIRIT_CLASSIC_NS::closure<tags_closure, string>
  31. {
  32. member1 tag;
  33. };
  34. struct tags : public grammar<tags>
  35. {
  36. template <typename ScannerT>
  37. struct definition {
  38. definition(tags const& /*self*/)
  39. {
  40. element = start_tag >> *element >> end_tag;
  41. start_tag =
  42. '<'
  43. >> lexeme_d
  44. [
  45. (+alpha_p)
  46. [
  47. // construct string from arg1 and arg2 lazily
  48. // and assign to element.tag
  49. element.tag = construct_<string>(arg1, arg2)
  50. ]
  51. ]
  52. >> '>';
  53. end_tag = "</" >> f_str_p(element.tag) >> '>';
  54. }
  55. rule<ScannerT, tags_closure::context_t> element;
  56. rule<ScannerT> start_tag, end_tag;
  57. rule<ScannerT, tags_closure::context_t> const&
  58. start() const { return element; }
  59. };
  60. };
  61. ////////////////////////////////////////////////////////////////////////////
  62. //
  63. // Main program
  64. //
  65. ////////////////////////////////////////////////////////////////////////////
  66. int
  67. main()
  68. {
  69. cout << "/////////////////////////////////////////////////////////\n\n";
  70. cout << "\t\tHTML/XML like tag matching parser demo \n\n";
  71. cout << "/////////////////////////////////////////////////////////\n\n";
  72. cout << "Type an HTML/XML like nested tag input...or [q or Q] to quit\n\n";
  73. cout << "Example: <html><head></head><body></body></html>\n\n";
  74. tags p; // Our parser
  75. string str;
  76. while (getline(cin, str))
  77. {
  78. if (str.empty() || str[0] == 'q' || str[0] == 'Q')
  79. break;
  80. parse_info<> info = parse(str.c_str(), p, space_p);
  81. if (info.full)
  82. {
  83. cout << "-------------------------\n";
  84. cout << "Parsing succeeded\n";
  85. cout << "-------------------------\n";
  86. }
  87. else
  88. {
  89. cout << "-------------------------\n";
  90. cout << "Parsing failed\n";
  91. cout << "stopped at: \": " << info.stop << "\"\n";
  92. cout << "-------------------------\n";
  93. }
  94. }
  95. cout << "Bye... :-) \n\n";
  96. return 0;
  97. }