dhcp6_lexer.ll 34.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/* Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")

   This Source Code Form is subject to the terms of the Mozilla Public
   License, v. 2.0. If a copy of the MPL was not distributed with this
   file, You can obtain one at http://mozilla.org/MPL/2.0/. */

%{ /* -*- C++ -*- */
#include <cerrno>
#include <climits>
#include <cstdlib>
#include <string>
#include <dhcp6/parser_context.h>
#include <asiolink/io_address.h>
#include <boost/lexical_cast.hpp>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
15
#include <exceptions/exceptions.h>
16 17 18 19 20 21 22 23

// Work around an incompatibility in flex (at least versions
// 2.5.31 through 2.5.33): it generates code that does
// not conform to C89.  See Debian bug 333231
// <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.
# undef yywrap
# define yywrap() 1

Francis Dupont's avatar
Francis Dupont committed
24 25 26 27 28
namespace {

bool start_token_flag = false;

isc::dhcp::Parser6Context::ParserType start_token_value;
29
unsigned int comment_start_line = 0;
Francis Dupont's avatar
Francis Dupont committed
30 31

};
32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
// To avoid the call to exit... oops!
#define YY_FATAL_ERROR(msg) isc::dhcp::Parser6Context::fatal(msg)
%}

/* noyywrap disables automatic rewinding for the next file to parse. Since we
   always parse only a single string, there's no need to do any wraps. And
   using yywrap requires linking with -lfl, which provides the default yywrap
   implementation that always returns 1 anyway. */
%option noyywrap

/* nounput simplifies the lexer, by removing support for putting a character
   back into the input stream. We never use such capability anyway. */
%option nounput

/* batch means that we'll never use the generated lexer interactively. */
%option batch

50 51 52
/* avoid to get static global variables to remain with C++. */
/* in last resort %option reentrant */

53 54 55 56 57 58 59 60 61
/* Enables debug mode. To see the debug messages, one needs to also set
   yy_flex_debug to 1, then the debug messages will be printed on stderr. */
%option debug

/* I have no idea what this option does, except it was specified in the bison
   examples and Postgres folks added it to remove gcc 4.3 warnings. Let's
   be on the safe side and keep it. */
%option noinput

Tomek Mrugalski's avatar
Tomek Mrugalski committed
62
%x COMMENT
Francis Dupont's avatar
Francis Dupont committed
63
%x DIR_ENTER DIR_INCLUDE DIR_EXIT
Tomek Mrugalski's avatar
Tomek Mrugalski committed
64

65 66 67 68
/* These are not token expressions yet, just convenience expressions that
   can be used during actual token definitions. Note some can match
   incorrect inputs (e.g., IP addresses) which must be checked. */
int   \-?[0-9]+
69
blank [ \t\r]
70

