loc.step();
}
+\"Dhcp6\" { return isc::dhcp::Dhcp6Parser::make_DHCP6(loc); }
+\"interfaces-config\" { return isc::dhcp::Dhcp6Parser::make_INTERFACES_CONFIG(loc); }
+\"interfaces\" { return isc::dhcp::Dhcp6Parser::make_INTERFACES(loc); }
+\"lease-database\" { return isc::dhcp::Dhcp6Parser::make_LEASE_DATABASE(loc); }
+\"preferred-lifetime\" { return isc::dhcp::Dhcp6Parser::make_PREFERRED_LIFETIME(loc); }
+\"valid-lifetime\" { return isc::dhcp::Dhcp6Parser::make_VALID_LIFETIME(loc); }
+\"renew-timer\" { return isc::dhcp::Dhcp6Parser::make_RENEW_TIMER(loc); }
+\"rebind-timer\" { return isc::dhcp::Dhcp6Parser::make_REBIND_TIMER(loc); }
+\"subnet6\" { return isc::dhcp::Dhcp6Parser::make_SUBNET6(loc); }
+\"option-data\" { return isc::dhcp::Dhcp6Parser::make_OPTION_DATA(loc); }
+\"name\" { return isc::dhcp::Dhcp6Parser::make_NAME(loc); }
+\"data\" { return isc::dhcp::Dhcp6Parser::make_DATA(loc); }
+\"pools\" { return isc::dhcp::Dhcp6Parser::make_POOLS(loc); }
+\"pool\" { return isc::dhcp::Dhcp6Parser::make_POOL(loc); }
+\"subnet\" { return isc::dhcp::Dhcp6Parser::make_SUBNET(loc); }
+\"interface\" { return isc::dhcp::Dhcp6Parser::make_INTERFACE(loc); }
+\"type\" { return isc::dhcp::Dhcp6Parser::make_TYPE(loc); }
+\"code\" { return isc::dhcp::Dhcp6Parser::make_CODE(loc); }
+
+\"Logging\" { return isc::dhcp::Dhcp6Parser::make_LOGGING(loc); }
+\"loggers\" { return isc::dhcp::Dhcp6Parser::make_LOGGERS(loc); }
+\"output_options\" { return isc::dhcp::Dhcp6Parser::make_OUTPUT_OPTIONS(loc); }
+\"output\" { return isc::dhcp::Dhcp6Parser::make_OUTPUT_OPTIONS(loc); }
+\"debuglevel\" { return isc::dhcp::Dhcp6Parser::make_DEBUGLEVEL(loc); }
+\"severity\" { return isc::dhcp::Dhcp6Parser::make_SEVERITY(loc); }
{JSONString} {
// A string has been matched. It contains the actual string and single quotes.
return isc::dhcp::Dhcp6Parser::make_STRING(tmp, loc);
}
-"[" { return isc::dhcp::Dhcp6Parser::make_LSQUARE_BRACKET(loc); }
-"]" { return isc::dhcp::Dhcp6Parser::make_RSQUARE_BRACKET(loc); }
-"{" { return isc::dhcp::Dhcp6Parser::make_LCURLY_BRACKET(loc); }
-"}" { return isc::dhcp::Dhcp6Parser::make_RCURLY_BRACKET(loc); }
-"," { return isc::dhcp::Dhcp6Parser::make_COMMA(loc); }
-":" { return isc::dhcp::Dhcp6Parser::make_COLON(loc); }
+"[" { return isc::dhcp::Dhcp6Parser::make_LSQUARE_BRACKET(loc); }
+"]" { return isc::dhcp::Dhcp6Parser::make_RSQUARE_BRACKET(loc); }
+"{" { return isc::dhcp::Dhcp6Parser::make_LCURLY_BRACKET(loc); }
+"}" { return isc::dhcp::Dhcp6Parser::make_RCURLY_BRACKET(loc); }
+"," { return isc::dhcp::Dhcp6Parser::make_COMMA(loc); }
+":" { return isc::dhcp::Dhcp6Parser::make_COLON(loc); }
{int} {
// An integer was found.
LCURLY_BRACKET "{"
RCURLY_BRACKET "}"
NULL_TYPE "null"
+
+ DHCP6 "Dhcp6"
+ INTERFACES_CONFIG "interfaces-config"
+ INTERFACES "interfaces"
+ LEASE_DATABASE "lease-database"
+ TYPE "type"
+ PREFERRED_LIFETIME "preferred-lifetime"
+ VALID_LIFETIME "valid-lifetime"
+ RENEW_TIMER "renew-timer"
+ REBIND_TIMER "rebind-timer"
+ SUBNET6 "subnet6"
+ OPTION_DATA "option-data"
+ NAME "name"
+ DATA "data"
+ CODE "code"
+ POOLS "pools"
+ POOL "pool"
+ SUBNET "subnet"
+ INTERFACE "interface"
+
+ LOGGING "Logging"
+ LOGGERS "loggers"
+ OUTPUT_OPTIONS "output_options"
+ OUTPUT "output"
+ DEBUGLEVEL "debuglevel"
+ SEVERITY "severity"
;
%token <std::string> STRING "constant string"
%%
// The whole grammar starts with a map, because the config file
// constists of Dhcp, Logger and DhcpDdns entries in one big { }.
-%start map;
+// %start map - this will parse everything as generic JSON
+// %start dhcp6_map - this will parse everything with Dhcp6 syntax checking
+%start syntax_map;
// Values rule
value : INTEGER { $$ = ElementPtr(new IntElement($1)); }
| list { $$ = ctx.stack_.back(); ctx.stack_.pop_back(); }
;
-
map: LCURLY_BRACKET {
// This code is executed when we're about to start parsing
// the content of the map
// Assignments rule
map_content: { /* do nothing, it's an empty map */ }
| STRING COLON value {
- // map containing a single entry
- ctx.stack_.back()->set($1, $3);
+ // map containing a single entry
+ ctx.stack_.back()->set($1, $3);
}
| map_content COMMA STRING COLON value {
- // map consisting of a shorter map followed by comma and string:value
- ctx.stack_.back()->set($3, $5);
+ // map consisting of a shorter map followed by comma and string:value
+ ctx.stack_.back()->set($3, $5);
}
;
list_content: { /* do nothing, it's an empty list */ }
| value {
- // List consisting of a single element.
- ctx.stack_.back()->add($1);
+ // List consisting of a single element.
+ ctx.stack_.back()->add($1);
}
| list_content COMMA value {
- // List ending with , and a value.
- ctx.stack_.back()->add($3);
+ // List ending with , and a value.
+ ctx.stack_.back()->add($3);
}
;
+global_params: global_param
+| global_params COMMA global_param;
+
+// These are the parameters that are allowed in the top-level for
+// Dhcp6.
+global_param
+: preferred_lifetime
+| valid_lifetime
+| renew_timer
+| rebind_timer
+| subnet6_list
+| interfaces_config
+| lease_database
+;
+
+preferred_lifetime: PREFERRED_LIFETIME COLON INTEGER {
+
+};
+
+valid_lifetime: VALID_LIFETIME COLON INTEGER {
+
+};
+
+renew_timer: RENEW_TIMER COLON INTEGER {
+
+};
+
+interfaces_config: INTERFACES_CONFIG COLON LCURLY_BRACKET interface_config_map RCURLY_BRACKET;
+
+interface_config_map: INTERFACES COLON list;
+
+lease_database: LEASE_DATABASE COLON LCURLY_BRACKET lease_database_map RCURLY_BRACKET;
+
+lease_database_map: TYPE COLON STRING;
+
+rebind_timer: REBIND_TIMER COLON INTEGER {
+
+};
+
+// This defines subnet6 as a list of maps.
+// "subnet6": [ ... ]
+subnet6_list: SUBNET6 COLON LSQUARE_BRACKET {
+ ElementPtr l(new ListElement());
+ ctx.stack_.push_back(l);
+} subnet6_list_content RSQUARE_BRACKET {
+
+};
+
+// This defines the ... in "subnet6": [ ... ]
+// It can either be empty (no subnets defined), have one subnet
+// or have multiple subnets separate by comma.
+subnet6_list_content: { /* no subnets defined at all */ }
+| subnet6
+| subnet6_list_content COMMA subnet6
+;
+
+// This defines a single subnet, i.e. a single map with
+// subnet6 array.
+subnet6: LCURLY_BRACKET subnet6_params RCURLY_BRACKET;
+
+subnet6_params: subnet6_param
+| subnet6_params COMMA subnet6_param;
+
+subnet6_param: { /* empty list */ }
+| option_data_list
+| pools_list
+| SUBNET COLON STRING { }
+| INTERFACE COLON STRING { }
+;
+
+// ---- option-data --------------------------
+
+// This defines the "option-data": [ ... ] entry that may appear
+// in several places, but most notably in subnet6 entries.
+option_data_list: OPTION_DATA COLON LSQUARE_BRACKET option_data_list_content RSQUARE_BRACKET;
+
+// This defines the content of option-data. It may be empty,
+// have one entry or multiple entries separated by comma.
+option_data_list_content: { }
+| option_data_entry
+| option_data_list_content COMMA option_data_entry;
+
+// This defines th content of a single entry { ... } within
+// option-data list.
+option_data_entry: LCURLY_BRACKET option_data_params RCURLY_BRACKET;
+
+// This defines parameters specified inside the map that itself
+// is an entry in option-data list.
+option_data_params: {}
+| option_data_param
+| option_data_params COMMA option_data_param;
+
+option_data_param: NAME COLON STRING {}
+| DATA COLON STRING
+| CODE COLON INTEGER;
+
+// ---- pools ------------------------------------
+
+// This defines the "pools": [ ... ] entry that may appear in subnet6.
+pools_list: POOLS COLON LSQUARE_BRACKET pools_list_content RSQUARE_BRACKET;
+
+// Pools may be empty, contain a single pool entry or multiple entries
+// separate by commas.
+pools_list_content: { }
+| pool_entry
+| pools_list_content COMMA pool_entry;
+
+pool_entry: LCURLY_BRACKET pool_params RCURLY_BRACKET;
+
+pool_params: pool_param
+| pool_params COMMA pool_param;
+
+pool_param: POOL COLON STRING
+| option_data_list;
+
+dhcp6_object: DHCP6 COLON LCURLY_BRACKET {
+ // This code is executed when we're about to start parsing
+ // the content of the map
+ ElementPtr m(new MapElement());
+ ctx.stack_.push_back(m);
+} global_params RCURLY_BRACKET {
+ // map parsing completed. If we ever want to do any wrap up
+ // (maybe some sanity checking), this would be the best place
+ // for it.
+};
+
+logging_object: LOGGING COLON map;
+
+// This represents a single top level entry, e.g. Dhcp6 or DhcpDdns.
+global_object: dhcp6_object
+| logging_object;
+
+// This represents top-level entries: Dhcp6, Dhcp4, DhcpDdns, Logging
+global_objects
+: global_object
+| global_objects COMMA global_object
+;
+
+// This defines the top-level { } that holds Dhcp6, Dhcp4, DhcpDdns or Logging
+// objects.
+syntax_map: LCURLY_BRACKET {
+ // This code is executed when we're about to start parsing
+ // the content of the map
+ ElementPtr m(new MapElement());
+ ctx.stack_.push_back(m);
+} global_objects RCURLY_BRACKET {
+ // map parsing completed. If we ever want to do any wrap up
+ // (maybe some sanity checking), this would be the best place
+ // for it.
+};
+
+
+
%%
void
isc::dhcp::Dhcp6Parser::error(const location_type& loc,
- const std::string& what)
+ const std::string& what)
{
ctx.error(loc, what);
}