Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:45

0001 /*=============================================================================
0002     Copyright (c) 2001-2011 Joel de Guzman
0003 
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 ==============================================================================*/
0007 #if !defined(BOOST_SPIRIT_ERROR_HANDLER_APRIL_29_2007_1042PM)
0008 #define BOOST_SPIRIT_ERROR_HANDLER_APRIL_29_2007_1042PM
0009 
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013 
0014 #include <boost/spirit/home/qi/operator/expect.hpp>
0015 #include <boost/spirit/home/qi/nonterminal/rule.hpp>
0016 #include <boost/spirit/home/support/multi_pass_wrapper.hpp>
0017 #include <boost/function.hpp>
0018 #include <boost/assert.hpp>
0019 
0020 namespace boost { namespace spirit { namespace qi
0021 {
0022     enum error_handler_result
0023     {
0024         fail
0025       , retry
0026       , accept
0027       , rethrow
0028     };
0029 
0030     namespace detail
0031     {
0032         // Helper template allowing to manage the inhibit clear queue flag in
0033         // a multi_pass iterator. This is the usual specialization used for
0034         // anything but a multi_pass iterator.
0035         template <typename Iterator, bool active>
0036         struct reset_on_exit
0037         {
0038             reset_on_exit(Iterator&) {}
0039         };
0040 
0041         // For 'retry' or 'fail' error handlers we need to inhibit the flushing 
0042         // of the internal multi_pass buffers which otherwise might happen at 
0043         // deterministic expectation points inside the encapsulated right hand 
0044         // side of rule.
0045         template <typename Iterator>
0046         struct reset_on_exit<Iterator, true>
0047         {
0048             reset_on_exit(Iterator& it)
0049               : it_(it)
0050               , inhibit_clear_queue_(spirit::traits::inhibit_clear_queue(it)) 
0051             {
0052                 spirit::traits::inhibit_clear_queue(it_, true);
0053             }
0054 
0055             ~reset_on_exit()
0056             {
0057                 // reset inhibit flag in multi_pass on exit
0058                 spirit::traits::inhibit_clear_queue(it_, inhibit_clear_queue_);
0059             }
0060 
0061             Iterator& it_;
0062             bool inhibit_clear_queue_;
0063         };
0064     }
0065 
0066     template <
0067         typename Iterator, typename Context
0068       , typename Skipper, typename F, error_handler_result action
0069     >
0070     struct error_handler
0071     {
0072         typedef function<
0073             bool(Iterator& first, Iterator const& last
0074               , Context& context
0075               , Skipper const& skipper
0076             )>
0077         function_type;
0078 
0079         error_handler(function_type subject_, F f_)
0080           : subject(subject_)
0081           , f(f_)
0082         {
0083         }
0084 
0085         bool operator()(
0086             Iterator& first, Iterator const& last
0087           , Context& context, Skipper const& skipper) const
0088         {
0089             typedef qi::detail::reset_on_exit<Iterator
0090               , traits::is_multi_pass<Iterator>::value && 
0091                   (action == retry || action == fail)> on_exit_type;
0092 
0093             on_exit_type on_exit(first);
0094             for(;;)
0095             {
0096                 try
0097                 {
0098                     Iterator i = first;
0099                     bool r = subject(i, last, context, skipper);
0100                     if (r)
0101                         first = i;
0102                     return r;
0103                 }
0104                 catch (expectation_failure<Iterator> const& x)
0105                 {
0106                     typedef
0107                         fusion::vector<
0108                             Iterator&
0109                           , Iterator const&
0110                           , Iterator const&
0111                           , info const&>
0112                     params;
0113                     error_handler_result r = action;
0114                     params args(first, last, x.first, x.what_);
0115                     f(args, context, r);
0116 
0117                     // The assertions below will fire if you are using a
0118                     // multi_pass as the underlying iterator, one of your error
0119                     // handlers forced its guarded rule to 'fail' or 'retry',
0120                     // and the error handler has not been instantiated using
0121                     // either 'fail' or 'retry' in the first place. Please see 
0122                     // the multi_pass docs for more information.
0123                     switch (r)
0124                     {
0125                         case fail: 
0126                             BOOST_ASSERT(
0127                                 !traits::is_multi_pass<Iterator>::value ||
0128                                     action == retry || action == fail);
0129                             return false;
0130                         case retry: 
0131                             BOOST_ASSERT(
0132                                 !traits::is_multi_pass<Iterator>::value ||
0133                                     action == retry || action == fail);
0134                             continue;
0135                         case accept: return true;
0136                         case rethrow: boost::throw_exception(x);
0137                     }
0138                 }
0139             }
0140             return false;
0141         }
0142 
0143         function_type subject;
0144         F f;
0145     };
0146 
0147     template <
0148         error_handler_result action
0149       , typename Iterator, typename T0, typename T1, typename T2
0150       , typename F>
0151     void on_error(rule<Iterator, T0, T1, T2>& r, F f)
0152     {
0153         typedef rule<Iterator, T0, T1, T2> rule_type;
0154 
0155         typedef
0156             error_handler<
0157                 Iterator
0158               , typename rule_type::context_type
0159               , typename rule_type::skipper_type
0160               , F
0161               , action>
0162         error_handler;
0163         r.f = error_handler(r.f, f);
0164     }
0165 
0166     // Error handling support when <action> is not
0167     // specified. We will default to <fail>.
0168     template <typename Iterator, typename T0, typename T1
0169       , typename T2, typename F>
0170     void on_error(rule<Iterator, T0, T1, T2>& r, F f)
0171     {
0172         on_error<fail>(r, f);
0173     }
0174 }}}
0175 
0176 #endif