dd9c720b9631009f2ac0277eb51c2f2fdc7ae2ff
[m6w6/libmemcached] / libmemcached / csl / parser.yy
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * Libmemcached library
4 *
5 * Copyright (C) 2012 Data Differential, http://datadifferential.com/
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * * The names of its contributors may not be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37 %{
38
39 #include <libmemcached/csl/common.h>
40
41 class Context;
42
43 %}
44
45 %error-verbose
46 %debug
47 %defines
48 %expect 0
49 %output "libmemcached/csl/parser.cc"
50 %defines "libmemcached/csl/parser.h"
51 %lex-param { yyscan_t *scanner }
52 %name-prefix="config_"
53 %parse-param { class Context *context }
54 %parse-param { yyscan_t *scanner }
55 %pure-parser
56 %require "2.5"
57 %start begin
58 %verbose
59
60 %{
61
62 #include <libmemcached/options.hpp>
63
64 #include <libmemcached/csl/context.h>
65 #include <libmemcached/csl/symbol.h>
66 #include <libmemcached/csl/scanner.h>
67
68 #ifndef __INTEL_COMPILER
69 # pragma GCC diagnostic ignored "-Wold-style-cast"
70 #endif
71
72 #ifndef __INTEL_COMPILER
73 # ifndef __clang__
74 # pragma GCC diagnostic ignored "-Wlogical-op"
75 # pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
76 # endif
77 #endif
78
79 int conf_lex(YYSTYPE* lvalp, void* scanner);
80
81 #define select_yychar(__context) yychar == UNKNOWN ? ( (__context)->previous_token == END ? UNKNOWN : (__context)->previous_token ) : yychar
82
83 #define stryytname(__yytokentype) ((__yytokentype) < YYNTOKENS ) ? yytname[(__yytokentype)] : ""
84
85 #define parser_abort(__context, __error_message) do { (__context)->abort((__error_message), yytokentype(select_yychar(__context)), stryytname(YYTRANSLATE(select_yychar(__context)))); YYABORT; } while (0)
86
87 // This is bison calling error.
88 inline void __config_error(Context *context, yyscan_t *scanner, const char *error, int last_token, const char *last_token_str)
89 {
90 if (not context->end())
91 {
92 context->error(error, yytokentype(last_token), last_token_str);
93 }
94 else
95 {
96 context->error(error, yytokentype(last_token), last_token_str);
97 }
98 }
99
100 #define config_error(__context, __scanner, __error_msg) do { __config_error((__context), (__scanner), (__error_msg), select_yychar(__context), stryytname(YYTRANSLATE(select_yychar(__context)))); } while (0)
101
102
103 %}
104
105 %token COMMENT
106 %token END
107 %token CSL_ERROR
108 %token RESET
109 %token PARSER_DEBUG
110 %token INCLUDE
111 %token CONFIGURE_FILE
112 %token EMPTY_LINE
113 %token SERVER
114 %token CSL_SOCKET
115 %token SERVERS
116 %token SERVERS_OPTION
117 %token UNKNOWN_OPTION
118 %token UNKNOWN
119
120 /* All behavior options */
121 %token BINARY_PROTOCOL
122 %token BUFFER_REQUESTS
123 %token CONNECT_TIMEOUT
124 %token DISTRIBUTION
125 %token HASH
126 %token HASH_WITH_NAMESPACE
127 %token IO_BYTES_WATERMARK
128 %token IO_KEY_PREFETCH
129 %token IO_MSG_WATERMARK
130 %token KETAMA_HASH
131 %token KETAMA_WEIGHTED
132 %token NOREPLY
133 %token NUMBER_OF_REPLICAS
134 %token POLL_TIMEOUT
135 %token RANDOMIZE_REPLICA_READ
136 %token RCV_TIMEOUT
137 %token REMOVE_FAILED_SERVERS
138 %token RETRY_TIMEOUT
139 %token SND_TIMEOUT
140 %token SOCKET_RECV_SIZE
141 %token SOCKET_SEND_SIZE
142 %token SORT_HOSTS
143 %token SUPPORT_CAS
144 %token USER_DATA
145 %token USE_UDP
146 %token VERIFY_KEY
147 %token _TCP_KEEPALIVE
148 %token _TCP_KEEPIDLE
149 %token _TCP_NODELAY
150 %token FETCH_VERSION
151
152 /* Callbacks */
153 %token NAMESPACE
154
155 /* Pool */
156 %token POOL_MIN
157 %token POOL_MAX
158
159 /* Hash types */
160 %token MD5
161 %token CRC
162 %token FNV1_64
163 %token FNV1A_64
164 %token FNV1_32
165 %token FNV1A_32
166 %token HSIEH
167 %token MURMUR
168 %token JENKINS
169
170 /* Distributions */
171 %token CONSISTENT
172 %token MODULA
173 %token RANDOM
174
175 /* Boolean values */
176 %token <boolean> CSL_TRUE
177 %token <boolean> CSL_FALSE
178
179 %nonassoc ','
180 %nonassoc '='
181
182 %token <number> CSL_FLOAT
183 %token <number> NUMBER
184 %token <number> PORT
185 %token <number> WEIGHT_START
186 %token <server> IPADDRESS
187 %token <server> HOSTNAME
188 %token <string> STRING
189 %token <string> QUOTED_STRING
190 %token <string> FILE_PATH
191
192 %type <behavior> behavior_boolean
193 %type <behavior> behavior_number
194 %type <distribution> distribution
195 %type <hash> hash
196 %type <number> optional_port
197 %type <number> optional_weight
198 %type <string> string
199
200 %%
201
202 begin:
203 statement
204 | begin ' ' statement
205 ;
206
207 statement:
208 expression
209 { }
210 | COMMENT
211 { }
212 | EMPTY_LINE
213 { }
214 | END
215 {
216 context->set_end();
217 YYACCEPT;
218 }
219 | CSL_ERROR
220 {
221 context->rc= MEMCACHED_PARSE_USER_ERROR;
222 parser_abort(context, "ERROR called directly");
223 }
224 | RESET
225 {
226 memcached_reset(context->memc);
227 }
228 | PARSER_DEBUG
229 {
230 yydebug= 1;
231 }
232 | INCLUDE ' ' string
233 {
234 if ((context->rc= memcached_parse_configure_file(*context->memc, $3.c_str, $3.size)) != MEMCACHED_SUCCESS)
235 {
236 parser_abort(context, "Failed to parse configuration file");
237 }
238 }
239 ;
240
241
242 expression:
243 SERVER HOSTNAME optional_port optional_weight
244 {
245 if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $3, uint32_t($4))))
246 {
247 char buffer[1024];
248 snprintf(buffer, sizeof(buffer), "Failed to add server: %s:%u", $2.c_str, uint32_t($3));
249 parser_abort(context, buffer);
250 }
251 context->unset_server();
252 }
253 | SERVER IPADDRESS optional_port optional_weight
254 {
255 if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $3, uint32_t($4))))
256 {
257 char buffer[1024];
258 snprintf(buffer, sizeof(buffer), "Failed to add server: %s:%u", $2.c_str, uint32_t($3));
259 parser_abort(context, buffer);
260 }
261 context->unset_server();
262 }
263 | CSL_SOCKET string optional_weight
264 {
265 if (memcached_failed(context->rc= memcached_server_add_unix_socket_with_weight(context->memc, $2.c_str, uint32_t($3))))
266 {
267 char buffer[1024];
268 snprintf(buffer, sizeof(buffer), "Failed to add socket: %s", $2.c_str);
269 parser_abort(context, buffer);
270 }
271 }
272 | CONFIGURE_FILE string
273 {
274 memcached_set_configuration_file(context->memc, $2.c_str, $2.size);
275 }
276 | POOL_MIN NUMBER
277 {
278 context->memc->configure.initial_pool_size= uint32_t($2);
279 }
280 | POOL_MAX NUMBER
281 {
282 context->memc->configure.max_pool_size= uint32_t($2);
283 }
284 | behaviors
285 ;
286
287 behaviors:
288 NAMESPACE string
289 {
290 if (memcached_callback_get(context->memc, MEMCACHED_CALLBACK_PREFIX_KEY, NULL))
291 {
292 parser_abort(context, "--NAMESPACE can only be called once");
293 }
294
295 if ((context->rc= memcached_set_namespace(*context->memc, $2.c_str, $2.size)) != MEMCACHED_SUCCESS)
296 {
297 parser_abort(context, memcached_last_error_message(context->memc));
298 }
299 }
300 | FETCH_VERSION
301 {
302 memcached_flag(*context->memc, MEMCACHED_FLAG_IS_FETCHING_VERSION, true);
303 }
304 | DISTRIBUTION distribution
305 {
306 // Check to see if DISTRIBUTION has already been set
307 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
308 {
309 parser_abort(context, "--DISTRIBUTION can only be called once");
310 }
311
312 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
313 {
314 parser_abort(context, memcached_last_error_message(context->memc));;
315 }
316 }
317 | DISTRIBUTION distribution ',' hash
318 {
319 // Check to see if DISTRIBUTION has already been set
320 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
321 {
322 parser_abort(context, "--DISTRIBUTION can only be called once");
323 }
324
325 if ((context->rc= memcached_behavior_set_distribution_hash(context->memc, $4)) != MEMCACHED_SUCCESS)
326 {
327 parser_abort(context, "Unable to set the hash for the DISTRIBUTION requested");
328 }
329 }
330 | HASH hash
331 {
332 if (context->set_hash($2) == false)
333 {
334 parser_abort(context, "--HASH can only be set once");
335 }
336 }
337 | behavior_number NUMBER
338 {
339 if ((context->rc= memcached_behavior_set(context->memc, $1, $2)) != MEMCACHED_SUCCESS)
340 {
341 parser_abort(context, "Unable to set behavior");
342 }
343 }
344 | behavior_boolean
345 {
346 if ((context->rc= memcached_behavior_set(context->memc, $1, true)) != MEMCACHED_SUCCESS)
347 {
348 char buffer[1024];
349 snprintf(buffer, sizeof(buffer), "Could not set: %s", libmemcached_string_behavior($1));
350 parser_abort(context, buffer);
351 }
352 }
353 | USER_DATA
354 {
355 }
356 ;
357
358 behavior_number:
359 REMOVE_FAILED_SERVERS
360 {
361 $$= MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS;
362 }
363 | CONNECT_TIMEOUT
364 {
365 $$= MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT;
366 }
367 | IO_MSG_WATERMARK
368 {
369 $$= MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK;
370 }
371 | IO_BYTES_WATERMARK
372 {
373 $$= MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK;
374 }
375 | IO_KEY_PREFETCH
376 {
377 $$= MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH;
378 }
379 | NUMBER_OF_REPLICAS
380 {
381 $$= MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS;
382 }
383 | POLL_TIMEOUT
384 {
385 $$= MEMCACHED_BEHAVIOR_POLL_TIMEOUT;
386 }
387 | RCV_TIMEOUT
388 {
389 $$= MEMCACHED_BEHAVIOR_RCV_TIMEOUT;
390 }
391 | RETRY_TIMEOUT
392 {
393 $$= MEMCACHED_BEHAVIOR_RETRY_TIMEOUT;
394 }
395 | SND_TIMEOUT
396 {
397 $$= MEMCACHED_BEHAVIOR_SND_TIMEOUT;
398 }
399 | SOCKET_RECV_SIZE
400 {
401 $$= MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE;
402 }
403 | SOCKET_SEND_SIZE
404 {
405 $$= MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE;
406 }
407 ;
408
409 behavior_boolean:
410 BINARY_PROTOCOL
411 {
412 $$= MEMCACHED_BEHAVIOR_BINARY_PROTOCOL;
413 }
414 | BUFFER_REQUESTS
415 {
416 $$= MEMCACHED_BEHAVIOR_BUFFER_REQUESTS;
417 }
418 | HASH_WITH_NAMESPACE
419 {
420 $$= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY;
421 }
422 | NOREPLY
423 {
424 $$= MEMCACHED_BEHAVIOR_NOREPLY;
425 }
426 | RANDOMIZE_REPLICA_READ
427 {
428 $$= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ;
429 }
430 | SORT_HOSTS
431 {
432 $$= MEMCACHED_BEHAVIOR_SORT_HOSTS;
433 }
434 | SUPPORT_CAS
435 {
436 $$= MEMCACHED_BEHAVIOR_SUPPORT_CAS;
437 }
438 | _TCP_NODELAY
439 {
440 $$= MEMCACHED_BEHAVIOR_TCP_NODELAY;
441 }
442 | _TCP_KEEPALIVE
443 {
444 $$= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE;
445 }
446 | _TCP_KEEPIDLE
447 {
448 $$= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE;
449 }
450 | USE_UDP
451 {
452 $$= MEMCACHED_BEHAVIOR_USE_UDP;
453 }
454 | VERIFY_KEY
455 {
456 $$= MEMCACHED_BEHAVIOR_VERIFY_KEY;
457 }
458
459
460 optional_port:
461 { $$= MEMCACHED_DEFAULT_PORT;}
462 | PORT
463 { };
464 ;
465
466 optional_weight:
467 { $$= 1; }
468 | WEIGHT_START
469 { }
470 ;
471
472 hash:
473 MD5
474 {
475 $$= MEMCACHED_HASH_MD5;
476 }
477 | CRC
478 {
479 $$= MEMCACHED_HASH_CRC;
480 }
481 | FNV1_64
482 {
483 $$= MEMCACHED_HASH_FNV1_64;
484 }
485 | FNV1A_64
486 {
487 $$= MEMCACHED_HASH_FNV1A_64;
488 }
489 | FNV1_32
490 {
491 $$= MEMCACHED_HASH_FNV1_32;
492 }
493 | FNV1A_32
494 {
495 $$= MEMCACHED_HASH_FNV1A_32;
496 }
497 | HSIEH
498 {
499 $$= MEMCACHED_HASH_HSIEH;
500 }
501 | MURMUR
502 {
503 $$= MEMCACHED_HASH_MURMUR;
504 }
505 | JENKINS
506 {
507 $$= MEMCACHED_HASH_JENKINS;
508 }
509 ;
510
511 string:
512 STRING
513 {
514 $$= $1;
515 }
516 | QUOTED_STRING
517 {
518 $$= $1;
519 }
520 ;
521
522 distribution:
523 CONSISTENT
524 {
525 $$= MEMCACHED_DISTRIBUTION_CONSISTENT;
526 }
527 | MODULA
528 {
529 $$= MEMCACHED_DISTRIBUTION_MODULA;
530 }
531 | RANDOM
532 {
533 $$= MEMCACHED_DISTRIBUTION_RANDOM;
534 }
535 ;
536
537 %%
538
539 void Context::start()
540 {
541 config_parse(this, (void **)scanner);
542 }
543