PageRenderTime 27ms CodeModel.GetById 16ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/qi/nonterminal/error_handler.hpp

http://hadesmem.googlecode.com/
C++ Header | 176 lines | 137 code | 17 blank | 22 comment | 13 complexity | 98551f801e04c2b052cc2d3ffbf79c01 MD5 | raw file
  1/*=============================================================================
  2    Copyright (c) 2001-2011 Joel de Guzman
  3
  4    Distributed under the Boost Software License, Version 1.0. (See accompanying
  5    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6==============================================================================*/
  7#if !defined(BOOST_SPIRIT_ERROR_HANDLER_APRIL_29_2007_1042PM)
  8#define BOOST_SPIRIT_ERROR_HANDLER_APRIL_29_2007_1042PM
  9
 10#if defined(_MSC_VER)
 11#pragma once
 12#endif
 13
 14#include <boost/spirit/home/qi/operator/expect.hpp>
 15#include <boost/spirit/home/qi/nonterminal/rule.hpp>
 16#include <boost/spirit/home/support/multi_pass_wrapper.hpp>
 17#include <boost/function.hpp>
 18#include <boost/assert.hpp>
 19
 20namespace boost { namespace spirit { namespace qi
 21{
 22    enum error_handler_result
 23    {
 24        fail
 25      , retry
 26      , accept
 27      , rethrow
 28    };
 29
 30    namespace detail
 31    {
 32        // Helper template allowing to manage the inhibit clear queue flag in
 33        // a multi_pass iterator. This is the usual specialization used for
 34        // anything but a multi_pass iterator.
 35        template <typename Iterator, bool active>
 36        struct reset_on_exit
 37        {
 38            reset_on_exit(Iterator&) {}
 39        };
 40
 41        // For 'retry' or 'fail' error handlers we need to inhibit the flushing 
 42        // of the internal multi_pass buffers which otherwise might happen at 
 43        // deterministic expectation points inside the encapsulated right hand 
 44        // side of rule.
 45        template <typename Iterator>
 46        struct reset_on_exit<Iterator, true>
 47        {
 48            reset_on_exit(Iterator& it)
 49              : it_(it)
 50              , inhibit_clear_queue_(spirit::traits::inhibit_clear_queue(it)) 
 51            {
 52                spirit::traits::inhibit_clear_queue(it_, true);
 53            }
 54
 55            ~reset_on_exit()
 56            {
 57                // reset inhibit flag in multi_pass on exit
 58                spirit::traits::inhibit_clear_queue(it_, inhibit_clear_queue_);
 59            }
 60
 61            Iterator& it_;
 62            bool inhibit_clear_queue_;
 63        };
 64    }
 65
 66    template <
 67        typename Iterator, typename Context
 68      , typename Skipper, typename F, error_handler_result action
 69    >
 70    struct error_handler
 71    {
 72        typedef function<
 73            bool(Iterator& first, Iterator const& last
 74              , Context& context
 75              , Skipper const& skipper
 76            )>
 77        function_type;
 78
 79        error_handler(function_type subject, F f)
 80          : subject(subject)
 81          , f(f)
 82        {
 83        }
 84
 85        bool operator()(
 86            Iterator& first, Iterator const& last
 87          , Context& context, Skipper const& skipper) const
 88        {
 89            typedef qi::detail::reset_on_exit<Iterator
 90              , traits::is_multi_pass<Iterator>::value && 
 91                  (action == retry || action == fail)> on_exit_type;
 92
 93            on_exit_type on_exit(first);
 94            for(;;)
 95            {
 96                try
 97                {
 98                    Iterator i = first;
 99                    bool r = subject(i, last, context, skipper);
100                    if (r)
101                        first = i;
102                    return r;
103                }
104                catch (expectation_failure<Iterator> const& x)
105                {
106                    typedef
107                        fusion::vector<
108                            Iterator&
109                          , Iterator const&
110                          , Iterator const&
111                          , info const&>
112                    params;
113                    error_handler_result r = action;
114                    params args(first, last, x.first, x.what_);
115                    f(args, context, r);
116
117                    // The assertions below will fire if you are using a
118                    // multi_pass as the underlying iterator, one of your error
119                    // handlers forced its guarded rule to 'fail' or 'retry',
120                    // and the error handler has not been instantiated using
121                    // either 'fail' or 'retry' in the first place. Please see 
122                    // the multi_pass docs for more information.
123                    switch (r)
124                    {
125                        case fail: 
126                            BOOST_ASSERT(
127                                !traits::is_multi_pass<Iterator>::value ||
128                                    action == retry || action == fail);
129                            return false;
130                        case retry: 
131                            BOOST_ASSERT(
132                                !traits::is_multi_pass<Iterator>::value ||
133                                    action == retry || action == fail);
134                            continue;
135                        case accept: return true;
136                        case rethrow: boost::throw_exception(x);
137                    }
138                }
139            }
140            return false;
141        }
142
143        function_type subject;
144        F f;
145    };
146
147    template <
148        error_handler_result action
149      , typename Iterator, typename T0, typename T1, typename T2
150      , typename F>
151    void on_error(rule<Iterator, T0, T1, T2>& r, F f)
152    {
153        typedef rule<Iterator, T0, T1, T2> rule_type;
154
155        typedef
156            error_handler<
157                Iterator
158              , typename rule_type::context_type
159              , typename rule_type::skipper_type
160              , F
161              , action>
162        error_handler;
163        r.f = error_handler(r.f, f);
164    }
165
166    // Error handling support when <action> is not
167    // specified. We will default to <fail>.
168    template <typename Iterator, typename T0, typename T1
169      , typename T2, typename F>
170    void on_error(rule<Iterator, T0, T1, T2>& r, F f)
171    {
172        on_error<fail>(r, f);
173    }
174}}}
175
176#endif