summaryrefslogtreecommitdiff
path: root/boost/spirit/home/qi/nonterminal/debug_handler.hpp
blob: 6a9f5366992b799f1eecc1b8c94338190ffaa867 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*=============================================================================
    Copyright (c) 2001-2011 Joel de Guzman

    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)
==============================================================================*/
#if !defined(BOOST_SPIRIT_DEBUG_HANDLER_DECEMBER_05_2008_0734PM)
#define BOOST_SPIRIT_DEBUG_HANDLER_DECEMBER_05_2008_0734PM

#if defined(_MSC_VER)
#pragma once
#endif

#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/qi/nonterminal/rule.hpp>
#include <boost/spirit/home/qi/nonterminal/debug_handler_state.hpp>
#include <boost/spirit/home/qi/operator/expect.hpp>
#include <boost/function.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/out.hpp>
#include <iostream>

namespace boost { namespace spirit { namespace qi
{
    template <
        typename Iterator, typename Context
      , typename Skipper, typename F>
    struct debug_handler
    {
        typedef function<
            bool(Iterator& first, Iterator const& last
              , Context& context
              , Skipper const& skipper
            )>
        function_type;

        debug_handler(
            function_type subject_
          , F f_
          , std::string const& rule_name_)
          : subject(subject_)
          , f(f_)
          , rule_name(rule_name_)
        {
        }

        bool operator()(
            Iterator& first, Iterator const& last
          , Context& context, Skipper const& skipper) const
        {
            f(first, last, context, pre_parse, rule_name);
            try // subject might throw an exception
            {
                if (subject(first, last, context, skipper))
                {
                    f(first, last, context, successful_parse, rule_name);
                    return true;
                }
                f(first, last, context, failed_parse, rule_name);
            }
            catch (expectation_failure<Iterator> const& e)
            {
                f(first, last, context, failed_parse, rule_name);
                boost::throw_exception(e);
            }
            return false;
        }

        function_type subject;
        F f;
        std::string rule_name;
    };

    template <typename Iterator
      , typename T1, typename T2, typename T3, typename T4, typename F>
    void debug(rule<Iterator, T1, T2, T3, T4>& r, F f)
    {
        typedef rule<Iterator, T1, T2, T3, T4> rule_type;

        typedef
            debug_handler<
                Iterator
              , typename rule_type::context_type
              , typename rule_type::skipper_type
              , F>
        debug_handler;
        r.f = debug_handler(r.f, f, r.name());
    }

    struct simple_trace;

    namespace detail
    {
        // This class provides an extra level of indirection through a
        // template to produce the simple_trace type. This way, the use
        // of simple_trace below is hidden behind a dependent type, so
        // that compilers eagerly type-checking template definitions
        // won't complain that simple_trace is incomplete.
        template<typename T>
        struct get_simple_trace
        {
            typedef simple_trace type;
        };
    }

    template <typename Iterator
      , typename T1, typename T2, typename T3, typename T4>
    void debug(rule<Iterator, T1, T2, T3, T4>& r)
    {
        typedef rule<Iterator, T1, T2, T3, T4> rule_type;

        typedef
            debug_handler<
                Iterator
              , typename rule_type::context_type
              , typename rule_type::skipper_type
              , simple_trace>
        debug_handler;

        typedef typename qi::detail::get_simple_trace<Iterator>::type trace;
        r.f = debug_handler(r.f, trace(), r.name());
    }

}}}

///////////////////////////////////////////////////////////////////////////////
//  Utility macro for easy enabling of rule and grammar debugging
#if !defined(BOOST_SPIRIT_DEBUG_NODE)
  #if defined(BOOST_SPIRIT_DEBUG) || defined(BOOST_SPIRIT_QI_DEBUG)
    #define BOOST_SPIRIT_DEBUG_NODE(r)  r.name(#r); debug(r)
  #else
    #define BOOST_SPIRIT_DEBUG_NODE(r)  r.name(#r)
  #endif
#endif

#define BOOST_SPIRIT_DEBUG_NODE_A(r, _, name)                                   \
    BOOST_SPIRIT_DEBUG_NODE(name);                                              \
    /***/

#define BOOST_SPIRIT_DEBUG_NODES(seq)                                           \
    BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEBUG_NODE_A, _, seq)                    \
    /***/

#endif