71 72 73 74 75 76
UnicodeEscapeSequence           u[0-9A-Fa-f]{4}
JSONEscapeCharacter             ["\\/bfnrt]
JSONEscapeSequence              {JSONEscapeCharacter}|{UnicodeEscapeSequence}
JSONStandardCharacter           [^\x00-\x1f"\\]
JSONStringCharacter             {JSONStandardCharacter}|\\{JSONEscapeSequence}
JSONString                      \"{JSONStringCharacter}*\"
77

78 79 80 81 82 83
/* for errors */

BadUnicodeEscapeSequence        u[0-9A-Fa-f]{0,3}[^0-9A-Fa-f]
BadJSONEscapeSequence           [^"\\/bfnrtu]|{BadUnicodeEscapeSequence}
ControlCharacter                [\x00-\x1f]
ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
84 85 86 87 88

%{
// This code run each time a pattern is matched. It updates the location
// by moving it ahead by yyleng bytes. yyleng specifies the length of the
// currently matched token.
89
#define YY_USER_ACTION  driver.loc_.columns(yyleng);
90 91 92 93 94
%}

%%

%{
95 96 97 98
    // This part of the code is copied over to the verbatim to the top
    // of the generated yylex function. Explanation:
    // http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html

99
    // Code run each time yylex is called.
100
    driver.loc_.step();
Tomek Mrugalski's avatar
Tomek Mrugalski committed
101

102 103 104
    if (start_token_flag) {
        start_token_flag = false;
        switch (start_token_value) {
105
        case Parser6Context::PARSER_JSON:
106
        default:
107
            return isc::dhcp::Dhcp6Parser::make_TOPLEVEL_JSON(driver.loc_);
108
        case Parser6Context::PARSER_DHCP6:
109
            return isc::dhcp::Dhcp6Parser::make_TOPLEVEL_DHCP6(driver.loc_);
110 111
        case Parser6Context::SUBPARSER_DHCP6:
            return isc::dhcp::Dhcp6Parser::make_SUB_DHCP6(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
112
        case Parser6Context::PARSER_INTERFACES:
113
            return isc::dhcp::Dhcp6Parser::make_SUB_INTERFACES6(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
114
        case Parser6Context::PARSER_SUBNET6:
115
            return isc::dhcp::Dhcp6Parser::make_SUB_SUBNET6(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
116
        case Parser6Context::PARSER_POOL6:
117
            return isc::dhcp::Dhcp6Parser::make_SUB_POOL6(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
118
        case Parser6Context::PARSER_PD_POOL:
119
            return isc::dhcp::Dhcp6Parser::make_SUB_PD_POOL(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
120
        case Parser6Context::PARSER_HOST_RESERVATION:
121
            return isc::dhcp::Dhcp6Parser::make_SUB_RESERVATION(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
122
        case Parser6Context::PARSER_OPTION_DATA:
123
            return isc::dhcp::Dhcp6Parser::make_SUB_OPTION_DATA(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
124
        case Parser6Context::PARSER_HOOKS_LIBRARY:
125
            return isc::dhcp::Dhcp6Parser::make_SUB_HOOKS_LIBRARY(driver.loc_);
126 127
        }
    }
128 129
%}

Tomek Mrugalski's avatar
Tomek Mrugalski committed
130 131 132 133 134 135
#.* ;

"//"(.*) ;

"/*" {
  BEGIN(COMMENT);
136
  comment_start_line = driver.loc_.end.line;;
Tomek Mrugalski's avatar
Tomek Mrugalski committed
137 138 139
}

<COMMENT>"*/" BEGIN(INITIAL);
140
<COMMENT>. ;
Tomek Mrugalski's avatar
Tomek Mrugalski committed
141
<COMMENT><<EOF>> {
142
    isc_throw(Dhcp6ParseError, "Comment not closed. (/* in line " << comment_start_line);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
143 144
}

Francis Dupont's avatar
Francis Dupont committed
145 146 147 148 149 150 151 152 153
"<?" BEGIN(DIR_ENTER);
<DIR_ENTER>"include" BEGIN(DIR_INCLUDE);
<DIR_INCLUDE>\"([^\"\n])+\" {
    // Include directive.

    // Extract the filename.
    std::string tmp(yytext+1);
    tmp.resize(tmp.size() - 1);

154
    driver.includeFile(tmp);
Francis Dupont's avatar
Francis Dupont committed
155
}
156
<DIR_ENTER,DIR_INCLUDE,DIR_EXIT><<EOF>> {
157
    isc_throw(Dhcp6ParseError, "Directive not closed.");
158
}
Francis Dupont's avatar
Francis Dupont committed
159
<DIR_EXIT>"?>" BEGIN(INITIAL);
160

Francis Dupont's avatar
Francis Dupont committed
161

162
<*>{blank}+   {
163
    // Ok, we found a with space. Let's ignore it and update loc variable.
164
    driver.loc_.step();
165
}
166

167
<*>[\n]+      {
168
    // Newline found. Let's update the location and continue.
169 170
    driver.loc_.lines(yyleng);
    driver.loc_.step();
171 172
}

173

174 175 176
\"Dhcp6\"  {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
177
        return isc::dhcp::Dhcp6Parser::make_DHCP6(driver.loc_);
178
    default:
179
        return isc::dhcp::Dhcp6Parser::make_STRING("Dhcp6", driver.loc_);
180 181 182 183 184 185
    }
}

\"interfaces-config\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
186
        return  isc::dhcp::Dhcp6Parser::make_INTERFACES_CONFIG(driver.loc_);
187
    default:
188
        return isc::dhcp::Dhcp6Parser::make_STRING("interfaces-config", driver.loc_);
189 190 191 192 193 194
    }
}

\"interfaces\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::INTERFACES_CONFIG:
195
        return  isc::dhcp::Dhcp6Parser::make_INTERFACES(driver.loc_);
196
    default:
197
        return isc::dhcp::Dhcp6Parser::make_STRING("interfaces", driver.loc_);
198 199 200 201 202 203
    }
}

\"lease-database\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
204
        return isc::dhcp::Dhcp6Parser::make_LEASE_DATABASE(driver.loc_);
205
    default:
206
        return isc::dhcp::Dhcp6Parser::make_STRING("lease-database", driver.loc_);
207 208 209 210 211 212
    }
}

\"hosts-database\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
213
        return isc::dhcp::Dhcp6Parser::make_HOSTS_DATABASE(driver.loc_);
214
    default:
215
        return isc::dhcp::Dhcp6Parser::make_STRING("hosts-database", driver.loc_);
216 217 218
    }
}

