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