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