• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
parse_main(ScannerT const & scan) const101     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
parse(ScannerT const & scan) const120     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             (*this, scan, scan);
125     }
126 
127     template < typename ScannerT >
find(ScannerT const & scan) const128     T* find(ScannerT const& scan) const
129     { 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 
symbol_inserter(SetT & set_)183     symbol_inserter(SetT& set_)
184     : set(set_) {}
185 
186     typedef symbol_inserter const & result_type;
187 
188     template <typename IteratorT>
189     symbol_inserter const&
operator ()(IteratorT first,IteratorT const & last,T const & data=T ()) const190     operator()(IteratorT first, IteratorT const& last, T const& data = T()) const
191     {
192         set.add(first, last, data);
193         return *this;
194     }
195 
196     template <typename CharT>
197     symbol_inserter const&
operator ()(CharT const * str,T const & data=T ()) const198     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&
operator ,(CharT const * str) const209     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
230