blob: 48b82cf70fbc08996362213d85bcf19795dd43f9 [file] [log] [blame]
/*=============================================================================
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_META_GRAMMAR_FEB_02_2007_0925AM)
#define BOOST_SPIRIT_META_GRAMMAR_FEB_02_2007_0925AM
#include <boost/spirit/home/qi/domain.hpp>
#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
{
///////////////////////////////////////////////////////////////////////////
// forwards
///////////////////////////////////////////////////////////////////////////
template <typename Char>
struct any_char;
template <typename Char>
struct literal_char;
struct lazy_char;
template <typename Char>
struct char_range;
struct lazy_char_range;
template <typename Positive>
struct negated_char_parser;
template <typename Tag>
struct char_class;
struct char_meta_grammar;
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Enable>
struct is_valid_expr;
template <typename Expr, typename Enable>
struct expr_transform;
///////////////////////////////////////////////////////////////////////////
// get the director of an any_char
///////////////////////////////////////////////////////////////////////////
template <typename Tag>
struct extract_any_char_director;
template <>
struct extract_any_char_director<tag::char_>
{
typedef any_char<char> type;
};
template <>
struct extract_any_char_director<tag::wchar>
{
typedef any_char<wchar_t> type;
};
///////////////////////////////////////////////////////////////////////////
// get the director of a character literal type
///////////////////////////////////////////////////////////////////////////
template <typename Tag, typename T>
struct extract_literal_char_director;
template <typename T>
struct extract_literal_char_director<tag::char_, T>
{
typedef literal_char<T> type;
};
template <typename T>
struct extract_literal_char_director<tag::wchar, T>
{
typedef literal_char<wchar_t> type;
};
template <typename T>
struct extract_literal_char_director<tag::lit, T>
{
typedef literal_char<T> type;
};
template <typename T>
struct extract_literal_char_director<tag::wlit, T>
{
typedef literal_char<wchar_t> type;
};
///////////////////////////////////////////////////////////////////////////
// get the director of a character range type
///////////////////////////////////////////////////////////////////////////
template <typename Tag, typename T>
struct extract_char_range_director;
template <typename T>
struct extract_char_range_director<tag::char_, T>
{
typedef char_range<T> type;
};
template <typename T>
struct extract_char_range_director<tag::wchar, T>
{
typedef char_range<wchar_t> type;
};
///////////////////////////////////////////////////////////////////////////
// char parser meta-grammars
///////////////////////////////////////////////////////////////////////////
// literals: 'x', L'x'
struct basic_char_literal_meta_grammar
: proto::or_<
proto::terminal<char>
, proto::terminal<wchar_t>
>
{
};
// 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_<
meta_grammar::terminal_rule<
qi::domain, char, literal_char<char>
>
, meta_grammar::terminal_rule<
qi::domain, wchar_t, literal_char<wchar_t>
>
>
{
};
// 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;
}
}
template <typename CharSetClass> // no-case version
char_set_component(Char const* definition, CharSetClass)
: ptr(new detail::basic_chset<Char>())
{
Char ch = *definition++;
while (ch)
{
Char next = *definition++;
if (next == '-')
{
next = *definition++;
if (next == 0)
{
ptr->set(CharSetClass::tolower(ch));
ptr->set(CharSetClass::tolower('-'));
ptr->set(CharSetClass::toupper(ch));
ptr->set(CharSetClass::toupper('-'));
break;
}
ptr->set(CharSetClass::tolower(ch)
, CharSetClass::tolower(next));
ptr->set(CharSetClass::toupper(ch)
, CharSetClass::toupper(next));
}
else
{
ptr->set(CharSetClass::tolower(ch));
ptr->set(CharSetClass::toupper(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"), 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_<
// char_, wchar --> any_char
meta_grammar::compose_empty<
proto::if_<
is_char_tag<proto::_child, qi::domain>()
>
, qi::domain
, mpl::identity<extract_any_char_director<mpl::_> >
>
// 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::_child, qi::domain>()
>
, single_char_literal_meta_grammar
>
, qi::domain
, mpl::identity<extract_literal_char_director<mpl::_, mpl::_> >
>
// lit("x"), wlit(L"x") --> literal_char
, meta_grammar::compose_function1_eval<
proto::function<
proto::if_<
is_lit_tag<proto::_child, qi::domain>()
>
, basic_char_literal_meta_grammar
>
, 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::_child, 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
, tag::char_
, lazy_char
>
// char_('x', 'z'), wchar(L'x', L'z') --> char_range
, meta_grammar::compose_function2_eval<
proto::function<
proto::if_<
is_char_tag<proto::_child, qi::domain>()
>
, basic_char_literal_meta_grammar
, basic_char_literal_meta_grammar
>
, qi::domain
, mpl::identity<extract_char_range_director<mpl::_, mpl::_> >
>
// char_(F1(), F2()) --> lazy_char_range
, meta_grammar::function2_rule<
qi::domain
, tag::char_
, lazy_char_range
>
>
{
};
// char_classes: alnum, alpha, cntrl, ... etc.
struct char_class_meta_grammar
: proto::or_<
// alnum, alpha, cntrl, ... etc.
meta_grammar::compose_empty<
proto::terminal<spirit::char_class::key<proto::_, proto::_> >
, qi::domain
, char_class<mpl::_>
>
, meta_grammar::compose_empty<
proto::terminal<spirit::char_class::lower_case_tag<proto::_> >
, qi::domain
, char_class<mpl::_>
>
, meta_grammar::compose_empty<
proto::terminal<spirit::char_class::upper_case_tag<proto::_> >
, qi::domain
, char_class<mpl::_>
>
>
{};
// ~x (where x is a char_parser)
struct negated_char_meta_grammar
: meta_grammar::compose_single<
proto::unary_expr<
proto::tag::complement
, char_meta_grammar
>
, qi::domain
, negated_char_parser<mpl::_>
>
{
};
// main char_meta_grammar
struct char_meta_grammar
: proto::or_<
char_meta_grammar1
, char_class_meta_grammar
, char_literal_meta_grammar
, negated_char_meta_grammar
>
{
};
///////////////////////////////////////////////////////////////////////////
// These specializations non-intrusively hooks into the RD meta-grammar.
// (see qi/meta_grammar.hpp)
///////////////////////////////////////////////////////////////////////////
template <typename Expr>
struct is_valid_expr<Expr
, typename enable_if<proto::matches<Expr, char_meta_grammar> >::type>
: mpl::true_
{
};
template <typename Expr>
struct expr_transform<Expr
, typename enable_if<proto::matches<Expr, char_meta_grammar> >::type>
: mpl::identity<char_meta_grammar>
{
};
}}}
#endif