Back to home page

EIC code displayed by LXR

 
 

    


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

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_CONFIX_HPP
0009 #define BOOST_SPIRIT_CONFIX_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/composite/operators.hpp>
0016 
0017 #include <boost/spirit/home/classic/utility/confix_fwd.hpp>
0018 #include <boost/spirit/home/classic/utility/impl/confix.ipp>
0019 
0020 ///////////////////////////////////////////////////////////////////////////////
0021 namespace boost { namespace spirit {
0022 
0023 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0024 
0025 ///////////////////////////////////////////////////////////////////////////////
0026 //
0027 //  confix_parser class
0028 //
0029 //      Parses a sequence of 3 sub-matches. This class may
0030 //      be used to parse structures, where the opening part is possibly
0031 //      contained in the expression part and the whole sequence is only
0032 //      parsed after seeing the closing part matching the first opening
0033 //      subsequence. Example: C-comments:
0034 //
0035 //      /* This is a C-comment */
0036 //
0037 ///////////////////////////////////////////////////////////////////////////////
0038 
0039 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0040 #pragma warning(push)
0041 #pragma warning(disable:4512) //assignment operator could not be generated
0042 #endif
0043 
0044 template<typename NestedT = non_nested, typename LexemeT = non_lexeme>
0045 struct confix_parser_gen;
0046 
0047 template <
0048     typename OpenT, typename ExprT, typename CloseT, typename CategoryT,
0049     typename NestedT, typename LexemeT
0050 >
0051 struct confix_parser :
0052     public parser<
0053         confix_parser<OpenT, ExprT, CloseT, CategoryT, NestedT, LexemeT>
0054     >
0055 {
0056     typedef
0057         confix_parser<OpenT, ExprT, CloseT, CategoryT, NestedT, LexemeT>
0058         self_t;
0059 
0060     confix_parser(OpenT const &open_, ExprT const &expr_, CloseT const &close_)
0061     : open(open_), expr(expr_), close(close_)
0062     {}
0063 
0064     template <typename ScannerT>
0065     typename parser_result<self_t, ScannerT>::type
0066     parse(ScannerT const& scan) const
0067     {
0068         return impl::confix_parser_type<CategoryT>::
0069             parse(NestedT(), LexemeT(), *this, scan, open, expr, close);
0070     }
0071 
0072 private:
0073 
0074     typename as_parser<OpenT>::type::embed_t open;
0075     typename as_parser<ExprT>::type::embed_t expr;
0076     typename as_parser<CloseT>::type::embed_t close;
0077 };
0078 
0079 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0080 #pragma warning(pop)
0081 #endif
0082 
0083 ///////////////////////////////////////////////////////////////////////////////
0084 //
0085 //  Confix parser generator template
0086 //
0087 //      This is a helper for generating a correct confix_parser<> from
0088 //      auxiliary parameters. There are the following types supported as
0089 //      parameters yet: parsers, single characters and strings (see
0090 //      as_parser).
0091 //
0092 //      If the body parser is an action_parser_category type parser (a parser
0093 //      with an attached semantic action) we have to do something special. This
0094 //      happens, if the user wrote something like:
0095 //
0096 //          confix_p(open, body[f], close)
0097 //
0098 //      where 'body' is the parser matching the body of the confix sequence
0099 //      and 'f' is a functor to be called after matching the body. If we would
0100 //      do nothing, the resulting code would parse the sequence as follows:
0101 //
0102 //          start >> (body[f] - close) >> close
0103 //
0104 //      what in most cases is not what the user expects.
0105 //      (If this _is_ what you've expected, then please use the confix_p
0106 //      generator function 'direct()', which will inhibit
0107 //      re-attaching the actor to the body parser).
0108 //
0109 //      To make the confix parser behave as expected:
0110 //
0111 //          start >> (body - close)[f] >> close
0112 //
0113 //      the actor attached to the 'body' parser has to be re-attached to the
0114 //      (body - close) parser construct, which will make the resulting confix
0115 //      parser 'do the right thing'. This refactoring is done by the help of
0116 //      the refactoring parsers (see the files refactoring.[hi]pp).
0117 //
0118 //      Additionally special care must be taken, if the body parser is a
0119 //      unary_parser_category type parser as
0120 //
0121 //          confix_p(open, *anychar_p, close)
0122 //
0123 //      which without any refactoring would result in
0124 //
0125 //          start >> (*anychar_p - close) >> close
0126 //
0127 //      and will not give the expected result (*anychar_p will eat up all the
0128 //      input up to the end of the input stream). So we have to refactor this
0129 //      into:
0130 //
0131 //          start >> *(anychar_p - close) >> close
0132 //
0133 //      what will give the correct result.
0134 //
0135 //      The case, where the body parser is a combination of the two mentioned
0136 //      problems (i.e. the body parser is a unary parser  with an attached
0137 //      action), is handled accordingly too:
0138 //
0139 //          confix_p(start, (*anychar_p)[f], end)
0140 //
0141 //      will be parsed as expected:
0142 //
0143 //          start >> (*(anychar_p - end))[f] >> end.
0144 //
0145 ///////////////////////////////////////////////////////////////////////////////
0146 
0147 template<typename NestedT, typename LexemeT>
0148 struct confix_parser_gen
0149 {
0150     // Generic generator function for creation of concrete confix parsers
0151 
0152     template<typename StartT, typename ExprT, typename EndT>
0153     struct paren_op_result_type
0154     {
0155         typedef confix_parser<
0156             typename as_parser<StartT>::type,
0157             typename as_parser<ExprT>::type,
0158             typename as_parser<EndT>::type,
0159             typename as_parser<ExprT>::type::parser_category_t,
0160             NestedT,
0161             LexemeT
0162         > type;
0163     };
0164   
0165     template<typename StartT, typename ExprT, typename EndT>
0166     typename paren_op_result_type<StartT, ExprT, EndT>::type 
0167     operator()(StartT const &start_, ExprT const &expr_, EndT const &end_) const
0168     {
0169         typedef typename paren_op_result_type<StartT,ExprT,EndT>::type 
0170             return_t;
0171 
0172         return return_t(
0173             as_parser<StartT>::convert(start_),
0174             as_parser<ExprT>::convert(expr_),
0175             as_parser<EndT>::convert(end_)
0176         );
0177     }
0178 
0179     // Generic generator function for creation of concrete confix parsers
0180     // which have an action directly attached to the ExprT part of the
0181     // parser (see comment above, no automatic refactoring)
0182 
0183     template<typename StartT, typename ExprT, typename EndT>
0184     struct direct_result_type
0185     {
0186         typedef confix_parser<
0187             typename as_parser<StartT>::type,
0188             typename as_parser<ExprT>::type,
0189             typename as_parser<EndT>::type,
0190             plain_parser_category,   // do not re-attach action
0191             NestedT,
0192             LexemeT
0193         > type;
0194     };
0195 
0196     template<typename StartT, typename ExprT, typename EndT>
0197     typename direct_result_type<StartT,ExprT,EndT>::type
0198     direct(StartT const &start_, ExprT const &expr_, EndT const &end_) const
0199     {
0200         typedef typename direct_result_type<StartT,ExprT,EndT>::type
0201             return_t;
0202 
0203         return return_t(
0204             as_parser<StartT>::convert(start_),
0205             as_parser<ExprT>::convert(expr_),
0206             as_parser<EndT>::convert(end_)
0207         );
0208     }
0209 };
0210 
0211 ///////////////////////////////////////////////////////////////////////////////
0212 //
0213 //  Predefined non_nested confix parser generators
0214 //
0215 ///////////////////////////////////////////////////////////////////////////////
0216 
0217 const confix_parser_gen<non_nested, non_lexeme> confix_p =
0218     confix_parser_gen<non_nested, non_lexeme>();
0219 
0220 ///////////////////////////////////////////////////////////////////////////////
0221 //
0222 //  Comments are special types of confix parsers
0223 //
0224 //      Comment parser generator template. This is a helper for generating a
0225 //      correct confix_parser<> from auxiliary parameters, which is able to
0226 //      parse comment constructs: (StartToken >> Comment text >> EndToken).
0227 //
0228 //      There are the following types supported as parameters yet: parsers,
0229 //      single characters and strings (see as_parser).
0230 //
0231 //      There are two diffenerent predefined comment parser generators
0232 //      (comment_p and comment_nest_p, see below), which may be used for
0233 //      creating special comment parsers in two different ways.
0234 //
0235 //      If these are used with one parameter, a comment starting with the given
0236 //      first parser parameter up to the end of the line is matched. So for
0237 //      instance the following parser matches C++ style comments:
0238 //
0239 //          comment_p("//").
0240 //
0241 //      If these are used with two parameters, a comment starting with the
0242 //      first parser parameter up to the second parser parameter is matched.
0243 //      For instance a C style comment parser should be constrcuted as:
0244 //
0245 //          comment_p("/*", "*/").
0246 //
0247 //      Please note, that a comment is parsed implicitly as if the whole
0248 //      comment_p(...) statement were embedded into a lexeme_d[] directive.
0249 //
0250 ///////////////////////////////////////////////////////////////////////////////
0251 
0252 template<typename NestedT>
0253 struct comment_parser_gen
0254 {
0255     // Generic generator function for creation of concrete comment parsers
0256     // from an open token. The newline parser eol_p is used as the
0257     // closing token.
0258 
0259     template<typename StartT>
0260     struct paren_op1_result_type
0261     {
0262         typedef confix_parser<
0263             typename as_parser<StartT>::type,
0264             kleene_star<anychar_parser>,
0265             alternative<eol_parser, end_parser>,
0266             unary_parser_category,          // there is no action to re-attach
0267             NestedT,
0268             is_lexeme                       // insert implicit lexeme_d[]
0269         >
0270         type;
0271     };
0272 
0273     template<typename StartT>
0274     typename paren_op1_result_type<StartT>::type 
0275     operator() (StartT const &start_) const
0276     {
0277         typedef typename paren_op1_result_type<StartT>::type
0278             return_t;
0279 
0280         return return_t(
0281             as_parser<StartT>::convert(start_),
0282             *anychar_p,
0283             eol_p | end_p
0284         );
0285     }
0286 
0287     // Generic generator function for creation of concrete comment parsers
0288     // from an open and a close tokens.
0289 
0290     template<typename StartT, typename EndT>
0291     struct paren_op2_result_type
0292     {
0293         typedef confix_parser<
0294             typename as_parser<StartT>::type,
0295             kleene_star<anychar_parser>,
0296             typename as_parser<EndT>::type,
0297             unary_parser_category,          // there is no action to re-attach
0298             NestedT,
0299             is_lexeme                       // insert implicit lexeme_d[]
0300         > type;
0301     };
0302 
0303     template<typename StartT, typename EndT>
0304     typename paren_op2_result_type<StartT,EndT>::type
0305     operator() (StartT const &start_, EndT const &end_) const
0306     {
0307         typedef typename paren_op2_result_type<StartT,EndT>::type
0308             return_t;
0309 
0310         return return_t(
0311             as_parser<StartT>::convert(start_),
0312             *anychar_p,
0313             as_parser<EndT>::convert(end_)
0314         );
0315     }
0316 };
0317 
0318 ///////////////////////////////////////////////////////////////////////////////
0319 //
0320 //  Predefined non_nested comment parser generator
0321 //
0322 ///////////////////////////////////////////////////////////////////////////////
0323 
0324 const comment_parser_gen<non_nested> comment_p =
0325     comment_parser_gen<non_nested>();
0326 
0327 ///////////////////////////////////////////////////////////////////////////////
0328 //
0329 //  comment_nest_parser class
0330 //
0331 //      Parses a nested comments.
0332 //      Example: nested PASCAL-comments:
0333 //
0334 //      { This is a { nested } PASCAL-comment }
0335 //
0336 ///////////////////////////////////////////////////////////////////////////////
0337 
0338 template<typename OpenT, typename CloseT>
0339 struct comment_nest_parser:
0340     public parser<comment_nest_parser<OpenT, CloseT> >
0341 {
0342     typedef comment_nest_parser<OpenT, CloseT> self_t;
0343 
0344     comment_nest_parser(OpenT const &open_, CloseT const &close_):
0345         open(open_), close(close_)
0346     {}
0347 
0348     template<typename ScannerT>
0349     typename parser_result<self_t, ScannerT>::type
0350         parse(ScannerT const &scan) const
0351     {
0352         return do_parse(
0353             open >> *(*this | (anychar_p - close)) >> close,
0354             scan);
0355     }
0356 
0357 private:
0358     template<typename ParserT, typename ScannerT>
0359     typename parser_result<self_t, ScannerT>::type
0360         do_parse(ParserT const &p, ScannerT const &scan) const
0361     {
0362         return
0363             impl::contiguous_parser_parse<
0364                 typename parser_result<ParserT, ScannerT>::type
0365             >(p, scan, scan);
0366     }
0367 
0368     typename as_parser<OpenT>::type::embed_t open;
0369     typename as_parser<CloseT>::type::embed_t close;
0370 };
0371 
0372 ///////////////////////////////////////////////////////////////////////////////
0373 //
0374 //  Predefined nested comment parser generator
0375 //
0376 ///////////////////////////////////////////////////////////////////////////////
0377 
0378 template<typename OpenT, typename CloseT>
0379 struct comment_nest_p_result
0380 {
0381     typedef comment_nest_parser<
0382         typename as_parser<OpenT>::type,
0383         typename as_parser<CloseT>::type
0384     > type;
0385 };
0386 
0387 template<typename OpenT, typename CloseT>
0388 inline typename comment_nest_p_result<OpenT,CloseT>::type 
0389 comment_nest_p(OpenT const &open, CloseT const &close)
0390 {
0391     typedef typename comment_nest_p_result<OpenT,CloseT>::type
0392         result_t;
0393 
0394     return result_t(
0395         as_parser<OpenT>::convert(open),
0396         as_parser<CloseT>::convert(close)
0397     );
0398 }
0399 
0400 ///////////////////////////////////////////////////////////////////////////////
0401 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0402 
0403 }} // namespace BOOST_SPIRIT_CLASSIC_NS
0404 
0405 #endif