Merge in updates to all docs/etc.
[m6w6/libmemcached] / libmemcached / options / parser.yy
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * Libmemcached Scanner and Parser
4 *
5 * Copyright (C) 2011 DataDifferental, http://datadifferential.com
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 %error-verbose
22 %debug
23 %defines
24 %expect 0
25 %output "libmemcached/options/parser.cc"
26 %defines "libmemcached/options/parser.h"
27 %lex-param { yyscan_t *scanner }
28 %name-prefix="config_"
29 %parse-param { Context *context }
30 %parse-param { yyscan_t *scanner }
31 %pure-parser
32 %require "2.2"
33 %start begin
34 %verbose
35
36 %{
37
38 #include <config.h>
39
40 #include <stdint.h>
41
42 #include <libmemcached/options/context.h>
43 #include <libmemcached/options/string.h>
44 #include <libmemcached/options/symbol.h>
45 #include <libmemcached/visibility.h>
46 #include <libmemcached/prefix_key.h>
47
48 #pragma GCC diagnostic ignored "-Wold-style-cast"
49 #include <libmemcached/options/scanner.h>
50
51 int conf_lex(YYSTYPE* lvalp, void* scanner);
52
53 #define parser_abort(A, B) do { (A)->abort((B)); YYABORT; } while (0)
54
55 inline void config_error(Context *context, yyscan_t *scanner, const char *error)
56 {
57 if (not context->end())
58 context->abort(error);
59 }
60
61 %}
62
63 %token COMMENT
64 %token END
65 %token ERROR
66 %token RESET
67 %token PARSER_DEBUG
68 %token INCLUDE
69 %token CONFIGURE_FILE
70 %token EMPTY_LINE
71 %token SERVER
72 %token SERVERS
73 %token SERVERS_OPTION
74 %token UNKNOWN_OPTION
75 %token UNKNOWN
76
77 /* All behavior options */
78 %token BINARY_PROTOCOL
79 %token BUFFER_REQUESTS
80 %token CONNECT_TIMEOUT
81 %token DISTRIBUTION
82 %token HASH
83 %token HASH_WITH_NAMESPACE
84 %token IO_BYTES_WATERMARK
85 %token IO_KEY_PREFETCH
86 %token IO_MSG_WATERMARK
87 %token KETAMA_HASH
88 %token KETAMA_WEIGHTED
89 %token NOREPLY
90 %token NUMBER_OF_REPLICAS
91 %token POLL_TIMEOUT
92 %token RANDOMIZE_REPLICA_READ
93 %token RCV_TIMEOUT
94 %token REMOVE_FAILED_SERVERS
95 %token RETRY_TIMEOUT
96 %token SND_TIMEOUT
97 %token SOCKET_RECV_SIZE
98 %token SOCKET_SEND_SIZE
99 %token SORT_HOSTS
100 %token SUPPORT_CAS
101 %token USER_DATA
102 %token USE_UDP
103 %token VERIFY_KEY
104 %token _TCP_KEEPALIVE
105 %token _TCP_KEEPIDLE
106 %token _TCP_NODELAY
107
108 /* Callbacks */
109 %token NAMESPACE
110
111 /* Pool */
112 %token POOL_MIN
113 %token POOL_MAX
114
115 /* Hash types */
116 %token MD5
117 %token CRC
118 %token FNV1_64
119 %token FNV1A_64
120 %token FNV1_32
121 %token FNV1A_32
122 %token HSIEH
123 %token MURMUR
124 %token JENKINS
125
126 /* Distributions */
127 %token CONSISTENT
128 %token MODULA
129 %token RANDOM
130
131 /* Boolean values */
132 %token <boolean> TRUE
133 %token <boolean> FALSE
134
135 %nonassoc ','
136 %nonassoc '='
137
138 %token <number> FLOAT
139 %token <number> NUMBER
140 %token PORT
141 %token WEIGHT_START
142 %token <server> IPADDRESS
143 %token <server> HOSTNAME
144 %token <string> STRING
145 %token <string> QUOTED_STRING
146 %token <string> FILE_PATH
147
148 %type <string> string
149 %type <distribution> distribution
150 %type <hash> hash
151 %type <behavior> behavior_boolean
152 %type <behavior> behavior_number
153
154 %%
155
156 begin:
157 statement
158 | begin ' ' statement
159 ;
160
161 statement:
162 expression
163 { }
164 | COMMENT
165 { }
166 | EMPTY_LINE
167 { }
168 | END
169 {
170 context->set_end();
171 YYACCEPT;
172 }
173 | ERROR
174 {
175 context->rc= MEMCACHED_PARSE_USER_ERROR;
176 parser_abort(context, NULL);
177 }
178 | RESET
179 {
180 memcached_reset(context->memc);
181 }
182 | PARSER_DEBUG
183 {
184 yydebug= 1;
185 }
186 | INCLUDE ' ' string
187 {
188 if ((context->rc= memcached_parse_configure_file(context->memc, $3.c_str, $3.length)) != MEMCACHED_SUCCESS)
189 {
190 parser_abort(context, NULL);
191 }
192 }
193 ;
194
195
196 expression:
197 SERVER HOSTNAME optional_port optional_weight
198 {
199 if ((context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $2.port, $2.weight)) != MEMCACHED_SUCCESS)
200 {
201 parser_abort(context, NULL);
202 }
203 context->unset_server();
204 }
205 | SERVER IPADDRESS optional_port optional_weight
206 {
207 if ((context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $2.port, $2.weight)) != MEMCACHED_SUCCESS)
208 {
209 parser_abort(context, NULL);
210 }
211 context->unset_server();
212 }
213 | CONFIGURE_FILE string
214 {
215 memcached_set_configuration_file(context->memc, $2.c_str, $2.length);
216 }
217 | POOL_MIN NUMBER
218 {
219 context->memc->configure.initial_pool_size= $2;
220 }
221 | POOL_MAX NUMBER
222 {
223 context->memc->configure.max_pool_size= $2;
224 }
225 | behaviors
226 ;
227
228 behaviors:
229 NAMESPACE string
230 {
231 if ((context->rc= memcached_set_prefix_key(context->memc, $2.c_str, $2.length)) != MEMCACHED_SUCCESS)
232 {
233 parser_abort(context, NULL);;
234 }
235 }
236 | DISTRIBUTION distribution
237 {
238 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
239 {
240 parser_abort(context, NULL);;
241 }
242 }
243 | DISTRIBUTION distribution ',' hash
244 {
245 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
246 {
247 parser_abort(context, NULL);;
248 }
249 if ((context->rc= memcached_behavior_set_distribution_hash(context->memc, $4)) != MEMCACHED_SUCCESS)
250 {
251 parser_abort(context, NULL);;
252 }
253 }
254 | HASH hash
255 {
256 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_HASH, $2)) != MEMCACHED_SUCCESS)
257 {
258 parser_abort(context, NULL);;
259 }
260 }
261 | behavior_number NUMBER
262 {
263 if ((context->rc= memcached_behavior_set(context->memc, $1, $2)) != MEMCACHED_SUCCESS)
264 {
265 parser_abort(context, NULL);;
266 }
267 }
268 | behavior_boolean
269 {
270 if ((context->rc= memcached_behavior_set(context->memc, $1, true)) != MEMCACHED_SUCCESS)
271 {
272 parser_abort(context, NULL);;
273 }
274 }
275 | USER_DATA
276 {
277 }
278 ;
279
280 behavior_number:
281 REMOVE_FAILED_SERVERS
282 {
283 $$= MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS;
284 }
285 | CONNECT_TIMEOUT
286 {
287 $$= MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT;
288 }
289 | IO_MSG_WATERMARK
290 {
291 $$= MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK;
292 }
293 | IO_BYTES_WATERMARK
294 {
295 $$= MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK;
296 }
297 | IO_KEY_PREFETCH
298 {
299 $$= MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH;
300 }
301 | NUMBER_OF_REPLICAS
302 {
303 $$= MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS;
304 }
305 | POLL_TIMEOUT
306 {
307 $$= MEMCACHED_BEHAVIOR_POLL_TIMEOUT;
308 }
309 | RCV_TIMEOUT
310 {
311 $$= MEMCACHED_BEHAVIOR_RCV_TIMEOUT;
312 }
313 | RETRY_TIMEOUT
314 {
315 $$= MEMCACHED_BEHAVIOR_RETRY_TIMEOUT;
316 }
317 | SND_TIMEOUT
318 {
319 $$= MEMCACHED_BEHAVIOR_SND_TIMEOUT;
320 }
321 | SOCKET_RECV_SIZE
322 {
323 $$= MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE;
324 }
325 | SOCKET_SEND_SIZE
326 {
327 $$= MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE;
328 }
329 ;
330
331 behavior_boolean:
332 BINARY_PROTOCOL
333 {
334 $$= MEMCACHED_BEHAVIOR_BINARY_PROTOCOL;
335 }
336 | BUFFER_REQUESTS
337 {
338 $$= MEMCACHED_BEHAVIOR_BUFFER_REQUESTS;
339 }
340 | HASH_WITH_NAMESPACE
341 {
342 $$= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY;
343 }
344 | NOREPLY
345 {
346 $$= MEMCACHED_BEHAVIOR_NOREPLY;
347 }
348 | RANDOMIZE_REPLICA_READ
349 {
350 $$= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ;
351 }
352 | SORT_HOSTS
353 {
354 $$= MEMCACHED_BEHAVIOR_SORT_HOSTS;
355 }
356 | SUPPORT_CAS
357 {
358 $$= MEMCACHED_BEHAVIOR_SUPPORT_CAS;
359 }
360 | _TCP_NODELAY
361 {
362 $$= MEMCACHED_BEHAVIOR_TCP_NODELAY;
363 }
364 | _TCP_KEEPALIVE
365 {
366 $$= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE;
367 }
368 | _TCP_KEEPIDLE
369 {
370 $$= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE;
371 }
372 | USE_UDP
373 {
374 $$= MEMCACHED_BEHAVIOR_USE_UDP;
375 }
376 | VERIFY_KEY
377 {
378 $$= MEMCACHED_BEHAVIOR_VERIFY_KEY;
379 }
380
381
382 optional_port:
383 { }
384 | PORT
385 { };
386 ;
387
388 optional_weight:
389 { }
390 | WEIGHT_START
391 { }
392 ;
393
394 hash:
395 MD5
396 {
397 $$= MEMCACHED_HASH_MD5;
398 }
399 | CRC
400 {
401 $$= MEMCACHED_HASH_CRC;
402 }
403 | FNV1_64
404 {
405 $$= MEMCACHED_HASH_FNV1_64;
406 }
407 | FNV1A_64
408 {
409 $$= MEMCACHED_HASH_FNV1A_64;
410 }
411 | FNV1_32
412 {
413 $$= MEMCACHED_HASH_FNV1_32;
414 }
415 | FNV1A_32
416 {
417 $$= MEMCACHED_HASH_FNV1A_32;
418 }
419 | HSIEH
420 {
421 $$= MEMCACHED_HASH_HSIEH;
422 }
423 | MURMUR
424 {
425 $$= MEMCACHED_HASH_MURMUR;
426 }
427 | JENKINS
428 {
429 $$= MEMCACHED_HASH_JENKINS;
430 }
431 ;
432
433 string:
434 STRING
435 {
436 $$= $1;
437 }
438 | QUOTED_STRING
439 {
440 $$.c_str= $1.c_str +1; // +1 to move use passed the initial quote
441 $$.length= $1.length -1; // -1 removes the end quote
442 }
443 ;
444
445 distribution:
446 CONSISTENT
447 {
448 $$= MEMCACHED_DISTRIBUTION_CONSISTENT;
449 }
450 | MODULA
451 {
452 $$= MEMCACHED_DISTRIBUTION_MODULA;
453 }
454 | RANDOM
455 {
456 $$= MEMCACHED_DISTRIBUTION_RANDOM;
457 }
458 ;
459
460 %%
461
462 void Context::start()
463 {
464 config_parse(this, (void **)scanner);
465 }
466