comments.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*=============================================================================
  2. Copyright (c) 2001-2003 Hartmut Kaiser
  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. // This example shows:
  11. // 1. Parsing of different comment styles
  12. // parsing C/C++-style comment
  13. // parsing C++-style comment
  14. // parsing PASCAL-style comment
  15. // 2. Parsing tagged data with the help of the confix_parser
  16. // 3. Parsing tagged data with the help of the confix_parser but the semantic
  17. // action is directly attached to the body sequence parser
  18. //
  19. ///////////////////////////////////////////////////////////////////////////////
  20. #include <string>
  21. #include <iostream>
  22. #include <cassert>
  23. #include <boost/spirit/include/classic_core.hpp>
  24. #include <boost/spirit/include/classic_confix.hpp>
  25. #include <boost/spirit/include/classic_chset.hpp>
  26. ///////////////////////////////////////////////////////////////////////////////
  27. // used namespaces
  28. using namespace std;
  29. using namespace BOOST_SPIRIT_CLASSIC_NS;
  30. ///////////////////////////////////////////////////////////////////////////////
  31. // actor called after successfully matching a single character
  32. class actor_string
  33. {
  34. public:
  35. actor_string(std::string &rstr) :
  36. matched(rstr)
  37. {
  38. }
  39. void operator() (const char *pbegin, const char *pend) const
  40. {
  41. matched += std::string(pbegin, pend-pbegin);
  42. }
  43. private:
  44. std::string &matched;
  45. };
  46. ///////////////////////////////////////////////////////////////////////////////
  47. // actor called after successfully matching a C++-comment
  48. void actor_cpp (const char *pfirst, const char *plast)
  49. {
  50. cout << "Parsing C++-comment" <<endl;
  51. cout << "Matched (" << plast-pfirst << ") characters: ";
  52. cout << "\"" << std::string(pfirst, plast) << "\"" << endl;
  53. }
  54. ///////////////////////////////////////////////////////////////////////////////
  55. // main entry point
  56. int main ()
  57. {
  58. ///////////////////////////////////////////////////////////////////////////////
  59. //
  60. // 1. Parsing different comment styles
  61. // parsing C/C++-style comments (non-nested!)
  62. //
  63. ///////////////////////////////////////////////////////////////////////////////
  64. char const* pCComment = "/* This is a /* nested */ C-comment */";
  65. rule<> cpp_comment;
  66. cpp_comment =
  67. comment_p("/*", "*/") // rule for C-comments
  68. | comment_p("//") // rule for C++ comments
  69. ;
  70. std::string comment_c;
  71. parse_info<> result;
  72. result = parse (pCComment, cpp_comment[actor_string(comment_c)]);
  73. if (result.hit)
  74. {
  75. cout << "Parsed C-comment successfully!" << endl;
  76. cout << "Matched (" << (int)comment_c.size() << ") characters: ";
  77. cout << "\"" << comment_c << "\"" << endl;
  78. }
  79. else
  80. {
  81. cout << "Failed to parse C/C++-comment!" << endl;
  82. }
  83. cout << endl;
  84. // parsing C++-style comment
  85. char const* pCPPComment = "// This is a C++-comment\n";
  86. std::string comment_cpp;
  87. result = parse (pCPPComment, cpp_comment[&actor_cpp]);
  88. if (result.hit)
  89. cout << "Parsed C++-comment successfully!" << endl;
  90. else
  91. cout << "Failed to parse C++-comment!" << endl;
  92. cout << endl;
  93. // parsing PASCAL-style comment (nested!)
  94. char const* pPComment = "{ This is a (* nested *) PASCAL-comment }";
  95. rule<> pascal_comment;
  96. pascal_comment = // in PASCAL we have two comment styles
  97. comment_nest_p('{', '}') // both may be nested
  98. | comment_nest_p("(*", "*)")
  99. ;
  100. std::string comment_pascal;
  101. result = parse (pPComment, pascal_comment[actor_string(comment_pascal)]);
  102. if (result.hit)
  103. {
  104. cout << "Parsed PASCAL-comment successfully!" << endl;
  105. cout << "Matched (" << (int)comment_pascal.size() << ") characters: ";
  106. cout << "\"" << comment_pascal << "\"" << endl;
  107. }
  108. else
  109. {
  110. cout << "Failed to parse PASCAL-comment!" << endl;
  111. }
  112. cout << endl;
  113. ///////////////////////////////////////////////////////////////////////////////
  114. //
  115. // 2. Parsing tagged data with the help of the confix parser
  116. //
  117. ///////////////////////////////////////////////////////////////////////////////
  118. std::string body;
  119. rule<> open_tag, html_tag, close_tag, body_text;
  120. open_tag =
  121. str_p("<b>")
  122. ;
  123. body_text =
  124. anychar_p
  125. ;
  126. close_tag =
  127. str_p("</b>")
  128. ;
  129. html_tag =
  130. confix_p (open_tag, (*body_text)[actor_string(body)], close_tag)
  131. ;
  132. char const* pTag = "<b>Body text</b>";
  133. result = parse (pTag, html_tag);
  134. if (result.hit)
  135. {
  136. cout << "Parsed HTML snippet \"<b>Body text</b>\" successfully "
  137. "(with re-attached actor)!" << endl;
  138. cout << "Found body (" << (int)body.size() << " characters): ";
  139. cout << "\"" << body << "\"" << endl;
  140. }
  141. else
  142. {
  143. cout << "Failed to parse HTML snippet (with re-attached actor)!"
  144. << endl;
  145. }
  146. cout << endl;
  147. ///////////////////////////////////////////////////////////////////////////////
  148. //
  149. // 3. Parsing tagged data with the help of the confix_parser but the
  150. // semantic action is directly attached to the body sequence parser
  151. // (see comment in confix.hpp) and out of the usage of the 'direct()'
  152. // construction function no automatic refactoring takes place.
  153. //
  154. // As you can see, for successful parsing it is required to refactor the
  155. // confix parser by hand. To see, how it fails, you can try the following:
  156. //
  157. // html_tag_direct =
  158. // confix_p.direct(
  159. // str_p("<b>"),
  160. // (*body_text)[actor_string(bodydirect)],
  161. // str_p("</b>")
  162. // )
  163. // ;
  164. //
  165. // Here the *body_text parser eats up all the input up to the end of the
  166. // input sequence.
  167. //
  168. ///////////////////////////////////////////////////////////////////////////////
  169. rule<> html_tag_direct;
  170. std::string bodydirect;
  171. html_tag_direct =
  172. confix_p.direct(
  173. str_p("<b>"),
  174. (*(body_text - str_p("</b>")))[actor_string(bodydirect)],
  175. str_p("</b>")
  176. )
  177. ;
  178. char const* pTagDirect = "<b>Body text</b>";
  179. result = parse (pTagDirect, html_tag_direct);
  180. if (result.hit)
  181. {
  182. cout << "Parsed HTML snippet \"<b>Body text</b>\" successfully "
  183. "(with direct actor)!" << endl;
  184. cout << "Found body (" << (int)bodydirect.size() << " characters): ";
  185. cout << "\"" << bodydirect << "\"" << endl;
  186. }
  187. else
  188. {
  189. cout << "Failed to parse HTML snippet (with direct actor)!" << endl;
  190. }
  191. cout << endl;
  192. return 0;
  193. }