flush_multi_pass.cpp 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright (c) 2001-2010 Hartmut Kaiser
  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. // The purpose of this example is to demonstrate a simple use case for the
  6. // flush_multi_pass parser.
  7. #include <iostream>
  8. #include <fstream>
  9. #include <string>
  10. //[qi_flush_multi_pass_includes
  11. #include <boost/spirit/include/qi.hpp>
  12. #include <boost/spirit/repository/include/qi_flush_multi_pass.hpp>
  13. //]
  14. //[qi_flush_multi_pass_namespace
  15. namespace spirit = boost::spirit;
  16. using boost::spirit::repository::flush_multi_pass;
  17. //]
  18. namespace client
  19. {
  20. //[qi_flush_multi_pass_clear_buffer
  21. template <typename Iterator, typename Skipper>
  22. struct preprocessor : spirit::qi::grammar<Iterator, Skipper>
  23. {
  24. // This is a simplified preprocessor grammar recognizing
  25. //
  26. // #define MACRONAME something
  27. // #undef MACRONAME
  28. //
  29. // Its sole purpose is to show an example how to use the
  30. // flush_multi_pass parser. At the end of each line no backtracking can
  31. // occur anymore so that it's safe to clear all internal buffers in the
  32. // multi_pass.
  33. preprocessor() : preprocessor::base_type(file)
  34. {
  35. using spirit::ascii::char_;
  36. using spirit::qi::eol;
  37. using spirit::qi::lit;
  38. file =
  39. *line
  40. ;
  41. line = ( command | *(char_ - eol) )
  42. >> eol
  43. >> flush_multi_pass
  44. ;
  45. command =
  46. "#define" >> *lit(' ') >> *(char_ - ' ') >> *lit(' ') >> *(char_ - eol)
  47. | "#undef" >> *lit(' ') >> *(char_ - eol)
  48. ;
  49. }
  50. spirit::qi::rule<Iterator, Skipper> file, line, command;
  51. };
  52. //]
  53. }
  54. template <typename Iterator, typename Skipper>
  55. bool parse(Iterator& first, Iterator end, Skipper const& skipper)
  56. {
  57. client::preprocessor<Iterator, Skipper> g;
  58. return boost::spirit::qi::phrase_parse(first, end, g, skipper);
  59. }
  60. int main()
  61. {
  62. namespace spirit = boost::spirit;
  63. using spirit::ascii::char_;
  64. using spirit::qi::eol;
  65. std::ifstream in("flush_multi_pass.txt"); // we get our input from this file
  66. if (!in.is_open()) {
  67. std::cout << "Could not open input file: 'flush_multi_pass.txt'" << std::endl;
  68. return -1;
  69. }
  70. typedef std::istreambuf_iterator<char> base_iterator_type;
  71. spirit::multi_pass<base_iterator_type> first =
  72. spirit::make_default_multi_pass(base_iterator_type(in));
  73. spirit::multi_pass<base_iterator_type> end =
  74. spirit::make_default_multi_pass(base_iterator_type());
  75. bool result = parse(first, end, '#' >> *(char_ - eol) >> eol);
  76. if (!result) {
  77. std::cout << "Failed parsing input file!" << std::endl;
  78. return -2;
  79. }
  80. std::cout << "Successfully parsed input file!" << std::endl;
  81. return 0;
  82. }