219 220 221 222 223 224 225 226 227
\"readonly\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
        return isc::dhcp::Dhcp6Parser::make_READONLY(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("readonly", driver.loc_);
    }
}

228 229
\"type\" {
    switch(driver.ctx_) {
230 231
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
232
    case isc::dhcp::Parser6Context::OPTION_DEF:
233
    case isc::dhcp::Parser6Context::SERVER_ID:
234
        return isc::dhcp::Dhcp6Parser::make_TYPE(driver.loc_);
235
    default:
236
        return isc::dhcp::Dhcp6Parser::make_STRING("type", driver.loc_);
237 238 239 240 241
    }
}

\"user\" {
    switch(driver.ctx_) {
242 243
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
244
        return isc::dhcp::Dhcp6Parser::make_USER(driver.loc_);
245
    default:
246
        return isc::dhcp::Dhcp6Parser::make_STRING("user", driver.loc_);
247 248 249 250 251
    }
}

\"password\" {
    switch(driver.ctx_) {
252 253
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
254
        return isc::dhcp::Dhcp6Parser::make_PASSWORD(driver.loc_);
255
    default:
256
        return isc::dhcp::Dhcp6Parser::make_STRING("password", driver.loc_);
257 258 259 260 261
    }
}

\"host\" {
    switch(driver.ctx_) {
262 263
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
264
        return isc::dhcp::Dhcp6Parser::make_HOST(driver.loc_);
265
    default:
266
        return isc::dhcp::Dhcp6Parser::make_STRING("host", driver.loc_);
267 268 269 270 271
    }
}

\"persist\" {
    switch(driver.ctx_) {
272 273
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
274
    case isc::dhcp::Parser6Context::SERVER_ID:
275
        return isc::dhcp::Dhcp6Parser::make_PERSIST(driver.loc_);
276
    default:
277
        return isc::dhcp::Dhcp6Parser::make_STRING("persist", driver.loc_);
278 279 280 281 282
    }
}

\"lfc-interval\" {
    switch(driver.ctx_) {
283 284
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
285
        return isc::dhcp::Dhcp6Parser::make_LFC_INTERVAL(driver.loc_);
286
    default:
287
        return isc::dhcp::Dhcp6Parser::make_STRING("lfc-interval", driver.loc_);
288 289 290 291 292 293
    }
}

\"preferred-lifetime\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
294
    case isc::dhcp::Parser6Context::SUBNET6:
295
        return isc::dhcp::Dhcp6Parser::make_PREFERRED_LIFETIME(driver.loc_);
296
    default:
297
        return isc::dhcp::Dhcp6Parser::make_STRING("preferred-lifetime", driver.loc_);
298 299 300 301 302 303
    }
}

\"valid-lifetime\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
304
    case isc::dhcp::Parser6Context::SUBNET6:
305
        return isc::dhcp::Dhcp6Parser::make_VALID_LIFETIME(driver.loc_);
306
    default:
307
        return isc::dhcp::Dhcp6Parser::make_STRING("valid-lifetime", driver.loc_);
308 309 310 311 312 313
    }
}

\"renew-timer\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
314
    case isc::dhcp::Parser6Context::SUBNET6:
315
        return isc::dhcp::Dhcp6Parser::make_RENEW_TIMER(driver.loc_);
316
    default:
317
        return isc::dhcp::Dhcp6Parser::make_STRING("renew-timer", driver.loc_);
318 319 320 321 322 323
    }
}

\"rebind-timer\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
324
    case isc::dhcp::Parser6Context::SUBNET6:
325
        return isc::dhcp::Dhcp6Parser::make_REBIND_TIMER(driver.loc_);
326
    default:
327
        return isc::dhcp::Dhcp6Parser::make_STRING("rebind-timer", driver.loc_);
328 329 330
    }
}

331 332 333 334 335 336 337 338 339
\"decline-probation-period\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
        return isc::dhcp::Dhcp6Parser::make_DECLINE_PROBATION_PERIOD(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("decline-probation-period", driver.loc_);
    }
}

340 341 342
\"subnet6\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
343
        return isc::dhcp::Dhcp6Parser::make_SUBNET6(driver.loc_);
344
    default:
345
        return isc::dhcp::Dhcp6Parser::make_STRING("subnet6", driver.loc_);
346 347 348
    }
}

