SimpleAI
 All Classes Namespaces Files Functions Variables Typedefs Macros Groups Pages
ConditionParser.h
Go to the documentation of this file.
1 
5 #pragma once
6 
8 #include "common/IParser.h"
9 #include "conditions/Filter.h"
10 #include "AIRegistry.h"
11 
12 namespace ai {
13 
14 class IAIFactory;
15 
23 class ConditionParser : public IParser {
24 private:
25  const IAIFactory& _aiFactory;
26  std::string _conditionString;
27 
28  void splitConditions(const std::string& string, std::vector<std::string>& tokens) const;
29  bool fillInnerConditions(ConditionFactoryContext& ctx, const std::string& inner);
30  bool fillInnerFilters(FilterFactoryContext& ctx, const std::string& inner);
31 
32 public:
33  ConditionParser(const IAIFactory& aiFactory, const std::string& conditionString) :
34  IParser(), _aiFactory(aiFactory) {
35  _conditionString = ai::Str::eraseAllSpaces(conditionString);
36  }
37  virtual ~ConditionParser() {}
38 
39  ConditionPtr getCondition();
40 };
41 
42 inline void ConditionParser::splitConditions(const std::string& string, std::vector<std::string>& tokens) const {
43  int inParameter = 0;
44  int inChildren = 0;
45  std::string token;
46  for (std::string::const_iterator i = string.begin(); i != string.end(); ++i) {
47  if (*i == '{') {
48  ++inParameter;
49  } else if (*i == '}') {
50  --inParameter;
51  } else if (*i == '(') {
52  ++inChildren;
53  } else if (*i == ')') {
54  --inChildren;
55  }
56 
57  if (inParameter == 0 && inChildren == 0) {
58  if (*i == ',') {
59  tokens.push_back(token);
60  token.clear();
61  continue;
62  }
63  }
64  token.push_back(*i);
65  }
66  tokens.push_back(token);
67 }
68 
69 inline bool ConditionParser::fillInnerFilters(FilterFactoryContext& ctx, const std::string& filterStr) {
70  std::vector<std::string> conditions;
71  splitConditions(filterStr, conditions);
72  if (conditions.size() > 1) {
73  for (std::vector<std::string>::const_iterator i = conditions.begin(); i != conditions.end(); ++i) {
74  if (!fillInnerFilters(ctx, *i)) {
75  return false;
76  }
77  }
78  return true;
79  }
80 
81  std::string parameters;
82  std::size_t n = filterStr.find("(");
83  if (n == std::string::npos || filterStr.find("{") < n) {
84  parameters = getBetween(filterStr, "{", "}");
85  n = filterStr.find("{");
86  }
87 
88  std::string name;
89  if (n != std::string::npos) {
90  name = filterStr.substr(0, n);
91  } else {
92  name = filterStr;
93  }
94  FilterFactoryContext ctxInner(parameters);
95  n = filterStr.find("(");
96  if (n != std::string::npos) {
97  const std::size_t r = filterStr.rfind(")");
98  if (r == std::string::npos) {
99  setError("syntax error, missing closing brace");
100  return false;
101  }
102  const std::string& inner = filterStr.substr(n + 1, r - n - 1);
103  if (!fillInnerFilters(ctxInner, inner)) {
104  return false;
105  }
106  }
107  const FilterPtr& c = _aiFactory.createFilter(name, ctxInner);
108  if (!c) {
109  setError("could not create filter for %s", name.c_str());
110  return false;
111  }
112  ctx.filters.push_back(c);
113  return true;
114 }
115 
116 inline bool ConditionParser::fillInnerConditions(ConditionFactoryContext& ctx, const std::string& conditionStr) {
117  std::vector<std::string> conditions;
118  splitConditions(conditionStr, conditions);
119  if (conditions.size() > 1) {
120  for (std::vector<std::string>::const_iterator i = conditions.begin(); i != conditions.end(); ++i) {
121  if (!fillInnerConditions(ctx, *i)) {
122  return false;
123  }
124  }
125  } else {
126  std::string parameters;
127  std::size_t n = conditionStr.find("(");
128  if (n == std::string::npos || conditionStr.find("{") < n) {
129  parameters = getBetween(conditionStr, "{", "}");
130  n = conditionStr.find("{");
131  }
132 
133  std::string name;
134  if (n != std::string::npos) {
135  name = conditionStr.substr(0, n);
136  } else {
137  name = conditionStr;
138  }
139  // filter condition is a little bit special and deserves some extra attention
140  if (ctx.filter) {
141  FilterFactoryContext ctxInner(parameters);
142  n = conditionStr.find("(");
143  if (n != std::string::npos) {
144  const std::size_t r = conditionStr.rfind(")");
145  if (r == std::string::npos) {
146  setError("syntax error, missing closing brace");
147  return false;
148  }
149  const std::string& inner = conditionStr.substr(n + 1, r - n - 1);
150  if (!fillInnerFilters(ctxInner, inner)) {
151  return false;
152  }
153  }
154  const FilterPtr& c = _aiFactory.createFilter(name, ctxInner);
155  if (!c) {
156  setError("could not create filter for %s", name.c_str());
157  return false;
158  }
159  ctx.filters.push_back(c);
160  } else {
161  ConditionFactoryContext ctxInner(parameters);
162  ctxInner.filter = name == FILTER_NAME;
163  n = conditionStr.find("(");
164  if (n != std::string::npos) {
165  const std::size_t r = conditionStr.rfind(")");
166  if (r == std::string::npos) {
167  setError("syntax error, missing closing brace");
168  return false;
169  }
170  const std::string& inner = conditionStr.substr(n + 1, r - n - 1);
171  if (!fillInnerConditions(ctxInner, inner)) {
172  return false;
173  }
174  }
175  const ConditionPtr& c = _aiFactory.createCondition(name, ctxInner);
176  if (!c) {
177  setError("could not create inner condition for %s", name.c_str());
178  return false;
179  }
180  ctx.conditions.push_back(c);
181  }
182  }
183  return true;
184 }
185 
186 inline ConditionPtr ConditionParser::getCondition() {
187  resetError();
188  std::string parameters;
189  std::size_t n = _conditionString.find("(");
190  if (n == std::string::npos || _conditionString.find("{") < n) {
191  parameters = getBetween(_conditionString, "{", "}");
192  n = _conditionString.find("{");
193  }
194  std::string name;
195  if (n != std::string::npos) {
196  name = _conditionString.substr(0, n);
197  } else {
198  name = _conditionString;
199  }
200  ConditionFactoryContext ctx(parameters);
201  ctx.filter = name == FILTER_NAME;
202  n = _conditionString.find("(");
203  if (n != std::string::npos) {
204  const std::size_t r = _conditionString.rfind(")");
205  if (r == std::string::npos) {
206  setError("syntax error, missing closing brace");
207  return ConditionPtr();
208  }
209  const std::string& inner = _conditionString.substr(n + 1, r - n - 1);
210  if (!fillInnerConditions(ctx, inner)) {
211  return ConditionPtr();
212  }
213  } else if (ctx.filter) {
214  setError("missing details for Filter condition");
215  return ConditionPtr();
216  }
217  const ConditionPtr& c = _aiFactory.createCondition(name, ctx);
218  if (!c) {
219  setError("could not create condition for %s", name.c_str());
220  return ConditionPtr();
221  }
222  return c;
223 }
224 
225 }
virtual ConditionPtr createCondition(const std::string &type, const ConditionFactoryContext &ctx) const =0
Allocates a new ICondition for the given type. The type must be registered in the AIRegistry for this...
Definition: AIFactories.h:51
Condition related stuff.
virtual FilterPtr createFilter(const std::string &type, const FilterFactoryContext &ctx) const =0
Allocates a new IFilter for the given type. The type must be registered in the AIRegistry for this to...
Definition: IParser.h:14
Definition: AIFactories.h:34
Definition: IAIFactory.h:39
Transforms the string representation of a condition with all its sub conditions and parameters into a...
Definition: ConditionParser.h:23