blob: 65d84051d6b43d76d12a157141f3f262d0863d10 [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át41378452018-06-06 16:29:40 +020025 } else if (!schema.listHasKey(parserContext.m_curPath, 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át0a2a2e82018-05-11 13:59:12 +020042struct identifier_class;
43
44struct listPrefix_class {
45 template <typename T, typename Iterator, typename Context>
46 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
47 {
48 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020049 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020050
Václav Kubernát48fc3832018-05-28 14:21:22 +020051 if (schema.isList(parserContext.m_curPath, ast)) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020052 parserContext.m_tmpListName = ast;
53 } else {
54 _pass(context) = false;
55 }
56 }
57};
58
59struct listSuffix_class {
60 template <typename T, typename Iterator, typename Context>
61 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
62 {
63 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020064 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020065
Václav Kubernát48fc3832018-05-28 14:21:22 +020066 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, parserContext.m_tmpListName);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020067 std::set<std::string> keysSupplied;
68 for (const auto& it : ast)
69 keysSupplied.insert(it.first);
70
71 if (keysNeeded != keysSupplied) {
72 parserContext.m_errorMsg = "Not enough keys for " + parserContext.m_tmpListName + ". " +
73 "These keys were not supplied:";
74 std::set<std::string> missingKeys;
75 std::set_difference(keysNeeded.begin(), keysNeeded.end(),
76 keysSupplied.begin(), keysSupplied.end(),
77 std::inserter(missingKeys, missingKeys.end()));
78
79 for (const auto& it : missingKeys)
80 parserContext.m_errorMsg += " " + it;
81 parserContext.m_errorMsg += ".";
82
83 _pass(context) = false;
84 }
85 }
Václav Kubernát41378452018-06-06 16:29:40 +020086
87 template <typename Iterator, typename Exception, typename Context>
88 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
89 {
90 auto& parserContext = x3::get<parser_context_tag>(context);
91 if (parserContext.m_errorMsg.empty())
92 parserContext.m_errorMsg = "Expecting ']' here:";
93 return x3::error_handler_result::rethrow;
Václav Kubernát41378452018-06-06 16:29:40 +020094 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020095};
96struct listElement_class {
97 template <typename T, typename Iterator, typename Context>
98 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
99 {
100 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát814fa412018-05-25 19:47:18 +0200101 parserContext.m_curPath.m_nodes.push_back(ast);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200102 }
103
104 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200105 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200106 {
107 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200108 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200109 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200110 } else {
111 return x3::error_handler_result::rethrow;
112 }
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200113 }
114};
115
Václav Kubernát60d6f292018-05-25 09:45:32 +0200116struct nodeup_class {
117 template <typename T, typename Iterator, typename Context>
118 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
119 {
120 auto& parserContext = x3::get<parser_context_tag>(context);
121
Václav Kubernát814fa412018-05-25 19:47:18 +0200122 if (!parserContext.m_curPath.m_nodes.empty()) {
123 parserContext.m_curPath.m_nodes.pop_back();
Václav Kubernát60d6f292018-05-25 09:45:32 +0200124 } else {
125 _pass(context) = false;
126 }
Václav Kubernát60d6f292018-05-25 09:45:32 +0200127 }
128};
129
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200130struct container_class {
131 template <typename T, typename Iterator, typename Context>
132 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
133 {
134 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +0200135 const auto& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200136
Václav Kubernát48fc3832018-05-28 14:21:22 +0200137 if (schema.isContainer(parserContext.m_curPath, ast.m_name)) {
Václav Kubernát814fa412018-05-25 19:47:18 +0200138 parserContext.m_curPath.m_nodes.push_back(ast);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200139 } else {
140 _pass(context) = false;
141 }
142 }
143};
144
Václav Kubernát07204242018-06-04 18:12:09 +0200145struct leaf_class {
146 template <typename T, typename Iterator, typename Context>
147 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
148 {
149 auto& parserContext = x3::get<parser_context_tag>(context);
150 const auto& schema = parserContext.m_schema;
151
152 if (schema.isLeaf(parserContext.m_curPath, ast.m_name)) {
153 parserContext.m_curPath.m_nodes.push_back(ast);
154 } else {
155 _pass(context) = false;
156 }
157 }
158};
159
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200160struct path_class {
161 template <typename T, typename Iterator, typename Context>
162 void on_success(Iterator const&, Iterator const&, T&, Context const&)
163 {
164 }
Václav Kubernát07204242018-06-04 18:12:09 +0200165
166 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200167 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernát07204242018-06-04 18:12:09 +0200168 {
169 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200170 if (parserContext.m_errorMsg.empty()) {
171 parserContext.m_errorMsg = "Expected path.";
Václav Kubernát07204242018-06-04 18:12:09 +0200172 return x3::error_handler_result::fail;
Václav Kubernát41378452018-06-06 16:29:40 +0200173 } else {
174 return x3::error_handler_result::rethrow;
175 }
Václav Kubernát07204242018-06-04 18:12:09 +0200176 }
177};
178
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200179struct cd_class {
180 template <typename T, typename Iterator, typename Context>
181 void on_success(Iterator const&, Iterator const&, T&, Context const&)
182 {
183 }
184
185 template <typename Iterator, typename Exception, typename Context>
186 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
187 {
188 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200189 if (parserContext.m_errorMsg.empty())
190 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
191 return x3::error_handler_result::rethrow;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200192 }
193};
Václav Kubernátb61336d2018-05-28 17:35:03 +0200194
195struct presenceContainerPathHandler {
196 template <typename T, typename Iterator, typename Context>
197 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
198 {
199 auto& parserContext = x3::get<parser_context_tag>(context);
200 const auto& schema = parserContext.m_schema;
201 try {
202 container_ cont = boost::get<container_>(ast.m_path.m_nodes.back());
Václav Kubernátebca2552018-06-08 19:06:02 +0200203 path_ location = pathWithoutLastNode(parserContext.m_curPath);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200204
205 if (!schema.isPresenceContainer(location, cont.m_name)) {
Václav Kubernát41378452018-06-06 16:29:40 +0200206 parserContext.m_errorMsg = "This container is not a presence container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200207 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200208 }
209 } catch (boost::bad_get&) {
Václav Kubernát41378452018-06-06 16:29:40 +0200210 parserContext.m_errorMsg = "This is not a container.";
Václav Kubernátb61336d2018-05-28 17:35:03 +0200211 _pass(context) = false;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200212 }
213 }
214
215 template <typename Iterator, typename Exception, typename Context>
Václav Kubernát41378452018-06-06 16:29:40 +0200216 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
Václav Kubernátb61336d2018-05-28 17:35:03 +0200217 {
218 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200219 if (parserContext.m_errorMsg.empty())
220 parserContext.m_errorMsg = "Couldn't parse create/delete command.";
221 return x3::error_handler_result::rethrow;
Václav Kubernátb61336d2018-05-28 17:35:03 +0200222 }
223};
224
225struct create_class : public presenceContainerPathHandler {
226};
227
228struct delete_class : public presenceContainerPathHandler {
229};
230
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200231struct leaf_path_class {
232 template <typename T, typename Iterator, typename Context>
233 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
234 {
235 auto& parserContext = x3::get<parser_context_tag>(context);
236 try {
237 auto leaf = boost::get<leaf_>(ast.m_nodes.back());
238 } catch (boost::bad_get&) {
239 parserContext.m_errorMsg = "This is not a path to leaf.";
240 _pass(context) = false;
241 }
242 }
243};
244
Václav Kubernátebca2552018-06-08 19:06:02 +0200245struct leaf_data_class {
Václav Kubernát0b0272f2018-06-13 14:13:08 +0200246 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 auto& schema = parserContext.m_schema;
251 if (parserContext.m_errorMsg.empty()) {
252 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back());
253 path_ location = pathWithoutLastNode(parserContext.m_curPath);
254 parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, leaf.m_name)) + " here:";
255 return x3::error_handler_result::fail;
256 }
257 return x3::error_handler_result::rethrow;
258 }
Václav Kubernátebca2552018-06-08 19:06:02 +0200259};
260
261struct leaf_data_base_class {
262 yang::LeafDataTypes m_type;
263
264 leaf_data_base_class(yang::LeafDataTypes type)
265 : m_type(type)
266 {
267 }
268
269 template <typename T, typename Iterator, typename Context>
270 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
271 {
272 auto& parserContext = x3::get<parser_context_tag>(context);
273 auto& schema = parserContext.m_schema;
274
275 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back());
276 path_ location = pathWithoutLastNode(parserContext.m_curPath);
277
278 if (schema.leafType(location, leaf.m_name) != m_type) {
279 _pass(context) = false;
280 }
281 }
282};
283
284struct leaf_data_enum_class : leaf_data_base_class {
285 leaf_data_enum_class()
286 : leaf_data_base_class(yang::LeafDataTypes::Enum)
287 {
288 }
289
290 template <typename T, typename Iterator, typename Context>
291 void on_success(Iterator const& start, Iterator const& end, T& ast, Context const& context)
292 {
293 leaf_data_base_class::on_success(start, end, ast, context);
294 auto& parserContext = x3::get<parser_context_tag>(context);
295 auto& schema = parserContext.m_schema;
296
297 leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back());
298 path_ location = pathWithoutLastNode(parserContext.m_curPath);
299
300 if (!schema.leafEnumHasValue(location, leaf.m_name, ast.m_value)) {
301 _pass(context) = false;
302 }
303 }
304};
305
306struct leaf_data_decimal_class : leaf_data_base_class {
307 leaf_data_decimal_class()
308 : leaf_data_base_class(yang::LeafDataTypes::Decimal)
309 {
310 }
311};
312
313struct leaf_data_bool_class : leaf_data_base_class {
314 leaf_data_bool_class()
315 : leaf_data_base_class(yang::LeafDataTypes::Bool)
316 {
317 }
318};
319
320struct leaf_data_int_class : leaf_data_base_class {
321 leaf_data_int_class()
322 : leaf_data_base_class(yang::LeafDataTypes::Int)
323 {
324 }
325};
326
327struct leaf_data_uint_class : leaf_data_base_class {
328 leaf_data_uint_class()
329 : leaf_data_base_class(yang::LeafDataTypes::Uint)
330 {
331 }
332};
333
334struct leaf_data_string_class : leaf_data_base_class {
335 leaf_data_string_class()
336 : leaf_data_base_class(yang::LeafDataTypes::String)
337 {
338 }
339};
340
Václav Kubernát07204242018-06-04 18:12:09 +0200341struct set_class {
Václav Kubernát07204242018-06-04 18:12:09 +0200342 template <typename Iterator, typename Exception, typename Context>
343 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
344 {
345 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát41378452018-06-06 16:29:40 +0200346 if (parserContext.m_errorMsg.empty())
347 parserContext.m_errorMsg = "Expected " + x.which() + " here:";
348 return x3::error_handler_result::rethrow;
Václav Kubernát07204242018-06-04 18:12:09 +0200349 }
350};
351
Václav Kubernátb61336d2018-05-28 17:35:03 +0200352struct command_class {
353 template <typename Iterator, typename Exception, typename Context>
354 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
355 {
356 auto& parserContext = x3::get<parser_context_tag>(context);
357 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
Václav Kubernát41378452018-06-06 16:29:40 +0200358 if (parserContext.m_errorMsg.empty()) {
359 parserContext.m_errorMsg = "Unknown command.";
360 }
361 error_handler(x.where(), parserContext.m_errorMsg);
Václav Kubernátb61336d2018-05-28 17:35:03 +0200362 return x3::error_handler_result::fail;
363 }
364};