]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/lex/lexer/support_functions.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / spirit / home / lex / lexer / support_functions.hpp
1 // Copyright (c) 2001-2011 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 #ifndef BOOST_SPIRIT_LEX_LEXER_SUPPORT_FUNCTIONS_HPP
7 #define BOOST_SPIRIT_LEX_LEXER_SUPPORT_FUNCTIONS_HPP
8
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12
13 #include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
14 #include <boost/spirit/home/lex/lexer/pass_flags.hpp>
15 #include <boost/spirit/home/lex/lexer/support_functions_expression.hpp>
16 #include <boost/phoenix/core/actor.hpp>
17 #include <boost/phoenix/core/as_actor.hpp>
18 #include <boost/phoenix/core/value.hpp> // includes as_actor specialization
19
20 ///////////////////////////////////////////////////////////////////////////////
21 namespace boost { namespace spirit { namespace lex
22 {
23 ///////////////////////////////////////////////////////////////////////////
24 // The function object less_type is used by the implementation of the
25 // support function lex::less(). Its functionality is equivalent to flex'
26 // function yyless(): it returns an iterator positioned to the nth input
27 // character beyond the current start iterator (i.e. by assigning the
28 // return value to the placeholder '_end' it is possible to return all but
29 // the first n characters of the current token back to the input stream.
30 //
31 // This Phoenix actor is invoked whenever the function lex::less(n) is
32 // used inside a lexer semantic action:
33 //
34 // lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
35 // this->self = identifier [ _end = lex::less(4) ];
36 //
37 // The example shows how to limit the length of the matched identifier to
38 // four characters.
39 //
40 // Note: the function lex::less() has no effect if used on it's own, you
41 // need to use the returned result in order to make use of its
42 // functionality.
43 template <typename Actor>
44 struct less_type
45 {
46 typedef mpl::true_ no_nullary;
47
48 template <typename Env>
49 struct result
50 {
51 typedef typename remove_reference<
52 typename remove_const<
53 typename mpl::at_c<typename Env::args_type, 4>::type
54 >::type
55 >::type context_type;
56 typedef typename context_type::base_iterator_type type;
57 };
58
59 template <typename Env>
60 typename result<Env>::type
61 eval(Env const& env) const
62 {
63 typename result<Env>::type it;
64 return fusion::at_c<4>(env.args()).less(it, actor_());
65 }
66
67 less_type(Actor const& actor)
68 : actor_(actor) {}
69
70 Actor actor_;
71 };
72
73 // The function lex::less() is used to create a Phoenix actor allowing to
74 // implement functionality similar to flex' function yyless().
75 template <typename T>
76 inline typename expression::less<
77 typename phoenix::as_actor<T>::type
78 >::type const
79 less(T const& v)
80 {
81 return expression::less<T>::make(phoenix::as_actor<T>::convert(v));
82 }
83
84 ///////////////////////////////////////////////////////////////////////////
85 // The function object more_type is used by the implementation of the
86 // support function lex::more(). Its functionality is equivalent to flex'
87 // function yymore(): it tells the lexer that the next time it matches a
88 // rule, the corresponding token should be appended onto the current token
89 // value rather than replacing it.
90 //
91 // This Phoenix actor is invoked whenever the function lex::more(n) is
92 // used inside a lexer semantic action:
93 //
94 // lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
95 // this->self = identifier [ lex::more() ];
96 //
97 // The example shows how prefix the next matched token with the matched
98 // identifier.
99 struct more_type
100 {
101 typedef mpl::true_ no_nullary;
102
103 template <typename Env>
104 struct result
105 {
106 typedef void type;
107 };
108
109 template <typename Env>
110 void eval(Env const& env) const
111 {
112 fusion::at_c<4>(env.args()).more();
113 }
114 };
115
116 // The function lex::more() is used to create a Phoenix actor allowing to
117 // implement functionality similar to flex' function yymore().
118 //inline expression::more<mpl::void_>::type const
119 inline phoenix::actor<more_type> more()
120 {
121 return phoenix::actor<more_type>();
122 }
123
124 ///////////////////////////////////////////////////////////////////////////
125 // The function object lookahead_type is used by the implementation of the
126 // support function lex::lookahead(). Its functionality is needed to
127 // emulate the flex' lookahead operator a/b. Use lex::lookahead() inside
128 // of lexer semantic actions to test whether the argument to this function
129 // matches the current look ahead input. lex::lookahead() can be used with
130 // either a token id or a token_def instance as its argument. It returns
131 // a bool indicating whether the look ahead has been matched.
132 template <typename IdActor, typename StateActor>
133 struct lookahead_type
134 {
135 typedef mpl::true_ no_nullary;
136
137 template <typename Env>
138 struct result
139 {
140 typedef bool type;
141 };
142
143 template <typename Env>
144 bool eval(Env const& env) const
145 {
146 return fusion::at_c<4>(env.args()).
147 lookahead(id_actor_(), state_actor_());
148 }
149
150 lookahead_type(IdActor const& id_actor, StateActor const& state_actor)
151 : id_actor_(id_actor), state_actor_(state_actor) {}
152
153 IdActor id_actor_;
154 StateActor state_actor_;
155 };
156
157 // The function lex::lookahead() is used to create a Phoenix actor
158 // allowing to implement functionality similar to flex' lookahead operator
159 // a/b.
160 template <typename T>
161 inline typename expression::lookahead<
162 typename phoenix::as_actor<T>::type
163 , typename phoenix::as_actor<std::size_t>::type
164 >::type const
165 lookahead(T const& id)
166 {
167 typedef typename phoenix::as_actor<T>::type id_actor_type;
168 typedef typename phoenix::as_actor<std::size_t>::type state_actor_type;
169
170 return expression::lookahead<id_actor_type, state_actor_type>::make(
171 phoenix::as_actor<T>::convert(id),
172 phoenix::as_actor<std::size_t>::convert(std::size_t(~0)));
173 }
174
175 template <typename Attribute, typename Char, typename Idtype>
176 inline typename expression::lookahead<
177 typename phoenix::as_actor<Idtype>::type
178 , typename phoenix::as_actor<std::size_t>::type
179 >::type const
180 lookahead(token_def<Attribute, Char, Idtype> const& tok)
181 {
182 typedef typename phoenix::as_actor<Idtype>::type id_actor_type;
183 typedef typename phoenix::as_actor<std::size_t>::type state_actor_type;
184
185 std::size_t state = tok.state();
186
187 // The following assertion fires if you pass a token_def instance to
188 // lex::lookahead without first associating this instance with the
189 // lexer.
190 BOOST_ASSERT(std::size_t(~0) != state &&
191 "token_def instance not associated with lexer yet");
192
193 return expression::lookahead<id_actor_type, state_actor_type>::make(
194 phoenix::as_actor<Idtype>::convert(tok.id()),
195 phoenix::as_actor<std::size_t>::convert(state));
196 }
197
198 ///////////////////////////////////////////////////////////////////////////
199 inline BOOST_SCOPED_ENUM(pass_flags) ignore()
200 {
201 return pass_flags::pass_ignore;
202 }
203
204 }}}
205
206 #endif