349 350 351 352 353 354 355 356 357
\"option-def\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
        return isc::dhcp::Dhcp6Parser::make_OPTION_DEF(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("option-def", driver.loc_);
    }
}

358 359 360 361 362 363 364 365 366
\"option-data\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
    case isc::dhcp::Parser6Context::SUBNET6:
    case isc::dhcp::Parser6Context::POOLS:
    case isc::dhcp::Parser6Context::PD_POOLS:
    case isc::dhcp::Parser6Context::RESERVATIONS:
    case isc::dhcp::Parser6Context::CLIENT_CLASSES:
    case isc::dhcp::Parser6Context::CLIENT_CLASS:
367
        return isc::dhcp::Dhcp6Parser::make_OPTION_DATA(driver.loc_);
368
    default:
369
        return isc::dhcp::Dhcp6Parser::make_STRING("option-data", driver.loc_);
370 371 372 373 374
    }
}

\"name\" {
    switch(driver.ctx_) {
375 376
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
377
    case isc::dhcp::Parser6Context::OPTION_DEF:
378 379 380 381
    case isc::dhcp::Parser6Context::OPTION_DATA:
    case isc::dhcp::Parser6Context::CLIENT_CLASSES:
    case isc::dhcp::Parser6Context::CLIENT_CLASS:
    case isc::dhcp::Parser6Context::LOGGERS:
382
        return isc::dhcp::Dhcp6Parser::make_NAME(driver.loc_);
383
    default:
384
        return isc::dhcp::Dhcp6Parser::make_STRING("name", driver.loc_);
385 386 387 388 389 390
    }
}

\"data\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OPTION_DATA:
391
        return isc::dhcp::Dhcp6Parser::make_DATA(driver.loc_);
392
    default:
393
        return isc::dhcp::Dhcp6Parser::make_STRING("data", driver.loc_);
394 395 396 397 398 399
    }
}

\"pools\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
400
        return isc::dhcp::Dhcp6Parser::make_POOLS(driver.loc_);
401
    default:
402
        return isc::dhcp::Dhcp6Parser::make_STRING("pools", driver.loc_);
403 404 405 406 407 408
    }
}

\"pd-pools\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
409
        return isc::dhcp::Dhcp6Parser::make_PD_POOLS(driver.loc_);
410
    default:
411
        return isc::dhcp::Dhcp6Parser::make_STRING("pd-pools", driver.loc_);
412 413 414 415 416 417
    }
}

\"prefix\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::PD_POOLS:
418
        return isc::dhcp::Dhcp6Parser::make_PREFIX(driver.loc_);
419
    default:
420
        return isc::dhcp::Dhcp6Parser::make_STRING("prefix", driver.loc_);
421 422 423 424 425 426
    }
}

\"prefix-len\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::PD_POOLS:
427
        return isc::dhcp::Dhcp6Parser::make_PREFIX_LEN(driver.loc_);
428
    default:
429
        return isc::dhcp::Dhcp6Parser::make_STRING("prefix-len", driver.loc_);
430 431 432
    }
}

433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
\"excluded-prefix\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::PD_POOLS:
        return isc::dhcp::Dhcp6Parser::make_EXCLUDED_PREFIX(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("excluded-prefix", driver.loc_);
    }
}

\"excluded-prefix-len\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::PD_POOLS:
        return isc::dhcp::Dhcp6Parser::make_EXCLUDED_PREFIX_LEN(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("excluded-prefix-len", driver.loc_);
    }
}

451 452 453
\"delegated-len\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::PD_POOLS:
454
        return isc::dhcp::Dhcp6Parser::make_DELEGATED_LEN(driver.loc_);
455
    default:
456
        return isc::dhcp::Dhcp6Parser::make_STRING("delegated-len", driver.loc_);
457 458 459 460 461 462
    }
}

\"pool\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::POOLS:
463
        return isc::dhcp::Dhcp6Parser::make_POOL(driver.loc_);
464
    default:
465
        return isc::dhcp::Dhcp6Parser::make_STRING("pool", driver.loc_);
466 467 468 469 470 471
    }
}

\"subnet\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
472
        return isc::dhcp::Dhcp6Parser::make_SUBNET(driver.loc_);
473
    default:
474
        return isc::dhcp::Dhcp6Parser::make_STRING("subnet", driver.loc_);
475 476 477 478 479 480
    }
}

\"interface\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
481
        return isc::dhcp::Dhcp6Parser::make_INTERFACE(driver.loc_);
482
    default:
483
        return isc::dhcp::Dhcp6Parser::make_STRING("interface", driver.loc_);
484 485 486
    }
}

