// This file is part of fityk program. Copyright (C) Marcin Wojdyr
// $Id: optional_suffix.h 126 2006-01-16 17:01:51Z wojdyr $
// Licence of this file: either GPL or Boost Software License, Version 1.0.
#ifndef FITYK__OPTIONAL_SUFFIX__H
#define FITYK__OPTIONAL_SUFFIX__H
#include <boost/ref.hpp>
#include <boost/spirit/core/assert.hpp>
#include <boost/spirit/core/parser.hpp>
#include <boost/spirit/core/composite/impl/directives.ipp>
using namespace boost::spirit;
template<
typename RT,
typename IteratorT,
typename ScannerT>
inline RT
optional_suffix_parser_parse(
IteratorT base_first,
IteratorT base_last,
IteratorT suffix_first,
IteratorT suffix_last,
ScannerT& scan)
{
typedef typename ScannerT::iterator_t iterator_t;
iterator_t saved = scan.first;
std::size_t slen = base_last - base_first;
while (base_first != base_last)
{
if (scan.at_end() || (*base_first != *scan))
return scan.no_match();
++base_first;
++scan;
}
while (suffix_first != suffix_last)
{
if (scan.at_end() || (*suffix_first != *scan))
break;
++suffix_first;
++scan;
++slen;
}
return scan.create_match(slen, nil_t(), saved, scan.first);
}
///////////////////////////////////////////////////////////////////////////
//
// optional_suffix_seq_parser class
//
///////////////////////////////////////////////////////////////////////////
template <typename IteratorT = char const*>
class optional_suffix_seq_parser :
public parser<optional_suffix_seq_parser<IteratorT> >
{
public:
typedef optional_suffix_seq_parser<IteratorT> self_t;
optional_suffix_seq_parser(IteratorT base_first_, IteratorT base_last_,
IteratorT suffix_first_, IteratorT suffix_last_)
: base_first(base_first_), base_last(base_last_),
suffix_first(suffix_first_), suffix_last(suffix_last_) {}
optional_suffix_seq_parser(IteratorT base_first_,
IteratorT suffix_first_)
: base_first(base_first_),
base_last(boost::spirit::impl::get_last(base_first_)),
suffix_first(suffix_first_),
suffix_last(boost::spirit::impl::get_last(suffix_first_)){}
template <typename ScannerT>
typename parser_result<self_t, ScannerT>::type
parse(ScannerT const& scan) const
{
typedef typename boost::unwrap_reference<IteratorT>::type striter_t;
typedef typename parser_result<self_t, ScannerT>::type result_t;
return optional_suffix_parser_parse<result_t>(
striter_t(base_first),
striter_t(base_last),
striter_t(suffix_first),
striter_t(suffix_last),
scan);
}
private:
IteratorT base_first;
IteratorT base_last;
IteratorT suffix_first;
IteratorT suffix_last;
};
///////////////////////////////////////////////////////////////////////////
//
// optional_suffix_parser class
//
///////////////////////////////////////////////////////////////////////////
template <typename IteratorT = char const*>
class optional_suffix_parser :
public parser<optional_suffix_parser<IteratorT> >
{
public:
typedef optional_suffix_parser<IteratorT> self_t;
optional_suffix_parser(IteratorT base_first, IteratorT base_last,
IteratorT suffix_first, IteratorT suffix_last)
: seq(base_first, base_last, suffix_first, suffix_last) {}
optional_suffix_parser(IteratorT base_first, IteratorT suffix_first)
: seq(base_first, suffix_first) {}
template <typename ScannerT>
typename parser_result<self_t, ScannerT>::type
parse(ScannerT const& scan) const
{
typedef typename parser_result<self_t, ScannerT>::type result_t;
return boost::spirit::impl::contiguous_parser_parse<result_t>
(seq, scan, scan);
}
private:
optional_suffix_seq_parser<IteratorT> seq;
};
template <typename CharT>
inline optional_suffix_parser<CharT const*>
optional_suffix_p(CharT const* base_str, CharT const* suffix_str)
{
return optional_suffix_parser<CharT const*>(base_str, suffix_str);
}
template <typename IteratorT>
inline optional_suffix_parser<IteratorT>
optional_suffix_p(IteratorT base_first, IteratorT base_last,
IteratorT suffix_first, IteratorT suffix_last)
{
return optional_suffix_parser<IteratorT>(base_first, base_last,
suffix_first, suffix_last);
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1