blob: 1feeeab315fd893b51082afa719d5a8467be604a [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át0a2a2e82018-05-11 13:59:12 +020013
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020014struct keyValue_class {
15 template <typename T, typename Iterator, typename Context>
16 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
17 {
18 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020019 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020020
21 if (parserContext.m_tmpListKeys.find(ast.first) != parserContext.m_tmpListKeys.end()) {
22 _pass(context) = false;
23 parserContext.m_errorMsg = "Key \"" + ast.first + "\" was entered more than once.";
Václav Kubernát48fc3832018-05-28 14:21:22 +020024 } else if (schema.listHasKey(parserContext.m_curPath, parserContext.m_tmpListName, ast.first)) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020025 parserContext.m_tmpListKeys.insert(ast.first);
26 } else {
27 _pass(context) = false;
28 parserContext.m_errorMsg = parserContext.m_tmpListName + " is not indexed by \"" + ast.first + "\".";
29 }
30 }
31};
32struct identifier_class;
33
34struct listPrefix_class {
35 template <typename T, typename Iterator, typename Context>
36 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
37 {
38 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020039 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020040
Václav Kubernát48fc3832018-05-28 14:21:22 +020041 if (schema.isList(parserContext.m_curPath, ast)) {
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020042 parserContext.m_tmpListName = ast;
43 } else {
44 _pass(context) = false;
45 }
46 }
47};
48
49struct listSuffix_class {
50 template <typename T, typename Iterator, typename Context>
51 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
52 {
53 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +020054 const Schema& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020055
Václav Kubernát48fc3832018-05-28 14:21:22 +020056 const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, parserContext.m_tmpListName);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020057 std::set<std::string> keysSupplied;
58 for (const auto& it : ast)
59 keysSupplied.insert(it.first);
60
61 if (keysNeeded != keysSupplied) {
62 parserContext.m_errorMsg = "Not enough keys for " + parserContext.m_tmpListName + ". " +
63 "These keys were not supplied:";
64 std::set<std::string> missingKeys;
65 std::set_difference(keysNeeded.begin(), keysNeeded.end(),
66 keysSupplied.begin(), keysSupplied.end(),
67 std::inserter(missingKeys, missingKeys.end()));
68
69 for (const auto& it : missingKeys)
70 parserContext.m_errorMsg += " " + it;
71 parserContext.m_errorMsg += ".";
72
73 _pass(context) = false;
74 }
75 }
76};
77struct listElement_class {
78 template <typename T, typename Iterator, typename Context>
79 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
80 {
81 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát814fa412018-05-25 19:47:18 +020082 parserContext.m_curPath.m_nodes.push_back(ast);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020083 }
84
85 template <typename Iterator, typename Exception, typename Context>
86 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& ex, Context const& context)
87 {
88 auto& parserContext = x3::get<parser_context_tag>(context);
89 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
90 if (parserContext.m_errorHandled) // someone already handled our error
91 return x3::error_handler_result::fail;
92
93 parserContext.m_errorHandled = true;
94
95 std::string message = parserContext.m_errorMsg;
96 error_handler(ex.where(), message);
97 return x3::error_handler_result::fail;
98 }
99};
100
Václav Kubernát60d6f292018-05-25 09:45:32 +0200101
102struct nodeup_class {
103 template <typename T, typename Iterator, typename Context>
104 void on_success(Iterator const&, Iterator const&, T&, Context const& context)
105 {
106 auto& parserContext = x3::get<parser_context_tag>(context);
107
Václav Kubernát814fa412018-05-25 19:47:18 +0200108 if (!parserContext.m_curPath.m_nodes.empty()) {
109 parserContext.m_curPath.m_nodes.pop_back();
Václav Kubernát60d6f292018-05-25 09:45:32 +0200110 } else {
111 _pass(context) = false;
112 }
Václav Kubernát60d6f292018-05-25 09:45:32 +0200113 }
114};
115
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200116struct container_class {
117 template <typename T, typename Iterator, typename Context>
118 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
119 {
120 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +0200121 const auto& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200122
Václav Kubernát48fc3832018-05-28 14:21:22 +0200123 if (schema.isContainer(parserContext.m_curPath, ast.m_name)) {
Václav Kubernát814fa412018-05-25 19:47:18 +0200124 parserContext.m_curPath.m_nodes.push_back(ast);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200125 } else {
126 _pass(context) = false;
127 }
128 }
129};
130
131struct path_class {
132 template <typename T, typename Iterator, typename Context>
133 void on_success(Iterator const&, Iterator const&, T&, Context const&)
134 {
135 }
136};
137
138struct cd_class {
139 template <typename T, typename Iterator, typename Context>
140 void on_success(Iterator const&, Iterator const&, T&, Context const&)
141 {
142 }
143
144 template <typename Iterator, typename Exception, typename Context>
145 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
146 {
147 auto& parserContext = x3::get<parser_context_tag>(context);
148 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
149 std::string message = "This isn't a list or a container or nothing.";
150 if (parserContext.m_errorHandled) // someone already handled our error
151 return x3::error_handler_result::fail;
152
153 parserContext.m_errorHandled = true;
154 error_handler(x.where(), message);
155 return x3::error_handler_result::fail;
156 }
157};
Václav Kubernátb61336d2018-05-28 17:35:03 +0200158
159struct presenceContainerPathHandler {
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 try {
166 container_ cont = boost::get<container_>(ast.m_path.m_nodes.back());
167 path_ location{decltype(path_::m_nodes)(parserContext.m_curPath.m_nodes.begin(),
168 parserContext.m_curPath.m_nodes.end() - 1)};
169
170 if (!schema.isPresenceContainer(location, cont.m_name)) {
171 _pass(context) = false;
172 return;
173 }
174 } catch (boost::bad_get&) {
175 _pass(context) = false;
176 return;
177 }
178 }
179
180 template <typename Iterator, typename Exception, typename Context>
181 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
182 {
183 auto& parserContext = x3::get<parser_context_tag>(context);
184 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
185 std::string message = "This isn't a path to a presence container.";
186 if (parserContext.m_errorHandled) // someone already handled our error
187 return x3::error_handler_result::fail;
188
189 parserContext.m_errorHandled = true;
190 error_handler(x.where(), message);
191 return x3::error_handler_result::fail;
192 }
193};
194
195struct create_class : public presenceContainerPathHandler {
196};
197
198struct delete_class : public presenceContainerPathHandler {
199};
200
201struct command_class {
202 template <typename Iterator, typename Exception, typename Context>
203 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
204 {
205 auto& parserContext = x3::get<parser_context_tag>(context);
206 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
207 std::string message = "Couldn't parse command.";
208 if (parserContext.m_errorHandled) // someone already handled our error
209 return x3::error_handler_result::fail;
210
211 parserContext.m_errorHandled = true;
212 error_handler(x.where(), message);
213 return x3::error_handler_result::fail;
214 }
215};