1 //  Copyright (c) 2001-2010 Hartmut Kaiser
2 //  Copyright (c) 2010 Sergey "GooRoo" Olendarenko
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 #include <boost/detail/lightweight_test.hpp>
8 #include <boost/config/warning_disable.hpp>
9 
10 #include <cstdlib>
11 #include <iostream>
12 #include <locale>
13 #include <string>
14 
15 #include <boost/spirit/include/lex_lexertl.hpp>
16 #include <boost/spirit/include/phoenix_object.hpp>
17 #include <boost/spirit/include/phoenix_operator.hpp>
18 #include <boost/spirit/include/phoenix_statement.hpp>
19 #include <boost/spirit/include/phoenix_container.hpp>
20 
21 namespace lex = boost::spirit::lex;
22 namespace phoenix = boost::phoenix;
23 
24 typedef std::basic_string<wchar_t> wstring_type;
25 
26 ///////////////////////////////////////////////////////////////////////////////
27 enum tokenids
28 {
29     ID_IDENT = 1,
30     ID_CONSTANT,
31     ID_OPERATION,
32     ID_BRACKET
33 };
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 struct test_data
37 {
38     int tokenid;
39     wstring_type value;
40 };
41 
42 // alpha+x1*(2.836-x2[i])
43 test_data data[] =
44 {
45     { ID_IDENT, L"alpha" },
46     { ID_OPERATION, L"+" },
47     { ID_IDENT, L"x1" },
48     { ID_OPERATION, L"*" },
49     { ID_BRACKET, L"(" },
50     { ID_CONSTANT, L"2.836" },
51     { ID_OPERATION, L"-" },
52     { ID_IDENT, L"x2" },
53     { ID_BRACKET, L"[" },
54     { ID_IDENT, L"i" },
55     { ID_BRACKET, L"]" },
56     { ID_BRACKET, L")" }
57 };
58 
59 ///////////////////////////////////////////////////////////////////////////////
60 struct test_impl
61 {
62     typedef void result_type;
63     template <typename TokenId, typename Value>
64     struct result { typedef void type; };
65 
66     template <typename TokenId, typename Value>
operator ()test_impl67     void operator()(TokenId const& tokenid, Value const& val) const
68     {
69         BOOST_TEST(sequence_counter < sizeof(data)/sizeof(data[0]));
70         BOOST_TEST(data[sequence_counter].tokenid == tokenid);
71         BOOST_TEST(0 == val.which());
72 
73         typedef boost::iterator_range<wstring_type::iterator> iterator_range;
74         iterator_range r = boost::get<iterator_range>(val);
75         BOOST_TEST(data[sequence_counter].value ==
76             wstring_type(r.begin(), r.end()));
77 
78         ++sequence_counter;
79     }
80 
81     static int sequence_counter;
82 };
83 int test_impl::sequence_counter = 0;
84 
85 phoenix::function<test_impl> const test = test_impl();
86 
87 ///////////////////////////////////////////////////////////////////////////////
88 template <typename Lexer>
89 struct mega_tokens : lex::lexer<Lexer>
90 {
mega_tokensmega_tokens91     mega_tokens()
92         : identifier(L"[a-zA-Z_][a-zA-Z0-9_]*", ID_IDENT)
93         , constant  (L"[0-9]+(\\.[0-9]+)?", ID_CONSTANT)
94         , operation (L"[\\+\\-\\*/]", ID_OPERATION)
95         , bracket   (L"[\\(\\)\\[\\]]", ID_BRACKET)
96     {
97         using lex::_tokenid;
98         using lex::_val;
99 
100         this->self
101             = operation  [ test(_tokenid, _val) ]
102             | identifier [ test(_tokenid, _val) ]
103             | constant   [ test(_tokenid, _val) ]
104             | bracket    [ test(_tokenid, _val) ]
105         ;
106     }
107 
108     lex::token_def<wchar_t, wchar_t> operation;
109     lex::token_def<wstring_type, wchar_t> identifier;
110     lex::token_def<double, wchar_t> constant;
111     lex::token_def<wchar_t, wchar_t> bracket;
112 };
113 
114 ///////////////////////////////////////////////////////////////////////////////
main()115 int main()
116 {
117     typedef wstring_type::iterator base_iterator;
118     typedef lex::lexertl::token<
119         base_iterator, boost::mpl::vector<wchar_t, wstring_type, double>
120     > token_type;
121     typedef lex::lexertl::actor_lexer<token_type> lexer_type;
122     typedef mega_tokens<lexer_type>::iterator_type iterator_type;
123 
124     mega_tokens<lexer_type> mega_lexer;
125 
126     wstring_type exampleStr = L"alpha+x1*(2.836-x2[i])";
127     base_iterator first = exampleStr.begin();
128 
129     BOOST_TEST(lex::tokenize(first, exampleStr.end(), mega_lexer));
130     BOOST_TEST(test_impl::sequence_counter == sizeof(data)/sizeof(data[0]));
131 
132     return boost::report_errors();
133 }
134