dhcp6_lexer.ll 33.9 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) {
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
    }
}

\"delegated-len\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::PD_POOLS:
436
        return isc::dhcp::Dhcp6Parser::make_DELEGATED_LEN(driver.loc_);
437
    default:
438
        return isc::dhcp::Dhcp6Parser::make_STRING("delegated-len", driver.loc_);
439 440 441 442 443 444
    }
}

\"pool\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::POOLS:
445
        return isc::dhcp::Dhcp6Parser::make_POOL(driver.loc_);
446
    default:
447
        return isc::dhcp::Dhcp6Parser::make_STRING("pool", driver.loc_);
448 449 450 451 452 453
    }
}

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

\"interface\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
463
        return isc::dhcp::Dhcp6Parser::make_INTERFACE(driver.loc_);
464
    default:
465
        return isc::dhcp::Dhcp6Parser::make_STRING("interface", driver.loc_);
466 467 468
    }
}

469 470 471 472 473 474 475 476 477
\"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_);
    }
}

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

487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
\"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_);
    }
}

505 506
\"code\" {
    switch(driver.ctx_) {
507
    case isc::dhcp::Parser6Context::OPTION_DEF:
508
    case isc::dhcp::Parser6Context::OPTION_DATA:
509
        return isc::dhcp::Dhcp6Parser::make_CODE(driver.loc_);
510
    default:
511
        return isc::dhcp::Dhcp6Parser::make_STRING("code", driver.loc_);
512 513 514 515 516 517
    }
}

\"mac-sources\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
518
        return isc::dhcp::Dhcp6Parser::make_MAC_SOURCES(driver.loc_);
519
    default:
520
        return isc::dhcp::Dhcp6Parser::make_STRING("mac-sources", driver.loc_);
521 522 523 524 525 526
    }
}

\"relay-supplied-options\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
527
        return isc::dhcp::Dhcp6Parser::make_RELAY_SUPPLIED_OPTIONS(driver.loc_);
528
    default:
529
        return isc::dhcp::Dhcp6Parser::make_STRING("relay-supplied-options", driver.loc_);
530 531 532 533 534 535
    }
}

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

\"Logging\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
545
        return isc::dhcp::Dhcp6Parser::make_LOGGING(driver.loc_);
546
    default:
547
        return isc::dhcp::Dhcp6Parser::make_STRING("Logging", driver.loc_);
548 549 550 551 552 553
    }
}

\"loggers\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::LOGGING:
554
        return isc::dhcp::Dhcp6Parser::make_LOGGERS(driver.loc_);
555
    default:
556
        return isc::dhcp::Dhcp6Parser::make_STRING("loggers", driver.loc_);
557 558 559 560 561 562
    }
}

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

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

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

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

\"client-classes\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
    case isc::dhcp::Parser6Context::RESERVATIONS:
600
        return isc::dhcp::Dhcp6Parser::make_CLIENT_CLASSES(driver.loc_);
601
    default:
602
        return isc::dhcp::Dhcp6Parser::make_STRING("client-classes", driver.loc_);
603 604 605 606 607 608 609
    }
}

\"client-class\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::SUBNET6:
    case isc::dhcp::Parser6Context::CLIENT_CLASSES:
610
        return isc::dhcp::Dhcp6Parser::make_CLIENT_CLASS(driver.loc_);
611
    default:
612
        return isc::dhcp::Dhcp6Parser::make_STRING("client-class", driver.loc_);
613 614 615 616 617 618 619
    }
}

\"test\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CLIENT_CLASSES:
    case isc::dhcp::Parser6Context::CLIENT_CLASS:
620
        return isc::dhcp::Dhcp6Parser::make_TEST(driver.loc_);
621
    default:
622
        return isc::dhcp::Dhcp6Parser::make_STRING("test", driver.loc_);
623 624 625 626 627 628
    }
}

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

\"ip-addresses\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RESERVATIONS:
638
        return isc::dhcp::Dhcp6Parser::make_IP_ADDRESSES(driver.loc_);
639
    default:
