blob: b19ece0af0d3e3f7d234ba7e633a0565e0c03885 [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át0a2a2e82018-05-11 13:59:12 +020014
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020015struct keyValue_class {
16 template <typename T, typename Iterator, typename Context>
17 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
18 {
19 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020020 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020021
22 if (parserContext.m_tmpListKeys.find(ast.first) != parserContext.m_tmpListKeys.end()) {
23 _pass(context) = false;
24 parserContext.m_errorMsg = "Key \"" + ast.first + "\" was entered more than once.";
Václav Kubernát744f57f2018-06-29 22:46:26 +020025 } else if (!schema.listHasKey(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName}, ast.first)) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020026 _pass(context) = false;
27 parserContext.m_errorMsg = parserContext.m_tmpListName + " is not indexed by \"" + ast.first + "\".";
Václav Kubernát41378452018-06-06 16:29:40 +020028 } else {
29 parserContext.m_tmpListKeys.insert(ast.first);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020030 }
31 }
Václav Kubernát41378452018-06-06 16:29:40 +020032
33 template <typename Iterator, typename Exception, typename Context>
34 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
35 {
36 auto& parserContext = x3::get<parser_context_tag>(context);
37 parserContext.m_errorMsg = "Error parsing key values here:";
38 return x3::error_handler_result::rethrow;
39 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020040};
Václav Kubernát41378452018-06-06 16:29:40 +020041
Václav Kubernát744f57f2018-06-29 22:46:26 +020042struct node_identifier_class {
43 template <typename T, typename Iterator, typename Context>
44 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
45 {
46 auto& parserContext = x3::get<parser_context_tag>(context);
47
48 if (!parserContext.m_topLevelModulePresent) {
49 if (parserContext.m_errorMsg.empty())
50 parserContext.m_errorMsg = "You have to specify a top level module.";
51 _pass(context) = false;
52 }
53 }
54};
55
Václav Kubernát89728d82018-09-13 16:28:28 +020056struct key_identifier_class;
57
Václav Kubernát744f57f2018-06-29 22:46:26 +020058struct module_identifier_class;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020059
60struct listPrefix_class {
61 template <typename T, typename Iterator, typename Context>
62 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
63 {
64 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020065 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020066
Václav Kubernát744f57f2018-06-29 22:46:26 +020067 if (schema.isList(parserContext.m_curPath, {parserContext.m_curModule, ast})) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020068 parserContext.m_tmpListName = ast;
69 } else {
70 _pass(context) = false;
71 }
72 }
73};
74
75struct listSuffix_class {
76 template <typename T, typename Iterator, typename Context>
77 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
78 {
79 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020080 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020081
Václav Kubernát744f57f2018-06-29 22:46:26 +020082 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020083 std::set<std::string> keysSupplied;
84 for (const auto& it : ast)
85 keysSupplied.insert(it.first);
86
87 if (keysNeeded != keysSupplied) {
88 parserContext.m_errorMsg = "Not enough keys for " + parserContext.m_tmpListName + ". " +
89 "These keys were not supplied:";
90 std::set<std::string> missingKeys;
91 std::set_difference(keysNeeded.begin(), keysNeeded.end(),
92 keysSupplied.begin(), keysSupplied.end(),
93 std::inserter(missingKeys, missingKeys.end()));
94
95 for (const auto& it : missingKeys)
96 parserContext.m_errorMsg += " " + it;
97 parserContext.m_errorMsg += ".";
98
99 _pass(context) = false;
100 }
101 }
Václav Kubernát41378452018-06-06 16:29:40 +0200102
103 template <typename Iterator, typename Exception, typename Context>
104 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
105 {
106 auto& parserContext = x3::get<parser_context_tag>(context);
107 if (parserContext.m_errorMsg.empty())
108 parserContext.m_errorMsg = "Expecting ']' here:";
109 return x3::error_handler_result::rethrow;
Václav Kubernát41378452018-06-06 16:29:40 +0200110 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200111};
112struct listElement_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200113 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200114 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200115 {
116 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200117 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200118 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200119 } else {
120 return x3::error_handler_result::rethrow;
121 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200122 }
123};
124
Václav Kubernát60d6f292018-05-25 09:45:32 +0200125struct nodeup_class {
126 template <typename T, typename Iterator, typename Context>
127 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
128 {
129 auto& parserContext = x3::get<parser_context_tag>(context);
130
Václav Kubernát744f57f2018-06-29 22:46:26 +0200131 if (parserContext.m_curPath.m_nodes.empty())
Václav Kubernát60d6f292018-05-25 09:45:32 +0200132 _pass(context) = false;
Václav Kubernát60d6f292018-05-25 09:45:32 +0200133 }
134};
135
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200136struct container_class {
137 template <typename T, typename Iterator, typename Context>
138 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
139 {
140 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +0200141 const auto& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200142
Václav Kubernát744f57f2018-06-29 22:46:26 +0200143 if (!schema.isContainer(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200144 _pass(context) = false;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200145 }
146};
147
Václav Kubernát07204242018-06-04 18:12:09 +0200148struct leaf_class {
149 template <typename T, typename Iterator, typename Context>
150 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
151 {
152 auto& parserContext = x3::get<parser_context_tag>(context);
153 const auto& schema = parserContext.m_schema;
154
Václav Kubernát744f57f2018-06-29 22:46:26 +0200155 if (!schema.isLeaf(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
156 _pass(context) = false;
157 }
158};
159
160
161struct module_class {
162 template <typename T, typename Iterator, typename Context>
163 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
164 {
165 auto& parserContext = x3::get<parser_context_tag>(context);
166 const auto& schema = parserContext.m_schema;
167
168 if (schema.isModule(parserContext.m_curPath, ast.m_name)) {
169 parserContext.m_curModule = ast.m_name;
170 parserContext.m_topLevelModulePresent = true;
Václav Kubernát07204242018-06-04 18:12:09 +0200171 } else {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200172 parserContext.m_errorMsg = "Invalid module name.";
Václav Kubernát07204242018-06-04 18:12:09 +0200173 _pass(context) = false;
174 }
175 }
176};
177
Václav Kubernát744f57f2018-06-29 22:46:26 +0200178struct node_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200179 template <typename T, typename Iterator, typename Context>
Václav Kubernát744f57f2018-06-29 22:46:26 +0200180 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200181 {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200182 auto& parserContext = x3::get<parser_context_tag>(context);
183 if (ast.m_suffix.type() == typeid(nodeup_)) {
184 parserContext.m_curPath.m_nodes.pop_back();
185 if (parserContext.m_curPath.m_nodes.empty())
186 parserContext.m_topLevelModulePresent = false;
187 } else {
188 parserContext.m_curPath.m_nodes.push_back(ast);
189 parserContext.m_curModule = boost::none;
190 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200191 }
Václav Kubernát744f57f2018-06-29 22:46:26 +0200192};
Václav Kubernát07204242018-06-04 18:12:09 +0200193
Václav Kubernát37171a12018-08-31 17:01:48 +0200194struct absoluteStart_class {
195 template <typename T, typename Iterator, typename Context>
196 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
197 {
198 auto& parserContext = x3::get<parser_context_tag>(context);
199 parserContext.m_curPath.m_nodes.clear();
200 }
201};
202
Václav Kubernát744f57f2018-06-29 22:46:26 +0200203struct path_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200204 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200205 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát07204242018-06-04 18:12:09 +0200206 {
207 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200208 if (parserContext.m_errorMsg.empty()) {
209 parserContext.m_errorMsg = "Expected path.";
Václav Kubernát07204242018-06-04 18:12:09 +0200210 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200211 } else {
212 return x3::error_handler_result::rethrow;
213 }
Václav Kubernát07204242018-06-04 18:12:09 +0200214 }
215};
216
Václav Kubernát6d791432018-10-25 16:00:35 +0200217struct discard_class;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200218
Václav Kubernát11afac72018-07-18 14:59:53 +0200219struct ls_class;
220
Václav Kubernát744f57f2018-06-29 22:46:26 +0200221struct cd_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200222 template <typename Iterator, typename Exception, typename Context>
223 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
224 {
225 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200226 if (parserContext.m_errorMsg.empty())
227 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
228 return x3::error_handler_result::rethrow;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200229 }
230};
Václav Kubernátb61336d2018-05-28 17:35:03 +0200231
232struct presenceContainerPathHandler {
233 template <typename T, typename Iterator, typename Context>
234 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
235 {
236 auto& parserContext = x3::get<parser_context_tag>(context);
237 const auto& schema = parserContext.m_schema;
238 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200239 boost::optional<std::string> module;
240 if (ast.m_path.m_nodes.back().m_prefix)
241 module = ast.m_path.m_nodes.back().m_prefix.value().m_name;
242 container_ cont = boost::get<container_>(ast.m_path.m_nodes.back().m_suffix);
Václav Kubernátebca2552018-06-08 19:06:02 +0200243 path_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200244
Václav Kubernát744f57f2018-06-29 22:46:26 +0200245 if (!schema.isPresenceContainer(location, {module, cont.m_name})) {
Václav Kubernát41378452018-06-06 16:29:40 +0200246 parserContext.m_errorMsg = "This container is not a presence container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200247 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200248 }
249 } catch (boost::bad_get&) {
Václav Kubernát41378452018-06-06 16:29:40 +0200250 parserContext.m_errorMsg = "This is not a container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200251 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200252 }
253 }
254
255 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200256 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernátb61336d2018-05-28 17:35:03 +0200257 {
258 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200259 if (parserContext.m_errorMsg.empty())
260 parserContext.m_errorMsg = "Couldn't parse create/delete command.";
261 return x3::error_handler_result::rethrow;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200262 }
263};
264
265struct create_class : public presenceContainerPathHandler {
266};
267
268struct delete_class : public presenceContainerPathHandler {
269};
270
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200271struct leaf_path_class {
272 template <typename T, typename Iterator, typename Context>
273 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
274 {
275 auto& parserContext = x3::get<parser_context_tag>(context);
276 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200277 auto leaf = boost::get<leaf_>(ast.m_nodes.back().m_suffix);
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200278 } catch (boost::bad_get&) {
279 parserContext.m_errorMsg = "This is not a path to leaf.";
280 _pass(context) = false;
281 }
282 }
283};
284
Václav Kubernátebca2552018-06-08 19:06:02 +0200285struct leaf_data_class {
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200286 template <typename Iterator, typename Exception, typename Context>
287 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
288 {
289 auto& parserContext = x3::get<parser_context_tag>(context);
290 auto& schema = parserContext.m_schema;
291 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200292 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200293 path_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernát744f57f2018-06-29 22:46:26 +0200294 parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, {parserContext.m_curModule, leaf.m_name})) + " here:";
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200295 return x3::error_handler_result::fail;
296 }
297 return x3::error_handler_result::rethrow;
298 }
Václav Kubernátebca2552018-06-08 19:06:02 +0200299};
300
301struct leaf_data_base_class {
302 yang::LeafDataTypes m_type;
303
304 leaf_data_base_class(yang::LeafDataTypes type)
305 : m_type(type)
306 {
307 }
308
309 template <typename T, typename Iterator, typename Context>
310 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
311 {
312 auto& parserContext = x3::get<parser_context_tag>(context);
313 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200314 boost::optional<std::string> module;
315 if (parserContext.m_curPath.m_nodes.back().m_prefix)
316 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200317
Václav Kubernát744f57f2018-06-29 22:46:26 +0200318 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernátebca2552018-06-08 19:06:02 +0200319 path_ location = pathWithoutLastNode(parserContext.m_curPath);
320
Václav Kubernát744f57f2018-06-29 22:46:26 +0200321 if (schema.leafType(location, {module, leaf.m_name}) != m_type) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200322 _pass(context) = false;
323 }
324 }
325};
326
327struct leaf_data_enum_class : leaf_data_base_class {
328 leaf_data_enum_class()
329 : leaf_data_base_class(yang::LeafDataTypes::Enum)
330 {
331 }
332
333 template <typename T, typename Iterator, typename Context>
334 void on_success(Iterator const& start, Iterator const& end, T& ast, Context const& context)
335 {
336 leaf_data_base_class::on_success(start, end, ast, context);
337 auto& parserContext = x3::get<parser_context_tag>(context);
338 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200339 boost::optional<std::string> module;
340 if (parserContext.m_curPath.m_nodes.back().m_prefix)
341 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200342
Václav Kubernát744f57f2018-06-29 22:46:26 +0200343 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernátebca2552018-06-08 19:06:02 +0200344 path_ location = pathWithoutLastNode(parserContext.m_curPath);
345
Václav Kubernát744f57f2018-06-29 22:46:26 +0200346 if (!schema.leafEnumHasValue(location, {module, leaf.m_name}, ast.m_value)) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200347 _pass(context) = false;
348 }
349 }
350};
351
352struct leaf_data_decimal_class : leaf_data_base_class {
353 leaf_data_decimal_class()
354 : leaf_data_base_class(yang::LeafDataTypes::Decimal)
355 {
356 }
357};
358
359struct leaf_data_bool_class : leaf_data_base_class {
360 leaf_data_bool_class()
361 : leaf_data_base_class(yang::LeafDataTypes::Bool)
362 {
363 }
364};
365
366struct leaf_data_int_class : leaf_data_base_class {
367 leaf_data_int_class()
368 : leaf_data_base_class(yang::LeafDataTypes::Int)
369 {
370 }
371};
372
373struct leaf_data_uint_class : leaf_data_base_class {
374 leaf_data_uint_class()
375 : leaf_data_base_class(yang::LeafDataTypes::Uint)
376 {
377 }
378};
379
380struct leaf_data_string_class : leaf_data_base_class {
381 leaf_data_string_class()
382 : leaf_data_base_class(yang::LeafDataTypes::String)
383 {
384 }
385};
386
Václav Kubernát07204242018-06-04 18:12:09 +0200387struct set_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200388 template <typename Iterator, typename Exception, typename Context>
389 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
390 {
391 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200392 if (parserContext.m_errorMsg.empty())
393 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
394 return x3::error_handler_result::rethrow;
Václav Kubernát07204242018-06-04 18:12:09 +0200395 }
396};
397
Václav Kubernát812ee282018-08-30 17:10:03 +0200398struct commit_class;
399
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200400struct get_class;
401
Václav Kubernátb61336d2018-05-28 17:35:03 +0200402struct command_class {
403 template <typename Iterator, typename Exception, typename Context>
404 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
405 {
406 auto& parserContext = x3::get<parser_context_tag>(context);
407 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
Václav Kubernát41378452018-06-06 16:29:40 +0200408 if (parserContext.m_errorMsg.empty()) {
409 parserContext.m_errorMsg = "Unknown command.";
410 }
411 error_handler(x.where(), parserContext.m_errorMsg);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200412 return x3::error_handler_result::fail;
413 }
414};