package com.github.elucash.lambda4jdt;
import static org.eclipse.jdt.core.compiler.ITerminalSymbols.*;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.InvalidInputException;
class ScannerHelper {
final IScanner scanner;
boolean eof;
int token = -1;
int offset = -1;
int endOffset = -1;
char[] identifier;
int firstNonWhitespace = -1;
int identifierOffset = -1;
boolean wasFlowControlStatement;
int lastBraceBlockEnd = -1;
ScannerHelper(String source) {
this.scanner = ToolFactory.createScanner(false, false, true, true);
char[] charArraySource = source.toCharArray();
scanner.setSource(charArraySource);
scanner.resetTo(0, charArraySource.length);
}
private int updateFields(int lastToken) {
if (lastToken == TokenNameEOF) {
eof = true;
token = -1;
endOffset = -1;
offset = -1;
} else {
token = lastToken;
offset = scanner.getCurrentTokenStartPosition();
endOffset = scanner.getCurrentTokenEndPosition();
eof = false;
}
return token;
}
private void resetFieldsBeforeSeek() {
wasFlowControlStatement = false;
lastBraceBlockEnd = -1;
firstNonWhitespace = -1;
identifier = null;
identifierOffset = -1;
}
private int nextToken() throws InvalidInputException {
int t = scanner.getNextToken();
if (t == TokenNameIdentifier) {
identifier = scanner.getCurrentTokenSource();
identifierOffset = scanner.getCurrentTokenStartPosition();
}
if (t != TokenNameWHITESPACE && firstNonWhitespace < 0) {
firstNonWhitespace = scanner.getCurrentTokenStartPosition();
}
if (t == TokenNamewhile || t == TokenNamedo || t == TokenNameif || t == TokenNamefor ||
t == TokenNametry) {
wasFlowControlStatement = true;
}
return t;
}
int[] lineEnds() {
return scanner.getLineEnds();
}
int seek(int... tokensToSeek) {
resetFieldsBeforeSeek();
try {
for (;;) {
int t = nextToken();
if (t == TokenNameEOF)
return updateFields(t);
for (int i : tokensToSeek) {
if (i == t)
return updateFields(t);
}
}
} catch (InvalidInputException e) {}
return -1;
}
int seekAnyExcept(int... tokensToSeekExcept) {
resetFieldsBeforeSeek();
try {
for (;;) {
int t = nextToken();
if (t == TokenNameEOF)
return updateFields(t);
for (int i : tokensToSeekExcept)
if (i == t)
continue;
return updateFields(t);
}
} catch (InvalidInputException e) {}
return -1;
}
int seekCorrespondingWithTypeParameterBrackets(int... tokensToSeek) {
resetFieldsBeforeSeek();
try {
for (int nestingLevel = 0;;) {
int t = nextToken();
if (t == TokenNameEOF)
return updateFields(t);
if (nestingLevel <= 0)
for (int i : tokensToSeek)
if (i == t)
return updateFields(t);
switch (t) {
case TokenNameLPAREN:
case TokenNameLBRACE:
case TokenNameLESS:
nestingLevel++;
break;
case TokenNameRIGHT_SHIFT:
nestingLevel-=2;
break;
case TokenNameUNSIGNED_RIGHT_SHIFT:
nestingLevel-=3;
break;
case TokenNameGREATER:
nestingLevel--;
break;
case TokenNameRPAREN:
nestingLevel--;
break;
case TokenNameRBRACE:
nestingLevel--;
lastBraceBlockEnd = scanner.getCurrentTokenStartPosition();
break;
}
}
} catch (InvalidInputException e) {}
return -1;
}
int seekCorresponding(int... tokensToSeek) {
resetFieldsBeforeSeek();
try {
for (int nestingLevel = 0;;) {
int t = nextToken();
if (t == TokenNameEOF)
return updateFields(t);
if (nestingLevel <= 0)
for (int i : tokensToSeek)
if (i == t)
return updateFields(t);
switch (t) {
case TokenNameLPAREN:
case TokenNameLBRACE:
nestingLevel++;
break;
case TokenNameRPAREN:
nestingLevel--;
break;
case TokenNameRBRACE:
nestingLevel--;
lastBraceBlockEnd = scanner.getCurrentTokenStartPosition();
break;
}
}
} catch (InvalidInputException e) {}
return -1;
}
}