1 #ifndef TOKEN_H
2 #define TOKEN_H
3 
4 #include "common/utils.h"
5 #include <QString>
6 #include <QList>
7 #include <QSharedPointer>
8 
9 /** @file */
10 
11 /**
12  * @def TOKEN_TYPE_MASK_DB_OBJECT
13  *
14  * Bit mask used to test Token::Type for representing any database object name, in any form.
15  * It's used in Token::isDbObjectType().
16  */
17 #define TOKEN_TYPE_MASK_DB_OBJECT 0x1000
18 
19 struct Token;
20 
21 /**
22  * @brief Shared pointer to the Token.
23  */
24 typedef QSharedPointer<Token> TokenPtr;
25 
26 /**
27  * @brief SQL query entity representing isolated part of the query.
28  *
29  * Tokens are generated by Lexer. Each token represents isolated part of the query,
30  * like a name, a number, an operator, a string, a keyword, or a comment, etc.
31  *
32  * In other words, tokenizing SQL query is splitting it into logical parts.
33  *
34  * Each token has a type, a value and position indexes of where it starts and where it ends (in the query string).
35  *
36  * Tokens are used mainly by the Parser to perform syntax analysis, but they can be also very helpful
37  * in other areas. They provide easy way for safe manipulation on the query string, without worrying
38  * about counting open or close characters of the string, etc. If the string has a single-quote used twice inside,
39  * this is still a regular SQL string and in that case there will be only a single string token representing it.
40  *
41  * If you're constructing Token outside of the Lemon parser, you should be interested only in 4 constructors:
42  * Token(), Token(QString value), Token(Type type, QString value)
43  * and Token(Type type, QString value, qint64 start, qint64 end).
44  * Rest of the constructors are to be used from the Lemon parser, as they require Lemon token ID to be provided.
45  *
46  * You will usually have the most to do with tokens when dealing with SqliteStatement and its 2 members:
47  * SqliteStatement::tokens and SqliteStatement::tokenMap.
48  */
49 struct API_EXPORT Token
50 {
51     /**
52      * @brief Token type.
53      *
54      * There are 2 kind of types - regular and context-oriented.
55      *
56      * Regular types are those defined by the SQL grammar and they represent real tokens. A special token type
57      * from group of regular types is the Type::INVALID, which means, that the character(s) encountered
58      * by the Lexer are invalid in SQL syntax understanding, or when there was no more query characters to read
59      * (which in this case means that tokenizing ended before this token).
60      *
61      * The context-oriented types are special meta types used by the Parser to probe potential candidates
62      * for next valid token when Parser::getNextTokenCandidates() is called. They are then processed by
63      * CompletionHelper. You won't deal with this kind of token types on regular basis. Context-oriented
64      * types are those starting with <tt>CTX_</tt>.
65      */
66     enum Type
67     {
68         INVALID = 0x0001,               /**< Invalid token, or no more tokens available from Lexer. */
69         OTHER = 0x1002,                 /**< A name, a word. */
70         STRING = 0x0003,                /**< A string (value will be stripped of the surrounding quotes). */
71         COMMENT = 0x0004,               /**< A comment, including starting/ending markers. */
72         FLOAT = 0x0005,                 /**< A decimal number. */
73         INTEGER = 0x0006,               /**< An integer number. */
74         BIND_PARAM = 0x0007,            /**< A bind parameter (<tt>:param</tt>, <tt>\@param</tt>, or <tt>?</tt>). */
75         OPERATOR = 0x0008,              /**< An operator (like <tt>";"</tt>, <tt>"+"</tt>, <tt>","</tt>, etc). */
76         PAR_LEFT = 0x0009,              /**< A left parenthesis (<tt>"("</tt>). */
77         PAR_RIGHT = 0x0010,             /**< A right parenthesis (<tt>")"</tt>). */
78         SPACE = 0x0011,                 /**< White space(s), including new line characters and tabs. */
79         BLOB = 0x0012,                  /**< Literal BLOB value (<tt>X'...'</tt> or <tt>x'...'</tt>). */
80         KEYWORD = 0x0013,               /**< A keyword (see getKeywords3() and getKeywords2()). */
81         CTX_COLUMN = 0x1014,            /**< Existing column name is valid at this token position. */
82         CTX_TABLE = 0x1015,             /**< Existing table name is valid at this token potision. */
83         CTX_DATABASE = 0x1016,          /**< Database name is valid at this token position. */
84         CTX_FUNCTION = 0x0017,          /**< Function name is valid at this token position. */
85         CTX_COLLATION = 0x0018,         /**< Collation name is valid at this token position. */
86         CTX_INDEX = 0x1019,             /**< Existing index name is valid at this token position. */
87         CTX_TRIGGER = 0x1020,           /**< Existing trigger name is valid at this token position. */
88         CTX_VIEW = 0x1021,              /**< View name is valid at this token position. */
89         CTX_JOIN_OPTS = 0x0022,         /**< JOIN keywords are valid at this token position (see getJoinKeywords()). */
90         CTX_TABLE_NEW = 0x0023,         /**< Name for new table is valid at this token position. */
91         CTX_INDEX_NEW = 0x0024,         /**< Name for new index is valid at this token position. */
92         CTX_VIEW_NEW = 0x0025,          /**< Name for new view is valid at this token position. */
93         CTX_TRIGGER_NEW = 0x0026,       /**< Name for new trigger is valid at this token position. */
94         CTX_ALIAS = 0x0027,             /**< Alias name is valid at this token position. */
95         CTX_TRANSACTION = 0x0028,       /**< Transaction name is valid at this token position. */
96         CTX_COLUMN_NEW = 0x0029,        /**< Name for the new column is valid at this token position. */
97         CTX_COLUMN_TYPE = 0x0030,       /**< Data type for the new column is valid at this token position. */
98         CTX_CONSTRAINT = 0x0031,        /**< Name for the new constraint is valid at this token position. */
99         CTX_FK_MATCH = 0x0032,          /**< MATCH keywords are valid at this token position (see getFkMatchKeywords()). */
100         CTX_PRAGMA = 0x0033,            /**< Pragma name is valid at this token position. */
101         CTX_ROWID_KW = 0x0034,          /**< ROWID keywords is valid at this token position (see isRowIdKeyword()). */
102         CTX_NEW_KW = 0x0035,            /**< The <tt>NEW</tt> keyword is valid at this token position. */
103         CTX_OLD_KW = 0x0036,            /**< The <tt>OLD</tt> keyword is valid at this token position. */
104         CTX_ERROR_MESSAGE = 0x0037      /**< Error message string is valid at this token position. */
105     };
106 
107     /**
108      * @brief Creates empty token with type Type::INVALID.
109      *
110      * Lemon token ID is set to 0 and start/end positions are set to -1.
111      */
112     Token();
113 
114     /**
115      * @brief Creates fully defined token.
116      * @param lemonType Lemon token ID to use (see sqlite3_parser.h).
117      * @param type Token type.
118      * @param value Value of the token.
119      * @param start Start position of the token (index of the first character in the query).
120      * @param end End position of the token (index of last character in the query).
121      *
122      * This constructor is intended to be used from Lemon parser only. For other use cases
123      * use constructors without the \p lemonType parameter, unless you need it and you know what you're doing.
124      */
125     Token(int lemonType, Type type, QString value, qint64 start, qint64 end);
126 
127     /**
128      * @overload
129      */
130     Token(int lemonType, Type type, QChar value, qint64 start, qint64 end);
131 
132     /**
133      * @overload
134      */
135     Token(int lemonType, Type type, QString value);
136 
137     /**
138      * @brief Creates token with type Type::INVALID and given value.
139      * @param value Value for the token.
140      *
141      * Start/end positions are set to -1.
142      */
143     explicit Token(QString value);
144 
145     /**
146      * @brief Creates token of given type and with given value.
147      * @param type Type for the token.
148      * @param value Value for the token.
149      *
150      * Start/end positions are set to -1.
151      */
152     Token(Type type, QString value);
153 
154     /**
155      * @brief Creates fully defined token.
156      * @param type Type of the token.
157      * @param value Value for the token.
158      * @param start Start position of the token (index of the first character in the query).
159      * @param end End position of the token (index of last character in the query).
160      */
161     Token(Type type, QString value, qint64 start, qint64 end);
162 
163     /**
164      * @brief Destructor declared as virtual. Does nothing in this implementation.
165      */
166     virtual ~Token();
167 
168     /**
169      * @brief Serializes token to human readable form.
170      * @return Token values in format: <tt>{type value start end}</tt>
171      */
172     QString toString();
173 
174     /**
175      * @brief Converts given token type into its string representation.
176      * @param type Type to convert.
177      * @return Type as a string (same as textual representation of the enum in the code).
178      */
179     static const QString typeToString(Type type);
180 
181     /**
182      * @brief Provides range of the token in the query.
183      * @return Start and end character index in relation to the query it comes from.
184      */
185     Range getRange();
186 
187     /**
188      * @brief Tests whether this token represents any kind of whitespace.
189      * @return true if it's a whitespace, or false otherwise.
190      *
191      * Note, that from SQL perspective also comments are whitespaces.
192      */
193     bool isWhitespace(bool includeComments = true) const;
194 
195     /**
196      * @brief Tests whether this token represents separating value (like an operator, or parenthesis) in SQL understanding.
197      * @return true if it's a separating token, or false otherwise.
198      */
199     bool isSeparating() const;
200 
201     /**
202      * @brief Tests whether the token represents meaningful type.
203      * @return true if token is meaningful, like a word, object, string, number, etc. Not comment, not whitespace, not context marker.
204      */
205     bool isMeaningful() const;
206 
207     /**
208      * @brief Tests whether this token is representing any kind of database object name.
209      * @return true if the token is the name an object, or false otherwise.
210      *
211      * From regular token types only the Type::OTHER represents.
212      * For context-oriented types there are several types representing object name.
213      * Use this method to find out which is and which is not.
214      *
215      * You won't need to use this method in most cases. It's useful only to CompletionHelper
216      * for now.
217      */
218     bool isDbObjectType() const;
219 
220     /**
221      * @brief Converts token's type into a string representation.
222      * @return Token type as a string.
223      */
224     QString typeString() const;
225 
226     /**
227      * @brief Compares other token to this token.
228      * @param other Other token to compare.
229      * @return 1 if tokens are equal, 0 if they're different.
230      *
231      * Tokens are equal then 4 members are equal: type, value, start and end.
232      * The lemonType member is ignored by this operator.
233      */
234     int operator==(const Token& other);
235 
236     /**
237      * @brief Compares other token to this token and tells which one is greater.
238      * @param other Other token to compare.
239      * @return true if the other token is greater than this one, or false if it's smaller or equal.
240      *
241      * This operator compares only 2 members: the start and the end indexes. This operator
242      * is used to sort tokens by the character position they occurred at.
243      *
244      * The start value has higher precedence than the end value, but if start values are equal,
245      * then the end value is conclusive.
246      */
247     bool operator<(const Token& other) const;
248 
249     /**
250      * @brief Lemon token ID. Used by the Parser class only.
251      */
252     int lemonType;
253 
254     /**
255      * @brief Token type, describing general class of the token.
256      */
257     Type type;
258 
259     /**
260      * @brief Literal value of the token, captured directly from the query.
261      */
262     QString value;
263 
264     /**
265      * @brief Start position (first character index) of the token in the query.
266      */
267     qint64 start;
268 
269     /**
270      * @brief End position (last character index) of the token in the query.
271      */
272     qint64 end;
273 };
274 
275 /**
276  * @brief qHash implementation for TokenPtr, so it can be used as a key in QHash and QSet.
277  * @param token Token that the hash code is calculated for.
278  * @return Unique integer value for the token.
279  */
280 uint qHash(const TokenPtr& token);
281 
282 struct TolerantToken;
283 /**
284  * @brief Shared pointer to TolerantToken.
285  */
286 typedef QSharedPointer<TolerantToken> TolerantTokenPtr;
287 
288 /**
289  * @brief Variation of token that has additional "invalid" flag.
290  *
291  * TolerantToken is used by Lexer to tolerate unfinished comments, like when you start the
292  * comment at the end of the query, but you never close the comment. This is tolerable case,
293  * while not entire correct by the syntax.
294  *
295  * In such cases the syntax highlighter must be aware of the token being invalid, so the proper
296  * state is marked for the paragraph.
297  */
298 struct TolerantToken : public Token
299 {
300     /**
301      * @brief Invalid state flag for the token.
302      */
303     bool invalid = false;
304 };
305 
306 /**
307  * @brief Ordered list of tokens.
308  *
309  * This is pretty much a QList of Token pointers, but it also provides some
310  * utility methods regarding this collection, which is very common in SQLiteStudio.
311  */
312 class API_EXPORT TokenList : public QList<TokenPtr>
313 {
314     public:
315         /**
316          * @brief Creates empty list.
317          */
318         TokenList();
319 
320         /**
321          * @brief Creates list filled with the same entries as the other list.
322          * @param other List to copy pointers from.
323          */
324         TokenList(const QList<TokenPtr>& other);
325 
326         /**
327          * @brief Serializes contents of the list into readable form.
328          * @return Contents in format: <tt>{type1 value1 start1 end1} {type2 value2 start2 end2} ...</tt>.
329          *
330          * Tokens are serialized with Token::toString(), then all serialized values are joined with single whitespace
331          * into the QString.
332          */
333         QString toString() const;
334 
335         /**
336          * @brief Serializes tokens from the list into strings.
337          * @return List of tokens serialized into strings.
338          *
339          * Tokens are serialized with Token::toString().
340          */
341         QStringList toStringList() const;
342 
343         /**
344          * @brief Converts list of tokens into list of their values.
345          * @return List of tokens values.
346          */
347         QStringList toValueList() const;
348 
349         /**
350          * @brief Provides index of first occurrence of the token in the list.
351          * @param token Token to look for.
352          * @return Index of the token, or -1 if token was not found.
353          */
354         int indexOf(TokenPtr token) const;
355 
356         /**
357          * @brief Provides index of first occurrence of the token with given type.
358          * @param type Toke type to look for.
359          * @return Index of the token, or -1 if token was not found.
360          */
361         int indexOf(Token::Type type) const;
362 
363         /**
364          * @brief Provides index of first occurrence of the token with given type and value.
365          * @param type Token type to look for.
366          * @param value Token value to look for.
367          * @param caseSensitivity Should value lookup be case sensitive?
368          * @return Index of the token, or -1 if token was not found.
369          */
370         int indexOf(Token::Type type, const QString& value, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) const;
371 
372         /**
373          * @brief Provides index of first occurrence of the token with given value.
374          * @param value Value to look for.
375          * @param caseSensitivity Should value lookup be case sensitive?
376          * @return Index of the token, or -1 if token was not found.
377          */
378         int indexOf(const QString& value, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) const;
379 
380         /**
381          * @brief Provides index of last occurrence of the token in the list.
382          * @param token Token to look for.
383          * @return Index of the token, or -1 if token was not found.
384          */
385         int lastIndexOf(TokenPtr token) const;
386 
387         /**
388          * @brief Provides index of last occurrence of the token with given type.
389          * @param type Token type to look for.
390          * @return Index of the token, or -1 if token was not found.
391          */
392         int lastIndexOf(Token::Type type) const;
393 
394         /**
395          * @brief Provides index of last occurrence of the token with given type and value.
396          * @param type Token type to look for.
397          * @param value Token value to look for.
398          * @param caseSensitivity Should value lookup be case sensitive?
399          * @return Index of the token, or -1 if token was not found.
400          */
401         int lastIndexOf(Token::Type type, const QString& value, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) const;
402 
403         /**
404          * @brief Provides index of last occurrence of the token with given value.
405          * @param value Value to look for.
406          * @param caseSensitivity Should value lookup be case sensitive?
407          * @return Index of the token, or -1 if token was not found.
408          */
409         int lastIndexOf(const QString& value, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) const;
410 
411         /**
412          * @brief Finds first token with given type in the list.
413          * @param type Type to look for.
414          * @return Token found, or null pointer if it was not found.
415          */
416         TokenPtr find(Token::Type type) const;
417 
418         /**
419          * @brief Finds first token with given type and value.
420          * @param type Type to look for.
421          * @param value Token value to look for.
422          * @param caseSensitivity Should value lookup be case sensitive?
423          * @return Token found, or null pointer if it was not found.
424          */
425         TokenPtr find(Token::Type type, const QString& value, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) const;
426 
427         /**
428          * @brief Finds first token with given type and value.
429          * @param value Token value to look for.
430          * @param caseSensitivity Should value lookup be case sensitive?
431          * @return Token found, or null pointer if it was not found.
432          */
433         TokenPtr find(const QString& value, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) const;
434 
435         /**
436          * @brief Finds last token with given type in the list.
437          * @param type Type to look for.
438          * @return Token found, or null pointer if it was not found.
439          */
440         TokenPtr findLast(Token::Type type) const;
441 
442         /**
443          * @brief Finds last token with given type and value.
444          * @param type Type to look for.
445          * @param value Token value to look for.
446          * @param caseSensitivity Should value lookup be case sensitive?
447          * @return Token found, or null pointer if it was not found.
448          */
449         TokenPtr findLast(Token::Type type, const QString& value, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) const;
450 
451         /**
452          * @brief Finds last token with given value.
453          * @param value Token value to look for.
454          * @param caseSensitivity Should value lookup be case sensitive?
455          * @return Token found, or null pointer if it was not found.
456          */
457         TokenPtr findLast(const QString& value, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) const;
458 
459         /**
460          * @brief Finds token that according to its start and end values covers given character position.
461          * @param cursorPosition Position to get token for.
462          * @return Token found, or null pointer if it was not found.
463          */
464         TokenPtr atCursorPosition(quint64 cursorPosition) const;
465 
466         /**
467          * @brief Inserts tokens at given position in this list.
468          * @param i Position to insert at.
469          * @param list List of tokens to insert.
470          */
471         void insert(int i, const TokenList& list);
472 
473         /**
474          * @brief Inserts a token at given position in this list.
475          * @param i Position to insert at.
476          * @param token Token to insert.
477          */
478         void insert(int i, TokenPtr token);
479 
480         /**
481          * @brief Puts all tokens from the other list to this list.
482          * @param other List to get tokens from.
483          * @return Reference to this list.
484          *
485          * It erases any previous entries in this list, just like you would normally expect for the <tt>=</tt> operator.
486          */
487         TokenList& operator=(const QList<TokenPtr>& other);
488 
489         /**
490          * @brief Detokenizes all tokens from this list.
491          * @return String from all tokens.
492          *
493          * This is just a convenient method to call Lexer::detokenize() on this list.
494          */
495         QString detokenize() const;
496 
497         /**
498          * @brief Replaces tokens on this list with other tokens.
499          * @param startIdx Position of the first token in this list to replace.
500          * @param length Number of tokens to replace.
501          * @param newTokens New tokens to put in place of removed ones.
502          */
503         void replace(int startIdx, int length, const TokenList& newTokens);
504 
505         /**
506          * @brief Replaces tokens on this list with another token.
507          * @param startIdx Position of the first token in this list to replace.
508          * @param length Number of tokens to replace.
509          * @param newToken New token to put in place of removed ones.
510          */
511         void replace(int startIdx, int length, TokenPtr newToken);
512 
513         /**
514          * @brief Replaces token with another token.
515          * @param startIdx Position of the token in this list to replace.
516          * @param newToken New token to put in place of removed one.
517          */
518         void replace(int startIdx, TokenPtr newToken);
519 
520         /**
521          * @brief Replaces token on this list with other tokens.
522          * @param startIdx Position of the token in this list to replace.
523          * @param newTokens New tokens to put in place of removed ones.
524          */
525         void replace(int startIdx, const TokenList& newTokens);
526 
527         /**
528          * @brief Replaces tokens on this list with other tokens.
529          * @param startToken First token to replace.
530          * @param endToken Last token to replace.
531          * @param newTokens New tokens to put in place of removed ones.
532          * @return Number of tokens replaced.
533          *
534          * If either \p startToken or \p endToken were not found on the list, this method does nothing
535          * and returns 0.
536          */
537         int replace(TokenPtr startToken, TokenPtr endToken, const TokenList& newTokens);
538 
539         /**
540          * @brief Replaces tokens on this list with other tokens.
541          * @param startToken First token to replace.
542          * @param endToken Last token to replace.
543          * @param newToken New token to put in place of removed ones.
544          * @return Number of tokens replaced.
545          *
546          * If either \p startToken or \p endToken were not found on the list, this method does nothing
547          * and returns 0.
548          */
549         int replace(TokenPtr startToken, TokenPtr endToken, TokenPtr newToken);
550 
551         /**
552          * @brief Replaces token on this list with another token.
553          * @param oldToken Token to replace.
554          * @param newToken Token to replace with.
555          * @return true if \p oldToken was found and replaced, or false otherwise.
556          */
557         bool replace(TokenPtr oldToken, TokenPtr newToken);
558 
559         /**
560          * @brief Replaces token on this list with other tokens.
561          * @param oldToken Token to replace.
562          * @param newTokens Tokens to replace with.
563          * @return true if \p oldToken was found and replaced, or false otherwise.
564          */
565         bool replace(TokenPtr oldToken, const TokenList& newTokens);
566 
567         /**
568          * @brief Removes tokens from the list.
569          * @param startToken First token to remove.
570          * @param endToken Last token to remove.
571          * @return true if \p startToken and \p endToken were found in the list and removed, or false otherwise.
572          *
573          * In case \p startToken is placed after \p endToken, this method does nothing and returns false.
574          */
575         bool remove(TokenPtr startToken, TokenPtr endToken);
576 
577         /**
578          * @brief Removes first token of given type from the list.
579          * @param type Token type to remove.
580          * @return true if token was located and removed, or false otherwise.
581          */
582         bool remove(Token::Type type);
583 
584         /**
585          * @brief Removes all white-space tokens from the beginning of the list.
586          *
587          * White-space tokens are tested with Token::isWhitespace().
588          */
589         TokenList &trimLeft();
590 
591         /**
592          * @brief Removes all white-space tokens from the end of the list.
593          *
594          * White-space tokens are tested with Token::isWhitespace().
595          */
596         TokenList &trimRight();
597 
598         /**
599          * @brief Removes all white-space tokens from both the beginning and the end of the list.
600          *
601          * White-space tokens are tested with Token::isWhitespace().
602          */
603         TokenList &trim();
604 
605         /**
606          * @brief Removes all tokens that match given criteria from the beginning of the list.
607          * @param type Token type to remove.
608          * @param alsoTrim Token value to remove.
609          *
610          * This method is an extension to the regular trimLeft(). It removes white-space tokens,
611          * as well as tokens that are of given \p type and have given \p value (both conditions must be met).
612          */
613         TokenList &trimLeft(Token::Type type, const QString& alsoTrim);
614 
615         /**
616          * @brief Removes all tokens that match given criteria from the end of the list.
617          * @param type Token type to remove.
618          * @param alsoTrim Token value to remove.
619          *
620          * This method is an extension to the regular trimRight(). It removes white-space tokens,
621          * as well as tokens that are of given \p type and have given \p value (both conditions must be met).
622          */
623         TokenList &trimRight(Token::Type type, const QString& alsoTrim);
624 
625         /**
626          * @brief Removes all tokens that match given criteria from the beginning and the end of the list.
627          * @param type Token type to remove.
628          * @param alsoTrim Token value to remove.
629          *
630          * This method is an extension to the regular trim(). It removes white-space tokens,
631          * as well as tokens that are of given \p type and have given \p value (both conditions must be met).
632          */
633         TokenList &trim(Token::Type type, const QString& alsoTrim);
634 
635         /**
636          * @brief Creates list of tokens from this list, letting through only tokens of given type.
637          * @param type Type of tokens to provide in the new list.
638          * @return List of tokens from this list matching given \p type.
639          */
640         TokenList filter(Token::Type type) const;
641         TokenList filterOut(Token::Type type) const;
642 
643         /**
644          * @brief Creates list of tokens from this list, letting through only tokens that are not a whitespace.
645          * @return List of tokens from this list that are not a whitespace.
646          *
647          * The condition to test if tokens is a whitespace is a call to Token::isWhitespace().
648          */
649         TokenList filterWhiteSpaces(bool includeComments = true) const;
650 
651         /**
652          * @brief Returns sub-list of tokens from this list.
653          * @param pos Position to start sublist from.
654          * @param length Number of tokens to get from this list. If -1 (default), then all from the \p pos to the end.
655          * @return Sub-list of tokens from this list.
656          */
657         TokenList mid(int pos, int length = -1) const;
658 
659     private:
660         /**
661          * @brief Finds first occurrence of token with given type.
662          * @param type Type of token to look for.
663          * @param idx Pointer to integer variable to store position in.
664          * @return Token found, or null pointer if token was not found.
665          *
666          * If \p idx is not null, then the position of token found is stored in it. If token was not found,
667          * then -1 is stored in the \p idx.
668          *
669          * This method is used by the public findFirst() and indexOf() methods, as they share common logic.
670          */
671         TokenPtr findFirst(Token::Type type, int* idx) const;
672 
673         /**
674          * @brief Finds first occurrence of token with given type and value.
675          * @param type Type of token to look for.
676          * @param value Value of the token to look for.
677          * @param caseSensitivity Should value lookup be case sensitive?
678          * @param idx Pointer to integer variable to store position in.
679          * @return Token found, or null pointer if token was not found.
680          *
681          * If \p idx is not null, then the position of token found is stored in it. If token was not found,
682          * then -1 is stored in the \p idx.
683          *
684          * This method is used by the public findFirst() and indexOf() methods, as they share common logic.
685          */
686         TokenPtr findFirst(Token::Type type, const QString& value, Qt::CaseSensitivity caseSensitivity, int* idx) const;
687 
688         /**
689          * @brief Finds first occurrence of token with given value.
690          * @param value Value of the token to look for.
691          * @param caseSensitivity Should value lookup be case sensitive?
692          * @param idx Pointer to integer variable to store position in.
693          * @return Token found, or null pointer if token was not found.
694          *
695          * If \p idx is not null, then the position of token found is stored in it. If token was not found,
696          * then -1 is stored in the \p idx.
697          *
698          * This method is used by the public findFirst() and indexOf() methods, as they share common logic.
699          */
700         TokenPtr findFirst(const QString& value, Qt::CaseSensitivity caseSensitivity, int* idx) const;
701 
702         /**
703          * @brief Finds last occurrence of token with given type.
704          * @param type Type of token to look for.
705          * @param idx Pointer to integer variable to store position in.
706          * @return Token found, or null pointer if token was not found.
707          *
708          * If \p idx is not null, then the position of token found is stored in it. If token was not found,
709          * then -1 is stored in the \p idx.
710          *
711          * This method is used by the public findLast() and lastIndexOf() methods, as they share common logic.
712          */
713         TokenPtr findLast(Token::Type type, int* idx) const;
714 
715         /**
716          * @brief Finds last occurrence of token with given type and value.
717          * @param type Type of token to look for.
718          * @param value Value of the token to look for.
719          * @param caseSensitivity Should value lookup be case sensitive?
720          * @param idx Pointer to integer variable to store position in.
721          * @return Token found, or null pointer if token was not found.
722          *
723          * If \p idx is not null, then the position of token found is stored in it. If token was not found,
724          * then -1 is stored in the \p idx.
725          *
726          * This method is used by the public findLast() and lastIndexOf() methods, as they share common logic.
727          */
728         TokenPtr findLast(Token::Type type, const QString& value, Qt::CaseSensitivity caseSensitivity, int* idx) const;
729 
730         /**
731          * @brief Finds last occurrence of token with given value.
732          * @param value Value of the token to look for.
733          * @param caseSensitivity Should value lookup be case sensitive?
734          * @param idx Pointer to integer variable to store position in.
735          * @return Token found, or null pointer if token was not found.
736          *
737          * If \p idx is not null, then the position of token found is stored in it. If token was not found,
738          * then -1 is stored in the \p idx.
739          *
740          * This method is used by the public findLast() and lastIndexOf() methods, as they share common logic.
741          */
742         TokenPtr findLast(const QString& value, Qt::CaseSensitivity caseSensitivity, int* idx) const;
743 };
744 
745 
746 #endif // TOKEN_H
747