1 /*
2 <pre>
3                __________                                 ____  ___
4     _____  __ _\______   \_____ _______  ______ __________\   \/  /
5    /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
6   |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
7   |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
8         \/                     \/           \/     \/           \_/
9                                        Copyright (C) 2016 Ingo Berg
10                                        All rights reserved.
11 
12   muParserX - A C++ math parser library with array and string support
13   Copyright (c) 2016, Ingo Berg
14   All rights reserved.
15 
16   Redistribution and use in source and binary forms, with or without
17   modification, are permitted provided that the following conditions are met:
18 
19    * Redistributions of source code must retain the above copyright notice,
20      this list of conditions and the following disclaimer.
21    * Redistributions in binary form must reproduce the above copyright notice,
22      this list of conditions and the following disclaimer in the documentation
23      and/or other materials provided with the distribution.
24 
25   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28   IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34   POSSIBILITY OF SUCH DAMAGE.
35 </pre>
36 */
37 #ifndef MUP_ITOKEN_H
38 #define MUP_ITOKEN_H
39 
40 #include <list>
41 #include "mpTypes.h"
42 #include "mpFwdDecl.h"
43 
44 MUP_NAMESPACE_START
45 
46   //------------------------------------------------------------------------------
47   /** \brief Generic token interface for expression tokens.
48       \author (C) 2010 Ingo Berg
49 
50       Tokens can either be Functions, operators, values, variables or necessary
51       base tokens like brackets. ´The IToken baseclass implements reference
52       counting. Only TokenPtr<...> templates may be used as pointers to tokens.
53   */
54   class IToken
55   {
56   friend std::ostream& operator<<(std::ostream &a_Stream, const IToken &a_Val);
57   friend std::wostream& operator<<(std::wostream &a_Stream, const IToken &a_Val);
58 
59   friend class TokenPtr<IToken>;
60   friend class TokenPtr<IValue>;
61   friend class TokenPtr<IOprtBin>;
62   friend class TokenPtr<IOprtInfix>;
63   friend class TokenPtr<IOprtPostfix>;
64   friend class TokenPtr<IFunction>;
65   friend class TokenPtr<Value>;
66   friend class TokenPtr<Variable>;
67   friend class TokenPtr<ICallback>;
68   friend class TokenPtr<IOprtBinShortcut>;
69 
70   public:
71 
72     enum EFlags
73     {
74       flNONE = 0,
75       flVOLATILE = 1
76     };
77 
78     virtual IToken* Clone() const = 0;
79     virtual string_type ToString() const;
80     virtual string_type AsciiDump() const;
81 
82     virtual ICallback* AsICallback();
83     virtual IValue* AsIValue();
84     virtual IPrecedence* AsIPrecedence();
85 
86     virtual void Compile(const string_type &sArg);
87 
88     ECmdCode GetCode() const;
89     int GetExprPos() const;
90 
91     const string_type& GetIdent() const;
92     long GetRef() const;
93     void SetIdent(const string_type &a_sIdent);
94     void SetExprPos(int nPos);
95 
96     void AddFlags(int flags);
97     bool IsFlagSet(int flags) const;
98 
99   protected:
100 
101     explicit IToken(ECmdCode a_iCode);
102     virtual ~IToken();
103     IToken(ECmdCode a_iCode, string_type a_sIdent);
104     IToken(const IToken &ref);
105 
106     void ResetRef();
107 
108   private:
109 
110     /** \brief Release the token.
111 
112       This Function either deletes the token or releases it to
113       the value cache for reuse without deletion.
114     */
115     virtual void Release();
116 
117     void IncRef() const;
118     long DecRef() const;
119 
120     ECmdCode m_eCode;
121     string_type m_sIdent;
122     int m_nPosExpr;           ///< Original position of the token in the expression
123     mutable long m_nRefCount; ///< Reference counter.
124     int m_flags;
125 
126 #ifdef MUP_LEAKAGE_REPORT
127     static std::list<IToken*> s_Tokens;
128 
129   public:
130     static void LeakageReport();
131 #endif
132   };
133 
134 
135   //---------------------------------------------------------------------------
136   /** \brief Default token implentation.
137   */
138   class GenericToken : public IToken
139   {
140   public:
141       GenericToken(ECmdCode a_iCode, string_type a_sIdent);
142       explicit GenericToken(ECmdCode a_iCode);
143       GenericToken(const GenericToken &a_Tok);
144       virtual ~GenericToken();
145       virtual IToken* Clone() const;
146       virtual string_type AsciiDump() const;
147   };
148 
149   //------------------------------------------------------------------------------
150   template<typename T>
151   class TokenPtr
152   {
153   public:
154 
155       typedef T* token_type;
156 
157       //---------------------------------------------------------------------------
158       TokenPtr(token_type p = 0)
m_pTok(p)159         :m_pTok(p)
160       {
161         if (m_pTok)
162           m_pTok->IncRef();
163       }
164 
165       //---------------------------------------------------------------------------
TokenPtr(const TokenPtr & p)166       TokenPtr(const TokenPtr &p)
167         :m_pTok(p.m_pTok)
168       {
169         if (m_pTok)
170           m_pTok->IncRef();
171       }
172 
173       //---------------------------------------------------------------------------
~TokenPtr()174      ~TokenPtr()
175       {
176         if (m_pTok && m_pTok->DecRef()==0)
177           m_pTok->Release();
178       }
179 
180       //---------------------------------------------------------------------------
181       token_type operator->() const
182       {
183         return static_cast<token_type>(m_pTok);
184       }
185 
186       //---------------------------------------------------------------------------
187       T& operator*() const
188       {
189         assert(m_pTok);
190         return *(static_cast<token_type>(m_pTok));
191       }
192 
193       //---------------------------------------------------------------------------
Get()194       token_type Get() const
195       {
196         return static_cast<token_type>(m_pTok);
197       }
198 
199       //---------------------------------------------------------------------------
200       /** \brief Release the managed pointer and assign a new pointer. */
Reset(token_type tok)201       void Reset(token_type tok)
202       {
203         if (m_pTok && m_pTok->DecRef()==0)
204         {
205           m_pTok->Release();
206           //delete m_pTok;
207         }
208 
209         tok->IncRef();
210         m_pTok = tok;
211       }
212 
213       //---------------------------------------------------------------------------
214       TokenPtr& operator=(const TokenPtr &p)
215       {
216         if (p.m_pTok)
217           p.m_pTok->IncRef();
218 
219         if (m_pTok && m_pTok->DecRef()==0)
220         {
221           m_pTok->Release();
222           //delete m_pTok;
223         }
224 
225         m_pTok = p.m_pTok;
226 
227         return *this;
228       }
229 
230   private:
231       IToken *m_pTok;
232   };
233 
234 MUP_NAMESPACE_END
235 
236 #endif // include guard
237