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// problem in multi_pass showing up in conjunction with certain lexer usage patterns
8
9#include <boost/spirit/include/support_multi_pass.hpp>
10#include <boost/spirit/include/lex_lexertl.hpp>
11
12#include <boost/core/lightweight_test.hpp>
13#include <boost/phoenix/operator/self.hpp>
14#include <boost/phoenix/statement/sequence.hpp>
15
16#include <sstream>
17
18namespace spirit = boost::spirit;
19namespace lex = spirit::lex;
20
21typedef char const* content_iterator;
22
23struct identifier
24{
25 identifier(content_iterator, content_iterator)
26 {
27 }
28};
29
30struct string_literal
31{
32 string_literal(content_iterator, content_iterator)
33 {
34 }
35};
36
37typedef lex::lexertl::token<
38 content_iterator, boost::mpl::vector<identifier, string_literal>
39> token_type;
40
41struct lexer
42 : lex::lexer<lex::lexertl::actor_lexer<token_type> >
43{
44 lexer()
45 : id("[a-zA-Z0-9]+", 1)
46 , st("'[^'\\n]*'", 2)
47 {
48 self = id [
49 lex::_state = "ST"
50 ]
51 | lex::token_def<>(".", 3) [
52 lex::_state = "ST"
53 ]
54 ;
55
56 self("ST") =
57 st [
58 lex::_state = "INITIAL"
59 ]
60 | lex::token_def<>(".", 4) [(
61 lex::_state = "INITIAL"
62 , lex::_pass = lex::pass_flags::pass_fail
63 )]
64 ;
65 }
66
67 lex::token_def<identifier> id;
68 lex::token_def<string_literal> st;
69};
70
71typedef lexer::iterator_type token_iterator;
72
73int main()
74{
75 std::string const s = "foo 'bar'";
76
77 content_iterator begin = s.data();
78 content_iterator end = s.data() + s.size();
79
80 lexer l;
81 token_iterator begin2 = l.begin(first&: begin, last: end, initial_state: "ST");
82 token_iterator end2 = l.end();
83
84 std::size_t test_data[] = { 1, 3, 2 };
85 std::size_t const test_data_size = sizeof(test_data)/sizeof(test_data[0]);
86
87 token_iterator it = begin2;
88 std::size_t i = 0;
89 for (/**/; it != end2 && i < test_data_size; ++it, ++i)
90 {
91 BOOST_TEST(it->id() == test_data[i]);
92 }
93 BOOST_TEST(it == end2);
94 BOOST_TEST(i == test_data_size);
95
96 return boost::report_errors();
97}
98

source code of boost/libs/spirit/test/lex/multi_pass.cpp