blob: 746116e88b37cfb1250e92b547d8e91d0de2d9c0 [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 +020014
15struct 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);
20 const CTree& tree = parserContext.m_tree;
21
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.";
25 } else if (tree.listHasKey(parserContext.m_curPath, parserContext.m_tmpListName, ast.first)) {
26 parserContext.m_tmpListKeys.insert(ast.first);
27 } else {
28 _pass(context) = false;
29 parserContext.m_errorMsg = parserContext.m_tmpListName + " is not indexed by \"" + ast.first + "\".";
30 }
31 }
32};
33struct identifier_class;
34
35struct listPrefix_class {
36 template <typename T, typename Iterator, typename Context>
37 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
38 {
39 auto& parserContext = x3::get<parser_context_tag>(context);
40 const CTree& tree = parserContext.m_tree;
41
42 if (tree.isList(parserContext.m_curPath, ast)) {
43 parserContext.m_tmpListName = ast;
44 } else {
45 _pass(context) = false;
46 }
47 }
48};
49
50struct listSuffix_class {
51 template <typename T, typename Iterator, typename Context>
52 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
53 {
54 auto& parserContext = x3::get<parser_context_tag>(context);
55 const CTree& tree = parserContext.m_tree;
56
57 const auto& keysNeeded = tree.listKeys(parserContext.m_curPath, parserContext.m_tmpListName);
58 std::set<std::string> keysSupplied;
59 for (const auto& it : ast)
60 keysSupplied.insert(it.first);
61
62 if (keysNeeded != keysSupplied) {
63 parserContext.m_errorMsg = "Not enough keys for " + parserContext.m_tmpListName + ". " +
64 "These keys were not supplied:";
65 std::set<std::string> missingKeys;
66 std::set_difference(keysNeeded.begin(), keysNeeded.end(),
67 keysSupplied.begin(), keysSupplied.end(),
68 std::inserter(missingKeys, missingKeys.end()));
69
70 for (const auto& it : missingKeys)
71 parserContext.m_errorMsg += " " + it;
72 parserContext.m_errorMsg += ".";
73
74 _pass(context) = false;
75 }
76 }
77};
78struct listElement_class {
79 template <typename T, typename Iterator, typename Context>
80 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
81 {
82 auto& parserContext = x3::get<parser_context_tag>(context);
Václav Kubernát0b76a042018-05-16 20:16:47 +020083 parserContext.m_curPath = joinPaths(parserContext.m_curPath, ast.m_name);
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020084 }
85
86 template <typename Iterator, typename Exception, typename Context>
87 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& ex, Context const& context)
88 {
89 auto& parserContext = x3::get<parser_context_tag>(context);
90 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
91 if (parserContext.m_errorHandled) // someone already handled our error
92 return x3::error_handler_result::fail;
93
94 parserContext.m_errorHandled = true;
95
96 std::string message = parserContext.m_errorMsg;
97 error_handler(ex.where(), message);
98 return x3::error_handler_result::fail;
99 }
100};
101
102struct container_class {
103 template <typename T, typename Iterator, typename Context>
104 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
105 {
106 auto& parserContext = x3::get<parser_context_tag>(context);
107 const auto& tree = parserContext.m_tree;
108
109 if (tree.isContainer(parserContext.m_curPath, ast.m_name)) {
110 parserContext.m_curPath = joinPaths(parserContext.m_curPath, ast.m_name);
111 } else {
112 _pass(context) = false;
113 }
114 }
115};
116
117struct path_class {
118 template <typename T, typename Iterator, typename Context>
119 void on_success(Iterator const&, Iterator const&, T&, Context const&)
120 {
121 }
122};
123
124struct cd_class {
125 template <typename T, typename Iterator, typename Context>
126 void on_success(Iterator const&, Iterator const&, T&, Context const&)
127 {
128 }
129
130 template <typename Iterator, typename Exception, typename Context>
131 x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
132 {
133 auto& parserContext = x3::get<parser_context_tag>(context);
134 auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
135 std::string message = "This isn't a list or a container or nothing.";
136 if (parserContext.m_errorHandled) // someone already handled our error
137 return x3::error_handler_result::fail;
138
139 parserContext.m_errorHandled = true;
140 error_handler(x.where(), message);
141 return x3::error_handler_result::fail;
142 }
143};