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 char_token_defboost::spirit::lex::char_token_def83 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> collectboost::spirit::lex::char_token_def89 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> add_actionsboost::spirit::lex::char_token_def112 void add_actions(LexerDef&) const {} 113 idboost::spirit::lex::char_token_def114 IdType id() const { return id_; } unique_idboost::spirit::lex::char_token_def115 std::size_t unique_id() const { return unique_id_; } stateboost::spirit::lex::char_token_def116 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> operator ()boost::spirit::lex::detail::basic_literal135 result_type operator()(Char ch, unused_type) const 136 { 137 return result_type(ch, ch); 138 } 139 140 template <typename Char> operator ()boost::spirit::lex::detail::basic_literal141 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> operator ()boost::spirit::lex::make_primitive178 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> operator ()boost::spirit::lex::make_primitive196 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> operator ()boost::spirit::lex::make_primitive215 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> operator ()boost::spirit::lex::make_primitive234 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 243