1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.parser.diagnose;
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.core.compiler.InvalidInputException;
15 import org.eclipse.jdt.internal.compiler.parser.Scanner;
16 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
18 public class LexStream implements TerminalTokens {
19 public static final int IS_AFTER_JUMP = 1;
20 public static final int LBRACE_MISSING = 2;
30 public String toString() {
31 StringBuffer buffer = new StringBuffer();
32 buffer.append(name).append('[').append(kind).append(']');
33 buffer.append('{').append(start).append(',').append(end).append('}').append(line);
34 return buffer.toString();
39 private int tokenCacheIndex;
40 private int tokenCacheEOFIndex;
41 private Token[] tokenCache;
43 private int currentIndex = -1;
45 private Scanner scanner;
46 private int[] intervalStartToSkip;
47 private int[] intervalEndToSkip;
48 private int[] intervalFlagsToSkip;
50 private int previousInterval = -1;
52 public LexStream(int size, Scanner scanner, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip, int firstToken, int init, int eof) {
53 this.tokenCache = new Token[size];
54 this.tokenCacheIndex = 0;
55 this.tokenCacheEOFIndex = Integer.MAX_VALUE;
56 this.tokenCache[0] = new Token();
57 this.tokenCache[0].kind = firstToken;
58 this.tokenCache[0].name = CharOperation.NO_CHAR;
59 this.tokenCache[0].start = init;
60 this.tokenCache[0].end = init;
61 this.tokenCache[0].line = 0;
63 this.intervalStartToSkip = intervalStartToSkip;
64 this.intervalEndToSkip = intervalEndToSkip;
65 this.intervalFlagsToSkip = intervalFlagsToSkip;
67 scanner.resetTo(init, eof);
68 this.scanner = scanner;
71 private void readTokenFromScanner(){
72 int length = tokenCache.length;
73 boolean tokenNotFound = true;
75 while(tokenNotFound) {
77 int tokenKind = scanner.getNextToken();
78 if(tokenKind != TokenNameEOF) {
79 int start = scanner.getCurrentTokenStartPosition();
80 int end = scanner.getCurrentTokenEndPosition();
81 if(!RangeUtil.isInInterval(start, end, intervalStartToSkip, intervalEndToSkip)) {
82 Token token = new Token();
83 token.kind = tokenKind;
84 token.name = scanner.getCurrentTokenSource();
87 token.line = scanner.getLineNumber(end);
89 int pInterval = RangeUtil.getPreviousInterval(start, end, intervalStartToSkip, intervalEndToSkip);
90 if(pInterval != previousInterval && (intervalFlagsToSkip[previousInterval + 1] & RangeUtil.IGNORE) == 0){
91 token.flags = IS_AFTER_JUMP;
92 if((intervalFlagsToSkip[pInterval] & RangeUtil.LBRACE_MISSING) != 0){
93 token.flags |= LBRACE_MISSING;
96 previousInterval = pInterval;
98 tokenCache[++tokenCacheIndex % length] = token;
100 tokenNotFound = false;
103 int start = scanner.getCurrentTokenStartPosition();
104 int end = scanner.getCurrentTokenEndPosition();
105 Token token = new Token();
106 token.kind = tokenKind;
107 token.name = CharOperation.NO_CHAR;
110 token.line = scanner.getLineNumber(end);
112 tokenCache[++tokenCacheIndex % length] = token;
114 tokenCacheEOFIndex = tokenCacheIndex;
115 tokenNotFound = false;
117 } catch (InvalidInputException e) {
123 public Token token(int index) {
125 Token eofToken = new Token();
126 eofToken.kind = TokenNameEOF;
127 eofToken.name = CharOperation.NO_CHAR;
130 if(this.tokenCacheEOFIndex >= 0 && index > this.tokenCacheEOFIndex) {
131 return token(this.tokenCacheEOFIndex);
133 int length = tokenCache.length;
134 if(index > this.tokenCacheIndex) {
135 int tokensToRead = index - this.tokenCacheIndex;
136 while(tokensToRead-- != 0) {
137 readTokenFromScanner();
139 } else if(this.tokenCacheIndex - length >= index) {
143 return tokenCache[index % length];
148 public int getToken() {
149 return currentIndex = next(currentIndex);
152 public int previous(int tokenIndex) {
153 return tokenIndex > 0 ? tokenIndex - 1 : 0;
156 public int next(int tokenIndex) {
157 return tokenIndex < this.tokenCacheEOFIndex ? tokenIndex + 1 : this.tokenCacheEOFIndex;
160 public boolean afterEol(int i) {
161 return i < 1 ? true : line(i - 1) < line(i);
164 public void reset() {
168 public void reset(int i) {
169 currentIndex = previous(i);
172 public int badtoken() {
176 public int kind(int tokenIndex) {
177 return token(tokenIndex).kind;
180 public char[] name(int tokenIndex) {
181 return token(tokenIndex).name;
184 public int line(int tokenIndex) {
185 return token(tokenIndex).line;
188 public int start(int tokenIndex) {
189 return token(tokenIndex).start;
192 public int end(int tokenIndex) {
193 return token(tokenIndex).end;
196 public int flags(int tokenIndex) {
197 return token(tokenIndex).flags;
200 public boolean isInsideStream(int index) {
201 if(this.tokenCacheEOFIndex >= 0 && index > this.tokenCacheEOFIndex) {
203 } else if(index > this.tokenCacheIndex) {
205 } else if(this.tokenCacheIndex - tokenCache.length >= index) {
213 * @see java.lang.Object#toString()
215 public String toString() {
216 StringBuffer res = new StringBuffer();
218 String source = new String(scanner.source);
219 if(currentIndex < 0) {
222 Token token = token(currentIndex);
223 int curtokKind = token.kind;
224 int curtokStart = token.start;
225 int curtokEnd = token.end;
227 int previousEnd = -1;
228 for (int i = 0; i < intervalStartToSkip.length; i++) {
229 int intervalStart = intervalStartToSkip[i];
230 int intervalEnd = intervalEndToSkip[i];
232 if(curtokStart >= previousEnd && curtokEnd <= intervalStart) {
233 res.append(source.substring(previousEnd + 1, curtokStart));
236 res.append(source.substring(curtokStart, curtokEnd + 1));
239 res.append(source.substring(curtokEnd+1, intervalStart));
241 res.append(source.substring(previousEnd + 1, intervalStart));
245 res.append(source.substring(intervalStart, intervalEnd + 1));
249 previousEnd = intervalEnd;
251 if(curtokStart >= previousEnd) {
252 res.append(source.substring(previousEnd + 1, curtokStart));
255 if(curtokKind == TokenNameEOF) {
256 res.append("EOF#>"); //$NON-NLS-1$
258 res.append(source.substring(curtokStart, curtokEnd + 1));
261 res.append(source.substring(curtokEnd+1));
264 res.append(source.substring(previousEnd + 1));
268 return res.toString();