📄 utilities.hpp
字号:
template<>
struct parser_type<char>
{
typedef chlit<char> parser_t;
};
////////////////////////////////////////////////////////
template<>
struct parser_type<wchar_t>
{
typedef chlit<wchar_t> parser_t;
};
////////////////////////////////////////////////////////
template<>
struct parser_type<char const *>
{
typedef strlit<cstring<char> > parser_t;
};
////////////////////////////////////////////////////////
template<>
struct parser_type<wchar_t const *>
{
typedef strlit<cstring<wchar_t> > parser_t;
};
////////////////////////////////////////////////////////
template <class T>
struct parser_type_get
{
static T* t(void);
typedef impl::IF<boost::is_array<T>::value,
selector1,
selector2>::RET selector_t;
typedef typename parser_type_helper<(sizeof(selector_t))>
::template inner<T>::parser_t parser_t;
typedef typename parser_type_helper<(sizeof(selector_t))>
::template inner<T>::return_t return_t;
typedef typename parser_type_helper<(sizeof(selector_t))>
::template inner<T>::dispatcher_t dispatcher_t;
typedef typename parser_type_helper<(sizeof(selector_t))>
::template inner<T>::parameter_t parameter_t;
static return_t get_helper(parameter_t x , selector1) { return parser_t(x); }
static return_t get_helper(parameter_t x , selector2) { return x; }
static return_t get( parameter_t x ) {return get_helper(x, dispatcher_t()); }
};
////////////////////////////////////////////////////////
template<>
struct parser_type_get<char>
{
typedef chlit<char> parser_t;
static parser_t get(char ch) { return parser_t(ch); }
};
////////////////////////////////////////////////////////
template<>
struct parser_type_get<wchar_t>
{
typedef chlit<wchar_t> parser_t;
static parser_t get(wchar_t ch) { return parser_t(ch); }
};
////////////////////////////////////////////////////////
template<>
struct parser_type_get<char const *>
{
typedef strlit<cstring<char> > parser_t;
static parser_t get(char const* str) { return parser_t(str); }
};
////////////////////////////////////////////////////////
template<>
struct parser_type_get<wchar_t const *>
{
typedef strlit<cstring<wchar_t> > parser_t;
static parser_t get(wchar_t const* str) { return parser_t(str); }
};
////////////////////////////////////////////////////////
struct dummy_category {};
template<typename T>
struct determine_category
{
typedef typename parser_type<T>::parser_t type_of_parser;
typedef type_of_parser::parser_category category;
};
////////////////////////////////////////////////////////
template <typename NestedT, typename CategoryT>
struct confix_parser_type;
} // namespace impl
///////////////////////////////////////////////////////////////////////////////
//
// confix_parser class
//
// Parses a (possibly nested) sequence of 3 sub-matches. This class may
// be used to parse structures, where the opening part is possibly
// contained in the expression part and the whole sequence is only
// parsed after seeing the closing part matching the first opening
// subsequence. Example: nested PASCAL-comments:
//
// { This is a { nested } PASCAL-comment }
//
///////////////////////////////////////////////////////////////////////////////
template <
typename OpenT, typename ExprT, typename CloseT,
typename NestedT = non_nested,
typename CategoryT = impl::dummy_category
>
struct confix_parser :
public parser<
confix_parser<
OpenT, ExprT, CloseT, NestedT,
typename impl::IF<boost::is_same<CategoryT, impl::dummy_category>::value,
typename impl::determine_category<ExprT>::category ,
CategoryT
>::RET
>
>
{
confix_parser(OpenT const &open_, ExprT const &expr_, CloseT const &close_) ;
typedef typename impl::IF<boost::is_same<CategoryT, impl::dummy_category>::value,
typename impl::determine_category<ExprT>::category ,
CategoryT
>::RET category_type;
typedef confix_parser<OpenT, ExprT, CloseT, NestedT, category_type>
parser_with_correct_category;
template <typename IteratorT>
match
parse(IteratorT& first, IteratorT const& last) const
{
parser_with_correct_category* transformed_this =
(parser_with_correct_category*)(this);
return impl::confix_parser_type<NestedT, category_type>::
parse(first, last, *transformed_this, open, expr, close);
}
private:
typename embed_trait<OpenT>::type open;
typename embed_trait<ExprT>::type expr;
typename embed_trait<CloseT>::type close;
};
///////////////////////////////////////////////////////////////////////////////
//
// Confix parser generator template
//
// This is a helper for generating a correct confix_parser<> from
// auxilliary parameters. There are the following types supported as
// parameters yet: parsers, single characters and strings (see
// impl::parser_type).
//
// If ExprT is an action_parser_category type (parser with an attached
// semantic action) we have to do something special. This happens, if the
// user wrote something like:
//
// confix_p(open, body[f], close)
//
// where 'body' is the parser matching the body of the confix sequence
// and 'f' is a functor to be called after matching the body. If we would
// do nothing, the resulting code would parse the sequence as follows:
//
// start >> *(body[f] - close) >> close
//
// what in most cases is not what the user expects.
// (If this _is_ what you've expected, then please use the confix_p or
// confix_nest_p generator function 'direct', which will inhibit
// re-attaching the actor to the body parser).
//
// To make the confix parser behave as expected:
//
// start >> (*(body - close))[f] >> close
//
// the actor attached to the 'body' parser has to be re-attached to the
// *(body - close) parser construct, which will make the resulting confix
// parser 'do the right thing'.
//
///////////////////////////////////////////////////////////////////////////////
template<class NestedT>
struct confix_parser_gen
{
// Generic generator function for creation of concrete confix parsers
template<typename StartT, typename ExprT, typename EndT>
confix_parser<
typename impl::parser_type<StartT>::parser_t,
typename impl::parser_type<ExprT>::parser_t ,
typename impl::parser_type<EndT>::parser_t,
NestedT,
typename impl::determine_category<ExprT>::category
>
operator()(
StartT const &start_, ExprT const &expr_, EndT const &end_) const
{
typedef typename impl::parser_type<StartT>::parser_t start_t;
typedef typename impl::parser_type<ExprT>::parser_t expr_t ;
typedef typename impl::parser_type<EndT>::parser_t end_t;
typedef
typename impl::determine_category<ExprT>::category
parser_category;
typedef confix_parser<start_t, expr_t, end_t, NestedT, parser_category> return_t;
return return_t(
impl::parser_type_get<StartT>::get(start_),
impl::parser_type_get<ExprT>::get(expr_),
impl::parser_type_get<EndT>::get(end_)
);
}
// Generic generator function for creation of concrete confix parsers
// which have a action directly attached to the ExprT part of the
// parser (see comment above)
template<typename StartT, typename ExprT, typename EndT>
confix_parser<
typename impl::parser_type<StartT>::parser_t,
typename impl::parser_type<ExprT>::parser_t,
typename impl::parser_type<EndT>::parser_t,
NestedT,
plain_parser_category // do not re-attach action
>
direct(
StartT const &start_, ExprT const &expr_, EndT const &end_) const
{
typedef typename impl::parser_type<StartT>::parser_t start_t;
typedef typename impl::parser_type<ExprT>::parser_t expr_t;
typedef typename impl::parser_type<EndT>::parser_t end_t;
typedef plain_parser_category parser_category;
typedef
confix_parser<start_t, expr_t, end_t, NestedT, parser_category>
return_t;
return return_t(
impl::parser_type_get<StartT>::get(start_),
impl::parser_type_get<ExprT>::get(expr_),
impl::parser_type_get<EndT>::get(end_)
);
}
};
///////////////////////////////////////////////////////////////////////////////
//
// Predefined non_nested and nested confix parser generators
//
///////////////////////////////////////////////////////////////////////////////
const confix_parser_gen<non_nested> confix_p = confix_parser_gen<non_nested>();
const confix_parser_gen<nested> confix_nest_p = confix_parser_gen<nested>();
///////////////////////////////////////////////////////////////////////////////
//
// Comments are special types of confix parsers
//
// Comment parser generator template. This is a helper for generating a
// correct confix_parser<> from auxilliary parameters, which is able to
// parse comment constructs: (StartToken >> Comment text >> EndToken).
// There are the following types supported as parameters yet: parsers,
// single characters and strings (see impl::parser_type).
//
///////////////////////////////////////////////////////////////////////////////
template<typename NestedT>
struct comment_parser_gen
{
// generic generator function for creation of concrete comment parsers
template<typename StartT, typename EndT>
confix_parser<
typename impl::parser_type<StartT>::parser_t,
anychar_,
typename impl::parser_type<EndT>::parser_t,
NestedT
>
operator() (StartT const &start_, EndT const &end_) const
{
typedef typename impl::parser_type<StartT>::parser_t start_t;
typedef typename impl::parser_type<EndT>::parser_t end_t;
typedef confix_parser<start_t, anychar_, end_t, NestedT> return_t;
return return_t(
impl::parser_type_get<StartT>::get(start_),
anychar,
impl::parser_type_get<EndT>::get(end_) );
}
};
///////////////////////////////////////////////////////////////////////////////
//
// Predefined non_nested and nested comment parser generator
//
///////////////////////////////////////////////////////////////////////////////
comment_parser_gen<non_nested> comment_p = comment_parser_gen<non_nested>();
comment_parser_gen<nested> comment_nest_p = comment_parser_gen<nested>();
///////////////////////////////////////////////////////////////////////////////
//
// list_action class
//
// Links an list parser with a user defined semantic action.
// The semantic action may be a function or a functor. A function
// should be compatible with the interface:
//
// template <typename IteratorT>
// void f (IteratorT it);
//
// Where 'it' is an input iterator for iteration over the matched items
// in the list. Dereferencing this iterator will yield in getting a
// list item as a StringT.
//
// A functor should have a member operator() with a compatible signature
// as above. The matching item is passed into the function/functor.
// This is the default class that list parsers use when dealing with
// the construct:
//
// p[f]
//
// where p is a parser and f is a function or functor.
//
///////////////////////////////////////////////////////////////////////////////
template <typename ParserT, typename ActionT>
struct list_action :
public unary<ParserT>,
public parser<list_action<ParserT, ActionT> >
{
typedef action_parser_category parser_category;
list_action(ParserT const& subject, ActionT const& actor_);
template <typename IteratorT>
match
parse(IteratorT& first, IteratorT const& last) const
{
typedef impl::strip_scanner<IteratorT> strip_scanner;
typedef list_action_iterator<ParserT, IteratorT,
ParserT::string_t> iterator_t;
typename strip_scanner::iterator_type begin = strip_scanner::get(first);
iterator_t list_it (&subject(), first, last);
actor(list_it, iterator_t());
if (list_it.matched()) {
first = list_it.actposition();
return match (std::distance(begin, strip_scanner::get(first)));
}
return match();
}
ActionT const &predicate() const { return actor; }
private:
typename embed_trait<ActionT>::type actor;
};
///////////////////////////////////////////////////////////////////////////////
//
// class list_action_iterator
//
// The list_action_iterator is an input iterator, which allows access
// to the successfully parsed list items.
//
///////////////////////////////////////////////////////////////////////////////
template <typename ParserT, typename IteratorT, typename BaseT = std::string>
struct list_action_iterator
{
typedef std::input_iterator_tag iterator_category;
typedef BaseT value_type;
typedef ptrdiff_t difference_type;
typedef BaseT * pointer;
typedef BaseT & reference;
list_action_iterator();
list_action_iterator(
ParserT const *parser, IteratorT &first, IteratorT const &last);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -