Browse Source

[5014] The syntax parser is able to parse Dhcp6 (Logging still wip)

Tomek Mrugalski 8 years ago
parent
commit
6da00d2f6a
2 changed files with 222 additions and 17 deletions
  1. 31 6
      src/bin/dhcp6/dhcp6_lexer.ll
  2. 191 11
      src/bin/dhcp6/dhcp6_parser.yy

+ 31 - 6
src/bin/dhcp6/dhcp6_lexer.ll

@@ -112,6 +112,31 @@ JSONString                              \"{JSONStringCharacter}*\"
     loc.step();
     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} {
 {JSONString} {
     // A string has been matched. It contains the actual string and single quotes.
     // A string has been matched. It contains the actual string and single quotes.
@@ -123,12 +148,12 @@ JSONString                              \"{JSONStringCharacter}*\"
     return isc::dhcp::Dhcp6Parser::make_STRING(tmp, loc);
     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} {
 {int} {
     // An integer was found.
     // An integer was found.

+ 191 - 11
src/bin/dhcp6/dhcp6_parser.yy

@@ -47,6 +47,32 @@ using namespace std;
   LCURLY_BRACKET "{"
   LCURLY_BRACKET "{"
   RCURLY_BRACKET "}"
   RCURLY_BRACKET "}"
   NULL_TYPE "null"
   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"
 %token <std::string> STRING "constant string"
@@ -61,7 +87,9 @@ using namespace std;
 %%
 %%
 // The whole grammar starts with a map, because the config file
 // The whole grammar starts with a map, because the config file
 // constists of Dhcp, Logger and DhcpDdns entries in one big { }.
 // 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
 // Values rule
 value : INTEGER { $$ = ElementPtr(new IntElement($1)); }
 value : INTEGER { $$ = ElementPtr(new IntElement($1)); }
@@ -73,7 +101,6 @@ value : INTEGER { $$ = ElementPtr(new IntElement($1)); }
      | list { $$ = ctx.stack_.back(); ctx.stack_.pop_back(); }
      | list { $$ = ctx.stack_.back(); ctx.stack_.pop_back(); }
     ;
     ;
 
 
-
 map: LCURLY_BRACKET {
 map: LCURLY_BRACKET {
     // This code is executed when we're about to start parsing
     // This code is executed when we're about to start parsing
     // the content of the map
     // the content of the map
@@ -88,12 +115,12 @@ map: LCURLY_BRACKET {
 // Assignments rule
 // Assignments rule
 map_content:  { /* do nothing, it's an empty map */ }
 map_content:  { /* do nothing, it's an empty map */ }
     | STRING COLON value {
     | 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_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);
     }
     }
     ;
     ;
 
 
@@ -107,20 +134,173 @@ list: LSQUARE_BRACKET {
 
 
 list_content: { /* do nothing, it's an empty list */ }
 list_content: { /* do nothing, it's an empty list */ }
     | value {
     | 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_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
 void
 isc::dhcp::Dhcp6Parser::error(const location_type& loc,
 isc::dhcp::Dhcp6Parser::error(const location_type& loc,
-                              const std::string& what)
+			      const std::string& what)
 {
 {
     ctx.error(loc, what);
     ctx.error(loc, what);
 }
 }