print_numbers.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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. // This example is the equivalent to the following lex program:
  6. //
  7. // %{
  8. // #include <stdio.h>
  9. // %}
  10. // %%
  11. // [0-9]+ { printf("%s\n", yytext); }
  12. // .|\n ;
  13. // %%
  14. // main()
  15. // {
  16. // yylex();
  17. // }
  18. //
  19. // Its purpose is to print all the (integer) numbers found in a file
  20. #include <boost/config/warning_disable.hpp>
  21. #include <boost/spirit/include/qi.hpp>
  22. #include <boost/spirit/include/lex_lexertl.hpp>
  23. #include <boost/spirit/include/phoenix_operator.hpp>
  24. #include <iostream>
  25. #include <string>
  26. #include "example.hpp"
  27. using namespace boost::spirit;
  28. ///////////////////////////////////////////////////////////////////////////////
  29. // Token definition: We use the lexertl based lexer engine as the underlying
  30. // lexer type.
  31. ///////////////////////////////////////////////////////////////////////////////
  32. template <typename Lexer>
  33. struct print_numbers_tokens : lex::lexer<Lexer>
  34. {
  35. // define tokens and associate it with the lexer, we set the lexer flags
  36. // not to match newlines while matching a dot, so we need to add the
  37. // '\n' explicitly below
  38. print_numbers_tokens()
  39. : print_numbers_tokens::base_type(lex::match_flags::match_not_dot_newline)
  40. {
  41. this->self = lex::token_def<int>("[0-9]+") | ".|\n";
  42. }
  43. };
  44. ///////////////////////////////////////////////////////////////////////////////
  45. // Grammar definition
  46. ///////////////////////////////////////////////////////////////////////////////
  47. template <typename Iterator>
  48. struct print_numbers_grammar : qi::grammar<Iterator>
  49. {
  50. print_numbers_grammar()
  51. : print_numbers_grammar::base_type(start)
  52. {
  53. // we just know, that the token ids get assigned starting min_token_id
  54. // so, "[0-9]+" gets the id 'min_token_id' and ".|\n" gets the id
  55. // 'min_token_id+1'.
  56. start = *( qi::token(lex::min_token_id) [ std::cout << _1 << "\n" ]
  57. | qi::token(lex::min_token_id+1)
  58. )
  59. ;
  60. }
  61. qi::rule<Iterator> start;
  62. };
  63. ///////////////////////////////////////////////////////////////////////////////
  64. int main(int argc, char* argv[])
  65. {
  66. // iterator type used to expose the underlying input stream
  67. typedef std::string::iterator base_iterator_type;
  68. // the token type to be used, 'int' is available as the type of the token
  69. // attribute and no lexer state is supported
  70. typedef lex::lexertl::token<base_iterator_type, boost::mpl::vector<int>
  71. , boost::mpl::false_> token_type;
  72. // lexer type
  73. typedef lex::lexertl::lexer<token_type> lexer_type;
  74. // iterator type exposed by the lexer
  75. typedef print_numbers_tokens<lexer_type>::iterator_type iterator_type;
  76. // now we use the types defined above to create the lexer and grammar
  77. // object instances needed to invoke the parsing process
  78. print_numbers_tokens<lexer_type> print_tokens; // Our lexer
  79. print_numbers_grammar<iterator_type> print; // Our parser
  80. // Parsing is done based on the token stream, not the character
  81. // stream read from the input.
  82. std::string str (read_from_file(1 == argc ? "print_numbers.input" : argv[1]));
  83. base_iterator_type first = str.begin();
  84. bool r = lex::tokenize_and_parse(first, str.end(), print_tokens, print);
  85. if (r) {
  86. std::cout << "-------------------------\n";
  87. std::cout << "Parsing succeeded\n";
  88. std::cout << "-------------------------\n";
  89. }
  90. else {
  91. std::string rest(first, str.end());
  92. std::cout << "-------------------------\n";
  93. std::cout << "Parsing failed\n";
  94. std::cout << "stopped at: \"" << rest << "\"\n";
  95. std::cout << "-------------------------\n";
  96. }
  97. std::cout << "Bye... :-) \n\n";
  98. return 0;
  99. }