487 488 489 490 491 492 493 494 495
\"interface-id\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
        return isc::dhcp::Dhcp6Parser::make_INTERFACE_ID(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("interface-id", driver.loc_);
    }
}

496 497 498
\"id\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
499
        return isc::dhcp::Dhcp6Parser::make_ID(driver.loc_);
500
    default:
501
        return isc::dhcp::Dhcp6Parser::make_STRING("id", driver.loc_);
502 503 504
    }
}

505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
\"rapid-commit\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
        return isc::dhcp::Dhcp6Parser::make_RAPID_COMMIT(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("rapid-commit", driver.loc_);
    }
}

\"reservation-mode\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
        return isc::dhcp::Dhcp6Parser::make_RESERVATION_MODE(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("reservation-mode", driver.loc_);
    }
}

523 524
\"code\" {
    switch(driver.ctx_) {
525
    case isc::dhcp::Parser6Context::OPTION_DEF:
526
    case isc::dhcp::Parser6Context::OPTION_DATA:
527
        return isc::dhcp::Dhcp6Parser::make_CODE(driver.loc_);
528
    default:
529
        return isc::dhcp::Dhcp6Parser::make_STRING("code", driver.loc_);
530 531 532 533 534 535
    }
}

\"mac-sources\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
536
        return isc::dhcp::Dhcp6Parser::make_MAC_SOURCES(driver.loc_);
537
    default:
538
        return isc::dhcp::Dhcp6Parser::make_STRING("mac-sources", driver.loc_);
539 540 541 542 543 544
    }
}

\"relay-supplied-options\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
545
        return isc::dhcp::Dhcp6Parser::make_RELAY_SUPPLIED_OPTIONS(driver.loc_);
546
    default:
547
        return isc::dhcp::Dhcp6Parser::make_STRING("relay-supplied-options", driver.loc_);
548 549 550 551 552 553
    }
}

\"host-reservation-identifiers\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
554
        return isc::dhcp::Dhcp6Parser::make_HOST_RESERVATION_IDENTIFIERS(driver.loc_);
555
    default:
556
        return isc::dhcp::Dhcp6Parser::make_STRING("host-reservation-identifiers", driver.loc_);
557 558 559 560 561 562
    }
}

\"Logging\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
563
        return isc::dhcp::Dhcp6Parser::make_LOGGING(driver.loc_);
564
    default:
565
        return isc::dhcp::Dhcp6Parser::make_STRING("Logging", driver.loc_);
566 567 568 569 570 571
    }
}

\"loggers\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::LOGGING:
572
        return isc::dhcp::Dhcp6Parser::make_LOGGERS(driver.loc_);
573
    default:
574
        return isc::dhcp::Dhcp6Parser::make_STRING("loggers", driver.loc_);
575 576 577 578 579 580
    }
}

\"output_options\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::LOGGERS:
581
        return isc::dhcp::Dhcp6Parser::make_OUTPUT_OPTIONS(driver.loc_);
582
    default:
583
        return isc::dhcp::Dhcp6Parser::make_STRING("output_options", driver.loc_);
584 585 586 587 588 589
    }
}

\"output\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OUTPUT_OPTIONS:
590
        return isc::dhcp::Dhcp6Parser::make_OUTPUT(driver.loc_);
591
    default:
592
        return isc::dhcp::Dhcp6Parser::make_STRING("output", driver.loc_);
593 594 595 596 597 598
    }
}

\"debuglevel\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::LOGGERS:
599
        return isc::dhcp::Dhcp6Parser::make_DEBUGLEVEL(driver.loc_);
600
    default:
601
        return isc::dhcp::Dhcp6Parser::make_STRING("debuglevel", driver.loc_);
602 603 604 605 606 607
    }
}

\"severity\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::LOGGERS:
608
        return isc::dhcp::Dhcp6Parser::make_SEVERITY(driver.loc_);
609
    default:
610
        return isc::dhcp::Dhcp6Parser::make_STRING("severity", driver.loc_);
611 612 613 614 615 616 617
    }
}

\"client-classes\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
    case isc::dhcp::Parser6Context::RESERVATIONS:
618
        return isc::dhcp::Dhcp6Parser::make_CLIENT_CLASSES(driver.loc_);
619
    default:
620
        return isc::dhcp::Dhcp6Parser::make_STRING("client-classes", driver.loc_);
621 622 623 624 625 626 627
    }
}

\"client-class\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
    case isc::dhcp::Parser6Context::CLIENT_CLASSES:
628
        return isc::dhcp::Dhcp6Parser::make_CLIENT_CLASS(driver.loc_);
