|
Boost-Commit : |
From: joel_at_[hidden]
Date: 2008-04-17 05:01:52
Author: djowel
Date: 2008-04-17 05:01:51 EDT (Thu, 17 Apr 2008)
New Revision: 44491
URL: http://svn.boost.org/trac/boost/changeset/44491
Log:
char-sets
Added:
trunk/boost/spirit/home/qi/char/detail/basic_chset.hpp (contents, props changed)
Text files modified:
trunk/boost/spirit/home/qi/char/char.hpp | 37 +++++++++++
trunk/boost/spirit/home/qi/char/meta_grammar.hpp | 123 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 154 insertions(+), 6 deletions(-)
Modified: trunk/boost/spirit/home/qi/char/char.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/char/char.hpp (original)
+++ trunk/boost/spirit/home/qi/char/char.hpp 2008-04-17 05:01:51 EDT (Thu, 17 Apr 2008)
@@ -51,10 +51,24 @@
typedef unused_type type; // literal parsers have no attribute
};
+ template <typename Char_, typename CharParam>
+ static bool test_impl(Char_ ch, CharParam param)
+ {
+ // tests plain chars
+ return ch == param;
+ }
+
+ template <typename Char_, typename CharParam>
+ static bool test_impl(Char_ const* ch, CharParam param)
+ {
+ // tests single char null terminated strings
+ return *ch == param;
+ }
+
template <typename Component, typename CharParam, typename Context>
static bool test(Component const& component, CharParam ch, Context&)
{
- return fusion::at_c<0>(component.elements) == ch;
+ return test_impl(fusion::at_c<0>(component.elements), ch);
}
template <typename Component>
@@ -62,12 +76,31 @@
{
return std::string("'")
+ spirit::detail::to_narrow_char(
- fusion::at_c<0>(component.elements))
+ 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>
+ static std::string what(Component const&)
+ {
+ return "char-set";
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
// parse a lazy character
///////////////////////////////////////////////////////////////////////////
struct lazy_char : char_parser<lazy_char>
Added: trunk/boost/spirit/home/qi/char/detail/basic_chset.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/qi/char/detail/basic_chset.hpp 2008-04-17 05:01:51 EDT (Thu, 17 Apr 2008)
@@ -0,0 +1,244 @@
+/*=============================================================================
+ Copyright (c) 2001-2008 Joel de Guzman
+ Copyright (c) 2001-2003 Daniel Nuffer
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+#ifndef BOOST_SPIRIT_BASIC_CHSET_APRIL_17_2008
+#define BOOST_SPIRIT_BASIC_CHSET_APRIL_17_2008
+
+///////////////////////////////////////////////////////////////////////////////
+#include <bitset>
+#include <boost/spirit/home/qi/char/detail/range_run.hpp>
+
+namespace boost { namespace spirit { namespace qi { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // basic_chset: basic character set implementation using range_run
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Char>
+ struct basic_chset
+ {
+ basic_chset() {}
+ basic_chset(basic_chset const& arg_)
+ : rr(arg_.rr) {}
+
+ bool
+ test(Char v) const
+ {
+ return rr.test(v);
+ }
+
+ void
+ set(Char from, Char to)
+ {
+ rr.set(range<Char>(from, to));
+ }
+
+ void
+ set(Char c)
+ {
+ rr.set(range<Char>(c, c));
+ }
+
+ void
+ clear(Char from, Char to)
+ {
+ rr.set(range<Char>(c, c));
+ }
+
+ void
+ clear(Char c)
+ {
+ rr.clear(range<Char>(from, to));
+ }
+
+ void
+ clear()
+ {
+ rr.clear();
+ }
+
+ void
+ inverse()
+ {
+ basic_chset inv;
+ inv.set(
+ (std::numeric_limits<Char>::min)(),
+ (std::numeric_limits<Char>::max)()
+ );
+ inv -= *this;
+ swap(inv);
+ }
+
+ void
+ swap(basic_chset& x)
+ {
+ rr.swap(x.rr);
+ }
+
+
+ basic_chset&
+ operator|=(basic_chset const& x)
+ {
+ typedef typename range_run<Char>::const_iterator const_iterator;
+ for (const_iterator iter = x.rr.begin(); iter != x.rr.end(); ++iter)
+ rr.set(*iter);
+ return *this;
+ }
+
+ basic_chset&
+ operator&=(basic_chset const& x)
+ {
+ basic_chset inv;
+ inv.set(
+ (std::numeric_limits<Char>::min)(),
+ (std::numeric_limits<Char>::max)()
+ );
+ inv -= x;
+ *this -= inv;
+ return *this;
+ }
+
+ basic_chset&
+ operator-=(basic_chset const& x)
+ {
+ typedef typename range_run<Char>::const_iterator const_iterator;
+ for (const_iterator iter = x.rr.begin(); iter != x.rr.end(); ++iter)
+ rr.clear(*iter);
+ return *this;
+ }
+
+ basic_chset&
+ operator^=(basic_chset const& x)
+ {
+ basic_chset bma = x;
+ bma -= *this;
+ *this -= x;
+ *this |= bma;
+ return *this;
+ }
+
+ private: range_run<Char> rr;
+ };
+
+#if (CHAR_BIT == 8)
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // basic_chset: specializations for 8 bit chars using std::bitset
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Char>
+ struct basic_chset_8bit
+ {
+ basic_chset_8bit() {}
+ basic_chset_8bit(basic_chset_8bit const& arg_)
+ : bset(arg_.bset) {}
+
+ bool
+ test(Char v) const
+ {
+ return bset.test((unsigned char)v);
+ }
+
+ void
+ set(Char from, Char to)
+ {
+ for (int i = from; i <= to; ++i)
+ bset.set((unsigned char)i);
+ }
+
+ void
+ set(Char c)
+ {
+ bset.set((unsigned char)c);
+ }
+
+ void
+ clear(Char from, Char to)
+ {
+ for (int i = from; i <= to; ++i)
+ bset.reset((unsigned char)i);
+ }
+
+ void
+ clear(Char c)
+ {
+ bset.reset((unsigned char)c);
+ }
+
+ void
+ clear()
+ {
+ bset.reset();
+ }
+
+ void
+ inverse()
+ {
+ bset.flip();
+ }
+
+ void
+ swap(basic_chset_8bit& x)
+ {
+ std::swap(bset, x.bset);
+ }
+
+ basic_chset_8bit&
+ operator|=(basic_chset_8bit const& x)
+ {
+ bset |= x.bset;
+ return *this;
+ }
+
+ basic_chset_8bit&
+ operator&=(basic_chset_8bit const& x)
+ {
+ bset &= x.bset;
+ return *this;
+ }
+
+ basic_chset_8bit&
+ operator-=(basic_chset_8bit const& x)
+ {
+ bset &= ~x.bset;
+ return *this;
+ }
+
+ basic_chset_8bit&
+ operator^=(basic_chset_8bit const& x)
+ {
+ bset ^= x.bset;
+ return *this;
+ }
+
+ private: std::bitset<256> bset;
+ };
+
+ /////////////////////////////////
+ template <>
+ struct basic_chset<char>
+ : basic_chset_8bit<char> {};
+
+ /////////////////////////////////
+ template <>
+ struct basic_chset<signed char>
+ : basic_chset_8bit<signed char> {};
+
+ /////////////////////////////////
+ template <>
+ struct basic_chset<unsigned char>
+ : basic_chset_8bit<unsigned char> {};
+
+#endif // #if (CHAR_BIT == 8)
+
+}}}}
+
+#endif
+
Modified: trunk/boost/spirit/home/qi/char/meta_grammar.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/char/meta_grammar.hpp (original)
+++ trunk/boost/spirit/home/qi/char/meta_grammar.hpp 2008-04-17 05:01:51 EDT (Thu, 17 Apr 2008)
@@ -11,8 +11,34 @@
#include <boost/spirit/home/support/placeholders.hpp>
#include <boost/spirit/home/support/meta_grammar.hpp>
#include <boost/spirit/home/support/char_class.hpp>
+#include <boost/spirit/home/qi/char/detail/basic_chset.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace boost { namespace spirit { namespace qi
+{
+ template <typename Char>
+ struct char_set;
+
+ template <typename Char, typename Elements>
+ struct char_set_component;
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ template <typename Char, typename Elements, typename Modifier>
+ struct make_component<qi::domain, qi::char_set<Char>, Elements, Modifier>
+ : 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));
+ }
+ };
+}}}
namespace boost { namespace spirit { namespace qi
{
@@ -126,6 +152,22 @@
{
};
+
+ // literals: 'x', L'x' and single char strings: "x", L"x"
+ struct single_char_literal_meta_grammar
+ : proto::or_<
+ // plain chars:
+ proto::terminal<char>
+ , proto::terminal<wchar_t>
+ // single char null terminates strings:
+ , proto::terminal<char[2]>
+ , proto::terminal<char(&)[2]>
+ , proto::terminal<wchar_t[2]>
+ , proto::terminal<wchar_t(&)[2]>
+ >
+ {
+ };
+
// literals: 'x', L'x'
struct char_literal_meta_grammar
: proto::or_<
@@ -139,10 +181,73 @@
{
};
- // char_, char_('x'), char_(f), char_('x', 'z'),
+ // literal strings: "hello" (defined in qi/string/meta_grammar.hpp)
+ struct basic_string_literal_meta_grammar;
+
+ // std::string(s) (defined in qi/string/meta_grammar.hpp)
+ struct basic_std_string_meta_grammar;
+
+ template <typename T>
+ struct extract_char; // (defined in qi/string/metagrammar.hpp)
+
+ template <typename Tag, typename T>
+ struct extract_chset_director;
+
+ template <typename T>
+ struct extract_chset_director<tag::char_, T>
+ {
+ typedef typename extract_char<T>::type char_type;
+ typedef char_set<char_type> type;
+ };
+
+ template <typename T>
+ struct extract_chset_director<tag::wchar, T>
+ {
+ typedef typename extract_char<T>::type char_type;
+ typedef char_set<char_type> type;
+ };
+
+ template <typename Char, typename Elements>
+ struct char_set_component
+ {
+ typedef qi::domain domain;
+ typedef char_set<Char> director;
+ typedef Elements elements_type;
+
+ char_set_component(Char const* definition)
+ : ptr(new detail::basic_chset<Char>())
+ {
+ Char ch = *definition++;
+ while (ch)
+ {
+ Char next = *definition++;
+ if (next == '-')
+ {
+ next = *definition++;
+ if (next == 0)
+ {
+ ptr->set(ch);
+ ptr->set('-');
+ break;
+ }
+ ptr->set(ch, next);
+ }
+ else
+ {
+ ptr->set(ch);
+ }
+ ch = next;
+ }
+ }
+
+ boost::shared_ptr<detail::basic_chset<Char> > ptr;
+ };
+
+ // char_, char_('x'), char_("x"), char_(f), char_('x', 'z'),
// char_(L'x'), char_(L'x', L'z'),
- // wchar, wchar('x'), wchar('x', 'z'),
+ // wchar, wchar('x'), wchar("x"), wchar('x', 'z'),
// wchar(L'x'), wchar(L'x', L'z')
+ // char_("a-z"), wchar("a-z")
// [w]lit('x'), [w]lit(L'x')
struct char_meta_grammar1
: proto::or_<
@@ -154,13 +259,13 @@
, qi::domain
, mpl::identity<extract_any_char_director<mpl::_> >
>
- // char_('x'), wchar(L'x') --> literal_char
+ // char_('x'), wchar(L'x'), char_("x"), wchar(L"x")--> literal_char
, meta_grammar::compose_function1_eval<
proto::function<
proto::if_<
is_char_tag<proto::_arg, qi::domain>()
>
- , basic_char_literal_meta_grammar
+ , single_char_literal_meta_grammar
>
, qi::domain
, mpl::identity<extract_literal_char_director<mpl::_, mpl::_> >
@@ -176,6 +281,16 @@
, qi::domain
, mpl::identity<extract_literal_char_director<mpl::_, mpl::_> >
>
+ // char_("a-z"), char_(L"a-z"), wchar(L"a-z") --> char_set
+ , meta_grammar::compose_function1_eval<
+ proto::function<
+ proto::if_<
+ is_char_tag<proto::_arg, qi::domain>()>
+ , proto::or_<basic_string_literal_meta_grammar, basic_std_string_meta_grammar>
+ >
+ , qi::domain
+ , mpl::identity<extract_chset_director<mpl::_, mpl::_> >
+ >
// char_(F()) --> lazy_char
, meta_grammar::function1_rule<
qi::domain
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk