// covers all longer lists recursively.
not_empty_map: STRING COLON value {
// map containing a single entry
+ ctx.unique($1, ctx.loc2pos(@1));
ctx.stack_.back()->set($1, $3);
}
| not_empty_map COMMA STRING COLON value {
// map consisting of a shorter map followed by
// comma and string:value
+ ctx.unique($3, ctx.loc2pos(@3));
ctx.stack_.back()->set($3, $5);
}
;
// top level map (that's already on the stack) and put the new map
// on the stack as well, so child elements will be able to add
// themselves to it.
+ ctx.unique("Control-agent", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("Control-agent", m);
ctx.stack_.push_back(m);
;
http_host: HTTP_HOST {
+ ctx.unique("http-host", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr host(new StringElement($4, ctx.loc2pos(@4)));
};
http_port: HTTP_PORT COLON INTEGER {
+ ctx.unique("http-port", ctx.loc2pos(@1));
ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("http-port", prf);
};
// --- hooks-libraries ---------------------------------------------------------
hooks_libraries: HOOKS_LIBRARIES {
+ ctx.unique("hooks-libraries", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("hooks-libraries", l);
ctx.stack_.push_back(l);
;
library: LIBRARY {
+ ctx.unique("library", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr lib(new StringElement($4, ctx.loc2pos(@4)));
};
parameters: PARAMETERS {
+ ctx.unique("parameters", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON map_value {
ctx.stack_.back()->set("parameters", $4);
// --- control-sockets starts here ---------------------------------------------
control_sockets: CONTROL_SOCKETS COLON LCURLY_BRACKET {
+ ctx.unique("control-sockets", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("control-sockets", m);
ctx.stack_.push_back(m);
// That's an entry for dhcp4 socket.
dhcp4_server_socket: DHCP4_SERVER {
+ ctx.unique("dhcp4", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("dhcp4", m);
ctx.stack_.push_back(m);
// That's an entry for dhcp6 socket.
dhcp6_server_socket: DHCP6_SERVER {
+ ctx.unique("dhcp6", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("dhcp6", m);
ctx.stack_.push_back(m);
// That's an entry for d2 socket.
d2_server_socket: D2_SERVER {
+ ctx.unique("d2", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("d2", m);
ctx.stack_.push_back(m);
// This rule defines socket-name parameter.
socket_name: SOCKET_NAME {
+ ctx.unique("socket-name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
// This rule specifies socket type.
socket_type: SOCKET_TYPE {
+ ctx.unique("socket-type", ctx.loc2pos(@1));
ctx.enter(ctx.SOCKET_TYPE);
} COLON socket_type_value {
ctx.stack_.back()->set("socket-type", $4);
// --- Loggers starts here -----------------------------------------------------
loggers: LOGGERS {
+ ctx.unique("loggers", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("loggers", l);
ctx.stack_.push_back(l);
;
name: NAME {
+ ctx.unique("name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
};
debuglevel: DEBUGLEVEL COLON INTEGER {
+ ctx.unique("debuglevel", ctx.loc2pos(@1));
ElementPtr dl(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("debuglevel", dl);
};
severity: SEVERITY {
+ ctx.unique("severity", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
};
output_options_list: OUTPUT_OPTIONS {
+ ctx.unique("output_options", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("output_options", l);
ctx.stack_.push_back(l);
;
output: OUTPUT {
+ ctx.unique("output", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
};
flush: FLUSH COLON BOOLEAN {
+ ctx.unique("flush", ctx.loc2pos(@1));
ElementPtr flush(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("flush", flush);
}
maxsize: MAXSIZE COLON INTEGER {
+ ctx.unique("maxsize", ctx.loc2pos(@1));
ElementPtr maxsize(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("maxsize", maxsize);
}
maxver: MAXVER COLON INTEGER {
+ ctx.unique("maxver", ctx.loc2pos(@1));
ElementPtr maxver(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("maxver", maxver);
}
pattern: PATTERN {
+ ctx.unique("pattern", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
" \"comment\": \"second\" }}\n",
ParserContext::PARSER_AGENT,
"<string>:2.23: syntax error, unexpected \",\", expecting }");
+
+ // duplicate of not string entries
+ testError("{ \"Control-agent\":{\n"
+ " \"http-port\": 8000,\n"
+ " \"http-port\": 8001 }}\n",
+ ParserContext::PARSER_AGENT,
+ "<string>:3:2: duplicate http-port entries in "
+ "Control-agent map (previous at <string>:2:15)");
+
+ // duplicate of string entries
+ testError("{ \"Control-agent\":{\n"
+ " \"http-host\": \"127.0.0.1\",\n"
+ " \"http-host\": \"::1\" }}\n",
+ ParserContext::PARSER_AGENT,
+ "<string>:3:2: duplicate http-host entries in "
+ "Control-agent map (previous at <string>:2:15)");
}
// Check unicode escapes
not_empty_map: STRING COLON value {
// map containing a single entry
+ ctx.unique($1, ctx.loc2pos(@1));
ctx.stack_.back()->set($1, $3);
}
| not_empty_map COMMA STRING COLON value {
// map consisting of a shorter map followed by
// comma and string:value
+ ctx.unique($3, ctx.loc2pos(@3));
ctx.stack_.back()->set($3, $5);
}
;
// --- dhcp ddns ---------------------------------------------
// This represents the single top level entry, e.g. DhcpDdns.
global_object: DHCPDDNS {
+ ctx.unique("DhcpDdns", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("DhcpDdns", m);
ctx.stack_.push_back(m);
;
ip_address: IP_ADDRESS {
+ ctx.unique("ip-address", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
};
port: PORT COLON INTEGER {
+ ctx.unique("port", ctx.loc2pos(@1));
if ($3 <= 0 || $3 >= 65536 ) {
error(@3, "port must be greater than zero but less than 65536");
}
};
dns_server_timeout: DNS_SERVER_TIMEOUT COLON INTEGER {
+ ctx.unique("dns-server-timeout", ctx.loc2pos(@1));
if ($3 <= 0) {
error(@3, "dns-server-timeout must be greater than zero");
} else {
};
ncr_protocol: NCR_PROTOCOL {
+ ctx.unique("ncr-protocol", ctx.loc2pos(@1));
ctx.enter(ctx.NCR_PROTOCOL);
} COLON ncr_protocol_value {
ctx.stack_.back()->set("ncr-protocol", $4);
;
ncr_format: NCR_FORMAT {
+ ctx.unique("ncr-format", ctx.loc2pos(@1));
ctx.enter(ctx.NCR_FORMAT);
} COLON JSON {
ElementPtr json(new StringElement("JSON", ctx.loc2pos(@4)));
};
forward_ddns : FORWARD_DDNS {
+ ctx.unique("forward-ddns", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("forward-ddns", m);
ctx.stack_.push_back(m);
};
reverse_ddns : REVERSE_DDNS {
+ ctx.unique("reverse-ddns", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("reverse-ddns", m);
ctx.stack_.push_back(m);
// --- ddns-domains ----------------------------------------
ddns_domains: DDNS_DOMAINS {
+ ctx.unique("ddns-domains", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("ddns-domains", l);
ctx.stack_.push_back(l);
// @todo NAME needs to be an FQDN sort of thing
ddns_domain_name: NAME {
+ ctx.unique("name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
if ($4 == "") {
};
ddns_domain_key_name: KEY_NAME {
+ ctx.unique("key-name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
// --- dns-servers ----------------------------------------
dns_servers: DNS_SERVERS {
+ ctx.unique("dns-servers", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("dns-servers", l);
ctx.stack_.push_back(l);
;
dns_server_hostname: HOSTNAME {
+ ctx.unique("hostname", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
if ($4 != "") {
};
dns_server_ip_address: IP_ADDRESS {
+ ctx.unique("ip-address", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
};
dns_server_port: PORT COLON INTEGER {
+ ctx.unique("port", ctx.loc2pos(@1));
if ($3 <= 0 || $3 >= 65536 ) {
error(@3, "port must be greater than zero but less than 65536");
}
// --- tsig-keys ----------------------------------------
// "tsig-keys" : [ ... ]
tsig_keys: TSIG_KEYS {
+ ctx.unique("tsig-keys", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("tsig-keys", l);
ctx.stack_.push_back(l);
;
tsig_key_name: NAME {
+ ctx.unique("name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
if ($4 == "") {
};
tsig_key_algorithm: ALGORITHM {
+ ctx.unique("algorithm", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
if ($4 == "") {
};
tsig_key_digest_bits: DIGEST_BITS COLON INTEGER {
+ ctx.unique("digest-bits", ctx.loc2pos(@1));
if ($3 < 0 || ($3 > 0 && ($3 % 8 != 0))) {
error(@3, "TSIG key digest-bits must either be zero or a positive, multiple of eight");
}
};
tsig_key_secret: SECRET {
+ ctx.unique("secret", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
if ($4 == "") {
// --- control socket ----------------------------------------
control_socket: CONTROL_SOCKET {
+ ctx.unique("control-socket", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("control-socket", m);
ctx.stack_.push_back(m);
;
control_socket_type: SOCKET_TYPE {
+ ctx.unique("socket-type", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr stype(new StringElement($4, ctx.loc2pos(@4)));
};
control_socket_name: SOCKET_NAME {
+ ctx.unique("socket-name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
// --- loggers entry -----------------------------------------
loggers: LOGGERS {
+ ctx.unique("loggers", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("loggers", l);
ctx.stack_.push_back(l);
;
name: NAME {
+ ctx.unique("name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
};
debuglevel: DEBUGLEVEL COLON INTEGER {
+ ctx.unique("debuglevel", ctx.loc2pos(@1));
ElementPtr dl(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("debuglevel", dl);
};
+
severity: SEVERITY {
+ ctx.unique("severity", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
};
output_options_list: OUTPUT_OPTIONS {
+ ctx.unique("output_options", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("output_options", l);
ctx.stack_.push_back(l);
;
output: OUTPUT {
+ ctx.unique("output", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
};
flush: FLUSH COLON BOOLEAN {
+ ctx.unique("flush", ctx.loc2pos(@1));
ElementPtr flush(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("flush", flush);
}
maxsize: MAXSIZE COLON INTEGER {
+ ctx.unique("maxsize", ctx.loc2pos(@1));
ElementPtr maxsize(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("maxsize", maxsize);
}
maxver: MAXVER COLON INTEGER {
+ ctx.unique("maxver", ctx.loc2pos(@1));
ElementPtr maxver(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("maxver", maxver);
}
pattern: PATTERN {
+ ctx.unique("pattern", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
" \"comment\": \"second\" }}\n",
D2ParserContext::PARSER_DHCPDDNS,
"<string>:2.23: syntax error, unexpected \",\", expecting }");
+
+ // duplicate of not string entries
+ testError("{ \"DhcpDdns\":{\n"
+ " \"port\": 53001,\n"
+ " \"port\": 53002 }}\n",
+ D2ParserContext::PARSER_DHCPDDNS,
+ "<string>:3:3: duplicate port entries in "
+ "DhcpDdns map (previous at <string>:2:11)");
+
+ // duplicate of string entries
+ testError("{ \"DhcpDdns\":{\n"
+ " \"ip-address\": \"127.0.0.1\",\n"
+ " \"ip-address\": \"::1\" }}\n",
+ D2ParserContext::PARSER_DHCPDDNS,
+ "<string>:3:3: duplicate ip-address entries in "
+ "DhcpDdns map (previous at <string>:2:17)");
}
// Check unicode escapes
" \"comment\": \"second\" }}\n",
Parser4Context::PARSER_DHCP4,
"<string>:2.23: syntax error, unexpected \",\", expecting }");
+
+ // duplicate of not string entries
+ testError("{ \"Dhcp4\":{\n"
+ " \"subnet4\": [],\n"
+ " \"subnet4\": [] }}\n",
+ Parser4Context::PARSER_DHCP4,
+ "<string>:3:2: duplicate subnet4 entries in "
+ "Dhcp4 map (previous at <string>:2:2)");
+
+ // duplicate of string entries
+ testError("{\n"
+ " \"server-hostname\": \"nohost\",\n"
+ " \"server-hostname\": \"nofile\" }\n",
+ Parser4Context::PARSER_HOST_RESERVATION,
+ "<string>:3:2: duplicate server-hostname entries in "
+ "reservations map (previous at <string>:2:21)");
}
// Check unicode escapes
// covers all longer lists recursively.
not_empty_map: STRING COLON value {
// map containing a single entry
+ ctx.unique($1, ctx.loc2pos(@1));
ctx.stack_.back()->set($1, $3);
}
| not_empty_map COMMA STRING COLON value {
// map consisting of a shorter map followed by
// comma and string:value
+ ctx.unique($3, ctx.loc2pos(@3));
ctx.stack_.back()->set($3, $5);
}
;
;
boot_update: BOOT_UPDATE COLON BOOLEAN {
+ ctx.unique("boot-update", ctx.loc2pos(@1));
ElementPtr flag(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("boot-update", flag);
};
subscribe_changes: SUBSCRIBE_CHANGES COLON BOOLEAN {
+ ctx.unique("subscribe-changes", ctx.loc2pos(@1));
ElementPtr flag(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("subscribe-changes", flag);
};
validate_changes: VALIDATE_CHANGES COLON BOOLEAN {
+ ctx.unique("validate-changes", ctx.loc2pos(@1));
ElementPtr flag(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("validate-changes", flag);
};
// --- hooks-libraries ---------------------------------------------------------
hooks_libraries: HOOKS_LIBRARIES {
+ ctx.unique("hooks-libraries", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("hooks-libraries", l);
ctx.stack_.push_back(l);
;
library: LIBRARY {
+ ctx.unique("library", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr lib(new StringElement($4, ctx.loc2pos(@4)));
};
parameters: PARAMETERS {
+ ctx.unique("parameters", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON map_value {
ctx.stack_.back()->set("parameters", $4);
// --- managed-servsers starts here ---------------------------------------------
managed_servers: MANAGED_SERVERS COLON LCURLY_BRACKET {
+ ctx.unique("managed-servers", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("managed-servers", m);
ctx.stack_.push_back(m);
// That's an entry for dhcp4 server.
dhcp4_server: DHCP4_SERVER {
+ ctx.unique("dhcp4", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("dhcp4", m);
ctx.stack_.push_back(m);
// That's an entry for dhcp6 server.
dhcp6_server: DHCP6_SERVER {
+ ctx.unique("dhcp6", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("dhcp6", m);
ctx.stack_.push_back(m);
// That's an entry for d2 server.
d2_server: D2_SERVER {
+ ctx.unique("d2", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("d2", m);
ctx.stack_.push_back(m);
// That's an entry for ca server.
ca_server: CA_SERVER {
+ ctx.unique("ca", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("ca", m);
ctx.stack_.push_back(m);
// YANG model
model: MODEL {
+ ctx.unique("model", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr model(new StringElement($4, ctx.loc2pos(@4)));
// Control socket.
control_socket: CONTROL_SOCKET {
+ ctx.unique("control-socket", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("control-socket", m);
ctx.stack_.push_back(m);
;
socket_type: SOCKET_TYPE {
+ ctx.unique("socket-type", ctx.loc2pos(@1));
ctx.enter(ctx.SOCKET_TYPE);
} COLON socket_type_value {
ctx.stack_.back()->set("socket-type", $4);
;
// Unix name.
socket_name: SOCKET_NAME {
+ ctx.unique("socket-name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
// HTTP url.
socket_url: SOCKET_URL {
+ ctx.unique("socket-url", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr url(new StringElement($4, ctx.loc2pos(@4)));
// --- Loggers starts here -----------------------------------------------------
loggers: LOGGERS {
+ ctx.unique("loggers", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("loggers", l);
ctx.stack_.push_back(l);
;
name: NAME {
+ ctx.unique("name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
};
debuglevel: DEBUGLEVEL COLON INTEGER {
+ ctx.unique("debuglevel", ctx.loc2pos(@1));
ElementPtr dl(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("debuglevel", dl);
};
severity: SEVERITY {
+ ctx.unique("severity", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
};
output_options_list: OUTPUT_OPTIONS {
+ ctx.unique("output_options", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("output_options", l);
ctx.stack_.push_back(l);
;
output: OUTPUT {
+ ctx.unique("output", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
};
flush: FLUSH COLON BOOLEAN {
+ ctx.unique("flush", ctx.loc2pos(@1));
ElementPtr flush(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("flush", flush);
};
maxsize: MAXSIZE COLON INTEGER {
+ ctx.unique("maxsize", ctx.loc2pos(@1));
ElementPtr maxsize(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("maxsize", maxsize);
};
maxver: MAXVER COLON INTEGER {
+ ctx.unique("maxver", ctx.loc2pos(@1));
ElementPtr maxver(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("maxver", maxver);
};
pattern: PATTERN {
+ ctx.unique("pattern", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORDS);
} COLON STRING {
ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
case MANAGED_SERVERS:
return ("managed-servers");
case SERVER:
- return ("managed-servers/*");
+ return ("managed-servers entry");
case CONTROL_SOCKET:
return ("control-socket");
case SOCKET_TYPE:
" \"comment\": \"second\" }}\n",
ParserContext::PARSER_NETCONF,
"<string>:2.23: syntax error, unexpected \",\", expecting }");
+
+ // duplicate of not string entries
+ testError("{ \"Netconf\":{\n"
+ " \"boot-update\": true,\n"
+ " \"boot-update\": false }}\n",
+ ParserContext::PARSER_NETCONF,
+ "<string>:3:2: duplicate boot-update entries in "
+ "Netconf map (previous at <string>:2:17)");
+
+ // duplicate of string entries
+ testError("{ \"Netconf\":{\n"
+ " \"managed-servers\": {\n"
+ " \"d2\": {\n"
+ " \"model\": \"foo\",\n"
+ " \"model\": \"bar\" }}}}\n",
+ ParserContext::PARSER_NETCONF,
+ "<string>:5:7: duplicate model entries in "
+ "managed-servers entry map (previous at <string>:4:16)");
}
// Check unicode escapes