blob: 96ccc532e8a568ed6ad0a2820ef441262561c712 [file] [log] [blame]
Václav Kubernát0a2a2e82018-05-11 13:59:12 +02001/*
2 * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
3 * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
4 *
5 * Written by Václav Kubernát <kubervac@fit.cvut.cz>
6 *
7*/
8
9#pragma once
Václav Kubernát195eeea2018-05-18 13:52:36 +020010
Václav Kubernát57272422019-02-08 12:48:24 +010011#include <boost/mpl/for_each.hpp>
12#include "ast_commands.hpp"
Václav Kubernát195eeea2018-05-18 13:52:36 +020013#include "parser_context.hpp"
Václav Kubernát48fc3832018-05-28 14:21:22 +020014#include "schema.hpp"
Václav Kubernátebca2552018-06-08 19:06:02 +020015#include "utils.hpp"
Václav Kubernát329c6c32019-02-06 16:41:53 +010016namespace x3 = boost::spirit::x3;
17
18struct parser_context_tag;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020019
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020020struct keyValue_class {
21 template <typename T, typename Iterator, typename Context>
22 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
23 {
24 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020025 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020026
27 if (parserContext.m_tmpListKeys.find(ast.first) != parserContext.m_tmpListKeys.end()) {
28 _pass(context) = false;
29 parserContext.m_errorMsg = "Key \"" + ast.first + "\" was entered more than once.";
Václav Kubernát744f57f2018-06-29 22:46:26 +020030 } else if (!schema.listHasKey(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName}, ast.first)) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020031 _pass(context) = false;
32 parserContext.m_errorMsg = parserContext.m_tmpListName + " is not indexed by \"" + ast.first + "\".";
Václav Kubernát41378452018-06-06 16:29:40 +020033 } else {
34 parserContext.m_tmpListKeys.insert(ast.first);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020035 }
36 }
Václav Kubernát41378452018-06-06 16:29:40 +020037
38 template <typename Iterator, typename Exception, typename Context>
39 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
40 {
41 auto& parserContext = x3::get<parser_context_tag>(context);
42 parserContext.m_errorMsg = "Error parsing key values here:";
43 return x3::error_handler_result::rethrow;
44 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020045};
Václav Kubernát41378452018-06-06 16:29:40 +020046
Václav Kubernát744f57f2018-06-29 22:46:26 +020047struct node_identifier_class {
48 template <typename T, typename Iterator, typename Context>
49 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
50 {
51 auto& parserContext = x3::get<parser_context_tag>(context);
52
53 if (!parserContext.m_topLevelModulePresent) {
54 if (parserContext.m_errorMsg.empty())
55 parserContext.m_errorMsg = "You have to specify a top level module.";
56 _pass(context) = false;
57 }
58 }
59};
60
Václav Kubernát89728d82018-09-13 16:28:28 +020061struct key_identifier_class;
62
Václav Kubernát744f57f2018-06-29 22:46:26 +020063struct module_identifier_class;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020064
65struct listPrefix_class {
66 template <typename T, typename Iterator, typename Context>
67 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
68 {
69 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020070 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020071
Václav Kubernát744f57f2018-06-29 22:46:26 +020072 if (schema.isList(parserContext.m_curPath, {parserContext.m_curModule, ast})) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020073 parserContext.m_tmpListName = ast;
74 } else {
75 _pass(context) = false;
76 }
77 }
78};
79
80struct listSuffix_class {
81 template <typename T, typename Iterator, typename Context>
82 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
83 {
84 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020085 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020086
Václav Kubernát744f57f2018-06-29 22:46:26 +020087 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020088 std::set<std::string> keysSupplied;
89 for (const auto& it : ast)
90 keysSupplied.insert(it.first);
91
92 if (keysNeeded != keysSupplied) {
93 parserContext.m_errorMsg = "Not enough keys for " + parserContext.m_tmpListName + ". " +
94 "These keys were not supplied:";
95 std::set<std::string> missingKeys;
96 std::set_difference(keysNeeded.begin(), keysNeeded.end(),
97 keysSupplied.begin(), keysSupplied.end(),
98 std::inserter(missingKeys, missingKeys.end()));
99
100 for (const auto& it : missingKeys)
101 parserContext.m_errorMsg += " " + it;
102 parserContext.m_errorMsg += ".";
103
104 _pass(context) = false;
105 }
106 }
Václav Kubernát41378452018-06-06 16:29:40 +0200107
108 template <typename Iterator, typename Exception, typename Context>
109 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
110 {
111 auto& parserContext = x3::get<parser_context_tag>(context);
112 if (parserContext.m_errorMsg.empty())
113 parserContext.m_errorMsg = "Expecting ']' here:";
114 return x3::error_handler_result::rethrow;
Václav Kubernát41378452018-06-06 16:29:40 +0200115 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200116};
117struct listElement_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200118 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200119 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200120 {
121 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200122 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200123 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200124 } else {
125 return x3::error_handler_result::rethrow;
126 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200127 }
128};
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200129struct list_class {
130 template <typename T, typename Iterator, typename Context>
131 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
132 {
133 auto& parserContext = x3::get<parser_context_tag>(context);
134 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200135
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200136 if (!schema.isList(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name})) {
137 _pass(context) = false;
138 }
139 }
140};
Václav Kubernát60d6f292018-05-25 09:45:32 +0200141struct nodeup_class {
142 template <typename T, typename Iterator, typename Context>
143 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
144 {
145 auto& parserContext = x3::get<parser_context_tag>(context);
146
Václav Kubernát744f57f2018-06-29 22:46:26 +0200147 if (parserContext.m_curPath.m_nodes.empty())
Václav Kubernát60d6f292018-05-25 09:45:32 +0200148 _pass(context) = false;
Václav Kubernát60d6f292018-05-25 09:45:32 +0200149 }
150};
151
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200152struct container_class {
153 template <typename T, typename Iterator, typename Context>
154 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
155 {
156 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +0200157 const auto& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200158
Václav Kubernát744f57f2018-06-29 22:46:26 +0200159 if (!schema.isContainer(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200160 _pass(context) = false;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200161 }
162};
163
Václav Kubernát07204242018-06-04 18:12:09 +0200164struct leaf_class {
165 template <typename T, typename Iterator, typename Context>
166 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
167 {
168 auto& parserContext = x3::get<parser_context_tag>(context);
169 const auto& schema = parserContext.m_schema;
170
Václav Kubernát744f57f2018-06-29 22:46:26 +0200171 if (!schema.isLeaf(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
172 _pass(context) = false;
173 }
174};
175
Václav Kubernát744f57f2018-06-29 22:46:26 +0200176struct module_class {
177 template <typename T, typename Iterator, typename Context>
178 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
179 {
180 auto& parserContext = x3::get<parser_context_tag>(context);
181 const auto& schema = parserContext.m_schema;
182
183 if (schema.isModule(parserContext.m_curPath, ast.m_name)) {
184 parserContext.m_curModule = ast.m_name;
185 parserContext.m_topLevelModulePresent = true;
Václav Kubernát07204242018-06-04 18:12:09 +0200186 } else {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200187 parserContext.m_errorMsg = "Invalid module name.";
Václav Kubernát07204242018-06-04 18:12:09 +0200188 _pass(context) = false;
189 }
190 }
191};
192
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200193struct schemaNode_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200194 template <typename T, typename Iterator, typename Context>
Václav Kubernát744f57f2018-06-29 22:46:26 +0200195 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200196 {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200197 auto& parserContext = x3::get<parser_context_tag>(context);
198 if (ast.m_suffix.type() == typeid(nodeup_)) {
199 parserContext.m_curPath.m_nodes.pop_back();
200 if (parserContext.m_curPath.m_nodes.empty())
201 parserContext.m_topLevelModulePresent = false;
202 } else {
203 parserContext.m_curPath.m_nodes.push_back(ast);
204 parserContext.m_curModule = boost::none;
205 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200206 }
Václav Kubernát744f57f2018-06-29 22:46:26 +0200207};
Václav Kubernát07204242018-06-04 18:12:09 +0200208
Václav Kubernát39ae9592019-02-05 17:35:16 +0100209struct dataNodeList_class {
210 template <typename T, typename Iterator, typename Context>
211 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
212 {
213 auto& parserContext = x3::get<parser_context_tag>(context);
214 parserContext.m_curPath.m_nodes.push_back(dataNodeToSchemaNode(ast));
215 }
216};
Václav Kubernát5c75b252018-10-10 18:33:47 +0200217
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200218struct dataNode_class {
219 template <typename T, typename Iterator, typename Context>
220 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
221 {
222 auto& parserContext = x3::get<parser_context_tag>(context);
223 if (ast.m_suffix.type() == typeid(nodeup_)) {
224 parserContext.m_curPath.m_nodes.pop_back();
225 if (parserContext.m_curPath.m_nodes.empty())
226 parserContext.m_topLevelModulePresent = false;
227 } else {
228 parserContext.m_curPath.m_nodes.push_back(dataNodeToSchemaNode(ast));
229 parserContext.m_curModule = boost::none;
230 }
231 }
232};
233
Václav Kubernát37171a12018-08-31 17:01:48 +0200234struct absoluteStart_class {
235 template <typename T, typename Iterator, typename Context>
236 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
237 {
238 auto& parserContext = x3::get<parser_context_tag>(context);
239 parserContext.m_curPath.m_nodes.clear();
240 }
241};
242
Václav Kubernát5c75b252018-10-10 18:33:47 +0200243struct dataNodesListEnd_class;
244
245struct dataPathListEnd_class;
246
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200247struct dataPath_class {
248 template <typename Iterator, typename Exception, typename Context>
249 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
250 {
251 auto& parserContext = x3::get<parser_context_tag>(context);
252 if (parserContext.m_errorMsg.empty()) {
253 parserContext.m_errorMsg = "Expected path.";
254 return x3::error_handler_result::fail;
255 } else {
256 return x3::error_handler_result::rethrow;
257 }
258 }
259};
260
261struct schemaPath_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200262 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200263 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát07204242018-06-04 18:12:09 +0200264 {
265 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200266 if (parserContext.m_errorMsg.empty()) {
267 parserContext.m_errorMsg = "Expected path.";
Václav Kubernát07204242018-06-04 18:12:09 +0200268 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200269 } else {
270 return x3::error_handler_result::rethrow;
271 }
Václav Kubernát07204242018-06-04 18:12:09 +0200272 }
273};
274
Václav Kubernát6d791432018-10-25 16:00:35 +0200275struct discard_class;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200276
Václav Kubernát11afac72018-07-18 14:59:53 +0200277struct ls_class;
278
Václav Kubernát744f57f2018-06-29 22:46:26 +0200279struct cd_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200280 template <typename Iterator, typename Exception, typename Context>
281 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
282 {
283 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200284 if (parserContext.m_errorMsg.empty())
285 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
286 return x3::error_handler_result::rethrow;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200287 }
288};
Václav Kubernátb61336d2018-05-28 17:35:03 +0200289
290struct presenceContainerPathHandler {
291 template <typename T, typename Iterator, typename Context>
292 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
293 {
294 auto& parserContext = x3::get<parser_context_tag>(context);
295 const auto& schema = parserContext.m_schema;
296 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200297 boost::optional<std::string> module;
298 if (ast.m_path.m_nodes.back().m_prefix)
299 module = ast.m_path.m_nodes.back().m_prefix.value().m_name;
300 container_ cont = boost::get<container_>(ast.m_path.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200301 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200302
Václav Kubernát744f57f2018-06-29 22:46:26 +0200303 if (!schema.isPresenceContainer(location, {module, cont.m_name})) {
Václav Kubernát41378452018-06-06 16:29:40 +0200304 parserContext.m_errorMsg = "This container is not a presence container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200305 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200306 }
307 } catch (boost::bad_get&) {
Václav Kubernát41378452018-06-06 16:29:40 +0200308 parserContext.m_errorMsg = "This is not a container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200309 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200310 }
311 }
312
313 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200314 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernátb61336d2018-05-28 17:35:03 +0200315 {
316 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200317 if (parserContext.m_errorMsg.empty())
318 parserContext.m_errorMsg = "Couldn't parse create/delete command.";
319 return x3::error_handler_result::rethrow;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200320 }
321};
322
323struct create_class : public presenceContainerPathHandler {
324};
325
326struct delete_class : public presenceContainerPathHandler {
327};
328
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200329struct leaf_path_class {
330 template <typename T, typename Iterator, typename Context>
331 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
332 {
333 auto& parserContext = x3::get<parser_context_tag>(context);
334 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200335 auto leaf = boost::get<leaf_>(ast.m_nodes.back().m_suffix);
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200336 } catch (boost::bad_get&) {
337 parserContext.m_errorMsg = "This is not a path to leaf.";
338 _pass(context) = false;
339 }
340 }
341};
342
Václav Kubernátebca2552018-06-08 19:06:02 +0200343struct leaf_data_class {
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200344 template <typename Iterator, typename Exception, typename Context>
345 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
346 {
347 auto& parserContext = x3::get<parser_context_tag>(context);
348 auto& schema = parserContext.m_schema;
349 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200350 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200351 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
352 if (location.m_nodes.empty()) {
Václav Kubernát5c75b252018-10-10 18:33:47 +0200353 parserContext.m_curModule = parserContext.m_curPath.m_nodes.back().m_prefix->m_name;
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200354 }
Václav Kubernát744f57f2018-06-29 22:46:26 +0200355 parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, {parserContext.m_curModule, leaf.m_name})) + " here:";
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200356 return x3::error_handler_result::fail;
357 }
358 return x3::error_handler_result::rethrow;
359 }
Václav Kubernátebca2552018-06-08 19:06:02 +0200360};
361
362struct leaf_data_base_class {
363 yang::LeafDataTypes m_type;
364
365 leaf_data_base_class(yang::LeafDataTypes type)
366 : m_type(type)
367 {
368 }
369
370 template <typename T, typename Iterator, typename Context>
371 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
372 {
373 auto& parserContext = x3::get<parser_context_tag>(context);
374 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200375 boost::optional<std::string> module;
376 if (parserContext.m_curPath.m_nodes.back().m_prefix)
377 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200378
Václav Kubernát744f57f2018-06-29 22:46:26 +0200379 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200380 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátebca2552018-06-08 19:06:02 +0200381
Václav Kubernát744f57f2018-06-29 22:46:26 +0200382 if (schema.leafType(location, {module, leaf.m_name}) != m_type) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200383 _pass(context) = false;
384 }
385 }
386};
387
388struct leaf_data_enum_class : leaf_data_base_class {
389 leaf_data_enum_class()
390 : leaf_data_base_class(yang::LeafDataTypes::Enum)
391 {
392 }
393
394 template <typename T, typename Iterator, typename Context>
395 void on_success(Iterator const& start, Iterator const& end, T& ast, Context const& context)
396 {
397 leaf_data_base_class::on_success(start, end, ast, context);
398 auto& parserContext = x3::get<parser_context_tag>(context);
399 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200400 boost::optional<std::string> module;
401 if (parserContext.m_curPath.m_nodes.back().m_prefix)
402 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200403
Václav Kubernát744f57f2018-06-29 22:46:26 +0200404 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200405 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátebca2552018-06-08 19:06:02 +0200406
Václav Kubernát744f57f2018-06-29 22:46:26 +0200407 if (!schema.leafEnumHasValue(location, {module, leaf.m_name}, ast.m_value)) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200408 _pass(context) = false;
409 }
410 }
411};
412
413struct leaf_data_decimal_class : leaf_data_base_class {
414 leaf_data_decimal_class()
415 : leaf_data_base_class(yang::LeafDataTypes::Decimal)
416 {
417 }
418};
419
420struct leaf_data_bool_class : leaf_data_base_class {
421 leaf_data_bool_class()
422 : leaf_data_base_class(yang::LeafDataTypes::Bool)
423 {
424 }
425};
426
427struct leaf_data_int_class : leaf_data_base_class {
428 leaf_data_int_class()
429 : leaf_data_base_class(yang::LeafDataTypes::Int)
430 {
431 }
432};
433
434struct leaf_data_uint_class : leaf_data_base_class {
435 leaf_data_uint_class()
436 : leaf_data_base_class(yang::LeafDataTypes::Uint)
437 {
438 }
439};
440
441struct leaf_data_string_class : leaf_data_base_class {
442 leaf_data_string_class()
443 : leaf_data_base_class(yang::LeafDataTypes::String)
444 {
445 }
446};
447
Václav Kubernát07204242018-06-04 18:12:09 +0200448struct set_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200449 template <typename Iterator, typename Exception, typename Context>
450 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
451 {
452 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200453 if (parserContext.m_errorMsg.empty())
454 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
455 return x3::error_handler_result::rethrow;
Václav Kubernát07204242018-06-04 18:12:09 +0200456 }
457};
458
Václav Kubernát812ee282018-08-30 17:10:03 +0200459struct commit_class;
460
Václav Kubernát054cc992019-02-21 14:23:52 +0100461struct help_class;
462
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200463struct get_class;
464
Václav Kubernátb61336d2018-05-28 17:35:03 +0200465struct command_class {
466 template <typename Iterator, typename Exception, typename Context>
467 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
468 {
469 auto& parserContext = x3::get<parser_context_tag>(context);
470 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
Václav Kubernát41378452018-06-06 16:29:40 +0200471 if (parserContext.m_errorMsg.empty()) {
472 parserContext.m_errorMsg = "Unknown command.";
473 }
474 error_handler(x.where(), parserContext.m_errorMsg);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200475 return x3::error_handler_result::fail;
476 }
477};
Václav Kubernát5c75b252018-10-10 18:33:47 +0200478
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100479struct initializePath_class {
Václav Kubernát5c75b252018-10-10 18:33:47 +0200480 template <typename T, typename Iterator, typename Context>
481 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
482 {
483 auto& parserContext = x3::get<parser_context_tag>(context);
484 parserContext.m_curPath = parserContext.m_curPathOrig;
485 parserContext.m_tmpListKeys.clear();
486 parserContext.m_tmpListName.clear();
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100487 parserContext.m_suggestions.clear();
Václav Kubernát5c75b252018-10-10 18:33:47 +0200488 if (!parserContext.m_curPath.m_nodes.empty() && parserContext.m_curPath.m_nodes.at(0).m_prefix)
489 parserContext.m_topLevelModulePresent = true;
490 else
491 parserContext.m_topLevelModulePresent = false;
492 }
493};
Václav Kubernátd6fd2492018-11-19 15:11:16 +0100494
495struct trailingSlash_class;
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100496
497struct createPathSuggestions_class {
498 template <typename T, typename Iterator, typename Context>
499 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
500 {
501 auto& parserContext = x3::get<parser_context_tag>(context);
502 const auto& schema = parserContext.m_schema;
503
504 parserContext.m_completionIterator = begin;
505 parserContext.m_suggestions = schema.childNodes(parserContext.m_curPath, Recursion::NonRecursive);
506 }
507};
Václav Kubernát329c6c32019-02-06 16:41:53 +0100508
509std::set<std::string> generateMissingKeyCompletionSet(std::set<std::string> keysNeeded, std::set<std::string> currentSet);
510
511struct createKeySuggestions_class {
512 template <typename T, typename Iterator, typename Context>
513 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
514 {
515 auto& parserContext = x3::get<parser_context_tag>(context);
516 const auto& schema = parserContext.m_schema;
517
518 parserContext.m_completionIterator = begin;
519
520 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
521 parserContext.m_suggestions = generateMissingKeyCompletionSet(keysNeeded, parserContext.m_tmpListKeys);
522 }
523};
524
525struct suggestKeysEnd_class {
526 template <typename T, typename Iterator, typename Context>
527 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
528 {
529 auto& parserContext = x3::get<parser_context_tag>(context);
530 const auto& schema = parserContext.m_schema;
531
532 parserContext.m_completionIterator = begin;
533 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
534 if (generateMissingKeyCompletionSet(keysNeeded, parserContext.m_tmpListKeys).empty()) {
535 parserContext.m_suggestions = {"]/"};
536 } else {
537 parserContext.m_suggestions = {"]"};
538 }
539 }
540};
Václav Kubernát57272422019-02-08 12:48:24 +0100541
542struct commandNamesVisitor {
543 template <typename T>
544 auto operator()(boost::type<T>)
545 {
546 return T::name;
547 }
548};
549
550struct createCommandSuggestions_class {
551 template <typename T, typename Iterator, typename Context>
552 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
553 {
554 auto& parserContext = x3::get<parser_context_tag>(context);
555 parserContext.m_completionIterator = begin;
556
557 parserContext.m_suggestions.clear();
558 boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([&parserContext](auto cmd) {
559 parserContext.m_suggestions.emplace(commandNamesVisitor()(cmd));
560 });
561 }
562};
Václav Kubernátac035d62019-02-18 10:59:08 +0100563
564struct completing_class {
565 template <typename T, typename Iterator, typename Context>
566 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
567 {
568 auto& parserContext = x3::get<parser_context_tag>(context);
569
570 if (!parserContext.m_completing)
571 _pass(context) = false;
572 }
573};
Václav Kubernát989b5de2019-02-20 16:28:35 +0100574
575struct createEnumSuggestions_class {
576 template <typename T, typename Iterator, typename Context>
577 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
578 {
579 auto& parserContext = x3::get<parser_context_tag>(context);
580 parserContext.m_completionIterator = begin;
581 const Schema& schema = parserContext.m_schema;
582
583 boost::optional<std::string> module;
584 if (parserContext.m_curPath.m_nodes.back().m_prefix)
585 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
586
587 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
588 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
589
590 parserContext.m_suggestions = schema.enumValues(location, {module, leaf.m_name});
591 }
592};