]>
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(BOOST_SPIRIT_LEX_CHAR_TOKEN_DEF_MAR_28_2007_0626PM) | |
7 | #define BOOST_SPIRIT_LEX_CHAR_TOKEN_DEF_MAR_28_2007_0626PM | |
8 | ||
9 | #if defined(_MSC_VER) | |
10 | #pragma once | |
11 | #endif | |
12 | ||
13 | #include <boost/spirit/home/support/common_terminals.hpp> | |
14 | #include <boost/spirit/home/support/string_traits.hpp> | |
15 | #include <boost/spirit/home/lex/domain.hpp> | |
16 | #include <boost/spirit/home/lex/lexer_type.hpp> | |
17 | #include <boost/spirit/home/lex/meta_compiler.hpp> | |
18 | ||
19 | namespace boost { namespace spirit | |
20 | { | |
21 | /////////////////////////////////////////////////////////////////////////// | |
22 | // Enablers | |
23 | /////////////////////////////////////////////////////////////////////////// | |
24 | ||
25 | // enables 'x' | |
26 | template <> | |
27 | struct use_terminal<lex::domain, char> | |
28 | : mpl::true_ {}; | |
29 | ||
30 | // enables "x" | |
31 | template <> | |
32 | struct use_terminal<lex::domain, char[2]> | |
33 | : mpl::true_ {}; | |
34 | ||
35 | // enables wchar_t | |
36 | template <> | |
37 | struct use_terminal<lex::domain, wchar_t> | |
38 | : mpl::true_ {}; | |
39 | ||
40 | // enables L"x" | |
41 | template <> | |
42 | struct use_terminal<lex::domain, wchar_t[2]> | |
43 | : mpl::true_ {}; | |
44 | ||
45 | // enables char_('x'), char_("x") | |
46 | template <typename CharEncoding, typename A0> | |
47 | struct use_terminal<lex::domain | |
48 | , terminal_ex< | |
49 | tag::char_code<tag::char_, CharEncoding> | |
50 | , fusion::vector1<A0> > > | |
51 | : mpl::true_ {}; | |
52 | ||
53 | // enables char_('x', ID), char_("x", ID) | |
54 | template <typename CharEncoding, typename A0, typename A1> | |
55 | struct use_terminal<lex::domain | |
56 | , terminal_ex< | |
57 | tag::char_code<tag::char_, CharEncoding> | |
58 | , fusion::vector2<A0, A1> > > | |
59 | : mpl::true_ {}; | |
60 | }} | |
61 | ||
62 | namespace boost { namespace spirit { namespace lex | |
63 | { | |
64 | // use char_ from standard character set by default | |
65 | #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
66 | using spirit::standard::char_; | |
67 | #endif | |
68 | using spirit::standard::char_type; | |
69 | ||
70 | /////////////////////////////////////////////////////////////////////////// | |
71 | // | |
72 | // char_token_def | |
73 | // represents a single character token definition | |
74 | // | |
75 | /////////////////////////////////////////////////////////////////////////// | |
76 | template <typename CharEncoding = char_encoding::standard | |
77 | , typename IdType = std::size_t> | |
78 | struct char_token_def | |
79 | : primitive_lexer<char_token_def<CharEncoding, IdType> > | |
80 | { | |
81 | typedef typename CharEncoding::char_type char_type; | |
82 | ||
83 | char_token_def(char_type ch, IdType const& id) | |
84 | : ch(ch), id_(id), unique_id_(std::size_t(~0)) | |
85 | , token_state_(std::size_t(~0)) | |
86 | {} | |
87 | ||
88 | template <typename LexerDef, typename String> | |
89 | void collect(LexerDef& lexdef, String const& state | |
90 | , String const& targetstate) const | |
91 | { | |
92 | std::size_t state_id = lexdef.add_state(state.c_str()); | |
93 | ||
94 | // If the following assertion fires you are probably trying to use | |
95 | // a single char_token_def instance in more than one lexer state. | |
96 | // This is not possible. Please create a separate token_def instance | |
97 | // from the same regular expression for each lexer state it needs | |
98 | // to be associated with. | |
99 | BOOST_ASSERT( | |
100 | (std::size_t(~0) == token_state_ || state_id == token_state_) && | |
101 | "Can't use single char_token_def with more than one lexer state"); | |
102 | ||
103 | char_type const* target = targetstate.empty() ? 0 : targetstate.c_str(); | |
104 | if (target) | |
105 | lexdef.add_state(target); | |
106 | ||
107 | token_state_ = state_id; | |
108 | unique_id_ = lexdef.add_token (state.c_str(), ch, id_, target); | |
109 | } | |
110 | ||
111 | template <typename LexerDef> | |
112 | void add_actions(LexerDef&) const {} | |
113 | ||
114 | IdType id() const { return id_; } | |
115 | std::size_t unique_id() const { return unique_id_; } | |
116 | std::size_t state() const { return token_state_; } | |
117 | ||
118 | char_type ch; | |
119 | mutable IdType id_; | |
120 | mutable std::size_t unique_id_; | |
121 | mutable std::size_t token_state_; | |
122 | }; | |
123 | ||
124 | /////////////////////////////////////////////////////////////////////////// | |
125 | // Lexer generators: make_xxx function (objects) | |
126 | /////////////////////////////////////////////////////////////////////////// | |
127 | namespace detail | |
128 | { | |
129 | template <typename CharEncoding> | |
130 | struct basic_literal | |
131 | { | |
132 | typedef char_token_def<CharEncoding> result_type; | |
133 | ||
134 | template <typename Char> | |
135 | result_type operator()(Char ch, unused_type) const | |
136 | { | |
137 | return result_type(ch, ch); | |
138 | } | |
139 | ||
140 | template <typename Char> | |
141 | result_type operator()(Char const* str, unused_type) const | |
142 | { | |
143 | return result_type(str[0], str[0]); | |
144 | } | |
145 | }; | |
146 | } | |
147 | ||
148 | // literals: 'x', "x" | |
149 | template <typename Modifiers> | |
150 | struct make_primitive<char, Modifiers> | |
151 | : detail::basic_literal<char_encoding::standard> {}; | |
152 | ||
153 | template <typename Modifiers> | |
154 | struct make_primitive<char const(&)[2], Modifiers> | |
155 | : detail::basic_literal<char_encoding::standard> {}; | |
156 | ||
157 | // literals: L'x', L"x" | |
158 | template <typename Modifiers> | |
159 | struct make_primitive<wchar_t, Modifiers> | |
160 | : detail::basic_literal<char_encoding::standard_wide> {}; | |
161 | ||
162 | template <typename Modifiers> | |
163 | struct make_primitive<wchar_t const(&)[2], Modifiers> | |
164 | : detail::basic_literal<char_encoding::standard_wide> {}; | |
165 | ||
166 | // handle char_('x') | |
167 | template <typename CharEncoding, typename Modifiers, typename A0> | |
168 | struct make_primitive< | |
169 | terminal_ex< | |
170 | tag::char_code<tag::char_, CharEncoding> | |
171 | , fusion::vector1<A0> | |
172 | > | |
173 | , Modifiers> | |
174 | { | |
175 | typedef char_token_def<CharEncoding> result_type; | |
176 | ||
177 | template <typename Terminal> | |
178 | result_type operator()(Terminal const& term, unused_type) const | |
179 | { | |
180 | return result_type(fusion::at_c<0>(term.args), fusion::at_c<0>(term.args)); | |
181 | } | |
182 | }; | |
183 | ||
184 | // handle char_("x") | |
185 | template <typename CharEncoding, typename Modifiers, typename Char> | |
186 | struct make_primitive< | |
187 | terminal_ex< | |
188 | tag::char_code<tag::char_, CharEncoding> | |
189 | , fusion::vector1<Char(&)[2]> // single char strings | |
190 | > | |
191 | , Modifiers> | |
192 | { | |
193 | typedef char_token_def<CharEncoding> result_type; | |
194 | ||
195 | template <typename Terminal> | |
196 | result_type operator()(Terminal const& term, unused_type) const | |
197 | { | |
198 | Char ch = fusion::at_c<0>(term.args)[0]; | |
199 | return result_type(ch, ch); | |
200 | } | |
201 | }; | |
202 | ||
203 | // handle char_('x', ID) | |
204 | template <typename CharEncoding, typename Modifiers, typename A0, typename A1> | |
205 | struct make_primitive< | |
206 | terminal_ex< | |
207 | tag::char_code<tag::char_, CharEncoding> | |
208 | , fusion::vector2<A0, A1> | |
209 | > | |
210 | , Modifiers> | |
211 | { | |
212 | typedef char_token_def<CharEncoding> result_type; | |
213 | ||
214 | template <typename Terminal> | |
215 | result_type operator()(Terminal const& term, unused_type) const | |
216 | { | |
217 | return result_type( | |
218 | fusion::at_c<0>(term.args), fusion::at_c<1>(term.args)); | |
219 | } | |
220 | }; | |
221 | ||
222 | // handle char_("x", ID) | |
223 | template <typename CharEncoding, typename Modifiers, typename Char, typename A1> | |
224 | struct make_primitive< | |
225 | terminal_ex< | |
226 | tag::char_code<tag::char_, CharEncoding> | |
227 | , fusion::vector2<Char(&)[2], A1> // single char strings | |
228 | > | |
229 | , Modifiers> | |
230 | { | |
231 | typedef char_token_def<CharEncoding> result_type; | |
232 | ||
233 | template <typename Terminal> | |
234 | result_type operator()(Terminal const& term, unused_type) const | |
235 | { | |
236 | return result_type( | |
237 | fusion::at_c<0>(term.args)[0], fusion::at_c<1>(term.args)); | |
238 | } | |
239 | }; | |
240 | }}} // namespace boost::spirit::lex | |
241 | ||
242 | #endif |