blob: 0c7f1c3217a19f011752adc4c23101c12fd5e7f2 [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 }
113
114 }
115};
116
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200117struct container_class {
118 template <typename T, typename Iterator, typename Context>
119 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
120 {
121 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát48fc3832018-05-28 14:21:22 +0200122 const auto& schema = parserContext.m_schema;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200123
Václav Kubernát48fc3832018-05-28 14:21:22 +0200124 if (schema.isContainer(parserContext.m_curPath, ast.m_name)) {
Václav Kubernát814fa412018-05-25 19:47:18 +0200125 parserContext.m_curPath.m_nodes.push_back(ast);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200126 } else {
127 _pass(context) = false;
128 }
129 }
130};
131
132struct path_class {
133 template <typename T, typename Iterator, typename Context>
134 void on_success(Iterator const&, Iterator const&, T&, Context const&)
135 {
136 }
137};
138
139struct cd_class {
140 template <typename T, typename Iterator, typename Context>
141 void on_success(Iterator const&, Iterator const&, T&, Context const&)
142 {
143 }
144
145 template <typename Iterator, typename Exception, typename Context>
146 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
147 {
148 auto& parserContext = x3::get<parser_context_tag>(context);
149 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
150 std::string message = "This isn't a list or a container or nothing.";
151 if (parserContext.m_errorHandled) // someone already handled our error
152 return x3::error_handler_result::fail;
153
154 parserContext.m_errorHandled = true;
155 error_handler(x.where(), message);
156 return x3::error_handler_result::fail;
157 }
158};