00001 #include "ConditionParser.h"
00002
00003 #include <boost/version.hpp>
00004 #if BOOST_VERSION >= 103800
00005 #define BOOST_SPIRIT_USE_OLD_NAMESPACE
00006 #include <boost/spirit/include/classic_core.hpp>
00007 #else
00008 #include <boost/spirit/core.hpp>
00009 #endif
00010
00011 using namespace std;
00012 using namespace boost::spirit;
00013
00014 namespace {
00015
00017 struct TempParameter {
00018 TempParameter():name(),param(){}
00019 ~TempParameter() { }
00020
00021 std::string name;
00022 BasicParam* param;
00023
00025 template <class T>
00026 void setValue(T value){
00027 if (param) delete param;
00028 param = new Param<T>(value);
00029 }
00030
00032 template <class T>
00033 void newVector(){
00034 if (param) delete param;
00035 param = new Param<std::vector<T> >();
00036 }
00037
00039 struct SetName {
00040 SetName(TempParameter &par):temp(par){}
00041 TempParameter &temp;
00042 void operator () (char const*b, char const*e) const {
00043 temp.name = std::string(b,e);
00044
00045 }
00046 };
00047
00049 template <class T>
00050 struct SetValue {
00051 SetValue(TempParameter &par):temp(par){}
00052 TempParameter &temp;
00053 void operator () (T val) const {
00054
00055 temp.setValue<T>(val);
00056 }
00057 };
00058
00060 struct SetValueString {
00061 SetValueString(TempParameter &par):temp(par){}
00062 TempParameter &temp;
00063 void operator () (char const*b, char const*e) const {
00064 temp.setValue<std::string>(std::string(b,e));
00065
00066 }
00067 };
00068
00070 template <class T>
00071 struct AddVector {
00072 AddVector(TempParameter &par):temp(par){}
00073 TempParameter &temp;
00074 void operator () (char const*, char const*) const {
00075
00076 temp.newVector<T>();
00077 }
00078 };
00079
00081 template <class T>
00082 struct PushBack {
00083 PushBack(TempParameter &par):temp(par){}
00084 TempParameter &temp;
00085 void operator () (T val) const {
00086
00087 temp.param->template get<std::vector<T> >().push_back(val);
00088 }
00089 };
00090
00092 struct PushBackString {
00093 PushBackString(TempParameter &par):temp(par){}
00094 TempParameter &temp;
00095 void operator () (char const*b, char const*e) const {
00096
00097 temp.param->get<std::vector<std::string> >().push_back(std::string(b,e));
00098 }
00099 };
00100
00102 struct AddParameter {
00103 AddParameter(ParamValidDataObject &c, TempParameter &par):temp(par),cond(c){}
00104 TempParameter &temp;
00105 ParamValidDataObject &cond;
00106 void operator () (char const*, char const*) const {
00107
00108 cond.addBasicParam(temp.name,temp.param);
00109 }
00110 };
00111
00112 };
00113
00115 struct SetString {
00116 SetString(std::string &s):temp(s){}
00117 std::string &temp;
00118 void operator () (char const*b, char const*e) const {
00119 temp = std::string(b,e);
00120
00121 }
00122 };
00123
00125 class ConditionGrammar : public grammar<ConditionGrammar> {
00126 public:
00127
00128 ConditionGrammar() {}
00129
00131 std::string name;
00133 ParamValidDataObject condition;
00134
00135
00137 template <class ScannerT>
00138 struct definition {
00139
00141 enum Types {
00142 Integer = 0,
00143 Double,
00144 String,
00145 IntegerVector,
00146 DoubleVector,
00147 StringVector,
00148 NTypes};
00149
00151 ParamValidDataObject &cond;
00153 std::string &condition_name;
00155 TempParameter tmp;
00156
00158 rule<ScannerT> identifier, name, parameter, type[NTypes], value[NTypes];
00159 rule<ScannerT> spaces, eq, sep;
00161 rule<ScannerT> condition;
00162
00164 definition ( const ConditionGrammar &self ):
00165 cond(const_cast<ConditionGrammar &>(self).condition),
00166 condition_name(const_cast<ConditionGrammar &>(self).name)
00167 {
00168
00169 identifier = *(alnum_p | ch_p('/') | ch_p('_') | ch_p('-') | ch_p(':'));
00170
00171
00172 name = identifier[TempParameter::SetName(tmp)];
00173
00174
00175
00176 type[Integer] = str_p("int");
00177 type[Double] = (str_p("double") | str_p("dbl"));
00178 type[String] = (str_p("string") | str_p("str"));
00179
00180 type[IntegerVector] = str_p("int_v")
00181 [TempParameter::AddVector<int>(tmp)];
00182 type[DoubleVector] = (str_p("double_v") | str_p("dbl_v"))
00183 [TempParameter::AddVector<double>(tmp)];
00184 type[StringVector] = (str_p("string_v") | str_p("str_v"))
00185 [TempParameter::AddVector<std::string>(tmp)];
00186
00187
00188 spaces = *space_p;
00189 eq = ch_p('=');
00190 sep = ch_p(';');
00191
00192
00193 value[Integer] = int_p
00194 [TempParameter::SetValue<int>(tmp)];
00195 value[Double] = real_p
00196 [TempParameter::SetValue<double>(tmp)];
00197 value[String] = ((+alnum_p) % spaces)
00198 [TempParameter::SetValueString(tmp)];
00199
00200 value[IntegerVector] = int_p[TempParameter::PushBack<int>(tmp)] % spaces;
00201 value[DoubleVector] = real_p[TempParameter::PushBack<double>(tmp)] % spaces;
00202 value[StringVector] = (+~space_p)[TempParameter::PushBackString(tmp)] % spaces;
00203
00204
00205 parameter =
00206 (
00207
00208 ( type[IntegerVector] >> spaces >> name >> spaces >> eq >> spaces >> value[IntegerVector] ) |
00209
00210 ( type[DoubleVector] >> spaces >> name >> spaces >> eq >> spaces >> value[DoubleVector] ) |
00211
00212 ( type[StringVector] >> spaces >> name >> spaces >> eq >> spaces >> value[StringVector] ) |
00213
00214 ( type[Integer] >> spaces >> name >> spaces >> eq >> spaces >> value[Integer] ) |
00215
00216 ( type[Double] >> spaces >> name >> spaces >> eq >> spaces >> value[Double] ) |
00217
00218 ( type[String] >> spaces >> name >> spaces >> eq >> spaces >> value[String] )
00219 )
00220
00221 [TempParameter::AddParameter(cond,tmp)];
00222
00223
00224 condition =
00225
00226 identifier[SetString(condition_name)] >> spaces >>
00227
00228 str_p(":=") >> spaces >>
00229
00230 ( parameter % ( spaces >> sep >> spaces ) ) >>
00231
00232 spaces >> !(sep >> spaces);
00233 }
00234
00236 rule<ScannerT> const& start() const { return condition; }
00237 };
00238 };
00239 }
00240
00241
00242
00243
00244 bool ConditionParser(const std::string &str, std::string &name, ParamValidDataObject &cond){
00245 ConditionGrammar g;
00246
00247 if ( parse(str.c_str(),g).full ){
00248 name = g.name;
00249 cond.update(g.condition);
00250 return true;
00251 }
00252 return false;
00253 }