| /*============================================================================= |
| Copyright (c) 2001-2007 Joel de Guzman |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| ==============================================================================*/ |
| #if !defined(BOOST_SPIRIT_CHAR_APR_16_2006_1051AM) |
| #define BOOST_SPIRIT_CHAR_APR_16_2006_1051AM |
| |
| #include <boost/spirit/home/qi/char/char_parser.hpp> |
| #include <boost/spirit/home/qi/char/detail/get_char.hpp> |
| #include <boost/spirit/home/qi/domain.hpp> |
| #include <boost/fusion/include/at.hpp> |
| #include <boost/fusion/include/value_at.hpp> |
| #include <boost/fusion/include/vector.hpp> |
| #include <boost/spirit/home/support/modifier.hpp> |
| #include <boost/spirit/home/support/char_class.hpp> |
| #include <boost/spirit/home/support/detail/to_narrow.hpp> |
| #include <boost/utility/enable_if.hpp> |
| #include <boost/type_traits/remove_reference.hpp> |
| #include <boost/foreach.hpp> |
| #include <boost/mpl/print.hpp> |
| |
| namespace boost { namespace spirit { namespace qi |
| { |
| /////////////////////////////////////////////////////////////////////////// |
| // parse any character |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Char> |
| struct any_char : char_parser<any_char<Char>, Char> |
| { |
| template <typename Component, typename CharParam, typename Context> |
| static bool test(Component const&, CharParam, Context&) |
| { |
| return true; |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| return "any-char"; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // parse a single character |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Char> |
| struct literal_char : char_parser<literal_char<Char>, Char> |
| { |
| template <typename Component, typename Context, typename Iterator> |
| struct attribute |
| { |
| typedef unused_type type; // literal parsers have no attribute |
| }; |
| |
| template <typename Component, typename CharParam, typename Context> |
| static bool test(Component const& component, CharParam ch, Context&) |
| { |
| return detail::get_char(fusion::at_c<0>(component.elements)) == ch; |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| return std::string("'") |
| + spirit::detail::to_narrow_char( |
| detail::get_char(fusion::at_c<0>(component.elements))) |
| + '\''; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // parse a character set |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Char> |
| struct char_set : char_parser<char_set<Char>, Char> |
| { |
| template <typename Component, typename CharParam, typename Context> |
| static bool test(Component const& component, CharParam ch, Context&) |
| { |
| return component.ptr->test(ch); |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| return "char-set"; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // parse a lazy character |
| /////////////////////////////////////////////////////////////////////////// |
| struct lazy_char : char_parser<lazy_char> |
| { |
| template <typename Component, typename Context, typename Iterator> |
| struct attribute |
| { |
| typedef typename |
| result_of::subject<Component>::type |
| subject_type; |
| |
| typedef typename |
| remove_reference< |
| typename boost::result_of<subject_type(unused_type, Context)>::type |
| >::type |
| type; |
| }; |
| |
| template <typename Component, typename CharParam, typename Context> |
| static bool test(Component const& component, CharParam ch, Context& context) |
| { |
| return fusion::at_c<0>(component.elements)(unused, context) == ch; |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| return std::string("'") |
| + spirit::detail::to_narrow_char( |
| fusion::at_c<0>(component.elements)(unused, ctx)) |
| + '\''; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // parse a character range |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Char> |
| struct char_range : char_parser<char_range<Char>, Char> |
| { |
| template <typename Component, typename CharParam, typename Context> |
| static bool test(Component const& component, CharParam ch, Context&) |
| { |
| return |
| !(ch < fusion::at_c<0>(component.elements)) && |
| !(fusion::at_c<1>(component.elements) < ch); |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| std::string result; |
| result += std::string("'") + fusion::at_c<0>(component.elements) + '\''; |
| result += "..."; |
| result += std::string("'") + fusion::at_c<1>(component.elements) + '\''; |
| return result; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // parse a lazy character range |
| /////////////////////////////////////////////////////////////////////////// |
| struct lazy_char_range : char_parser<lazy_char_range> |
| { |
| template <typename Component, typename Context, typename Iterator> |
| struct attribute |
| { |
| typedef typename |
| result_of::subject<Component>::type |
| subject_type; |
| |
| typedef typename |
| remove_reference< |
| typename boost::result_of<subject_type(unused_type, Context)>::type |
| >::type |
| type; |
| }; |
| |
| template <typename Component, typename CharParam, typename Context> |
| static bool test(Component const& component, CharParam ch, Context& context) |
| { |
| return |
| !(ch < fusion::at_c<0>(component.elements)(unused, context)) && |
| !(fusion::at_c<1>(component.elements)(unused, context) < ch); |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| return "char-range"; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // no_case literal_char version |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Char> |
| struct no_case_literal_char : char_parser<no_case_literal_char<Char>, Char> |
| { |
| template <typename Component, typename Context, typename Iterator> |
| struct attribute |
| { |
| typedef unused_type type; // literal parsers have no attribute |
| }; |
| |
| template <typename Component, typename CharParam, typename Context> |
| static bool test(Component const& component, CharParam ch, Context&) |
| { |
| return detail::get_char(fusion::at_c<0>(component.elements)) == ch |
| || detail::get_char(fusion::at_c<1>(component.elements)) == ch |
| ; |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| std::string result; |
| result += std::string("'") |
| + spirit::detail::to_narrow_char( |
| detail::get_char(fusion::at_c<0>(component.elements))) + '\''; |
| result += " or "; |
| result += std::string("'") + |
| spirit::detail::to_narrow_char( |
| detail::get_char(fusion::at_c<1>(component.elements))) + '\''; |
| return result; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // no_case char_range version |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Char> |
| struct no_case_char_range : char_parser<no_case_char_range<Char>, Char> |
| { |
| template <typename Component, typename CharParam, typename Context> |
| static bool test(Component const& component, CharParam ch, Context&) |
| { |
| return |
| (!(ch < fusion::at_c<0>(component.elements)) && |
| !(fusion::at_c<1>(component.elements) < ch)) |
| || (!(ch < fusion::at_c<2>(component.elements)) && |
| !(fusion::at_c<3>(component.elements) < ch)) |
| ; |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| std::string result; |
| result += std::string("'") + fusion::at_c<0>(component.elements) + '\''; |
| result += "..."; |
| result += std::string("'") + fusion::at_c<1>(component.elements) + '\''; |
| result += " or "; |
| result += std::string("'") + fusion::at_c<2>(component.elements) + '\''; |
| result += "..."; |
| result += std::string("'") + fusion::at_c<3>(component.elements) + '\''; |
| return result; |
| } |
| }; |
| |
| template <typename Char, typename Elements> |
| struct char_set_component; |
| }}} |
| |
| namespace boost { namespace spirit { namespace traits |
| { |
| /////////////////////////////////////////////////////////////////////////// |
| // char_set_component generator |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Char, typename Elements, typename Modifier> |
| struct make_component<qi::domain, qi::char_set<Char>, Elements, Modifier |
| , typename disable_if< |
| is_member_of_modifier<Modifier, spirit::char_class::no_case_base_tag> |
| >::type |
| > : mpl::identity<qi::char_set_component<Char, Elements> > |
| { |
| static qi::char_set_component<Char, Elements> |
| call(Elements const& elements) |
| { |
| return qi::char_set_component<Char, Elements>( |
| fusion::at_c<0>(elements)); |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // no_case char_set_component generator |
| /////////////////////////////////////////////////////////////////////////// |
| template < |
| typename Domain, typename Elements, typename Modifier, typename Char |
| > |
| struct make_modified_component< |
| Domain, qi::char_set<Char>, Elements, Modifier |
| , typename enable_if< |
| is_member_of_modifier<Modifier, spirit::char_class::no_case_base_tag> |
| >::type |
| > |
| { |
| typedef qi::char_set_component<Char, Elements> type; |
| typedef typename Modifier::char_set char_set; |
| |
| static type |
| call(Elements const& elements) |
| { |
| return qi::char_set_component<Char, Elements>( |
| fusion::at_c<0>(elements), char_set()); |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // no_case_literal_char generator |
| /////////////////////////////////////////////////////////////////////////// |
| template < |
| typename Domain, typename Elements, typename Modifier, typename Char |
| > |
| struct make_modified_component< |
| Domain, qi::literal_char<Char>, Elements, Modifier |
| , typename enable_if< |
| is_member_of_modifier<Modifier, spirit::char_class::no_case_base_tag> |
| >::type |
| > |
| { |
| typedef fusion::vector<Char, Char> vector_type; |
| typedef |
| component<qi::domain, qi::no_case_literal_char<Char>, vector_type> |
| type; |
| |
| static type |
| call(Elements const& elements) |
| { |
| typedef typename Modifier::char_set char_set; |
| |
| Char ch = qi::detail::get_char(fusion::at_c<0>(elements)); |
| vector_type v( |
| char_set::tolower(ch) |
| , char_set::toupper(ch) |
| ); |
| return type(v); |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // no_case_char_range generator |
| /////////////////////////////////////////////////////////////////////////// |
| template < |
| typename Domain, typename Elements, typename Modifier, typename Char |
| > |
| struct make_modified_component< |
| Domain, qi::char_range<Char>, Elements, Modifier |
| , typename enable_if< |
| is_member_of_modifier<Modifier, spirit::char_class::no_case_base_tag> |
| >::type |
| > |
| { |
| typedef fusion::vector<Char, Char, Char, Char> vector_type; |
| typedef |
| component<qi::domain, qi::no_case_char_range<Char>, vector_type> |
| type; |
| |
| static type |
| call(Elements const& elements) |
| { |
| typedef typename Modifier::char_set char_set; |
| |
| Char first = fusion::at_c<0>(elements); |
| Char last = fusion::at_c<1>(elements); |
| vector_type v( |
| char_set::tolower(first) |
| , char_set::tolower(last) |
| , char_set::toupper(first) |
| , char_set::toupper(last) |
| ); |
| return type(v); |
| } |
| }; |
| }}} |
| |
| #endif |