source: NonGTP/Boost/boost/spirit/symbols/symbols.hpp @ 857

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