Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:08

0001 /*=============================================================================
0002     Copyright (c) 2002-2003 Hartmut Kaiser
0003     http://spirit.sourceforge.net/
0004 
0005   Distributed under the Boost Software License, Version 1.0. (See accompanying
0006   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 =============================================================================*/
0008 #ifndef BOOST_SPIRIT_LISTS_HPP
0009 #define BOOST_SPIRIT_LISTS_HPP
0010 
0011 ///////////////////////////////////////////////////////////////////////////////
0012 #include <boost/config.hpp>
0013 #include <boost/spirit/home/classic/namespace.hpp>
0014 #include <boost/spirit/home/classic/meta/as_parser.hpp>
0015 #include <boost/spirit/home/classic/core/parser.hpp>
0016 #include <boost/spirit/home/classic/core/composite/composite.hpp>
0017 
0018 #include <boost/spirit/home/classic/utility/lists_fwd.hpp>
0019 #include <boost/spirit/home/classic/utility/impl/lists.ipp>
0020 
0021 ///////////////////////////////////////////////////////////////////////////////
0022 namespace boost { namespace spirit {
0023 
0024 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0025 
0026 ///////////////////////////////////////////////////////////////////////////////
0027 //
0028 //  list_parser class
0029 //
0030 //      List parsers allow to parse constructs like
0031 //
0032 //          item >> *(delim >> item)
0033 //
0034 //      where 'item' is an auxiliary expression to parse and 'delim' is an
0035 //      auxiliary delimiter to parse.
0036 //
0037 //      The list_parser class also can match an optional closing delimiter
0038 //      represented by the 'end' parser at the end of the list:
0039 //
0040 //          item >> *(delim >> item) >> !end.
0041 //
0042 //      If ItemT is an action_parser_category type (parser with an attached
0043 //      semantic action) we have to do something special. This happens, if the
0044 //      user wrote something like:
0045 //
0046 //          list_p(item[f], delim)
0047 //
0048 //      where 'item' is the parser matching one item of the list sequence and
0049 //      'f' is a functor to be called after matching one item. If we would do
0050 //      nothing, the resulting code would parse the sequence as follows:
0051 //
0052 //          (item[f] - delim) >> *(delim >> (item[f] - delim))
0053 //
0054 //      what in most cases is not what the user expects.
0055 //      (If this _is_ what you've expected, then please use one of the list_p
0056 //      generator functions 'direct()', which will inhibit re-attaching
0057 //      the actor to the item parser).
0058 //
0059 //      To make the list parser behave as expected:
0060 //
0061 //          (item - delim)[f] >> *(delim >> (item - delim)[f])
0062 //
0063 //      the actor attached to the 'item' parser has to be re-attached to the
0064 //      *(item - delim) parser construct, which will make the resulting list
0065 //      parser 'do the right thing'.
0066 //
0067 //      Additionally special care must be taken, if the item parser is a
0068 //      unary_parser_category type parser as
0069 //
0070 //          list_p(*anychar_p, ',')
0071 //
0072 //      which without any refactoring would result in
0073 //
0074 //          (*anychar_p - ch_p(','))
0075 //              >> *( ch_p(',') >> (*anychar_p - ch_p(',')) )
0076 //
0077 //      and will not give the expected result (the first *anychar_p will eat up
0078 //      all the input up to the end of the input stream). So we have to
0079 //      refactor this into:
0080 //
0081 //          *(anychar_p - ch_p(','))
0082 //              >> *( ch_p(',') >> *(anychar_p - ch_p(',')) )
0083 //
0084 //      what will give the correct result.
0085 //
0086 //      The case, where the item parser is a combination of the two mentioned
0087 //      problems (i.e. the item parser is a unary parser  with an attached
0088 //      action), is handled accordingly too:
0089 //
0090 //          list_p((*anychar_p)[f], ',')
0091 //
0092 //      will be parsed as expected:
0093 //
0094 //          (*(anychar_p - ch_p(',')))[f]
0095 //              >> *( ch_p(',') >> (*(anychar_p - ch_p(',')))[f] ).
0096 //
0097 ///////////////////////////////////////////////////////////////////////////////
0098 template <
0099     typename ItemT, typename DelimT, typename EndT, typename CategoryT
0100 >
0101 struct list_parser :
0102     public parser<list_parser<ItemT, DelimT, EndT, CategoryT> > {
0103 
0104     typedef list_parser<ItemT, DelimT, EndT, CategoryT> self_t;
0105     typedef CategoryT parser_category_t;
0106 
0107     list_parser(ItemT const &item_, DelimT const &delim_,
0108         EndT const& end_ = no_list_endtoken())
0109     : item(item_), delim(delim_), end(end_)
0110     {}
0111 
0112     template <typename ScannerT>
0113     typename parser_result<self_t, ScannerT>::type
0114     parse(ScannerT const& scan) const
0115     {
0116         return impl::list_parser_type<CategoryT>
0117             ::parse(scan, *this, item, delim, end);
0118     }
0119 
0120 private:
0121     typename as_parser<ItemT>::type::embed_t item;
0122     typename as_parser<DelimT>::type::embed_t delim;
0123     typename as_parser<EndT>::type::embed_t end;
0124 };
0125 
0126 ///////////////////////////////////////////////////////////////////////////////
0127 //
0128 //  List parser generator template
0129 //
0130 //      This is a helper for generating a correct list_parser<> from
0131 //      auxiliary parameters. There are the following types supported as
0132 //      parameters yet: parsers, single characters and strings (see
0133 //      as_parser<> in meta/as_parser.hpp).
0134 //
0135 //      The list_parser_gen by itself can be used for parsing comma separated
0136 //      lists without item formatting:
0137 //
0138 //          list_p.parse(...)
0139 //              matches any comma separated list.
0140 //
0141 //      If list_p is used with one parameter, this parameter is used to match
0142 //      the delimiter:
0143 //
0144 //          list_p(';').parse(...)
0145 //              matches any semicolon separated list.
0146 //
0147 //      If list_p is used with two parameters, the first parameter is used to
0148 //      match the items and the second parameter matches the delimiters:
0149 //
0150 //          list_p(uint_p, ',').parse(...)
0151 //              matches comma separated unsigned integers.
0152 //
0153 //      If list_p is used with three parameters, the first parameter is used
0154 //      to match the items, the second one is used to match the delimiters and
0155 //      the third one is used to match an optional ending token sequence:
0156 //
0157 //          list_p(real_p, ';', eol_p).parse(...)
0158 //              matches a semicolon separated list of real numbers optionally
0159 //              followed by an end of line.
0160 //
0161 //      The list_p in the previous examples denotes the predefined parser
0162 //      generator, which should be used to define list parsers (see below).
0163 //
0164 ///////////////////////////////////////////////////////////////////////////////
0165 
0166 template <typename CharT = char>
0167 struct list_parser_gen :
0168     public list_parser<kleene_star<anychar_parser>, chlit<CharT> >
0169 {
0170     typedef list_parser_gen<CharT> self_t;
0171 
0172 // construct the list_parser_gen object as an list parser for comma separated
0173 // lists without item formatting.
0174     list_parser_gen()
0175     : list_parser<kleene_star<anychar_parser>, chlit<CharT> >
0176         (*anychar_p, chlit<CharT>(','))
0177     {}
0178 
0179 // The following generator functions should be used under normal circumstances.
0180 // (the operator()(...) functions)
0181 
0182     // Generic generator functions for creation of concrete list parsers, which
0183     // support 'normal' syntax:
0184     //
0185     //      item >> *(delim >> item)
0186     //
0187     // If item isn't given, everything between two delimiters is matched.
0188 
0189     template<typename DelimT>
0190     list_parser<
0191         kleene_star<anychar_parser>,
0192         typename as_parser<DelimT>::type,
0193         no_list_endtoken,
0194         unary_parser_category      // there is no action to re-attach
0195     >
0196     operator()(DelimT const &delim_) const
0197     {
0198         typedef kleene_star<anychar_parser> item_t;
0199         typedef typename as_parser<DelimT>::type delim_t;
0200 
0201         typedef
0202             list_parser<item_t, delim_t, no_list_endtoken, unary_parser_category>
0203             return_t;
0204 
0205         return return_t(*anychar_p, as_parser<DelimT>::convert(delim_));
0206     }
0207 
0208     template<typename ItemT, typename DelimT>
0209     list_parser<
0210         typename as_parser<ItemT>::type,
0211         typename as_parser<DelimT>::type,
0212         no_list_endtoken,
0213         typename as_parser<ItemT>::type::parser_category_t
0214     >
0215     operator()(ItemT const &item_, DelimT const &delim_) const
0216     {
0217         typedef typename as_parser<ItemT>::type item_t;
0218         typedef typename as_parser<DelimT>::type delim_t;
0219         typedef list_parser<item_t, delim_t, no_list_endtoken,
0220                 BOOST_DEDUCED_TYPENAME item_t::parser_category_t>
0221             return_t;
0222 
0223         return return_t(
0224             as_parser<ItemT>::convert(item_),
0225             as_parser<DelimT>::convert(delim_)
0226         );
0227     }
0228 
0229     // Generic generator function for creation of concrete list parsers, which
0230     // support 'extended' syntax:
0231     //
0232     //      item >> *(delim >> item) >> !end
0233 
0234     template<typename ItemT, typename DelimT, typename EndT>
0235     list_parser<
0236         typename as_parser<ItemT>::type,
0237         typename as_parser<DelimT>::type,
0238         typename as_parser<EndT>::type,
0239         typename as_parser<ItemT>::type::parser_category_t
0240     >
0241     operator()(
0242         ItemT const &item_, DelimT const &delim_, EndT const &end_) const
0243     {
0244         typedef typename as_parser<ItemT>::type item_t;
0245         typedef typename as_parser<DelimT>::type delim_t;
0246         typedef typename as_parser<EndT>::type end_t;
0247 
0248         typedef list_parser<item_t, delim_t, end_t,
0249                 BOOST_DEDUCED_TYPENAME item_t::parser_category_t>
0250             return_t;
0251 
0252         return return_t(
0253             as_parser<ItemT>::convert(item_),
0254             as_parser<DelimT>::convert(delim_),
0255             as_parser<EndT>::convert(end_)
0256         );
0257     }
0258 
0259 // The following functions should be used, if the 'item' parser has an attached
0260 // semantic action or is a unary_parser_category type parser and the structure
0261 // of the resulting list parser should _not_ be refactored during parser
0262 // construction (see comment above).
0263 
0264     // Generic generator function for creation of concrete list parsers, which
0265     // support 'normal' syntax:
0266     //
0267     //      item >> *(delim >> item)
0268 
0269     template<typename ItemT, typename DelimT>
0270     list_parser<
0271         typename as_parser<ItemT>::type,
0272         typename as_parser<DelimT>::type,
0273         no_list_endtoken,
0274         plain_parser_category        // inhibit action re-attachment
0275     >
0276     direct(ItemT const &item_, DelimT const &delim_) const
0277     {
0278         typedef typename as_parser<ItemT>::type item_t;
0279         typedef typename as_parser<DelimT>::type delim_t;
0280         typedef list_parser<item_t, delim_t, no_list_endtoken,
0281                 plain_parser_category>
0282             return_t;
0283 
0284         return return_t(
0285             as_parser<ItemT>::convert(item_),
0286             as_parser<DelimT>::convert(delim_)
0287         );
0288     }
0289 
0290     // Generic generator function for creation of concrete list parsers, which
0291     // support 'extended' syntax:
0292     //
0293     //      item >> *(delim >> item) >> !end
0294 
0295     template<typename ItemT, typename DelimT, typename EndT>
0296     list_parser<
0297         typename as_parser<ItemT>::type,
0298         typename as_parser<DelimT>::type,
0299         typename as_parser<EndT>::type,
0300         plain_parser_category        // inhibit action re-attachment
0301     >
0302     direct(
0303         ItemT const &item_, DelimT const &delim_, EndT const &end_) const
0304     {
0305         typedef typename as_parser<ItemT>::type item_t;
0306         typedef typename as_parser<DelimT>::type delim_t;
0307         typedef typename as_parser<EndT>::type end_t;
0308 
0309         typedef
0310             list_parser<item_t, delim_t, end_t, plain_parser_category>
0311             return_t;
0312 
0313         return return_t(
0314             as_parser<ItemT>::convert(item_),
0315             as_parser<DelimT>::convert(delim_),
0316             as_parser<EndT>::convert(end_)
0317         );
0318     }
0319 };
0320 
0321 ///////////////////////////////////////////////////////////////////////////////
0322 //
0323 //  Predefined list parser generator
0324 //
0325 //      The list_p parser generator can be used
0326 //        - by itself for parsing comma separated lists without item formatting
0327 //      or
0328 //        - for generating list parsers with auxiliary parser parameters
0329 //          for the 'item', 'delim' and 'end' subsequences.
0330 //      (see comment above)
0331 //
0332 ///////////////////////////////////////////////////////////////////////////////
0333 const list_parser_gen<> list_p = list_parser_gen<>();
0334 
0335 ///////////////////////////////////////////////////////////////////////////////
0336 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0337 
0338 }} // namespace BOOST_SPIRIT_CLASSIC_NS
0339 
0340 #endif