File indexing completed on 2024-04-21 15:25:34

0001 /*
0002   This file is part of kdev-pg
0003   Copyright 2005, 2006 Roberto Raggi <roberto@kdevelop.org>
0004 
0005   Permission to use, copy, modify, distribute, and sell this software and its
0006   documentation for any purpose is hereby granted without fee, provided that
0007   the above copyright notice appear in all copies and that both that
0008   copyright notice and this permission notice appear in supporting
0009   documentation.
0010 
0011   The above copyright notice and this permission notice shall be included in
0012   all copies or substantial portions of the Software.
0013 
0014   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
0017   KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
0018   AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0019   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0020 */
0021 
0022 //krazy:excludeall=inline
0023 #ifndef KDEV_PG_TOKEN_STREAM_H
0024 #define KDEV_PG_TOKEN_STREAM_H
0025 
0026 #include <vector>
0027 
0028 #include "kdev-pg-location-table.h"
0029 
0030 /* T& front() ✓
0031  * T& back() ✓
0032  * T& curr()                →   ?
0033  * 
0034  * T& advance()             →   read()
0035  * qint64 tokenIndex()      →   delete
0036  * qint64 index() ✓
0037  * T& next()                →   push(), push(Token)
0038  * int nextToken()          →   delete
0039  * T& token(index)          →   at()
0040  * ? more
0041  * 
0042  * rewind(index) ✓
0043  * qint64 size() ✓
0044  * reset() ✓
0045  * free()                   →   clear()
0046  * 
0047  * locationTable() ✓
0048  * 
0049  * startPosition(index, line, column) ✓
0050  * endPosition(index, line, column) ✓
0051  */
0052 
0053 namespace KDevPG
0054 {
0055 
0056 class Token {
0057   public:
0058     int kind;
0059     qint64 begin;
0060     qint64 end;
0061 };
0062 
0063 /**
0064  * Stores a stream of tokens and has an associated location table.
0065  * You can add tokens and traverse them (Java-style unidirectional iterator with random access).
0066  * Internal representation similar to a std::vector (capacity gets multiplied if it get exceeded).
0067  * @todo Fix inconsistencies in naming: advance vs. next vs. nextToken, token vs. nextToken
0068  */
0069 template<class T>
0070 class TokenStreamBase
0071 {
0072 public:
0073   typedef T Token;
0074   TokenStreamBase()
0075     : mIndex(0),
0076       mLocationTable(nullptr)
0077   {
0078     reset();
0079   }
0080 
0081   ~TokenStreamBase()
0082   {
0083     if (mLocationTable)
0084       delete mLocationTable;
0085   }
0086   
0087   /**
0088    * Clears the stream.
0089    * @note It does not free the reserved memory, because usually as much memory is required as before.
0090    * @note It will not affect the location table.
0091    * @sa free
0092    */
0093   inline void reset()
0094   {
0095     mIndex = 0;
0096   }
0097   
0098   /**
0099    * Clears the stream and frees all memory.
0100    * @note It will not affect the location table.
0101    * @sa reset
0102    */
0103   inline void clear()
0104   {
0105     mIndex = 0;
0106     mTokenBuffer.clear();
0107   }
0108   
0109   /**
0110    * The number of tokens in the stream.
0111    */
0112   inline qint64 size() const
0113   {
0114     return mTokenBuffer.size();
0115   }
0116   
0117   /**
0118    * The current position in the stream.
0119    */
0120   inline qint64 index() const
0121   {
0122     return mIndex;
0123   }
0124   
0125   /**
0126    * Sets the position in the stream.
0127    * All tokens will be unaffected.
0128    */
0129   inline void rewind(qint64 index)
0130   {
0131     Q_ASSERT(0 <= index && index <= size());
0132     mIndex = index;
0133   }
0134   
0135   /**
0136    * Returns the token at the specified position in the stream.
0137    */
0138   inline T const &at(qint64 index) const
0139   {
0140     Q_ASSERT(0 <= index && index < size());
0141     return mTokenBuffer[index];
0142   }
0143   
0144   /**
0145    * Returns the token at the specified position in the stream.
0146    */
0147   inline T &at(qint64 index)
0148   {
0149     Q_ASSERT(0 <= index && index < size());
0150     return mTokenBuffer[index];
0151   }
0152   
0153   /**
0154    * Pushes a new token to the stream.
0155    * @return The new default-initialized token (reference)
0156    */
0157   inline T &push()
0158   {
0159     mTokenBuffer.push_back({});
0160     return mTokenBuffer.back();
0161   }
0162   
0163   /**
0164    * Pushes the specified token to the stream.
0165    * @return Reference to the inserted token
0166    */
0167   inline T &push(const T& t)
0168   {
0169     mTokenBuffer.push_back(t);
0170     return mTokenBuffer.back();
0171   }
0172   
0173   /**
0174    * Advances and returns the token at the current position.
0175    */
0176   inline T &read()
0177   {
0178     if(mIndex == size())
0179     {
0180       push().kind = 1000;
0181     }
0182     return mTokenBuffer[mIndex++];
0183   }
0184   
0185   /**
0186    * Current token in the stream.
0187    */
0188   inline T &curr()
0189   {
0190     Q_ASSERT(mIndex < size());
0191     return mTokenBuffer[mIndex];
0192   }
0193   
0194   /**
0195    * Last token in the stream.
0196    */
0197   inline T &back()
0198   {
0199     Q_ASSERT(!mTokenBuffer.empty());
0200     return mTokenBuffer.back();
0201   }
0202   
0203   /**
0204    * First token in the stream.
0205    */
0206   inline T &front()
0207   {
0208     Q_ASSERT(!mTokenBuffer.empty());
0209     return mTokenBuffer.front();
0210   }
0211   
0212   /**
0213    * @return The associated location table.
0214    */
0215   inline LocationTable *locationTable()
0216   {
0217     if (!mLocationTable)
0218       mLocationTable = new LocationTable();
0219 
0220     return mLocationTable;
0221   }
0222   
0223   /**
0224    * Coordinates of the beginning of the first token.
0225    */
0226   inline void startPosition(qint64 index, qint64 *line, qint64 *column)
0227   {
0228     if (!mLocationTable)
0229       {
0230         *line = 0; *column = 0;
0231       }
0232     else
0233       mLocationTable->positionAt(at(index).begin, line, column);
0234   }
0235   
0236   /**
0237    * Coordinate at the end of all tokens.
0238    */
0239   inline void endPosition(qint64 index, qint64 *line, qint64 *column)
0240   {
0241     if (!mLocationTable)
0242       {
0243         *line = 0; *column = 0;
0244       }
0245     else
0246       mLocationTable->positionAt(at(index).end, line, column);
0247   }
0248 
0249 private:
0250   std::vector<T> mTokenBuffer;
0251   qint64 mIndex;
0252   LocationTable *mLocationTable;
0253 
0254 private:
0255   TokenStreamBase(TokenStreamBase const &other);
0256   void operator = (TokenStreamBase const &other);
0257 };
0258 
0259 
0260 class TokenStream : public TokenStreamBase<Token>
0261 {
0262 };
0263 
0264 
0265 }
0266 
0267 #endif // KDEV_PG_TOKEN_STREAM_H
0268