// variable will be useful for logging errors.
static isc::dhcp::location loc;
+static bool start_token_flag = false;
+
+static isc::dhcp::Parser6Context::ParserType start_token_value;
+
// To avoid the call to exit... oops!
#define YY_FATAL_ERROR(msg) isc::dhcp::Parser6Context::fatal(msg)
%}
%%
%{
+ // 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
+
// Code run each time yylex is called.
loc.step();
int comment_start_line = 0;
+
+ if (start_token_flag) {
+ start_token_flag = false;
+ switch (start_token_value) {
+ case Parser6Context::PARSER_DHCP6:
+ return isc::dhcp::Dhcp6Parser::make_TOPLEVEL_DHCP6(loc);
+ case Parser6Context::PARSER_GENERIC_JSON:
+ return isc::dhcp::Dhcp6Parser::make_TOPLEVEL_GENERIC_JSON(loc);
+ }
+ }
%}
#.* ;
using namespace isc::dhcp;
void
-Parser6Context::scanStringBegin()
+Parser6Context::scanStringBegin(ParserType parser_type)
{
+ start_token_flag = true;
+ start_token_value = parser_type;
+
loc.initialize(&file_);
yy_flex_debug = trace_scanning_;
YY_BUFFER_STATE buffer;
}
void
-Parser6Context::scanFileBegin(FILE * f) {
+Parser6Context::scanFileBegin(FILE * f, ParserType parser_type) {
+
+ start_token_flag = true;
+ start_token_value = parser_type;
+
loc.initialize(&file_);
yy_flex_debug = trace_scanning_;
YY_BUFFER_STATE buffer;
class Parser6Context
{
public:
+
+ typedef enum { PARSER_DHCP6,
+ PARSER_GENERIC_JSON } ParserType;
+
/// @brief Default constructor.
///
/// @param option_universe Option universe: DHCPv4 or DHCPv6. This is used
std::vector<isc::data::ElementPtr> stack_;
/// @brief Method called before scanning starts on a string.
- void scanStringBegin();
+ void scanStringBegin(ParserType type);
/// @brief Method called after the last tokens are scanned from a string.
void scanStringEnd();
- void scanFileBegin(FILE * f);
+ void scanFileBegin(FILE * f, ParserType type);
void scanFileEnd(FILE * f);
/// @brief Run the parser on the string specified.
///
/// @param str string to be written
/// @return true on success.
- isc::data::ConstElementPtr parseString(const std::string& str);
+ isc::data::ConstElementPtr parseString(const std::string& str,
+ ParserType parser_type);
- isc::data::ConstElementPtr parseFile(const std::string& filename);
+ isc::data::ConstElementPtr parseFile(const std::string& filename,
+ ParserType parser_type);
/// @brief The name of the file being parsed.
/// Used later to pass the file name to the location tracker.
ASSERT_TRUE(a);
ASSERT_TRUE(b);
if (print) {
- std::cout << a->str() << std::endl;
- std::cout << b->str() << std::endl;
+ std::cout << "JSON A: -----" << endl << a->str() << std::endl;
+ std::cout << "JSON B: -----" << endl << b->str() << std::endl;
+ cout << "---------" << endl << endl;
}
EXPECT_EQ(a->str(), b->str());
}
-void testParser(const std::string& txt) {
+void testParser(const std::string& txt, Parser6Context::ParserType parser_type) {
ElementPtr reference_json;
ConstElementPtr test_json;
EXPECT_NO_THROW(reference_json = Element::fromJSON(txt, true));
EXPECT_NO_THROW({
Parser6Context ctx;
- test_json = ctx.parseString(txt);
+ test_json = ctx.parseString(txt, parser_type);
});
// Now compare if both representations are the same.
compareJSON(reference_json, test_json);
}
-void testParser2(const std::string& txt) {
+void testParser2(const std::string& txt, Parser6Context::ParserType parser_type) {
ConstElementPtr test_json;
EXPECT_NO_THROW({
Parser6Context ctx;
- test_json = ctx.parseString(txt);
+ test_json = ctx.parseString(txt, parser_type);
});
/// @todo: Implement actual validation here. since the original
/// Element::fromJSON does not support several comment types, we don't
TEST(ParserTest, mapInMap) {
string txt = "{ \"Dhcp6\": { \"foo\": 123, \"baz\": 456 } }";
- testParser(txt);
+ testParser(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, listInList) {
string txt = "{ \"countries\": [ [ \"Britain\", \"Wales\", \"Scotland\" ], "
"[ \"Pomorze\", \"Wielkopolska\", \"Tatry\"] ] }";
- testParser(txt);
+ testParser(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, nestedMaps) {
string txt = "{ \"europe\": { \"UK\": { \"London\": { \"street\": \"221B Baker\" }}}}";
- testParser(txt);
+ testParser(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, nestedLists) {
string txt = "{ \"unity\": [ \"half\", [ \"quarter\", [ \"eighth\", [ \"sixteenth\" ]]]] }";
- testParser(txt);
+ testParser(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, listsInMaps) {
string txt = "{ \"constellations\": { \"orion\": [ \"rigel\", \"betelguese\" ], "
"\"cygnus\": [ \"deneb\", \"albireo\"] } }";
- testParser(txt);
+ testParser(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, mapsInLists) {
string txt = "{ \"solar-system\": [ { \"name\": \"earth\", \"gravity\": 1.0 },"
" { \"name\": \"mars\", \"gravity\": 0.376 } ] }";
- testParser(txt);
+ testParser(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, types) {
"\"map\": { \"foo\": \"bar\" },"
"\"list\": [ 1, 2, 3 ],"
"\"null\": null }";
- testParser(txt);
+ testParser(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, bashComments) {
" \"interface\": \"eth0\""
" } ],"
"\"valid-lifetime\": 4000 }";
- testParser(txt);
+ testParser(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, cComments) {
" \"interface\": \"eth0\""
" } ],"
"\"valid-lifetime\": 4000 }";
- testParser2(txt);
+ testParser2(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, bashComments2) {
" \"interface\": \"eth0\""
" } ],"
"\"valid-lifetime\": 4000 }";
- testParser2(txt);
+ testParser2(txt, Parser6Context::PARSER_GENERIC_JSON);
}
TEST(ParserTest, multilineComments) {
" \"interface\": \"eth0\""
" } ],"
"\"valid-lifetime\": 4000 }";
- testParser2(txt);
+ testParser2(txt, Parser6Context::PARSER_GENERIC_JSON);
}
try {
Parser6Context ctx;
- test_json = ctx.parseFile(fname);
+ test_json = ctx.parseFile(fname, Parser6Context::PARSER_DHCP6);
} catch (const std::exception &x) {
cout << "EXCEPTION: " << x.what() << endl;
}