629
    default:
630
        return isc::dhcp::Dhcp6Parser::make_STRING("client-class", driver.loc_);
631 632 633 634 635 636 637
    }
}

\"test\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CLIENT_CLASSES:
    case isc::dhcp::Parser6Context::CLIENT_CLASS:
638
        return isc::dhcp::Dhcp6Parser::make_TEST(driver.loc_);
639
    default:
640
        return isc::dhcp::Dhcp6Parser::make_STRING("test", driver.loc_);
641 642 643 644 645 646
    }
}

\"reservations\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
647
        return isc::dhcp::Dhcp6Parser::make_RESERVATIONS(driver.loc_);
648
    default:
649
        return isc::dhcp::Dhcp6Parser::make_STRING("reservations", driver.loc_);
650 651 652 653 654 655
    }
}

\"ip-addresses\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RESERVATIONS:
656
        return isc::dhcp::Dhcp6Parser::make_IP_ADDRESSES(driver.loc_);
657
    default:
658
        return isc::dhcp::Dhcp6Parser::make_STRING("ip-addresses", driver.loc_);
659 660 661 662 663 664
    }
}

\"prefixes\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RESERVATIONS:
665
        return isc::dhcp::Dhcp6Parser::make_PREFIXES(driver.loc_);
666
    default:
667
        return isc::dhcp::Dhcp6Parser::make_STRING("prefixes", driver.loc_);
668 669 670 671 672 673 674 675
    }
}

\"duid\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::MAC_SOURCES:
    case isc::dhcp::Parser6Context::HOST_RESERVATION_IDENTIFIERS:
    case isc::dhcp::Parser6Context::RESERVATIONS:
676
        return isc::dhcp::Dhcp6Parser::make_DUID(driver.loc_);
677
    default:
678
        return isc::dhcp::Dhcp6Parser::make_STRING("duid", driver.loc_);
679 680 681 682 683 684 685
    }
}

\"hw-address\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::HOST_RESERVATION_IDENTIFIERS:
    case isc::dhcp::Parser6Context::RESERVATIONS:
686
        return isc::dhcp::Dhcp6Parser::make_HW_ADDRESS(driver.loc_);
687
    default:
688
        return isc::dhcp::Dhcp6Parser::make_STRING("hw-address", driver.loc_);
689 690 691 692 693 694
    }
}

\"hostname\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RESERVATIONS:
695
        return isc::dhcp::Dhcp6Parser::make_HOSTNAME(driver.loc_);
696
    default:
697
        return isc::dhcp::Dhcp6Parser::make_STRING("hostname", driver.loc_);
698 699 700 701 702
    }
}

\"space\" {
    switch(driver.ctx_) {
703
    case isc::dhcp::Parser6Context::OPTION_DEF:
704
    case isc::dhcp::Parser6Context::OPTION_DATA:
705
        return isc::dhcp::Dhcp6Parser::make_SPACE(driver.loc_);
706
    default:
707
        return isc::dhcp::Dhcp6Parser::make_STRING("space", driver.loc_);
708 709 710 711 712 713
    }
}

\"csv-format\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OPTION_DATA:
714
        return isc::dhcp::Dhcp6Parser::make_CSV_FORMAT(driver.loc_);
715
    default:
716
        return isc::dhcp::Dhcp6Parser::make_STRING("csv-format", driver.loc_);
717 718 719
    }
}

720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
\"record-types\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OPTION_DEF:
        return isc::dhcp::Dhcp6Parser::make_RECORD_TYPES(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("record-types", driver.loc_);
    }
}

\"encapsulate\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OPTION_DEF:
        return isc::dhcp::Dhcp6Parser::make_ENCAPSULATE(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("encapsulate", driver.loc_);
    }
}

\"array\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OPTION_DEF:
        return isc::dhcp::Dhcp6Parser::make_ARRAY(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("array", driver.loc_);
    }
}

\"relay\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
        return isc::dhcp::Dhcp6Parser::make_RELAY(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("relay", driver.loc_);
    }
}

\"ip-address\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RELAY:
    return isc::dhcp::Dhcp6Parser::make_IP_ADDRESS(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("ip-address", driver.loc_);
    }
}

765 766 767
\"hooks-libraries\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
768
        return isc::dhcp::Dhcp6Parser::make_HOOKS_LIBRARIES(driver.loc_);
769
    default:
770
        return isc::dhcp::Dhcp6Parser::make_STRING("hooks-libraries", driver.loc_);
771 772 773
    }
}

774 775 776 777 778 779 780 781 782 783

