summaryrefslogtreecommitdiffstats
blob: 2f7dd23e801b4d87b0357daa9b8d698fba98a329 (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
146
147
148
149
150
/*=============================================================================
    Copyright (c) 2002-2003 Joel de Guzman
    Copyright (c) 2002-2003 Hartmut Kaiser
    http://spirit.sourceforge.net/

  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_PARSER_CONTEXT_HPP)
#define BOOST_SPIRIT_PARSER_CONTEXT_HPP

///////////////////////////////////////////////////////////////////////////////
namespace boost
{
    namespace spirit
    {
    BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN


    ///////////////////////////////////////////////////////////////////////////
    //
    //  default_parser_context_base class { default context base }
    //
    ///////////////////////////////////////////////////////////////////////////
    struct default_parser_context_base
    {
        template <typename DerivedT>
        struct aux {};
    };

    ///////////////////////////////////////////////////////////////////////////
    //
    //  parser_context_base class { base class of all context classes }
    //
    ///////////////////////////////////////////////////////////////////////////
    struct parser_context_base {};

    ///////////////////////////////////////////////////////////////////////////
    //
    //  parser_context class { default context }
    //
    ///////////////////////////////////////////////////////////////////////////
    struct nil_t;
    template<typename ContextT> struct parser_context_linker;

    template<typename AttrT = nil_t>
    struct parser_context : parser_context_base
    {
        typedef AttrT attr_t;
        typedef default_parser_context_base base_t;
        typedef parser_context_linker<parser_context<AttrT> > context_linker_t;

        template <typename ParserT>
        parser_context(ParserT const&) {}

        template <typename ParserT, typename ScannerT>
        void
        pre_parse(ParserT const&, ScannerT const&) {}

        template <typename ResultT, typename ParserT, typename ScannerT>
        ResultT&
        post_parse(ResultT& hit, ParserT const&, ScannerT const&)
        { return hit; }
    };

    ///////////////////////////////////////////////////////////////////////////
    //
    //  context_aux class
    //
    //      context_aux<ContextT, DerivedT> is a class derived from the
    //      ContextT's nested base_t::base<DerivedT> template class. (see
    //      default_parser_context_base::aux for an example).
    //
    //      Basically, this class provides ContextT dependent optional
    //      functionality to the derived class DerivedT through the CRTP
    //      idiom (Curiously recurring template pattern).
    //
    ///////////////////////////////////////////////////////////////////////////
    template <typename ContextT, typename DerivedT>
    struct context_aux : public ContextT::base_t::template aux<DerivedT> {};

    ///////////////////////////////////////////////////////////////////////////
    //
    //  parser_scanner_linker and parser_scanner_linker classes
    //  { helper templates for the rule extensibility }
    //
    //      This classes can be 'overloaded' (defined elsewhere), to plug
    //      in additional functionality into the non-terminal parsing process.
    //
    ///////////////////////////////////////////////////////////////////////////
    #if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
    #define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED

    template<typename ScannerT>
    struct parser_scanner_linker : public ScannerT
    {
        parser_scanner_linker(ScannerT const scan_) : ScannerT(scan_) {}
    };

    #endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)

    //////////////////////////////////
    #if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
    #define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED

    template<typename ContextT>
    struct parser_context_linker : public ContextT
    {
        template <typename ParserT>
        parser_context_linker(ParserT const& p)
        : ContextT(p) {}

        template <typename ParserT, typename ScannerT>
        void pre_parse(ParserT const& p, ScannerT const& scan)
        { ContextT::pre_parse(p, scan); }

        template <typename ResultT, typename ParserT, typename ScannerT>
        ResultT&
        post_parse(ResultT& hit, ParserT const& p, ScannerT const& scan)
        { return ContextT::post_parse(hit, p, scan); }
    };

    #endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)

    ///////////////////////////////////////////////////////////////////////////
    //
    //  BOOST_SPIRIT_CONTEXT_PARSE helper macro
    //
    //      The original implementation uses a template class. However, we
    //      need to lessen the template instantiation depth to help inferior
    //      compilers that sometimes choke on deep template instantiations.
    //      The objective is to avoid code redundancy. A macro, in this case
    //      is an obvious solution. Sigh!
    //
    //      WARNING: INTERNAL USE ONLY. NOT FOR PUBLIC CONSUMPTION.
    //
    ///////////////////////////////////////////////////////////////////////////
    #define BOOST_SPIRIT_CONTEXT_PARSE(scan, this_, scanner_t, context_t, result_t) \
            scanner_t scan_wrap(scan);                                              \
            context_t context_wrap(this_);                                          \
            context_wrap.pre_parse(this_, scan_wrap);                               \
            result_t hit = parse_main(scan);                                        \
            return context_wrap.post_parse(hit, this_, scan_wrap);

    BOOST_SPIRIT_CLASSIC_NAMESPACE_END

    } // namespace spirit
} // namespace boost

#endif