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