blob: aa37574d6ceec3f39d968afc26efdee1e9ed4ba3 [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
56struct module_identifier_class;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020057
58struct listPrefix_class {
59 template <typename T, typename Iterator, typename Context>
60 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
61 {
62 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020063 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020064
Václav Kubernát744f57f2018-06-29 22:46:26 +020065 if (schema.isList(parserContext.m_curPath, {parserContext.m_curModule, ast})) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020066 parserContext.m_tmpListName = ast;
67 } else {
68 _pass(context) = false;
69 }
70 }
71};
72
73struct listSuffix_class {
74 template <typename T, typename Iterator, typename Context>
75 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
76 {
77 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020078 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020079
Václav Kubernát744f57f2018-06-29 22:46:26 +020080 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020081 std::set<std::string> keysSupplied;
82 for (const auto& it : ast)
83 keysSupplied.insert(it.first);
84
85 if (keysNeeded != keysSupplied) {
86 parserContext.m_errorMsg = "Not enough keys for " + parserContext.m_tmpListName + ". " +
87 "These keys were not supplied:";
88 std::set<std::string> missingKeys;
89 std::set_difference(keysNeeded.begin(), keysNeeded.end(),
90 keysSupplied.begin(), keysSupplied.end(),
91 std::inserter(missingKeys, missingKeys.end()));
92
93 for (const auto& it : missingKeys)
94 parserContext.m_errorMsg += " " + it;
95 parserContext.m_errorMsg += ".";
96
97 _pass(context) = false;
98 }
99 }
Václav Kubernát41378452018-06-06 16:29:40 +0200100
101 template <typename Iterator, typename Exception, typename Context>
102 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
103 {
104 auto& parserContext = x3::get<parser_context_tag>(context);
105 if (parserContext.m_errorMsg.empty())
106 parserContext.m_errorMsg = "Expecting ']' here:";
107 return x3::error_handler_result::rethrow;
Václav Kubernát41378452018-06-06 16:29:40 +0200108 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200109};
110struct listElement_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200111 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200112 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200113 {
114 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200115 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200116 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200117 } else {
118 return x3::error_handler_result::rethrow;
119 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200120 }
121};
122
Václav Kubernát60d6f292018-05-25 09:45:32 +0200123struct nodeup_class {
124 template <typename T, typename Iterator, typename Context>
125 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
126 {
127 auto& parserContext = x3::get<parser_context_tag>(context);
128
Václav Kubernát744f57f2018-06-29 22:46:26 +0200129 if (parserContext.m_curPath.m_nodes.empty())
Václav Kubernát60d6f292018-05-25 09:45:32 +0200130 _pass(context) = false;
Václav Kubernát60d6f292018-05-25 09:45:32 +0200131 }
132};
133
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200134struct container_class {
135 template <typename T, typename Iterator, typename Context>
136 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
137 {
138 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +0200139 const auto& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200140
Václav Kubernát744f57f2018-06-29 22:46:26 +0200141 if (!schema.isContainer(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200142 _pass(context) = false;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200143 }
144};
145
Václav Kubernát07204242018-06-04 18:12:09 +0200146struct leaf_class {
147 template <typename T, typename Iterator, typename Context>
148 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
149 {
150 auto& parserContext = x3::get<parser_context_tag>(context);
151 const auto& schema = parserContext.m_schema;
152
Václav Kubernát744f57f2018-06-29 22:46:26 +0200153 if (!schema.isLeaf(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
154 _pass(context) = false;
155 }
156};
157
158
159struct module_class {
160 template <typename T, typename Iterator, typename Context>
161 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
162 {
163 auto& parserContext = x3::get<parser_context_tag>(context);
164 const auto& schema = parserContext.m_schema;
165
166 if (schema.isModule(parserContext.m_curPath, ast.m_name)) {
167 parserContext.m_curModule = ast.m_name;
168 parserContext.m_topLevelModulePresent = true;
Václav Kubernát07204242018-06-04 18:12:09 +0200169 } else {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200170 parserContext.m_errorMsg = "Invalid module name.";
Václav Kubernát07204242018-06-04 18:12:09 +0200171 _pass(context) = false;
172 }
173 }
174};
175
Václav Kubernát744f57f2018-06-29 22:46:26 +0200176struct node_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200177 template <typename T, typename Iterator, typename Context>
Václav Kubernát744f57f2018-06-29 22:46:26 +0200178 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200179 {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200180 auto& parserContext = x3::get<parser_context_tag>(context);
181 if (ast.m_suffix.type() == typeid(nodeup_)) {
182 parserContext.m_curPath.m_nodes.pop_back();
183 if (parserContext.m_curPath.m_nodes.empty())
184 parserContext.m_topLevelModulePresent = false;
185 } else {
186 parserContext.m_curPath.m_nodes.push_back(ast);
187 parserContext.m_curModule = boost::none;
188 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200189 }
Václav Kubernát744f57f2018-06-29 22:46:26 +0200190};
Václav Kubernát07204242018-06-04 18:12:09 +0200191
Václav Kubernát37171a12018-08-31 17:01:48 +0200192struct absoluteStart_class {
193 template <typename T, typename Iterator, typename Context>
194 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
195 {
196 auto& parserContext = x3::get<parser_context_tag>(context);
197 parserContext.m_curPath.m_nodes.clear();
198 }
199};
200
Václav Kubernát744f57f2018-06-29 22:46:26 +0200201struct path_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200202 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200203 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát07204242018-06-04 18:12:09 +0200204 {
205 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200206 if (parserContext.m_errorMsg.empty()) {
207 parserContext.m_errorMsg = "Expected path.";
Václav Kubernát07204242018-06-04 18:12:09 +0200208 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200209 } else {
210 return x3::error_handler_result::rethrow;
211 }
Václav Kubernát07204242018-06-04 18:12:09 +0200212 }
213};
214
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200215
Václav Kubernát11afac72018-07-18 14:59:53 +0200216struct ls_class;
217
Václav Kubernát744f57f2018-06-29 22:46:26 +0200218struct cd_class {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200219 template <typename Iterator, typename Exception, typename Context>
220 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
221 {
222 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200223 if (parserContext.m_errorMsg.empty())
224 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
225 return x3::error_handler_result::rethrow;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200226 }
227};
Václav Kubernátb61336d2018-05-28 17:35:03 +0200228
229struct presenceContainerPathHandler {
230 template <typename T, typename Iterator, typename Context>
231 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
232 {
233 auto& parserContext = x3::get<parser_context_tag>(context);
234 const auto& schema = parserContext.m_schema;
235 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200236 boost::optional<std::string> module;
237 if (ast.m_path.m_nodes.back().m_prefix)
238 module = ast.m_path.m_nodes.back().m_prefix.value().m_name;
239 container_ cont = boost::get<container_>(ast.m_path.m_nodes.back().m_suffix);
Václav Kubernátebca2552018-06-08 19:06:02 +0200240 path_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200241
Václav Kubernát744f57f2018-06-29 22:46:26 +0200242 if (!schema.isPresenceContainer(location, {module, cont.m_name})) {
Václav Kubernát41378452018-06-06 16:29:40 +0200243 parserContext.m_errorMsg = "This container is not a presence container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200244 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200245 }
246 } catch (boost::bad_get&) {
Václav Kubernát41378452018-06-06 16:29:40 +0200247 parserContext.m_errorMsg = "This is not a container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200248 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200249 }
250 }
251
252 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200253 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernátb61336d2018-05-28 17:35:03 +0200254 {
255 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200256 if (parserContext.m_errorMsg.empty())
257 parserContext.m_errorMsg = "Couldn't parse create/delete command.";
258 return x3::error_handler_result::rethrow;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200259 }
260};
261
262struct create_class : public presenceContainerPathHandler {
263};
264
265struct delete_class : public presenceContainerPathHandler {
266};
267
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200268struct leaf_path_class {
269 template <typename T, typename Iterator, typename Context>
270 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
271 {
272 auto& parserContext = x3::get<parser_context_tag>(context);
273 try {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200274 auto leaf = boost::get<leaf_>(ast.m_nodes.back().m_suffix);
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200275 } catch (boost::bad_get&) {
276 parserContext.m_errorMsg = "This is not a path to leaf.";
277 _pass(context) = false;
278 }
279 }
280};
281
Václav Kubernátebca2552018-06-08 19:06:02 +0200282struct leaf_data_class {
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200283 template <typename Iterator, typename Exception, typename Context>
284 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
285 {
286 auto& parserContext = x3::get<parser_context_tag>(context);
287 auto& schema = parserContext.m_schema;
288 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát744f57f2018-06-29 22:46:26 +0200289 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200290 path_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernát744f57f2018-06-29 22:46:26 +0200291 parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, {parserContext.m_curModule, leaf.m_name})) + " here:";
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200292 return x3::error_handler_result::fail;
293 }
294 return x3::error_handler_result::rethrow;
295 }
Václav Kubernátebca2552018-06-08 19:06:02 +0200296};
297
298struct leaf_data_base_class {
299 yang::LeafDataTypes m_type;
300
301 leaf_data_base_class(yang::LeafDataTypes type)
302 : m_type(type)
303 {
304 }
305
306 template <typename T, typename Iterator, typename Context>
307 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
308 {
309 auto& parserContext = x3::get<parser_context_tag>(context);
310 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200311 boost::optional<std::string> module;
312 if (parserContext.m_curPath.m_nodes.back().m_prefix)
313 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200314
Václav Kubernát744f57f2018-06-29 22:46:26 +0200315 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernátebca2552018-06-08 19:06:02 +0200316 path_ location = pathWithoutLastNode(parserContext.m_curPath);
317
Václav Kubernát744f57f2018-06-29 22:46:26 +0200318 if (schema.leafType(location, {module, leaf.m_name}) != m_type) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200319 _pass(context) = false;
320 }
321 }
322};
323
324struct leaf_data_enum_class : leaf_data_base_class {
325 leaf_data_enum_class()
326 : leaf_data_base_class(yang::LeafDataTypes::Enum)
327 {
328 }
329
330 template <typename T, typename Iterator, typename Context>
331 void on_success(Iterator const& start, Iterator const& end, T& ast, Context const& context)
332 {
333 leaf_data_base_class::on_success(start, end, ast, context);
334 auto& parserContext = x3::get<parser_context_tag>(context);
335 auto& schema = parserContext.m_schema;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200336 boost::optional<std::string> module;
337 if (parserContext.m_curPath.m_nodes.back().m_prefix)
338 module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
Václav Kubernátebca2552018-06-08 19:06:02 +0200339
Václav Kubernát744f57f2018-06-29 22:46:26 +0200340 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
Václav Kubernátebca2552018-06-08 19:06:02 +0200341 path_ location = pathWithoutLastNode(parserContext.m_curPath);
342
Václav Kubernát744f57f2018-06-29 22:46:26 +0200343 if (!schema.leafEnumHasValue(location, {module, leaf.m_name}, ast.m_value)) {
Václav Kubernátebca2552018-06-08 19:06:02 +0200344 _pass(context) = false;
345 }
346 }
347};
348
349struct leaf_data_decimal_class : leaf_data_base_class {
350 leaf_data_decimal_class()
351 : leaf_data_base_class(yang::LeafDataTypes::Decimal)
352 {
353 }
354};
355
356struct leaf_data_bool_class : leaf_data_base_class {
357 leaf_data_bool_class()
358 : leaf_data_base_class(yang::LeafDataTypes::Bool)
359 {
360 }
361};
362
363struct leaf_data_int_class : leaf_data_base_class {
364 leaf_data_int_class()
365 : leaf_data_base_class(yang::LeafDataTypes::Int)
366 {
367 }
368};
369
370struct leaf_data_uint_class : leaf_data_base_class {
371 leaf_data_uint_class()
372 : leaf_data_base_class(yang::LeafDataTypes::Uint)
373 {
374 }
375};
376
377struct leaf_data_string_class : leaf_data_base_class {
378 leaf_data_string_class()
379 : leaf_data_base_class(yang::LeafDataTypes::String)
380 {
381 }
382};
383
Václav Kubernát07204242018-06-04 18:12:09 +0200384struct set_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200385 template <typename Iterator, typename Exception, typename Context>
386 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
387 {
388 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200389 if (parserContext.m_errorMsg.empty())
390 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
391 return x3::error_handler_result::rethrow;
Václav Kubernát07204242018-06-04 18:12:09 +0200392 }
393};
394
Václav Kubernátb61336d2018-05-28 17:35:03 +0200395struct command_class {
396 template <typename Iterator, typename Exception, typename Context>
397 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
398 {
399 auto& parserContext = x3::get<parser_context_tag>(context);
400 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
Václav Kubernát41378452018-06-06 16:29:40 +0200401 if (parserContext.m_errorMsg.empty()) {
402 parserContext.m_errorMsg = "Unknown command.";
403 }
404 error_handler(x.where(), parserContext.m_errorMsg);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200405 return x3::error_handler_result::fail;
406 }
407};