Update after fixing clang issue with pragma.
[awesomized/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 %error-verbose
38 %debug
39 %defines
40 %expect 0
41 %output "libmemcached/csl/parser.cc"
42 %defines "libmemcached/csl/parser.h"
43 %lex-param { yyscan_t *scanner }
44 %name-prefix="config_"
45 %parse-param { Context *context }
46 %parse-param { yyscan_t *scanner }
47 %pure-parser
48 %require "2.4"
49 %start begin
50 %verbose
51
52 %{
53
54 #include <libmemcached/csl/common.h>
55 #include <libmemcached/options.hpp>
56
57 #include <libmemcached/csl/context.h>
58 #include <libmemcached/csl/symbol.h>
59 #include <libmemcached/csl/scanner.h>
60
61 #ifndef __INTEL_COMPILER
62 #pragma GCC diagnostic ignored "-Wold-style-cast"
63 #endif
64
65 #ifndef __INTEL_COMPILER
66 #ifndef __clang__
67 #pragma GCC diagnostic ignored "-Wlogical-op"
68 #endif
69 #endif
70
71 int conf_lex(YYSTYPE* lvalp, void* scanner);
72
73 #define select_yychar(__context) yychar == UNKNOWN ? ( (__context)->previous_token == END ? UNKNOWN : (__context)->previous_token ) : yychar
74
75 #define stryytname(__yytokentype) ((__yytokentype) < YYNTOKENS ) ? yytname[(__yytokentype)] : ""
76
77 #define parser_abort(__context, __error_message) do { (__context)->abort((__error_message), yytokentype(select_yychar(__context)), stryytname(YYTRANSLATE(select_yychar(__context)))); YYABORT; } while (0)
78
79 // This is bison calling error.
80 inline void __config_error(Context *context, yyscan_t *scanner, const char *error, int last_token, const char *last_token_str)
81 {
82 if (not context->end())
83 {
84 context->error(error, yytokentype(last_token), last_token_str);
85 }
86 else
87 {
88 context->error(error, yytokentype(last_token), last_token_str);
89 }
90 }
91
92 #define config_error(__context, __scanner, __error_msg) do { __config_error((__context), (__scanner), (__error_msg), select_yychar(__context), stryytname(YYTRANSLATE(select_yychar(__context)))); } while (0)
93
94
95 %}
96
97 %token COMMENT
98 %token END
99 %token ERROR
100 %token RESET
101 %token PARSER_DEBUG
102 %token INCLUDE
103 %token CONFIGURE_FILE
104 %token EMPTY_LINE
105 %token SERVER
106 %token SOCKET
107 %token SERVERS
108 %token SERVERS_OPTION
109 %token UNKNOWN_OPTION
110 %token UNKNOWN
111
112 /* All behavior options */
113 %token BINARY_PROTOCOL
114 %token BUFFER_REQUESTS
115 %token CONNECT_TIMEOUT
116 %token DISTRIBUTION
117 %token HASH
118 %token HASH_WITH_NAMESPACE
119 %token IO_BYTES_WATERMARK
120 %token IO_KEY_PREFETCH
121 %token IO_MSG_WATERMARK
122 %token KETAMA_HASH
123 %token KETAMA_WEIGHTED
124 %token NOREPLY
125 %token NUMBER_OF_REPLICAS
126 %token POLL_TIMEOUT
127 %token RANDOMIZE_REPLICA_READ
128 %token RCV_TIMEOUT
129 %token REMOVE_FAILED_SERVERS
130 %token RETRY_TIMEOUT
131 %token SND_TIMEOUT
132 %token SOCKET_RECV_SIZE
133 %token SOCKET_SEND_SIZE
134 %token SORT_HOSTS
135 %token SUPPORT_CAS
136 %token USER_DATA
137 %token USE_UDP
138 %token VERIFY_KEY
139 %token _TCP_KEEPALIVE
140 %token _TCP_KEEPIDLE
141 %token _TCP_NODELAY
142 %token FETCH_VERSION
143
144 /* Callbacks */
145 %token NAMESPACE
146
147 /* Pool */
148 %token POOL_MIN
149 %token POOL_MAX
150
151 /* Hash types */
152 %token MD5
153 %token CRC
154 %token FNV1_64
155 %token FNV1A_64
156 %token FNV1_32
157 %token FNV1A_32
158 %token HSIEH
159 %token MURMUR
160 %token JENKINS
161
162 /* Distributions */
163 %token CONSISTENT
164 %token MODULA
165 %token RANDOM
166
167 /* Boolean values */
168 %token <boolean> TRUE
169 %token <boolean> FALSE
170
171 %nonassoc ','
172 %nonassoc '='
173
174 %token <number> FLOAT
175 %token <number> NUMBER
176 %token <number> PORT
177 %token <number> WEIGHT_START
178 %token <server> IPADDRESS
179 %token <server> HOSTNAME
180 %token <string> STRING
181 %token <string> QUOTED_STRING
182 %token <string> FILE_PATH
183
184 %type <behavior> behavior_boolean
185 %type <behavior> behavior_number
186 %type <distribution> distribution
187 %type <hash> hash
188 %type <number> optional_port
189 %type <number> optional_weight
190 %type <string> string
191
192 %%
193
194 begin:
195 statement
196 | begin ' ' statement
197 ;
198
199 statement:
200 expression
201 { }
202 | COMMENT
203 { }
204 | EMPTY_LINE
205 { }
206 | END
207 {
208 context->set_end();
209 YYACCEPT;
210 }
211 | ERROR
212 {
213 context->rc= MEMCACHED_PARSE_USER_ERROR;
214 parser_abort(context, "ERROR called directly");
215 }
216 | RESET
217 {
218 memcached_reset(context->memc);
219 }
220 | PARSER_DEBUG
221 {
222 yydebug= 1;
223 }
224 | INCLUDE ' ' string
225 {
226 if ((context->rc= memcached_parse_configure_file(*context->memc, $3.c_str, $3.size)) != MEMCACHED_SUCCESS)
227 {
228 parser_abort(context, "Failed to parse configuration file");
229 }
230 }
231 ;
232
233
234 expression:
235 SERVER HOSTNAME optional_port optional_weight
236 {
237 if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $3, uint32_t($4))))
238 {
239 char buffer[1024];
240 snprintf(buffer, sizeof(buffer), "Failed to add server: %s:%u", $2.c_str, uint32_t($3));
241 parser_abort(context, buffer);
242 }
243 context->unset_server();
244 }
245 | SERVER IPADDRESS optional_port optional_weight
246 {
247 if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $3, uint32_t($4))))
248 {
249 char buffer[1024];
250 snprintf(buffer, sizeof(buffer), "Failed to add server: %s:%u", $2.c_str, uint32_t($3));
251 parser_abort(context, buffer);
252 }
253 context->unset_server();
254 }
255 | SOCKET string optional_weight
256 {
257 if (memcached_failed(context->rc= memcached_server_add_unix_socket_with_weight(context->memc, $2.c_str, uint32_t($3))))
258 {
259 char buffer[1024];
260 snprintf(buffer, sizeof(buffer), "Failed to add socket: %s", $2.c_str);
261 parser_abort(context, buffer);
262 }
263 }
264 | CONFIGURE_FILE string
265 {
266 memcached_set_configuration_file(context->memc, $2.c_str, $2.size);
267 }
268 | POOL_MIN NUMBER
269 {
270 context->memc->configure.initial_pool_size= uint32_t($2);
271 }
272 | POOL_MAX NUMBER
273 {
274 context->memc->configure.max_pool_size= uint32_t($2);
275 }
276 | behaviors
277 ;
278
279 behaviors:
280 NAMESPACE string
281 {
282 if (memcached_callback_get(context->memc, MEMCACHED_CALLBACK_PREFIX_KEY, NULL))
283 {
284 parser_abort(context, "--NAMESPACE can only be called once");
285 }
286
287 if ((context->rc= memcached_set_namespace(context->memc, $2.c_str, $2.size)) != MEMCACHED_SUCCESS)
288 {
289 parser_abort(context, memcached_last_error_message(context->memc));
290 }
291 }
292 | FETCH_VERSION
293 {
294 memcached_flag(*context->memc, MEMCACHED_FLAG_IS_FETCHING_VERSION, true);
295 }
296 | DISTRIBUTION distribution
297 {
298 // Check to see if DISTRIBUTION has already been set
299 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
300 {
301 parser_abort(context, "--DISTRIBUTION can only be called once");
302 }
303
304 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
305 {
306 parser_abort(context, memcached_last_error_message(context->memc));;
307 }
308 }
309 | DISTRIBUTION distribution ',' hash
310 {
311 // Check to see if DISTRIBUTION has already been set
312 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
313 {
314 parser_abort(context, "--DISTRIBUTION can only be called once");
315 }
316
317 if ((context->rc= memcached_behavior_set_distribution_hash(context->memc, $4)) != MEMCACHED_SUCCESS)
318 {
319 parser_abort(context, "Unable to set the hash for the DISTRIBUTION requested");
320 }
321 }
322 | HASH hash
323 {
324 if (context->set_hash($2) == false)
325 {
326 parser_abort(context, "--HASH can only be set once");
327 }
328 }
329 | behavior_number NUMBER
330 {
331 if ((context->rc= memcached_behavior_set(context->memc, $1, $2)) != MEMCACHED_SUCCESS)
332 {
333 parser_abort(context, "Unable to set behavior");
334 }
335 }
336 | behavior_boolean
337 {
338 if ((context->rc= memcached_behavior_set(context->memc, $1, true)) != MEMCACHED_SUCCESS)
339 {
340 char buffer[1024];
341 snprintf(buffer, sizeof(buffer), "Could not set: %s", libmemcached_string_behavior($1));
342 parser_abort(context, buffer);
343 }
344 }
345 | USER_DATA
346 {
347 }
348 ;
349
350 behavior_number:
351 REMOVE_FAILED_SERVERS
352 {
353 $$= MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS;
354 }
355 | CONNECT_TIMEOUT
356 {
357 $$= MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT;
358 }
359 | IO_MSG_WATERMARK
360 {
361 $$= MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK;
362 }
363 | IO_BYTES_WATERMARK
364 {
365 $$= MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK;
366 }
367 | IO_KEY_PREFETCH
368 {
369 $$= MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH;
370 }
371 | NUMBER_OF_REPLICAS
372 {
373 $$= MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS;
374 }
375 | POLL_TIMEOUT
376 {
377 $$= MEMCACHED_BEHAVIOR_POLL_TIMEOUT;
378 }
379 | RCV_TIMEOUT
380 {
381 $$= MEMCACHED_BEHAVIOR_RCV_TIMEOUT;
382 }
383 | RETRY_TIMEOUT
384 {
385 $$= MEMCACHED_BEHAVIOR_RETRY_TIMEOUT;
386 }
387 | SND_TIMEOUT
388 {
389 $$= MEMCACHED_BEHAVIOR_SND_TIMEOUT;
390 }
391 | SOCKET_RECV_SIZE
392 {
393 $$= MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE;
394 }
395 | SOCKET_SEND_SIZE
396 {
397 $$= MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE;
398 }
399 ;
400
401 behavior_boolean:
402 BINARY_PROTOCOL
403 {
404 $$= MEMCACHED_BEHAVIOR_BINARY_PROTOCOL;
405 }
406 | BUFFER_REQUESTS
407 {
408 $$= MEMCACHED_BEHAVIOR_BUFFER_REQUESTS;
409 }
410 | HASH_WITH_NAMESPACE
411 {
412 $$= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY;
413 }
414 | NOREPLY
415 {
416 $$= MEMCACHED_BEHAVIOR_NOREPLY;
417 }
418 | RANDOMIZE_REPLICA_READ
419 {
420 $$= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ;
421 }
422 | SORT_HOSTS
423 {
424 $$= MEMCACHED_BEHAVIOR_SORT_HOSTS;
425 }
426 | SUPPORT_CAS
427 {
428 $$= MEMCACHED_BEHAVIOR_SUPPORT_CAS;
429 }
430 | _TCP_NODELAY
431 {
432 $$= MEMCACHED_BEHAVIOR_TCP_NODELAY;
433 }
434 | _TCP_KEEPALIVE
435 {
436 $$= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE;
437 }
438 | _TCP_KEEPIDLE
439 {
440 $$= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE;
441 }
442 | USE_UDP
443 {
444 $$= MEMCACHED_BEHAVIOR_USE_UDP;
445 }
446 | VERIFY_KEY
447 {
448 $$= MEMCACHED_BEHAVIOR_VERIFY_KEY;
449 }
450
451
452 optional_port:
453 { $$= MEMCACHED_DEFAULT_PORT;}
454 | PORT
455 { };
456 ;
457
458 optional_weight:
459 { $$= 1; }
460 | WEIGHT_START
461 { }
462 ;
463
464 hash:
465 MD5
466 {
467 $$= MEMCACHED_HASH_MD5;
468 }
469 | CRC
470 {
471 $$= MEMCACHED_HASH_CRC;
472 }
473 | FNV1_64
474 {
475 $$= MEMCACHED_HASH_FNV1_64;
476 }
477 | FNV1A_64
478 {
479 $$= MEMCACHED_HASH_FNV1A_64;
480 }
481 | FNV1_32
482 {
483 $$= MEMCACHED_HASH_FNV1_32;
484 }
485 | FNV1A_32
486 {
487 $$= MEMCACHED_HASH_FNV1A_32;
488 }
489 | HSIEH
490 {
491 $$= MEMCACHED_HASH_HSIEH;
492 }
493 | MURMUR
494 {
495 $$= MEMCACHED_HASH_MURMUR;
496 }
497 | JENKINS
498 {
499 $$= MEMCACHED_HASH_JENKINS;
500 }
501 ;
502
503 string:
504 STRING
505 {
506 $$= $1;
507 }
508 | QUOTED_STRING
509 {
510 $$= $1;
511 }
512 ;
513
514 distribution:
515 CONSISTENT
516 {
517 $$= MEMCACHED_DISTRIBUTION_CONSISTENT;
518 }
519 | MODULA
520 {
521 $$= MEMCACHED_DISTRIBUTION_MODULA;
522 }
523 | RANDOM
524 {
525 $$= MEMCACHED_DISTRIBUTION_RANDOM;
526 }
527 ;
528
529 %%
530
531 void Context::start()
532 {
533 config_parse(this, (void **)scanner);
534 }
535