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

   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 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
\"LLT\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DUID_TYPE:
        return isc::dhcp::Dhcp6Parser::make_LLT(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("LLT", driver.loc_);
    }
}

\"EN\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DUID_TYPE:
        return isc::dhcp::Dhcp6Parser::make_EN(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("EN", driver.loc_);
    }
}

\"LL\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DUID_TYPE:
        return isc::dhcp::Dhcp6Parser::make_LL(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("LL", driver.loc_);
    }
}

829 830 831
\"identifier\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
832
        return isc::dhcp::Dhcp6Parser::make_IDENTIFIER(driver.loc_);
833
    default:
834
        return isc::dhcp::Dhcp6Parser::make_STRING("identifier", driver.loc_);
835 836 837 838 839 840
    }
}

\"htype\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
841
        return isc::dhcp::Dhcp6Parser::make_HTYPE(driver.loc_);
842
    default:
843
        return isc::dhcp::Dhcp6Parser::make_STRING("htype", driver.loc_);
844 845 846 847 848 849
    }
}

\"time\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
850
        return isc::dhcp::Dhcp6Parser::make_TIME(driver.loc_);
851
    default:
852
        return isc::dhcp::Dhcp6Parser::make_STRING("time", driver.loc_);
853 854 855 856 857 858
    }
}

\"enterprise-id\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
859
        return isc::dhcp::Dhcp6Parser::make_ENTERPRISE_ID(driver.loc_);
860
    default:
861
        return isc::dhcp::Dhcp6Parser::make_STRING("enterprise-id", driver.loc_);
862 863 864 865 866 867
    }
}

\"expired-leases-processing\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
868
        return isc::dhcp::Dhcp6Parser::make_EXPIRED_LEASES_PROCESSING(driver.loc_);
869
    default:
870
        return isc::dhcp::Dhcp6Parser::make_STRING("expired-leases-processing", driver.loc_);
871 872 873
    }
}

Francis Dupont's avatar
Francis Dupont committed
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
\"reclaim-timer-wait-time\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::EXPIRED_LEASES_PROCESSING:
        return isc::dhcp::Dhcp6Parser::make_RECLAIM_TIMER_WAIT_TIME(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("reclaim-timer-wait-time", driver.loc_);
    }
}

\"flush-reclaimed-timer-wait-time\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::EXPIRED_LEASES_PROCESSING:
        return isc::dhcp::Dhcp6Parser::make_FLUSH_RECLAIMED_TIMER_WAIT_TIME(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("flush-reclaimed-timer-wait-time", driver.loc_);
    }
}

\"hold-reclaimed-time\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::EXPIRED_LEASES_PROCESSING:
        return isc::dhcp::Dhcp6Parser::make_HOLD_RECLAIMED_TIME(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("hold-reclaimed-time", driver.loc_);
    }
}

\"max-reclaim-leases\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::EXPIRED_LEASES_PROCESSING:
        return isc::dhcp::Dhcp6Parser::make_MAX_RECLAIM_LEASES(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("max-reclaim-leases", driver.loc_);
    }
}

\"max-reclaim-time\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::EXPIRED_LEASES_PROCESSING:
        return isc::dhcp::Dhcp6Parser::make_MAX_RECLAIM_TIME(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("max-reclaim-time", driver.loc_);
    }
}

\"unwarned-reclaim-cycles\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::EXPIRED_LEASES_PROCESSING:
        return isc::dhcp::Dhcp6Parser::make_UNWARNED_RECLAIM_CYCLES(driver.loc_);
    default:
        return isc::dhcp::Dhcp6Parser::make_STRING("unwarned-reclaim-cycles", driver.loc_);
    }
}

928 929 930
\"dhcp4o6-port\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
931
        return isc::dhcp::Dhcp6Parser::make_DHCP4O6_PORT(driver.loc_);
932
    default:
933
        return isc::dhcp::Dhcp6Parser::make_STRING("dhcp4o6-port", driver.loc_);
934 935 936
    }
}

937 938 939 940 941 942
\"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_);
943 944 945
    }
}

946
\"socket-type\" {
947
    switch(driver.ctx_) {
948 949
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_TYPE(driver.loc_);
950
    default:
951
        return isc::dhcp::Dhcp6Parser::make_STRING("socket-type", driver.loc_);
952 953 954
    }
}

