dhcp6_lexer.ll 33.7 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 750 751 752 753 754 755 756

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

757 758 759
\"library\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::HOOKS_LIBRARIES:
760
        return isc::dhcp::Dhcp6Parser::make_LIBRARY(driver.loc_);
761
    default:
762
        return isc::dhcp::Dhcp6Parser::make_STRING("library", driver.loc_);
763 764 765 766 767 768
    }
}

\"server-id\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
769
        return isc::dhcp::Dhcp6Parser::make_SERVER_ID(driver.loc_);
770
    default:
771
        return isc::dhcp::Dhcp6Parser::make_STRING("server-id", driver.loc_);
772 773 774 775 776 777
    }
}

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

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

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

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

\"expired-leases-processing\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
814
        return isc::dhcp::Dhcp6Parser::make_EXPIRED_LEASES_PROCESSING(driver.loc_);
815
    default:
816
        return isc::dhcp::Dhcp6Parser::make_STRING("expired-leases-processing", driver.loc_);
817 818 819 820 821 822
    }
}

\"dhcp4o6-port\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
823
        return isc::dhcp::Dhcp6Parser::make_DHCP4O6_PORT(driver.loc_);
824
    default:
825
        return isc::dhcp::Dhcp6Parser::make_STRING("dhcp4o6-port", driver.loc_);
826 827 828
    }
}

829
\"version\" {
830 831
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::DHCP6:
832
        return isc::dhcp::Dhcp6Parser::make_VERSION(driver.loc_);
833
    default:
834 835 836 837 838 839 840 841 842 843
        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_);
844 845 846
    }
}

847
\"socket-type\" {
848
    switch(driver.ctx_) {
849 850
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_TYPE(driver.loc_);
851
    default:
852
        return isc::dhcp::Dhcp6Parser::make_STRING("socket-type", driver.loc_);
853 854 855
    }
}

856
\"socket-name\" {
857
    switch(driver.ctx_) {
858 859
    case isc::dhcp::Parser6Context::CONTROL_SOCKET:
        return isc::dhcp::Dhcp6Parser::make_SOCKET_NAME(driver.loc_);
860
    default:
861 862 863 864 865 866 867 868 869 870
        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_);
871 872
    }
}
873

874 875 876
\"Dhcp4\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
877
        return isc::dhcp::Dhcp6Parser::make_DHCP4(driver.loc_);
878
    default:
879
        return isc::dhcp::Dhcp6Parser::make_STRING("Dhcp4", driver.loc_);
880 881 882 883 884 885
    }
}

\"DhcpDdns\" {
    switch(driver.ctx_) {
    case isc::dhcp::Parser6Context::CONFIG:
886
        return isc::dhcp::Dhcp6Parser::make_DHCPDDNS(driver.loc_);
887
    default:
888
        return isc::dhcp::Dhcp6Parser::make_STRING("DhcpDdns", driver.loc_);
889 890
    }
}
891

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

952
    return isc::dhcp::Dhcp6Parser::make_STRING(decoded, driver.loc_);
953 954 955 956
}

\"{JSONStringCharacter}*{ControlCharacter}{ControlCharacterFill}*\" {
    // Bad string with a forbidden control character inside
957
    driver.error(driver.loc_, "Invalid control in " + std::string(yytext));
958 959 960 961
}

\"{JSONStringCharacter}*\\{BadJSONEscapeSequence}[^\x00-\x1f"]*\" {
    // Bad string with a bad escape inside
962
    driver.error(driver.loc_, "Bad escape in " + std::string(yytext));
963 964 965 966
}
    
\"{JSONStringCharacter}*\\\" {
    // Bad string with an open escape at the end
967
    driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
968 969
}

970 971 972 973 974 975
"["    { 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_); }
976 977 978 979 980 981 982 983 984 985 986 987

{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 &) {
988
        driver.error(driver.loc_, "Failed to convert " + tmp + " to an integer.");
989 990 991
    }

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

995 996 997 998 999 1000 1001
[-+]?[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 &) {
1002
        driver.error(driver.loc_, "Failed to convert " + tmp + " to a floating point.");
1003 1004
    }

1005
    return isc::dhcp::Dhcp6Parser::make_FLOAT(fp, driver.loc_);
1006 1007 1008 1009
}

true|false {
    string tmp(yytext);
1010
    return isc::dhcp::Dhcp6Parser::make_BOOLEAN(tmp == "true", driver.loc_);
1011 1012 1013
}

null {
1014
   return isc::dhcp::Dhcp6Parser::make_NULL_TYPE(driver.loc_);
1015 1016
}

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

1019
<<EOF>> {
1020 1021
    if (driver.states_.empty()) {
        return isc::dhcp::Dhcp6Parser::make_END(driver.loc_);
Francis Dupont's avatar
Francis Dupont committed
1022
    }
1023 1024 1025 1026
    driver.loc_ = driver.locs_.back();
    driver.locs_.pop_back();
    driver.file_ = driver.files_.back();
    driver.files_.pop_back();
1027 1028 1029 1030 1031 1032 1033 1034
    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
1035
    parser6__delete_buffer(YY_CURRENT_BUFFER);
1036 1037
    parser6__switch_to_buffer(driver.states_.back());
    driver.states_.pop_back();
Francis Dupont's avatar
Francis Dupont committed
1038 1039 1040 1041

    BEGIN(DIR_EXIT);
}