From: Tomek Mrugalski Date: Tue, 6 Dec 2016 19:28:55 +0000 (+0100) Subject: [5036] Comments added, some constants removed. X-Git-Tag: trac5085_base~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fab8be8e25afbd46c31f161deb490565f1d5faa1;p=thirdparty%2Fkea.git [5036] Comments added, some constants removed. --- diff --git a/src/bin/dhcp6/dhcp6_lexer.ll b/src/bin/dhcp6/dhcp6_lexer.ll index 3d65b8b2eb..0ebe6e818c 100644 --- a/src/bin/dhcp6/dhcp6_lexer.ll +++ b/src/bin/dhcp6/dhcp6_lexer.ll @@ -102,10 +102,9 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} if (start_token_flag) { start_token_flag = false; switch (start_token_value) { - case Parser6Context::SUBPARSER_JSON: + case Parser6Context::PARSER_JSON: default: - return isc::dhcp::Dhcp6Parser::make_SUB_JSON(driver.loc_); -// return isc::dhcp::Dhcp6Parser::make_TOPLEVEL_GENERIC_JSON(driver.loc_); + return isc::dhcp::Dhcp6Parser::make_TOPLEVEL_JSON(driver.loc_); case Parser6Context::PARSER_DHCP6: return isc::dhcp::Dhcp6Parser::make_TOPLEVEL_DHCP6(driver.loc_); case Parser6Context::SUBPARSER_DHCP6: diff --git a/src/bin/dhcp6/dhcp6_parser.yy b/src/bin/dhcp6/dhcp6_parser.yy index a084ec37bf..248975084b 100644 --- a/src/bin/dhcp6/dhcp6_parser.yy +++ b/src/bin/dhcp6/dhcp6_parser.yy @@ -144,7 +144,7 @@ using namespace std; // Not real tokens, just a way to signal what the parser is expected to // parse. - TOPLEVEL_GENERIC_JSON + TOPLEVEL_JSON TOPLEVEL_DHCP6 SUB_DHCP6 SUB_INTERFACES6 @@ -155,7 +155,6 @@ using namespace std; SUB_OPTION_DEF SUB_OPTION_DATA SUB_HOOKS_LIBRARY - SUB_JSON ; %token STRING "constant string" @@ -175,7 +174,7 @@ using namespace std; // We made the same for subparsers at the exception of the JSON value. %start start; -start: TOPLEVEL_GENERIC_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } map2 +start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json | TOPLEVEL_DHCP6 { ctx.ctx_ = ctx.CONFIG; } syntax_map | SUB_DHCP6 { ctx.ctx_ = ctx.DHCP6; } sub_dhcp6 | SUB_INTERFACES6 { ctx.ctx_ = ctx.INTERFACES_CONFIG; } sub_interfaces6 @@ -186,7 +185,6 @@ start: TOPLEVEL_GENERIC_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } map2 | SUB_OPTION_DEF { ctx.ctx_ = ctx.OPTION_DEF; } sub_option_def | SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data | SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library - | SUB_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json ; // ---- generic JSON parser --------------------------------- @@ -270,7 +268,7 @@ not_empty_list: value { // Unknown keyword in a map unknown_map_entry: STRING COLON { - const std::string& where = ctx.context_name(); + const std::string& where = ctx.contextName(); const std::string& keyword = $1; error(@1, "got unexpected keyword \"" + keyword + "\" in " + where + " map."); @@ -279,7 +277,6 @@ unknown_map_entry: STRING COLON { // This defines the top-level { } that holds Dhcp6, Dhcp4, DhcpDdns or Logging // objects. -// ctx_ = CONFIG syntax_map: LCURLY_BRACKET { // This code is executed when we're about to start parsing // the content of the map diff --git a/src/bin/dhcp6/parser_context.cc b/src/bin/dhcp6/parser_context.cc index 3b9c25f86e..8f2f28195e 100644 --- a/src/bin/dhcp6/parser_context.cc +++ b/src/bin/dhcp6/parser_context.cc @@ -114,7 +114,7 @@ Parser6Context::leave() } const std::string -Parser6Context::context_name() +Parser6Context::contextName() { switch (ctx_) { case NO_KEYWORD: diff --git a/src/bin/dhcp6/parser_context.h b/src/bin/dhcp6/parser_context.h index e3728c52bf..5e97beda37 100644 --- a/src/bin/dhcp6/parser_context.h +++ b/src/bin/dhcp6/parser_context.h @@ -48,41 +48,40 @@ public: /// is being told to start parsing as SUBPARSER_HOST_RESERVATION6. typedef enum { /// This parser will parse the content as generic JSON. - //PARSER_GENERIC_JSON, + PARSER_JSON, - SUBPARSER_JSON, - - /// This parser will parse the content as Dhcp6 config wrapped in a map (that's - /// the regular config file) + /// This parser will parse the content as Dhcp6 config wrapped in a map + /// (that's the regular config file) PARSER_DHCP6, - /// This parser will parse the content of Dhcp6. It is mostly used - /// in unit-tests as most of the unit-tests do not define the outer - /// map and Dhcp6 entity, just the contents of it. + /// This parser will parse the content of Dhcp6 (without outer { } and + /// without "Dhcp6"). It is mostly used in unit-tests as most of the + /// unit-tests do not define the outer map and Dhcp6 entity, just the + /// contents of it. SUBPARSER_DHCP6, - /// This will parse the conde as Subnet6 content. + /// This will parse the input as Subnet6 content. PARSER_SUBNET6, - /// This parser will parse pool6 content. + /// This will parse the input as pool6 content. PARSER_POOL6, - /// This parser will parse the interfaces content. + /// This will parse the input as interfaces content. PARSER_INTERFACES, - /// This parser will parse the content as pd-pool. + /// This will parse the input as pd-pool content. PARSER_PD_POOL, - /// This parser will parse the content as host-reservation + /// This will parse the input as host-reservation. PARSER_HOST_RESERVATION, - /// This parser will parse the content as option definition. + /// This will parse the input as option definition. PARSER_OPTION_DEF, - /// This parser will parse the content as option data. + /// This will parse the input as option data. PARSER_OPTION_DATA, - /// This parser will parse the content as hooks-library + /// This will parse the input as hooks-library. PARSER_HOOKS_LIBRARY } ParserType; @@ -109,13 +108,27 @@ public: /// @brief Run the parser on the string specified. /// + /// This method parses specified string. Depending on the value of + /// parser_type, parser may either check only that the input is valid + /// JSON, or may do more specific syntax checking. See @ref ParserType + /// for supported syntax checkers. + /// /// @param str string to be parsed - /// @param parser_type specifies expected content (either DHCP6 or generic JSON) - /// @return true on success. + /// @param parser_type specifies expected content (usually DHCP6 or generic JSON) + /// @return Element structure representing parsed text. isc::data::ConstElementPtr parseString(const std::string& str, ParserType parser_type); /// @brief Run the parser on the file specified. + /// + /// This method parses specified file. Depending on the value of + /// parser_type, parser may either check only that the input is valid + /// JSON, or may do more specific syntax checking. See @ref ParserType + /// for supported syntax checkers. + /// + /// @param filename file to be parsed + /// @param parser_type specifies expected content (usually DHCP6 or generic JSON) + /// @return Element structure representing parsed text. isc::data::ConstElementPtr parseFile(const std::string& filename, ParserType parser_type); @@ -141,43 +154,86 @@ public: /// /// Convert a bison location into an element position /// (take the begin, the end is lost) + /// @brief loc location in bison format + /// @return Position in format accepted by Element isc::data::Element::Position loc2pos(isc::dhcp::location& loc); /// @brief Defines syntactic contexts for lexical tie-ins typedef enum { - /// at toplevel + ///< This one is used in pure JSON mode. NO_KEYWORD, + + ///< Used while parsing top level (that contains Dhcp6, Logging and others) CONFIG, - /// in config + + ///< Used while parsing content of Dhcp6. DHCP6, + // not yet DHCP4, // not yet DHCP_DDNS, + + ///< Used while parsing content of Logging LOGGING, - /// Dhcp6 + + /// Used while parsing Dhcp6/interfaces structures. INTERFACES_CONFIG, - LEASE_DATABASE, + + /// Used while parsing Dhcp6/hosts-database structures. HOSTS_DATABASE, + + /// Used while parsing Dhcp6/lease-database structures. + LEASE_DATABASE, + + /// Used while parsing Dhcp6/mac-sources structures. MAC_SOURCES, + + /// Used while parsing Dhcp6/host-reservation-identifiers. HOST_RESERVATION_IDENTIFIERS, + + /// Used while parsing Dhcp6/hooks-libraries. HOOKS_LIBRARIES, + + /// Used while parsing Dhcp6/Subnet6 structures. SUBNET6, + + /// Used while parsing Dhcp6/option-def structures. OPTION_DEF, + + /// Used while parsing Dhcp6/option-data, Dhcp6/subnet6/option-data + /// or anywhere option-data is present (client classes, host + /// reservations and possibly others). OPTION_DATA, + + /// Used while parsing Dhcp6/client-classes structures. CLIENT_CLASSES, + + /// Used while parsing Dhcp6/server-id structures. SERVER_ID, + + /// Used while parsing Dhcp6/control-socket structures. CONTROL_SOCKET, - /// subnet6 + + /// Used while parsing Dhcp6/subnet6/pools structures. POOLS, + + /// Used while parsing Dhcp6/subnet6/pd-pools structures. PD_POOLS, + + /// Used while parsing Dhcp6/reservations structures. RESERVATIONS, + + /// Used while parsing Dhcp6/subnet6/relay structures. RELAY, - /// client-classes + + /// Used while parsing Dhcp6/client-classes structures. CLIENT_CLASS, - /// Logging + + /// Used while parsing Logging/loggers structures. LOGGERS, - /// loggers + + /// Used while parsing Logging/loggers/output_options structures. OUTPUT_OPTIONS - } ParserContext; + } ParserContext; /// @brief File name std::string file_; @@ -201,12 +257,24 @@ public: FILE* sfile_; /// @brief sFile (aka FILE) stack + /// + /// This is a stack of files. Typically there's only one file (the + /// one being currently parsed), but there may be more if one + /// file includes another. std::vector sfiles_; /// @brief Current syntactic context ParserContext ctx_; /// @brief Enter a new syntactic context + /// + /// Entering a nex syntactic context is useful in several ways. + /// First, it allows the parser to avoid conflicts. Second, it + /// allows the lexer to return different tokens depending on + /// context (e.g. if "renew-timer" string is detected, the lexer + /// will return STRING token if in JSON mode or RENEW_TIMER if + /// in DHCP6 mode. Finally, the stntactic context allows the + /// error message to be more descriptive. void enter(const ParserContext& ctx); /// @brief Leave a syntactic context @@ -214,7 +282,8 @@ public: void leave(); /// @brief Get the syntactix context name - const std::string context_name(); + /// @return printable name of the context. + const std::string contextName(); private: /// @brief Flag determining scanner debugging. diff --git a/src/bin/dhcp6/tests/dhcp6_test_utils.h b/src/bin/dhcp6/tests/dhcp6_test_utils.h index 0ac3cabe22..a790acd39d 100644 --- a/src/bin/dhcp6/tests/dhcp6_test_utils.h +++ b/src/bin/dhcp6/tests/dhcp6_test_utils.h @@ -639,15 +639,24 @@ public: NakedDhcpv6Srv srv_; }; -// For parser testing (JSON map, no exception expected) +/// @brief Runs parser in JSON mode, useful for parser testing +/// +/// @param in string to be parsed +/// @return ElementPtr structure representing parsed JSON inline isc::data::ConstElementPtr parseJSON(const std::string& in) { isc::dhcp::Parser6Context ctx; - return (ctx.parseString(in, isc::dhcp::Parser6Context::SUBPARSER_JSON)); + return (ctx.parseString(in, isc::dhcp::Parser6Context::PARSER_JSON)); } -// For parser testing (DHCP6) +/// @brief Runs parser in Dhcp6 mode +/// +/// This is a simplified Dhcp6 mode, so no outer { } and "Dhcp6" is +/// needed. This format is used by most of the tests. +/// +/// @param in string to be parsed +/// @return ElementPtr structure representing parsed JSON inline isc::data::ConstElementPtr parseDHCP6(const std::string& in) { @@ -656,14 +665,17 @@ parseDHCP6(const std::string& in) return (ctx.parseString(in, isc::dhcp::Parser6Context::SUBPARSER_DHCP6)); } catch (const std::exception& ex) { -#ifdef ENABLE_DEBUG std::cout << "EXCEPTION: " << ex.what() << std::endl; -#endif // ENABLE_DEBUG throw; } } -// For parser testing (OPTION_DEF) +/// @brief Runs parser in option definition mode +/// +/// This function parses specified text as JSON that defines option definitions. +/// +/// @param in string to be parsed +/// @return ElementPtr structure representing parsed JSON inline isc::data::ConstElementPtr parseOPTION_DEF(const std::string& in) { @@ -672,9 +684,7 @@ parseOPTION_DEF(const std::string& in) return (ctx.parseString(in, isc::dhcp::Parser6Context::PARSER_OPTION_DEF)); } catch (const std::exception& ex) { -#ifdef ENABLE_DEBUG std::cout << "EXCEPTION: " << ex.what() << std::endl; -#endif // ENABLE_DEBUG throw; } } diff --git a/src/bin/dhcp6/tests/parser_unittest.cc b/src/bin/dhcp6/tests/parser_unittest.cc index 3453859ea0..a797469569 100644 --- a/src/bin/dhcp6/tests/parser_unittest.cc +++ b/src/bin/dhcp6/tests/parser_unittest.cc @@ -65,35 +65,35 @@ void testParser2(const std::string& txt, Parser6Context::ParserType parser_type) TEST(ParserTest, mapInMap) { string txt = "{ \"xyzzy\": { \"foo\": 123, \"baz\": 456 } }"; - testParser(txt, Parser6Context::SUBPARSER_JSON); + testParser(txt, Parser6Context::PARSER_JSON); } TEST(ParserTest, listInList) { string txt = "[ [ \"Britain\", \"Wales\", \"Scotland\" ], " "[ \"Pomorze\", \"Wielkopolska\", \"Tatry\"] ]"; - testParser(txt, Parser6Context::SUBPARSER_JSON); + testParser(txt, Parser6Context::PARSER_JSON); } TEST(ParserTest, nestedMaps) { string txt = "{ \"europe\": { \"UK\": { \"London\": { \"street\": \"221B Baker\" }}}}"; - testParser(txt, Parser6Context::SUBPARSER_JSON); + testParser(txt, Parser6Context::PARSER_JSON); } TEST(ParserTest, nestedLists) { string txt = "[ \"half\", [ \"quarter\", [ \"eighth\", [ \"sixteenth\" ]]]]"; - testParser(txt, Parser6Context::SUBPARSER_JSON); + testParser(txt, Parser6Context::PARSER_JSON); } TEST(ParserTest, listsInMaps) { string txt = "{ \"constellations\": { \"orion\": [ \"rigel\", \"betelguese\" ], " "\"cygnus\": [ \"deneb\", \"albireo\"] } }"; - testParser(txt, Parser6Context::SUBPARSER_JSON); + testParser(txt, Parser6Context::PARSER_JSON); } TEST(ParserTest, mapsInLists) { string txt = "[ { \"body\": \"earth\", \"gravity\": 1.0 }," " { \"body\": \"mars\", \"gravity\": 0.376 } ]"; - testParser(txt, Parser6Context::SUBPARSER_JSON); + testParser(txt, Parser6Context::PARSER_JSON); } TEST(ParserTest, types) { @@ -103,7 +103,7 @@ TEST(ParserTest, types) { "\"map\": { \"foo\": \"bar\" }," "\"list\": [ 1, 2, 3 ]," "\"null\": null }"; - testParser(txt, Parser6Context::SUBPARSER_JSON); + testParser(txt, Parser6Context::PARSER_JSON); } TEST(ParserTest, keywordJSON) { @@ -111,7 +111,7 @@ TEST(ParserTest, keywordJSON) { "\"type\": \"password\"," "\"user\": \"name\"," "\"password\": \"type\" }"; - testParser(txt, Parser6Context::SUBPARSER_JSON); + testParser(txt, Parser6Context::PARSER_JSON); } TEST(ParserTest, keywordDhcp6) { @@ -267,142 +267,142 @@ void testError(const std::string& txt, // Check errors TEST(ParserTest, errors) { // no input - testError("", Parser6Context::SUBPARSER_JSON, + testError("", Parser6Context::PARSER_JSON, ":1.1: syntax error, unexpected end of file"); - testError(" ", Parser6Context::SUBPARSER_JSON, + testError(" ", Parser6Context::PARSER_JSON, ":1.2: syntax error, unexpected end of file"); - testError("\n", Parser6Context::SUBPARSER_JSON, + testError("\n", Parser6Context::PARSER_JSON, ":2.1: syntax error, unexpected end of file"); // comments testError("# nothing\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":2.1: syntax error, unexpected end of file, " "expecting {"); testError(" #\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":2.1: syntax error, unexpected end of file, " "expecting {"); testError("// nothing\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":2.1: syntax error, unexpected end of file, " "expecting {"); testError("/* nothing */\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":2.1: syntax error, unexpected end of file, " "expecting {"); testError("/* no\nthing */\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":3.1: syntax error, unexpected end of file, " "expecting {"); testError("/* no\nthing */\n\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":4.1: syntax error, unexpected end of file, " "expecting {"); testError("/* nothing\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, "Comment not closed. (/* in line 1"); testError("\n\n\n/* nothing\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, "Comment not closed. (/* in line 4"); testError("{ /* */*/ }\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.3-8: Invalid character: *"); testError("{ /* // *// }\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.3-11: Invalid character: /"); testError("{ /* // */// }\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":2.1: syntax error, unexpected end of file, " "expecting }"); // includes testError("/n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, "Can't open include file /foo/bar"); // numbers testError("123", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-3: syntax error, unexpected integer, " "expecting {"); testError("-456", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-4: syntax error, unexpected integer, " "expecting {"); testError("-0001", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-5: syntax error, unexpected integer, " "expecting {"); testError("1234567890123456789012345678901234567890", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-40: Failed to convert " "1234567890123456789012345678901234567890" " to an integer."); testError("-3.14e+0", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-8: syntax error, unexpected floating point, " "expecting {"); testError("1e50000", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-7: Failed to convert 1e50000 " "to a floating point."); // strings testError("\"aabb\"", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-6: syntax error, unexpected constant string, " "expecting {"); testError("{ \"aabb\"err", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.9: Invalid character: e"); testError("{ err\"aabb\"", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.3: Invalid character: e"); testError("\"a\n\tb\"", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-6: Invalid control in \"a\n\tb\""); testError("\"a\\n\\tb\"", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-8: syntax error, unexpected constant string, " "expecting {"); testError("\"a\\x01b\"", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-8: Bad escape in \"a\\x01b\""); testError("\"a\\u0062\"", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-9: Unsupported unicode escape in \"a\\u0062\""); testError("\"a\\u062z\"", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-9: Bad escape in \"a\\u062z\""); testError("\"abc\\\"", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1-6: Overflow escape in \"abc\\\""); // from data_unittest.c testError("\\a", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1: Invalid character: \\"); testError("\\", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1: Invalid character: \\"); testError("\\\"\\\"", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1: Invalid character: \\"); // want a map testError("[]\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.1: syntax error, unexpected [, " "expecting {"); testError("[]\n", @@ -410,14 +410,14 @@ TEST(ParserTest, errors) { ":1.1: syntax error, unexpected [, " "expecting {"); testError("{ 123 }\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.3-5: syntax error, unexpected integer, " "expecting }"); testError("{ 123 }\n", Parser6Context::PARSER_DHCP6, ":1.3-5: syntax error, unexpected integer"); testError("{ \"foo\" }\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.9: syntax error, unexpected }, " "expecting :"); testError("{ \"foo\" }\n", @@ -436,21 +436,21 @@ TEST(ParserTest, errors) { ":2.1: syntax error, unexpected end of file, " "expecting \",\" or }"); testError("{}{}\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.3: syntax error, unexpected {, " "expecting end of file"); // bad commas testError("{ , }\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.3: syntax error, unexpected \",\", " "expecting }"); testError("{ , \"foo\":true }\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.3: syntax error, unexpected \",\", " "expecting }"); testError("{ \"foo\":true, }\n", - Parser6Context::SUBPARSER_JSON, + Parser6Context::PARSER_JSON, ":1.15: syntax error, unexpected }, " "expecting constant string");