dhcp6_lexer.ll 33.4 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 160 161
<DIR_EXIT>"?>" BEGIN(INITIAL);
    

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
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

\"csv-format\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::OPTION_DATA:
687
        return isc::dhcp::Dhcp6Parser::make_CSV_FORMAT(driver.loc_);
688
    default:
689
        return isc::dhcp::Dhcp6Parser::make_STRING("csv-format", driver.loc_);
690 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
\"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_);
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    BEGIN(DIR_EXIT);
}

1032 1033 1034 1035 1036
%%

using namespace isc::dhcp;

void