\"parameters\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::HOOKS_LIBRARIES:
        return isc::dhcp::Dhcp6Parser::make_PARAMETERS(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("parameters", driver.loc_);
    }
}

784 785 786
\"library\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::HOOKS_LIBRARIES:
787
        return isc::dhcp::Dhcp6Parser::make_LIBRARY(driver.loc_);
788
    default:
789
        return isc::dhcp::Dhcp6Parser::make_STRING("library", driver.loc_);
790 791 792 793 794 795
    }
}

\"server-id\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
796
        return isc::dhcp::Dhcp6Parser::make_SERVER_ID(driver.loc_);
797
    default:
798
        return isc::dhcp::Dhcp6Parser::make_STRING("server-id", driver.loc_);
799 800 801 802 803 804
    }
}

\"identifier\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
805
        return isc::dhcp::Dhcp6Parser::make_IDENTIFIER(driver.loc_);
806
    default:
807
        return isc::dhcp::Dhcp6Parser::make_STRING("identifier", driver.loc_);
808 809 810 811 812 813
    }
}

\"htype\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
814
        return isc::dhcp::Dhcp6Parser::make_HTYPE(driver.loc_);
815
    default:
816
        return isc::dhcp::Dhcp6Parser::make_STRING("htype", driver.loc_);
817 818 819 820 821 822
    }
}

\"time\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
823
        return isc::dhcp::Dhcp6Parser::make_TIME(driver.loc_);
824
    default:
825
        return isc::dhcp::Dhcp6Parser::make_STRING("time", driver.loc_);
826 827 828 829 830 831
    }
}

\"enterprise-id\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
832
        return isc::dhcp::Dhcp6Parser::make_ENTERPRISE_ID(driver.loc_);
833
    default:
834
        return isc::dhcp::Dhcp6Parser::make_STRING("enterprise-id", driver.loc_);
835 836 837 838 839 840
    }
}

\"expired-leases-processing\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
841
        return isc::dhcp::Dhcp6Parser::make_EXPIRED_LEASES_PROCESSING(driver.loc_);
842
    default:
843
        return isc::dhcp::Dhcp6Parser::make_STRING("expired-leases-processing", driver.loc_);
844 845 846 847 848 849
    }
}

\"dhcp4o6-port\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
850
        return isc::dhcp::Dhcp6Parser::make_DHCP4O6_PORT(driver.loc_);
851
    default:
852
        return isc::dhcp::Dhcp6Parser::make_STRING("dhcp4o6-port", driver.loc_);
853 854 855
    }
}

856
\"version\" {
857 858
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
859
        return isc::dhcp::Dhcp6Parser::make_VERSION(driver.loc_);
860
    default:
861 862 863 864 865 866 867 868 869 870
        return isc::dhcp::Dhcp6Parser::make_STRING("version", driver.loc_);
    }
}

\"control-socket\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
        return isc::dhcp::Dhcp6Parser::make_CONTROL_SOCKET(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("control-socket", driver.loc_);
871 872 873
    }
}

874
\"socket-type\" {
875
    switch(driver.ctx_) {
876 877
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_TYPE(driver.loc_);
878
    default:
879
        return isc::dhcp::Dhcp6Parser::make_STRING("socket-type", driver.loc_);
880 881 882
    }
}

883
\"socket-name\" {
884
    switch(driver.ctx_) {
885 886
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_NAME(driver.loc_);
887
    default:
888 889 890 891 892 893 894 895 896 897
        return isc::dhcp::Dhcp6Parser::make_STRING("socket-name", driver.loc_);
    }
}

\"dhcp-ddns\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
        return isc::dhcp::Dhcp6Parser::make_DHCP_DDNS(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("dhcp-ddns", driver.loc_);
898 899
    }
}
900

901 902 903
\"Dhcp4\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
904
        return isc::dhcp::Dhcp6Parser::make_DHCP4(driver.loc_);
905
    default:
906
        return isc::dhcp::Dhcp6Parser::make_STRING("Dhcp4", driver.loc_);
907 908 909 910 911 912
    }
}

\"DhcpDdns\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
913
        return isc::dhcp::Dhcp6Parser::make_DHCPDDNS(driver.loc_);
914
    default:
915
        return isc::dhcp::Dhcp6Parser::make_STRING("DhcpDdns", driver.loc_);
916 917
    }
}
918

