00001
00002
00003
00004
00005
00006
00008 #include <boost/spirit/core.hpp>
00009 #include <boost/spirit/symbols/symbols.hpp>
00010 #include <boost/spirit/utility.hpp>
00011 #include <boost/spirit/dynamic.hpp>
00012
00013 #include <iostream>
00014 #include <string>
00015 #include <stack>
00016 #include <typeinfo>
00017 #include <algorithm>
00018 #include <cctype>
00019
00020 #include "RuleParser/ParameterDescription.h"
00021 #include "RuleParser/Rules.h"
00022 #include "RuleParser/RuleFactory.h"
00023 #include "RuleParser/CreateRules.h"
00024 #include "units.h"
00025
00027 using namespace std;
00028 using namespace boost::spirit;
00029 using namespace RuleParser;
00030
00031
00032
00033
00034
00035 struct ParserStore
00036 {
00037
00038 stack<std::string> mStackOperators;
00039 stack<double> mStackDouble;
00040 stack<double> mStackUnit;
00041 stack<string> mStackString;
00042 stack<ParameterDescription> mStackParam;
00043 stack<Rule*> mStackRules;
00044
00045 stack<string> mTempStack;
00046
00047 void popval(double& r) { r = mStackDouble.top(); mStackDouble.pop();};
00048 void popval(string& r) { r = mStackString.top(); mStackString.pop();};
00049
00050 void clear() {
00051 while(! mStackOperators.empty()) mStackOperators.pop();
00052 while(! mStackDouble .empty()) mStackDouble .pop();
00053 while(! mStackString .empty()) mStackString .pop();
00054 while(! mStackParam .empty()) mStackParam .pop();
00055 while(! mStackRules .empty()) mStackRules .pop();
00056 };
00057 };
00058
00059
00061
00062
00063
00065
00066 struct debugprint{
00067 debugprint(std::string n) : name(n) {};
00068 std::string name;
00069 void operator()(char const* a, char const* b) const{
00070 string s(a,b);
00071
00072 }
00073 void operator()(char const* a) const{
00074
00075 }
00076 void operator()(const double &a) const{
00077
00078 }
00079 };
00080
00081 struct mySemantic {
00082 mySemantic(ParserStore& rp) : m_store(rp) {};
00083 ParserStore& m_store;
00084 };
00085
00086 struct my_do_double : public mySemantic
00087 {
00088 my_do_double(ParserStore& rp) : mySemantic(rp) {};
00089 void operator()(const double &d) const{
00090 m_store.mStackDouble.push(d);
00091 }
00092 };
00093
00094 struct my_do_string : public mySemantic
00095 {
00096 my_do_string(ParserStore& rp) : mySemantic(rp) {};
00097 void operator()(char const* a, char const* b) const{
00098 string s(a,b);
00099 m_store.mStackString.push(s);
00100 }
00101 };
00102
00103 struct my_do_unit : public mySemantic
00104 {
00105 my_do_unit(ParserStore& rp) : mySemantic(rp) {};
00106 void operator()(const double &d) const{
00107 m_store.mStackUnit.push(d);
00108 }
00109 };
00110
00111 struct my_do_double_with_unit : public mySemantic
00112 {
00113 my_do_double_with_unit(ParserStore& rp) : mySemantic(rp) {};
00114 void operator()(char const*, char const*) const {
00115 assert(m_store.mStackUnit.size()>0);
00116 assert(m_store.mStackDouble.size()>0);
00117 double d = m_store.mStackUnit.top() * m_store.mStackDouble.top();
00118 m_store.mStackDouble.pop();
00119 m_store.mStackUnit.pop();
00120 m_store.mStackDouble.push(d);
00121 }
00122 };
00123
00124 struct my_do_param : public mySemantic
00125 {
00126 my_do_param(ParserStore& rp) : mySemantic(rp) {};
00127
00128
00129
00130
00131
00132 void operator()(const ParameterDescription& d) const {
00133
00134 m_store.mStackParam.push(d);
00135 }
00136 };
00137
00138 struct my_do_operator : public mySemantic
00139 {
00140 my_do_operator(ParserStore& rp) : mySemantic(rp) {};
00141 void operator()(char const* a, char const* b) const{
00142 std::string s(a,b);
00143
00144 m_store.mStackOperators.push(s);
00145 }
00146
00147
00148
00149
00150
00151 };
00152
00153
00154 template<typename T>
00155 struct my_do_simple_comparison : public mySemantic
00156 {
00157 my_do_simple_comparison(ParserStore& rp,bool param_on_left) : mySemantic(rp), m_param_on_left(param_on_left){};
00158 bool m_param_on_left;
00159
00160 void operator()(char const* a, char const* b) const{
00161
00162
00163
00164
00165 string s(a,b);
00166 T val;
00167 m_store.popval(val);
00168
00169 ParameterDescription par = m_store.mStackParam.top();
00170 m_store.mStackParam.pop();
00171
00172 string op = m_store.mStackOperators.top();
00173 m_store.mStackOperators.pop();
00174
00175
00176 if(m_param_on_left != true) {
00177 if(op == "<" ) op = ">";
00178 if(op == "<=") op = ">=";
00179 if(op == ">" ) op = "<";
00180 if(op == ">=") op = "<=";
00181 }
00182
00183 Rule* outRule = 0;
00184 if(op=="<" ) outRule = new LT_Rule<T>(s,par.id(),val);
00185 if(op=="<=") outRule = new LE_Rule<T>(s,par.id(),val);
00186 if(op==">" ) outRule = new GT_Rule<T>(s,par.id(),val);
00187 if(op==">=") outRule = new GE_Rule<T>(s,par.id(),val);
00188 if(op=="==" || op=="=") outRule = new EQ_Rule<T>(s,par.id(),val);
00189 if(op=="!=") outRule = new NEQ_Rule<T>(s,par.id(),val);
00190
00191 assert(outRule);
00192 m_store.mStackRules.push(outRule);
00193
00194 }
00195 };
00196
00197
00198 template <typename T>
00199 struct my_do_custom : public mySemantic
00200 {
00201 my_do_custom(ParserStore& rp,
00202 const ParameterDescription& par,
00203 int which_operator,
00204 bool param_on_left)
00205 : mySemantic(rp)
00206 , m_par(par)
00207 , m_which_operator(which_operator)
00208 , m_param_on_left(param_on_left){};
00209
00210 const ParameterDescription& m_par;
00211 int m_which_operator;
00212 bool m_param_on_left;
00213
00214 void operator()(char const* , char const* ) const{
00215
00216 T val;
00217 m_store.popval(val);
00218
00219 assert(m_par.factory());
00220 Rule* rule = m_par.factory()->createRule(m_par, m_which_operator, val, m_param_on_left);
00221
00222 assert(rule);
00223 m_store.mStackRules.push(rule);
00224
00225 }
00226 };
00227
00228 struct my_do_and : public mySemantic
00229 {
00230 my_do_and(ParserStore& rp) : mySemantic(rp) {};
00231 void operator()(char const* a, char const* b) const{
00232
00233
00234
00235
00236 string s(a,b);
00237
00238 assert(m_store.mStackRules.size()>=2);
00239 Rule* rule2 = m_store.mStackRules.top();
00240 m_store.mStackRules.pop();
00241
00242 Rule* rule1 = m_store.mStackRules.top();
00243 m_store.mStackRules.pop();
00244
00245 string name=rule1->name();
00246 name.append(" ");
00247 name.append(s);
00248
00249 Rule* outRule = new AndRule(name,rule1,rule2);
00250
00251
00252 m_store.mStackRules.push(outRule);
00253 }
00254 };
00255
00256 struct my_do_or : public mySemantic
00257 {
00258 my_do_or(ParserStore& rp) : mySemantic(rp) {};
00259 void operator()(char const* a, char const* b) const{
00260
00261
00262
00263
00264 string s(a,b);
00265
00266 assert(m_store.mStackRules.size()>=2);
00267 Rule* rule2 = m_store.mStackRules.top();
00268 m_store.mStackRules.pop();
00269
00270 Rule* rule1 = m_store.mStackRules.top();
00271 m_store.mStackRules.pop();
00272
00273 string name=rule1->name();
00274 name.append(" ");
00275 name.append(s);
00276
00277 Rule* outRule = new OrRule(name,rule1,rule2);
00278
00279
00280 m_store.mStackRules.push(outRule);
00281 }
00282 };
00283
00284 struct my_do_not : public mySemantic
00285 {
00286 my_do_not(ParserStore& rp) : mySemantic(rp) {};
00287 void operator()(char const* a, char const* b) const{
00288 assert(m_store.mStackRules.size()>=1);
00289 Rule* rule1 = m_store.mStackRules.top();
00290 m_store.mStackRules.pop();
00291
00292 Rule* outRule = new NotRule(string(a,b),rule1);
00293
00294
00295 m_store.mStackRules.push(outRule);
00296 }
00297 };
00298
00299 struct my_do_any : public mySemantic
00300 {
00301 my_do_any(ParserStore& rp) : mySemantic(rp) {};
00302 void operator()(char const* , char const* ) const{
00303
00304
00305 m_store.mStackRules.push(new AnyRule);
00306 }
00307 };
00308
00309 struct my_do_none : public mySemantic
00310 {
00311 my_do_none(ParserStore& rp) : mySemantic(rp) {};
00312 void operator()(char const* , char const* ) const{
00313
00314
00315 m_store.mStackRules.push(new NoneRule);
00316 }
00317 };
00318
00319
00320
00322
00323
00324
00326
00327 struct ruleparser : public grammar<ruleparser>
00328 {
00329 ruleparser(ParserStore& s, ParameterList pars)
00330 : m_store(s)
00331 , m_pars(pars) {};
00332 ParserStore &m_store;
00333 ParameterList m_pars;
00334
00335 template <typename ScannerT>
00336 struct definition
00337 {
00338 definition(const ruleparser& self)
00339 {
00340
00341 static unitlist sUnitlist;
00342 const unitlist::UnitList_t& ulist = sUnitlist();
00343 unitlist::UnitList_t::const_iterator it = ulist.begin();
00344 for( ; it != ulist.end(); ++it ){
00345 unit_symbols.add(it->first.begin(),it->first.end(),it->second);
00346 }
00347
00348
00349 value_real
00350 = (real_p[my_do_double(self.m_store)] >> unit_symbols[my_do_unit(self.m_store)][debugprint("unit")])
00351 [my_do_double_with_unit(self.m_store)][debugprint("realvalue-with-unit")]
00352 | (real_p[my_do_double(self.m_store)])[debugprint("realvalue")]
00353 ;
00354
00355
00356 value_string
00357 = ch_p('\'') >> (*(alnum_p | ch_p('/') | ch_p('-')| ch_p('_')))[my_do_string(self.m_store)][debugprint("stringvalue")] >> ch_p('\'')
00358 ;
00359
00360 custom_comparison = nothing_p;
00361
00362 for(unsigned int i=0; i<self.m_pars.size(); i++) {
00363 const ParameterDescription& par = self.m_pars[i];
00364
00365
00366
00367 std::string temp = par.name();
00368 for(std::string::iterator c = temp.begin(); c!= temp.end(); ++c) *c = tolower(*c);
00369 self.m_store.mTempStack.push(temp);
00370 std::string& parname = self.m_store.mTempStack.top();
00371
00372
00373 if( par.factory() ) {
00374
00375
00376 for(unsigned int iop=0; iop < par.operators().size(); ++iop){
00377 std::string temp = par.operators()[iop];
00378
00379 for(std::string::iterator c = temp.begin(); c!= temp.end(); ++c) *c = tolower(*c);
00380 self.m_store.mTempStack.push(temp);
00381 std::string& op = self.m_store.mTempStack.top();
00382
00383
00384 if(par.type() == typeid(double).name()){
00385 custom_comparison
00386 = ( as_lower_d[parname.c_str()]
00387 >> as_lower_d[op.c_str()]
00388 >> value_real
00389 ) [my_do_custom<double>(self.m_store,par,iop,true)]
00390
00391 | ( value_real
00392 >> as_lower_d[op.c_str()]
00393 >> as_lower_d[parname.c_str()]
00394 ) [my_do_custom<double>(self.m_store,par,iop,false)]
00395
00396 | custom_comparison.copy()
00397 ;
00398 }
00399
00400
00401 else {
00402 custom_comparison
00403 = ( as_lower_d[parname.c_str()]
00404 >> as_lower_d[op.c_str()]
00405 >> value_string
00406 ) [my_do_custom<string>(self.m_store,par,iop,true)]
00407
00408 | ( value_string
00409 >> as_lower_d[op.c_str()]
00410 >> as_lower_d[parname.c_str()]
00411 ) [my_do_custom<string>(self.m_store,par,iop,false)]
00412
00413 | custom_comparison.copy()
00414 ;
00415 }
00416
00417
00418 }
00419
00420 } else {
00421
00422
00423 if(par.type() == typeid(double).name())
00424 parlist_real.add(parname.begin(), parname.end(), par);
00425 else
00426 parlist_string.add(parname.begin(), parname.end(), par);
00427 }
00428 };
00429
00430
00431 par_real = as_lower_d[parlist_real[my_do_param(self.m_store)]];
00432 par_string = as_lower_d[parlist_string[my_do_param(self.m_store)]];
00433
00434
00435
00436 operators_num
00437 = str_p("<=" )
00438 | str_p(">=")
00439 | str_p("<" )
00440 | str_p(">")
00441 | str_p("==")
00442 | str_p("=" )
00443 | str_p("!=")
00444 ;
00445
00446
00447 operators_string
00448 = str_p("==" )
00449 | str_p("=")
00450 | str_p("!=")
00451 ;
00452
00453 basic_lefthand_comparison
00454 = (par_real >> operators_num [my_do_operator(self.m_store)] >> value_real )[my_do_simple_comparison<double>(self.m_store,true)]
00455 | (par_string >> operators_string[my_do_operator(self.m_store)] >> value_string)[my_do_simple_comparison<string>(self.m_store,true)]
00456 ;
00457
00458 basic_righthand_comparison
00459 = (
00460 (value_real >> operators_num [my_do_operator(self.m_store)] >> par_real )[my_do_simple_comparison<double>(self.m_store,false)]
00461 | (value_string >> operators_string[my_do_operator(self.m_store)] >> par_string)[my_do_simple_comparison<string>(self.m_store,false)]
00462 );
00463
00464
00465 comparison
00466 = basic_lefthand_comparison[debugprint("lefthand-comparison")]
00467 | basic_righthand_comparison[debugprint("righthand-comparison")]
00468 | custom_comparison[debugprint("custom-comparison")]
00469 ;
00470
00471
00472 expression
00473 = (term >>
00474 !( ((as_lower_d["and"]|str_p("&&")) >> term)[my_do_and(self.m_store)][debugprint("do-and")]
00475 | ((as_lower_d["or"] |str_p("||")) >> term)[my_do_or(self.m_store)][debugprint("do-or")]
00476 )
00477 )[debugprint("expression")]
00478 ;
00479
00480
00481 term
00482 = (as_lower_d["any"] | as_lower_d["all"] )[my_do_any(self.m_store)]
00483 | ( as_lower_d["none"]| as_lower_d["nothing"])[my_do_none(self.m_store)]
00484 | comparison[debugprint("comparison-as-term")]
00485 | ('(' >> expression >> ')')[debugprint("expression-as-term")]
00486 | ((as_lower_d["not"]|str_p("!")) >> term)[my_do_not(self.m_store)][debugprint("do-not")][debugprint("not-as-term")]
00487 ;
00488
00489
00490
00491 my_grammar
00492 = expression >> end_p
00493 ;
00494 }
00495
00496 symbols<ParameterDescription> parlist_real;
00497 symbols<ParameterDescription> parlist_int;
00498 symbols<ParameterDescription> parlist_string;
00499 symbols<double> unit_symbols;
00500 stored_rule<ScannerT> custom_comparison;
00501 rule<ScannerT> operators_num;
00502 rule<ScannerT> operators_string;
00503 rule<ScannerT> par_real, par_int, par_string;
00504 rule<ScannerT> value_real, value_int, value_string;
00505 rule<ScannerT> basic_lefthand_comparison, basic_righthand_comparison;
00506 rule<ScannerT> comparison, term, selection, expression;
00507 rule<ScannerT> my_grammar;
00508 const rule<ScannerT>&
00509 start() const { return my_grammar; }
00510 };
00511 };
00512
00513
00514
00515
00517
00518
00519
00521
00522 bool RuleParser::CreateRules(
00523 const std::string& inString,
00524 const ParameterList& inParameters,
00525 Rule* &outRule
00526 )
00527 {
00532
00533 ParserStore store;
00534 ruleparser rp(store,inParameters);
00535
00536
00537 outRule = 0;
00538
00539 if(inString.empty()) {
00540
00541 outRule = new NoneRule;
00542 }
00543
00544 store.clear();
00545
00546
00547 parse_info<> info = parse(inString.c_str(), rp, space_p);
00548
00549 if (info.full)
00550 {
00551 outRule = store.mStackRules.top();
00552 return true;
00553 }
00554 cerr << "-------------------------\n";
00555 cerr << "Parsing failed\n";
00556 cerr << "stopped at: \"" << info.stop << "\"\n";
00557 cerr << "-------------------------\n";
00558 return false;
00559 }
00560