955
\"socket-name\" {
956
    switch(driver.ctx_) {
957 958
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_NAME(driver.loc_);
959
    default:
960 961 962 963 964 965 966 967 968 969
        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_);
970 971
    }
}
972

973 974 975
\"Dhcp4\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
976
        return isc::dhcp::Dhcp6Parser::make_DHCP4(driver.loc_);
977
    default:
978
        return isc::dhcp::Dhcp6Parser::make_STRING("Dhcp4", driver.loc_);
979 980 981 982 983 984
    }
}

\"DhcpDdns\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
985
        return isc::dhcp::Dhcp6Parser::make_DHCPDDNS(driver.loc_);
986
    default:
987
        return isc::dhcp::Dhcp6Parser::make_STRING("DhcpDdns", driver.loc_);
988 989
    }
}
990

991 992 993 994
{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
995 996 997 998 999 1000
    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) {
1001
        int b = 0;
1002 1003 1004 1005
        char c = raw[pos];
        switch (c) {
        case '"':
            // impossible condition
1006
            driver.error(driver.loc_, "Bad quote in \"" + raw + "\"");
1007 1008 1009 1010
        case '\\':
            ++pos;
            if (pos >= len) {
                // impossible condition
1011
                driver.error(driver.loc_, "Overflow escape in \"" + raw + "\"");
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
            }
            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':
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
                // support only \u0000 to \u00ff
                ++pos;
                if (pos + 4 > len) {
                    // impossible condition
                    driver.error(driver.loc_,
                                 "Overflow unicode escape in \"" + raw + "\"");
                }
                if ((raw[pos] != '0') || (raw[pos + 1] != '0')) {
                    driver.error(driver.loc_, "Unsupported unicode escape in \"" + raw + "\"");
                }
                pos += 2;
                c = raw[pos];
                if ((c >= '0') && (c <= '9')) {
                    b = (c - '0') << 4;
                } else if ((c >= 'A') && (c <= 'F')) {
                    b = (c - 'A' + 10) << 4;
                } else if ((c >= 'a') && (c <= 'f')) {
                    b = (c - 'a' + 10) << 4;
                } else {
                    // impossible condition
                    driver.error(driver.loc_, "Not hexadecimal in unicode escape in \"" + raw + "\"");
                }
                pos++;
                c = raw[pos];
                if ((c >= '0') && (c <= '9')) {
                    b |= c - '0';
                } else if ((c >= 'A') && (c <= 'F')) {
                    b |= c - 'A' + 10;
                } else if ((c >= 'a') && (c <= 'f')) {
                    b |= c - 'a' + 10;
                } else {
                    // impossible condition
                    driver.error(driver.loc_, "Not hexadecimal in unicode escape in \"" + raw + "\"");
                }
                decoded.push_back(static_cast<char>(b & 0xff));
                break;
1072 1073
            default:
                // impossible condition
1074
                driver.error(driver.loc_, "Bad escape in \"" + raw + "\"");
1075 1076 1077
            }
            break;
        default:
1078
            if ((c >= 0) && (c < 0x20)) {
1079
                // impossible condition
1080
                driver.error(driver.loc_, "Invalid control in \"" + raw + "\"");
1081 1082 1083 1084
            }
            decoded.push_back(c);
        }
    }
1085

1086
    return isc::dhcp::Dhcp6Parser::make_STRING(decoded, driver.loc_);
1087 1088 1089 1090
}

\"{JSONStringCharacter}*{ControlCharacter}{ControlCharacterFill}*\" {
    // Bad string with a forbidden control character inside
1091
    driver.error(driver.loc_, "Invalid control in " + std::string(yytext));
1092 1093 1094 1095
}

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

1099 1100
\"{JSONStringCharacter}*\\\" {
    // Bad string with an open escape at the end
1101
    driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
1102 1103
}

1104 1105 1106 1107 1108 1109
"["    { return isc::dhcp::Dhcp6Parser::make_LSQUARE_BRACKET(driver.loc_); }
"]"    { return isc::dhcp::Dhcp6Parser::make_RSQUARE_BRACKET(driver.loc_); }
"{"