sl@0
|
1 |
/*=============================================================================
|
sl@0
|
2 |
Copyright (c) 2001-2003 Joel de Guzman
|
sl@0
|
3 |
http://spirit.sourceforge.net/
|
sl@0
|
4 |
|
sl@0
|
5 |
Use, modification and distribution is subject to the Boost Software
|
sl@0
|
6 |
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
sl@0
|
7 |
http://www.boost.org/LICENSE_1_0.txt)
|
sl@0
|
8 |
=============================================================================*/
|
sl@0
|
9 |
#ifndef BOOST_SPIRIT_SYMBOLS_HPP
|
sl@0
|
10 |
#define BOOST_SPIRIT_SYMBOLS_HPP
|
sl@0
|
11 |
|
sl@0
|
12 |
///////////////////////////////////////////////////////////////////////////////
|
sl@0
|
13 |
#include <string>
|
sl@0
|
14 |
|
sl@0
|
15 |
#include <boost/ref.hpp>
|
sl@0
|
16 |
|
sl@0
|
17 |
#include <boost/spirit/core/parser.hpp>
|
sl@0
|
18 |
#include <boost/spirit/core/composite/directives.hpp>
|
sl@0
|
19 |
|
sl@0
|
20 |
#include <boost/spirit/symbols/symbols_fwd.hpp>
|
sl@0
|
21 |
|
sl@0
|
22 |
|
sl@0
|
23 |
///////////////////////////////////////////////////////////////////////////////
|
sl@0
|
24 |
namespace boost { namespace spirit {
|
sl@0
|
25 |
|
sl@0
|
26 |
///////////////////////////////////////////////////////////////////////////////
|
sl@0
|
27 |
//
|
sl@0
|
28 |
// symbols class
|
sl@0
|
29 |
//
|
sl@0
|
30 |
// This class implements a symbol table. The symbol table holds a
|
sl@0
|
31 |
// dictionary of symbols where each symbol is a sequence of CharTs.
|
sl@0
|
32 |
// The template class can work efficiently with 8, 16 and 32 bit
|
sl@0
|
33 |
// characters. Mutable data of type T is associated with each
|
sl@0
|
34 |
// symbol.
|
sl@0
|
35 |
//
|
sl@0
|
36 |
// The class is a parser. The parse member function returns
|
sl@0
|
37 |
// additional information in the symbol_match class (see below).
|
sl@0
|
38 |
// The additional data is a pointer to some data associated with
|
sl@0
|
39 |
// the matching symbol.
|
sl@0
|
40 |
//
|
sl@0
|
41 |
// The actual set implementation is supplied by the SetT template
|
sl@0
|
42 |
// parameter. By default, this uses the tst class (see tst.ipp).
|
sl@0
|
43 |
//
|
sl@0
|
44 |
// Symbols are added into the symbol table statically using the
|
sl@0
|
45 |
// construct:
|
sl@0
|
46 |
//
|
sl@0
|
47 |
// sym = a, b, c, d ...;
|
sl@0
|
48 |
//
|
sl@0
|
49 |
// where sym is a symbol table and a..d are strings. Example:
|
sl@0
|
50 |
//
|
sl@0
|
51 |
// sym = "pineapple", "orange", "banana", "apple";
|
sl@0
|
52 |
//
|
sl@0
|
53 |
// Alternatively, symbols may be added dynamically through the
|
sl@0
|
54 |
// member functor 'add' (see symbol_inserter below). The member
|
sl@0
|
55 |
// functor 'add' may be attached to a parser as a semantic action
|
sl@0
|
56 |
// taking in a begin/end pair:
|
sl@0
|
57 |
//
|
sl@0
|
58 |
// p[sym.add]
|
sl@0
|
59 |
//
|
sl@0
|
60 |
// where p is a parser (and sym is a symbol table). On success,
|
sl@0
|
61 |
// the matching portion of the input is added to the symbol table.
|
sl@0
|
62 |
//
|
sl@0
|
63 |
// 'add' may also be used to directly initialize data. Examples:
|
sl@0
|
64 |
//
|
sl@0
|
65 |
// sym.add("hello", 1)("crazy", 2)("world", 3);
|
sl@0
|
66 |
//
|
sl@0
|
67 |
///////////////////////////////////////////////////////////////////////////////
|
sl@0
|
68 |
template <typename T, typename CharT, typename SetT>
|
sl@0
|
69 |
class symbols
|
sl@0
|
70 |
: private SetT
|
sl@0
|
71 |
, public parser<symbols<T, CharT, SetT> >
|
sl@0
|
72 |
{
|
sl@0
|
73 |
public:
|
sl@0
|
74 |
|
sl@0
|
75 |
typedef parser<symbols<T, CharT, SetT> > parser_base_t;
|
sl@0
|
76 |
typedef symbols<T, CharT, SetT> self_t;
|
sl@0
|
77 |
typedef self_t const& embed_t;
|
sl@0
|
78 |
typedef T symbol_data_t;
|
sl@0
|
79 |
typedef boost::reference_wrapper<T> symbol_ref_t;
|
sl@0
|
80 |
|
sl@0
|
81 |
symbols();
|
sl@0
|
82 |
symbols(symbols const& other);
|
sl@0
|
83 |
~symbols();
|
sl@0
|
84 |
|
sl@0
|
85 |
symbols&
|
sl@0
|
86 |
operator=(symbols const& other);
|
sl@0
|
87 |
|
sl@0
|
88 |
symbol_inserter<T, SetT> const&
|
sl@0
|
89 |
operator=(CharT const* str);
|
sl@0
|
90 |
|
sl@0
|
91 |
template <typename ScannerT>
|
sl@0
|
92 |
struct result
|
sl@0
|
93 |
{
|
sl@0
|
94 |
typedef typename match_result<ScannerT, symbol_ref_t>::type type;
|
sl@0
|
95 |
};
|
sl@0
|
96 |
|
sl@0
|
97 |
template <typename ScannerT>
|
sl@0
|
98 |
typename parser_result<self_t, ScannerT>::type
|
sl@0
|
99 |
parse_main(ScannerT const& scan) const
|
sl@0
|
100 |
{
|
sl@0
|
101 |
typedef typename ScannerT::iterator_t iterator_t;
|
sl@0
|
102 |
iterator_t first = scan.first;
|
sl@0
|
103 |
typename SetT::search_info result = SetT::find(scan);
|
sl@0
|
104 |
|
sl@0
|
105 |
if (result.data)
|
sl@0
|
106 |
return scan.
|
sl@0
|
107 |
create_match(
|
sl@0
|
108 |
result.length,
|
sl@0
|
109 |
symbol_ref_t(*result.data),
|
sl@0
|
110 |
first,
|
sl@0
|
111 |
scan.first);
|
sl@0
|
112 |
else
|
sl@0
|
113 |
return scan.no_match();
|
sl@0
|
114 |
}
|
sl@0
|
115 |
|
sl@0
|
116 |
template <typename ScannerT>
|
sl@0
|
117 |
typename parser_result<self_t, ScannerT>::type
|
sl@0
|
118 |
parse(ScannerT const& scan) const
|
sl@0
|
119 |
{
|
sl@0
|
120 |
typedef typename parser_result<self_t, ScannerT>::type result_t;
|
sl@0
|
121 |
return impl::implicit_lexeme_parse<result_t>
|
sl@0
|
122 |
(*this, scan, scan);
|
sl@0
|
123 |
}
|
sl@0
|
124 |
|
sl@0
|
125 |
template < typename ScannerT >
|
sl@0
|
126 |
T* find(ScannerT const& scan) const
|
sl@0
|
127 |
{ return SetT::find(scan).data; }
|
sl@0
|
128 |
|
sl@0
|
129 |
symbol_inserter<T, SetT> const add;
|
sl@0
|
130 |
};
|
sl@0
|
131 |
|
sl@0
|
132 |
///////////////////////////////////////////////////////////////////////////////
|
sl@0
|
133 |
//
|
sl@0
|
134 |
// Symbol table utilities
|
sl@0
|
135 |
//
|
sl@0
|
136 |
// add
|
sl@0
|
137 |
//
|
sl@0
|
138 |
// adds a symbol 'sym' (string) to a symbol table 'table' plus an
|
sl@0
|
139 |
// optional data 'data' associated with the symbol. Returns a pointer to
|
sl@0
|
140 |
// the data associated with the symbol or NULL if add failed (e.g. when
|
sl@0
|
141 |
// the symbol is already added before).
|
sl@0
|
142 |
//
|
sl@0
|
143 |
// find
|
sl@0
|
144 |
//
|
sl@0
|
145 |
// finds a symbol 'sym' (string) from a symbol table 'table'. Returns a
|
sl@0
|
146 |
// pointer to the data associated with the symbol or NULL if not found
|
sl@0
|
147 |
//
|
sl@0
|
148 |
///////////////////////////////////////////////////////////////////////////////
|
sl@0
|
149 |
template <typename T, typename CharT, typename SetT>
|
sl@0
|
150 |
T* add(symbols<T, CharT, SetT>& table, CharT const* sym, T const& data = T());
|
sl@0
|
151 |
|
sl@0
|
152 |
template <typename T, typename CharT, typename SetT>
|
sl@0
|
153 |
T* find(symbols<T, CharT, SetT> const& table, CharT const* sym);
|
sl@0
|
154 |
|
sl@0
|
155 |
///////////////////////////////////////////////////////////////////////////////
|
sl@0
|
156 |
//
|
sl@0
|
157 |
// symbol_inserter class
|
sl@0
|
158 |
//
|
sl@0
|
159 |
// The symbols class holds an instance of this class named 'add'.
|
sl@0
|
160 |
// This can be called directly just like a member function,
|
sl@0
|
161 |
// passing in a first/last iterator and optional data:
|
sl@0
|
162 |
//
|
sl@0
|
163 |
// sym.add(first, last, data);
|
sl@0
|
164 |
//
|
sl@0
|
165 |
// Or, passing in a C string and optional data:
|
sl@0
|
166 |
//
|
sl@0
|
167 |
// sym.add(c_string, data);
|
sl@0
|
168 |
//
|
sl@0
|
169 |
// where sym is a symbol table. The 'data' argument is optional.
|
sl@0
|
170 |
// This may also be used as a semantic action since it conforms
|
sl@0
|
171 |
// to the action interface (see action.hpp):
|
sl@0
|
172 |
//
|
sl@0
|
173 |
// p[sym.add]
|
sl@0
|
174 |
//
|
sl@0
|
175 |
///////////////////////////////////////////////////////////////////////////////
|
sl@0
|
176 |
template <typename T, typename SetT>
|
sl@0
|
177 |
class symbol_inserter
|
sl@0
|
178 |
{
|
sl@0
|
179 |
public:
|
sl@0
|
180 |
|
sl@0
|
181 |
symbol_inserter(SetT& set_)
|
sl@0
|
182 |
: set(set_) {}
|
sl@0
|
183 |
|
sl@0
|
184 |
typedef symbol_inserter const & result_type;
|
sl@0
|
185 |
|
sl@0
|
186 |
template <typename IteratorT>
|
sl@0
|
187 |
symbol_inserter const&
|
sl@0
|
188 |
operator()(IteratorT first, IteratorT const& last, T const& data = T()) const
|
sl@0
|
189 |
{
|
sl@0
|
190 |
set.add(first, last, data);
|
sl@0
|
191 |
return *this;
|
sl@0
|
192 |
}
|
sl@0
|
193 |
|
sl@0
|
194 |
template <typename CharT>
|
sl@0
|
195 |
symbol_inserter const&
|
sl@0
|
196 |
operator()(CharT const* str, T const& data = T()) const
|
sl@0
|
197 |
{
|
sl@0
|
198 |
CharT const* last = str;
|
sl@0
|
199 |
while (*last)
|
sl@0
|
200 |
last++;
|
sl@0
|
201 |
set.add(str, last, data);
|
sl@0
|
202 |
return *this;
|
sl@0
|
203 |
}
|
sl@0
|
204 |
|
sl@0
|
205 |
template <typename CharT>
|
sl@0
|
206 |
symbol_inserter const&
|
sl@0
|
207 |
operator,(CharT const* str) const
|
sl@0
|
208 |
{
|
sl@0
|
209 |
CharT const* last = str;
|
sl@0
|
210 |
while (*last)
|
sl@0
|
211 |
last++;
|
sl@0
|
212 |
set.add(str, last, T());
|
sl@0
|
213 |
return *this;
|
sl@0
|
214 |
}
|
sl@0
|
215 |
|
sl@0
|
216 |
private:
|
sl@0
|
217 |
|
sl@0
|
218 |
SetT& set;
|
sl@0
|
219 |
};
|
sl@0
|
220 |
|
sl@0
|
221 |
///////////////////////////////////////////////////////////////////////////////
|
sl@0
|
222 |
}} // namespace boost::spirit
|
sl@0
|
223 |
|
sl@0
|
224 |
#include <boost/spirit/symbols/impl/symbols.ipp>
|
sl@0
|
225 |
#endif
|