]>
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_STRING_TOKEN_DEF_MAR_28_2007_0722PM) | |
7 | #define BOOST_SPIRIT_LEX_STRING_TOKEN_DEF_MAR_28_2007_0722PM | |
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 | #include <boost/type_traits/add_const.hpp> | |
19 | #include <boost/type_traits/add_reference.hpp> | |
20 | #include <boost/type_traits/is_integral.hpp> | |
21 | #include <boost/type_traits/remove_const.hpp> | |
22 | #include <boost/fusion/include/vector.hpp> | |
23 | #include <boost/fusion/include/at.hpp> | |
24 | ||
25 | namespace boost { namespace spirit | |
26 | { | |
27 | /////////////////////////////////////////////////////////////////////////// | |
28 | // Enablers | |
29 | /////////////////////////////////////////////////////////////////////////// | |
30 | ||
31 | // enables strings | |
32 | template <typename T> | |
33 | struct use_terminal<lex::domain, T | |
34 | , typename enable_if<traits::is_string<T> >::type> | |
35 | : mpl::true_ {}; | |
36 | ||
37 | // enables string(str) | |
38 | template <typename CharEncoding, typename A0> | |
39 | struct use_terminal<lex::domain | |
40 | , terminal_ex< | |
41 | tag::char_code<tag::string, CharEncoding> | |
42 | , fusion::vector1<A0> > > | |
43 | : traits::is_string<A0> {}; | |
44 | ||
45 | // enables string(str, ID) | |
46 | template <typename CharEncoding, typename A0, typename A1> | |
47 | struct use_terminal<lex::domain | |
48 | , terminal_ex< | |
49 | tag::char_code<tag::string, CharEncoding> | |
50 | , fusion::vector2<A0, A1> > > | |
51 | : traits::is_string<A0> {}; | |
52 | }} | |
53 | ||
54 | namespace boost { namespace spirit { namespace lex | |
55 | { | |
56 | // use string from standard character set by default | |
57 | #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
58 | using spirit::standard::string; | |
59 | #endif | |
60 | using spirit::standard::string_type; | |
61 | ||
62 | /////////////////////////////////////////////////////////////////////////// | |
63 | // | |
64 | // string_token_def | |
65 | // represents a string based token definition | |
66 | // | |
67 | /////////////////////////////////////////////////////////////////////////// | |
68 | template <typename String, typename IdType = std::size_t | |
69 | , typename CharEncoding = char_encoding::standard> | |
70 | struct string_token_def | |
71 | : primitive_lexer<string_token_def<String, IdType, CharEncoding> > | |
72 | { | |
73 | typedef typename | |
74 | remove_const<typename traits::char_type_of<String>::type>::type | |
75 | char_type; | |
76 | typedef std::basic_string<char_type> string_type; | |
77 | ||
78 | string_token_def(typename add_reference<String>::type str, IdType const& id) | |
79 | : str_(str), id_(id), unique_id_(std::size_t(~0)) | |
80 | , token_state_(std::size_t(~0)) | |
81 | {} | |
82 | ||
83 | template <typename LexerDef, typename String_> | |
84 | void collect(LexerDef& lexdef, String_ const& state | |
85 | , String_ const& targetstate) const | |
86 | { | |
87 | std::size_t state_id = lexdef.add_state(state.c_str()); | |
88 | ||
89 | // If the following assertion fires you are probably trying to use | |
90 | // a single string_token_def instance in more than one lexer state. | |
91 | // This is not possible. Please create a separate token_def instance | |
92 | // from the same regular expression for each lexer state it needs | |
93 | // to be associated with. | |
94 | BOOST_ASSERT( | |
95 | (std::size_t(~0) == token_state_ || state_id == token_state_) && | |
96 | "Can't use single string_token_def with more than one lexer state"); | |
97 | ||
98 | char_type const* target = targetstate.empty() ? 0 : targetstate.c_str(); | |
99 | if (target) | |
100 | lexdef.add_state(target); | |
101 | ||
102 | token_state_ = state_id; | |
103 | ||
104 | if (IdType(~0) == id_) | |
105 | id_ = IdType(lexdef.get_next_id()); | |
106 | ||
107 | unique_id_ = lexdef.add_token (state.c_str(), str_, id_, target); | |
108 | } | |
109 | ||
110 | template <typename LexerDef> | |
111 | void add_actions(LexerDef&) const {} | |
112 | ||
113 | std::size_t id() const { return id_; } | |
114 | std::size_t unique_id() const { return unique_id_; } | |
115 | std::size_t state() const { return token_state_; } | |
116 | ||
117 | string_type str_; | |
118 | mutable IdType id_; | |
119 | mutable std::size_t unique_id_; | |
120 | mutable std::size_t token_state_; | |
121 | }; | |
122 | ||
123 | /////////////////////////////////////////////////////////////////////////// | |
124 | // Lex generators: make_xxx function (objects) | |
125 | /////////////////////////////////////////////////////////////////////////// | |
126 | template <typename T, typename Modifiers> | |
127 | struct make_primitive<T, Modifiers | |
128 | , typename enable_if<traits::is_string<T> >::type> | |
129 | { | |
130 | typedef typename add_const<T>::type const_string; | |
131 | typedef string_token_def<const_string> result_type; | |
132 | ||
133 | result_type operator()( | |
134 | typename add_reference<const_string>::type str, unused_type) const | |
135 | { | |
136 | return result_type(str, std::size_t(~0)); | |
137 | } | |
138 | }; | |
139 | ||
140 | template <typename Modifiers, typename CharEncoding, typename A0> | |
141 | struct make_primitive< | |
142 | terminal_ex< | |
143 | tag::char_code<tag::string, CharEncoding> | |
144 | , fusion::vector1<A0> > | |
145 | , Modifiers> | |
146 | { | |
147 | typedef typename add_const<A0>::type const_string; | |
148 | typedef string_token_def<const_string, std::size_t, CharEncoding> | |
149 | result_type; | |
150 | ||
151 | template <typename Terminal> | |
152 | result_type operator()(Terminal const& term, unused_type) const | |
153 | { | |
154 | return result_type(fusion::at_c<0>(term.args), std::size_t(~0)); | |
155 | } | |
156 | }; | |
157 | ||
158 | template <typename Modifiers, typename CharEncoding, typename A0, typename A1> | |
159 | struct make_primitive< | |
160 | terminal_ex< | |
161 | tag::char_code<tag::string, CharEncoding> | |
162 | , fusion::vector2<A0, A1> > | |
163 | , Modifiers> | |
164 | { | |
165 | typedef typename add_const<A0>::type const_string; | |
166 | typedef string_token_def<const_string, A1, CharEncoding> result_type; | |
167 | ||
168 | template <typename Terminal> | |
169 | result_type operator()(Terminal const& term, unused_type) const | |
170 | { | |
171 | return result_type( | |
172 | fusion::at_c<0>(term.args), fusion::at_c<1>(term.args)); | |
173 | } | |
174 | }; | |
175 | }}} // namespace boost::spirit::lex | |
176 | ||
177 | #endif |