Fix problem where hostname would end up with trailing . and be accepted as
[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="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+= context->begin;
65 error_message+= " (";
66 if (context->rc == MEMCACHED_PARSE_ERROR and error)
67 {
68 error_message+= error;
69 }
70 else
71 {
72 error_message+= memcached_strerror(NULL, context->rc);
73 }
74 error_message+= ")";
75
76 memcached_set_error_string(context->memc, context->rc, error_message.c_str(), error_message.size());
77 }
78
79 inline void libmemcached_error(YYLTYPE *locp, Context *context, yyscan_t *scanner, const char *error)
80 {
81 if (not context->end())
82 parser_abort_func(context, error);
83 }
84
85 %}
86
87 %token COMMENT
88 %token END
89 %token RESET
90 %token DEBUG
91 %token INCLUDE
92 %token CONFIGURE_FILE
93 %token EMPTY_LINE
94 %token SERVER
95 %token SERVERS
96 %token SERVERS_OPTION
97 %token UNKNOWN_OPTION
98 %token UNKNOWN
99
100 /* All behavior options */
101 %token AUTO_EJECT_HOSTS
102 %token BINARY_PROTOCOL
103 %token BUFFER_REQUESTS
104 %token CACHE_LOOKUPS
105 %token CONNECT_TIMEOUT
106 %token _CORK
107 %token DISTRIBUTION
108 %token HASH
109 %token HASH_WITH_PREFIX_KEY
110 %token IO_BYTES_WATERMARK
111 %token IO_KEY_PREFETCH
112 %token IO_MSG_WATERMARK
113 %token KETAMA
114 %token KETAMA_HASH
115 %token KETAMA_WEIGHTED
116 %token NOREPLY
117 %token NUMBER_OF_REPLICAS
118 %token POLL_TIMEOUT
119 %token RANDOMIZE_REPLICA_READ
120 %token RCV_TIMEOUT
121 %token RETRY_TIMEOUT
122 %token SERVER_FAILURE_LIMIT
123 %token SND_TIMEOUT
124 %token SOCKET_RECV_SIZE
125 %token SOCKET_SEND_SIZE
126 %token SORT_HOSTS
127 %token SUPPORT_CAS
128 %token _TCP_NODELAY
129 %token _TCP_KEEPALIVE
130 %token _TCP_KEEPIDLE
131 %token USER_DATA
132 %token USE_UDP
133 %token VERIFY_KEY
134
135 /* Callbacks */
136 %token PREFIX_KEY
137
138 /* Hash types */
139 %token MD5
140 %token CRC
141 %token FNV1_64
142 %token FNV1A_64
143 %token FNV1_32
144 %token FNV1A_32
145 %token HSIEH
146 %token MURMUR
147 %token JENKINS
148
149 /* Distributions */
150 %token CONSISTENT
151 %token MODULA
152 %token RANDOM
153
154 /* Boolean values */
155 %token <boolean> TRUE
156 %token <boolean> FALSE
157
158 %nonassoc ','
159 %nonassoc '='
160
161 %token <number> NUMBER
162 %token <number> FLOAT
163 %token <string> HOSTNAME
164 %token <string> HOSTNAME_WITH_PORT
165 %token <string> IPADDRESS
166 %token <string> IPADDRESS_WITH_PORT
167 %token <string> STRING
168 %token <string> QUOTED_STRING
169 %token <string> FILE_PATH
170
171 %type <server> server
172 %type <string> string
173 %type <distribution> distribution
174 %type <hash> hash
175 %type <behavior> behavior_boolean
176 %type <behavior> behavior_number
177
178 %%
179
180 begin:
181 statement
182 | begin ' ' statement
183 ;
184
185 statement:
186 expression
187 { }
188 | COMMENT
189 { }
190 | EMPTY_LINE
191 { }
192 | END
193 {
194 context->set_end();
195 YYACCEPT;
196 }
197 | RESET
198 {
199 memcached_reset(context->memc);
200 }
201 | RESET SERVERS
202 {
203 memcached_servers_reset(context->memc);
204 }
205 | DEBUG
206 {
207 yydebug= 1;
208 }
209 | DEBUG TRUE
210 {
211 yydebug= 1;
212 }
213 | DEBUG FALSE
214 {
215 yydebug= 0;
216 }
217 | INCLUDE FILE_PATH
218 {
219 std::cerr << "Got into INCLUDE" << std::endl;
220 if ((context->rc= memcached_parse_configure_file(context->memc, $2.c_str, $2.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;
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;
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;
513 $$.length= $1.length -2;
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 ;