blob: c937eee57a71907a08f07f4e599f444d1fadbd0c [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
Václav Kubernát6797df02019-03-18 20:21:50 +0100291struct presenceContainerPath_class {
Václav Kubernátb61336d2018-05-28 17:35:03 +0200292 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;
Václav Kubernát6797df02019-03-18 20:21:50 +0100299 if (ast.m_nodes.back().m_prefix)
300 module = ast.m_nodes.back().m_prefix.value().m_name;
301 container_ cont = boost::get<container_>(ast.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 }
Václav Kubernát6797df02019-03-18 20:21:50 +0100313};
Václav Kubernátb61336d2018-05-28 17:35:03 +0200314
Václav Kubernát6797df02019-03-18 20:21:50 +0100315struct create_class {
Václav Kubernátb61336d2018-05-28 17:35:03 +0200316 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200317 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernátb61336d2018-05-28 17:35:03 +0200318 {
319 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200320 if (parserContext.m_errorMsg.empty())
321 parserContext.m_errorMsg = "Couldn't parse create/delete command.";
322 return x3::error_handler_result::rethrow;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200323 }
324};
325
Václav Kubernát6797df02019-03-18 20:21:50 +0100326struct delete_class {
327 template <typename Iterator, typename Exception, typename Context>
328 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
329 {
330 auto& parserContext = x3::get<parser_context_tag>(context);
331 if (parserContext.m_errorMsg.empty())
332 parserContext.m_errorMsg = "Couldn't parse create/delete command.";
333 return x3::error_handler_result::rethrow;
334 }
Václav Kubernátb61336d2018-05-28 17:35:03 +0200335};
336
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200337struct leaf_path_class {
338 template <typename T, typename Iterator, typename Context>
339 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
340 {
341 auto& parserContext = x3::get<parser_context_tag>(context);
342 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200343 auto leaf = boost::get<leaf_>(ast.m_nodes.back().m_suffix);
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200344 } catch (boost::bad_get&) {
345 parserContext.m_errorMsg = "This is not a path to leaf.";
346 _pass(context) = false;
347 }
348 }
349};
350
Václav Kubernátebca2552018-06-08 19:06:02 +0200351struct leaf_data_class {
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200352 template <typename Iterator, typename Exception, typename Context>
353 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
354 {
355 auto& parserContext = x3::get<parser_context_tag>(context);
356 auto& schema = parserContext.m_schema;
357 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200358 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200359 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
360 if (location.m_nodes.empty()) {
Václav Kubernát5c75b252018-10-10 18:33:47 +0200361 parserContext.m_curModule = parserContext.m_curPath.m_nodes.back().m_prefix->m_name;
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200362 }
Václav Kubernát744f57f2018-06-29 22:46:26 +0200363 parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, {parserContext.m_curModule, leaf.m_name})) + " here:";
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200364 return x3::error_handler_result::fail;
365 }
366 return x3::error_handler_result::rethrow;
367 }
Václav Kubernátebca2552018-06-08 19:06:02 +0200368};
369
370struct leaf_data_base_class {
371 yang::LeafDataTypes m_type;
372
373 leaf_data_base_class(yang::LeafDataTypes type)
374 : m_type(type)
375 {
376 }
377
378 template <typename T, typename Iterator, typename Context>
379 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
380 {
381 auto& parserContext = x3::get<parser_context_tag>(context);
382 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200383 boost::optional<std::string> module;
384 if (parserContext.m_curPath.m_nodes.back().m_prefix)
385 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200386
Václav Kubernát744f57f2018-06-29 22:46:26 +0200387 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200388 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátebca2552018-06-08 19:06:02 +0200389
Václav Kubernát744f57f2018-06-29 22:46:26 +0200390 if (schema.leafType(location, {module, leaf.m_name}) != m_type) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200391 _pass(context) = false;
392 }
393 }
394};
395
396struct leaf_data_enum_class : leaf_data_base_class {
397 leaf_data_enum_class()
398 : leaf_data_base_class(yang::LeafDataTypes::Enum)
399 {
400 }
401
402 template <typename T, typename Iterator, typename Context>
403 void on_success(Iterator const& start, Iterator const& end, T& ast, Context const& context)
404 {
405 leaf_data_base_class::on_success(start, end, ast, context);
406 auto& parserContext = x3::get<parser_context_tag>(context);
407 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200408 boost::optional<std::string> module;
409 if (parserContext.m_curPath.m_nodes.back().m_prefix)
410 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200411
Václav Kubernát744f57f2018-06-29 22:46:26 +0200412 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200413 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátebca2552018-06-08 19:06:02 +0200414
Václav Kubernát744f57f2018-06-29 22:46:26 +0200415 if (!schema.leafEnumHasValue(location, {module, leaf.m_name}, ast.m_value)) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200416 _pass(context) = false;
417 }
418 }
419};
420
421struct leaf_data_decimal_class : leaf_data_base_class {
422 leaf_data_decimal_class()
423 : leaf_data_base_class(yang::LeafDataTypes::Decimal)
424 {
425 }
426};
427
428struct leaf_data_bool_class : leaf_data_base_class {
429 leaf_data_bool_class()
430 : leaf_data_base_class(yang::LeafDataTypes::Bool)
431 {
432 }
433};
434
435struct leaf_data_int_class : leaf_data_base_class {
436 leaf_data_int_class()
437 : leaf_data_base_class(yang::LeafDataTypes::Int)
438 {
439 }
440};
441
442struct leaf_data_uint_class : leaf_data_base_class {
443 leaf_data_uint_class()
444 : leaf_data_base_class(yang::LeafDataTypes::Uint)
445 {
446 }
447};
448
449struct leaf_data_string_class : leaf_data_base_class {
450 leaf_data_string_class()
451 : leaf_data_base_class(yang::LeafDataTypes::String)
452 {
453 }
454};
455
Václav Kubernátab538992019-03-06 15:30:50 +0100456struct leaf_data_binary_data_class;
457
458struct leaf_data_binary_class : leaf_data_base_class {
459 leaf_data_binary_class()
460 : leaf_data_base_class(yang::LeafDataTypes::Binary)
461 {
462 }
463};
464
Václav Kubernát07204242018-06-04 18:12:09 +0200465struct set_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200466 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);
Václav Kubernát41378452018-06-06 16:29:40 +0200470 if (parserContext.m_errorMsg.empty())
471 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
472 return x3::error_handler_result::rethrow;
Václav Kubernát07204242018-06-04 18:12:09 +0200473 }
474};
475
Václav Kubernát812ee282018-08-30 17:10:03 +0200476struct commit_class;
477
Václav Kubernát054cc992019-02-21 14:23:52 +0100478struct help_class;
479
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200480struct get_class;
481
Václav Kubernátb61336d2018-05-28 17:35:03 +0200482struct command_class {
483 template <typename Iterator, typename Exception, typename Context>
484 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
485 {
486 auto& parserContext = x3::get<parser_context_tag>(context);
487 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
Václav Kubernát41378452018-06-06 16:29:40 +0200488 if (parserContext.m_errorMsg.empty()) {
489 parserContext.m_errorMsg = "Unknown command.";
490 }
491 error_handler(x.where(), parserContext.m_errorMsg);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200492 return x3::error_handler_result::fail;
493 }
494};
Václav Kubernát5c75b252018-10-10 18:33:47 +0200495
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100496struct initializePath_class {
Václav Kubernát5c75b252018-10-10 18:33:47 +0200497 template <typename T, typename Iterator, typename Context>
498 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
499 {
500 auto& parserContext = x3::get<parser_context_tag>(context);
501 parserContext.m_curPath = parserContext.m_curPathOrig;
502 parserContext.m_tmpListKeys.clear();
503 parserContext.m_tmpListName.clear();
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100504 parserContext.m_suggestions.clear();
Václav Kubernát5c75b252018-10-10 18:33:47 +0200505 if (!parserContext.m_curPath.m_nodes.empty() && parserContext.m_curPath.m_nodes.at(0).m_prefix)
506 parserContext.m_topLevelModulePresent = true;
507 else
508 parserContext.m_topLevelModulePresent = false;
509 }
510};
Václav Kubernátd6fd2492018-11-19 15:11:16 +0100511
512struct trailingSlash_class;
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100513
514struct createPathSuggestions_class {
515 template <typename T, typename Iterator, typename Context>
516 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
517 {
518 auto& parserContext = x3::get<parser_context_tag>(context);
519 const auto& schema = parserContext.m_schema;
520
521 parserContext.m_completionIterator = begin;
522 parserContext.m_suggestions = schema.childNodes(parserContext.m_curPath, Recursion::NonRecursive);
523 }
524};
Václav Kubernát329c6c32019-02-06 16:41:53 +0100525
526std::set<std::string> generateMissingKeyCompletionSet(std::set<std::string> keysNeeded, std::set<std::string> currentSet);
527
528struct createKeySuggestions_class {
529 template <typename T, typename Iterator, typename Context>
530 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
531 {
532 auto& parserContext = x3::get<parser_context_tag>(context);
533 const auto& schema = parserContext.m_schema;
534
535 parserContext.m_completionIterator = begin;
536
537 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
538 parserContext.m_suggestions = generateMissingKeyCompletionSet(keysNeeded, parserContext.m_tmpListKeys);
539 }
540};
541
542struct suggestKeysEnd_class {
543 template <typename T, typename Iterator, typename Context>
544 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
545 {
546 auto& parserContext = x3::get<parser_context_tag>(context);
547 const auto& schema = parserContext.m_schema;
548
549 parserContext.m_completionIterator = begin;
550 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
551 if (generateMissingKeyCompletionSet(keysNeeded, parserContext.m_tmpListKeys).empty()) {
552 parserContext.m_suggestions = {"]/"};
553 } else {
554 parserContext.m_suggestions = {"]"};
555 }
556 }
557};
Václav Kubernát57272422019-02-08 12:48:24 +0100558
559struct commandNamesVisitor {
560 template <typename T>
561 auto operator()(boost::type<T>)
562 {
563 return T::name;
564 }
565};
566
567struct createCommandSuggestions_class {
568 template <typename T, typename Iterator, typename Context>
569 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
570 {
571 auto& parserContext = x3::get<parser_context_tag>(context);
572 parserContext.m_completionIterator = begin;
573
574 parserContext.m_suggestions.clear();
575 boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([&parserContext](auto cmd) {
576 parserContext.m_suggestions.emplace(commandNamesVisitor()(cmd));
577 });
578 }
579};
Václav Kubernátac035d62019-02-18 10:59:08 +0100580
581struct completing_class {
582 template <typename T, typename Iterator, typename Context>
583 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
584 {
585 auto& parserContext = x3::get<parser_context_tag>(context);
586
587 if (!parserContext.m_completing)
588 _pass(context) = false;
589 }
590};
Václav Kubernát989b5de2019-02-20 16:28:35 +0100591
592struct createEnumSuggestions_class {
593 template <typename T, typename Iterator, typename Context>
594 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
595 {
596 auto& parserContext = x3::get<parser_context_tag>(context);
597 parserContext.m_completionIterator = begin;
598 const Schema& schema = parserContext.m_schema;
599
600 boost::optional<std::string> module;
601 if (parserContext.m_curPath.m_nodes.back().m_prefix)
602 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
603
604 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
605 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
606
607 parserContext.m_suggestions = schema.enumValues(location, {module, leaf.m_name});
608 }
609};