919 920 921 922
{JSONString} {
    // A string has been matched. It contains the actual string and single quotes.
    // We need to get those quotes out of the way and just use its content, e.g.
    // for 'foo' we should get foo
923 924 925 926 927 928 929 930 931 932
    std::string raw(yytext+1);
    size_t len = raw.size() - 1;
    raw.resize(len);
    std::string decoded;
    decoded.reserve(len);
    for (size_t pos = 0; pos < len; ++pos) {
        char c = raw[pos];
        switch (c) {
        case '"':
            // impossible condition
933
            driver.error(driver.loc_, "Bad quote in \"" + raw + "\"");
934 935 936 937
        case '\\':
            ++pos;
            if (pos >= len) {
                // impossible condition
938
                driver.error(driver.loc_, "Overflow escape in \"" + raw + "\"");
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
            }
            c = raw[pos];
            switch (c) {
            case '"':
            case '\\':
            case '/':
                decoded.push_back(c);
                break;
            case 'b':
                decoded.push_back('\b');
                break;
            case 'f':
                decoded.push_back('\f');
                break;
            case 'n':
                decoded.push_back('\n');
                break;
            case 'r':
                decoded.push_back('\r');
                break;
            case 't':
                decoded.push_back('\t');
                break;
            case 'u':
                // not yet implemented
964
                driver.error(driver.loc_, "Unsupported unicode escape in \"" + raw + "\"");
965 966
            default:
                // impossible condition
967
                driver.error(driver.loc_, "Bad escape in \"" + raw + "\"");
968 969 970
            }
            break;
        default:
971
            if ((c >= 0) && (c < 0x20)) {
972
                // impossible condition
973
                driver.error(driver.loc_, "Invalid control in \"" + raw + "\"");
974 975 976 977
            }
            decoded.push_back(c);
        }
    }
978

979
    return isc::dhcp::Dhcp6Parser::make_STRING(decoded, driver.loc_);
980 981 982 983
}

\"{JSONStringCharacter}*{ControlCharacter}{ControlCharacterFill}*\" {
    // Bad string with a forbidden control character inside
984
    driver.error(driver.loc_, "Invalid control in " + std::string(yytext));
985 986 987 988
}

\"{JSONStringCharacter}*\\{BadJSONEscapeSequence}[^\x00-\x1f"]*\" {
    // Bad string with a bad escape inside
989
    driver.error(driver.loc_, "Bad escape in " + std::string(yytext));
990
}
991

992 993
\"{JSONStringCharacter}*\\\" {
    // Bad string with an open escape at the end
994
    driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
995 996
}

997 998 999 1000 1001 1002
"["    { return isc::dhcp::Dhcp6Parser::make_LSQUARE_BRACKET(driver.loc_); }
"]"    { return isc::dhcp::Dhcp6Parser::make_RSQUARE_BRACKET(driver.loc_); }
"{"    { return isc::dhcp::Dhcp6Parser::make_LCURLY_BRACKET(driver.loc_); }
"}"    { return isc::dhcp::Dhcp6Parser::make_RCURLY_BRACKET(driver.loc_); }
","    { return isc::dhcp::Dhcp6Parser::make_COMMA(driver.loc_); }
":"    { return isc::dhcp::Dhcp6Parser::make_COLON(driver.loc_); }
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014

{int} {
    // An integer was found.
    std::string tmp(yytext);
    int64_t integer = 0;
    try {
        // In substring we want to use negative values (e.g. -1).
        // In enterprise-id we need to use values up to 0xffffffff.
        // To cover both of those use cases, we need at least
        // int64_t.
        integer = boost::lexical_cast<int64_t>(tmp);
    } catch (const boost::bad_lexical_cast &) {
1015
        driver.error(driver.loc_, "Failed to convert " + tmp + " to an integer.");
1016 1017 1018
    }

    // The parser needs the string form as double conversion is no lossless
1019
    return isc::dhcp::Dhcp6Parser::make_INTEGER(integer, driver.loc_);
1020
}
1021

1022 1023 1024 1025 1026 1027 1028
[-+]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)? {
    // A floating point was found.
    std::string tmp(yytext);
    double fp = 0.0;
    try {
        fp = boost::lexical_cast<double>(tmp);
    } catch (const boost::bad_lexical_cast &) {
1029
        driver.error(driver.loc_, "Failed to convert " + tmp + " to a floating point.");
1030 1031
    }

1032
    return isc::dhcp::Dhcp6Parser::make_FLOAT(fp, driver.loc_);
1033 1034 1035 1036
}

true|false {
    string tmp(yytext);
1037
    return isc::dhcp::Dhcp6Parser::make_BOOLEAN(tmp == "true", driver.loc_);
1038 1039 1040
}

null {
1041
   return isc::dhcp::Dhcp6Parser::make_NULL_TYPE(driver.loc_);