1 /* 2 __________ 3 _____ __ __\______ \_____ _______ ______ ____ _______ 4 / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ 5 | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ 6 |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| 7 \/ \/ \/ \/ 8 Copyright (C) 2004-2008 Ingo Berg 9 10 Permission is hereby granted, free of charge, to any person obtaining a copy of this 11 software and associated documentation files (the "Software"), to deal in the Software 12 without restriction, including without limitation the rights to use, copy, modify, 13 merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 14 permit persons to whom the Software is furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in all copies or 17 substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 20 NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 #ifndef MU_PARSER_TOKEN_H 27 #define MU_PARSER_TOKEN_H 28 29 #include <cassert> 30 #include <string> 31 #include <stack> 32 #include <vector> 33 #include <memory> 34 35 #include "muParserError.h" 36 #include "muParserCallback.h" 37 38 /** \file 39 \brief This file contains the parser token definition. 40 */ 41 42 namespace mu 43 { 44 /** \brief Encapsulation of the data for a single formula token. 45 46 Formula token implementation. Part of the Math Parser Package. 47 Formula tokens can be either one of the following: 48 <ul> 49 <li>value</li> 50 <li>variable</li> 51 <li>function with numerical arguments</li> 52 <li>functions with a string as argument</li> 53 <li>prefix operators</li> 54 <li>infix operators</li> 55 <li>binary operator</li> 56 </ul> 57 58 \author (C) 2004 Ingo Berg 59 */ 60 template<typename TBase, typename TString> 61 class ParserToken 62 { 63 public: 64 65 /** \brief Additional token flags. */ 66 enum ETokFlags 67 { 68 flVOLATILE = 1 ///< Mark a token that depends on a variable or a function that is not conservative 69 }; 70 71 private: 72 73 ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode. 74 ETypeCode m_iType; 75 void *m_pTok; ///< Stores Token pointer; not applicable for all tokens 76 int m_iFlags; ///< Additional flags for the token. 77 int m_iIdx; ///< An otional index to an external buffer storing the token data 78 TString m_strTok; ///< Token string 79 TString m_strVal; ///< Value for string variables 80 value_type m_fVal; 81 std::auto_ptr<ParserCallback> m_pCallback; 82 83 public: 84 85 //--------------------------------------------------------------------------- 86 /** \brief Constructor (default). 87 88 Sets token to an neutral state of type cmUNKNOWN. 89 \throw nothrow 90 \sa ECmdCode 91 */ ParserToken()92 ParserToken() 93 :m_iCode(cmUNKNOWN) 94 ,m_iType(tpVOID) 95 ,m_pTok(0) 96 ,m_iFlags(0) 97 ,m_iIdx(-1) 98 ,m_strTok() 99 ,m_pCallback() 100 {} 101 102 //------------------------------------------------------------------------------ 103 /** \brief Create token from another one. 104 105 Implemented by calling Assign(...) 106 \throw nothrow 107 \post m_iType==cmUNKNOWN 108 \sa #Assign 109 */ ParserToken(const ParserToken & a_Tok)110 ParserToken(const ParserToken &a_Tok) 111 { 112 Assign(a_Tok); 113 } 114 115 //------------------------------------------------------------------------------ 116 /** \brief Assignement operator. 117 118 Copy token state from another token and return this. 119 Implemented by calling Assign(...). 120 \throw nothrow 121 */ 122 ParserToken& operator=(const ParserToken &a_Tok) 123 { 124 Assign(a_Tok); 125 return *this; 126 } 127 128 //------------------------------------------------------------------------------ 129 /** \brief Copy token information from argument. 130 131 \throw nothrow 132 */ Assign(const ParserToken & a_Tok)133 void Assign(const ParserToken &a_Tok) 134 { 135 m_iCode = a_Tok.m_iCode; 136 m_pTok = a_Tok.m_pTok; 137 m_iFlags = a_Tok.m_iFlags; 138 m_strTok = a_Tok.m_strTok; 139 m_iIdx = a_Tok.m_iIdx; 140 m_strVal = a_Tok.m_strVal; 141 m_iType = a_Tok.m_iType; 142 m_fVal = a_Tok.m_fVal; 143 // create new callback object if a_Tok has one 144 m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0); 145 } 146 147 //------------------------------------------------------------------------------ 148 /** \brief Add additional flags to the token. 149 150 Flags are currently used to mark volatile (non optimizeable) functions. 151 \sa m_iFlags, ETokFlags 152 */ AddFlags(int a_iFlags)153 void AddFlags(int a_iFlags) 154 { 155 m_iFlags |= a_iFlags; 156 } 157 158 //------------------------------------------------------------------------------ 159 /** \brief Check if a certain flag ist set. 160 161 \throw nothrow 162 */ IsFlagSet(int a_iFlags)163 bool IsFlagSet(int a_iFlags) const 164 { 165 #if defined(_MSC_VER) 166 #pragma warning( disable : 4800 ) 167 #endif 168 169 return (bool)(m_iFlags & a_iFlags); 170 171 #if defined(_MSC_VER) 172 #pragma warning( default : 4800 ) // int: Variable set to boolean value (may degrade performance) 173 #endif 174 } 175 176 //------------------------------------------------------------------------------ 177 /** \brief Assign a token type. 178 179 Token may not be of type value, variable or function. Those have seperate set functions. 180 181 \pre [assert] a_iType!=cmVAR 182 \pre [assert] a_iType!=cmVAL 183 \pre [assert] a_iType!=cmFUNC 184 \post m_fVal = 0 185 \post m_pTok = 0 186 */ 187 ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString()) 188 { 189 // The following types cant be set this way, they have special Set functions 190 assert(a_iType!=cmVAR); 191 assert(a_iType!=cmVAL); 192 assert(a_iType!=cmFUNC); 193 194 m_iCode = a_iType; 195 m_iType = tpVOID; 196 m_pTok = 0; 197 m_iFlags = 0; 198 m_strTok = a_strTok; 199 m_iIdx = -1; 200 201 return *this; 202 } 203 204 //------------------------------------------------------------------------------ 205 /** \brief Set Callback type. */ Set(const ParserCallback & a_pCallback,const TString & a_sTok)206 ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok) 207 { 208 assert(a_pCallback.GetAddr()); 209 210 m_iCode = a_pCallback.GetCode(); 211 m_iType = tpVOID; 212 m_strTok = a_sTok; 213 m_pCallback.reset(new ParserCallback(a_pCallback)); 214 215 m_pTok = 0; 216 m_iFlags = 0; 217 m_iIdx = -1; 218 219 if (!m_pCallback->IsOptimizable()) 220 AddFlags(flVOLATILE); 221 222 return *this; 223 } 224 225 //------------------------------------------------------------------------------ 226 /** \brief Make this token a value token. 227 228 Member variables not necessary for value tokens will be invalidated. 229 \throw nothrow 230 */ 231 ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString()) 232 { 233 m_iCode = cmVAL; 234 m_iType = tpDBL; 235 m_fVal = a_fVal; 236 m_iFlags = 0; 237 m_strTok = a_strTok; 238 m_iIdx = -1; 239 240 m_pTok = 0; 241 m_pCallback.reset(0); 242 243 return *this; 244 } 245 246 //------------------------------------------------------------------------------ 247 /** \brief make this token a variable token. 248 249 Member variables not necessary for variable tokens will be invalidated. 250 \throw nothrow 251 */ SetVar(TBase * a_pVar,const TString & a_strTok)252 ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok) 253 { 254 m_iCode = cmVAR; 255 m_iType = tpDBL; 256 m_iFlags = 0; 257 m_strTok = a_strTok; 258 m_iIdx = -1; 259 m_pTok = (void*)a_pVar; 260 m_pCallback.reset(0); 261 262 AddFlags(ParserToken::flVOLATILE); 263 return *this; 264 } 265 266 //------------------------------------------------------------------------------ 267 /** \brief Make this token a variable token. 268 269 Member variables not necessary for variable tokens will be invalidated. 270 \throw nothrow 271 */ SetString(const TString & a_strTok,std::size_t a_iSize)272 ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize) 273 { 274 m_iCode = cmSTRING; 275 m_iType = tpSTR; 276 m_iFlags = 0; 277 m_strTok = a_strTok; 278 m_iIdx = static_cast<int>(a_iSize); 279 280 m_pTok = 0; 281 m_pCallback.reset(0); 282 283 AddFlags(ParserToken::flVOLATILE); 284 return *this; 285 } 286 287 //------------------------------------------------------------------------------ 288 /** \brief Set an index associated with the token related data. 289 290 In cmSTRFUNC - This is the index to a string table in the main parser. 291 \param a_iIdx The index the string function result will take in the bytecode parser. 292 \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING 293 */ SetIdx(int a_iIdx)294 void SetIdx(int a_iIdx) 295 { 296 if (m_iCode!=cmSTRING || a_iIdx<0) 297 throw ParserError(ecINTERNAL_ERROR); 298 299 m_iIdx = a_iIdx; 300 } 301 302 //------------------------------------------------------------------------------ 303 /** \brief Return Index associated with the token related data. 304 305 In cmSTRFUNC - This is the index to a string table in the main parser. 306 307 \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING 308 \return The index the result will take in the Bytecode calculatin array (#m_iIdx). 309 */ GetIdx()310 int GetIdx() const 311 { 312 if (m_iIdx<0 || m_iCode!=cmSTRING ) 313 throw ParserError(ecINTERNAL_ERROR); 314 315 return m_iIdx; 316 } 317 318 //------------------------------------------------------------------------------ 319 /** \brief Return the token type. 320 321 \return #m_iType 322 \throw nothrow 323 */ GetCode()324 ECmdCode GetCode() const 325 { 326 if (m_pCallback.get()) 327 { 328 return m_pCallback->GetCode(); 329 } 330 else 331 { 332 return m_iCode; 333 } 334 } 335 336 //------------------------------------------------------------------------------ GetType()337 ETypeCode GetType() const 338 { 339 if (m_pCallback.get()) 340 { 341 return m_pCallback->GetType(); 342 } 343 else 344 { 345 return m_iType; 346 } 347 } 348 349 //------------------------------------------------------------------------------ GetPri()350 int GetPri() const 351 { 352 if ( !m_pCallback.get()) 353 throw ParserError(ecINTERNAL_ERROR); 354 355 if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX) 356 throw ParserError(ecINTERNAL_ERROR); 357 358 return m_pCallback->GetPri(); 359 } 360 361 //------------------------------------------------------------------------------ 362 /** \brief Return the address of the callback function assoziated with 363 function and operator tokens. 364 365 \return The pointer stored in #m_pTok. 366 \throw exception_type if token type is non of: 367 <ul> 368 <li>cmFUNC</li> 369 <li>cmSTRFUNC</li> 370 <li>cmPOSTOP</li> 371 <li>cmINFIXOP</li> 372 <li>cmOPRT_BIN</li> 373 </ul> 374 \sa ECmdCode 375 */ GetFuncAddr()376 void* GetFuncAddr() const 377 { 378 return (m_pCallback.get()) ? m_pCallback->GetAddr() : 0; 379 } 380 381 //------------------------------------------------------------------------------ 382 /** \brief Get value of the token. 383 384 Only applicable to variable and value tokens. 385 \throw exception_type if token is no value/variable token. 386 */ GetVal()387 TBase GetVal() const 388 { 389 switch (m_iCode) 390 { 391 case cmVAL: return m_fVal; 392 case cmVAR: return *((TBase*)m_pTok); 393 default: throw ParserError(ecVAL_EXPECTED); 394 } 395 } 396 397 //------------------------------------------------------------------------------ 398 /** \brief Get address of a variable token. 399 400 Valid only if m_iType==CmdVar. 401 \throw exception_type if token is no variable token. 402 */ GetVar()403 TBase* GetVar() const 404 { 405 if (m_iCode!=cmVAR) 406 throw ParserError(ecINTERNAL_ERROR); 407 408 return (TBase*)m_pTok; 409 } 410 411 //------------------------------------------------------------------------------ 412 /** \brief Return the number of function arguments. 413 414 Valid only if m_iType==CmdFUNC. 415 */ GetArgCount()416 int GetArgCount() const 417 { 418 assert(m_pCallback.get()); 419 420 if (!m_pCallback->GetAddr()) 421 throw ParserError(ecINTERNAL_ERROR); 422 423 return m_pCallback->GetArgc(); 424 } 425 426 //------------------------------------------------------------------------------ 427 /** \brief Return the token identifier. 428 429 If #m_iType is cmSTRING the token identifier is the value of the string argument 430 for a string function. 431 \return #m_strTok 432 \throw nothrow 433 \sa m_strTok 434 */ GetAsString()435 const TString& GetAsString() const 436 { 437 return m_strTok; 438 } 439 }; 440 } // namespace mu 441 442 #endif 443