1 19 20 package org.netbeans.lib.lexer; 21 22 import java.util.Set ; 23 import org.netbeans.api.lexer.InputAttributes; 24 import org.netbeans.api.lexer.LanguagePath; 25 import org.netbeans.api.lexer.TokenId; 26 import org.netbeans.lib.lexer.token.AbstractToken; 27 28 41 42 public final class SubSequenceTokenList<T extends TokenId> implements TokenList<T> { 43 44 47 private TokenList<T> tokenList; 48 49 52 private AbstractToken<T> lastToken; 53 54 57 private int lastTokenIndex; 58 59 62 private int lastTokenOffset; 63 64 68 private final int limitStartOffset; 69 70 74 private final int limitEndOffset; 75 76 79 private int limitStartIndex; 80 81 84 private int limitEndIndex; 85 86 public SubSequenceTokenList(TokenList<T> tokenList, int limitStartOffset, int limitEndOffset) { 87 this.tokenList = tokenList; 88 this.limitStartOffset = limitStartOffset; 89 this.limitEndOffset = limitEndOffset; 90 91 if (limitStartOffset > 0) { 93 int diff = move(limitStartOffset); 94 if (diff != Integer.MAX_VALUE) { if (diff >= lastToken.length()) { lastTokenIndex++; 97 Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(lastTokenIndex); 98 if (tokenOrEmbeddingContainer != null && 99 (lastTokenOffset = tokenList.tokenOffset(lastTokenIndex)) < limitEndOffset 100 ) { 101 lastToken = LexerUtilsConstants.token(tokenOrEmbeddingContainer); 102 limitStartIndex = lastTokenIndex; 103 limitEndIndex = Integer.MAX_VALUE; } 106 } else { if (limitEndOffset == Integer.MAX_VALUE || lastTokenOffset < limitEndOffset) { 108 limitStartIndex = lastTokenIndex; 109 limitEndIndex = Integer.MAX_VALUE; } } 112 } 114 } else { Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(0); 117 if (tokenOrEmbeddingContainer != null && (lastTokenOffset = tokenList.tokenOffset(0)) < limitEndOffset) { 118 lastToken = LexerUtilsConstants.token(tokenOrEmbeddingContainer); limitEndIndex = Integer.MAX_VALUE; 120 } } 122 } 123 124 public TokenList<T> delegate() { 125 return tokenList; 126 } 127 128 public int limitStartOffset() { 129 return limitStartOffset; 130 } 131 132 public int limitEndOffset() { 133 return limitEndOffset; 134 } 135 136 public Object tokenOrEmbeddingContainer(int index) { 137 if (limitStartIndex == -1) return null; 139 index += limitStartIndex; if (limitEndIndex == Integer.MAX_VALUE) { switch (index - lastTokenIndex) { 142 case -1: if (index < limitStartIndex) 144 return null; 145 Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(index); 146 AbstractToken<T> token = LexerUtilsConstants.token(tokenOrEmbeddingContainer); 147 lastTokenIndex = index; 148 if (tokenList.isContinuous() || lastToken.isFlyweight()) 153 lastTokenOffset = lastTokenOffset - token.length(); 154 else lastTokenOffset = tokenList.tokenOffset(index); 156 lastToken = token; 157 return tokenOrEmbeddingContainer; 158 159 case 0: return lastToken; 161 162 case 1: tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(index); 164 if (tokenOrEmbeddingContainer != null) { 165 token = LexerUtilsConstants.token(tokenOrEmbeddingContainer); 166 int tokenOffset; 171 if (tokenList.isContinuous() || token.isFlyweight()) 172 tokenOffset = lastTokenOffset + lastToken.length(); 173 else tokenOffset = tokenList.tokenOffset(index); 175 if (tokenOffset < limitEndOffset) { lastToken = token; 178 lastTokenIndex = index; 179 lastTokenOffset = tokenOffset; 180 return tokenOrEmbeddingContainer; 181 } } 183 limitEndIndex = index; return null; 185 186 default: tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(index); 188 if (tokenOrEmbeddingContainer != null) { 189 int tokenOffset = tokenList.tokenOffset(index); 190 if (tokenOffset < limitEndOffset) { lastToken = LexerUtilsConstants.token(tokenOrEmbeddingContainer); 193 lastTokenIndex = index; 194 lastTokenOffset = tokenOffset; 195 return tokenOrEmbeddingContainer; 196 } } tokenCount(); 204 return null; 205 } 206 207 } else { return (index < limitEndIndex) 211 ? tokenList.tokenOrEmbeddingContainer(index) 212 : null; 213 } 214 } 215 216 public int tokenOffset(int index) { 217 index += limitStartIndex; 218 if (index == lastTokenIndex) { 219 return lastTokenOffset; 220 } 221 return tokenList.tokenOffset(index); 222 } 223 224 public int tokenCount() { 225 if (limitEndIndex == Integer.MAX_VALUE) { int diff = move(limitEndOffset - 1); 228 assert (diff != Integer.MAX_VALUE); limitEndIndex = lastTokenIndex + 1; } 231 return limitEndIndex - limitStartIndex; 232 } 233 234 public int tokenCountCurrent() { 235 if (limitEndIndex != Integer.MAX_VALUE) return tokenCount(); 237 int tcc = tokenList.tokenCountCurrent(); if (tokenOffset(tcc - 1 - limitStartIndex) >= limitEndOffset) return tokenCount(); 240 return tcc - limitStartIndex; 241 } 242 243 public AbstractToken<T> replaceFlyToken(int index, AbstractToken<T> flyToken, int offset) { 244 return tokenList.replaceFlyToken(index + limitStartIndex, flyToken, offset); 245 } 246 247 public int modCount() { 248 return tokenList.modCount(); 249 } 250 251 public LanguagePath languagePath() { 252 return tokenList.languagePath(); 253 } 254 255 public int childTokenOffset(int rawOffset) { 256 throw new IllegalStateException ("Unexpected call."); 257 } 258 259 public char childTokenCharAt(int rawOffset, int index) { 260 throw new IllegalStateException ("Unexpected call."); 261 } 262 263 public void wrapToken(int index, EmbeddingContainer<T> embeddingContainer) { 264 tokenList.wrapToken(limitStartIndex + index, embeddingContainer); 265 } 266 267 public TokenList<? extends TokenId> root() { 268 return tokenList.root(); 269 } 270 271 public TokenHierarchyOperation<?,? extends TokenId> tokenHierarchyOperation() { 272 return tokenList.tokenHierarchyOperation(); 273 } 274 275 public InputAttributes inputAttributes() { 276 return tokenList.inputAttributes(); 277 } 278 279 public int lookahead(int index) { 280 return tokenList.lookahead(index); 282 } 283 284 public Object state(int index) { 285 return tokenList.state(index); 286 } 287 288 public boolean isContinuous() { 289 return tokenList.isContinuous(); 290 } 291 292 public Set <T> skipTokenIds() { 293 return tokenList.skipTokenIds(); 294 } 295 296 private AbstractToken<T> token(int index) { 297 return LexerUtilsConstants.token(tokenList, index); 298 } 299 300 309 private int move(int offset) { 310 int tokenCount = tokenList.tokenCountCurrent(); if (tokenCount == 0) { if (tokenList.tokenOrEmbeddingContainer(0) == null) { return Integer.MAX_VALUE; 316 } 317 tokenCount = tokenList.tokenCountCurrent(); 319 } 320 321 lastTokenOffset = tokenList.tokenOffset(tokenCount - 1); 323 if (offset > lastTokenOffset) { lastToken = token(tokenCount - 1); 328 int tokenLength = lastToken.length(); 329 while (offset >= lastTokenOffset + tokenLength) { Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(tokenCount); 331 if (tokenOrEmbeddingContainer != null) { 332 lastToken = LexerUtilsConstants.token(tokenOrEmbeddingContainer); 333 if (lastToken.isFlyweight()) { lastTokenOffset += tokenLength; 335 } else { lastTokenOffset = tokenList.tokenOffset(tokenCount); 337 } 338 tokenLength = lastToken.length(); 339 tokenCount++; 340 341 } else { break; 343 } 344 } 345 lastTokenIndex = tokenCount - 1; 346 return offset - lastTokenOffset; 347 } 348 349 int low = 0; 352 int high = tokenCount - 1; 353 354 while (low <= high) { 355 int mid = (low + high) / 2; 356 int midStartOffset = tokenList.tokenOffset(mid); 357 358 if (midStartOffset < offset) { 359 low = mid + 1; 360 } else if (midStartOffset > offset) { 361 high = mid - 1; 362 } else { lastToken = token(mid); 364 lastTokenIndex = mid; 365 lastTokenOffset = midStartOffset; 366 return 0; } 368 } 369 370 if (high < 0) { high = 0; 374 } 375 lastToken = token(high); 376 lastTokenOffset = tokenList.tokenOffset(high); 377 lastTokenIndex = high; 378 return offset - lastTokenOffset; 379 } 380 381 } | Popular Tags |