Fix issue with multiple use of "DEBUG"
[awesomized/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="libmemcached_"
29 %parse-param { Context *context }
30 %parse-param { yyscan_t *scanner }
31 %locations
32 %pure-parser
33 %require "2.2"
34 %start begin
35 %verbose
36
37 %{
38
39 #include <config.h>
40
41 #include <stdint.h>
42 #include <iostream>
43 #include <sstream>
44 #include <string>
45
46 #include <libmemcached/options/context.h>
47 #include <libmemcached/options/string.h>
48 #include <libmemcached/options/symbol.h>
49
50 #pragma GCC diagnostic ignored "-Wold-style-cast"
51 #include <libmemcached/options/scanner.h>
52
53 int libmemcached_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);
54
55 #define parser_abort(A, B) do { parser_abort_func((A), (B)); YYABORT; } while (0)
56
57 inline void parser_abort_func(Context *context, const char *error)
58 {
59 (void)error;
60 if (context->rc == MEMCACHED_SUCCESS)
61 context->rc= MEMCACHED_PARSE_ERROR;
62
63 std::string error_message;
64 error_message+= "Error occured while parsing: ";
65 error_message+= context->begin;
66 error_message+= " (";
67 if (context->rc == MEMCACHED_PARSE_ERROR and error)
68 {
69 error_message+= error;
70 }
71 else
72 {
73 error_message+= memcached_strerror(NULL, context->rc);
74 }
75 error_message+= ")";
76
77 memcached_set_error_string(context->memc, context->rc, error_message.c_str(), error_message.size());
78 }
79
80 inline void libmemcached_error(YYLTYPE *locp, Context *context, yyscan_t *scanner, const char *error)
81 {
82 if (not context->end())
83 parser_abort_func(context, error);
84 }
85
86 int libmemcached_parse(Context*, yyscan_t *);
87 void Context::start()
88 {
89 libmemcached_parse(this, scanner);
90 }
91
92 %}
93
94 %token COMMENT
95 %token END
96 %token ERROR
97 %token RESET
98 %token PARSER_DEBUG
99 %token INCLUDE
100 %token CONFIGURE_FILE
101 %token EMPTY_LINE
102 %token SERVER
103 %token SERVERS
104 %token SERVERS_OPTION
105 %token UNKNOWN_OPTION
106 %token UNKNOWN
107
108 /* All behavior options */
109 %token AUTO_EJECT_HOSTS
110 %token BINARY_PROTOCOL
111 %token BUFFER_REQUESTS
112 %token CACHE_LOOKUPS
113 %token CONNECT_TIMEOUT
114 %token _CORK
115 %token DISTRIBUTION
116 %token HASH
117 %token HASH_WITH_PREFIX_KEY
118 %token IO_BYTES_WATERMARK
119 %token IO_KEY_PREFETCH
120 %token IO_MSG_WATERMARK
121 %token KETAMA
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 RETRY_TIMEOUT
130 %token SERVER_FAILURE_LIMIT
131 %token SND_TIMEOUT
132 %token SOCKET_RECV_SIZE
133 %token SOCKET_SEND_SIZE
134 %token SORT_HOSTS
135 %token SUPPORT_CAS
136 %token _TCP_NODELAY
137 %token _TCP_KEEPALIVE
138 %token _TCP_KEEPIDLE
139 %token USER_DATA
140 %token USE_UDP
141 %token VERIFY_KEY
142
143 /* Callbacks */
144 %token PREFIX_KEY
145
146 /* Hash types */
147 %token MD5
148 %token CRC
149 %token FNV1_64
150 %token FNV1A_64
151 %token FNV1_32
152 %token FNV1A_32
153 %token HSIEH
154 %token MURMUR
155 %token JENKINS
156
157 /* Distributions */
158 %token CONSISTENT
159 %token MODULA
160 %token RANDOM
161
162 /* Boolean values */
163 %token <boolean> TRUE
164 %token <boolean> FALSE
165
166 %nonassoc ','
167 %nonassoc '='
168
169 %token <number> NUMBER
170 %token <number> FLOAT
171 %token <string> HOSTNAME
172 %token <string> HOSTNAME_WITH_PORT
173 %token <string> IPADDRESS
174 %token <string> IPADDRESS_WITH_PORT
175 %token <string> STRING
176 %token <string> QUOTED_STRING
177 %token <string> FILE_PATH
178
179 %type <server> server
180 %type <string> string
181 %type <distribution> distribution
182 %type <hash> hash
183 %type <behavior> behavior_boolean
184 %type <behavior> behavior_number
185
186 %%
187
188 begin:
189 statement
190 | begin ' ' statement
191 ;
192
193 statement:
194 expression
195 { }
196 | COMMENT
197 { }
198 | EMPTY_LINE
199 { }
200 | END
201 {
202 context->set_end();
203 YYACCEPT;
204 }
205 | ERROR
206 {
207 context->rc= MEMCACHED_PARSE_USER_ERROR;
208 parser_abort(context, NULL);
209 }
210 | RESET
211 {
212 memcached_reset(context->memc);
213 }
214 | PARSER_DEBUG
215 {
216 yydebug= 1;
217 }
218 | INCLUDE ' ' string
219 {
220 if ((context->rc= memcached_parse_configure_file(context->memc, $3.c_str, $3.length)) != MEMCACHED_SUCCESS)
221 {
222 parser_abort(context, NULL);
223 }
224 }
225 ;
226
227
228 expression:
229 SERVER '=' server
230 {
231 if ((context->rc= memcached_server_add_parsed(context->memc, $3.c_str, $3.length, $3.port, 0)) != MEMCACHED_SUCCESS)
232 {
233 parser_abort(context, NULL);
234 }
235 }
236 | SERVERS_OPTION '=' server_list
237 {
238 }
239 | CONFIGURE_FILE '=' string
240 {
241 memcached_set_configuration_file(context->memc, $3.c_str, $3.length);
242 }
243 | behaviors
244 ;
245
246 behaviors:
247 PREFIX_KEY '=' string
248 {
249 if ((context->rc= memcached_callback_set(context->memc, MEMCACHED_CALLBACK_PREFIX_KEY, std::string($3.c_str, $3.length).c_str())) != MEMCACHED_SUCCESS)
250 {
251 parser_abort(context, NULL);;
252 }
253 }
254 | DISTRIBUTION '=' distribution
255 {
256 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $3)) != MEMCACHED_SUCCESS)
257 {
258 parser_abort(context, NULL);;
259 }
260 }
261 | HASH '=' hash
262 {
263 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_HASH, $3)) != MEMCACHED_SUCCESS)
264 {
265 parser_abort(context, NULL);;
266 }
267 }
268 | KETAMA_HASH '=' hash
269 {
270 if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_KETAMA_HASH, $3)) != MEMCACHED_SUCCESS)
271 {
272 parser_abort(context, NULL);;
273 }
274 }
275 | behavior_number '=' NUMBER
276 {
277 if ((context->rc= memcached_behavior_set(context->memc, $1, $3)) != MEMCACHED_SUCCESS)
278 {
279 parser_abort(context, NULL);;
280 }
281 }
282 | behavior_boolean
283 {
284 if ((context->rc= memcached_behavior_set(context->memc, $1, true)) != MEMCACHED_SUCCESS)
285 {
286 parser_abort(context, NULL);;
287 }
288 }
289 | USER_DATA
290 {
291 }
292 ;
293
294 behavior_number:
295 CONNECT_TIMEOUT
296 {
297 $$= MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT;
298 }
299 | IO_MSG_WATERMARK
300 {
301 $$= MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK;
302 }
303 | IO_BYTES_WATERMARK
304 {
305 $$= MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK;
306 }
307 | IO_KEY_PREFETCH
308 {
309 $$= MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH;
310 }
311 | NUMBER_OF_REPLICAS
312 {
313 $$= MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS;
314 }
315 | POLL_TIMEOUT
316 {
317 $$= MEMCACHED_BEHAVIOR_POLL_TIMEOUT;
318 }
319 | RCV_TIMEOUT
320 {
321 $$= MEMCACHED_BEHAVIOR_RCV_TIMEOUT;
322 }
323 | RETRY_TIMEOUT
324 {
325 $$= MEMCACHED_BEHAVIOR_RETRY_TIMEOUT;
326 }
327 | SERVER_FAILURE_LIMIT
328 {
329 $$= MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT;
330 }
331 | SND_TIMEOUT
332 {
333 $$= MEMCACHED_BEHAVIOR_SND_TIMEOUT;
334 }
335 | SOCKET_RECV_SIZE
336 {
337 $$= MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE;
338 }
339 | SOCKET_SEND_SIZE
340 {
341 $$= MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE;
342 }
343 ;
344
345 behavior_boolean:
346 AUTO_EJECT_HOSTS
347 {
348 $$= MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS;
349 }
350 | BINARY_PROTOCOL
351 {
352 $$= MEMCACHED_BEHAVIOR_BINARY_PROTOCOL;
353 }
354 | BUFFER_REQUESTS
355 {
356 $$= MEMCACHED_BEHAVIOR_BUFFER_REQUESTS;
357 }
358 | CACHE_LOOKUPS
359 {
360 $$= MEMCACHED_BEHAVIOR_CACHE_LOOKUPS;
361 }
362 | _CORK
363 {
364 $$= MEMCACHED_BEHAVIOR_CORK;
365 }
366 | HASH_WITH_PREFIX_KEY
367 {
368 $$= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY;
369 }
370 | KETAMA
371 {
372 $$= MEMCACHED_BEHAVIOR_KETAMA;
373 }
374 | KETAMA_WEIGHTED
375 {
376 $$= MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED;
377 }
378 | NOREPLY
379 {
380 $$= MEMCACHED_BEHAVIOR_NOREPLY;
381 }
382 | RANDOMIZE_REPLICA_READ
383 {
384 $$= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ;
385 }
386 | SORT_HOSTS
387 {
388 $$= MEMCACHED_BEHAVIOR_SORT_HOSTS;
389 }
390 | SUPPORT_CAS
391 {
392 $$= MEMCACHED_BEHAVIOR_SUPPORT_CAS;
393 }
394 | _TCP_NODELAY
395 {
396 $$= MEMCACHED_BEHAVIOR_TCP_NODELAY;
397 }
398 | _TCP_KEEPALIVE
399 {
400 $$= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE;
401 }
402 | _TCP_KEEPIDLE
403 {
404 $$= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE;
405 }
406 | USE_UDP
407 {
408 $$= MEMCACHED_BEHAVIOR_USE_UDP;
409 }
410 | VERIFY_KEY
411 {
412 $$= MEMCACHED_BEHAVIOR_VERIFY_KEY;
413 }
414
415
416 server_list:
417 server
418 {
419 if ((context->rc= memcached_server_add_parsed(context->memc, $1.c_str, $1.length, $1.port, 0)) != MEMCACHED_SUCCESS)
420 {
421 parser_abort(context, NULL);;
422 }
423 }
424 | server_list ',' server
425 {
426 if ((context->rc= memcached_server_add_parsed(context->memc, $3.c_str, $3.length, $3.port, 0)) != MEMCACHED_SUCCESS)
427 {
428 parser_abort(context, NULL);;
429 }
430 }
431 ;
432
433 server:
434 HOSTNAME_WITH_PORT NUMBER
435 {
436 $$.c_str= $1.c_str;
437 $$.length= $1.length -1; // -1 to remove :
438 $$.port= $2;
439 }
440 | HOSTNAME
441 {
442 $$.c_str= $1.c_str;
443 $$.length= $1.length;
444 $$.port= MEMCACHED_DEFAULT_PORT;
445 }
446 | STRING /* a match can be against "localhost" which is just a string */
447 {
448 $$.c_str= $1.c_str;
449 $$.length= $1.length;
450 $$.port= MEMCACHED_DEFAULT_PORT;
451 }
452 | IPADDRESS_WITH_PORT NUMBER
453 {
454 $$.c_str= $1.c_str;
455 $$.length= $1.length -1; // -1 to remove :
456 $$.port= $2;
457 }
458 | IPADDRESS
459 {
460 $$.c_str= $1.c_str;
461 $$.length= $1.length;
462 $$.port= MEMCACHED_DEFAULT_PORT;
463 }
464 ;
465
466 hash:
467 MD5
468 {
469 $$= MEMCACHED_HASH_MD5;
470 }
471 | CRC
472 {
473 $$= MEMCACHED_HASH_CRC;
474 }
475 | FNV1_64
476 {
477 $$= MEMCACHED_HASH_FNV1_64;
478 }
479 | FNV1A_64
480 {
481 $$= MEMCACHED_HASH_FNV1A_64;
482 }
483 | FNV1_32
484 {
485 $$= MEMCACHED_HASH_FNV1_32;
486 }
487 | FNV1A_32
488 {
489 $$= MEMCACHED_HASH_FNV1A_32;
490 }
491 | HSIEH
492 {
493 $$= MEMCACHED_HASH_HSIEH;
494 }
495 | MURMUR
496 {
497 $$= MEMCACHED_HASH_MURMUR;
498 }
499 | JENKINS
500 {
501 $$= MEMCACHED_HASH_JENKINS;
502 }
503 ;
504
505 string:
506 STRING
507 {
508 $$= $1;
509 }
510 | QUOTED_STRING
511 {
512 $$.c_str= $1.c_str +1; // +1 to move use passed the initial quote
513 $$.length= $1.length -1; // -1 removes the end quote
514 }
515 ;
516
517 distribution:
518 CONSISTENT
519 {
520 $$= MEMCACHED_DISTRIBUTION_CONSISTENT;
521 }
522 | MODULA
523 {
524 $$= MEMCACHED_DISTRIBUTION_MODULA;
525 }
526 | RANDOM
527 {
528 $$= MEMCACHED_DISTRIBUTION_RANDOM;
529 }
530 ;