1 19 20 package org.netbeans.lib.lexer; 21 22 import org.netbeans.lib.editor.util.ArrayUtilities; 23 import org.netbeans.lib.lexer.token.AbstractToken; 24 import org.netbeans.spi.lexer.CharPreprocessor; 25 import org.netbeans.spi.lexer.LexerInput; 26 27 28 41 42 public final class CharPreprocessorOperation implements CharProvider { 43 44 45 private static final boolean testing = Boolean.getBoolean("netbeans.debug.lexer.test"); 46 47 50 private CharProvider parent; 51 52 53 private CharPreprocessor preprocessor; 54 55 59 private int readIndex; 60 61 66 private int lookaheadIndex; 67 68 72 private int prepStartIndex; 73 74 80 private int prepEndIndex; 81 82 92 private char[] prepChars = ArrayUtilities.emptyCharArray(); 93 94 103 private int[] rawLengthShifts; 104 105 108 private int lastOutputChar; 109 110 111 private int tokenLength; 112 113 private LexerInputOperation lexerInputOperation; 114 115 private int tokenEndRawLengthShift; 116 117 121 CharPreprocessorOperation(CharProvider parent, CharPreprocessor preprocessor, 122 LexerInputOperation lexerInputOperation) { 123 this.parent = parent; 124 this.preprocessor = preprocessor; 125 this.lexerInputOperation = lexerInputOperation; 126 LexerSpiPackageAccessor.get().init(preprocessor, this); 128 } 129 130 136 public void initApprovedToken(AbstractToken token) { 137 138 } 139 140 149 public int inputRead() { 150 return parent.read(); 151 } 152 153 public void inputBackup(int count) { 154 parent.backup(count); 155 } 156 157 public void outputOriginal(int ch) { 158 lastOutputChar = ch; 159 if (ch != LexerInput.EOF) { 160 if (prepStartIndex == lookaheadIndex) { prepStartIndex++; 162 } else { } 165 lookaheadIndex++; 166 } 167 } 168 169 public void outputPreprocessed(char ch, int extraInputLength) { 170 lastOutputChar = ch; 171 if (prepStartIndex == lookaheadIndex) { prepEndIndex = prepStartIndex; 173 } else if (prepEndIndex < lookaheadIndex) { 174 do { 176 addPrepChar(parent.readExisting(prepEndIndex), 0); 177 } while (prepEndIndex < lookaheadIndex); 178 } addPrepChar(ch, extraInputLength); 180 lookaheadIndex++; } 182 183 public int deepRawLength(int length) { 184 return parent.deepRawLength(parentLength(length)); 185 } 186 187 public int deepRawLengthShift(int index) { 188 return rawLengthShift(index) + parent.deepRawLengthShift(index); 189 } 190 191 private int rawLengthShift(int index) { 192 if (index < prepStartIndex) { 193 return index; 194 } else if (index < prepEndIndex) { 195 return rawLengthShifts[index - prepStartIndex]; 196 } else { 197 return totalRawLengthShift(); 198 } 199 } 200 201 204 private int parentLength(int length) { 205 System.out.println("STATUS: length=" + length + ", " + this); 206 if (length > prepStartIndex) { 207 if (length <= prepEndIndex) { 208 length += rawLengthShifts[length - 1 - prepStartIndex]; 209 } else { 210 length += totalRawLengthShift(); 211 } 212 } 213 return length; 214 } 215 216 private int totalRawLengthShift() { 217 return rawLengthShifts[prepEndIndex - 1 - prepStartIndex]; 218 } 219 220 public void notifyError(String errorMessage) { 221 if (lexerInputOperation != null) { 222 int parentIndex = parent.readIndex(); lexerInputOperation.notifyPreprocessorError( 224 new CharPreprocessorError(errorMessage, parent.deepRawLength(parentIndex))); 225 } 226 } 227 228 public int read() { 229 if (readIndex == lookaheadIndex) { 231 LexerSpiPackageAccessor.get().preprocessChar(preprocessor); 233 readIndex++; 234 if (readIndex == lookaheadIndex) { 236 return lastOutputChar; 237 } else { readIndex--; 239 if (readIndex == lookaheadIndex && lastOutputChar == LexerInput.EOF) { 241 return LexerInput.EOF; 242 } 243 } 244 245 } 246 247 return readExisting(readIndex++); 248 } 249 250 public char readExisting(int index) { 251 return (index < prepStartIndex) ? parent.readExisting(index) 253 : (index < prepEndIndex) ? prepChars[index - prepStartIndex] 255 : parent.readExisting(index + totalRawLengthShift()); 256 } 257 258 public int readIndex() { 259 return readIndex; 260 } 261 262 public void backup(int count) { 263 readIndex -= count; 264 } 265 266 public int tokenLength() { 267 return tokenLength; 268 } 269 270 public void tokenRecognized(int tokenLength) { 271 this.tokenLength = tokenLength; 272 parent.tokenRecognized(parentLength(tokenLength)); 274 } 275 276 public PreprocessedTextStorage createPreprocessedTextStorage(CharSequence rawText, 277 CharProvider.ExtraPreprocessedChars epc) { 278 int pStartIndex; 279 int pEndIndex; 280 int topEndIndex; 281 if (prepStartIndex >= tokenLength) { 282 if (prepEndIndex > tokenLength) { 283 updateTokenEndRawLengthShift(); 284 pEndIndex = tokenLength - 1; 285 while (--pEndIndex >= prepStartIndex && rawLengthShifts[pEndIndex] == tokenEndRawLengthShift) { } 290 pEndIndex += 2; 291 } else pEndIndex = prepEndIndex; 293 topEndIndex = parentLength(pEndIndex); 294 295 for (int i = prepStartIndex; i < pEndIndex; i++) { 297 rawLengthShifts[i - prepStartIndex] = deepRawLength(i + 1) - (i + 1); 298 } 299 pStartIndex = prepStartIndex; 300 301 } else { pStartIndex = tokenLength; 303 pEndIndex = tokenLength; 304 topEndIndex = tokenLength; 305 } 306 307 PreprocessedTextStorage prepStorage; 308 if (epc != null) { 309 parent.collectExtraPreprocessedChars(epc, pStartIndex, pEndIndex, topEndIndex); 310 prepStorage = PreprocessedTextStorage.create(rawText, 311 prepChars, pEndIndex - pStartIndex, pStartIndex, rawLengthShifts, 312 epc.extraPrepChars(), epc.extraRawLengthShifts(), 313 epc.preStartIndex(), epc.postEndIndex()); 314 epc.clear(); 315 316 } else { prepStorage = PreprocessedTextStorage.create(rawText, 318 prepChars, pEndIndex - pStartIndex, pStartIndex, rawLengthShifts); 319 } 320 return prepStorage; 321 } 322 323 private void updateTokenEndRawLengthShift() { 324 tokenEndRawLengthShift = rawLengthShifts[tokenLength - 1 - prepStartIndex]; 325 } 326 327 public void collectExtraPreprocessedChars(ExtraPreprocessedChars epc, 328 int prepStartIndex, int prepEndIndex, int topPrepEndIndex) { 329 if (prepStartIndex < tokenLength) { int preCount = Math.max(prepStartIndex - this.prepStartIndex, 0); 332 int postCount; 334 if (this.prepEndIndex > tokenLength) { 335 updateTokenEndRawLengthShift(); 336 postCount = tokenLength - prepEndIndex; 337 if (postCount > 0) { 338 int i = tokenLength - 2; 339 while (--i >= prepStartIndex && postCount > 0 && rawLengthShifts[i] == tokenEndRawLengthShift) { postCount--; 344 } 345 } else postCount = 0; 347 348 } else { postCount = this.prepEndIndex - prepEndIndex; 350 } 351 352 assert (preCount >= 0 && postCount >= 0); 353 epc.ensureExtraLength(preCount + postCount); 354 while (--preCount >= 0) { 355 epc.insert(readExisting(prepStartIndex - 1), deepRawLength(prepStartIndex) - prepStartIndex); 356 prepStartIndex--; 357 } 358 while (--postCount >= 0) { 359 epc.append(readExisting(prepEndIndex), deepRawLength(prepEndIndex) - topPrepEndIndex); 360 prepEndIndex++; 361 topPrepEndIndex++; 362 } 363 } 364 365 parent.collectExtraPreprocessedChars(epc, prepStartIndex, prepEndIndex, topPrepEndIndex); 366 } 367 368 372 public void tokenApproved() { 373 if (prepStartIndex != lookaheadIndex) { if (prepStartIndex < tokenLength) { if (prepEndIndex <= tokenLength) { prepStartIndex = lookaheadIndex; } else { for (int i = tokenLength; i < prepEndIndex; i++) { 380 rawLengthShifts[i] -= tokenEndRawLengthShift; 381 } 382 System.arraycopy(prepChars, prepStartIndex, prepChars, 0, 383 prepEndIndex - prepStartIndex); 384 System.arraycopy(rawLengthShifts, prepStartIndex, rawLengthShifts, 0, 385 prepEndIndex - prepStartIndex); 386 prepStartIndex = 0; 387 prepEndIndex -= tokenLength; 388 } 389 390 } else { prepStartIndex -= tokenLength; 392 prepEndIndex -= tokenLength; 393 } 394 } else 395 prepStartIndex -= tokenLength; 396 397 readIndex -= tokenLength; 398 lookaheadIndex -= tokenLength; 399 parent.tokenApproved(); 400 401 if (testing) 402 consistencyCheck(); 403 } 404 405 408 private void addPrepChar(char ch, int extraInputLength) { 409 int prepCharsLength = prepEndIndex - prepStartIndex; 410 if (prepCharsLength == prepChars.length) { prepChars = ArrayUtilities.charArray(prepChars); 412 rawLengthShifts = ArrayUtilities.intArray(rawLengthShifts); 413 } 414 prepChars[prepCharsLength] = ch; 415 int prevRawLengthShift = (prepCharsLength > 0) 416 ? rawLengthShifts[prepCharsLength -1] 417 : 0; 418 rawLengthShifts[prepCharsLength] = prevRawLengthShift + extraInputLength; 419 prepEndIndex++; 420 } 421 422 private void consistencyCheck() { 423 if (readIndex > lookaheadIndex) { 424 throw new IllegalStateException ("readIndex > lookaheadIndex: " + this); 425 } 426 if (prepStartIndex > lookaheadIndex) { 427 throw new IllegalStateException ("prepStartIndex > lookaheadIndex: " + this); 428 } 429 if (prepStartIndex != lookaheadIndex && prepStartIndex >= prepEndIndex) { 430 throw new IllegalStateException ("prepStartIndex >= prepEndIndex: " + this); 431 } 432 } 433 434 public String toString() { 435 StringBuilder sb = new StringBuilder (); 436 sb.append("readIndex="); 437 sb.append(readIndex); 438 sb.append(", lookaheadIndex="); 439 sb.append(lookaheadIndex); 440 sb.append(", prepStartIndex="); 441 sb.append(prepStartIndex); 442 sb.append(", prepEndIndex="); 443 sb.append(prepEndIndex); 444 return sb.toString(); 445 } 446 447 } 448 | Popular Tags |