blob: 5a55f36db0cbddcf7f4afe26570c13c3de9b4d1f [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át195eeea2018-05-18 13:52:36 +020011#include "parser_context.hpp"
Václav Kubernát48fc3832018-05-28 14:21:22 +020012#include "schema.hpp"
Václav Kubernátebca2552018-06-08 19:06:02 +020013#include "utils.hpp"
Václav Kubernát329c6c32019-02-06 16:41:53 +010014namespace x3 = boost::spirit::x3;
15
16struct parser_context_tag;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020017
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020018struct keyValue_class {
19 template <typename T, typename Iterator, typename Context>
20 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
21 {
22 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020023 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020024
25 if (parserContext.m_tmpListKeys.find(ast.first) != parserContext.m_tmpListKeys.end()) {
26 _pass(context) = false;
27 parserContext.m_errorMsg = "Key \"" + ast.first + "\" was entered more than once.";
Václav Kubernát744f57f2018-06-29 22:46:26 +020028 } else if (!schema.listHasKey(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName}, ast.first)) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020029 _pass(context) = false;
30 parserContext.m_errorMsg = parserContext.m_tmpListName + " is not indexed by \"" + ast.first + "\".";
Václav Kubernát41378452018-06-06 16:29:40 +020031 } else {
32 parserContext.m_tmpListKeys.insert(ast.first);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020033 }
34 }
Václav Kubernát41378452018-06-06 16:29:40 +020035
36 template <typename Iterator, typename Exception, typename Context>
37 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
38 {
39 auto& parserContext = x3::get<parser_context_tag>(context);
40 parserContext.m_errorMsg = "Error parsing key values here:";
41 return x3::error_handler_result::rethrow;
42 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020043};
Václav Kubernát41378452018-06-06 16:29:40 +020044
Václav Kubernát744f57f2018-06-29 22:46:26 +020045struct node_identifier_class {
46 template <typename T, typename Iterator, typename Context>
47 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
48 {
49 auto& parserContext = x3::get<parser_context_tag>(context);
50
51 if (!parserContext.m_topLevelModulePresent) {
52 if (parserContext.m_errorMsg.empty())
53 parserContext.m_errorMsg = "You have to specify a top level module.";
54 _pass(context) = false;
55 }
56 }
57};
58
Václav Kubernát89728d82018-09-13 16:28:28 +020059struct key_identifier_class;
60
Václav Kubernát744f57f2018-06-29 22:46:26 +020061struct module_identifier_class;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020062
63struct listPrefix_class {
64 template <typename T, typename Iterator, typename Context>
65 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
66 {
67 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020068 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020069
Václav Kubernát744f57f2018-06-29 22:46:26 +020070 if (schema.isList(parserContext.m_curPath, {parserContext.m_curModule, ast})) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020071 parserContext.m_tmpListName = ast;
72 } else {
73 _pass(context) = false;
74 }
75 }
76};
77
78struct listSuffix_class {
79 template <typename T, typename Iterator, typename Context>
80 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
81 {
82 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020083 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020084
Václav Kubernát744f57f2018-06-29 22:46:26 +020085 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020086 std::set<std::string> keysSupplied;
87 for (const auto& it : ast)
88 keysSupplied.insert(it.first);
89
90 if (keysNeeded != keysSupplied) {
91 parserContext.m_errorMsg = "Not enough keys for " + parserContext.m_tmpListName + ". " +
92 "These keys were not supplied:";
93 std::set<std::string> missingKeys;
94 std::set_difference(keysNeeded.begin(), keysNeeded.end(),
95 keysSupplied.begin(), keysSupplied.end(),
96 std::inserter(missingKeys, missingKeys.end()));
97
98 for (const auto& it : missingKeys)
99 parserContext.m_errorMsg += " " + it;
100 parserContext.m_errorMsg += ".";
101
102 _pass(context) = false;
103 }
104 }
Václav Kubernát41378452018-06-06 16:29:40 +0200105
106 template <typename Iterator, typename Exception, typename Context>
107 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
108 {
109 auto& parserContext = x3::get<parser_context_tag>(context);
110 if (parserContext.m_errorMsg.empty())
111 parserContext.m_errorMsg = "Expecting ']' here:";
112 return x3::error_handler_result::rethrow;
Václav Kubernát41378452018-06-06 16:29:40 +0200113 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200114};
115struct listElement_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200116 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200117 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200118 {
119 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200120 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200121 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200122 } else {
123 return x3::error_handler_result::rethrow;
124 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200125 }
126};
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200127struct list_class {
128 template <typename T, typename Iterator, typename Context>
129 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
130 {
131 auto& parserContext = x3::get<parser_context_tag>(context);
132 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200133
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200134 if (!schema.isList(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name})) {
135 _pass(context) = false;
136 }
137 }
138};
Václav Kubernát60d6f292018-05-25 09:45:32 +0200139struct nodeup_class {
140 template <typename T, typename Iterator, typename Context>
141 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
142 {
143 auto& parserContext = x3::get<parser_context_tag>(context);
144
Václav Kubernát744f57f2018-06-29 22:46:26 +0200145 if (parserContext.m_curPath.m_nodes.empty())
Václav Kubernát60d6f292018-05-25 09:45:32 +0200146 _pass(context) = false;
Václav Kubernát60d6f292018-05-25 09:45:32 +0200147 }
148};
149
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200150struct container_class {
151 template <typename T, typename Iterator, typename Context>
152 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
153 {
154 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +0200155 const auto& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200156
Václav Kubernát744f57f2018-06-29 22:46:26 +0200157 if (!schema.isContainer(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200158 _pass(context) = false;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200159 }
160};
161
Václav Kubernát07204242018-06-04 18:12:09 +0200162struct leaf_class {
163 template <typename T, typename Iterator, typename Context>
164 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
165 {
166 auto& parserContext = x3::get<parser_context_tag>(context);
167 const auto& schema = parserContext.m_schema;
168
Václav Kubernát744f57f2018-06-29 22:46:26 +0200169 if (!schema.isLeaf(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
170 _pass(context) = false;
171 }
172};
173
Václav Kubernát744f57f2018-06-29 22:46:26 +0200174struct module_class {
175 template <typename T, typename Iterator, typename Context>
176 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
177 {
178 auto& parserContext = x3::get<parser_context_tag>(context);
179 const auto& schema = parserContext.m_schema;
180
181 if (schema.isModule(parserContext.m_curPath, ast.m_name)) {
182 parserContext.m_curModule = ast.m_name;
183 parserContext.m_topLevelModulePresent = true;
Václav Kubernát07204242018-06-04 18:12:09 +0200184 } else {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200185 parserContext.m_errorMsg = "Invalid module name.";
Václav Kubernát07204242018-06-04 18:12:09 +0200186 _pass(context) = false;
187 }
188 }
189};
190
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200191struct schemaNode_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200192 template <typename T, typename Iterator, typename Context>
Václav Kubernát744f57f2018-06-29 22:46:26 +0200193 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200194 {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200195 auto& parserContext = x3::get<parser_context_tag>(context);
196 if (ast.m_suffix.type() == typeid(nodeup_)) {
197 parserContext.m_curPath.m_nodes.pop_back();
198 if (parserContext.m_curPath.m_nodes.empty())
199 parserContext.m_topLevelModulePresent = false;
200 } else {
201 parserContext.m_curPath.m_nodes.push_back(ast);
202 parserContext.m_curModule = boost::none;
203 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200204 }
Václav Kubernát744f57f2018-06-29 22:46:26 +0200205};
Václav Kubernát07204242018-06-04 18:12:09 +0200206
Václav Kubernát39ae9592019-02-05 17:35:16 +0100207struct dataNodeList_class {
208 template <typename T, typename Iterator, typename Context>
209 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
210 {
211 auto& parserContext = x3::get<parser_context_tag>(context);
212 parserContext.m_curPath.m_nodes.push_back(dataNodeToSchemaNode(ast));
213 }
214};
Václav Kubernát5c75b252018-10-10 18:33:47 +0200215
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200216struct dataNode_class {
217 template <typename T, typename Iterator, typename Context>
218 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
219 {
220 auto& parserContext = x3::get<parser_context_tag>(context);
221 if (ast.m_suffix.type() == typeid(nodeup_)) {
222 parserContext.m_curPath.m_nodes.pop_back();
223 if (parserContext.m_curPath.m_nodes.empty())
224 parserContext.m_topLevelModulePresent = false;
225 } else {
226 parserContext.m_curPath.m_nodes.push_back(dataNodeToSchemaNode(ast));
227 parserContext.m_curModule = boost::none;
228 }
229 }
230};
231
Václav Kubernát37171a12018-08-31 17:01:48 +0200232struct absoluteStart_class {
233 template <typename T, typename Iterator, typename Context>
234 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
235 {
236 auto& parserContext = x3::get<parser_context_tag>(context);
237 parserContext.m_curPath.m_nodes.clear();
238 }
239};
240
Václav Kubernát5c75b252018-10-10 18:33:47 +0200241struct dataNodesListEnd_class;
242
243struct dataPathListEnd_class;
244
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200245struct dataPath_class {
246 template <typename Iterator, typename Exception, typename Context>
247 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
248 {
249 auto& parserContext = x3::get<parser_context_tag>(context);
250 if (parserContext.m_errorMsg.empty()) {
251 parserContext.m_errorMsg = "Expected path.";
252 return x3::error_handler_result::fail;
253 } else {
254 return x3::error_handler_result::rethrow;
255 }
256 }
257};
258
259struct schemaPath_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200260 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200261 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát07204242018-06-04 18:12:09 +0200262 {
263 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200264 if (parserContext.m_errorMsg.empty()) {
265 parserContext.m_errorMsg = "Expected path.";
Václav Kubernát07204242018-06-04 18:12:09 +0200266 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200267 } else {
268 return x3::error_handler_result::rethrow;
269 }
Václav Kubernát07204242018-06-04 18:12:09 +0200270 }
271};
272
Václav Kubernát6d791432018-10-25 16:00:35 +0200273struct discard_class;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200274
Václav Kubernát11afac72018-07-18 14:59:53 +0200275struct ls_class;
276
Václav Kubernát744f57f2018-06-29 22:46:26 +0200277struct cd_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200278 template <typename Iterator, typename Exception, typename Context>
279 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
280 {
281 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200282 if (parserContext.m_errorMsg.empty())
283 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
284 return x3::error_handler_result::rethrow;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200285 }
286};
Václav Kubernátb61336d2018-05-28 17:35:03 +0200287
288struct presenceContainerPathHandler {
289 template <typename T, typename Iterator, typename Context>
290 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
291 {
292 auto& parserContext = x3::get<parser_context_tag>(context);
293 const auto& schema = parserContext.m_schema;
294 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200295 boost::optional<std::string> module;
296 if (ast.m_path.m_nodes.back().m_prefix)
297 module = ast.m_path.m_nodes.back().m_prefix.value().m_name;
298 container_ cont = boost::get<container_>(ast.m_path.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200299 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200300
Václav Kubernát744f57f2018-06-29 22:46:26 +0200301 if (!schema.isPresenceContainer(location, {module, cont.m_name})) {
Václav Kubernát41378452018-06-06 16:29:40 +0200302 parserContext.m_errorMsg = "This container is not a presence container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200303 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200304 }
305 } catch (boost::bad_get&) {
Václav Kubernát41378452018-06-06 16:29:40 +0200306 parserContext.m_errorMsg = "This is not a container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200307 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200308 }
309 }
310
311 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200312 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernátb61336d2018-05-28 17:35:03 +0200313 {
314 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200315 if (parserContext.m_errorMsg.empty())
316 parserContext.m_errorMsg = "Couldn't parse create/delete command.";
317 return x3::error_handler_result::rethrow;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200318 }
319};
320
321struct create_class : public presenceContainerPathHandler {
322};
323
324struct delete_class : public presenceContainerPathHandler {
325};
326
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200327struct leaf_path_class {
328 template <typename T, typename Iterator, typename Context>
329 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
330 {
331 auto& parserContext = x3::get<parser_context_tag>(context);
332 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200333 auto leaf = boost::get<leaf_>(ast.m_nodes.back().m_suffix);
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200334 } catch (boost::bad_get&) {
335 parserContext.m_errorMsg = "This is not a path to leaf.";
336 _pass(context) = false;
337 }
338 }
339};
340
Václav Kubernátebca2552018-06-08 19:06:02 +0200341struct leaf_data_class {
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200342 template <typename Iterator, typename Exception, typename Context>
343 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
344 {
345 auto& parserContext = x3::get<parser_context_tag>(context);
346 auto& schema = parserContext.m_schema;
347 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200348 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200349 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
350 if (location.m_nodes.empty()) {
Václav Kubernát5c75b252018-10-10 18:33:47 +0200351 parserContext.m_curModule = parserContext.m_curPath.m_nodes.back().m_prefix->m_name;
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200352 }
Václav Kubernát744f57f2018-06-29 22:46:26 +0200353 parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, {parserContext.m_curModule, leaf.m_name})) + " here:";
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200354 return x3::error_handler_result::fail;
355 }
356 return x3::error_handler_result::rethrow;
357 }
Václav Kubernátebca2552018-06-08 19:06:02 +0200358};
359
360struct leaf_data_base_class {
361 yang::LeafDataTypes m_type;
362
363 leaf_data_base_class(yang::LeafDataTypes type)
364 : m_type(type)
365 {
366 }
367
368 template <typename T, typename Iterator, typename Context>
369 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
370 {
371 auto& parserContext = x3::get<parser_context_tag>(context);
372 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200373 boost::optional<std::string> module;
374 if (parserContext.m_curPath.m_nodes.back().m_prefix)
375 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200376
Václav Kubernát744f57f2018-06-29 22:46:26 +0200377 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200378 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátebca2552018-06-08 19:06:02 +0200379
Václav Kubernát744f57f2018-06-29 22:46:26 +0200380 if (schema.leafType(location, {module, leaf.m_name}) != m_type) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200381 _pass(context) = false;
382 }
383 }
384};
385
386struct leaf_data_enum_class : leaf_data_base_class {
387 leaf_data_enum_class()
388 : leaf_data_base_class(yang::LeafDataTypes::Enum)
389 {
390 }
391
392 template <typename T, typename Iterator, typename Context>
393 void on_success(Iterator const& start, Iterator const& end, T& ast, Context const& context)
394 {
395 leaf_data_base_class::on_success(start, end, ast, context);
396 auto& parserContext = x3::get<parser_context_tag>(context);
397 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200398 boost::optional<std::string> module;
399 if (parserContext.m_curPath.m_nodes.back().m_prefix)
400 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200401
Václav Kubernát744f57f2018-06-29 22:46:26 +0200402 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200403 schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátebca2552018-06-08 19:06:02 +0200404
Václav Kubernát744f57f2018-06-29 22:46:26 +0200405 if (!schema.leafEnumHasValue(location, {module, leaf.m_name}, ast.m_value)) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200406 _pass(context) = false;
407 }
408 }
409};
410
411struct leaf_data_decimal_class : leaf_data_base_class {
412 leaf_data_decimal_class()
413 : leaf_data_base_class(yang::LeafDataTypes::Decimal)
414 {
415 }
416};
417
418struct leaf_data_bool_class : leaf_data_base_class {
419 leaf_data_bool_class()
420 : leaf_data_base_class(yang::LeafDataTypes::Bool)
421 {
422 }
423};
424
425struct leaf_data_int_class : leaf_data_base_class {
426 leaf_data_int_class()
427 : leaf_data_base_class(yang::LeafDataTypes::Int)
428 {
429 }
430};
431
432struct leaf_data_uint_class : leaf_data_base_class {
433 leaf_data_uint_class()
434 : leaf_data_base_class(yang::LeafDataTypes::Uint)
435 {
436 }
437};
438
439struct leaf_data_string_class : leaf_data_base_class {
440 leaf_data_string_class()
441 : leaf_data_base_class(yang::LeafDataTypes::String)
442 {
443 }
444};
445
Václav Kubernát07204242018-06-04 18:12:09 +0200446struct set_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200447 template <typename Iterator, typename Exception, typename Context>
448 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
449 {
450 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200451 if (parserContext.m_errorMsg.empty())
452 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
453 return x3::error_handler_result::rethrow;
Václav Kubernát07204242018-06-04 18:12:09 +0200454 }
455};
456
Václav Kubernát812ee282018-08-30 17:10:03 +0200457struct commit_class;
458
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200459struct get_class;
460
Václav Kubernátb61336d2018-05-28 17:35:03 +0200461struct command_class {
462 template <typename Iterator, typename Exception, typename Context>
463 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
464 {
465 auto& parserContext = x3::get<parser_context_tag>(context);
466 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
Václav Kubernát41378452018-06-06 16:29:40 +0200467 if (parserContext.m_errorMsg.empty()) {
468 parserContext.m_errorMsg = "Unknown command.";
469 }
470 error_handler(x.where(), parserContext.m_errorMsg);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200471 return x3::error_handler_result::fail;
472 }
473};
Václav Kubernát5c75b252018-10-10 18:33:47 +0200474
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100475struct initializePath_class {
Václav Kubernát5c75b252018-10-10 18:33:47 +0200476 template <typename T, typename Iterator, typename Context>
477 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
478 {
479 auto& parserContext = x3::get<parser_context_tag>(context);
480 parserContext.m_curPath = parserContext.m_curPathOrig;
481 parserContext.m_tmpListKeys.clear();
482 parserContext.m_tmpListName.clear();
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100483 parserContext.m_suggestions.clear();
Václav Kubernát5c75b252018-10-10 18:33:47 +0200484 if (!parserContext.m_curPath.m_nodes.empty() && parserContext.m_curPath.m_nodes.at(0).m_prefix)
485 parserContext.m_topLevelModulePresent = true;
486 else
487 parserContext.m_topLevelModulePresent = false;
488 }
489};
Václav Kubernátd6fd2492018-11-19 15:11:16 +0100490
491struct trailingSlash_class;
Václav Kubernát4108e0d2018-10-29 13:32:22 +0100492
493struct createPathSuggestions_class {
494 template <typename T, typename Iterator, typename Context>
495 void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
496 {
497 auto& parserContext = x3::get<parser_context_tag>(context);
498 const auto& schema = parserContext.m_schema;
499
500 parserContext.m_completionIterator = begin;
501 parserContext.m_suggestions = schema.childNodes(parserContext.m_curPath, Recursion::NonRecursive);
502 }
503};
Václav Kubernát329c6c32019-02-06 16:41:53 +0100504
505std::set<std::string> generateMissingKeyCompletionSet(std::set<std::string> keysNeeded, std::set<std::string> currentSet);
506
507struct createKeySuggestions_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
516 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
517 parserContext.m_suggestions = generateMissingKeyCompletionSet(keysNeeded, parserContext.m_tmpListKeys);
518 }
519};
520
521struct suggestKeysEnd_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 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
530 if (generateMissingKeyCompletionSet(keysNeeded, parserContext.m_tmpListKeys).empty()) {
531 parserContext.m_suggestions = {"]/"};
532 } else {
533 parserContext.m_suggestions = {"]"};
534 }
535 }
536};