blob: b32330ebe45af73ed63058e886ab13f5993612f2 [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();
Václav Kubernátb9621052019-03-18 18:27:49 +0100240 parserContext.m_topLevelModulePresent = false;
Václav Kubernát37171a12018-08-31 17:01:48 +0200241 }
242};
243
Václav Kubernát5c75b252018-10-10 18:33:47 +0200244struct dataNodesListEnd_class;
245
246struct dataPathListEnd_class;
247
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200248struct dataPath_class {
249 template <typename Iterator, typename Exception, typename Context>
250 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
251 {
252 auto& parserContext = x3::get<parser_context_tag>(context);
253 if (parserContext.m_errorMsg.empty()) {
254 parserContext.m_errorMsg = "Expected path.";
255 return x3::error_handler_result::fail;
256 } else {
257 return x3::error_handler_result::rethrow;
258 }
259 }
260};
261
262struct schemaPath_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200263 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200264 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát07204242018-06-04 18:12:09 +0200265 {
266 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200267 if (parserContext.m_errorMsg.empty()) {
268 parserContext.m_errorMsg = "Expected path.";
Václav Kubernát07204242018-06-04 18:12:09 +0200269 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200270 } else {
271 return x3::error_handler_result::rethrow;
272 }
Václav Kubernát07204242018-06-04 18:12:09 +0200273 }
274};
275
Václav Kubernát6d791432018-10-25 16:00:35 +0200276struct discard_class;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200277
Václav Kubernát11afac72018-07-18 14:59:53 +0200278struct ls_class;
279
Václav Kubernát744f57f2018-06-29 22:46:26 +0200280struct cd_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200281 template <typename Iterator, typename Exception, typename Context>
282 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
283 {
284 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200285 if (parserContext.m_errorMsg.empty())
286 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
287 return x3::error_handler_result::rethrow;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200288 }
289};
Václav Kubernátb61336d2018-05-28 17:35:03 +0200290
291struct presenceContainerPathHandler {
292 template <typename T, typename Iterator, typename Context>
293 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
294 {
295 auto& parserContext = x3::get<parser_context_tag>(context);
296 const auto& schema = parserContext.m_schema;
297 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200298 boost::optional<std::string> module;
299 if (ast.m_path.m_nodes.back().m_prefix)
300 module = ast.m_path.m_nodes.back().m_prefix.value().m_name;
301 container_ cont = boost::get<container_>(ast.m_path.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200302 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200303
Václav Kubernát744f57f2018-06-29 22:46:26 +0200304 if (!schema.isPresenceContainer(location, {module, cont.m_name})) {
Václav Kubernát41378452018-06-06 16:29:40 +0200305 parserContext.m_errorMsg = "This container is not a presence container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200306 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200307 }
308 } catch (boost::bad_get&) {
Václav Kubernát41378452018-06-06 16:29:40 +0200309 parserContext.m_errorMsg = "This is not a container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200310 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200311 }
312 }
313
314 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200315 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernátb61336d2018-05-28 17:35:03 +0200316 {
317 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200318 if (parserContext.m_errorMsg.empty())
319 parserContext.m_errorMsg = "Couldn't parse create/delete command.";
320 return x3::error_handler_result::rethrow;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200321 }
322};
323
324struct create_class : public presenceContainerPathHandler {
325};
326
327struct delete_class : public presenceContainerPathHandler {
328};
329
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200330struct leaf_path_class {
331 template <typename T, typename Iterator, typename Context>
332 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
333 {
334 auto& parserContext = x3::get<parser_context_tag>(context);
335 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200336 auto leaf = boost::get<leaf_>(ast.m_nodes.back().m_suffix);
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200337 } catch (boost::bad_get&) {
338 parserContext.m_errorMsg = "This is not a path to leaf.";
339 _pass(context) = false;
340 }
341 }
342};
343
Václav Kubernátebca2552018-06-08 19:06:02 +0200344struct leaf_data_class {
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200345 template <typename Iterator, typename Exception, typename Context>
346 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
347 {
348 auto& parserContext = x3::get<parser_context_tag>(context);
349 auto& schema = parserContext.m_schema;
350 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200351 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200352 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
353 if (location.m_nodes.empty()) {
Václav Kubernát5c75b252018-10-10 18:33:47 +0200354 parserContext.m_curModule = parserContext.m_curPath.m_nodes.back().m_prefix->m_name;
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200355 }
Václav Kubernát744f57f2018-06-29 22:46:26 +0200356 parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, {parserContext.m_curModule, leaf.m_name})) + " here:";
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200357 return x3::error_handler_result::fail;
358 }
359 return x3::error_handler_result::rethrow;
360 }
Václav Kubernátebca2552018-06-08 19:06:02 +0200361};
362
363struct leaf_data_base_class {
364 yang::LeafDataTypes m_type;
365
366 leaf_data_base_class(yang::LeafDataTypes type)
367 : m_type(type)
368 {
369 }
370
371 template <typename T, typename Iterator, typename Context>
372 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
373 {
374 auto& parserContext = x3::get<parser_context_tag>(context);
375 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200376 boost::optional<std::string> module;
377 if (parserContext.m_curPath.m_nodes.back().m_prefix)
378 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200379
Václav Kubernát744f57f2018-06-29 22:46:26 +0200380 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200381 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátebca2552018-06-08 19:06:02 +0200382
Václav Kubernát744f57f2018-06-29 22:46:26 +0200383 if (schema.leafType(location, {module, leaf.m_name}) != m_type) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200384 _pass(context) = false;
385 }
386 }
387};
388
389struct leaf_data_enum_class : leaf_data_base_class {
390 leaf_data_enum_class()
391 : leaf_data_base_class(yang::LeafDataTypes::Enum)
392 {
393 }
394
395 template <typename T, typename Iterator, typename Context>
396 void on_success(Iterator const& start, Iterator const& end, T& ast, Context const& context)
397 {
398 leaf_data_base_class::on_success(start, end, ast, context);
399 auto& parserContext = x3::get<parser_context_tag>(context);
400 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200401 boost::optional<std::string> module;
402 if (parserContext.m_curPath.m_nodes.back().m_prefix)
403 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200404
Václav Kubernát744f57f2018-06-29 22:46:26 +0200405 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200406 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátebca2552018-06-08 19:06:02 +0200407
Václav Kubernát744f57f2018-06-29 22:46:26 +0200408 if (!schema.leafEnumHasValue(location, {module, leaf.m_name}, ast.m_value)) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200409 _pass(context) = false;
410 }
411 }
412};
413
414struct leaf_data_decimal_class : leaf_data_base_class {
415 leaf_data_decimal_class()
416 : leaf_data_base_class(yang::LeafDataTypes::Decimal)
417 {
418 }
419};
420
421struct leaf_data_bool_class : leaf_data_base_class {
422 leaf_data_bool_class()
423 : leaf_data_base_class(yang::LeafDataTypes::Bool)
424 {
425 }
426};
427
428struct leaf_data_int_class : leaf_data_base_class {
429 leaf_data_int_class()
430 : leaf_data_base_class(yang::LeafDataTypes::Int)
431 {
432 }
433};
434
435struct leaf_data_uint_class : leaf_data_base_class {
436 leaf_data_uint_class()
437 : leaf_data_base_class(yang::LeafDataTypes::Uint)
438 {
439 }
440};
441
442struct leaf_data_string_class : leaf_data_base_class {
443 leaf_data_string_class()
444 : leaf_data_base_class(yang::LeafDataTypes::String)
445 {
446 }
447};
448
Václav Kubernátab538992019-03-06 15:30:50 +0100449struct leaf_data_binary_data_class;
450
451struct leaf_data_binary_class : leaf_data_base_class {
452 leaf_data_binary_class()
453 : leaf_data_base_class(yang::LeafDataTypes::Binary)
454 {
455 }
456};
457
Václav Kubernát07204242018-06-04 18:12:09 +0200458struct set_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200459 template <typename Iterator, typename Exception, typename Context>
460 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
461 {
462 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200463 if (parserContext.m_errorMsg.empty())
464 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
465 return x3::error_handler_result::rethrow;
Václav Kubernát07204242018-06-04 18:12:09 +0200466 }
467};
468
Václav Kubernát812ee282018-08-30 17:10:03 +0200469struct commit_class;
470
Václav Kubernát054cc992019-02-21 14:23:52 +0100471struct help_class;
472
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200473struct get_class;
474
Václav Kubernátb61336d2018-05-28 17:35:03 +0200475struct command_class {
476 template <typename Iterator, typename Exception, typename Context>
477 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
478 {
479 auto& parserContext = x3::get<parser_context_tag>(context);
480 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
Václav Kubernát41378452018-06-06 16:29:40 +0200481 if (parserContext.m_errorMsg.empty()) {
482 parserContext.m_errorMsg = "Unknown command.";
483 }
484 error_handler(x.where(), parserContext.m_errorMsg);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200485 return x3::error_handler_result::fail;
486 }
487};
Václav Kubernát5c75b252018-10-10 18:33:47 +0200488
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100489struct initializePath_class {
Václav Kubernát5c75b252018-10-10 18:33:47 +0200490 template <typename T, typename Iterator, typename Context>
491 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
492 {
493 auto& parserContext = x3::get<parser_context_tag>(context);
494 parserContext.m_curPath = parserContext.m_curPathOrig;
495 parserContext.m_tmpListKeys.clear();
496 parserContext.m_tmpListName.clear();
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100497 parserContext.m_suggestions.clear();
Václav Kubernát5c75b252018-10-10 18:33:47 +0200498 if (!parserContext.m_curPath.m_nodes.empty() && parserContext.m_curPath.m_nodes.at(0).m_prefix)
499 parserContext.m_topLevelModulePresent = true;
500 else
501 parserContext.m_topLevelModulePresent = false;
502 }
503};
Václav Kubernátd6fd2492018-11-19 15:11:16 +0100504
505struct trailingSlash_class;
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100506
507struct createPathSuggestions_class {
508 template <typename T, typename Iterator, typename Context>
509 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
510 {
511 auto& parserContext = x3::get<parser_context_tag>(context);
512 const auto& schema = parserContext.m_schema;
513
514 parserContext.m_completionIterator = begin;
515 parserContext.m_suggestions = schema.childNodes(parserContext.m_curPath, Recursion::NonRecursive);
516 }
517};
Václav Kubernát329c6c32019-02-06 16:41:53 +0100518
519std::set<std::string> generateMissingKeyCompletionSet(std::set<std::string> keysNeeded, std::set<std::string> currentSet);
520
521struct createKeySuggestions_class {
522 template <typename T, typename Iterator, typename Context>
523 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
524 {
525 auto& parserContext = x3::get<parser_context_tag>(context);
526 const auto& schema = parserContext.m_schema;
527
528 parserContext.m_completionIterator = begin;
529
530 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
531 parserContext.m_suggestions = generateMissingKeyCompletionSet(keysNeeded, parserContext.m_tmpListKeys);
532 }
533};
534
535struct suggestKeysEnd_class {
536 template <typename T, typename Iterator, typename Context>
537 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
538 {
539 auto& parserContext = x3::get<parser_context_tag>(context);
540 const auto& schema = parserContext.m_schema;
541
542 parserContext.m_completionIterator = begin;
543 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
544 if (generateMissingKeyCompletionSet(keysNeeded, parserContext.m_tmpListKeys).empty()) {
545 parserContext.m_suggestions = {"]/"};
546 } else {
547 parserContext.m_suggestions = {"]"};
548 }
549 }
550};
Václav Kubernát57272422019-02-08 12:48:24 +0100551
552struct commandNamesVisitor {
553 template <typename T>
554 auto operator()(boost::type<T>)
555 {
556 return T::name;
557 }
558};
559
560struct createCommandSuggestions_class {
561 template <typename T, typename Iterator, typename Context>
562 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
563 {
564 auto& parserContext = x3::get<parser_context_tag>(context);
565 parserContext.m_completionIterator = begin;
566
567 parserContext.m_suggestions.clear();
568 boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([&parserContext](auto cmd) {
569 parserContext.m_suggestions.emplace(commandNamesVisitor()(cmd));
570 });
571 }
572};
Václav Kubernátac035d62019-02-18 10:59:08 +0100573
574struct completing_class {
575 template <typename T, typename Iterator, typename Context>
576 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
577 {
578 auto& parserContext = x3::get<parser_context_tag>(context);
579
580 if (!parserContext.m_completing)
581 _pass(context) = false;
582 }
583};
Václav Kubernát989b5de2019-02-20 16:28:35 +0100584
585struct createEnumSuggestions_class {
586 template <typename T, typename Iterator, typename Context>
587 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
588 {
589 auto& parserContext = x3::get<parser_context_tag>(context);
590 parserContext.m_completionIterator = begin;
591 const Schema& schema = parserContext.m_schema;
592
593 boost::optional<std::string> module;
594 if (parserContext.m_curPath.m_nodes.back().m_prefix)
595 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
596
597 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
598 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
599
600 parserContext.m_suggestions = schema.enumValues(location, {module, leaf.m_name});
601 }
602};