Commit 636c930f authored by Francis Dupont's avatar Francis Dupont
Browse files

[5351] Added comment in syntax

parent 499f6ca7
......@@ -586,6 +586,16 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
}
}
\"comment\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::POOLS:
return isc::dhcp::Dhcp4Parser::make_COMMENT(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("comment", driver.loc_);
}
}
\"subnet\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::SUBNET4:
......
......@@ -2304,7 +2304,7 @@ namespace isc { namespace dhcp {
case 377:
#line 1346 "dhcp4_parser.yy" // lalr1.cc:859
{
ctx.stack_.back()->set("user-context", yystack_[0].value.as< ElementPtr > ());
ctx.stack_.back()->combine_set("user-context", yystack_[0].value.as< ElementPtr > ());
ctx.leave();
}
#line 2311 "dhcp4_parser.cc" // lalr1.cc:859
......
......@@ -109,6 +109,7 @@ using namespace std;
POOLS "pools"
POOL "pool"
USER_CONTEXT "user-context"
COMMENT "comment"
SUBNET "subnet"
INTERFACE "interface"
......@@ -920,6 +921,7 @@ subnet4_param: valid_lifetime
| subnet_4o6_interface_id
| subnet_4o6_subnet
| user_context
| comment
| unknown_map_entry
;
......@@ -1330,6 +1332,7 @@ pool_params: pool_param
pool_param: pool_entry
| option_data_list
| user_context
| comment
| unknown_map_entry
;
......@@ -1344,7 +1347,16 @@ pool_entry: POOL {
user_context: USER_CONTEXT {
ctx.enter(ctx.NO_KEYWORD);
} COLON map_value {
ctx.stack_.back()->set("user-context", $4);
ctx.stack_.back()->combine_set("user-context", $4);
ctx.leave();
};
comment: COMMENT {
ctx.enter(ctx.NO_KEYWORD);
} COLON value {
ElementPtr e(new MapElement(ctx.loc2pos(@1)));
e->set("comment", $4);
ctx.stack_.back()->combine_set("user-context", e);
ctx.leave();
};
......
......@@ -817,6 +817,17 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
}
}
\"comment\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::POOLS:
case isc::dhcp::Parser6Context::PD_POOLS:
case isc::dhcp::Parser6Context::SUBNET6:
return isc::dhcp::Dhcp6Parser::make_COMMENT(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("comment", driver.loc_);
}
}
\"subnet\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::SUBNET6:
......
......@@ -99,6 +99,7 @@ using namespace std;
EXCLUDED_PREFIX_LEN "excluded-prefix-len"
DELEGATED_LEN "delegated-len"
USER_CONTEXT "user-context"
COMMENT "comment"
SUBNET "subnet"
INTERFACE "interface"
......@@ -908,6 +909,7 @@ subnet6_param: preferred_lifetime
| reservation_mode
| relay
| user_context
| comment
| unknown_map_entry
;
......@@ -1293,6 +1295,7 @@ pool_params: pool_param
pool_param: pool_entry
| option_data_list
| user_context
| comment
| unknown_map_entry
;
......@@ -1307,7 +1310,16 @@ pool_entry: POOL {
user_context: USER_CONTEXT {
ctx.enter(ctx.NO_KEYWORD);
} COLON map_value {
ctx.stack_.back()->set("user-context", $4);
ctx.stack_.back()->combine_set("user-context", $4);
ctx.leave();
};
comment: COMMENT {
ctx.enter(ctx.NO_KEYWORD);
} COLON value {
ElementPtr e(new MapElement(ctx.loc2pos(@1)));
e->set("comment", $4);
ctx.stack_.back()->combine_set("user-context", e);
ctx.leave();
};
......@@ -1369,6 +1381,7 @@ pd_pool_param: pd_prefix
| excluded_prefix
| excluded_prefix_len
| user_context
| comment
| unknown_map_entry
;
......
......@@ -171,6 +171,11 @@ Element::set(const std::string&, ConstElementPtr) {
throwTypeError("set(name, element) called on a non-map Element");
}
void
Element::combine_set(const std::string&, ConstElementPtr) {
throwTypeError("combine_set(name, element) called on a non-map Element");
}
void
Element::remove(const std::string&) {
throwTypeError("remove(string) called on a non-map Element");
......@@ -902,6 +907,18 @@ MapElement::set(const std::string& key, ConstElementPtr value) {
m[key] = value;
}
void
MapElement::combine_set(const std::string& key, ConstElementPtr value) {
auto previous = m.find(key);
if (previous == m.end()) {
m[key] = value;
return;
}
ElementPtr mutable_ = boost::const_pointer_cast<Element>(previous->second);
combine(mutable_, value);
m[key] = mutable_;
}
bool
MapElement::find(const std::string& id, ConstElementPtr& t) const {
try {
......@@ -1313,13 +1330,32 @@ prettyPrint(ConstElementPtr element, std::ostream& out,
// open the map
out << "{\n";
bool first = true;
// output comment first
if (element->contains("comment")) {
// add indentation
out << std::string(indent + step, ' ');
// add keyword:
out << "\"comment\": ";
// recursive call
prettyPrint(element->get("comment"), out, indent + step, step);
// it was the first
first = false;
}
// iterate on keyword: value
typedef std::map<std::string, ConstElementPtr> MapType;
const MapType& m = element->mapValue();
for (MapType::const_iterator it = m.begin();
it != m.end(); ++it) {
// skip comment
if (it->first == "comment") {
continue;
}
// add the separator if not the first item
if (it != m.begin()) {
if (first) {
first = false;
} else {
out << ",\n";
}
// add indentation
......
......@@ -321,6 +321,12 @@ public:
/// @param element The ElementPtr to set at the given key.
virtual void set(const std::string& name, ConstElementPtr element);
/// Sets the ElementPtr at the given key, if there was a previous
/// value it is combined with it
/// @param name The key of the Element to set
/// @param element The ElementPtr to set at the given key.
virtual void combine_set(const std::string& name, ConstElementPtr element);
/// Remove the ElementPtr at the given key
/// @param name The key of the Element to remove
virtual void remove(const std::string& name);
......@@ -667,6 +673,7 @@ public:
}
using Element::set;
void set(const std::string& key, ConstElementPtr value);
void combine_set(const std::string& key, ConstElementPtr value);
using Element::remove;
void remove(const std::string& s) { m.erase(s); }
bool contains(const std::string& s) const {
......@@ -773,6 +780,7 @@ bool isEquivalent(ConstElementPtr a, ConstElementPtr b);
/// This operator converts the @c ConstElementPtr into a string and
/// inserts it into the output stream @c out with an initial
/// indentation @c indent and add at each level @c step spaces.
/// For maps if there is a comment property it is printed first.
///
/// @param element A @c ConstElementPtr to pretty print
/// @param out A @c std::ostream on which the print operation is performed
......@@ -785,6 +793,7 @@ void prettyPrint(ConstElementPtr element, std::ostream& out,
///
/// This operator converts the @c ConstElementPtr into a string with
/// an initial indentation @c indent and add at each level @c step spaces.
/// For maps if there is a comment property it is printed first.
///
/// @param element A @c ConstElementPtr to pretty print
/// @param indent An initial number of spaces to add each new line
......
......@@ -654,6 +654,28 @@ TEST(Element, MapElement) {
el->remove("value3");
EXPECT_TRUE(isNull(el->get("value3")));
EXPECT_TRUE(isNull(el->get("value4")));
ElementPtr em = Element::fromJSON("{ \"a\": 1 }");
el->combine_set("value4", em);
ASSERT_FALSE(isNull(el->get("value4")));
EXPECT_EQ(em, el->get("value4"));
em = Element::fromJSON("{ \"a\": 2 }");
el->combine_set("value4", em);
ASSERT_FALSE(isNull(el->get("value4")));
ASSERT_EQ(Element::map, el->get("value4")->getType());
EXPECT_EQ(1, el->get("value4")->size());
ASSERT_FALSE(isNull(el->get("value4")->get("a")));
ASSERT_EQ(Element::list, el->get("value4")->get("a")->getType());
EXPECT_EQ(2, el->get("value4")->get("a")->size());
ASSERT_EQ(Element::integer,
el->get("value4")->get("a")->get(0)->getType());
EXPECT_EQ(1, el->get("value4")->get("a")->get(0)->intValue());
ASSERT_EQ(Element::integer,
el->get("value4")->get("a")->get(1)->getType());
EXPECT_EQ(2, el->get("value4")->get("a")->get(1)->intValue());
EXPECT_EQ(el->find("value2/number")->intValue(), 42);
EXPECT_TRUE(isNull(el->find("value2/nothing/")));
......@@ -1199,6 +1221,7 @@ TEST(Element, prettyPrint) {
// default step is 2, order is alphabetic, no \n at the end
string text = "{\n"
" \"comment\": \"this is an exception\",\n"
" \"boolean\": true,\n"
" \"empty-list\": [ ],\n"
" \"empty-map\": { },\n"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment