blob: 9ab47382630455350dd208f9294292b8bc1a4401 [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át0a2a2e82018-05-11 13:59:12 +020011#include "CTree.hpp"
Václav Kubernát195eeea2018-05-18 13:52:36 +020012#include "parser_context.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);
19 const CTree& tree = parserContext.m_tree;
20
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.";
24 } else if (tree.listHasKey(parserContext.m_curPath, parserContext.m_tmpListName, ast.first)) {
25 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);
39 const CTree& tree = parserContext.m_tree;
40
41 if (tree.isList(parserContext.m_curPath, ast)) {
42 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);
54 const CTree& tree = parserContext.m_tree;
55
56 const auto& keysNeeded = tree.listKeys(parserContext.m_curPath, parserContext.m_tmpListName);
57 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át0b76a042018-05-16 20:16:47 +020082 parserContext.m_curPath = joinPaths(parserContext.m_curPath, ast.m_name);
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
108 if (!parserContext.m_curPath.empty()) {
109 parserContext.m_curPath = stripLastNodeFromPath(parserContext.m_curPath);
110 } 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);
122 const auto& tree = parserContext.m_tree;
123
124 if (tree.isContainer(parserContext.m_curPath, ast.m_name)) {
125 parserContext.m_curPath = joinPaths(parserContext.m_curPath, ast.m_name);
126 } 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};