liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/*=============================================================================
    Copyright (c) 2001-2003 Joel de Guzman
    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)
=============================================================================*/
#ifndef BOOST_SPIRIT_SYMBOLS_HPP
#define BOOST_SPIRIT_SYMBOLS_HPP
 
///////////////////////////////////////////////////////////////////////////////
#include <string>
 
#include <boost/ref.hpp>
 
#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/core/parser.hpp>
#include <boost/spirit/home/classic/core/composite/directives.hpp>
 
#include <boost/spirit/home/classic/symbols/symbols_fwd.hpp>
 
 
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {
 
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
 
///////////////////////////////////////////////////////////////////////////////
//
//  symbols class
//
//      This class implements a symbol table. The symbol table holds a
//      dictionary of symbols where each symbol is a sequence of CharTs.
//      The template class can work efficiently with 8, 16 and 32 bit
//      characters. Mutable data of type T is associated with each
//      symbol.
//
//      The class is a parser. The parse member function returns
//      additional information in the symbol_match class (see below).
//      The additional data is a pointer to some data associated with
//      the matching symbol.
//
//      The actual set implementation is supplied by the SetT template
//      parameter. By default, this uses the tst class (see tst.ipp).
//
//      Symbols are added into the symbol table statically using the
//      construct:
//
//          sym = a, b, c, d ...;
//
//      where sym is a symbol table and a..d are strings. Example:
//
//          sym = "pineapple", "orange", "banana", "apple";
//
//      Alternatively, symbols may be added dynamically through the
//      member functor 'add' (see symbol_inserter below). The member
//      functor 'add' may be attached to a parser as a semantic action
//      taking in a begin/end pair:
//
//          p[sym.add]
//
//      where p is a parser (and sym is a symbol table). On success,
//      the matching portion of the input is added to the symbol table.
//
//      'add' may also be used to directly initialize data. Examples:
//
//          sym.add("hello", 1)("crazy", 2)("world", 3);
//
///////////////////////////////////////////////////////////////////////////////
template <typename T, typename CharT, typename SetT>
class symbols
:   private SetT
,   public parser<symbols<T, CharT, SetT> >
{
public:
 
    typedef parser<symbols<T, CharT, SetT> > parser_base_t;
    typedef symbols<T, CharT, SetT> self_t;
    typedef self_t const& embed_t;
    typedef T symbol_data_t;
    typedef boost::reference_wrapper<T> symbol_ref_t;
 
    symbols();
    symbols(symbols const& other);
    ~symbols();
 
    symbols&
    operator=(symbols const& other);
 
    symbol_inserter<T, SetT> const&
    operator=(CharT const* str);
 
    template <typename ScannerT>
    struct result
    {
        typedef typename match_result<ScannerT, symbol_ref_t>::type type;
    };
 
    template <typename ScannerT>
    typename parser_result<self_t, ScannerT>::type
    parse_main(ScannerT const& scan) const
    {
        typedef typename ScannerT::iterator_t iterator_t;
        iterator_t first = scan.first;
        typename SetT::search_info result = SetT::find(scan);
 
        if (result.data)
            return scan.
                create_match(
                    result.length,
                    symbol_ref_t(*result.data),
                    first,
                    scan.first);
        else
            return scan.no_match();
    }
 
    template <typename ScannerT>
    typename parser_result<self_t, ScannerT>::type
    parse(ScannerT const& scan) const
    {
        typedef typename parser_result<self_t, ScannerT>::type result_t;
        return impl::implicit_lexeme_parse<result_t>
            (*this, scan, scan);
    }
 
    template < typename ScannerT >
    T* find(ScannerT const& scan) const
    { return SetT::find(scan).data; }
 
    symbol_inserter<T, SetT> const add;
};
 
///////////////////////////////////////////////////////////////////////////////
//
//  Symbol table utilities
//
//  add
//
//      adds a symbol 'sym' (string) to a symbol table 'table' plus an
//      optional data 'data' associated with the symbol. Returns a pointer to
//      the data associated with the symbol or NULL if add failed (e.g. when
//      the symbol is already added before).
//
//  find
//
//      finds a symbol 'sym' (string) from a symbol table 'table'. Returns a
//      pointer to the data associated with the symbol or NULL if not found
//
///////////////////////////////////////////////////////////////////////////////
template <typename T, typename CharT, typename SetT>
T*  add(symbols<T, CharT, SetT>& table, CharT const* sym, T const& data = T());
 
template <typename T, typename CharT, typename SetT>
T*  find(symbols<T, CharT, SetT> const& table, CharT const* sym);
 
///////////////////////////////////////////////////////////////////////////////
//
//  symbol_inserter class
//
//      The symbols class holds an instance of this class named 'add'.
//      This can be called directly just like a member function,
//      passing in a first/last iterator and optional data:
//
//          sym.add(first, last, data);
//
//      Or, passing in a C string and optional data:
//
//          sym.add(c_string, data);
//
//      where sym is a symbol table. The 'data' argument is optional.
//      This may also be used as a semantic action since it conforms
//      to the action interface (see action.hpp):
//
//          p[sym.add]
//
///////////////////////////////////////////////////////////////////////////////
template <typename T, typename SetT>
class symbol_inserter
{
public:
 
    symbol_inserter(SetT& set_)
    : set(set_) {}
 
    typedef symbol_inserter const & result_type;
 
    template <typename IteratorT>
    symbol_inserter const&
    operator()(IteratorT first, IteratorT const& last, T const& data = T()) const
    {
        set.add(first, last, data);
        return *this;
    }
 
    template <typename CharT>
    symbol_inserter const&
    operator()(CharT const* str, T const& data = T()) const
    {
        CharT const* last = str;
        while (*last)
            last++;
        set.add(str, last, data);
        return *this;
    }
 
    template <typename CharT>
    symbol_inserter const&
    operator,(CharT const* str) const
    {
        CharT const* last = str;
        while (*last)
            last++;
        set.add(str, last, T());
        return *this;
    }
 
private:
 
    SetT& set;
};
 
///////////////////////////////////////////////////////////////////////////////
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
 
}} // namespace BOOST_SPIRIT_CLASSIC_NS
 
#include <boost/spirit/home/classic/symbols/impl/symbols.ipp>
#endif