00001
00007 #ifndef ___EXPRESSIONPARSER_H___
00008 #define ___EXPRESSIONPARSER_H___
00009
00010 #include "../src/exprparser.h"
00011 #include "../src/pointerlookup.h"
00012
00013 #ifdef ANSI_COMPATIBLE
00014
00015 #include "../src/ind_types.h"
00016 #endif
00017
00018
00020 template <class MapT=PointerLookup<Typeless> >
00021 class ExpressionParser : public ExprParser<> {
00022 public:
00023 typedef MapT MapType;
00024
00025 ExpressionParser(MapType& p,const char* expr)
00026 : ExprParser<>(expr), params(p) { };
00027
00028 virtual ~ExpressionParser() { }
00029
00030 template <class DT> DT* lookup_pointer(DT*& x);
00031
00032 private:
00033
00034 virtual const char* getstringval();
00035 virtual const Typeless& getval();
00036
00037 MapType& params;
00038 };
00039
00040
00041
00045 template <class MapT>
00046 template <class DT>
00047 DT* ExpressionParser<MapT>::lookup_pointer(DT*& x)
00048 {
00049 Typeless* p = params.getptr(remaining);
00050 Polymorph<DT>* pp = dynamic_cast<Polymorph<DT>*>(p);
00051 return x = (pp ? pp->valueptr() : 0);
00052 }
00053
00054
00055
00065 template <class MapT>
00066 const Typeless& ExpressionParser<MapT>::getval()
00067 {
00068 const char* str = remaining;
00069 int identlen = String::C_identifier_length(str,':');
00070 size_t checklen = identlen;
00071
00072 if (!identlen)
00073 return ExprParser<>::getval();
00074
00075
00076 const Typeless* p=0;
00077 p = params.getptr(string(str,checklen));
00078 remaining=str+identlen;
00079 if (p) return *p;
00080 else {
00081 static Polymorph<int> dummy(Uninitialized);
00082 return dummy;
00083 }
00084 }
00085
00086
00087
00101 template <class MapT>
00102 const char *ExpressionParser<MapT>::getstringval()
00103 {
00104 const size_t bufsize=16384;
00105 static char buf[bufsize];
00106 const char* maxbufptr=buf+bufsize;
00107
00108 char* bufptr=buf;
00109 int identlen;
00110
00111 const char* str = remaining;
00112 while (remaining && *remaining && bufptr<maxbufptr) {
00113
00114 while (*remaining && *remaining != '$' && bufptr<maxbufptr)
00115 *(bufptr++) = *(remaining)++;
00116
00117
00118 if (*remaining == '$') {
00119 (remaining)++;
00120 if (*remaining == '$')
00121 *(bufptr++) = *(remaining)++;
00122 else {
00123 int bracefound=false;
00124 string formatflags="";
00125 if (*remaining == '{') {
00126 bracefound=true;
00127 (remaining)++;
00128 }
00129
00130
00131
00132 bool conditional=false;
00133 if (*remaining=='?') {
00134 (remaining)++;
00135 conditional=true;
00136 }
00137
00138
00139 if (!isalpha(*remaining) && (*remaining)!=':') {
00140 const char *start=remaining;
00141 while (*remaining && !isalpha(*remaining))
00142 (remaining)++;
00143 formatflags=string(start,remaining);
00144 }
00145
00146
00147 identlen = String::C_identifier_length(remaining,':');
00148
00149
00150 const Typeless* p = params.getptr(string(remaining,identlen));
00151 remaining +=identlen;
00152 const string representation=p->stringrep(String::StreamFormat(formatflags));
00153
00154
00155 if (p) {
00156 if (!conditional)
00157 bufptr += SNPRINTF(bufptr,maxbufptr-bufptr,"%s",representation.c_str());
00158 else {
00159 if (*remaining==',' && bracefound) {
00160 (remaining)++;
00161
00162 const char *start=remaining;
00163 while (*remaining && !(*remaining=='}'))
00164 (remaining)++;
00165 const string replacetext=string(start,remaining);
00166
00167
00168 if (p->isnumeric()? p->numericvalue()!=0 : representation!="")
00169 bufptr += SNPRINTF(bufptr,maxbufptr-bufptr,"%s",replacetext.c_str());
00170 }
00171
00172 else if (p->isnumeric()? p->numericvalue()!=0 : representation!="")
00173 bufptr += SNPRINTF(bufptr,maxbufptr-bufptr,"%s",representation.c_str());
00174 }
00175 }
00176
00177 if (bracefound) {
00178 if (*remaining == '}')
00179 (remaining)++;
00180 else
00181 message(Msg::Warning,"Missing right brace in "+string(str));
00182 }
00183 }
00184 }
00185 }
00186 *bufptr='\0';
00187
00188 return buf;
00189 }
00190
00191
00192
00193
00198 template <class MapT=PointerLookup<Typeless>, class ParserT=ExpressionParser<MapT> >
00199 class ParamStringParser : public StringParser {
00200 public:
00201 typedef ParserT ParserType;
00202 typedef MapT MapType;
00203
00204 ParamStringParser(MapType& m) : params(m) { };
00205
00206 virtual ~ParamStringParser() { }
00207 virtual StringParser* clone() const { return new ParamStringParser(*this); };
00208
00209 virtual double& parse(const string& s, double& x) const { return x = parserfactory(s.c_str()).cmdf(); }
00210 virtual int& parse(const string& s, int& x) const { return x = parserfactory(s.c_str()).cmdi(); }
00211 virtual Tristate& parse(const string& s, Tristate& x) const { return x = Tristate(parserfactory(s.c_str()).cmdi()); }
00212 virtual string& parse(const string& s, string& x) const { return x = parserfactory(s.c_str()).cmds(); }
00213
00214 virtual double*& parse(const string& s, double*& x) const { return x = parse_pointer(s,x); }
00215 virtual int*& parse(const string& s, int*& x) const { return x = parse_pointer(s,x); }
00216 virtual Tristate*& parse(const string& s, Tristate*& x) const { return x = parse_pointer(s,x); }
00217 virtual string*& parse(const string& s, string*& x) const { return x = parse_pointer(s,x); }
00218
00219
00220
00221
00222 virtual string parse(const string& s) const
00223 { return StringParser::parse(s); }
00224
00225
00226
00227
00228 virtual arglist& parse(const string& s, arglist& x) const {
00229 x.resize(0);
00230 const char* remaining = s.c_str();
00231 while (*remaining)
00232 x.push_back(parse_token(remaining));
00233 return x;
00234 }
00235
00236 virtual void error(const string& s) const {
00237 Msg::LevelHandler<>* mh = Msg::LevelHandler<>::default_instance();
00238 if (mh) (*mh)(Msg::Error,s);
00239 }
00240
00241 private:
00242 MapType& params;
00243
00244 string parse_token( const char*& remaining) const;
00245 const char* consume_quote(const char*& remaining) const;
00246
00252 ParserType parserfactory(const char* expr) const
00253 { return ParserType(params,expr); }
00254
00271
00272 #define PARSE_POINTER_DEF(T)\
00273 T*& parse_pointer(const string& s, T*& x) const { \
00274 if (!ispointer(s)) \
00275 parse(s,*x); \
00276 else { \
00277 T* ptr; \
00278 parserfactory(s.c_str()+1).lookup_pointer(ptr); \
00279 if (ptr) x=ptr; \
00280 else error("StringParser: Could not get a " \
00281 "pointer of required type from "+s); \
00282 } \
00283 return x; \
00284 }
00285
00286 PARSE_POINTER_DEF(double);
00287 PARSE_POINTER_DEF(int);
00288 PARSE_POINTER_DEF(Tristate);
00289 PARSE_POINTER_DEF(string);
00290
00291
00292 virtual bool ispointer(const string& s) const {
00293 std::istrstream ist(s.c_str(),s.length());
00294 unsigned char w;
00295 ist >> w;
00296 return (w == '&');
00297 }
00298 };
00299
00300
00302 template <class MapT, class ParserT>
00303 const char* ParamStringParser<MapT,ParserT>::consume_quote(const char*& remaining) const {
00304 const char* quotepos=remaining;
00305 while (*(++(remaining)) && (*remaining!=*quotepos));
00306 const char* end=remaining;
00307 if (!*remaining) {
00308 string q;
00309 q=*quotepos;
00310 error("Unmatched " + q);
00311 }
00312 else (remaining)++;
00313 return end;
00314 }
00315
00317 template <class MapT, class ParserT>
00318 string ParamStringParser<MapT,ParserT>::parse_token(const char*& remaining) const {
00319 while (isspace(*remaining)) (remaining)++;
00320 const char* start=remaining;
00321 const char* end=remaining;
00322
00323 switch (*remaining) {
00324 case '\0': break;
00325 case '#': while (*(++(remaining))); start=end=(remaining); break;
00326 case '\"': start++; end=consume_quote(remaining); break;
00327 case '\'': start++; end=consume_quote(remaining); break;
00328 default:
00329 while (*(++(remaining)) && !isspace(*remaining) &&
00330 (*remaining!='"') && (*remaining!='\''));
00331 if (*remaining=='"' || *remaining=='\'') consume_quote(remaining);
00332 end=remaining;
00333 break;
00334 }
00335
00336
00337
00338 while (isspace(*remaining)) (remaining)++;
00339 return string(start,end);
00340 }
00341
00342
00343 #endif