640
        return isc::dhcp::Dhcp6Parser::make_STRING("ip-addresses", driver.loc_);
641 642 643 644 645 646
    }
}

\"prefixes\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RESERVATIONS:
647
        return isc::dhcp::Dhcp6Parser::make_PREFIXES(driver.loc_);
648
    default:
649
        return isc::dhcp::Dhcp6Parser::make_STRING("prefixes", driver.loc_);
650 651 652 653 654 655 656 657
    }
}

\"duid\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::MAC_SOURCES:
    case isc::dhcp::Parser6Context::HOST_RESERVATION_IDENTIFIERS:
    case isc::dhcp::Parser6Context::RESERVATIONS:
658
        return isc::dhcp::Dhcp6Parser::make_DUID(driver.loc_);
659
    default:
660
        return isc::dhcp::Dhcp6Parser::make_STRING("duid", driver.loc_);
661 662 663 664 665 666 667
    }
}

\"hw-address\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::HOST_RESERVATION_IDENTIFIERS:
    case isc::dhcp::Parser6Context::RESERVATIONS:
668
        return isc::dhcp::Dhcp6Parser::make_HW_ADDRESS(driver.loc_);
669
    default:
670
        return isc::dhcp::Dhcp6Parser::make_STRING("hw-address", driver.loc_);
671 672 673 674 675 676
    }
}

\"hostname\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::RESERVATIONS:
677
        return isc::dhcp::Dhcp6Parser::make_HOSTNAME(driver.loc_);
678
    default:
679
        return isc::dhcp::Dhcp6Parser::make_STRING("hostname", driver.loc_);
680 681 682 683 684
    }
}

\"space\" {
    switch(driver.ctx_) {
685
    case isc::dhcp::Parser6Context::OPTION_DEF:
686
    case isc::dhcp::Parser6Context::OPTION_DATA:
687
        return isc::dhcp::Dhcp6Parser::make_SPACE(driver.loc_);
688
    default:
689
        return isc::dhcp::Dhcp6Parser::make_STRING("space", driver.loc_);
690 691 692 693 694 695
    }
}

\"csv-format\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OPTION_DATA:
696
        return isc::dhcp::Dhcp6Parser::make_CSV_FORMAT(driver.loc_);
697
    default:
698
        return isc::dhcp::Dhcp6Parser::make_STRING("csv-format", driver.loc_);
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 739 740 741 742 743 744 745 746
\"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_);
    }
}

747 748 749
\"hooks-libraries\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
750
        return isc::dhcp::Dhcp6Parser::make_HOOKS_LIBRARIES(driver.loc_);
751
    default:
752
        return isc::dhcp::Dhcp6Parser::make_STRING("hooks-libraries", driver.loc_);
753 754 755
    }
}

756 757 758 759 760 761 762 763 764 765

\"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_);
    }
}

766 767 768
\"library\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::HOOKS_LIBRARIES:
769
        return isc::dhcp::Dhcp6Parser::make_LIBRARY(driver.loc_);
770
    default:
771
        return isc::dhcp::Dhcp6Parser::make_STRING("library", driver.loc_);
772 773 774 775 776 777
    }
}

\"server-id\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
778
        return isc::dhcp::Dhcp6Parser::make_SERVER_ID(driver.loc_);
779
    default:
780
        return isc::dhcp::Dhcp6Parser::make_STRING("server-id", driver.loc_);
781 782 783 784 785 786
    }
}

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

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

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

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

\"expired-leases-processing\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
823
        return isc::dhcp::Dhcp6Parser::make_EXPIRED_LEASES_PROCESSING(driver.loc_);
824
    default:
825
        return isc::dhcp::Dhcp6Parser::make_STRING("expired-leases-processing", driver.loc_);
826 827 828 829 830 831
    }
}

\"dhcp4o6-port\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
832
        return isc::dhcp::Dhcp6Parser::make_DHCP4O6_PORT(driver.loc_);
833
    default:
834
        return isc::dhcp::Dhcp6Parser::make_STRING("dhcp4o6-port", driver.loc_);
835 836 837
    }
}

