lists.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 341 行

HPP
341
字号
/*=============================================================================    Copyright (c) 2002-2003 Hartmut Kaiser    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_LISTS_HPP#define BOOST_SPIRIT_LISTS_HPP///////////////////////////////////////////////////////////////////////////////#include <boost/config.hpp>#include <boost/spirit/home/classic/namespace.hpp>#include <boost/spirit/home/classic/meta/as_parser.hpp>#include <boost/spirit/home/classic/core/parser.hpp>#include <boost/spirit/home/classic/core/composite/composite.hpp>#include <boost/spirit/home/classic/utility/lists_fwd.hpp>#include <boost/spirit/home/classic/utility/impl/lists.ipp>///////////////////////////////////////////////////////////////////////////////namespace boost { namespace spirit {BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN///////////////////////////////////////////////////////////////////////////////////  list_parser class////      List parsers allow to parse constructs like////          item >> *(delim >> item)////      where 'item' is an auxiliary expression to parse and 'delim' is an//      auxiliary delimiter to parse.////      The list_parser class also can match an optional closing delimiter//      represented by the 'end' parser at the end of the list:////          item >> *(delim >> item) >> !end.////      If ItemT 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:////          list_p(item[f], delim)////      where 'item' is the parser matching one item of the list sequence and//      'f' is a functor to be called after matching one item. If we would do//      nothing, the resulting code would parse the sequence as follows:////          (item[f] - delim) >> *(delim >> (item[f] - delim))////      what in most cases is not what the user expects.//      (If this _is_ what you've expected, then please use one of the list_p//      generator functions 'direct()', which will inhibit re-attaching//      the actor to the item parser).////      To make the list parser behave as expected:////          (item - delim)[f] >> *(delim >> (item - delim)[f])////      the actor attached to the 'item' parser has to be re-attached to the//      *(item - delim) parser construct, which will make the resulting list//      parser 'do the right thing'.////      Additionally special care must be taken, if the item parser is a//      unary_parser_category type parser as////          list_p(*anychar_p, ',')////      which without any refactoring would result in////          (*anychar_p - ch_p(','))//              >> *( ch_p(',') >> (*anychar_p - ch_p(',')) )////      and will not give the expected result (the first *anychar_p will eat up//      all the input up to the end of the input stream). So we have to//      refactor this into:////          *(anychar_p - ch_p(','))//              >> *( ch_p(',') >> *(anychar_p - ch_p(',')) )////      what will give the correct result.////      The case, where the item parser is a combination of the two mentioned//      problems (i.e. the item parser is a unary parser  with an attached//      action), is handled accordingly too:////          list_p((*anychar_p)[f], ',')////      will be parsed as expected:////          (*(anychar_p - ch_p(',')))[f]//              >> *( ch_p(',') >> (*(anychar_p - ch_p(',')))[f] )./////////////////////////////////////////////////////////////////////////////////template <    typename ItemT, typename DelimT, typename EndT, typename CategoryT>struct list_parser :    public parser<list_parser<ItemT, DelimT, EndT, CategoryT> > {    typedef list_parser<ItemT, DelimT, EndT, CategoryT> self_t;    typedef CategoryT parser_category_t;    list_parser(ItemT const &item_, DelimT const &delim_,        EndT const& end_ = no_list_endtoken())    : item(item_), delim(delim_), end(end_)    {}    template <typename ScannerT>    typename parser_result<self_t, ScannerT>::type    parse(ScannerT const& scan) const    {        return impl::list_parser_type<CategoryT>            ::parse(scan, *this, item, delim, end);    }private:    typename as_parser<ItemT>::type::embed_t item;    typename as_parser<DelimT>::type::embed_t delim;    typename as_parser<EndT>::type::embed_t end;};///////////////////////////////////////////////////////////////////////////////////  List parser generator template////      This is a helper for generating a correct list_parser<> from//      auxiliary parameters. There are the following types supported as//      parameters yet: parsers, single characters and strings (see//      as_parser<> in meta/as_parser.hpp).////      The list_parser_gen by itself can be used for parsing comma separated//      lists without item formatting:////          list_p.parse(...)//              matches any comma separated list.////      If list_p is used with one parameter, this parameter is used to match//      the delimiter:////          list_p(';').parse(...)//              matches any semicolon separated list.////      If list_p is used with two parameters, the first parameter is used to//      match the items and the second parameter matches the delimiters:////          list_p(uint_p, ',').parse(...)//              matches comma separated unsigned integers.////      If list_p is used with three parameters, the first parameter is used//      to match the items, the second one is used to match the delimiters and//      the third one is used to match an optional ending token sequence:////          list_p(real_p, ';', eol_p).parse(...)//              matches a semicolon separated list of real numbers optionally//              followed by an end of line.////      The list_p in the previous examples denotes the predefined parser//      generator, which should be used to define list parsers (see below)./////////////////////////////////////////////////////////////////////////////////template <typename CharT = char>struct list_parser_gen :    public list_parser<kleene_star<anychar_parser>, chlit<CharT> >{    typedef list_parser_gen<CharT> self_t;// construct the list_parser_gen object as an list parser for comma separated// lists without item formatting.    list_parser_gen()    : list_parser<kleene_star<anychar_parser>, chlit<CharT> >        (*anychar_p, chlit<CharT>(','))    {}// The following generator functions should be used under normal circumstances.// (the operator()(...) functions)    // Generic generator functions for creation of concrete list parsers, which    // support 'normal' syntax:    //    //      item >> *(delim >> item)    //    // If item isn't given, everything between two delimiters is matched.    template<typename DelimT>    list_parser<        kleene_star<anychar_parser>,        typename as_parser<DelimT>::type,        no_list_endtoken,        unary_parser_category      // there is no action to re-attach    >    operator()(DelimT const &delim_) const    {        typedef kleene_star<anychar_parser> item_t;        typedef typename as_parser<DelimT>::type delim_t;        typedef            list_parser<item_t, delim_t, no_list_endtoken, unary_parser_category>            return_t;        return return_t(*anychar_p, as_parser<DelimT>::convert(delim_));    }    template<typename ItemT, typename DelimT>    list_parser<        typename as_parser<ItemT>::type,        typename as_parser<DelimT>::type,        no_list_endtoken,        typename as_parser<ItemT>::type::parser_category_t    >    operator()(ItemT const &item_, DelimT const &delim_) const    {        typedef typename as_parser<ItemT>::type item_t;        typedef typename as_parser<DelimT>::type delim_t;        typedef list_parser<item_t, delim_t, no_list_endtoken,                BOOST_DEDUCED_TYPENAME item_t::parser_category_t>            return_t;        return return_t(            as_parser<ItemT>::convert(item_),            as_parser<DelimT>::convert(delim_)        );    }    // Generic generator function for creation of concrete list parsers, which    // support 'extended' syntax:    //    //      item >> *(delim >> item) >> !end    template<typename ItemT, typename DelimT, typename EndT>    list_parser<        typename as_parser<ItemT>::type,        typename as_parser<DelimT>::type,        typename as_parser<EndT>::type,        typename as_parser<ItemT>::type::parser_category_t    >    operator()(        ItemT const &item_, DelimT const &delim_, EndT const &end_) const    {        typedef typename as_parser<ItemT>::type item_t;        typedef typename as_parser<DelimT>::type delim_t;        typedef typename as_parser<EndT>::type end_t;        typedef list_parser<item_t, delim_t, end_t,                BOOST_DEDUCED_TYPENAME item_t::parser_category_t>            return_t;        return return_t(            as_parser<ItemT>::convert(item_),            as_parser<DelimT>::convert(delim_),            as_parser<EndT>::convert(end_)        );    }// The following functions should be used, if the 'item' parser has an attached// semantic action or is a unary_parser_category type parser and the structure// of the resulting list parser should _not_ be refactored during parser// construction (see comment above).    // Generic generator function for creation of concrete list parsers, which    // support 'normal' syntax:    //    //      item >> *(delim >> item)    template<typename ItemT, typename DelimT>    list_parser<        typename as_parser<ItemT>::type,        typename as_parser<DelimT>::type,        no_list_endtoken,        plain_parser_category        // inhibit action re-attachment    >    direct(ItemT const &item_, DelimT const &delim_) const    {        typedef typename as_parser<ItemT>::type item_t;        typedef typename as_parser<DelimT>::type delim_t;        typedef list_parser<item_t, delim_t, no_list_endtoken,                plain_parser_category>            return_t;        return return_t(            as_parser<ItemT>::convert(item_),            as_parser<DelimT>::convert(delim_)        );    }    // Generic generator function for creation of concrete list parsers, which    // support 'extended' syntax:    //    //      item >> *(delim >> item) >> !end    template<typename ItemT, typename DelimT, typename EndT>    list_parser<        typename as_parser<ItemT>::type,        typename as_parser<DelimT>::type,        typename as_parser<EndT>::type,        plain_parser_category        // inhibit action re-attachment    >    direct(        ItemT const &item_, DelimT const &delim_, EndT const &end_) const    {        typedef typename as_parser<ItemT>::type item_t;        typedef typename as_parser<DelimT>::type delim_t;        typedef typename as_parser<EndT>::type end_t;        typedef            list_parser<item_t, delim_t, end_t, plain_parser_category>            return_t;        return return_t(            as_parser<ItemT>::convert(item_),            as_parser<DelimT>::convert(delim_),            as_parser<EndT>::convert(end_)        );    }};///////////////////////////////////////////////////////////////////////////////////  Predefined list parser generator////      The list_p parser generator can be used//        - by itself for parsing comma separated lists without item formatting//      or//        - for generating list parsers with auxiliary parser parameters//          for the 'item', 'delim' and 'end' subsequences.//      (see comment above)/////////////////////////////////////////////////////////////////////////////////const list_parser_gen<> list_p = list_parser_gen<>();///////////////////////////////////////////////////////////////////////////////BOOST_SPIRIT_CLASSIC_NAMESPACE_END}} // namespace BOOST_SPIRIT_CLASSIC_NS#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?