print_number_tokenids.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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_tokenids : 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_tokenids()
  39. : print_numbers_tokenids::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. // this prints the token ids of the matched tokens
  57. start = *( qi::tokenid(lex::min_token_id)
  58. | qi::tokenid(lex::min_token_id+1)
  59. )
  60. [ std::cout << _1 << "\n" ]
  61. ;
  62. }
  63. qi::rule<Iterator> start;
  64. };
  65. ///////////////////////////////////////////////////////////////////////////////
  66. int main(int argc, char* argv[])
  67. {
  68. // iterator type used to expose the underlying input stream
  69. typedef std::string::iterator base_iterator_type;
  70. // the token type to be used, 'int' is available as the type of the token
  71. // attribute and no lexer state is supported
  72. typedef lex::lexertl::token<base_iterator_type, boost::mpl::vector<int>
  73. , boost::mpl::false_> token_type;
  74. // lexer type
  75. typedef lex::lexertl::lexer<token_type> lexer_type;
  76. // iterator type exposed by the lexer
  77. typedef print_numbers_tokenids<lexer_type>::iterator_type iterator_type;
  78. // now we use the types defined above to create the lexer and grammar
  79. // object instances needed to invoke the parsing process
  80. print_numbers_tokenids<lexer_type> print_tokens; // Our lexer
  81. print_numbers_grammar<iterator_type> print; // Our parser
  82. // Parsing is done based on the token stream, not the character
  83. // stream read from the input.
  84. std::string str (read_from_file(1 == argc ? "print_numbers.input" : argv[1]));
  85. base_iterator_type first = str.begin();
  86. bool r = lex::tokenize_and_parse(first, str.end(), print_tokens, print);
  87. if (r) {
  88. std::cout << "-------------------------\n";
  89. std::cout << "Parsing succeeded\n";
  90. std::cout << "-------------------------\n";
  91. }
  92. else {
  93. std::string rest(first, str.end());
  94. std::cout << "-------------------------\n";
  95. std::cout << "Parsing failed\n";
  96. std::cout << "stopped at: \"" << rest << "\"\n";
  97. std::cout << "-------------------------\n";
  98. }
  99. std::cout << "Bye... :-) \n\n";
  100. return 0;
  101. }