Lines 38-44
Link Here
|
38 |
* A typical use is a forward iteration through the tokens: |
38 |
* A typical use is a forward iteration through the tokens: |
39 |
* <pre> |
39 |
* <pre> |
40 |
* TokenSequence ts = tokenHierarchy.tokenSequence(); |
40 |
* TokenSequence ts = tokenHierarchy.tokenSequence(); |
41 |
* // Possible positioning by ts.move() |
41 |
* // Possible positioning by ts.move(offset); |
42 |
* while (ts.moveNext()) { |
42 |
* while (ts.moveNext()) { |
43 |
* Token t = ts.token(); |
43 |
* Token t = ts.token(); |
44 |
* if (t.id() == ...) { ... } |
44 |
* if (t.id() == ...) { ... } |
Lines 65-71
Link Here
|
65 |
|
65 |
|
66 |
private AbstractToken<T> token; // 16 bytes |
66 |
private AbstractToken<T> token; // 16 bytes |
67 |
|
67 |
|
68 |
private int tokenIndex = -1; // 20 bytes |
68 |
private int tokenIndex; // 20 bytes |
69 |
|
69 |
|
70 |
/** |
70 |
/** |
71 |
* Offset in the input at which the current token is located |
71 |
* Offset in the input at which the current token is located |
Lines 115-123
Link Here
|
115 |
/** |
115 |
/** |
116 |
* Get instance of current token to which this token sequence points to. |
116 |
* Get instance of current token to which this token sequence points to. |
117 |
* <br/> |
117 |
* <br/> |
118 |
* It is necessary to call {@link #moveNext()} before first calling this method. |
118 |
* A typical iteration usage: |
|
|
119 |
* <pre> |
120 |
* TokenSequence ts = tokenHierarchy.tokenSequence(); |
121 |
* // Possible positioning by ts.move(offset); |
122 |
* while (ts.moveNext()) { |
123 |
* Token t = ts.token(); |
124 |
* if (t.id() == ...) { ... } |
125 |
* if (TokenUtilities.equals(t.text(), "mytext")) { ... } |
126 |
* if (ts.offset() == ...) { ... } |
127 |
* } |
128 |
* </pre> |
119 |
* |
129 |
* |
120 |
* <p> |
|
|
121 |
* The returned token instance may be flyweight |
130 |
* The returned token instance may be flyweight |
122 |
* (returns true from {@link Token#isFlyweight()}) |
131 |
* (returns true from {@link Token#isFlyweight()}) |
123 |
* which means that its {@link Token#offset(TokenHierarchy)} will return -1. |
132 |
* which means that its {@link Token#offset(TokenHierarchy)} will return -1. |
Lines 133-145
Link Here
|
133 |
* The token instance should not be held across the input source modifications. |
142 |
* The token instance should not be held across the input source modifications. |
134 |
* </p> |
143 |
* </p> |
135 |
* |
144 |
* |
136 |
* @return non-null token instance. |
145 |
* @return token instance to which this token sequence is currently positioned |
|
|
146 |
* or null if this token sequence is not positioned to any token which may |
147 |
* happen after TS creation or after use of {@link #move(int)} or {@link moveIndex(int)}. |
148 |
* |
137 |
* @see #offsetToken() |
149 |
* @see #offsetToken() |
138 |
* @throws IllegalStateException if this token sequence was not positioned |
|
|
139 |
* to any token yet. |
140 |
*/ |
150 |
*/ |
141 |
public Token<T> token() { |
151 |
public Token<T> token() { |
142 |
checkToken(); |
|
|
143 |
return token; |
152 |
return token; |
144 |
} |
153 |
} |
145 |
|
154 |
|
Lines 160-166
Link Here
|
160 |
* to any token yet. |
169 |
* to any token yet. |
161 |
*/ |
170 |
*/ |
162 |
public Token<T> offsetToken() { |
171 |
public Token<T> offsetToken() { |
163 |
checkToken(); |
172 |
checkTokenNotNull(); |
164 |
if (token.isFlyweight()) { |
173 |
if (token.isFlyweight()) { |
165 |
token = tokenList.replaceFlyToken(tokenIndex, token, offset()); |
174 |
token = tokenList.replaceFlyToken(tokenIndex, token, offset()); |
166 |
} |
175 |
} |
Lines 183-189
Link Here
|
183 |
* to any token yet. |
192 |
* to any token yet. |
184 |
*/ |
193 |
*/ |
185 |
public int offset() { |
194 |
public int offset() { |
186 |
checkToken(); |
195 |
checkTokenNotNull(); |
187 |
if (tokenOffset == -1) { |
196 |
if (tokenOffset == -1) { |
188 |
tokenOffset = tokenList.tokenOffset(tokenIndex); |
197 |
tokenOffset = tokenList.tokenOffset(tokenIndex); |
189 |
} |
198 |
} |
Lines 191-200
Link Here
|
191 |
} |
200 |
} |
192 |
|
201 |
|
193 |
/** |
202 |
/** |
194 |
* Get the index of the current token in the complete list of tokens. |
203 |
* Get an index of token to which (or before which) this TS is currently positioned. |
|
|
204 |
* <br/> |
205 |
* Zero is returned after TS creation. |
195 |
* |
206 |
* |
196 |
* @return >=0 index of the current token or <code>-1</code> |
207 |
* @return >=0 index of the current token. |
197 |
* if this token sequence is initially located in front of the first token. |
|
|
198 |
*/ |
208 |
*/ |
199 |
public int index() { |
209 |
public int index() { |
200 |
return tokenIndex; |
210 |
return tokenIndex; |
Lines 216-222
Link Here
|
216 |
* to any token yet. |
226 |
* to any token yet. |
217 |
*/ |
227 |
*/ |
218 |
public TokenSequence<? extends TokenId> embedded() { |
228 |
public TokenSequence<? extends TokenId> embedded() { |
219 |
checkToken(); |
229 |
checkTokenNotNull(); |
220 |
return embeddedImpl(null); |
230 |
return embeddedImpl(null); |
221 |
} |
231 |
} |
222 |
|
232 |
|
Lines 249-255
Link Here
|
249 |
* has a language embedding. |
259 |
* has a language embedding. |
250 |
*/ |
260 |
*/ |
251 |
public <ET extends TokenId> TokenSequence<ET> embedded(Language<ET> embeddedLanguage) { |
261 |
public <ET extends TokenId> TokenSequence<ET> embedded(Language<ET> embeddedLanguage) { |
252 |
checkToken(); |
262 |
checkTokenNotNull(); |
253 |
return embeddedImpl(embeddedLanguage); |
263 |
return embeddedImpl(embeddedLanguage); |
254 |
} |
264 |
} |
255 |
|
265 |
|
Lines 294-300
Link Here
|
294 |
*/ |
304 |
*/ |
295 |
public boolean createEmbedding(Language<? extends TokenId> embeddedLanguage, |
305 |
public boolean createEmbedding(Language<? extends TokenId> embeddedLanguage, |
296 |
int startSkipLength, int endSkipLength, boolean joinSections) { |
306 |
int startSkipLength, int endSkipLength, boolean joinSections) { |
297 |
checkToken(); |
307 |
checkTokenNotNull(); |
298 |
return EmbeddingContainer.createEmbedding(tokenList, tokenIndex, |
308 |
return EmbeddingContainer.createEmbedding(tokenList, tokenIndex, |
299 |
embeddedLanguage, startSkipLength, endSkipLength, joinSections); |
309 |
embeddedLanguage, startSkipLength, endSkipLength, joinSections); |
300 |
} |
310 |
} |
Lines 302-349
Link Here
|
302 |
/** |
312 |
/** |
303 |
* Move to the next token in this token sequence. |
313 |
* Move to the next token in this token sequence. |
304 |
* <br/> |
314 |
* <br/> |
|
|
315 |
* This method can be used in case when TS is positioned before a token |
316 |
* (after its creation or after use of {@link #move(int)} or {@link #moveIndex(int)}) |
317 |
* or in case the TS already points to a concrete token <code>{@link #token()} != null</code> |
318 |
* - in such case it moves to next token and {@link #index()} gets increased by one. |
319 |
* <br/> |
305 |
* The next token may not necessarily start at the offset where |
320 |
* The next token may not necessarily start at the offset where |
306 |
* the current token ends (there may be gaps between tokens |
321 |
* the previous token ends (there may be gaps between tokens |
307 |
* caused by use of a token id filter). |
322 |
* caused by token filtering). |
308 |
* |
323 |
* |
309 |
* @return true if the sequence was successfully moved to the next token |
324 |
* @return true if the sequence was successfully moved to the next token |
310 |
* or false if stays on the original token because there are no more tokens |
325 |
* or false if it was not moved before there are no more tokens |
311 |
* in the forward direction. |
326 |
* in the forward direction. |
312 |
* @throws ConcurrentModificationException if this token sequence |
327 |
* @throws ConcurrentModificationException if this token sequence |
313 |
* is no longer valid because of an underlying mutable input source modification. |
328 |
* is no longer valid because of an underlying mutable input source modification. |
314 |
*/ |
329 |
*/ |
315 |
public boolean moveNext() { |
330 |
public boolean moveNext() { |
316 |
checkModCount(); |
331 |
checkModCount(); |
317 |
tokenIndex++; |
332 |
if (token != null) // Token already fetched |
|
|
333 |
tokenIndex++; |
318 |
Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(tokenIndex); |
334 |
Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(tokenIndex); |
319 |
if (tokenOrEmbeddingContainer != null) { |
335 |
if (tokenOrEmbeddingContainer != null) { |
320 |
AbstractToken origToken = token; |
336 |
AbstractToken origToken = token; |
321 |
assignToken(tokenOrEmbeddingContainer); |
337 |
token = LexerUtilsConstants.token(tokenOrEmbeddingContainer); |
|
|
338 |
// If origToken == null then the right offset might already be pre-computed from move() |
322 |
if (tokenOffset != -1) { |
339 |
if (tokenOffset != -1) { |
323 |
// If the token list is continuous or the fetched token |
340 |
if (origToken != null) { |
324 |
// is flyweight (there cannot be a gap before flyweight token) |
341 |
// If the token list is continuous or the fetched token |
325 |
// the original offset can be just increased |
342 |
// is flyweight (there cannot be a gap before flyweight token) |
326 |
// by the original token's length. |
343 |
// the original offset can be just increased |
327 |
if (tokenList.isContinuous() || token.isFlyweight()) { |
344 |
// by the original token's length. |
328 |
tokenOffset += origToken.length(); // advance by previous token's length |
345 |
if (tokenList.isContinuous() || token.isFlyweight()) { |
329 |
} else // Offset must be recomputed |
346 |
tokenOffset += origToken.length(); // advance by previous token's length |
330 |
tokenOffset = -1; // mark the offset to be recomputed |
347 |
} else // Offset must be recomputed |
|
|
348 |
tokenOffset = -1; // mark the offset to be recomputed |
349 |
} else // Not valid token previously |
350 |
tokenOffset = -1; |
331 |
} |
351 |
} |
332 |
return true; |
352 |
return true; |
333 |
} |
353 |
} |
334 |
tokenIndex--; |
354 |
if (token != null) // Unsuccessful move from existing token |
|
|
355 |
tokenIndex--; |
335 |
return false; |
356 |
return false; |
336 |
} |
357 |
} |
337 |
|
358 |
|
338 |
/** |
359 |
/** |
339 |
* Move to the previous token in this token sequence. |
360 |
* Move to a previous token in this token sequence. |
|
|
361 |
* <br/> |
362 |
* This method can be used in case when TS is positioned after a token |
363 |
* (after its creation or after use of {@link #move(int)} or {@link #moveIndex(int)}) |
364 |
* or in case the TS already points to a concrete token <code>{@link #token()} != null</code>. |
365 |
* <br/> |
366 |
* In both cases {@link #index()} gets decreased by one. |
340 |
* <br/> |
367 |
* <br/> |
341 |
* The next token may not necessarily end at the offset where |
|
|
342 |
* the present token starts (there may be gaps between tokens |
343 |
* caused by use of a token id filter). |
344 |
* |
368 |
* |
345 |
* @return true if the sequence was successfully moved to the previous token |
369 |
* @return true if the sequence was successfully moved to the previous token |
346 |
* or false if stayed on the original token because there are no more tokens |
370 |
* or false if it was not moved because there are no more tokens |
347 |
* in the backward direction. |
371 |
* in the backward direction. |
348 |
* @throws ConcurrentModificationException if this token sequence |
372 |
* @throws ConcurrentModificationException if this token sequence |
349 |
* is no longer valid because of an underlying mutable input source modification. |
373 |
* is no longer valid because of an underlying mutable input source modification. |
Lines 353-359
Link Here
|
353 |
if (tokenIndex > 0) { |
377 |
if (tokenIndex > 0) { |
354 |
AbstractToken origToken = token; |
378 |
AbstractToken origToken = token; |
355 |
tokenIndex--; |
379 |
tokenIndex--; |
356 |
assignToken(); |
380 |
token = LexerUtilsConstants.token(tokenList.tokenOrEmbeddingContainer(tokenIndex)); |
357 |
if (tokenOffset != -1) { |
381 |
if (tokenOffset != -1) { |
358 |
// If the token list is continuous or the original token |
382 |
// If the token list is continuous or the original token |
359 |
// is flyweight (there cannot be a gap before flyweight token) |
383 |
// is flyweight (there cannot be a gap before flyweight token) |
Lines 364-371
Link Here
|
364 |
} else { // mark the offset to be computed upon call to offset() |
388 |
} else { // mark the offset to be computed upon call to offset() |
365 |
tokenOffset = -1; |
389 |
tokenOffset = -1; |
366 |
} |
390 |
} |
367 |
} else { |
|
|
368 |
tokenOffset = -1; // mark the offset to be computed upon call to offset() |
369 |
} |
391 |
} |
370 |
return true; |
392 |
return true; |
371 |
|
393 |
|
Lines 374-465
Link Here
|
374 |
} |
396 |
} |
375 |
|
397 |
|
376 |
/** |
398 |
/** |
377 |
* Move the token sequence to point to the token with the given index. |
399 |
* Move TS to be positioned before a token with the given index. |
|
|
400 |
* <br/> |
401 |
* Example: Fetching tokens starting at the given index: |
402 |
* <pre> |
403 |
* TokenSequence ts = tokenHierarchy.tokenSequence(); |
404 |
* ts.moveIndex(index); |
405 |
* while (ts.moveNext()) { |
406 |
* Token t = ts.token(); |
407 |
* ... |
408 |
* } |
409 |
* </pre> |
378 |
* |
410 |
* |
379 |
* @param index index of the token to which this sequence |
411 |
* @param index index of the token to which this sequence |
380 |
* should be positioned. |
412 |
* should be positioned. |
381 |
* @return <code>true</code> if the sequence was moved to the token |
413 |
* <br/> |
382 |
* with the given index. Returns <code>false</code> |
414 |
* If <code>index >= {@link #tokenCount()}</code> |
383 |
* if <code>index < 0</code> or <code>index < tokenCount</code>. |
415 |
* then the TS will be positioned after the last token. |
384 |
* In such case the current token sequence's position stays unchanged. |
416 |
* <br/> |
|
|
417 |
* If <code>index < 0</code> |
418 |
* then the TS will be positioned before first token (at index 0). |
419 |
* @return difference between requested index and the index to which TS |
420 |
* is really set. |
385 |
* @throws ConcurrentModificationException if this token sequence |
421 |
* @throws ConcurrentModificationException if this token sequence |
386 |
* is no longer valid because of an underlying mutable input source modification. |
422 |
* is no longer valid because of an underlying mutable input source modification. |
387 |
*/ |
423 |
*/ |
388 |
public boolean moveIndex(int index) { |
424 |
public int moveIndex(int index) { |
389 |
checkModCount(); |
425 |
checkModCount(); |
390 |
if (index < 0) { |
426 |
if (index >= 0) { |
391 |
return false; |
427 |
Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(index); |
392 |
} |
428 |
if (tokenOrEmbeddingContainer != null) { // enough tokens |
393 |
Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(index); |
429 |
resetTokenIndex(index); |
394 |
if (tokenOrEmbeddingContainer != null) { // enough tokens |
430 |
} else // Token at the requested index does not exist - leave orig. index |
395 |
this.tokenIndex = index; |
431 |
resetTokenIndex(tokenCount()); |
396 |
assignToken(tokenOrEmbeddingContainer); |
432 |
} else // index < 0 |
397 |
tokenOffset = -1; |
433 |
resetTokenIndex(0); |
398 |
return true; |
434 |
return index - tokenIndex; |
399 |
|
435 |
} |
400 |
} else // Token at the requested index does not exist - leave orig. index |
436 |
|
401 |
return false; |
437 |
/** |
|
|
438 |
* Move the token sequence to be positioned before the first token. |
439 |
* <br/> |
440 |
* This is equivalent to <code>moveIndex(0)</code>. |
441 |
*/ |
442 |
public void moveStart() { |
443 |
moveIndex(0); |
402 |
} |
444 |
} |
403 |
|
445 |
|
404 |
/** |
446 |
/** |
405 |
* Move the token sequence to be positioned to the token |
447 |
* Move the token sequence to be positioned after the last token. |
|
|
448 |
* <br/> |
449 |
* This is equivalent to <code>moveIndex(tokenCount())</code>. |
450 |
*/ |
451 |
public void moveEnd() { |
452 |
moveIndex(tokenCount()); |
453 |
} |
454 |
|
455 |
/** |
456 |
* Move the token sequence to be positioned before the token |
406 |
* that "contains" the requested offset (the offset is at the begining |
457 |
* that "contains" the requested offset (the offset is at the begining |
407 |
* or inside of the token). |
458 |
* or inside of the token). |
408 |
* <br> |
459 |
* <br/> |
409 |
* If the offset is too big the token sequence will be positioned |
460 |
* Typical usage pattern: |
410 |
* to the last token and the return value will |
461 |
* <pre> |
411 |
* be the distance between the requested offset |
462 |
* TokenSequence ts = ... |
412 |
* and the start offset of the token to which the token sequence |
463 |
* ts.move(offset); |
413 |
* will be positioned.. |
464 |
* while (ts.moveNext()) { |
414 |
* <br> |
465 |
* Token t = ts.token(); |
415 |
* If there are no tokens in the sequence then {@link Integer#MAX_VALUE} |
466 |
* ... |
416 |
* will be returned. |
467 |
* } |
417 |
* |
468 |
* </pre> |
|
|
469 |
* |
470 |
* If the offset is too big then the token sequence will be positioned |
471 |
* behind the last token. |
418 |
* <p> |
472 |
* <p> |
419 |
* The underlying token list may contain gaps that are not covered |
473 |
* If token filtering is used there may be gaps that are not covered |
420 |
* by any tokens and if the offset is contained in such gap then |
474 |
* by any tokens and if the offset is contained in such gap then |
421 |
* the token sequence will be positioned to the token that precedes the gap. |
475 |
* the token sequence will be positioned before the token that follows the gap. |
422 |
* </p> |
476 |
* </p> |
423 |
* |
477 |
* |
424 |
* Example: |
|
|
425 |
* <pre> |
426 |
* int diff = tokenSequence.move(targetOffset); |
427 |
* // diff equals to (targetOffset - tokenSequence.token().offset()) |
428 |
* if (diff >= 0 && diff < tokenSequence.token().length()) { |
429 |
* // Within token bounds - tokenSequence.token() starts at or "contains" targetOffset |
430 |
* |
431 |
* } else if (diff == Integer.MAX_VALUE) { |
432 |
* // No tokens in the token sequence at all. |
433 |
* // Token sequence is not positioned to any token. |
434 |
* |
435 |
* } else { |
436 |
* // 1. diff >= tokenSequence.token().length() |
437 |
* // a) targetOffset is above the end of the last token in the sequence. |
438 |
* // Token sequence is positioned to the last token in the sequence. |
439 |
* // b) there are text areas not covered by any tokens |
440 |
* // due to skipped tokens (skipTokenIds was used |
441 |
* // in TokenHierarchy.create()) and the targetOffset points to such gap. |
442 |
* // Token sequence is positioned to the preceding token. |
443 |
* // |
444 |
* // 2. diff < 0 |
445 |
* // a) targetOffset < 0 |
446 |
* // b) targetOffset >= 0 but there is a text area |
447 |
* // at the begining that is not covered by any tokens |
448 |
* // (skipTokenIds was used in TokenHierarchy.create()) |
449 |
* // Token sequence is positioned to the first token in the sequence. |
450 |
* } |
451 |
* </pre> |
452 |
* |
453 |
* |
478 |
* |
454 |
* @param offset absolute offset in the input to which |
479 |
* @param offset absolute offset in the input to which |
455 |
* the token sequence should be moved. |
480 |
* the token sequence should be moved. |
456 |
* |
481 |
* |
457 |
* @return difference between the reqeuested offset |
482 |
* @return difference between the reqeuested offset |
458 |
* and the absolute starting offset of the token |
483 |
* and the start offset of the token |
459 |
* to which the the token sequence gets moved. |
484 |
* before which the the token sequence gets positioned. |
460 |
* <br> |
485 |
* <br/> |
461 |
* Returns {@link Integer#MAX_VALUE} if there are no tokens in the sequence. |
486 |
* If the TS is positioned after the last token the difference is computed |
462 |
* In such case there is no active token. |
487 |
* against the end offset of the last token. |
463 |
* |
488 |
* |
464 |
* @throws ConcurrentModificationException if this token sequence |
489 |
* @throws ConcurrentModificationException if this token sequence |
465 |
* is no longer valid because of an underlying mutable input source modification. |
490 |
* is no longer valid because of an underlying mutable input source modification. |
Lines 474-480
Link Here
|
474 |
if (tokenList.tokenOrEmbeddingContainer(0) == null) { // really no tokens at all |
499 |
if (tokenList.tokenOrEmbeddingContainer(0) == null) { // really no tokens at all |
475 |
// In this case the token sequence could not be positioned yet |
500 |
// In this case the token sequence could not be positioned yet |
476 |
// so no need to reset "index" or other vars |
501 |
// so no need to reset "index" or other vars |
477 |
return Integer.MAX_VALUE; |
502 |
resetTokenIndex(0); |
|
|
503 |
return offset; |
478 |
} |
504 |
} |
479 |
// Re-get the present token count (could be created a chunk of tokens at once) |
505 |
// Re-get the present token count (could be created a chunk of tokens at once) |
480 |
tokenCount = tokenList.tokenCountCurrent(); |
506 |
tokenCount = tokenList.tokenCountCurrent(); |
Lines 499-512
Link Here
|
499 |
tokenLength = t.length(); |
525 |
tokenLength = t.length(); |
500 |
tokenCount++; |
526 |
tokenCount++; |
501 |
|
527 |
|
502 |
} else { // no more tokens => break |
528 |
} else { // no more tokens => position after last token |
503 |
break; |
529 |
resetTokenIndex(tokenCount); |
|
|
530 |
tokenOffset = prevTokenOffset + tokenLength; // May assign the token's offset in advance |
531 |
return offset - tokenOffset; |
504 |
} |
532 |
} |
505 |
} |
533 |
} |
506 |
tokenIndex = tokenCount - 1; |
534 |
resetTokenIndex(tokenCount - 1); |
507 |
// Absolute token's start offset |
535 |
tokenOffset = prevTokenOffset; // May assign the token's offset in advance |
508 |
tokenOffset = prevTokenOffset; |
|
|
509 |
assignToken(); |
510 |
return offset - prevTokenOffset; |
536 |
return offset - prevTokenOffset; |
511 |
} |
537 |
} |
512 |
|
538 |
|
Lines 525-574
Link Here
|
525 |
high = mid - 1; |
551 |
high = mid - 1; |
526 |
} else { |
552 |
} else { |
527 |
// Token starting exactly at offset found |
553 |
// Token starting exactly at offset found |
528 |
tokenIndex = mid; |
554 |
resetTokenIndex(mid); |
529 |
tokenOffset = midStartOffset; |
555 |
tokenOffset = midStartOffset; |
530 |
assignToken(); |
|
|
531 |
return 0; // right at the token begining |
556 |
return 0; // right at the token begining |
532 |
} |
557 |
} |
533 |
} |
558 |
} |
534 |
|
559 |
|
535 |
// Not found exactly and high + 1 == low => high < low |
560 |
// Not found exactly and high + 1 == low => high < low |
536 |
// Check whether the token at "high" contains the offset |
561 |
// BTW there may be gaps between tokens; if offset is in gap then position to higher token |
537 |
if (high >= 0) { // could be -1 |
562 |
if (high >= 0) { // could be -1 |
538 |
AbstractToken t = LexerUtilsConstants.token(tokenList, high); |
563 |
AbstractToken t = LexerUtilsConstants.token(tokenList, high); |
539 |
prevTokenOffset = tokenList.tokenOffset(high); |
564 |
prevTokenOffset = tokenList.tokenOffset(high); |
|
|
565 |
// If gaps allowed check whether the token at "high" contains the offset |
566 |
if (!tokenList.isContinuous() && offset > prevTokenOffset + t.length()) { |
567 |
// Offset in the gap above the "high" token |
568 |
high++; |
569 |
prevTokenOffset += t.length(); |
570 |
} |
540 |
} else { // at least one token exists => use token at index 0 |
571 |
} else { // at least one token exists => use token at index 0 |
541 |
high = 0; |
572 |
high = 0; |
542 |
prevTokenOffset = tokenList.tokenOffset(0); // result may differ from 0 |
573 |
prevTokenOffset = tokenList.tokenOffset(0); // result may differ from 0 |
543 |
} |
574 |
} |
544 |
|
575 |
resetTokenIndex(high); |
545 |
tokenIndex = high; |
|
|
546 |
tokenOffset = prevTokenOffset; |
576 |
tokenOffset = prevTokenOffset; |
547 |
assignToken(); |
|
|
548 |
return offset - prevTokenOffset; |
577 |
return offset - prevTokenOffset; |
549 |
} |
578 |
} |
550 |
|
579 |
|
551 |
/** |
580 |
/** |
552 |
* Move to the first token in this token sequence. |
|
|
553 |
* |
554 |
* @return true if the sequence was positioned on the first token |
555 |
* or false if there are no tokens in the sequence. |
556 |
*/ |
557 |
public boolean moveFirst() { |
558 |
return moveIndex(0); |
559 |
} |
560 |
|
561 |
/** |
562 |
* Move to the last token in this token sequence. |
563 |
* |
564 |
* @return true if the sequence was positioned on the last token |
565 |
* or false if there are no tokens in the sequence. |
566 |
*/ |
567 |
public boolean moveLast() { |
568 |
return moveIndex(tokenCount() - 1); // Can be -1 but handled in move(index) |
569 |
} |
570 |
|
571 |
/** |
572 |
* Return total count of tokens in this sequence. |
581 |
* Return total count of tokens in this sequence. |
573 |
* <br> |
582 |
* <br> |
574 |
* <b>Note:</b> Calling this method will lead |
583 |
* <b>Note:</b> Calling this method will lead |
Lines 628-642
Link Here
|
628 |
return parentTokenIndexes; |
637 |
return parentTokenIndexes; |
629 |
} |
638 |
} |
630 |
|
639 |
|
631 |
private void assignToken(Object tokenOrEmbeddingContainer) { |
640 |
private void resetTokenIndex(int index) { |
632 |
token = LexerUtilsConstants.token(tokenOrEmbeddingContainer); |
641 |
// Position to the given index e.g. by move() and moveIndex() |
633 |
} |
642 |
tokenIndex = index; |
634 |
|
643 |
token = null; |
635 |
private void assignToken() { |
644 |
tokenOffset = -1; |
636 |
assignToken(tokenList.tokenOrEmbeddingContainer(tokenIndex)); |
|
|
637 |
} |
645 |
} |
638 |
|
646 |
|
639 |
private void checkToken() { |
647 |
private void checkTokenNotNull() { |
640 |
if (token == null) { |
648 |
if (token == null) { |
641 |
throw new IllegalStateException( |
649 |
throw new IllegalStateException( |
642 |
"No token fetched by moveNext() from token sequence yet: index=" + tokenIndex |
650 |
"No token fetched by moveNext() from token sequence yet: index=" + tokenIndex |