1 // Copyright (c) 2001-2010 Hartmut Kaiser
2 // Copyright (c) 2010 Mathias Gaunard
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 // This test makes sure that the BOL state (begin of line) is properly reset
8 // if a token matched at the beginning of a line is discarded using
9 // lex::pass_fail.
10
11 #include <boost/config/warning_disable.hpp>
12 #include <boost/detail/lightweight_test.hpp>
13
14 #include <boost/spirit/include/support_multi_pass.hpp>
15 #include <boost/spirit/include/classic_position_iterator.hpp>
16 #include <boost/spirit/include/lex_lexertl.hpp>
17 #include <boost/phoenix/operator/self.hpp>
18 #include <boost/phoenix/statement/sequence.hpp>
19
20 namespace spirit = boost::spirit;
21 namespace lex = spirit::lex;
22
23 typedef spirit::classic::position_iterator2<
24 spirit::multi_pass<std::istreambuf_iterator<char> >
25 > file_iterator;
26
27 inline file_iterator
make_file_iterator(std::istream & input,const std::string & filename)28 make_file_iterator(std::istream& input, const std::string& filename)
29 {
30 return file_iterator(
31 spirit::make_default_multi_pass(
32 std::istreambuf_iterator<char>(input)),
33 spirit::multi_pass<std::istreambuf_iterator<char> >(),
34 filename);
35 }
36
37 typedef lex::lexertl::token<file_iterator> token_type;
38
39 struct lexer
40 : lex::lexer<lex::lexertl::actor_lexer<token_type> >
41 {
lexerlexer42 lexer() : word("^[a-zA-Z0-9]+$", 1)
43 {
44 self = word [
45 lex::_state = "O"
46 ]
47 | lex::token_def<>("!.*$") [(
48 lex::_state = "O"
49 , lex::_pass = lex::pass_flags::pass_ignore
50 )]
51 | lex::token_def<>('\n', 2) [
52 lex::_state = "O"
53 ]
54 ;
55
56 self("O") =
57 lex::token_def<>(".") [(
58 lex::_state = "INITIAL"
59 , lex::_pass = lex::pass_flags::pass_fail
60 )]
61 ;
62 }
63
64 lex::token_def<> word;
65 };
66
67 typedef lexer::iterator_type token_iterator;
68
main()69 int main()
70 {
71 std::stringstream ss;
72 ss << "!foo\nbar\n!baz";
73
74 file_iterator begin = make_file_iterator(ss, "SS");
75 file_iterator end;
76
77 lexer l;
78 token_iterator begin2 = l.begin(begin, end);
79 token_iterator end2 = l.end();
80
81 std::size_t test_data[] = { 2, 1, 2 };
82 std::size_t const test_data_size = sizeof(test_data)/sizeof(test_data[0]);
83
84 token_iterator it = begin2;
85 std::size_t i = 0;
86 for (/**/; it != end2 && i < test_data_size; ++it, ++i)
87 {
88 BOOST_TEST(it->id() == test_data[i]);
89 }
90 BOOST_TEST(it == end2);
91 BOOST_TEST(i == test_data_size);
92
93 return boost::report_errors();
94 }
95