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

source code of boost/libs/spirit/example/lex/print_numbers.cpp