alaCarte Maps
Renderer for OpenStreetMap tiles
eval.hpp
Go to the documentation of this file.
1 
21 #pragma once
22 #ifndef _EVAL_HPP
23 #define _EVAL_HPP
24 
25 
26 
27 #include <boost/variant/apply_visitor.hpp>
28 #include <boost/variant/variant.hpp>
29 #include <boost/variant/get.hpp>
30 
31 
32 #include "settings.hpp"
33 #include "eval_helpers.hpp"
34 #include "eval.hpp"
35 #include "stnode.hpp"
36 #include "../parser/parser_logger.hpp"
37 #include "../parser/parse_info.hpp"
38 
39 class GeoObject;
40 
41 namespace eval {
42 
43 
44 shared_ptr<STNode> parseEval(string::const_iterator begin, string::const_iterator end, const shared_ptr<ParserLogger>& logger);
45 
52 template<typename TargetType>
53 class Eval
54 {
55 public:
56  typedef shared_ptr<STNode> node_ptr;
57  typedef boost::variant<TargetType, node_ptr> value_type;
58 
66  Eval(const TargetType& value)
67  : value(value)
68  , failed(false)
69  , info("[hard coded]", 0, 0, ToString(value))
70  {
71 
72  }
73 
85  Eval(const string& expr, const shared_ptr<ParserLogger>& logger, const ParseInfo& info)
86  : value(TargetType())
87  , logger(logger)
88  , failed(false)
89  , info(info)
90  {
91  shared_ptr<STNode> result = parseEval(expr.cbegin(), expr.cend(), logger);
92 
93  // If this is now eval expression, try to parse the type directly
94  if(result)
95  {
96  value = result;
97  } else {
98 
99  // If we extract a string here than cache it
100  if(!Conv(expr, &boost::get<TargetType>(value), true))
101  {
102  BOOST_THROW_EXCEPTION(excp::ParseException()
104  << excp::InfoFailureLine(info.getLine())
105  << excp::InfoWhat("Failed to parse the expression into an eval or a '" + string(typeid(TargetType).name()) + "'"));
106  }else{
107  if(expr.find("eval") == 0)
108  {
109  logger->warnStream() << "In line " << info.getLine() << " could be an eval but failed to parse so.";
110  logger->warnStream() << "Expression is used as " << string(typeid(TargetType).name()) << "!";
111  logger->warnStream() << "'" << info.getLineContent() << "'";
112  }
113  }
114  }
115  }
116 
123  void overwrite(GeoObject* obj, TargetType* v) const
124  {
125  // which() == 0 -> TargetType
126  // which() == 1 -> Eval
127  if(!isEval())
128  {
129  *v = boost::get<TargetType>(value);
130  }else{
131  assert(value.which() == 1);
132 
133  string result = boost::get<node_ptr>(value)->eval(obj);
134  if(!Conv(result, v) && !failed && logger)
135  {
136  failed = true;
137  logger->warnStream() << "Evaluation evaluated into \"" << result << "\", then failed to convert into " << typeid(TargetType).name() << ".";
138  logger->warnStream() << "[in line " << info.getLine() << " with content \"" << info.getLineContent() << "\"]";
139  }
140  }
141  }
142 
143  bool isEval() const
144  {
145  // which() == 0 -> TargetType
146  // which() == 1 -> Eval
147  return value.which() == 1;
148  }
149 private:
150  // Internal target value or evaluateable expression
151  value_type value;
152 
153  // Logger for this eval
154  shared_ptr<ParserLogger> logger;
155 
156  // Flag if this eval failed before
157  mutable bool failed;
158 
159  // Info about the source this eval is coming from.
161 };
162 
163 
164 
165 
170 template<typename TargetType>
171 class Eval< std::vector<TargetType> >
172 {
173 public:
174  typedef shared_ptr<STNode> node_ptr;
175  typedef boost::variant<TargetType, node_ptr> value_type;
176 
177  Eval(const std::vector<TargetType>& values)
178  : valuelist(values)
179  , failed(false)
180  , info("[hard coded]", 0, 0, ToString(values))
181  {
182 
183  }
184 
185  Eval(const string& expr, const shared_ptr<ParserLogger>& logger, const ParseInfo& info)
186  : logger(logger)
187  , failed(false)
188  , info(info)
189  {
190  // Use simple parser to separate commas
191  bool quote = false;
192  bool dquote = false;
193  int parentheses = 0;
194 
195  string::const_iterator begin = expr.cbegin();
196  string::const_iterator end = begin;
197 
198  while(end != expr.end())
199  {
200  switch(*end)
201  {
202  case ',':
203  // Handle ,
204  if(parentheses == 0 && !dquote && !quote)
205  {
206  addValue(string(begin, end));
207  begin = ++end;
208  continue;
209  }
210  break;
211 
212  case '(':
213  case ')':
214  // Handle parentheses
215  if(!dquote && !quote)
216  {
217  if(*end == '(')
218  {
219  ++parentheses;
220  }
221  else if(*end == ')' && parentheses > 0)
222  {
223  --parentheses;
224  }
225  }
226  break;
227 
228  case '\"':
229  // Handle "
230  if(!quote)
231  {
232  dquote = !dquote;
233  }
234  break;
235 
236  case '\'':
237  // Handle '
238  if(!dquote)
239  {
240  quote = !quote;
241  }
242  break;
243 
244  default:
245  break;
246  }
247 
248  ++end;
249  }
250 
251  addValue(string(begin, end));
252 
253 
254  }
255 
256  void overwrite(GeoObject* obj, std::vector<TargetType>* v) const
257  {
258  v->clear();
259  for(auto& e : valuelist)
260  {
261  // which() == 0 -> TargetType
262  // which() == 1 -> Eval
263  if(e.which() == 0)
264  {
265  v->push_back(boost::get<TargetType>(e));
266  }else{
267  string result = boost::get<node_ptr>(e)->eval(obj);
268  TargetType target;
269  if(!Conv(result, &target) && !failed && logger)
270  {
271  failed = true;
272  logger->warnStream() << "Evaluation evaluated into \"" << result << "\", then failed to convert into " << typeid(TargetType).name() << ".";
273  logger->warnStream() << "[in line " << info.getLine() << " with content \"" << info.getLineContent() << "\"]";
274  }else{
275  v->push_back(target);
276  }
277  }
278  }
279  }
280 
281  int size() const
282  {
283  return valuelist.size();
284  }
285 
286  bool isEval(int i) const
287  {
288  // which() == 0 -> TargetType
289  // which() == 1 -> Eval
290  return valuelist[i].which() == 1;
291  }
292 private:
293  void addValue(const string& part)
294  {
295  valuelist.push_back(TargetType());
296  if(!Conv(part, &boost::get<TargetType>(valuelist.back()), true))
297  {
298  shared_ptr<STNode> result = parseEval(part.cbegin(), part.cend(), logger);
299 
300  if(!result)
301  BOOST_THROW_EXCEPTION(excp::ParseException()
304  << excp::InfoWhat("Failed to parse the expression into an list of eval's or a " + string(typeid(TargetType).name()) + "'s"));
305 
306  valuelist.back() = result;
307  }
308  }
309 
310 
311  // Internal target values or evaluateable expressions
312  std::vector<value_type> valuelist;
313 
314  // Logger for this eval
315  shared_ptr<ParserLogger> logger;
316 
317  // Flag if this eval failed before
318  mutable bool failed;
319 
320  // Info about the source this eval is coming from.
322 };
323 
324 
325 }
326 
327 
328 #endif
shared_ptr< STNode > parseEval(string::const_iterator begin, string::const_iterator end, const shared_ptr< ParserLogger > &logger)
Creates a new eval.
Definition: eval.cpp:193
Eval(const string &expr, const shared_ptr< ParserLogger > &logger, const ParseInfo &info)
Creates an eval from a string.
Definition: eval.hpp:85
Thrown if the parsing fails.
Definition: exceptions.hpp:85
Eval(const string &expr, const shared_ptr< ParserLogger > &logger, const ParseInfo &info)
Definition: eval.hpp:185
bool Conv(const string &str, bool *out, bool tryToCache)
Use some extra function for bool conversion.
boost::variant< TargetType, node_ptr > value_type
Definition: eval.hpp:57
shared_ptr< STNode > node_ptr
Definition: eval.hpp:56
shared_ptr< ParserLogger > logger
Definition: eval.hpp:315
void addValue(const string &part)
Definition: eval.hpp:293
std::string string
Definition: settings.hpp:110
boost::error_info< struct TagWhatInfo, string > InfoWhat
Use this info to give an what msg to the exception.
Definition: exceptions.hpp:41
const unsigned int & getLine() const
Definition: parse_info.hpp:50
std::vector< value_type > valuelist
Definition: eval.hpp:312
boost::error_info< struct TagFailureLine, int > InfoFailureLine
Specifies the Line in the file where the failure appeared.
Definition: exceptions.hpp:51
This file is part of alaCarte.
boost::error_info< struct TagFailureLineContent, string > InfoFailureLineContent
Contains the content of the line where a failure appeared.
Definition: exceptions.hpp:55
value_type value
Definition: eval.hpp:151
Eval(const TargetType &value)
Creates an Eval from the value type, the eval should evaluated to.
Definition: eval.hpp:66
Represents a value in a style template.
Definition: eval.hpp:53
void overwrite(GeoObject *obj, std::vector< TargetType > *v) const
Definition: eval.hpp:256
shared_ptr< STNode > node_ptr
Definition: eval.hpp:174
string ToString(const bool &v)
bool failed
Definition: eval.hpp:157
Eval(const std::vector< TargetType > &values)
Definition: eval.hpp:177
shared_ptr< ParserLogger > logger
Definition: eval.hpp:154
void overwrite(GeoObject *obj, TargetType *v) const
Will overwrite the second parameter with an evaluated value.
Definition: eval.hpp:123
ParseInfo info
Definition: eval.hpp:160
bool isEval() const
Definition: eval.hpp:143
const string & getLineContent() const
Definition: parse_info.hpp:51
boost::variant< TargetType, node_ptr > value_type
Definition: eval.hpp:175