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