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