838
\"version\" {
839 840
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
841
        return isc::dhcp::Dhcp6Parser::make_VERSION(driver.loc_);
842
    default:
843 844 845 846 847 848 849 850 851 852
        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_);
853 854 855
    }
}

856
\"socket-type\" {
857
    switch(driver.ctx_) {
858 859
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_TYPE(driver.loc_);
860
    default:
861
        return isc::dhcp::Dhcp6Parser::make_STRING("socket-type", driver.loc_);
862 863 864
    }
}

865
\"socket-name\" {
866
    switch(driver.ctx_) {
867 868
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_NAME(driver.loc_);
869
    default:
870 871 872 873 874 875 876 877 878 879
        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_);
880 881
    }
}
882

883 884 885
\"Dhcp4\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
886
        return isc::dhcp::Dhcp6Parser::make_DHCP4(driver.loc_);
887
    default:
888
        return isc::dhcp::Dhcp6Parser::make_STRING("Dhcp4", driver.loc_);
889 890 891 892 893 894
    }
}

\"DhcpDdns\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
895
        return isc::dhcp::Dhcp6Parser::make_DHCPDDNS(driver.loc_);
896
    default:
897
        return isc::dhcp::Dhcp6Parser::make_STRING("DhcpDdns", driver.loc_);
898 899
    }
}
900

901 902 903 904
{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
905 906 907 908 909 910 911 912 913 914
    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
915
            driver.error(driver.loc_, "Bad quote in \"" + raw + "\"");
916 917 918 919
        case '\\':
            ++pos;
            if (pos >= len) {
                // impossible condition
920
                driver.error(driver.loc_, "Overflow escape in \"" + raw + "\"");
921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
            }
            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
946
                driver.error(driver.loc_, "Unsupported unicode escape in \"" + raw + "\"");
947 948
            default:
                // impossible condition
949
                driver.error(driver.loc_, "Bad escape in \"" + raw + "\"");
950 951 952 953 954
            }
            break;
        default:
            if (c < 0x20) {
                // impossible condition
955
                driver.error(driver.loc_, "Invalid control in \"" + raw + "\"");
956 957 958 959
            }
            decoded.push_back(c);
        }
    }
960

961
    return isc::dhcp::Dhcp6Parser::make_STRING(decoded, driver.loc_);
962 963 964 965
}

\"{JSONStringCharacter}*{ControlCharacter}{ControlCharacterFill}*\" {
    // Bad string with a forbidden control character inside
966
    driver.error(driver.loc_, "Invalid control in " + std::string(yytext));
967 968 969 970
}

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

974 975
\"{JSONStringCharacter}*\\\" {
    // Bad string with an open escape at the end
976
    driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
977 978
}

979 980 981 982 983 984
"["    { 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_); }
985 986 987 988 989 990 991 992 993 994 995 996

{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 &) {
997
        driver.error(driver.loc_, "Failed to convert " + tmp + " to an integer.");
998 999 1000
    }

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

1004 1005 1006 1007 1008 1009 1010
[-+]?[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 &) {
1011
        driver.error(driver.loc_, "Failed to convert " + tmp + " to a floating point.");
1012 1013
    }

1014
    return isc::dhcp::Dhcp6Parser::make_FLOAT(fp, driver.loc_);
1015 1016 1017 1018
}

true|false {
    string tmp(yytext);
1019
    return isc::dhcp::Dhcp6Parser::make_BOOLEAN(tmp == "true", driver.loc_);
1020 1021 1022
}

null {
1023
   return isc::dhcp::Dhcp6Parser::make_NULL_TYPE(driver.loc_);
1024 1025
}

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

1028
<<EOF>> {
1029 1030
    if (driver.states_.empty()) {
        return isc::dhcp::Dhcp6Parser::make_END(driver.loc_);
Francis Dupont's avatar
Francis Dupont committed
1031
    }
1032 1033 1034 1035
    driver.loc_ = driver.locs_.back();
    driver.locs_.pop_back();
    driver.file_ = driver.files_.back();
    driver.files_.pop_back();