dhcp6_lexer.ll 33.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 69 70
/* 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]+
blank [ \t]

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) {
Tomek Mrugalski's avatar
Tomek Mrugalski committed
105
        case Parser6Context::SUBPARSER_JSON:
106
        default:
Tomek Mrugalski's avatar
Tomek Mrugalski committed
107 108
            return isc::dhcp::Dhcp6Parser::make_SUB_JSON(driver.loc_);
//            return isc::dhcp::Dhcp6Parser::make_TOPLEVEL_GENERIC_JSON(driver.loc_);
109
        case Parser6Context::PARSER_DHCP6:
110
            return isc::dhcp::Dhcp6Parser::make_TOPLEVEL_DHCP6(driver.loc_);
111 112
        case Parser6Context::SUBPARSER_DHCP6:
            return isc::dhcp::Dhcp6Parser::make_SUB_DHCP6(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
113
        case Parser6Context::PARSER_INTERFACES:
114
            return isc::dhcp::Dhcp6Parser::make_SUB_INTERFACES6(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
115
        case Parser6Context::PARSER_SUBNET6:
116
            return isc::dhcp::Dhcp6Parser::make_SUB_SUBNET6(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
117
        case Parser6Context::PARSER_POOL6:
118
            return isc::dhcp::Dhcp6Parser::make_SUB_POOL6(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
119
        case Parser6Context::PARSER_PD_POOL:
120
            return isc::dhcp::Dhcp6Parser::make_SUB_PD_POOL(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
121
        case Parser6Context::PARSER_HOST_RESERVATION:
122
            return isc::dhcp::Dhcp6Parser::make_SUB_RESERVATION(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
123
        case Parser6Context::PARSER_OPTION_DATA:
124
            return isc::dhcp::Dhcp6Parser::make_SUB_OPTION_DATA(driver.loc_);
Tomek Mrugalski's avatar
Tomek Mrugalski committed
125
        case Parser6Context::PARSER_HOOKS_LIBRARY:
126
            return isc::dhcp::Dhcp6Parser::make_SUB_HOOKS_LIBRARY(driver.loc_);
127 128
        }
    }
129 130
%}

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

"//"(.*) ;

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

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

Francis Dupont's avatar
Francis Dupont committed
146 147 148 149 150 151 152 153 154
"<?" 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);

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

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

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

174

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

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

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

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

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

\"type\" {
    switch(driver.ctx_) {
222 223
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
224
    case isc::dhcp::Parser6Context::OPTION_DEF:
225
    case isc::dhcp::Parser6Context::SERVER_ID:
226
        return isc::dhcp::Dhcp6Parser::make_TYPE(driver.loc_);
227
    default:
228
        return isc::dhcp::Dhcp6Parser::make_STRING("type", driver.loc_);
229 230 231 232 233
    }
}

\"user\" {
    switch(driver.ctx_) {
234 235
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
236
        return isc::dhcp::Dhcp6Parser::make_USER(driver.loc_);
237
    default:
238
        return isc::dhcp::Dhcp6Parser::make_STRING("user", driver.loc_);
239 240 241 242 243
    }
}

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

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

\"persist\" {
    switch(driver.ctx_) {
264 265
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
266
    case isc::dhcp::Parser6Context::SERVER_ID:
267
        return isc::dhcp::Dhcp6Parser::make_PERSIST(driver.loc_);
268
    default:
269
        return isc::dhcp::Dhcp6Parser::make_STRING("persist", driver.loc_);
270 271 272 273 274
    }
}

\"lfc-interval\" {
    switch(driver.ctx_) {
275 276
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
277
        return isc::dhcp::Dhcp6Parser::make_LFC_INTERVAL(driver.loc_);
278
    default:
279
        return isc::dhcp::Dhcp6Parser::make_STRING("lfc-interval", driver.loc_);
280 281 282 283 284 285
    }
}

\"preferred-lifetime\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
286
    case isc::dhcp::Parser6Context::SUBNET6:
287
        return isc::dhcp::Dhcp6Parser::make_PREFERRED_LIFETIME(driver.loc_);
288
    default:
289
        return isc::dhcp::Dhcp6Parser::make_STRING("preferred-lifetime", driver.loc_);
290 291 292 293 294 295
    }
}

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

\"renew-timer\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
306
    case isc::dhcp::Parser6Context::SUBNET6:
307
        return isc::dhcp::Dhcp6Parser::make_RENEW_TIMER(driver.loc_);
308
    default:
309
        return isc::dhcp::Dhcp6Parser::make_STRING("renew-timer", driver.loc_);
310 311 312 313 314 315
    }
}

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

323 324 325 326 327 328 329 330 331
\"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_);
    }
}

332 333 334
\"subnet6\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
335
        return isc::dhcp::Dhcp6Parser::make_SUBNET6(driver.loc_);
336
    default:
337
        return isc::dhcp::Dhcp6Parser::make_STRING("subnet6", driver.loc_);
338 339 340
    }
}

341 342 343 344 345 346 347 348 349
\"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_);
    }
}

350 351 352 353 354 355 356 357 358
\"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:
359
        return isc::dhcp::Dhcp6Parser::make_OPTION_DATA(driver.loc_);
360
    default:
361
        return isc::dhcp::Dhcp6Parser::make_STRING("option-data", driver.loc_);
362 363 364 365 366
    }
}

\"name\" {
    switch(driver.ctx_) {
367 368
    case isc::dhcp::Parser6Context::LEASE_DATABASE:
    case isc::dhcp::Parser6Context::HOSTS_DATABASE:
369
    case isc::dhcp::Parser6Context::OPTION_DEF:
370 371 372 373
    case isc::dhcp::Parser6Context::OPTION_DATA:
    case isc::dhcp::Parser6Context::CLIENT_CLASSES:
    case isc::dhcp::Parser6Context::CLIENT_CLASS:
    case isc::dhcp::Parser6Context::LOGGERS:
374
        return isc::dhcp::Dhcp6Parser::make_NAME(driver.loc_);
375
    default:
376
        return isc::dhcp::Dhcp6Parser::make_STRING("name", driver.loc_);
377 378 379 380 381 382
    }
}

\"data\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OPTION_DATA:
383
        return isc::dhcp::Dhcp6Parser::make_DATA(driver.loc_);
384
    default:
385
        return isc::dhcp::Dhcp6Parser::make_STRING("data", driver.loc_);
386 387 388 389 390 391
    }
}

\"pools\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
392
        return isc::dhcp::Dhcp6Parser::make_POOLS(driver.loc_);
393
    default:
394
        return isc::dhcp::Dhcp6Parser::make_STRING("pools", driver.loc_);
395 396 397 398 399 400
    }
}

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

\"prefix\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::PD_POOLS:
410
        return isc::dhcp::Dhcp6Parser::make_PREFIX(driver.loc_);
411
    default:
412
        return isc::dhcp::Dhcp6Parser::make_STRING("prefix", driver.loc_);
413 414 415 416 417 418
    }
}

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

\"delegated-len\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::PD_POOLS:
428
        return isc::dhcp::Dhcp6Parser::make_DELEGATED_LEN(driver.loc_);
429
    default:
430
        return isc::dhcp::Dhcp6Parser::make_STRING("delegated-len", driver.loc_);
431 432 433 434 435 436
    }
}

\"pool\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::POOLS:
437
        return isc::dhcp::Dhcp6Parser::make_POOL(driver.loc_);
438
    default:
439
        return isc::dhcp::Dhcp6Parser::make_STRING("pool", driver.loc_);
440 441 442 443 444 445
    }
}

\"subnet\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
446
        return isc::dhcp::Dhcp6Parser::make_SUBNET(driver.loc_);
447
    default:
448
        return isc::dhcp::Dhcp6Parser::make_STRING("subnet", driver.loc_);
449 450 451 452 453 454
    }
}

\"interface\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
455
        return isc::dhcp::Dhcp6Parser::make_INTERFACE(driver.loc_);
456
    default:
457
        return isc::dhcp::Dhcp6Parser::make_STRING("interface", driver.loc_);
458 459 460
    }
}

461 462 463 464 465 466 467 468 469
\"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_);
    }
}

470 471 472
\"id\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
473
        return isc::dhcp::Dhcp6Parser::make_ID(driver.loc_);
474
    default:
475
        return isc::dhcp::Dhcp6Parser::make_STRING("id", driver.loc_);
476 477 478
    }
}

479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
\"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_);
    }
}

497 498
\"code\" {
    switch(driver.ctx_) {
499
    case isc::dhcp::Parser6Context::OPTION_DEF:
500
    case isc::dhcp::Parser6Context::OPTION_DATA:
501
        return isc::dhcp::Dhcp6Parser::make_CODE(driver.loc_);
502
    default:
503
        return isc::dhcp::Dhcp6Parser::make_STRING("code", driver.loc_);
504 505 506 507 508 509
    }
}

\"mac-sources\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
510
        return isc::dhcp::Dhcp6Parser::make_MAC_SOURCES(driver.loc_);
511
    default:
512
        return isc::dhcp::Dhcp6Parser::make_STRING("mac-sources", driver.loc_);
513 514 515 516 517 518
    }
}

\"relay-supplied-options\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
519
        return isc::dhcp::Dhcp6Parser::make_RELAY_SUPPLIED_OPTIONS(driver.loc_);
520
    default:
521
        return isc::dhcp::Dhcp6Parser::make_STRING("relay-supplied-options", driver.loc_);
522 523 524 525 526 527
    }
}

\"host-reservation-identifiers\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
528
        return isc::dhcp::Dhcp6Parser::make_HOST_RESERVATION_IDENTIFIERS(driver.loc_);
529
    default:
530
        return isc::dhcp::Dhcp6Parser::make_STRING("host-reservation-identifiers", driver.loc_);
531 532 533 534 535 536
    }
}

\"Logging\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
537
        return isc::dhcp::Dhcp6Parser::make_LOGGING(driver.loc_);
538
    default:
539
        return isc::dhcp::Dhcp6Parser::make_STRING("Logging", driver.loc_);
540 541 542 543 544 545
    }
}

\"loggers\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::LOGGING:
546
        return isc::dhcp::Dhcp6Parser::make_LOGGERS(driver.loc_);
547
    default:
548
        return isc::dhcp::Dhcp6Parser::make_STRING("loggers", driver.loc_);
549 550 551 552 553 554
    }
}

\"output_options\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::LOGGERS:
555
        return isc::dhcp::Dhcp6Parser::make_OUTPUT_OPTIONS(driver.loc_);
556
    default:
557
        return isc::dhcp::Dhcp6Parser::make_STRING("output_options", driver.loc_);
558 559 560 561 562 563
    }
}

\"output\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OUTPUT_OPTIONS:
564
        return isc::dhcp::Dhcp6Parser::make_OUTPUT(driver.loc_);
565
    default:
566
        return isc::dhcp::Dhcp6Parser::make_STRING("output", driver.loc_);
567 568 569 570 571 572
    }
}

\"debuglevel\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::LOGGERS:
573
        return isc::dhcp::Dhcp6Parser::make_DEBUGLEVEL(driver.loc_);
574
    default:
575
        return isc::dhcp::Dhcp6Parser::make_STRING("debuglevel", driver.loc_);
576 577 578 579 580 581
    }
}

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

\"client-classes\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
    case isc::dhcp::Parser6Context::RESERVATIONS:
592
        return isc::dhcp::Dhcp6Parser::make_CLIENT_CLASSES(driver.loc_);
593
    default:
594
        return isc::dhcp::Dhcp6Parser::make_STRING("client-classes", driver.loc_);
595 596 597 598 599 600 601
    }
}

\"client-class\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
    case isc::dhcp::Parser6Context::CLIENT_CLASSES:
602
        return isc::dhcp::Dhcp6Parser::make_CLIENT_CLASS(driver.loc_);
603
    default:
604
        return isc::dhcp::Dhcp6Parser::make_STRING("client-class", driver.loc_);
605 606 607 608 609 610 611
    }
}

\"test\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CLIENT_CLASSES:
    case isc::dhcp::Parser6Context::CLIENT_CLASS:
612
        return isc::dhcp::Dhcp6Parser::make_TEST(driver.loc_);
613
    default:
614
        return isc::dhcp::Dhcp6Parser::make_STRING("test", driver.loc_);
615 616 617 618 619 620
    }
}

\"reservations\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
621
        return isc::dhcp::Dhcp6Parser::make_RESERVATIONS(driver.loc_);
622
    default:
623
        return isc::dhcp::Dhcp6Parser::make_STRING("reservations", driver.loc_);
624 625 626 627 628 629
    }
}

\"ip-addresses\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RESERVATIONS:
630
        return isc::dhcp::Dhcp6Parser::make_IP_ADDRESSES(driver.loc_);
631
    default:
632
        return isc::dhcp::Dhcp6Parser::make_STRING("ip-addresses", driver.loc_);
633 634 635 636 637 638
    }
}

\"prefixes\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RESERVATIONS:
639
        return isc::dhcp::Dhcp6Parser::make_PREFIXES(driver.loc_);
640
    default:
641
        return isc::dhcp::Dhcp6Parser::make_STRING("prefixes", driver.loc_);
642 643 644 645 646 647 648 649
    }
}

\"duid\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::MAC_SOURCES:
    case isc::dhcp::Parser6Context::HOST_RESERVATION_IDENTIFIERS:
    case isc::dhcp::Parser6Context::RESERVATIONS:
650
        return isc::dhcp::Dhcp6Parser::make_DUID(driver.loc_);
651
    default:
652
        return isc::dhcp::Dhcp6Parser::make_STRING("duid", driver.loc_);
653 654 655 656 657 658 659
    }
}

\"hw-address\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::HOST_RESERVATION_IDENTIFIERS:
    case isc::dhcp::Parser6Context::RESERVATIONS:
660
        return isc::dhcp::Dhcp6Parser::make_HW_ADDRESS(driver.loc_);
661
    default:
662
        return isc::dhcp::Dhcp6Parser::make_STRING("hw-address", driver.loc_);
663 664 665 666 667 668
    }
}

\"hostname\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RESERVATIONS:
669
        return isc::dhcp::Dhcp6Parser::make_HOSTNAME(driver.loc_);
670
    default:
671
        return isc::dhcp::Dhcp6Parser::make_STRING("hostname", driver.loc_);
672 673 674 675 676
    }
}

\"space\" {
    switch(driver.ctx_) {
677
    case isc::dhcp::Parser6Context::OPTION_DEF:
678
    case isc::dhcp::Parser6Context::OPTION_DATA:
679
        return isc::dhcp::Dhcp6Parser::make_SPACE(driver.loc_);
680
    default:
681
        return isc::dhcp::Dhcp6Parser::make_STRING("space", driver.loc_);
682 683 684 685 686 687
    }
}

\"csv-format\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OPTION_DATA:
688
        return isc::dhcp::Dhcp6Parser::make_CSV_FORMAT(driver.loc_);
689
    default:
690
        return isc::dhcp::Dhcp6Parser::make_STRING("csv-format", driver.loc_);
691 692 693
    }
}

694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
\"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_);
    }
}

739 740 741
\"hooks-libraries\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
742
        return isc::dhcp::Dhcp6Parser::make_HOOKS_LIBRARIES(driver.loc_);
743
    default:
744
        return isc::dhcp::Dhcp6Parser::make_STRING("hooks-libraries", driver.loc_);
745 746 747 748 749 750
    }
}

\"library\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::HOOKS_LIBRARIES:
751
        return isc::dhcp::Dhcp6Parser::make_LIBRARY(driver.loc_);
752
    default:
753
        return isc::dhcp::Dhcp6Parser::make_STRING("library", driver.loc_);
754 755 756 757 758 759
    }
}

\"server-id\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
760
        return isc::dhcp::Dhcp6Parser::make_SERVER_ID(driver.loc_);
761
    default:
762
        return isc::dhcp::Dhcp6Parser::make_STRING("server-id", driver.loc_);
763 764 765 766 767 768
    }
}

\"identifier\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
769
        return isc::dhcp::Dhcp6Parser::make_IDENTIFIER(driver.loc_);
770
    default:
771
        return isc::dhcp::Dhcp6Parser::make_STRING("identifier", driver.loc_);
772 773 774 775 776 777
    }
}

\"htype\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
778
        return isc::dhcp::Dhcp6Parser::make_HTYPE(driver.loc_);
779
    default:
780
        return isc::dhcp::Dhcp6Parser::make_STRING("htype", driver.loc_);
781 782 783 784 785 786
    }
}

\"time\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SERVER_ID:
787
        return isc::dhcp::Dhcp6Parser::make_TIME(driver.loc_);
788
    default:
789
        return isc::dhcp::Dhcp6Parser::make_STRING("time", driver.loc_);
790 791 792 793 794 795
    }
}

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

\"expired-leases-processing\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
805
        return isc::dhcp::Dhcp6Parser::make_EXPIRED_LEASES_PROCESSING(driver.loc_);
806
    default:
807
        return isc::dhcp::Dhcp6Parser::make_STRING("expired-leases-processing", driver.loc_);
808 809 810 811 812 813
    }
}

\"dhcp4o6-port\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
814
        return isc::dhcp::Dhcp6Parser::make_DHCP4O6_PORT(driver.loc_);
815
    default:
816
        return isc::dhcp::Dhcp6Parser::make_STRING("dhcp4o6-port", driver.loc_);
817 818 819
    }
}

820
\"version\" {
821 822
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
823
        return isc::dhcp::Dhcp6Parser::make_VERSION(driver.loc_);
824
    default:
825 826 827 828 829 830 831 832 833 834
        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_);
835 836 837
    }
}

838
\"socket-type\" {
839
    switch(driver.ctx_) {
840 841
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_TYPE(driver.loc_);
842
    default:
843
        return isc::dhcp::Dhcp6Parser::make_STRING("socket-type", driver.loc_);
844 845 846
    }
}

847
\"socket-name\" {
848
    switch(driver.ctx_) {
849 850
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_NAME(driver.loc_);
851
    default:
852 853 854 855 856 857 858 859 860 861
        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_);
862 863
    }
}
864

865 866 867
\"Dhcp4\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
868
        return isc::dhcp::Dhcp6Parser::make_DHCP4(driver.loc_);
869
    default:
870
        return isc::dhcp::Dhcp6Parser::make_STRING("Dhcp4", driver.loc_);
871 872 873 874 875 876
    }
}

\"DhcpDdns\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
877
        return isc::dhcp::Dhcp6Parser::make_DHCPDDNS(driver.loc_);
878
    default:
879
        return isc::dhcp::Dhcp6Parser::make_STRING("DhcpDdns", driver.loc_);
880 881
    }
}
882

883 884 885 886
{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
887 888 889 890 891 892 893 894 895 896
    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
897
            driver.error(driver.loc_, "Bad quote in \"" + raw + "\"");
898 899 900 901
        case '\\':
            ++pos;
            if (pos >= len) {
                // impossible condition
902
                driver.error(driver.loc_, "Overflow escape in \"" + raw + "\"");
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
            }
            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
928
                driver.error(driver.loc_, "Unsupported unicode escape in \"" + raw + "\"");
929 930
            default:
                // impossible condition
931
                driver.error(driver.loc_, "Bad escape in \"" + raw + "\"");
932 933 934 935 936
            }
            break;
        default:
            if (c < 0x20) {
                // impossible condition
937
                driver.error(driver.loc_, "Invalid control in \"" + raw + "\"");
938 939 940 941
            }
            decoded.push_back(c);
        }
    }
942

943
    return isc::dhcp::Dhcp6Parser::make_STRING(decoded, driver.loc_);
944 945 946 947
}

\"{JSONStringCharacter}*{ControlCharacter}{ControlCharacterFill}*\" {
    // Bad string with a forbidden control character inside
948
    driver.error(driver.loc_, "Invalid control in " + std::string(yytext));
949 950 951 952
}

\"{JSONStringCharacter}*\\{BadJSONEscapeSequence}[^\x00-\x1f"]*\" {
    // Bad string with a bad escape inside
953
    driver.error(driver.loc_, "Bad escape in " + std::string(yytext));
954 955 956 957
}
    
\"{JSONStringCharacter}*\\\" {
    // Bad string with an open escape at the end
958
    driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
959 960
}

961 962 963 964 965 966
"["    { 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_); }
967 968 969 970 971 972 973 974 975 976 977 978

{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 &) {
979
        driver.error(driver.loc_, "Failed to convert " + tmp + " to an integer.");
980 981 982
    }

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

986 987 988 989 990 991 992
[-+]?[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 &) {
993
        driver.error(driver.loc_, "Failed to convert " + tmp + " to a floating point.");
994 995
    }

996
    return isc::dhcp::Dhcp6Parser::make_FLOAT(fp, driver.loc_);
997 998 999 1000
}

true|false {
    string tmp(yytext);
1001
    return isc::dhcp::Dhcp6Parser::make_BOOLEAN(tmp == "true", driver.loc_);
1002 1003 1004
}

null {
1005
   return isc::dhcp::Dhcp6Parser::make_NULL_TYPE(driver.loc_);
1006 1007
}

1008
<*>.   driver.error (driver.loc_, "Invalid character: " + std::string(yytext));
1009

1010
<<EOF>> {
1011 1012
    if (driver.states_.empty()) {
        return isc::dhcp::Dhcp6Parser::make_END(driver.loc_);
Francis Dupont's avatar
Francis Dupont committed
1013
    }
1014 1015 1016 1017
    driver.loc_ = driver.locs_.back();
    driver.locs_.pop_back();
    driver.file_ = driver.files_.back();
    driver.files_.pop_back();
1018 1019 1020 1021 1022 1023 1024 1025
    if (driver.sfile_) {
        fclose(driver.sfile_);
        driver.sfile_ = 0;
    }
    if (!driver.sfiles_.empty()) {
        driver.sfile_ = driver.sfiles_.back();
        driver.sfiles_.pop_back();
    }
Francis Dupont's avatar
Francis Dupont committed
1026
    parser6__delete_buffer(YY_CURRENT_BUFFER);
1027 1028
    parser6__switch_to_buffer(driver.states_.back());
    driver.states_.pop_back();
Francis Dupont's avatar
Francis Dupont committed
1029 1030 1031 1032

    BEGIN(DIR_EXIT);
}

1033 1034 1035 1036 1037
%%

using namespace isc::dhcp;

void
1038
Parser6Context::scanStringBegin(const std::string& str, ParserType parser_type)