1 /* 2 __________ 3 _____ __ __\______ \_____ _______ ______ ____ _______ 4 / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ 5 | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ 6 |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| 7 \/ \/ \/ \/ 8 Copyright (C) 2004-2013 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-2013 Ingo Berg 59 */ 60 template<typename TBase, typename TString> 61 class ParserToken 62 { 63 private: 64 65 ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode. 66 ETypeCode m_iType; 67 void *m_pTok; ///< Stores Token pointer; not applicable for all tokens 68 int m_iIdx; ///< An otional index to an external buffer storing the token data 69 TString m_strTok; ///< Token string 70 TString m_strVal; ///< Value for string variables 71 value_type m_fVal; ///< the value 72 std::auto_ptr<ParserCallback> m_pCallback; 73 74 public: 75 76 //--------------------------------------------------------------------------- 77 /** \brief Constructor (default). 78 79 Sets token to an neutral state of type cmUNKNOWN. 80 \throw nothrow 81 \sa ECmdCode 82 */ ParserToken()83 ParserToken() 84 :m_iCode(cmUNKNOWN) 85 ,m_iType(tpVOID) 86 ,m_pTok(0) 87 ,m_iIdx(-1) 88 ,m_strTok() 89 ,m_strVal() 90 ,m_fVal(0) 91 ,m_pCallback() 92 {} 93 94 //------------------------------------------------------------------------------ 95 /** \brief Create token from another one. 96 97 Implemented by calling Assign(...) 98 \throw nothrow 99 \post m_iType==cmUNKNOWN 100 \sa #Assign 101 */ ParserToken(const ParserToken & a_Tok)102 ParserToken(const ParserToken &a_Tok) 103 { 104 Assign(a_Tok); 105 } 106 107 //------------------------------------------------------------------------------ 108 /** \brief Assignement operator. 109 110 Copy token state from another token and return this. 111 Implemented by calling Assign(...). 112 \throw nothrow 113 */ 114 ParserToken& operator=(const ParserToken &a_Tok) 115 { 116 Assign(a_Tok); 117 return *this; 118 } 119 120 //------------------------------------------------------------------------------ 121 /** \brief Copy token information from argument. 122 123 \throw nothrow 124 */ Assign(const ParserToken & a_Tok)125 void Assign(const ParserToken &a_Tok) 126 { 127 m_iCode = a_Tok.m_iCode; 128 m_pTok = a_Tok.m_pTok; 129 m_strTok = a_Tok.m_strTok; 130 m_iIdx = a_Tok.m_iIdx; 131 m_strVal = a_Tok.m_strVal; 132 m_iType = a_Tok.m_iType; 133 m_fVal = a_Tok.m_fVal; 134 // create new callback object if a_Tok has one 135 m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0); 136 } 137 138 //------------------------------------------------------------------------------ 139 /** \brief Assign a token type. 140 141 Token may not be of type value, variable or function. Those have seperate set functions. 142 143 \pre [assert] a_iType!=cmVAR 144 \pre [assert] a_iType!=cmVAL 145 \pre [assert] a_iType!=cmFUNC 146 \post m_fVal = 0 147 \post m_pTok = 0 148 */ 149 ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString()) 150 { 151 // The following types cant be set this way, they have special Set functions 152 assert(a_iType!=cmVAR); 153 assert(a_iType!=cmVAL); 154 assert(a_iType!=cmFUNC); 155 156 m_iCode = a_iType; 157 m_iType = tpVOID; 158 m_pTok = 0; 159 m_strTok = a_strTok; 160 m_iIdx = -1; 161 162 return *this; 163 } 164 165 //------------------------------------------------------------------------------ 166 /** \brief Set Callback type. */ Set(const ParserCallback & a_pCallback,const TString & a_sTok)167 ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok) 168 { 169 assert(a_pCallback.GetAddr()); 170 171 m_iCode = a_pCallback.GetCode(); 172 m_iType = tpVOID; 173 m_strTok = a_sTok; 174 m_pCallback.reset(new ParserCallback(a_pCallback)); 175 176 m_pTok = 0; 177 m_iIdx = -1; 178 179 return *this; 180 } 181 182 //------------------------------------------------------------------------------ 183 /** \brief Make this token a value token. 184 185 Member variables not necessary for value tokens will be invalidated. 186 \throw nothrow 187 */ 188 ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString()) 189 { 190 m_iCode = cmVAL; 191 m_iType = tpDBL; 192 m_fVal = a_fVal; 193 m_strTok = a_strTok; 194 m_iIdx = -1; 195 196 m_pTok = 0; 197 m_pCallback.reset(0); 198 199 return *this; 200 } 201 202 //------------------------------------------------------------------------------ 203 /** \brief make this token a variable token. 204 205 Member variables not necessary for variable tokens will be invalidated. 206 \throw nothrow 207 */ SetVar(TBase * a_pVar,const TString & a_strTok)208 ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok) 209 { 210 m_iCode = cmVAR; 211 m_iType = tpDBL; 212 m_strTok = a_strTok; 213 m_iIdx = -1; 214 m_pTok = (void*)a_pVar; 215 m_pCallback.reset(0); 216 return *this; 217 } 218 219 //------------------------------------------------------------------------------ 220 /** \brief Make this token a variable token. 221 222 Member variables not necessary for variable tokens will be invalidated. 223 \throw nothrow 224 */ SetString(const TString & a_strTok,std::size_t a_iSize)225 ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize) 226 { 227 m_iCode = cmSTRING; 228 m_iType = tpSTR; 229 m_strTok = a_strTok; 230 m_iIdx = static_cast<int>(a_iSize); 231 232 m_pTok = 0; 233 m_pCallback.reset(0); 234 return *this; 235 } 236 237 //------------------------------------------------------------------------------ 238 /** \brief Set an index associated with the token related data. 239 240 In cmSTRFUNC - This is the index to a string table in the main parser. 241 \param a_iIdx The index the string function result will take in the bytecode parser. 242 \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING 243 */ SetIdx(int a_iIdx)244 void SetIdx(int a_iIdx) 245 { 246 if (m_iCode!=cmSTRING || a_iIdx<0) 247 throw ParserError(ecINTERNAL_ERROR); 248 249 m_iIdx = a_iIdx; 250 } 251 252 //------------------------------------------------------------------------------ 253 /** \brief Return Index associated with the token related data. 254 255 In cmSTRFUNC - This is the index to a string table in the main parser. 256 257 \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING 258 \return The index the result will take in the Bytecode calculatin array (#m_iIdx). 259 */ GetIdx()260 int GetIdx() const 261 { 262 if (m_iIdx<0 || m_iCode!=cmSTRING ) 263 throw ParserError(ecINTERNAL_ERROR); 264 265 return m_iIdx; 266 } 267 268 //------------------------------------------------------------------------------ 269 /** \brief Return the token type. 270 271 \return #m_iType 272 \throw nothrow 273 */ GetCode()274 ECmdCode GetCode() const 275 { 276 if (m_pCallback.get()) 277 { 278 return m_pCallback->GetCode(); 279 } 280 else 281 { 282 return m_iCode; 283 } 284 } 285 286 //------------------------------------------------------------------------------ GetType()287 ETypeCode GetType() const 288 { 289 if (m_pCallback.get()) 290 { 291 return m_pCallback->GetType(); 292 } 293 else 294 { 295 return m_iType; 296 } 297 } 298 299 //------------------------------------------------------------------------------ GetPri()300 int GetPri() const 301 { 302 if ( !m_pCallback.get()) 303 throw ParserError(ecINTERNAL_ERROR); 304 305 if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX) 306 throw ParserError(ecINTERNAL_ERROR); 307 308 return m_pCallback->GetPri(); 309 } 310 311 //------------------------------------------------------------------------------ GetAssociativity()312 EOprtAssociativity GetAssociativity() const 313 { 314 if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN) 315 throw ParserError(ecINTERNAL_ERROR); 316 317 return m_pCallback->GetAssociativity(); 318 } 319 320 //------------------------------------------------------------------------------ 321 /** \brief Return the address of the callback function assoziated with 322 function and operator tokens. 323 324 \return The pointer stored in #m_pTok. 325 \throw exception_type if token type is non of: 326 <ul> 327 <li>cmFUNC</li> 328 <li>cmSTRFUNC</li> 329 <li>cmPOSTOP</li> 330 <li>cmINFIXOP</li> 331 <li>cmOPRT_BIN</li> 332 </ul> 333 \sa ECmdCode 334 */ GetFuncAddr()335 generic_fun_type GetFuncAddr() const 336 { 337 return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0; 338 } 339 340 //------------------------------------------------------------------------------ 341 /** \biref Get value of the token. 342 343 Only applicable to variable and value tokens. 344 \throw exception_type if token is no value/variable token. 345 */ GetVal()346 TBase GetVal() const 347 { 348 switch (m_iCode) 349 { 350 case cmVAL: return m_fVal; 351 case cmVAR: return *((TBase*)m_pTok); 352 default: throw ParserError(ecVAL_EXPECTED); 353 } 354 } 355 356 //------------------------------------------------------------------------------ 357 /** \brief Get address of a variable token. 358 359 Valid only if m_iType==CmdVar. 360 \throw exception_type if token is no variable token. 361 */ GetVar()362 TBase* GetVar() const 363 { 364 if (m_iCode!=cmVAR) 365 throw ParserError(ecINTERNAL_ERROR); 366 367 return (TBase*)m_pTok; 368 } 369 370 //------------------------------------------------------------------------------ 371 /** \brief Return the number of function arguments. 372 373 Valid only if m_iType==CmdFUNC. 374 */ GetArgCount()375 int GetArgCount() const 376 { 377 assert(m_pCallback.get()); 378 379 if (!m_pCallback->GetAddr()) 380 throw ParserError(ecINTERNAL_ERROR); 381 382 return m_pCallback->GetArgc(); 383 } 384 385 //------------------------------------------------------------------------------ 386 /** \brief Return the token identifier. 387 388 If #m_iType is cmSTRING the token identifier is the value of the string argument 389 for a string function. 390 \return #m_strTok 391 \throw nothrow 392 \sa m_strTok 393 */ GetAsString()394 const TString& GetAsString() const 395 { 396 return m_strTok; 397 } 398 }; 399 } // namespace mu 400 401 #endif 402