/*******************************************************************************
 * Copyright (c) 2000, 2021 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
 *     Jesper S Moller  -. Contribution for bug 400830: [1.8][formatter] Code formatter for Java 8
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.parser;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.JavaFeature;
import org.eclipse.jdt.internal.compiler.parser.diagnose.DiagnoseParser;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.CharDeduplication;
import org.eclipse.jdt.internal.compiler.util.Util;

/**
 * OTDT changes:
 *
 * Added keywords: base tsuper callin within playedBy precedence with team as when
 *
 * Contextual keywords: replace after before get set
 * 		These are recognized as keywords only after the corresponding symbol <- or ->.
 *
 * IMPORTANT NOTE: Internal Scanner implementation. It is mirrored in
 * org.eclipse.jdt.core.compiler public package where it is API.
 * The mirror implementation is using the backward compatible ITerminalSymbols constant
 * definitions (stable with 2.0), whereas the internal implementation uses TerminalTokens
 * which constant values reflect the latest parser generation state.
 */
public class Scanner implements TerminalTokens {

	//public int newIdentCount = 0;

	/* APIs ares
	 - getNextToken() which return the current type of the token
	   (this value is not memorized by the scanner)
	 - getCurrentTokenSource() which provides with the token "REAL" source
	   (aka all unicode have been transformed into a correct char)
	 - sourceStart gives the position into the stream
	 - currentPosition-1 gives the sourceEnd position into the stream
	*/
	public long sourceLevel;
	public long complianceLevel;

	// 1.4 feature
	public boolean useAssertAsAnIndentifier = false;
	//flag indicating if processed source contains occurrences of keyword assert
	public boolean containsAssertKeyword = false;
	public boolean previewEnabled;

	// 1.5 feature
	public boolean useEnumAsAnIndentifier = false;

//{ObjectTeams: the scanner is now quite stateful:
	// a master switch to turn off all OT keywords:
	public boolean parsePureJavaOnly = false;
	// experimental switch, set to true if you encounter problems with the scanner:
	public boolean parseOTJonly = true;

	// general switch for std-Java vs. OT/J
	protected boolean _isOTSource = this.parseOTJonly; // initialized also in setSource().
	/** Fully enable OT/J keywords. */
    public void enterOTSource() {
    	this._isOTSource = true;
    	this._teamKeywordSeen = false; // not needed any more
    }

    //  within the body of a base predicate "base" is not a keyword
    protected boolean _forceBaseIsIdentifier = false;
    // seen 'team' but no 'class'/'interface' yet -> 'base' could still be an imported package name.
    protected boolean _teamKeywordSeen = false;
    // directly after 'import' 'base' is always a keyword/modifier:
    protected boolean _atStartOfImport = false;
    public void forceBaseIsIdentifier() {
    	this._forceBaseIsIdentifier = true;
    }
    public void restoreBaseKeyword() {
    	this._forceBaseIsIdentifier = false;
    }
    protected boolean baseIsKeyword(boolean atStartOfImport) {
    	if (this.parsePureJavaOnly)
    		return false;
    	// "base" keyword may appear before 'class' header of containing
    	// team/role has been consumed.
    	if (this.currentCharacter == '.')
    		atStartOfImport = false;
    	return (this._isOTSource || atStartOfImport) && !this._forceBaseIsIdentifier;
    }

    // remember if the previous token was a callin/callout symbol ...
    protected boolean _calloutSeen = false;
    protected boolean _callinSeen = false;
    // ... or the "precedence" keyword
	public boolean _precedenceSeen = false;

    // after a '.' even 'team' can be an identifier:
    protected int _dotSeen = 0; // 0: no, 1: previos, 2: this token

    public boolean _insideParameterMapping = false;
    enum LookaheadState { INIT, ONE_TOKEN, ID_SEEN, TWO_TOKENS, ID_CONSUMED }
    /**
     * A little state machine for lookahead of up-to 2 tokens.
     * This is used to disambiguate whether a '->' inside parameter mappings is
     * an ARROW (lambda) or a BINDOUT (parameter mapping role-to-base)
     */
    protected class BindoutLookahead {

    	LookaheadState state = LookaheadState.INIT;
    	int[] tokens = new int[2];
    	char[] identifier = null;
    	int[][] positions = new int[2][];

		public BindoutLookahead() throws InvalidInputException {
			int token = this.tokens[0] = getNextToken0();
			this.positions[0] = new int[] {Scanner.this.startPosition, Scanner.this.currentPosition};
			if (token == TerminalTokens.TokenNameIdentifier) {
				this.state = LookaheadState.ID_SEEN;
				this.identifier = getCurrentIdentifierSource();
			}
		}
		public char[] getIdentifier() {
			if (this.state == LookaheadState.TWO_TOKENS) {
				return this.identifier;
			}
			return null;
		}
		public int getNextToken() throws InvalidInputException {
			switch (this.state) {
				case INIT :
					// == initialization failed to match anything	=> signal no match
					this.state = LookaheadState.ONE_TOKEN;
					return TerminalTokens.TokenNameNotAToken;
				case ONE_TOKEN :
					// == we have one non-matching token			=> pop that token and unregister
					Scanner.this._bindoutLookahead = null;
					return popToken(0);
				case ID_SEEN :
					// == we've seen an identifier					=> check if second token matches, too
					this.tokens[1] = Scanner.this.getNextToken0();
					this.positions[1] = new int[] {Scanner.this.startPosition, Scanner.this.currentPosition};
					this.state = LookaheadState.TWO_TOKENS;
					switch (this.tokens[1]) {
						case TerminalTokens.TokenNameCOMMA :	  // more mappings?
						case TerminalTokens.TokenNameSEMICOLON :  // more mappings? (wrong delimiter, though)
						case TerminalTokens.TokenNameRBRACE :	  // end of parameter mappings?
							return TokenNameBINDOUT; 			  // match, tweak '->' to mean BINDOUT
						default:
							return TerminalTokens.TokenNameARROW; // no match, '->' should be interpreted as normal
					}
				case TWO_TOKENS :
					// == we've seen & stored two tokens			=> pop the identifier now
					this.state = LookaheadState.ID_CONSUMED;
					return popToken(0);
				case ID_CONSUMED :
					// == identifier has already been consumed		=> pop the second token and unregister
					Scanner.this._bindoutLookahead = null;
					return popToken(1);
			}
			return TerminalTokens.TokenNameNotAToken;
		}
		private int popToken(int i) {
			Scanner.this.startPosition = this.positions[i][0];
			Scanner.this.currentPosition = this.positions[i][1];
			return this.tokens[i];
		}
    }
    protected BindoutLookahead _bindoutLookahead = null;

    public char[] peekPendingIdentifier() {
    	if (this._bindoutLookahead != null)
    		return this._bindoutLookahead.identifier;
    	return null;
    }

    public void resetOTFlags() {
    	this._isOTSource = this.parseOTJonly;
    	this._teamKeywordSeen = false;
    	this._forceBaseIsIdentifier = false;
    	this._callinSeen = false;
    	this._calloutSeen = false;
    	this._insideParameterMapping = false;
    	this._bindoutLookahead = null;
    }

    public void setOTFlags(CompilerOptions options) {
	    this.parseOTJonly = !options.allowScopedKeywords;
	    this.parsePureJavaOnly = options.isPureJava;
    }

    public void copyOTFlags(Scanner other) {
    	this.parseOTJonly = other.parseOTJonly;
    	this.parsePureJavaOnly = other.parsePureJavaOnly;
    }

    /**
     * Check whether a given terminal token is currently enabled.
     * Some keywords can be disabled:
     *    (base) as callin playedBy precedence tsuper when with
     * Only within a join point query:
     *    # .. elementof
     * Some keyworkds can only be disabled by parsePureJavaOnly:
     *    team within
     */
    public boolean isTokenEnabled(int sym) {
    	switch (sym) {
    	case TokenNameteam:
    	case TokenNamewithin:
    		return !this.parsePureJavaOnly;

    	case TokenNamebase:
    		return baseIsKeyword(false);
    	case TokenNameas:
    	case TokenNameBINDIN:
    	case TokenNameBINDOUT:
    	case TokenNamecallin:
    	case TokenNameplayedBy:
    	case TokenNameprecedence:
    	case TokenNametsuper:
    	case TokenNamewhen:
    		return this._isOTSource;
    	case TokenNamewith:
    		return this._isOTSource || this.insideModuleInfo;
    	}
    	return true;
    }
// SH}

	public boolean recordLineSeparator = false;
	public char currentCharacter;
	public int startPosition;
	public int currentPosition;
	public int initialPosition, eofPosition;
	// after this position eof are generated instead of real token from the source

	public boolean skipComments = false;
	public boolean tokenizeComments = false;
	public boolean tokenizeWhiteSpace = false;

	//source should be viewed as a window (aka a part)
	//of a entire very large stream
	public char source[];

	//unicode support
	public char[] withoutUnicodeBuffer;
	public int withoutUnicodePtr; //when == 0 ==> no unicode in the current token
	public boolean unicodeAsBackSlash = false;

	public boolean scanningFloatLiteral = false;

	//support for /** comments
	public final static int COMMENT_ARRAYS_SIZE = 30;
	public int[] commentStops = new int[COMMENT_ARRAYS_SIZE];
	public int[] commentStarts = new int[COMMENT_ARRAYS_SIZE];
	public int[] commentTagStarts = new int[COMMENT_ARRAYS_SIZE];
	public int commentPtr = -1; // no comment test with commentPtr value -1
	public int lastCommentLinePosition = -1;

	// task tag support
	public char[][] foundTaskTags = null;
	public char[][] foundTaskMessages;
	public char[][] foundTaskPriorities = null;
	public int[][] foundTaskPositions;
	public int foundTaskCount = 0;
	public char[][] taskTags = null;
	public char[][] taskPriorities = null;
	public boolean isTaskCaseSensitive = true;

	//diet parsing support - jump over some method body when requested
	public boolean diet = false;

	//support for the  poor-line-debuggers ....
	//remember the position of the cr/lf
	public int[] lineEnds = new int[250];
	public int linePtr = -1;
	public boolean wasAcr = false;

	public boolean fakeInModule = false;
	public int caseStartPosition = -1;
	boolean inCondition = false;
	/* package */ int yieldColons = -1;
	boolean breakPreviewAllowed = false;
	/**
	 * The current context of the scanner w.r.t restricted keywords
	 *
	 */
	enum ScanContext {
		EXPECTING_KEYWORD, EXPECTING_IDENTIFIER, AFTER_REQUIRES, INACTIVE
	}
	protected ScanContext scanContext = null;
	protected boolean insideModuleInfo = false;
	public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$

	public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$
	public static final String INVALID_OCTAL = "Invalid_Octal_Literal"; //$NON-NLS-1$
	public static final String INVALID_CHARACTER_CONSTANT = "Invalid_Character_Constant";  //$NON-NLS-1$
	public static final String INVALID_ESCAPE = "Invalid_Escape"; //$NON-NLS-1$
	public static final String INVALID_INPUT = "Invalid_Input"; //$NON-NLS-1$
	public static final String INVALID_TEXTBLOCK = "Invalid_Textblock"; //$NON-NLS-1$
	public static final String INVALID_UNICODE_ESCAPE = "Invalid_Unicode_Escape"; //$NON-NLS-1$
	public static final String INVALID_FLOAT = "Invalid_Float_Literal"; //$NON-NLS-1$
	public static final String INVALID_LOW_SURROGATE = "Invalid_Low_Surrogate"; //$NON-NLS-1$
	public static final String INVALID_HIGH_SURROGATE = "Invalid_High_Surrogate"; //$NON-NLS-1$

	public static final String NULL_SOURCE_STRING = "Null_Source_String"; //$NON-NLS-1$
	public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$
	public static final String UNTERMINATED_TEXT_BLOCK = "Unterminated_Text_Block"; //$NON-NLS-1$
	public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
	public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
	public static final String INVALID_DIGIT = "Invalid_Digit"; //$NON-NLS-1$
	private static final int[] EMPTY_LINE_ENDS = Util.EMPTY_INT_ARRAY;

	public static final String INVALID_BINARY = "Invalid_Binary_Literal"; //$NON-NLS-1$
	public static final String BINARY_LITERAL_NOT_BELOW_17 = "Binary_Literal_Not_Below_17"; //$NON-NLS-1$
	public static final String ILLEGAL_HEXA_LITERAL = "Illegal_Hexa_Literal"; //$NON-NLS-1$
	public static final String INVALID_UNDERSCORE = "Invalid_Underscore"; //$NON-NLS-1$
	public static final String UNDERSCORES_IN_LITERALS_NOT_BELOW_17 = "Underscores_In_Literals_Not_Below_17"; //$NON-NLS-1$

	// support for detecting non-externalized string literals
	public static final char[] TAG_PREFIX= "//$NON-NLS-".toCharArray(); //$NON-NLS-1$
	public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length;
	public static final char TAG_POSTFIX= '$';
	public static final int TAG_POSTFIX_LENGTH= 1;

	// support for complaining on uninterned type comparisons.
	public static final char[] IDENTITY_COMPARISON_TAG = "//$IDENTITY-COMPARISON$".toCharArray(); //$NON-NLS-1$
	public boolean [] validIdentityComparisonLines;
	public boolean checkUninternedIdentityComparison;

	private NLSTag[] nlsTags = null;
	protected int nlsTagsPtr;
	public boolean checkNonExternalizedStringLiterals;

	protected int lastPosition;

	// generic support
	public boolean returnOnlyGreater = false;

	public boolean insideRecovery = false;
	int lookBack[] = new int[2]; // fall back to spring forward.
	protected int nextToken = TokenNameNotAToken; // allows for one token push back, only the most recent token can be reliably ungotten.
	private VanguardScanner vanguardScanner;
	private VanguardParser vanguardParser;
	ConflictedParser activeParser = null;
	private boolean consumingEllipsisAnnotations = false;
	protected boolean multiCaseLabelComma = false;

	public static final int RoundBracket = 0;
	public static final int SquareBracket = 1;
	public static final int CurlyBracket = 2;
	public static final int BracketKinds = 3;

	// extended unicode support
	public static final int LOW_SURROGATE_MIN_VALUE = 0xDC00;
	public static final int HIGH_SURROGATE_MIN_VALUE = 0xD800;
	public static final int HIGH_SURROGATE_MAX_VALUE = 0xDBFF;
	public static final int LOW_SURROGATE_MAX_VALUE = 0xDFFF;

	// text block support - 13
	protected int rawStart = -1;

	//Java 15 - first _ keyword appears
	Map<String, Integer> _Keywords = null;

	private CharDeduplication deduplication = CharDeduplication.getThreadLocalInstance();

public Scanner() {
	this(false /*comment*/, false /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/);
}

public Scanner(
		boolean tokenizeComments,
		boolean tokenizeWhiteSpace,
		boolean checkNonExternalizedStringLiterals,
		long sourceLevel,
		long complianceLevel,
		char[][] taskTags,
		char[][] taskPriorities,
		boolean isTaskCaseSensitive,
		boolean isPreviewEnabled) {

	this.eofPosition = Integer.MAX_VALUE;
	this.tokenizeComments = tokenizeComments;
	this.tokenizeWhiteSpace = tokenizeWhiteSpace;
	this.sourceLevel = sourceLevel;
	this.lookBack[0] = this.lookBack[1] = this.nextToken = TokenNameNotAToken;
	this.consumingEllipsisAnnotations = false;
	this.complianceLevel = complianceLevel;
	this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
	this.previewEnabled = isPreviewEnabled;
	this.caseStartPosition = -1;
	this.multiCaseLabelComma = false;
	if (taskTags != null) {
		int taskTagsLength = taskTags.length;
		int length = taskTagsLength;
		if (taskPriorities != null) {
			int taskPrioritiesLength = taskPriorities.length;
			if (taskPrioritiesLength != taskTagsLength) {
				if (taskPrioritiesLength > taskTagsLength) {
					System.arraycopy(taskPriorities, 0, (taskPriorities = new char[taskTagsLength][]), 0, taskTagsLength);
				} else {
					System.arraycopy(taskTags, 0, (taskTags = new char[taskPrioritiesLength][]), 0, taskPrioritiesLength);
					length = taskPrioritiesLength;
				}
			}
			int[] initialIndexes = new int[length];
			for (int i = 0; i < length; i++) {
				initialIndexes[i] = i;
			}
			Util.reverseQuickSort(taskTags, 0, length - 1, initialIndexes);
			char[][] temp = new char[length][];
			for (int i = 0; i < length; i++) {
				temp[i] = taskPriorities[initialIndexes[i]];
			}
			this.taskPriorities = temp;
		} else {
			Util.reverseQuickSort(taskTags, 0, length - 1);
		}
		this.taskTags = taskTags;
		this.isTaskCaseSensitive = isTaskCaseSensitive;
	}
}

public Scanner(
		boolean tokenizeComments,
		boolean tokenizeWhiteSpace,
		boolean checkNonExternalizedStringLiterals,
		long sourceLevel,
		char[][] taskTags,
		char[][] taskPriorities,
		boolean isTaskCaseSensitive,
		boolean isPreviewEnabled) {

	this(
		tokenizeComments,
		tokenizeWhiteSpace,
		checkNonExternalizedStringLiterals,
		sourceLevel,
		sourceLevel,
		taskTags,
		taskPriorities,
		isTaskCaseSensitive,
		isPreviewEnabled);
}

public Scanner(
		boolean tokenizeComments,
		boolean tokenizeWhiteSpace,
		boolean checkNonExternalizedStringLiterals,
		long sourceLevel,
		char[][] taskTags,
		char[][] taskPriorities,
		boolean isTaskCaseSensitive) {

	this(
		tokenizeComments,
		tokenizeWhiteSpace,
		checkNonExternalizedStringLiterals,
		sourceLevel,
		sourceLevel,
		taskTags,
		taskPriorities,
		isTaskCaseSensitive,
		false);
}
public final boolean atEnd() {
	// This code is not relevant if source is
	// Only a part of the real stream input

	return this.eofPosition <= this.currentPosition;
}

// chech presence of task: tags
// TODO (frederic) see if we need to take unicode characters into account...
public void checkTaskTag(int commentStart, int commentEnd) throws InvalidInputException {
	char[] src = this.source;

	// only look for newer task: tags
	if (this.foundTaskCount > 0
		&& this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
		return;
	}
	int foundTaskIndex = this.foundTaskCount;
	char previous = src[commentStart+1]; // should be '*' or '/'
	for (
		int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) {
		char[] tag = null;
		char[] priority = null;
		// check for tag occurrence only if not ambiguous with javadoc tag
		if (previous != '@') {
			nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) {
				tag = this.taskTags[itag];
				int tagLength = tag.length;
				if (tagLength == 0) continue nextTag;

				// ensure tag is not leaded with letter if tag starts with a letter
				if (ScannerHelper.isJavaIdentifierStart(this.complianceLevel, tag[0])) {
					if (ScannerHelper.isJavaIdentifierPart(this.complianceLevel, previous)) {
						continue nextTag;
					}
				}

				for (int t = 0; t < tagLength; t++) {
					char sc, tc;
					int x = i+t;
					if (x >= this.eofPosition || x >= commentEnd) continue nextTag;
					// case sensitive check
					if ((sc = src[i + t]) != (tc = tag[t])) {
						// case insensitive check
						if (this.isTaskCaseSensitive || (ScannerHelper.toLowerCase(sc) != ScannerHelper.toLowerCase(tc))) {
							continue nextTag;
						}
					}
				}
				// ensure tag is not followed with letter if tag finishes with a letter
				if (i+tagLength < commentEnd && ScannerHelper.isJavaIdentifierPart(this.complianceLevel, src[i+tagLength-1])) {
					if (ScannerHelper.isJavaIdentifierPart(this.complianceLevel, src[i + tagLength]))
						continue nextTag;
				}
				if (this.foundTaskTags == null) {
					this.foundTaskTags = new char[5][];
					this.foundTaskMessages = new char[5][];
					this.foundTaskPriorities = new char[5][];
					this.foundTaskPositions = new int[5][];
				} else if (this.foundTaskCount == this.foundTaskTags.length) {
					System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
					System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
					System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
					System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, this.foundTaskCount);
				}

				priority = this.taskPriorities != null && itag < this.taskPriorities.length
							? this.taskPriorities[itag]
							: null;

				this.foundTaskTags[this.foundTaskCount] = tag;
				this.foundTaskPriorities[this.foundTaskCount] = priority;
				this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 };
				this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
				this.foundTaskCount++;
				i += tagLength - 1; // will be incremented when looping
				break nextTag;
			}
		}
		previous = src[i];
	}
	boolean containsEmptyTask = false;
	for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
		// retrieve message start and end positions
		int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
		int max_value = i + 1 < this.foundTaskCount
				? this.foundTaskPositions[i + 1][0] - 1
				: commentEnd - 1;
		// at most beginning of next task
		if (max_value < msgStart) {
			max_value = msgStart; // would only occur if tag is before EOF.
		}
		int end = -1;
		char c;
		for (int j = msgStart; j < max_value; j++) {
			if ((c = src[j]) == '\n' || c == '\r') {
				end = j - 1;
				break;
			}
		}
		if (end == -1) {
			for (int j = max_value; j > msgStart; j--) {
				if ((c = src[j]) == '*') {
					end = j - 1;
					break;
				}
			}
			if (end == -1)
				end = max_value;
		}
		if (msgStart == end) {
			// if the description is empty, we might want to see if two tags are not sharing the same message
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=110797
			containsEmptyTask = true;
			continue;
		}
		// trim the message
		// we don't trim the beginning of the message to be able to show it after the task tag
		while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
			end--;
		// update the end position of the task
		this.foundTaskPositions[i][1] = end;
		// get the message source
		final int messageLength = end - msgStart + 1;
		char[] message = new char[messageLength];
		System.arraycopy(src, msgStart, message, 0, messageLength);
		this.foundTaskMessages[i] = message;
	}
	if (containsEmptyTask) {
		for (int i = foundTaskIndex, max = this.foundTaskCount; i < max; i++) {
			if (this.foundTaskMessages[i].length == 0) {
				loop: for (int j = i + 1; j < max; j++) {
					if (this.foundTaskMessages[j].length != 0) {
						this.foundTaskMessages[i] = this.foundTaskMessages[j];
						this.foundTaskPositions[i][1] = this.foundTaskPositions[j][1];
						break loop;
					}
				}
			}
		}
	}
}

public char[] getCurrentIdentifierSource() {
//{ObjectTeams: respect look-ahead:
	if (this._bindoutLookahead != null) {
		char[] result = this._bindoutLookahead.getIdentifier();
		if (result != null)
			return result;
	}
// SH}
	//return the token REAL source (aka unicodes are precomputed)
	if (this.withoutUnicodePtr != 0) {
		//0 is used as a fast test flag so the real first char is in position 1
		char[] result = new char[this.withoutUnicodePtr];
		System.arraycopy(
			this.withoutUnicodeBuffer,
			1,
			result,
			0,
			this.withoutUnicodePtr);
		return result;
	}
	int length = this.currentPosition - this.startPosition;
	if (length == this.eofPosition) return this.source;
	return this.deduplication.sharedCopyOfRange(this.source, this.startPosition, this.currentPosition);
}

public int getCurrentTokenEndPosition(){
	return this.currentPosition - 1;
}
public char[] getCurrentTokenSource() {
	// Return the token REAL source (aka unicodes are precomputed)

	char[] result;
	if (this.withoutUnicodePtr != 0)
		// 0 is used as a fast test flag so the real first char is in position 1
		System.arraycopy(
			this.withoutUnicodeBuffer,
			1,
			result = new char[this.withoutUnicodePtr],
			0,
			this.withoutUnicodePtr);
	else {
		int length;
		System.arraycopy(
			this.source,
			this.startPosition,
			result = new char[length = this.currentPosition - this.startPosition],
			0,
			length);
	}
	return result;
}
public final String getCurrentTokenString() {
	// Return current token as a string

	if (this.withoutUnicodePtr != 0) {
		// 0 is used as a fast test flag so the real first char is in position 1
		return new String(
			this.withoutUnicodeBuffer,
			1,
			this.withoutUnicodePtr);
	}
	return new String(
		this.source,
		this.startPosition,
		this.currentPosition - this.startPosition);
}
public char[] getCurrentTokenSourceString() {
	//return the token REAL source (aka unicodes are precomputed).
	//REMOVE the two " that are at the beginning and the end.

	char[] result;
	if (this.withoutUnicodePtr != 0)
		//0 is used as a fast test flag so the real first char is in position 1
		System.arraycopy(this.withoutUnicodeBuffer, 2,
		//2 is 1 (real start) + 1 (to jump over the ")
		result = new char[this.withoutUnicodePtr - 2], 0, this.withoutUnicodePtr - 2);
	else {
		int length;
		System.arraycopy(
			this.source,
			this.startPosition + 1,
			result = new char[length = this.currentPosition - this.startPosition - 2],
			0,
			length);
	}
	return result;
}
protected final boolean scanForTextBlockBeginning() {
	try {
		// Don't change the position and current character unless we are certain
		// to be dealing with a text block. For producing all errors like before
		// in case of a valid """ but missing \r or \n, just return false and not
		// throw any error.
		int temp = this.currentPosition;
		if ((this.source[temp++] == '\"' && this.source[temp++] == '\"')) {
			char c = this.source[temp++];
			while (ScannerHelper.isWhitespace(c)) {
				switch (c) {
					case 10 : /* \ u000a: LINE FEED               */
						this.currentCharacter = c;
						this.currentPosition = temp;
						return true;
					default:
						break;
				}
				c = this.source[temp++];
			}
		}
	} catch(IndexOutOfBoundsException e) {
		//let it return false;
	}
	return false;
}
protected final boolean scanForTextBlockClose() throws InvalidInputException {
	try {
		if (this.source[this.currentPosition] == '\"' && this.source[this.currentPosition + 1] == '\"') {
			return true;
		}
	} catch(IndexOutOfBoundsException e) {
		//let it return false;
	}
	return false;
}
public char[] getCurrentTextBlock() {
	// 1. Normalize, i.e. convert all CR CRLF to LF
	char[] all;
	if (this.withoutUnicodePtr != 0) {
		all = CharOperation.subarray(this.withoutUnicodeBuffer, this.rawStart + 1, this.withoutUnicodePtr + 1 );
	} else {
		all = CharOperation.subarray(this.source, this.startPosition + this.rawStart, this.currentPosition - 3);
		if (all == null) {
			all = new char[0];
		}
	}
	all = normalize(all);
	// 2. Split into lines. Consider both \n and \r as line separators
	char[][] lines = CharOperation.splitOn('\n', all);
	int size = lines.length;
	List<char[]> list = new ArrayList<>(lines.length);
	for(int i = 0; i < lines.length; i++) {
		char[] line = lines[i];
		if (i + 1 == size && line.length == 0) {
			list.add(line);
			break;
		}
		char[][] sub = CharOperation.splitOn('\r', line);
		if (sub.length == 0) {
			list.add(line);
		} else {
			for (char[] cs : sub) {
				list.add(cs);
			}
		}
	}
	size = list.size();
	lines = list.toArray(new char[size][]);

	// 	3. Handle incidental white space
	//  3.1. Split into lines and identify determining lines
	int prefix = -1;
	for(int i = 0; i < size; i++) {
		char[] line = lines[i];
		boolean blank = true;
		int whitespaces = 0;
 		for (char c : line) {
			if (blank) {
				if (ScannerHelper.isWhitespace(c)) {
					whitespaces++;
				} else {
					blank = false;
				}
			}
		}
 		// The last line with closing delimiter is part of the
 		// determining line list even if empty
		if (!blank || (i+1 == size)) {
			if (prefix < 0 || whitespaces < prefix) {
 				prefix = whitespaces;
			}
		}
	}
	// 3.2. Remove the common white space prefix
	// 4. Handle escape sequences  that are not already done in getNextToken0()
	if (prefix == -1)
		prefix = 0;
	StringBuilder result = new StringBuilder();
	boolean newLine = false;
	for(int i = 0; i < lines.length; i++) {
		char[] l  = lines[i];
		// Remove the common prefix from each line
		// And remove all trailing whitespace
		// Finally append the \n at the end of the line (except the last line)
		int length = l.length;
		int trail = length;
		for(;trail > 0;) {
			if (!ScannerHelper.isWhitespace(l[trail-1])) {
				break;
			}
			trail--;
		}
		if (i >= (size -1)) {
			if (newLine) result.append('\n');
			if (trail < prefix)
				continue;
			newLine = getLineContent(result, l, prefix, trail-1, false, true);
		} else {
			if (i > 0 && newLine)
				result.append('\n');
			if (trail <= prefix) {
				newLine = true;
			} else {
				boolean merge = length > 0 && l[length - 1] == '\\';
				newLine = getLineContent(result, l, prefix, trail-1, merge, false);
			}
		}
	}
	//	get rid of all the cached values
	this.rawStart = -1;
	return result.toString().toCharArray();
}
private char[] normalize(char[] content) {
	StringBuilder result = new StringBuilder();
	boolean isCR = false;
	for (char c : content) {
		switch (c) {
			case '\r':
				result.append(c);
				isCR = true;
				break;
			case '\n':
				if (!isCR) {
					result.append(c);
				}
				isCR = false;
				break;
			default:
				result.append(c);
				isCR = false;
				break;
		}
	}
	return result.toString().toCharArray();
}
// This method is for handling the left over escaped characters during the first
// scanning (scanForStringLiteral). Admittedly this goes over the text block
// content again char by char, but this is required in order to correctly
// treat all the white space and line endings
private boolean getLineContent(StringBuilder result, char[] line, int start, int end, boolean merge, boolean lastLine) {
	int lastPointer = 0;
	for(int i = start; i < end;) {
		char c = line[i];
		if (c != '\\') {
			i++;
			continue;
		}
		if (i < end) {
			if (lastPointer + 1 <= i) {
				result.append(CharOperation.subarray(line, lastPointer == 0 ? start : lastPointer, i));
			}
			char next = line[++i];
			switch (next) {
				case '\\' :
					result.append('\\');
					if (i == end)
						merge = false;
					break;
				case 's' :
					result.append(' ');
					break;
				case '"':
					result.append('"');
					break;
				case 'b' :
					result.append('\b');
					break;
				case 'n' :
					result.append('\n');
					break;
				case 'r' :
					result.append('\r');
					break;
				case 't' :
					result.append('\t');
					break;
				case 'f' :
					result.append('\f');
					break;
				default :
					// Direct copy from scanEscapeCharacter
					int pos = i + 1;
					int number = ScannerHelper.getHexadecimalValue(next);
					if (number >= 0 && number <= 7) {
						boolean zeroToThreeNot = number > 3;
						try {
							if (ScannerHelper.isDigit(next = line[pos])) {
								pos++;
								int digit = ScannerHelper.getHexadecimalValue(next);
								if (digit >= 0 && digit <= 7) {
									number = (number * 8) + digit;
									if (ScannerHelper.isDigit(next = line[pos])) {
										pos++;
										if (zeroToThreeNot) {
											// has read \NotZeroToThree OctalDigit Digit --> ignore last character
										} else {
											digit = ScannerHelper.getHexadecimalValue(next);
											if (digit >= 0 && digit <= 7){ // has read \ZeroToThree OctalDigit OctalDigit
												number = (number * 8) + digit;
											} else {
												// has read \ZeroToThree OctalDigit NonOctalDigit --> ignore last character
											}
										}
									} else {
										// has read \OctalDigit NonDigit--> ignore last character
									}
								} else {
									// has read \OctalDigit NonOctalDigit--> ignore last character
								}
							} else {
								// has read \OctalDigit --> ignore last character
							}
						} catch (InvalidInputException e) {
							// Unlikely as this has already been processed in scanForStringLiteral()
						}
						if (number < 255) {
							next = (char) number;
						}
						result.append(next);
						lastPointer = i = pos;
						continue;
					} else {
						// Dealing with just '\'
						result.append(c);
						lastPointer = i;
						continue;
					}
			}
			lastPointer = ++i;
		}
	}
	end = merge ? end : end >= line.length ? end : end + 1;
	char[] chars = lastPointer == 0 ?
			CharOperation.subarray(line, start, end) :
				CharOperation.subarray(line, lastPointer, end);
	// The below check is because CharOperation.subarray tend to return null when the
	// boundaries produce a zero sized char[]
	if (chars != null && chars.length > 0)
		result.append(chars);
	return (!merge && !lastLine);
}
public final String getCurrentStringLiteral() {
	//return the token REAL source (aka unicodes are precomputed).
	//REMOVE the two " that are at the beginning and the end.

	if (this.withoutUnicodePtr != 0)
		//0 is used as a fast test flag so the real first char is in position 1
		//2 is 1 (real start) + 1 (to jump over the ")
		return new String(this.withoutUnicodeBuffer, 2, this.withoutUnicodePtr - 2);
	else {
		return new String(this.source, this.startPosition + 1, this.currentPosition - this.startPosition - 2);
	}
}
public final char[] getRawTokenSource() {
	int length = this.currentPosition - this.startPosition;
	char[] tokenSource = new char[length];
	System.arraycopy(this.source, this.startPosition, tokenSource, 0, length);
	return tokenSource;
}

public final char[] getRawTokenSourceEnd() {
	int length = this.eofPosition - this.currentPosition - 1;
	char[] sourceEnd = new char[length];
	System.arraycopy(this.source, this.currentPosition, sourceEnd, 0, length);
	return sourceEnd;
}

public int getCurrentTokenStartPosition(){
	return this.startPosition;
}
/*
 * Search the source position corresponding to the end of a given line number
 *
 * Line numbers are 1-based, and relative to the scanner initialPosition.
 * Character positions are 0-based.
 *
 * In case the given line number is inconsistent, answers -1.
 */
public final int getLineEnd(int lineNumber) {

	if (this.lineEnds == null || this.linePtr == -1)
		return -1;
	if (lineNumber > this.lineEnds.length+1)
		return -1;
	if (lineNumber <= 0)
		return -1;
	if (lineNumber == this.lineEnds.length + 1)
		return this.eofPosition;
	return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line
}

public final int[] getLineEnds() {
	//return a bounded copy of this.lineEnds
	if (this.linePtr == -1) {
		return EMPTY_LINE_ENDS;
	}
	int[] copy;
	System.arraycopy(this.lineEnds, 0, copy = new int[this.linePtr + 1], 0, this.linePtr + 1);
	return copy;
}

/**
 * Search the source position corresponding to the beginning of a given line number
 *
 * Line numbers are 1-based, and relative to the scanner initialPosition.
 * Character positions are 0-based.
 *
 * e.g.	getLineStart(1) --> 0	indicates that the first line starts at character 0.
 *
 * In case the given line number is inconsistent, answers -1.
 *
 * @param lineNumber int
 * @return int
 */
public final int getLineStart(int lineNumber) {

	if (this.lineEnds == null || this.linePtr == -1)
		return -1;
	if (lineNumber > this.lineEnds.length + 1)
		return -1;
	if (lineNumber <= 0)
		return -1;

	if (lineNumber == 1)
		return this.initialPosition;
	return this.lineEnds[lineNumber-2]+1; // next line start one character behind the lineEnd of the previous line
}
public final int getNextChar() {
	try {
		if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
			&& (this.source[this.currentPosition] == 'u')) {
				getNextUnicodeChar();
		} else {
			this.unicodeAsBackSlash = false;
			if (this.withoutUnicodePtr != 0) {
			    unicodeStore();
			}
		}
		return this.currentCharacter;
	} catch(IndexOutOfBoundsException | InvalidInputException e) {
		return -1;
	}
}
public final int getNextCharWithBoundChecks() {
	if (this.currentPosition >= this.eofPosition) {
		return -1;
	}
	this.currentCharacter = this.source[this.currentPosition++];
	if (this.currentPosition >= this.eofPosition) {
		this.unicodeAsBackSlash = false;
		if (this.withoutUnicodePtr != 0) {
		    unicodeStore();
		}
		return this.currentCharacter;
	}
	if (this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u') {
		try {
			getNextUnicodeChar();
		} catch (InvalidInputException e) {
			return -1;
		}
	} else {
		this.unicodeAsBackSlash = false;
		if (this.withoutUnicodePtr != 0) {
		    unicodeStore();
		}
	}
	return this.currentCharacter;
}
public final boolean getNextChar(char testedChar) {
	//BOOLEAN
	//handle the case of unicode.
	//when a unicode appears then we must use a buffer that holds char internal values
	//At the end of this method currentCharacter holds the new visited char
	//and currentPosition points right next after it
	//Both previous lines are true if the currentCharacter is == to the testedChar
	//On false, no side effect has occured.

	//ALL getNextChar.... ARE OPTIMIZED COPIES

	if (this.currentPosition >= this.eofPosition) { // handle the obvious case upfront
		this.unicodeAsBackSlash = false;
		return false;
	}

	int temp = this.currentPosition;
	try {
		if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
			&& (this.source[this.currentPosition] == 'u')) {
			getNextUnicodeChar();
			if (this.currentCharacter != testedChar) {
				this.currentPosition = temp;
				this.withoutUnicodePtr--;
				return false;
			}
			return true;
		} //-------------end unicode traitement--------------
		else {
			if (this.currentCharacter != testedChar) {
				this.currentPosition = temp;
				return false;
			}
			this.unicodeAsBackSlash = false;
			if (this.withoutUnicodePtr != 0)
				unicodeStore();
			return true;
		}
	} catch(IndexOutOfBoundsException | InvalidInputException e) {
		this.unicodeAsBackSlash = false;
		this.currentPosition = temp;
		return false;
	}
}
public final int getNextChar(char testedChar1, char testedChar2) {
	//INT 0 : testChar1 \\\\///\\\\ 1 : testedChar2 \\\\///\\\\ -1 : others
	//test can be done with (x==0) for the first and (x>0) for the second
	//handle the case of unicode.
	//when a unicode appears then we must use a buffer that holds char internal values
	//At the end of this method currentCharacter holds the new visited char
	//and currentPosition points right next after it
	//Both previous lines are true if the currentCharacter is == to the testedChar1/2
	//On false, no side effect has occured.

	//ALL getNextChar.... ARE OPTIMIZED COPIES
	if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront
		return -1;

	int temp = this.currentPosition;
	try {
		int result;
		if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
			&& (this.source[this.currentPosition] == 'u')) {
			getNextUnicodeChar();
			if (this.currentCharacter == testedChar1) {
				result = 0;
			} else if (this.currentCharacter == testedChar2) {
				result = 1;
			} else {
				this.currentPosition = temp;
				this.withoutUnicodePtr--;
				result = -1;
			}
			return result;
		} else {
			if (this.currentCharacter == testedChar1) {
				result = 0;
			} else if (this.currentCharacter == testedChar2) {
				result = 1;
			} else {
				this.currentPosition = temp;
				return -1;
			}

			if (this.withoutUnicodePtr != 0)
				unicodeStore();
			return result;
		}
	} catch(IndexOutOfBoundsException | InvalidInputException e) {
		this.currentPosition = temp;
		return -1;
	}
}
/*
 * This method consumes digits as well as underscores if underscores are located between digits
 * @throws InvalidInputException if underscores are not located between digits or if underscores are used in source < 1.7
 */
private final void consumeDigits(int radix) throws InvalidInputException {
	consumeDigits(radix, false);
}
/*
 * This method consumes digits as well as underscores if underscores are located between digits
 * @throws InvalidInputException if underscores are not located between digits or if underscores are used in source < 1.7
 */
private final void consumeDigits(int radix, boolean expectingDigitFirst) throws InvalidInputException {
	final int USING_UNDERSCORE = 1;
	final int INVALID_POSITION = 2;
	switch(consumeDigits0(radix, USING_UNDERSCORE, INVALID_POSITION, expectingDigitFirst)) {
		case USING_UNDERSCORE :
			if (this.sourceLevel < ClassFileConstants.JDK1_7) {
				throw new InvalidInputException(UNDERSCORES_IN_LITERALS_NOT_BELOW_17);
			}
			break;
		case INVALID_POSITION :
			if (this.sourceLevel < ClassFileConstants.JDK1_7) {
				throw new InvalidInputException(UNDERSCORES_IN_LITERALS_NOT_BELOW_17);
			}
			throw new InvalidInputException(INVALID_UNDERSCORE);
	}
}
private final int consumeDigits0(int radix, int usingUnderscore, int invalidPosition, boolean expectingDigitFirst) throws InvalidInputException {
	int kind = 0;
	if (getNextChar('_')) {
		if (expectingDigitFirst) {
			return invalidPosition;
		}
		kind = usingUnderscore;
		while (getNextChar('_')) {/*empty */}
	}
	if (getNextCharAsDigit(radix)) {
		// continue to read digits or underscore
		while (getNextCharAsDigit(radix)) {/*empty */}
		int kind2 = consumeDigits0(radix, usingUnderscore, invalidPosition, false);
		if (kind2 == 0) {
			return kind;
		}
		return kind2;
	}
	if (kind == usingUnderscore) return invalidPosition;
	return kind;
}
public final boolean getNextCharAsDigit() throws InvalidInputException {
	//BOOLEAN
	//handle the case of unicode.
	//when a unicode appears then we must use a buffer that holds char internal values
	//At the end of this method currentCharacter holds the new visited char
	//and currentPosition points right next after it
	//Both previous lines are true if the currentCharacter is a digit
	//On false, no side effect has occured.

	//ALL getNextChar.... ARE OPTIMIZED COPIES
	if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront
		return false;

	int temp = this.currentPosition;
	try {
		if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
			&& (this.source[this.currentPosition] == 'u')) {
			getNextUnicodeChar();
			if (!ScannerHelper.isDigit(this.currentCharacter)) {
				this.currentPosition = temp;
				this.withoutUnicodePtr--;
				return false;
			}
			return true;
		} else {
			if (!ScannerHelper.isDigit(this.currentCharacter)) {
				this.currentPosition = temp;
				return false;
			}
			if (this.withoutUnicodePtr != 0)
				unicodeStore();
			return true;
		}
	} catch(IndexOutOfBoundsException | InvalidInputException e) {
		this.currentPosition = temp;
		return false;
	}
}
public final boolean getNextCharAsDigit(int radix) {
	//BOOLEAN
	//handle the case of unicode.
	//when a unicode appears then we must use a buffer that holds char internal values
	//At the end of this method currentCharacter holds the new visited char
	//and currentPosition points right next after it
	//Both previous lines are true if the currentCharacter is a digit base on radix
	//On false, no side effect has occured.

	//ALL getNextChar.... ARE OPTIMIZED COPIES
	if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront
		return false;

	int temp = this.currentPosition;
	try {
		if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
			&& (this.source[this.currentPosition] == 'u')) {
			getNextUnicodeChar();
			if (ScannerHelper.digit(this.currentCharacter, radix) == -1) {
				this.currentPosition = temp;
				this.withoutUnicodePtr--;
				return false;
			}
			return true;
		} else {
			if (ScannerHelper.digit(this.currentCharacter, radix) == -1) {
				this.currentPosition = temp;
				return false;
			}
			if (this.withoutUnicodePtr != 0)
				unicodeStore();
			return true;
		}
	} catch(IndexOutOfBoundsException | InvalidInputException e) {
		this.currentPosition = temp;
		return false;
	}
}
public boolean getNextCharAsJavaIdentifierPartWithBoundCheck() {
	//BOOLEAN
	//handle the case of unicode.
	//when a unicode appears then we must use a buffer that holds char internal values
	//At the end of this method currentCharacter holds the new visited char
	//and currentPosition points right next after it
	//Both previous lines are true if the currentCharacter is a JavaIdentifierPart
	//On false, no side effect has occured.

	//ALL getNextChar.... ARE OPTIMIZED COPIES
	int pos = this.currentPosition;
	if (pos >= this.eofPosition) // handle the obvious case upfront
		return false;

	int temp2 = this.withoutUnicodePtr;
	try {
		boolean unicode = false;
		this.currentCharacter = this.source[this.currentPosition++];
		if (this.currentPosition < this.eofPosition) {
			if (this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u') {
				getNextUnicodeChar();
				unicode = true;
			}
		}
		char c = this.currentCharacter;
		boolean isJavaIdentifierPart = false;
		if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
			if (this.complianceLevel < ClassFileConstants.JDK1_5) {
				this.currentPosition = pos;
				this.withoutUnicodePtr = temp2;
				return false;
			}
			// Unicode 4 detection
			char low = (char) getNextCharWithBoundChecks();
			if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
				// illegal low surrogate
				this.currentPosition = pos;
				this.withoutUnicodePtr = temp2;
				return false;
			}
			isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c, low);
		}
		else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
			this.currentPosition = pos;
			this.withoutUnicodePtr = temp2;
			return false;
		} else {
			isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c);
		}
		if (unicode) {
			if (!isJavaIdentifierPart) {
				this.currentPosition = pos;
				this.withoutUnicodePtr = temp2;
				return false;
			}
			return true;
		} else {
			if (!isJavaIdentifierPart) {
				this.currentPosition = pos;
				return false;
			}

			if (this.withoutUnicodePtr != 0)
			    unicodeStore();
			return true;
		}
	} catch(InvalidInputException e) {
		this.currentPosition = pos;
		this.withoutUnicodePtr = temp2;
		return false;
	}
}
public boolean getNextCharAsJavaIdentifierPart() {
	//BOOLEAN
	//handle the case of unicode.
	//when a unicode appears then we must use a buffer that holds char internal values
	//At the end of this method currentCharacter holds the new visited char
	//and currentPosition points right next after it
	//Both previous lines are true if the currentCharacter is a JavaIdentifierPart
	//On false, no side effect has occured.

	//ALL getNextChar.... ARE OPTIMIZED COPIES
	int pos;
	if ((pos = this.currentPosition) >= this.eofPosition) // handle the obvious case upfront
		return false;

	int temp2 = this.withoutUnicodePtr;
	try {
		boolean unicode = false;
		if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
			&& (this.source[this.currentPosition] == 'u')) {
			getNextUnicodeChar();
			unicode = true;
		}
		char c = this.currentCharacter;
		boolean isJavaIdentifierPart = false;
		if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
			if (this.complianceLevel < ClassFileConstants.JDK1_5) {
				this.currentPosition = pos;
				this.withoutUnicodePtr = temp2;
				return false;
			}
			// Unicode 4 detection
			char low = (char) getNextChar();
			if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
				// illegal low surrogate
				this.currentPosition = pos;
				this.withoutUnicodePtr = temp2;
				return false;
			}
			isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c, low);
		}
		else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
			this.currentPosition = pos;
			this.withoutUnicodePtr = temp2;
			return false;
		} else {
			isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c);
		}
		if (unicode) {
			if (!isJavaIdentifierPart) {
				this.currentPosition = pos;
				this.withoutUnicodePtr = temp2;
				return false;
			}
			return true;
		} else {
			if (!isJavaIdentifierPart) {
				this.currentPosition = pos;
				return false;
			}

			if (this.withoutUnicodePtr != 0)
			    unicodeStore();
			return true;
		}
	} catch(IndexOutOfBoundsException | InvalidInputException e) {
		this.currentPosition = pos;
		this.withoutUnicodePtr = temp2;
		return false;
	}
}
/*
 * External API in JavaConventions.
 * This is used to optimize the case where the scanner is used to scan a single identifier.
 * In this case, the AIOOBE is slower to handle than a bound check
 */
public int scanIdentifier() throws InvalidInputException {
	int whiteStart = 0;
	while (true) { //loop for jumping over comments
		this.withoutUnicodePtr = 0;
		//start with a new token (even comment written with unicode )
		// ---------Consume white space and handles startPosition---------
		whiteStart = this.currentPosition;
		boolean isWhiteSpace, hasWhiteSpaces = false;
		int offset;
		int unicodePtr;
		boolean checkIfUnicode = false;
		do {
			unicodePtr = this.withoutUnicodePtr;
			offset = this.currentPosition;
			this.startPosition = this.currentPosition;
			if (this.currentPosition < this.eofPosition) {
				this.currentCharacter = this.source[this.currentPosition++];
				checkIfUnicode = this.currentPosition < this.eofPosition
						&& this.currentCharacter == '\\'
						&& this.source[this.currentPosition] == 'u';
			} else if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
				// reposition scanner in case we are interested by spaces as tokens
				this.currentPosition--;
				this.startPosition = whiteStart;
				return TokenNameWHITESPACE;
			} else {
				return TokenNameEOF;
			}
			if (checkIfUnicode) {
				isWhiteSpace = jumpOverUnicodeWhiteSpace();
				offset = this.currentPosition - offset;
			} else {
				offset = this.currentPosition - offset;
				// inline version of:
				//isWhiteSpace =
				//	(this.currentCharacter == ' ') || ScannerHelper.isWhitespace(this.currentCharacter);
				switch (this.currentCharacter) {
					case 10 : /* \ u000a: LINE FEED               */
					case 12 : /* \ u000c: FORM FEED               */
					case 13 : /* \ u000d: CARRIAGE RETURN         */
					case 32 : /* \ u0020: SPACE                   */
					case 9 : /* \ u0009: HORIZONTAL TABULATION   */
						isWhiteSpace = true;
						break;
					default :
						isWhiteSpace = false;
				}
			}
			if (isWhiteSpace) {
				hasWhiteSpaces = true;
			}
		} while (isWhiteSpace);
		if (hasWhiteSpaces) {
			if (this.tokenizeWhiteSpace) {
				// reposition scanner in case we are interested by spaces as tokens
				this.currentPosition-=offset;
				this.startPosition = whiteStart;
				if (checkIfUnicode) {
					this.withoutUnicodePtr = unicodePtr;
				}
				return TokenNameWHITESPACE;
			} else if (checkIfUnicode) {
				this.withoutUnicodePtr = 0;
				unicodeStore();
			} else {
				this.withoutUnicodePtr = 0;
			}
		}
		char c = this.currentCharacter;
		if (c < ScannerHelper.MAX_OBVIOUS) {
			if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
				return scanIdentifierOrKeywordWithBoundCheck();
			}
			return TokenNameERROR;
		}
		boolean isJavaIdStart;
		if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
			if (this.complianceLevel < ClassFileConstants.JDK1_5) {
				throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
			}
			// Unicode 4 detection
			char low = (char) getNextCharWithBoundChecks();
			if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
				// illegal low surrogate
				throw new InvalidInputException(INVALID_LOW_SURROGATE);
			}
			isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low);
		} else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
			if (this.complianceLevel < ClassFileConstants.JDK1_5) {
				throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
			}
			throw new InvalidInputException(INVALID_HIGH_SURROGATE);
		} else {
			// optimized case already checked
			isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c);
		}
		if (isJavaIdStart)
			return scanIdentifierOrKeywordWithBoundCheck();
		return TokenNameERROR;
	}
}
public void ungetToken(int unambiguousToken) {
	if (this.nextToken != TokenNameNotAToken) {
		throw new ArrayIndexOutOfBoundsException("Single cell array overflow"); //$NON-NLS-1$
	}
	this.nextToken = unambiguousToken;
}
private void updateCase(int token) {
	if (token == TokenNamecase) {
		this.caseStartPosition = this.startPosition;
		this.breakPreviewAllowed = true;
	}
}
public int getNextToken() throws InvalidInputException {

	int token;
	if (this.nextToken != TokenNameNotAToken) {
		token = this.nextToken;
		this.nextToken = TokenNameNotAToken;
		return token; // presumed to be unambiguous.
	}

//{ObjectTeams: consume lookahead for parameter mappings:
	if (this._bindoutLookahead != null) {
		int result = this._bindoutLookahead.getNextToken();
		if (result != TerminalTokens.TokenNameNotAToken)
			return result;
	}
// SH}

	if (this.scanContext == null) { // init lazily, since isInModuleDeclaration needs the parser to be known
		this.scanContext = isInModuleDeclaration() ? ScanContext.EXPECTING_KEYWORD : ScanContext.INACTIVE;
	}
	token = getNextToken0();
	if (areRestrictedModuleKeywordsActive()) {
		if (isRestrictedKeyword(token))
			token = disambiguatedRestrictedKeyword(token);
		updateScanContext(token);
	}
	if (this.activeParser == null) { // anybody interested in the grammatical structure of the program should have registered.
		return token;
	}
	if (token == TokenNameLPAREN || token == TokenNameLESS || token == TokenNameAT || token == TokenNameARROW) {
		token = disambiguatedToken(token, this);
	} else if (token == TokenNameELLIPSIS) {
		this.consumingEllipsisAnnotations = false;
	} else if (mayBeAtCasePattern(token)) {
		token = disambiguateCasePattern(token, this);
	}
	this.lookBack[0] = this.lookBack[1];
	this.lookBack[1] = token;
	this.multiCaseLabelComma = false;
	updateCase(token);
	return token;
}
protected int getNextToken0() throws InvalidInputException {
//{ObjectTeams: support '.' 'team':
	if (this._dotSeen > 0)
		this._dotSeen--; // "aging"
// SH}
	this.wasAcr = false;
	if (this.diet) {
		jumpOverMethodBody();
		this.diet = false;
		return this.currentPosition > this.eofPosition ? TokenNameEOF : TokenNameRBRACE;
	}
	int whiteStart = 0;
	try {
		while (true) { //loop for jumping over comments
			this.withoutUnicodePtr = 0;
			//start with a new token (even comment written with unicode )

			// ---------Consume white space and handles startPosition---------
			whiteStart = this.currentPosition;
			boolean isWhiteSpace, hasWhiteSpaces = false;
			int offset;
			int unicodePtr;
			boolean checkIfUnicode = false;
			do {
				unicodePtr = this.withoutUnicodePtr;
				offset = this.currentPosition;
				this.startPosition = this.currentPosition;
				boolean repositionNeeded = false;
				if(this.currentPosition < this.source.length){
					this.currentCharacter = this.source[this.currentPosition];
					this.currentPosition++;
					if(this.currentCharacter == '\\') {
						if (this.currentPosition < this.source.length) {
							checkIfUnicode = this.source[this.currentPosition] == 'u';
						} else {
							repositionNeeded = true;
						}
					} else {
						checkIfUnicode = false;
					}
				} else {
					this.currentPosition++;
					repositionNeeded = true;
				}
				if(repositionNeeded){
					if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
						// reposition scanner in case we are interested by spaces as tokens
						this.currentPosition--;
						this.startPosition = whiteStart;
						return TokenNameWHITESPACE;
					}
					if (this.currentPosition > this.eofPosition)
						return TokenNameEOF;
				}
				if (this.currentPosition > this.eofPosition) {
					if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
						this.currentPosition--;
						// reposition scanner in case we are interested by spaces as tokens
						this.startPosition = whiteStart;
						return TokenNameWHITESPACE;
					}
					return TokenNameEOF;
				}
				if (checkIfUnicode) {
					isWhiteSpace = jumpOverUnicodeWhiteSpace();
					offset = this.currentPosition - offset;
				} else {
					offset = this.currentPosition - offset;
					if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
						if (this.recordLineSeparator) {
							pushLineSeparator();
						}
					}
					// inline version of:
					//isWhiteSpace =
					//	(this.currentCharacter == ' ') || ScannerHelper.isWhitespace(this.currentCharacter);
					switch (this.currentCharacter) {
						case 10 : /* \ u000a: LINE FEED               */
						case 12 : /* \ u000c: FORM FEED               */
						case 13 : /* \ u000d: CARRIAGE RETURN         */
						case 32 : /* \ u0020: SPACE                   */
						case 9 : /* \ u0009: HORIZONTAL TABULATION   */
							isWhiteSpace = true;
							break;
						default :
							isWhiteSpace = false;
					}
				}
				if (isWhiteSpace) {
					hasWhiteSpaces = true;
				}
			} while (isWhiteSpace);
			if (hasWhiteSpaces) {
				if (this.tokenizeWhiteSpace) {
					// reposition scanner in case we are interested by spaces as tokens
					this.currentPosition-=offset;
					this.startPosition = whiteStart;
					if (checkIfUnicode) {
						this.withoutUnicodePtr = unicodePtr;
					}
					return TokenNameWHITESPACE;
				} else if (checkIfUnicode) {
					this.withoutUnicodePtr = 0;
					unicodeStore();
				} else {
					this.withoutUnicodePtr = 0;
				}
			}
			// ---------Identify the next token-------------
			switch (this.currentCharacter) {
				case '@' :
/*					if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
						return TokenNameAT;
					} else {
						return TokenNameERROR;
					}*/
					return TokenNameAT;
				case '(' :
					return TokenNameLPAREN;
				case ')' :
					return TokenNameRPAREN;
				case '{' :
					return TokenNameLBRACE;
				case '}' :
					return TokenNameRBRACE;
				case '[' :
					return TokenNameLBRACKET;
				case ']' :
					return TokenNameRBRACKET;
				case ';' :
					return TokenNameSEMICOLON;
				case ',' :
					return TokenNameCOMMA;
				case '.' :
					if (getNextCharAsDigit()) {
						return scanNumber(true);
					}
					int temp = this.currentPosition;
					if (getNextChar('.')) {
						if (getNextChar('.')) {
							return TokenNameELLIPSIS;
						} else {
							this.currentPosition = temp;
							return TokenNameDOT;
						}
					} else {
//{ObjectTeams: record the one '.':
						this._dotSeen = 2; // now
// SH}
						this.currentPosition = temp;
						return TokenNameDOT;
					}
				case '+' :
					{
						int test;
						if ((test = getNextChar('+', '=')) == 0)
							return TokenNamePLUS_PLUS;
						if (test > 0)
							return TokenNamePLUS_EQUAL;
						return TokenNamePLUS;
					}
				case '-' :
					{
						int test;
						if ((test = getNextChar('-', '=')) == 0)
							return TokenNameMINUS_MINUS;
						if (test > 0)
							return TokenNameMINUS_EQUAL;
//{ObjectTeams: set _calloutSeen?
/* orig:
						if (getNextChar('>'))
							return TokenNameARROW;
  :giro */
						if (getNextChar('>')) {
							if (needBindoutDisambiguation()) {
								if (this._insideParameterMapping) {
									this._bindoutLookahead = new BindoutLookahead();
									return this._bindoutLookahead.getNextToken();
								}
								this._calloutSeen = true;
								return TokenNameBINDOUT;
							}
							return TokenNameARROW;
						}
// Markus Witte}
						return TokenNameMINUS;
					}
				case '~' :
					return TokenNameTWIDDLE;
				case '!' :
					if (getNextChar('='))
						return TokenNameNOT_EQUAL;
					return TokenNameNOT;
				case '*' :
					if (getNextChar('='))
						return TokenNameMULTIPLY_EQUAL;
					return TokenNameMULTIPLY;
				case '%' :
					if (getNextChar('='))
						return TokenNameREMAINDER_EQUAL;
					return TokenNameREMAINDER;
				case '<' :
					{
						int test;
						if ((test = getNextChar('=', '<')) == 0)
							return TokenNameLESS_EQUAL;
						if (test > 0) {
							if (getNextChar('='))
								return TokenNameLEFT_SHIFT_EQUAL;
							return TokenNameLEFT_SHIFT;
						}
//{ObjectTeams: check for callin binding after '<' tokens
						else {
							if (test < 0  && this._isOTSource)
								if (getNextChar('-')) {
									this._callinSeen = true;
									return TokenNameBINDIN;
								}
						}
// Markus Witte}
						return TokenNameLESS;
					}
				case '>' :
					{
						int test;
						if (this.returnOnlyGreater) {
							return TokenNameGREATER;
						}
						if ((test = getNextChar('=', '>')) == 0)
							return TokenNameGREATER_EQUAL;
						if (test > 0) {
							if ((test = getNextChar('=', '>')) == 0)
								return TokenNameRIGHT_SHIFT_EQUAL;
							if (test > 0) {
								if (getNextChar('='))
									return TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL;
								return TokenNameUNSIGNED_RIGHT_SHIFT;
							}
							return TokenNameRIGHT_SHIFT;
						}
						return TokenNameGREATER;
					}
				case '=' :
//{ObjectTeams: check for callout override after '=' tokens
				/* @original
					if (getNextChar('='))
						return TokenNameEQUAL_EQUAL;
					return TokenNameEQUAL;
				*/
				{
					int test;
					if ((test = getNextChar('=', '>')) == 0)
						return TokenNameEQUAL_EQUAL;
					if (test > 0) {
						this._calloutSeen = true;
						return TokenNameCALLOUT_OVERRIDE;
					} else {
						return TokenNameEQUAL;
					}
				}
// Markus Witte}
				case '&' :
					{
						int test;
						if ((test = getNextChar('&', '=')) == 0)
							return TokenNameAND_AND;
						if (test > 0)
							return TokenNameAND_EQUAL;
						return TokenNameAND;
					}
				case '|' :
					{
						int test;
						if ((test = getNextChar('|', '=')) == 0)
							return TokenNameOR_OR;
						if (test > 0)
							return TokenNameOR_EQUAL;
						return TokenNameOR;
					}
				case '^' :
					if (getNextChar('='))
						return TokenNameXOR_EQUAL;
					return TokenNameXOR;
				case '?' :
					return TokenNameQUESTION;
				case ':' :
					if (getNextChar(':'))
						return TokenNameCOLON_COLON;
					++this.yieldColons;
					return TokenNameCOLON;
				case '\'' :
					{
						int test;
						if ((test = getNextChar('\n', '\r')) == 0) {
							throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
						}
						if (test > 0) {
							// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
							for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
								if (this.currentPosition + lookAhead == this.eofPosition)
									break;
								if (this.source[this.currentPosition + lookAhead] == '\n')
									break;
								if (this.source[this.currentPosition + lookAhead] == '\'') {
									this.currentPosition += lookAhead + 1;
									break;
								}
							}
							throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
						}
					}
					if (getNextChar('\'')) {
						// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
						for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
							if (this.currentPosition + lookAhead == this.eofPosition)
								break;
							if (this.source[this.currentPosition + lookAhead] == '\n')
								break;
							if (this.source[this.currentPosition + lookAhead] == '\'') {
								this.currentPosition += lookAhead + 1;
								break;
							}
						}
						throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
					}
					if (getNextChar('\\')) {
						if (this.unicodeAsBackSlash) {
							// consume next character
							this.unicodeAsBackSlash = false;
							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
								getNextUnicodeChar();
							} else {
								if (this.withoutUnicodePtr != 0) {
									unicodeStore();
								}
							}
						} else {
							this.currentCharacter = this.source[this.currentPosition++];
						}
						scanEscapeCharacter();
					} else { // consume next character
						this.unicodeAsBackSlash = false;
						checkIfUnicode = false;
						try {
							checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
							&& (this.source[this.currentPosition] == 'u');
						} catch(IndexOutOfBoundsException e) {
							this.currentPosition--;
							throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
						}
						if (checkIfUnicode) {
							getNextUnicodeChar();
						} else {
							if (this.withoutUnicodePtr != 0) {
								unicodeStore();
							}
						}
					}
					if (getNextChar('\''))
						return TokenNameCharacterLiteral;
					// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
					for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
						if (this.currentPosition + lookAhead == this.eofPosition)
							break;
						if (this.source[this.currentPosition + lookAhead] == '\n')
							break;
						if (this.source[this.currentPosition + lookAhead] == '\'') {
							this.currentPosition += lookAhead + 1;
							break;
						}
					}
					throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
				case '"' :
					return scanForStringLiteral();
				case '/' :
					if (!this.skipComments) {
						int test = getNextChar('/', '*');
						if (test == 0) { //line comment
							this.lastCommentLinePosition = this.currentPosition;
							try { //get the next char
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
								}

								//handle the \\u case manually into comment
								if (this.currentCharacter == '\\') {
									if (this.source[this.currentPosition] == '\\')
										this.currentPosition++;
								} //jump over the \\
								boolean isUnicode = false;
								while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
									if (this.currentPosition >= this.eofPosition) {
										this.lastCommentLinePosition = this.currentPosition;
										this.currentPosition ++;
										// this avoids duplicating the code in the catch(IndexOutOfBoundsException e)
										throw new IndexOutOfBoundsException();
									}
									this.lastCommentLinePosition = this.currentPosition;
									//get the next char
									isUnicode = false;
									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
											&& (this.source[this.currentPosition] == 'u')) {
										getNextUnicodeChar();
										isUnicode = true;
									}
									//handle the \\u case manually into comment
									if (this.currentCharacter == '\\') {
										if (this.source[this.currentPosition] == '\\')
											this.currentPosition++;
									} //jump over the \\
								}
								/*
								 * We need to completely consume the line break
								 */
								if (this.currentCharacter == '\r'
										&& this.eofPosition > this.currentPosition) {
									if (this.source[this.currentPosition] == '\n') {
										this.currentPosition++;
										this.currentCharacter = '\n';
									} else if ((this.source[this.currentPosition] == '\\')
										&& (this.source[this.currentPosition + 1] == 'u')) {
										getNextUnicodeChar();
										isUnicode = true;
									}
								}
								recordComment(TokenNameCOMMENT_LINE);
								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
								if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
									if ((this.checkNonExternalizedStringLiterals || this.checkUninternedIdentityComparison) &&
											this.lastPosition < this.currentPosition) {
										parseTags();
									}
									if (this.recordLineSeparator) {
										if (isUnicode) {
											pushUnicodeLineSeparator();
										} else {
											pushLineSeparator();
										}
									}
								}
								if (this.tokenizeComments) {
									return TokenNameCOMMENT_LINE;
								}
							} catch (IndexOutOfBoundsException e) {
								this.currentPosition--;
								recordComment(TokenNameCOMMENT_LINE);
								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
								if ((this.checkNonExternalizedStringLiterals || this.checkUninternedIdentityComparison) &&
										this.lastPosition < this.currentPosition) {
									parseTags();
								}
								if (this.tokenizeComments) {
									return TokenNameCOMMENT_LINE;
								} else {
									this.currentPosition++;
								}
							}
							break;
						}
						if (test > 0) { //traditional and javadoc comment
							try { //get the next char
								boolean isJavadoc = false, star = false;
								boolean isUnicode = false;
								int previous;
								// consume next character
								this.unicodeAsBackSlash = false;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
									&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
									isUnicode = true;
								} else {
									isUnicode = false;
									if (this.withoutUnicodePtr != 0) {
										unicodeStore();
									}
								}

								if (this.currentCharacter == '*') {
									isJavadoc = true;
									star = true;
								}
								if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
									if (this.recordLineSeparator) {
										if (isUnicode) {
											pushUnicodeLineSeparator();
										} else {
											pushLineSeparator();
										}
									}
								}
								isUnicode = false;
								previous = this.currentPosition;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
									&& (this.source[this.currentPosition] == 'u')) {
									//-------------unicode traitement ------------
									getNextUnicodeChar();
									isUnicode = true;
								} else {
									isUnicode = false;
								}
								//handle the \\u case manually into comment
								if (this.currentCharacter == '\\') {
									if (this.source[this.currentPosition] == '\\')
										this.currentPosition++; //jump over the \\
								}
								// empty comment is not a javadoc /**/
								if (this.currentCharacter == '/') {
									isJavadoc = false;
								}
								//loop until end of comment */
								int firstTag = 0;
								while ((this.currentCharacter != '/') || (!star)) {
									if (this.currentPosition >= this.eofPosition) {
										throw new InvalidInputException(UNTERMINATED_COMMENT);
									}
									if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
										if (this.recordLineSeparator) {
											if (isUnicode) {
												pushUnicodeLineSeparator();
											} else {
												pushLineSeparator();
											}
										}
									}
									switch (this.currentCharacter) {
										case '*':
											star = true;
											break;
										case '@':
											if (firstTag == 0 && this.isFirstTag()) {
												firstTag = previous;
											}
											//$FALL-THROUGH$ default case to set star to false
										default:
											star = false;
									}
									//get next char
									previous = this.currentPosition;
									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
										//-------------unicode traitement ------------
										getNextUnicodeChar();
										isUnicode = true;
									} else {
										isUnicode = false;
									}
									//handle the \\u case manually into comment
									if (this.currentCharacter == '\\') {
										if (this.source[this.currentPosition] == '\\')
											this.currentPosition++;
									} //jump over the \\
								}
								int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK;
								recordComment(token);
								this.commentTagStarts[this.commentPtr] = firstTag;
								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
								if (this.tokenizeComments) {
									/*
									if (isJavadoc)
										return TokenNameCOMMENT_JAVADOC;
									return TokenNameCOMMENT_BLOCK;
									*/
									return token;
								}
							} catch (IndexOutOfBoundsException e) {
								this.currentPosition--;
								throw new InvalidInputException(UNTERMINATED_COMMENT);
							}
							break;
						}
					}
					if (getNextChar('='))
						return TokenNameDIVIDE_EQUAL;
					return TokenNameDIVIDE;
				case '\u001a' :
					if (atEnd())
						return TokenNameEOF;
					//the atEnd may not be <currentPosition == source.length> if source is only some part of a real (external) stream
					throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
				default :
					char c = this.currentCharacter;
					if (c < ScannerHelper.MAX_OBVIOUS) {
						if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
							return scanIdentifierOrKeyword();
						} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) {
								return scanNumber(false);
						} else {
							return TokenNameERROR;
						}
					}
					boolean isJavaIdStart;
					if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
						if (this.complianceLevel < ClassFileConstants.JDK1_5) {
							throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
						}
						// Unicode 4 detection
						char low = (char) getNextChar();
						if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
							// illegal low surrogate
							throw new InvalidInputException(INVALID_LOW_SURROGATE);
						}
						isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low);
					}
					else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
						if (this.complianceLevel < ClassFileConstants.JDK1_5) {
							throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
						}
						throw new InvalidInputException(INVALID_HIGH_SURROGATE);
					} else {
						// optimized case already checked
						isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c);
					}
					if (isJavaIdStart)
						return scanIdentifierOrKeyword();
					if (ScannerHelper.isDigit(this.currentCharacter)) {
						return scanNumber(false);
					}
					return TokenNameERROR;
			}
		}
	} //-----------------end switch while try--------------------
	catch (IndexOutOfBoundsException e) {
		if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
			// reposition scanner in case we are interested by spaces as tokens
			this.currentPosition--;
			this.startPosition = whiteStart;
			return TokenNameWHITESPACE;
		}
	}
	return TokenNameEOF;
}
protected boolean needBindoutDisambiguation() {
	if (!this._isOTSource)
		return false;
	if (this._calloutSeen || this._callinSeen)
		return false; // no nesting
	if (this.activeParser instanceof VanguardParser) {
		Goal goal = ((VanguardParser)this.activeParser).currentGoal;
		return !(goal == Goal.LambdaParameterListGoal || goal == Goal.PatternGoal || goal == Goal.SwitchLabelCaseLhsGoal);
	} else {
		Parser parser = null;
		if (this.activeParser instanceof DiagnoseParser) {
			parser = ((DiagnoseParser) this.activeParser).parser;
		} else if (this.activeParser instanceof Parser) {
			parser = (Parser) this.activeParser;
		} else {
			return true;
		}
		if (parser.referenceContext instanceof AbstractMethodDeclaration)
			return false; // no callout inside a method (incl. the case of local types in a method):)
		int ptr = parser.astPtr;
		while (ptr > -1) {
			ASTNode topAstNode = parser.astStack[ptr];
			if (topAstNode instanceof TypeDeclaration) {
				return true;
			} else if (topAstNode instanceof MethodDeclaration) {
				return true; // method to be reclassified as MethodSpec :( TODO: test content?
			} else if (topAstNode instanceof LambdaExpression) {
				return topAstNode.sourceEnd != 0; // disambiguation only when body is complete
			} else if (topAstNode instanceof Argument) {
				ptr--; // dig deeper
			} else {
				return true;
			}
		}
	}
	return true;
}
private int scanForStringLiteral() throws InvalidInputException {
	boolean isTextBlock = false;

	// consume next character
	this.unicodeAsBackSlash = false;
	boolean isUnicode = false;
	isTextBlock = scanForTextBlockBeginning();
	if (isTextBlock) {
		return scanForTextBlock();
	} else {
		try {
			// consume next character
			this.unicodeAsBackSlash = false;
			isUnicode = false;
			if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
					&& (this.source[this.currentPosition] == 'u')) {
				getNextUnicodeChar();
				isUnicode = true;
			} else {
				if (this.withoutUnicodePtr != 0) {
					unicodeStore();
				}
			}

			while (this.currentCharacter != '"') {
				if (this.currentPosition >= this.eofPosition) {
					throw new InvalidInputException(UNTERMINATED_STRING);
				}
				/**** \r and \n are not valid in string literals ****/
				if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
					// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
					if (isUnicode) {
						int start = this.currentPosition;
						for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
							if (this.currentPosition >= this.eofPosition) {
								this.currentPosition = start;
								break;
							}
							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
								isUnicode = true;
								getNextUnicodeChar();
							} else {
								isUnicode = false;
							}
							if (!isUnicode && this.currentCharacter == '\n') {
								this.currentPosition--; // set current position on new line character
								break;
							}
							if (this.currentCharacter == '\"') {
								throw new InvalidInputException(INVALID_CHAR_IN_STRING);
							}
						}
					} else {
						this.currentPosition--; // set current position on new line character
					}
					throw new InvalidInputException(INVALID_CHAR_IN_STRING);
				}
				if (this.currentCharacter == '\\') {
					if (this.unicodeAsBackSlash) {
						this.withoutUnicodePtr--;
						// consume next character
						this.unicodeAsBackSlash = false;
						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
							getNextUnicodeChar();
							isUnicode = true;
							this.withoutUnicodePtr--;
						} else {
							isUnicode = false;
						}
					} else {
						if (this.withoutUnicodePtr == 0) {
							unicodeInitializeBuffer(this.currentPosition - this.startPosition);
						}
						this.withoutUnicodePtr --;
						this.currentCharacter = this.source[this.currentPosition++];
					}
					// we need to compute the escape character in a separate buffer
					scanEscapeCharacter();
					if (this.withoutUnicodePtr != 0) {
						unicodeStore();
					}
				}
				// consume next character
				this.unicodeAsBackSlash = false;
				if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
						&& (this.source[this.currentPosition] == 'u')) {
					getNextUnicodeChar();
					isUnicode = true;
				} else {
					isUnicode = false;
					if (this.withoutUnicodePtr != 0) {
						unicodeStore();
					}
				}

			}
		} catch (IndexOutOfBoundsException e) {
			this.currentPosition--;
			throw new InvalidInputException(UNTERMINATED_STRING);
		} catch (InvalidInputException e) {
			if (e.getMessage().equals(INVALID_ESCAPE)) {
				// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
				for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
					if (this.currentPosition + lookAhead == this.eofPosition)
						break;
					if (this.source[this.currentPosition + lookAhead] == '\n')
						break;
					if (this.source[this.currentPosition + lookAhead] == '\"') {
						this.currentPosition += lookAhead + 1;
						break;
					}
				}

			}
			throw e; // rethrow
		}
		return TokenNameStringLiteral;
	}
}

protected int scanForTextBlock() throws InvalidInputException {
	int lastQuotePos = 0;
	try {
		this.rawStart = this.currentPosition - this.startPosition;
		while (this.currentPosition <= this.eofPosition) {
			if (this.currentCharacter == '"') {
				lastQuotePos = this.currentPosition;
				// look for text block delimiter
				if (scanForTextBlockClose()) {
					this.currentPosition += 2;
					return TerminalTokens.TokenNameTextBlock;
				}
				if (this.withoutUnicodePtr != 0) {
					unicodeStore();
				}
			} else {
				if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
					if (this.recordLineSeparator) {
						pushLineSeparator();
					}
				}
			}
			outer: if (this.currentCharacter == '\\') {
				switch(this.source[this.currentPosition]) {
					case 'n' :
					case 'r' :
					case 'f' :
					case 's' :
						break outer;
					case '\n' :
					case '\r' :
						this.currentCharacter = '\\';
						this.currentPosition++;
						break;
					case '\"' :
						this.currentPosition++;
						this.currentCharacter = this.source[this.currentPosition++];
						continue;
					case '\\' :
						this.currentPosition++;
						break;
					default :
						if (this.unicodeAsBackSlash) {
							this.withoutUnicodePtr--;
							// consume next character
							if (this.currentPosition >= this.eofPosition) {
								break;
							}
							this.unicodeAsBackSlash = false;
							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
									&& (this.source[this.currentPosition] == 'u')) {
								getNextUnicodeChar();
								this.withoutUnicodePtr--;
							}
						} else {
							if (this.withoutUnicodePtr == 0) {
								unicodeInitializeBuffer(this.currentPosition - this.startPosition);
							}
							this.withoutUnicodePtr --;
							this.currentCharacter = this.source[this.currentPosition++];
						}
						int oldPos = this.currentPosition - 1;
						scanEscapeCharacter();
						if (ScannerHelper.isWhitespace(this.currentCharacter)) {
							if (this.withoutUnicodePtr == 0) {
								unicodeInitializeBuffer(this.currentPosition - this.startPosition);
							}
							unicodeStore('\\');
							this.currentPosition = oldPos;
							this.currentCharacter = this.source[this.currentPosition];
							break outer;
						}
				}
				if (this.withoutUnicodePtr != 0) {
					unicodeStore();
				}
			}
			// consume next character
			this.unicodeAsBackSlash = false;
			if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
					&& (this.source[this.currentPosition] == 'u')) {
				getNextUnicodeChar();
			} else {
				if (this.currentCharacter == '"'/* || skipWhitespace*/)
					continue;
				if (this.withoutUnicodePtr != 0) {
					unicodeStore();
				}
			}
		}
		if (lastQuotePos > 0)
			this.currentPosition = lastQuotePos;
		this.currentPosition = (lastQuotePos > 0) ? lastQuotePos : this.startPosition + this.rawStart;
		throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
	} catch (IndexOutOfBoundsException e) {
		this.currentPosition = (lastQuotePos > 0) ? lastQuotePos : this.startPosition + this.rawStart;
		throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
	}
}
public void getNextUnicodeChar()
	throws InvalidInputException {
	//VOID
	//handle the case of unicode.
	//when a unicode appears then we must use a buffer that holds char internal values
	//At the end of this method currentCharacter holds the new visited char
	//and currentPosition points right next after it

	//ALL getNextChar.... ARE OPTIMIZED COPIES
	int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
	this.currentPosition++;
	if (this.currentPosition < this.eofPosition) {
		while (this.source[this.currentPosition] == 'u') {
			this.currentPosition++;
			if (this.currentPosition >= this.eofPosition) {
				this.currentPosition--;
				throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
			}
			unicodeSize++;
		}
	} else {
		this.currentPosition--;
		throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
	}

	if ((this.currentPosition + 4) > this.eofPosition) {
		this.currentPosition += (this.eofPosition - this.currentPosition);
		throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
	}
	if ((c1 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15
    		|| c1 < 0
    		|| (c2 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15
    		|| c2 < 0
    		|| (c3 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15
    		|| c3 < 0
    		|| (c4 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15
    		|| c4 < 0){
		throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
	}
	this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
	//need the unicode buffer
	if (this.withoutUnicodePtr == 0) {
		//buffer all the entries that have been left aside....
		unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
	}
	//fill the buffer with the char
	unicodeStore();
	this.unicodeAsBackSlash = this.currentCharacter == '\\';
}
public NLSTag[] getNLSTags() {
	final int length = this.nlsTagsPtr;
	if (length != 0) {
		NLSTag[] result = new NLSTag[length];
		System.arraycopy(this.nlsTags, 0, result, 0, length);
		this.nlsTagsPtr = 0;
		return result;
	}
	return null;
}
public boolean[] getIdentityComparisonLines() {
	boolean [] retVal = this.validIdentityComparisonLines;
	this.validIdentityComparisonLines = null;
	return retVal;
}
public char[] getSource(){
	return this.source;
}
protected boolean isFirstTag() {
	return true;
}
//{ObjectTeams: made initial "found" an argument:
public final void jumpOverMethodBody() {
	jumpOverMethodBody(1);
}
public final void jumpOverMethodBody(int found) {

	this.wasAcr = false;
/* orig:
	int found = 1;
  :giro */
// SH}
	try {
		while (true) { //loop for jumping over comments
			this.withoutUnicodePtr = 0;
			// ---------Consume white space and handles startPosition---------
			boolean isWhiteSpace;
			do {
				this.startPosition = this.currentPosition;
				if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
					&& (this.source[this.currentPosition] == 'u')) {
					isWhiteSpace = jumpOverUnicodeWhiteSpace();
				} else {
					if (this.recordLineSeparator
							&& ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
						pushLineSeparator();
					}
					isWhiteSpace = CharOperation.isWhitespace(this.currentCharacter);
				}
			} while (isWhiteSpace);

			// -------consume token until } is found---------
			NextToken: switch (this.currentCharacter) {
				case '{' :
					found++;
					break NextToken;
				case '}' :
					found--;
					if (found == 0)
						return;
					break NextToken;
				case '\'' :
					{
						boolean test;
						test = getNextChar('\\');
						if (test) {
							try {
								if (this.unicodeAsBackSlash) {
									// consume next character
									this.unicodeAsBackSlash = false;
									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
										getNextUnicodeChar();
									} else {
										if (this.withoutUnicodePtr != 0) {
											unicodeStore();
										}
									}
								} else {
									this.currentCharacter = this.source[this.currentPosition++];
								}
								scanEscapeCharacter();
							} catch (InvalidInputException ex) {
								// ignore
							}
						} else {
							try { // consume next character
								this.unicodeAsBackSlash = false;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
								} else {
									if (this.withoutUnicodePtr != 0) {
										unicodeStore();
									}
								}
							} catch (InvalidInputException ex) {
								// ignore
							}
						}
						getNextChar('\'');
						break NextToken;
					}
				case '"' :
					boolean isTextBlock = false;
					int firstClosingBrace = 0;
					try {
						try { // consume next character
							isTextBlock = scanForTextBlockBeginning();
							if (!isTextBlock) {
								this.unicodeAsBackSlash = false;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
								} else {
									if (this.withoutUnicodePtr != 0) {
										unicodeStore();
									}
								}
							}
						} catch (InvalidInputException ex) {
								// ignore
						}

						Inner: while (this.currentPosition <= this.eofPosition) {
							if (isTextBlock) {
								switch (this.currentCharacter) {
									case '"':
										// look for text block delimiter
										if (scanForTextBlockClose()) {
											this.currentPosition += 2;
											this.currentCharacter = this.source[this.currentPosition];
											isTextBlock = false;
											break Inner;
										}
										break;
									case '}':
										if (firstClosingBrace == 0)
											firstClosingBrace = this.currentPosition;
										break;
									case '\r' :
										if (this.source[this.currentPosition] == '\n')
											this.currentPosition++;
										//$FALL-THROUGH$
									case '\n' :
										pushLineSeparator();
										//$FALL-THROUGH$
									default:
										if (this.currentCharacter == '\\' && this.source[this.currentPosition] == '"') {
											this.currentPosition++;
										}
										this.currentCharacter = this.source[this.currentPosition++];
										continue Inner;
								}
							} else if (this.currentCharacter == '"') {
								break Inner;
							}
							if (this.currentCharacter == '\r'){
								if (this.source[this.currentPosition] == '\n') this.currentPosition++;
								break NextToken; // the string cannot go further that the line
							}
							if (this.currentCharacter == '\n'){
								break; // the string cannot go further that the line
							}
							if (this.currentCharacter == '\\') {
								try {
									if (this.unicodeAsBackSlash) {
										// consume next character
										this.unicodeAsBackSlash = false;
										if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
											getNextUnicodeChar();
										} else {
											if (this.withoutUnicodePtr != 0) {
												unicodeStore();
											}
										}
									} else {
										this.currentCharacter = this.source[this.currentPosition++];
									}
									scanEscapeCharacter();
								} catch (InvalidInputException ex) {
									// ignore
								}
							}
							try { // consume next character
								this.unicodeAsBackSlash = false;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
								} else {
									if (this.withoutUnicodePtr != 0) {
										unicodeStore();
									}
								}
							} catch (InvalidInputException ex) {
								// ignore
							}
						}
					} catch (IndexOutOfBoundsException e) {
						if(isTextBlock) {
							// Pull it back to the first closing brace after the beginning
							// of the unclosed text block and let recovery take over.
							if (firstClosingBrace > 0) {
								this.currentPosition = firstClosingBrace - 1;
							}
						}
					}
					break NextToken;
				case '/' :
					{
						int test;
						if ((test = getNextChar('/', '*')) == 0) { //line comment
							try {
								this.lastCommentLinePosition = this.currentPosition;
								//get the next char
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
								}
								//handle the \\u case manually into comment
								if (this.currentCharacter == '\\') {
									if (this.source[this.currentPosition] == '\\')
										this.currentPosition++;
								} //jump over the \\
								boolean isUnicode = false;
								while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
									if (this.currentPosition >= this.eofPosition) {
										this.lastCommentLinePosition = this.currentPosition;
										this.currentPosition ++;
										// this avoids duplicating the code inside the catch(IndexOutOfBoundsException e) below
										throw new IndexOutOfBoundsException();
									}
									this.lastCommentLinePosition = this.currentPosition;
									//get the next char
									isUnicode = false;
									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
											&& (this.source[this.currentPosition] == 'u')) {
										isUnicode = true;
										getNextUnicodeChar();
									}
									//handle the \\u case manually into comment
									if (this.currentCharacter == '\\') {
										if (this.source[this.currentPosition] == '\\')
											this.currentPosition++;
									} //jump over the \\
								}
								/*
								 * We need to completely consume the line break
								 */
								if (this.currentCharacter == '\r'
										&& this.eofPosition > this.currentPosition) {
									if (this.source[this.currentPosition] == '\n') {
										this.currentPosition++;
										this.currentCharacter = '\n';
									} else if ((this.source[this.currentPosition] == '\\')
											&& (this.source[this.currentPosition + 1] == 'u')) {
										isUnicode = true;
										getNextUnicodeChar();
									}
								}
								recordComment(TokenNameCOMMENT_LINE);
								if (this.recordLineSeparator
									&& ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
										if ((this.checkNonExternalizedStringLiterals || this.checkUninternedIdentityComparison) &&
												this.lastPosition < this.currentPosition) {
											parseTags();
										}
										if (this.recordLineSeparator) {
											if (isUnicode) {
												pushUnicodeLineSeparator();
											} else {
												pushLineSeparator();
											}
										}
									}
							} catch (IndexOutOfBoundsException e) {
								 //an eof will then be generated
								this.currentPosition--;
								recordComment(TokenNameCOMMENT_LINE);
								if ((this.checkNonExternalizedStringLiterals || this.checkUninternedIdentityComparison) &&
										this.lastPosition < this.currentPosition) {
									parseTags();
								}
								if (!this.tokenizeComments) {
									this.currentPosition++;
								}
							}
							break NextToken;
						}
						if (test > 0) { //traditional and javadoc comment
							boolean isJavadoc = false;
							try { //get the next char
								boolean star = false;
								int previous;
								boolean isUnicode = false;
								// consume next character
								this.unicodeAsBackSlash = false;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
									isUnicode = true;
								} else {
									isUnicode = false;
									if (this.withoutUnicodePtr != 0) {
										unicodeStore();
									}
								}

								if (this.currentCharacter == '*') {
									isJavadoc = true;
									star = true;
								}
								if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
									if (this.recordLineSeparator) {
										if (isUnicode) {
											pushUnicodeLineSeparator();
										} else {
											pushLineSeparator();
										}
									}
								}
								isUnicode = false;
								previous = this.currentPosition;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
									isUnicode = true;
								} else {
									isUnicode = false;
								}
								//handle the \\u case manually into comment
								if (this.currentCharacter == '\\') {
									if (this.source[this.currentPosition] == '\\')
										this.currentPosition++; //jump over the \\
								}
								// empty comment is not a javadoc /**/
								if (this.currentCharacter == '/') {
									isJavadoc = false;
								}
								//loop until end of comment */
								int firstTag = 0;
								while ((this.currentCharacter != '/') || (!star)) {
									if (this.currentPosition >= this.eofPosition) {
										return;
									}
									if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
										if (this.recordLineSeparator) {
											if (isUnicode) {
												pushUnicodeLineSeparator();
											} else {
												pushLineSeparator();
											}
										}
									}
									switch (this.currentCharacter) {
										case '*':
											star = true;
											break;
										case '@':
											if (firstTag == 0 && this.isFirstTag()) {
												firstTag = previous;
											}
											//$FALL-THROUGH$ default case to set star to false
										default:
											star = false;
									}
									//get next char
									previous = this.currentPosition;
									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
											&& (this.source[this.currentPosition] == 'u')) {
										getNextUnicodeChar();
										isUnicode = true;
									} else {
										isUnicode = false;
									}
									//handle the \\u case manually into comment
									if (this.currentCharacter == '\\') {
										if (this.source[this.currentPosition] == '\\')
											this.currentPosition++;
									} //jump over the \\
								}
								recordComment(isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK);
								this.commentTagStarts[this.commentPtr] = firstTag;
							} catch (IndexOutOfBoundsException e) {
								return;
							}
							break NextToken;
						}
						break NextToken;
					}

				default :
					try {
						char c = this.currentCharacter;
						if (c < ScannerHelper.MAX_OBVIOUS) {
							if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
								scanIdentifierOrKeyword();
								break NextToken;
							} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) {
								scanNumber(false);
								break NextToken;
							} else {
								break NextToken;
							}
						}
						boolean isJavaIdStart;
						if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
							if (this.complianceLevel < ClassFileConstants.JDK1_5) {
								throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
							}
							// Unicode 4 detection
							char low = (char) getNextChar();
							if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
								// illegal low surrogate
								break NextToken;
							}
							isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low);
						} else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
							break NextToken;
						} else {
							// optimized case already checked
							isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c);
						}
						if (isJavaIdStart) {
							scanIdentifierOrKeyword();
							break NextToken;
						}
//						if (ScannerHelper.isDigit(this.currentCharacter)) {
//							scanNumber(false);
//							break NextToken;
//						}
					} catch (InvalidInputException ex) {
						// ignore
					}
			}
		}
		//-----------------end switch while try--------------------
	} catch (IndexOutOfBoundsException | InvalidInputException e) {
		// ignore
	}
	return;
}
//{ObjectTeams: COPY&PASTE
/* Tokenize a guard predicate, assuming that parentheses are properly balanced.
 */
public final void jumpOverPredicate() {

	this.wasAcr = false;
	int found = 0;
	try {
		while (true) { //loop for jumping over comments
			this.withoutUnicodePtr = 0;
			// ---------Consume white space and handles startPosition---------
			boolean isWhiteSpace;
			do {
				this.startPosition = this.currentPosition;
				if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
					&& (this.source[this.currentPosition] == 'u')) {
					isWhiteSpace = jumpOverUnicodeWhiteSpace();
				} else {
					if (this.recordLineSeparator
							&& ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
						pushLineSeparator();
					}
					isWhiteSpace = CharOperation.isWhitespace(this.currentCharacter);
				}
			} while (isWhiteSpace);

			// -------consume token until } is found---------
			NextToken: switch (this.currentCharacter) {
//{ObjectTeams: predicates are enclosed in '(' ')':
				case '(' :
					found++;
					break;
				case ')' :
					found--;
					if (found == 0)
						return;
					break;
// SH}
				case '{' :
					found++;
					break NextToken;
				case '}' :
					found--;
					if (found == 0)
						return;
					break NextToken;
				case '\'' :
					{
						boolean test;
						test = getNextChar('\\');
						if (test) {
							try {
								if (this.unicodeAsBackSlash) {
									// consume next character
									this.unicodeAsBackSlash = false;
									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
										getNextUnicodeChar();
									} else {
										if (this.withoutUnicodePtr != 0) {
											unicodeStore();
										}
									}
								} else {
									this.currentCharacter = this.source[this.currentPosition++];
								}
								scanEscapeCharacter();
							} catch (InvalidInputException ex) {
								// ignore
							}
						} else {
							try { // consume next character
								this.unicodeAsBackSlash = false;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
								} else {
									if (this.withoutUnicodePtr != 0) {
										unicodeStore();
									}
								}
							} catch (InvalidInputException ex) {
								// ignore
							}
						}
						getNextChar('\'');
						break NextToken;
					}
				case '"' :
					try {
						try { // consume next character
							this.unicodeAsBackSlash = false;
							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
									&& (this.source[this.currentPosition] == 'u')) {
								getNextUnicodeChar();
							} else {
								if (this.withoutUnicodePtr != 0) {
								    unicodeStore();
								}
							}
						} catch (InvalidInputException ex) {
								// ignore
						}
						while (this.currentCharacter != '"') {
							if (this.currentCharacter == '\r'){
								if (this.source[this.currentPosition] == '\n') this.currentPosition++;
								break NextToken; // the string cannot go further that the line
							}
							if (this.currentCharacter == '\n'){
								break; // the string cannot go further that the line
							}
							if (this.currentCharacter == '\\') {
								try {
									if (this.unicodeAsBackSlash) {
										// consume next character
										this.unicodeAsBackSlash = false;
										if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
											getNextUnicodeChar();
										} else {
											if (this.withoutUnicodePtr != 0) {
												unicodeStore();
											}
										}
									} else {
										this.currentCharacter = this.source[this.currentPosition++];
									}
									scanEscapeCharacter();
								} catch (InvalidInputException ex) {
									// ignore
								}
							}
							try { // consume next character
								this.unicodeAsBackSlash = false;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
								} else {
									if (this.withoutUnicodePtr != 0) {
										unicodeStore();
									}
								}
							} catch (InvalidInputException ex) {
								// ignore
							}
						}
					} catch (IndexOutOfBoundsException e) {
						return;
					}
					break NextToken;
				case '/' :
					{
						int test;
						if ((test = getNextChar('/', '*')) == 0) { //line comment
							try {
								this.lastCommentLinePosition = this.currentPosition;
								//get the next char
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
								}
								//handle the \\u case manually into comment
								if (this.currentCharacter == '\\') {
									if (this.source[this.currentPosition] == '\\')
										this.currentPosition++;
								} //jump over the \\
								boolean isUnicode = false;
								while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
									this.lastCommentLinePosition = this.currentPosition;
									//get the next char
									isUnicode = false;
									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
											&& (this.source[this.currentPosition] == 'u')) {
										isUnicode = true;
										getNextUnicodeChar();
									}
									//handle the \\u case manually into comment
									if (this.currentCharacter == '\\') {
										if (this.source[this.currentPosition] == '\\')
											this.currentPosition++;
									} //jump over the \\
								}
								/*
								 * We need to completely consume the line break
								 */
								if (this.currentCharacter == '\r'
								   && this.eofPosition > this.currentPosition) {
								   	if (this.source[this.currentPosition] == '\n') {
										this.currentPosition++;
										this.currentCharacter = '\n';
								   	} else if ((this.source[this.currentPosition] == '\\')
											&& (this.source[this.currentPosition + 1] == 'u')) {
										isUnicode = true;
										getNextUnicodeChar();
									}
							   	}
								recordComment(TokenNameCOMMENT_LINE);
								if (this.recordLineSeparator
									&& ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
										if (this.checkNonExternalizedStringLiterals &&
												this.lastPosition < this.currentPosition) {
											parseTags();
										}
										if (this.recordLineSeparator) {
											if (isUnicode) {
												pushUnicodeLineSeparator();
											} else {
												pushLineSeparator();
											}
										}
									}
							} catch (IndexOutOfBoundsException e) {
								 //an eof will then be generated
								this.currentPosition--;
								recordComment(TokenNameCOMMENT_LINE);
								if (this.checkNonExternalizedStringLiterals &&
										this.lastPosition < this.currentPosition) {
									parseTags();
								}
								if (!this.tokenizeComments) {
									this.currentPosition++;
								}
							}
							break NextToken;
						}
						if (test > 0) { //traditional and javadoc comment
							boolean isJavadoc = false;
							try { //get the next char
								boolean star = false;
								int previous;
								boolean isUnicode = false;
								// consume next character
								this.unicodeAsBackSlash = false;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
									isUnicode = true;
								} else {
									isUnicode = false;
									if (this.withoutUnicodePtr != 0) {
    								    unicodeStore();
									}
								}

								if (this.currentCharacter == '*') {
									isJavadoc = true;
									star = true;
								}
								if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
									if (this.recordLineSeparator) {
										if (isUnicode) {
											pushUnicodeLineSeparator();
										} else {
											pushLineSeparator();
										}
									}
								}
								isUnicode = false;
								previous = this.currentPosition;
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
										&& (this.source[this.currentPosition] == 'u')) {
									getNextUnicodeChar();
									isUnicode = true;
								} else {
									isUnicode = false;
								}
								//handle the \\u case manually into comment
								if (this.currentCharacter == '\\') {
									if (this.source[this.currentPosition] == '\\')
										this.currentPosition++; //jump over the \\
								}
								// empty comment is not a javadoc /**/
								if (this.currentCharacter == '/') {
									isJavadoc = false;
								}
								//loop until end of comment */
								int firstTag = 0;
								while ((this.currentCharacter != '/') || (!star)) {
									if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
										if (this.recordLineSeparator) {
											if (isUnicode) {
												pushUnicodeLineSeparator();
											} else {
												pushLineSeparator();
											}
										}
									}
									switch (this.currentCharacter) {
										case '*':
											star = true;
											break;
										case '@':
											if (firstTag == 0 && this.isFirstTag()) {
												firstTag = previous;
											}
											//$FALL-THROUGH$ default case to set star to false
										default:
											star = false;
									}
									//get next char
									previous = this.currentPosition;
									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
											&& (this.source[this.currentPosition] == 'u')) {
										getNextUnicodeChar();
										isUnicode = true;
									} else {
										isUnicode = false;
									}
									//handle the \\u case manually into comment
									if (this.currentCharacter == '\\') {
										if (this.source[this.currentPosition] == '\\')
											this.currentPosition++;
									} //jump over the \\
								}
								recordComment(isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK);
								this.commentTagStarts[this.commentPtr] = firstTag;
							} catch (IndexOutOfBoundsException e) {
								return;
							}
							break NextToken;
						}
						break NextToken;
					}

				default :
					try {
						char c = this.currentCharacter;
						if (c < ScannerHelper.MAX_OBVIOUS) {
							if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
								scanIdentifierOrKeyword();
								break NextToken;
							} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) {
								scanNumber(false);
								break NextToken;
							} else {
								break NextToken;
							}
						}
						boolean isJavaIdStart;
						if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
							if (this.complianceLevel < ClassFileConstants.JDK1_5) {
								throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
							}
							// Unicode 4 detection
							char low = (char) getNextChar();
							if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
								// illegal low surrogate
								break NextToken;
							}
							isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low);
						} else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
							break NextToken;
						} else {
							// optimized case already checked
							isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c);
						}
						if (isJavaIdStart) {
							scanIdentifierOrKeyword();
							break NextToken;
						}
//						if (ScannerHelper.isDigit(this.currentCharacter)) {
//							scanNumber(false);
//							break NextToken;
//						}
					} catch (InvalidInputException ex) {
						// ignore
					}
			}
		}
		//-----------------end switch while try--------------------
	} catch (IndexOutOfBoundsException e) {
		// ignore
	} catch (InvalidInputException e) {
		// ignore
	}
	return;
}
// SH}
public final boolean jumpOverUnicodeWhiteSpace() throws InvalidInputException {
	//BOOLEAN
	//handle the case of unicode. Jump over the next whiteSpace
	//making startPosition pointing on the next available char
	//On false, the currentCharacter is filled up with a potential
	//correct char

	this.wasAcr = false;
	getNextUnicodeChar();
	return CharOperation.isWhitespace(this.currentCharacter);
}

public boolean isInModuleDeclaration() {
	return this.fakeInModule || this.insideModuleInfo ||
			(this.activeParser != null ? this.activeParser.isParsingModuleDeclaration() : false);
}
protected boolean areRestrictedModuleKeywordsActive() {
	return this.scanContext != null && this.scanContext != ScanContext.INACTIVE;
}
void updateScanContext(int token) {
	switch (token) {
		case TerminalTokens.TokenNameSEMICOLON:	// next could be a KEYWORD
		case TerminalTokens.TokenNameRBRACE:
		case TokenNameRPAREN:
			this.scanContext = ScanContext.EXPECTING_KEYWORD;
			break;
		case TokenNameopen:
			this.scanContext = ScanContext.EXPECTING_KEYWORD;
			break;
		case TokenNamerequires:
			this.scanContext = ScanContext.AFTER_REQUIRES;
			break;
		case TokenNamemodule:
		case TokenNameexports:
		case TokenNameopens:
		case TokenNameuses:
		case TokenNameprovides:
		case TokenNameto:
		case TokenNamewith:
		case TokenNametransitive:
		case TokenNameDOT:
		case TokenNameimport:
		case TokenNameAT:
		case TokenNameAT308:
		case TokenNameCOMMA:
			this.scanContext = ScanContext.EXPECTING_IDENTIFIER;
			break;
		case TokenNameIdentifier:
			this.scanContext = ScanContext.EXPECTING_KEYWORD;
			break;
		case TerminalTokens.TokenNameLBRACE:
			this.scanContext = ScanContext.EXPECTING_KEYWORD;
			break;
		default: // anything else is unexpected and should not alter the context
			break;
	}
}

private void parseTags() {
	int position = 0;
	final int currentStartPosition = this.startPosition;
	final int currentLinePtr = this.linePtr;
	if (currentLinePtr >= 0) {
		position = this.lineEnds[currentLinePtr] + 1;
	}
	while (ScannerHelper.isWhitespace(this.source[position])) {
		position++;
	}
	if (currentStartPosition == position) {
		// the whole line is commented out
		return;
	}
	char[] s = null;
	int sourceEnd = this.currentPosition;
	int sourceStart = currentStartPosition;
	int sourceDelta = 0;
	if (this.withoutUnicodePtr != 0) {
		// 0 is used as a fast test flag so the real first char is in position 1
		System.arraycopy(
			this.withoutUnicodeBuffer,
			1,
			s = new char[this.withoutUnicodePtr],
			0,
			this.withoutUnicodePtr);
		sourceEnd = this.withoutUnicodePtr;
		sourceStart = 1;
		sourceDelta = currentStartPosition;
	} else {
		s = this.source;
	}
	int pos;
	if (this.checkNonExternalizedStringLiterals &&
			(pos = CharOperation.indexOf(TAG_PREFIX, s, true, sourceStart, sourceEnd)) != -1) {
		if (this.nlsTags == null) {
			this.nlsTags = new NLSTag[10];
			this.nlsTagsPtr = 0;
		}
		while (pos != -1) {
			int start = pos + TAG_PREFIX_LENGTH;
			int end = CharOperation.indexOf(TAG_POSTFIX, s, start, sourceEnd);
			if (end != -1) {
				NLSTag currentTag = null;
				final int currentLine = currentLinePtr + 1;
				try {
					currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, extractInt(s, start, end));
				} catch (NumberFormatException e) {
					currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, -1);
				}
				if (this.nlsTagsPtr == this.nlsTags.length) {
					// resize
					System.arraycopy(this.nlsTags, 0, (this.nlsTags = new NLSTag[this.nlsTagsPtr + 10]), 0, this.nlsTagsPtr);
				}
				this.nlsTags[this.nlsTagsPtr++] = currentTag;
			} else {
				end = start;
			}
			pos = CharOperation.indexOf(TAG_PREFIX, s, true, end, sourceEnd);
		}
	}

	if (this.checkUninternedIdentityComparison &&
			(pos = CharOperation.indexOf(IDENTITY_COMPARISON_TAG, s, true, sourceStart, sourceEnd)) != -1) {
		if (this.validIdentityComparisonLines == null) {
			this.validIdentityComparisonLines = new boolean[0];
		}
		int currentLine = currentLinePtr + 1;
		int length = this.validIdentityComparisonLines.length;
		System.arraycopy(this.validIdentityComparisonLines, 0, this.validIdentityComparisonLines = new boolean[currentLine + 1], 0, length);
		this.validIdentityComparisonLines[currentLine] = true;
	}
}
private int extractInt(char[] array, int start, int end) {
	int value = 0;
	for (int i = start; i < end; i++) {
		final char currentChar = array[i];
		int digit = 0;
		switch(currentChar) {
			case '0' :
				digit = 0;
				break;
			case '1' :
				digit = 1;
				break;
			case '2' :
				digit = 2;
				break;
			case '3' :
				digit = 3;
				break;
			case '4' :
				digit = 4;
				break;
			case '5' :
				digit = 5;
				break;
			case '6' :
				digit = 6;
				break;
			case '7' :
				digit = 7;
				break;
			case '8' :
				digit = 8;
				break;
			case '9' :
				digit = 9;
				break;
			default :
				throw new NumberFormatException();
		}
		value *= 10;
		if (digit < 0) throw new NumberFormatException();
		value += digit;
	}
	return value;
}
public final void pushLineSeparator() {
	//see comment on isLineDelimiter(char) for the use of '\n' and '\r'
	final int INCREMENT = 250;
	//currentCharacter is at position currentPosition-1
	// cr 000D
	if (this.currentCharacter == '\r') {
		int separatorPos = this.currentPosition - 1;
		if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;
		int length = this.lineEnds.length;
		if (++this.linePtr >=  length)
			System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[2*length + INCREMENT], 0, length);
		this.lineEnds[this.linePtr] = separatorPos;
		// look-ahead for merged cr+lf
		try {
			if (this.source[this.currentPosition] == '\n') {
				//System.out.println("look-ahead LF-" + this.currentPosition);
				this.lineEnds[this.linePtr] = this.currentPosition;
				this.currentPosition++;
				this.wasAcr = false;
			} else {
				this.wasAcr = true;
			}
		} catch(IndexOutOfBoundsException e) {
			this.wasAcr = true;
		}
	} else {
		// lf 000A
		if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf
			if (this.wasAcr && (this.lineEnds[this.linePtr] == (this.currentPosition - 2))) {
				//System.out.println("merge LF-" + (this.currentPosition - 1));
				this.lineEnds[this.linePtr] = this.currentPosition - 1;
			} else {
				int separatorPos = this.currentPosition - 1;
				if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;
				int length = this.lineEnds.length;
				if (++this.linePtr >=  length)
					System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[2*length + INCREMENT], 0, length);
				this.lineEnds[this.linePtr] = separatorPos;
			}
			this.wasAcr = false;
		}
	}
}
public final void pushUnicodeLineSeparator() {
	// cr 000D
	if (this.currentCharacter == '\r') {
		if (this.source[this.currentPosition] == '\n') {
			this.wasAcr = false;
		} else {
			this.wasAcr = true;
		}
	} else {
		// lf 000A
		if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf
			this.wasAcr = false;
		}
	}
}

public void recordComment(int token) {
	// compute position
	int commentStart = this.startPosition;
	int stopPosition = this.currentPosition;
	switch (token) {
		case TokenNameCOMMENT_LINE:
			// both positions are negative
			commentStart = -this.startPosition;
			stopPosition = -this.lastCommentLinePosition;
			break;
		case TokenNameCOMMENT_BLOCK:
			// only end position is negative
			stopPosition = -this.currentPosition;
			break;
	}

	// a new comment is recorded
	int length = this.commentStops.length;
	if (++this.commentPtr >=  length) {
		int newLength = length + COMMENT_ARRAYS_SIZE*10;
		System.arraycopy(this.commentStops, 0, this.commentStops = new int[newLength], 0, length);
		System.arraycopy(this.commentStarts, 0, this.commentStarts = new int[newLength], 0, length);
		System.arraycopy(this.commentTagStarts, 0, this.commentTagStarts = new int[newLength], 0, length);
	}
	this.commentStops[this.commentPtr] = stopPosition;
	this.commentStarts[this.commentPtr] = commentStart;
}

/**
 * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position.
 * Beyond this position, the scanner will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>).
 *
 * @param begin the given start position
 * @param end the given end position
 */
public void resetTo(int begin, int end) {
	resetTo(begin, end, isInModuleDeclaration());
}
public void resetTo(int begin, int end, boolean isModuleInfo) {
	resetTo(begin, end, isModuleInfo, null);
}
/**
 * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position.
 * Beyond this position, the scanner will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>).
 *
 * @param begin the given start position
 * @param end the given end position
 * @param isModuleInfo if true apply rules for restricted keywords even without a connection to a properly configured parser
 * @param context The scan context to use for restricted keyword support, use null to compute
 */
public void resetTo(int begin, int end, boolean isModuleInfo, ScanContext context) {
	//reset the scanner to a given position where it may rescan again

	this.diet = false;
	this.initialPosition = this.startPosition = this.currentPosition = begin;
	if (this.source != null && this.source.length < end) {
		this.eofPosition = this.source.length;
	} else {
		this.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
	}
	this.commentPtr = -1; // reset comment stack
	this.foundTaskCount = 0;
	this.lookBack[0] = this.lookBack[1] = this.nextToken = TokenNameNotAToken;
	this.consumingEllipsisAnnotations = false;
//{ObjectTeams: lookahead on '->':
	this._insideParameterMapping = false;
	this._bindoutLookahead = null;
// SH}
	this.insideModuleInfo = isModuleInfo;
	this.scanContext = context == null ? getScanContext(begin) : context;
	this.multiCaseLabelComma = false;
}

private ScanContext getScanContext(int begin) {
	if (!isInModuleDeclaration())
		return ScanContext.INACTIVE;
	if (begin == 0)
		return ScanContext.EXPECTING_KEYWORD;
	CompilerOptions options = new CompilerOptions();
	options.complianceLevel = this.complianceLevel;
	options.sourceLevel = this.sourceLevel;
	ScanContextDetector parser = new ScanContextDetector(options);
	return parser.getScanContext(this.source, begin - 1);
}
protected final void scanEscapeCharacter() throws InvalidInputException {
	// the string with "\\u" is a legal string of two chars \ and u
	//thus we use a direct access to the source (for regular cases).
	switch (this.currentCharacter) {
		case 'b' :
			this.currentCharacter = '\b';
			break;
		case 't' :
			this.currentCharacter = '\t';
			break;
		case 'n' :
			this.currentCharacter = '\n';
			break;
		case 'f' :
			this.currentCharacter = '\f';
			break;
		case 'r' :
			this.currentCharacter = '\r';
			break;
		case '\"' :
			this.currentCharacter = '\"';
			break;
		case '\'' :
			this.currentCharacter = '\'';
			break;
		case 's' :
			if (this.sourceLevel < ClassFileConstants.JDK15) {
				throw new InvalidInputException(INVALID_ESCAPE);
			}
			this.currentCharacter = ' ';
			break;
		case '\\' :
			this.currentCharacter = '\\';
			break;
		default :
			// -----------octal escape--------------
			// OctalDigit
			// OctalDigit OctalDigit
			// ZeroToThree OctalDigit OctalDigit

			int number = ScannerHelper.getHexadecimalValue(this.currentCharacter);
			if (number >= 0 && number <= 7) {
				boolean zeroToThreeNot = number > 3;
				if (ScannerHelper.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
					int digit = ScannerHelper.getHexadecimalValue(this.currentCharacter);
					if (digit >= 0 && digit <= 7) {
						number = (number * 8) + digit;
						if (ScannerHelper.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
							if (zeroToThreeNot) {// has read \NotZeroToThree OctalDigit Digit --> ignore last character
								this.currentPosition--;
							} else {
								digit = ScannerHelper.getHexadecimalValue(this.currentCharacter);
								if (digit >= 0 && digit <= 7){ // has read \ZeroToThree OctalDigit OctalDigit
									number = (number * 8) + digit;
								} else {// has read \ZeroToThree OctalDigit NonOctalDigit --> ignore last character
									this.currentPosition--;
								}
							}
						} else { // has read \OctalDigit NonDigit--> ignore last character
							this.currentPosition--;
						}
					} else { // has read \OctalDigit NonOctalDigit--> ignore last character
						this.currentPosition--;
					}
				} else { // has read \OctalDigit --> ignore last character
					this.currentPosition--;
				}
				if (number > 255)
					throw new InvalidInputException(INVALID_ESCAPE);
				this.currentCharacter = (char) number;
			} else
				throw new InvalidInputException(INVALID_ESCAPE);
	}
}

//{ObjectTeams: added to retrieve OT-specific special identifiers (after, before, replace)
/*
 * If the Identifier is an SpecialIdentifier it will return the appropriate symbol from TerminalTokens.
 * @param data[] Identifier String
 * @return The int-type of an Special Identifier or TokenNameERROR
 */
public int getCallinModifierToken(char[] data) {
// replace after before

  	int length=data.length;
	int index=0;
	char firstLetter = data[index];
	switch (firstLetter) {
		case 'a' :
			switch(length) {
				case 5: //after
					if ((data[++index] == 'f')
						&& (data[++index] == 't')
						&& (data[++index] == 'e')
						&& (data[++index] == 'r'))
							return TokenNameafter;
			}
			break;
		case 'b' :
			switch (length) {
				case 6:// before
					if ((data[++index] == 'e')
						&& (data[++index] == 'f')
						&& (data[++index] == 'o')
						&& (data[++index] == 'r')
						&& (data[++index] == 'e'))
							return TokenNamebefore;
			}
			break;
		case 'r' :
			switch (length) {
				case 7: //replace
					if ((data[++index] == 'e')
						&& (data[++index] == 'p')
						&& (data[++index] == 'l')
						&& (data[++index] == 'a')
						&& (data[++index] == 'c')
						&& (data[++index] == 'e'))
							return TokenNamereplace;
			}
	}
	return TokenNameERROR;
}
// Markus Witte}

public int scanIdentifierOrKeywordWithBoundCheck() {
	//test keywords

	//first dispatch on the first char.
	//then the length. If there are several
	//keywors with the same length AND the same first char, then do another
	//dispatch on the second char
	this.useAssertAsAnIndentifier = false;
	this.useEnumAsAnIndentifier = false;

	char[] src = this.source;
	identLoop: {
		int pos;
		int srcLength = this.eofPosition;
		while (true) {
			if ((pos = this.currentPosition) >= srcLength) // handle the obvious case upfront
				break identLoop;
			char c = src[pos];
			if (c < ScannerHelper.MAX_OBVIOUS) {
				if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] &
						(ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_IDENT_PART | ScannerHelper.C_DIGIT)) != 0) {
					if (this.withoutUnicodePtr != 0) {
							this.currentCharacter = c;
							unicodeStore();
						}
						this.currentPosition++;
				} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_SEPARATOR | ScannerHelper.C_JLS_SPACE)) != 0) {
						this.currentCharacter = c;
						break identLoop;
				} else {
					//System.out.println("slow<=128:  "+ c);
					while (getNextCharAsJavaIdentifierPartWithBoundCheck()){/*empty*/}
					break identLoop;
				}
			} else {
				//System.out.println("slow>>128:  "+ c);
				while (getNextCharAsJavaIdentifierPartWithBoundCheck()){/*empty*/}
				break identLoop;
			}
		}
	}

	int index, length;
	char[] data;
	if (this.withoutUnicodePtr == 0) {
		//quick test on length == 1 but not on length > 12 while most identifier
		//have a length which is <= 12...but there are lots of identifier with
		//only one char....
		if ((length = this.currentPosition - this.startPosition) == 1) {
			return TokenNameIdentifier;
		}
		data = this.source;
		index = this.startPosition;
	} else {
		if ((length = this.withoutUnicodePtr) == 1)
			return TokenNameIdentifier;
		data = this.withoutUnicodeBuffer;
		index = 1;
	}

	return internalScanIdentifierOrKeyword(index, length, data);
}
public int scanIdentifierOrKeyword() {
	//test keywords

	//first dispatch on the first char.
	//then the length. If there are several
	//keywords with the same length AND the same first char, then do another
	//dispatch on the second char
	this.useAssertAsAnIndentifier = false;
	this.useEnumAsAnIndentifier = false;

	char[] src = this.source;
	identLoop: {
		int pos;
		int srcLength = this.eofPosition;
		while (true) {
			if ((pos = this.currentPosition) >= srcLength) // handle the obvious case upfront
				break identLoop;
			char c = src[pos];
			if (c < ScannerHelper.MAX_OBVIOUS) {
				if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] &
						(ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_IDENT_PART | ScannerHelper.C_DIGIT)) != 0) {
					if (this.withoutUnicodePtr != 0) {
							this.currentCharacter = c;
							unicodeStore();
						}
						this.currentPosition++;
				} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_SEPARATOR | ScannerHelper.C_JLS_SPACE)) != 0) {
						this.currentCharacter = c;
						break identLoop;
				} else {
					//System.out.println("slow<=128:  "+ c);
					while (getNextCharAsJavaIdentifierPart()){/*empty*/}
					break identLoop;
				}
			} else {
				//System.out.println("slow>>128:  "+ c);
				while (getNextCharAsJavaIdentifierPart()){/*empty*/}
				break identLoop;
			}
		}
	}

	int index, length;
	char[] data;
	if (this.withoutUnicodePtr == 0) {
		//quick test on length == 1 but not on length > 12 while most identifier
		//have a length which is <= 12...but there are lots of identifier with
		//only one char....
		if ((length = this.currentPosition - this.startPosition) == 1) {
			return TokenNameIdentifier;
		}
		data = this.source;
		index = this.startPosition;
	} else {
		if ((length = this.withoutUnicodePtr) == 1)
			return TokenNameIdentifier;
		data = this.withoutUnicodeBuffer;
		index = 1;
	}

	return internalScanIdentifierOrKeyword(index, length, data);
}
private int internalScanIdentifierOrKeyword(int index, int length, char[] data) {
//{ObjectTeams: callin/calloutSeen/atStartOfImport/precedenceSeen has effect only once:
	boolean calloutSeen = this._calloutSeen;
	this._calloutSeen = false;
	boolean callinSeen = this._callinSeen;
	this._callinSeen = false;
	boolean precedenceSeen = this._precedenceSeen;
	this._precedenceSeen = false;
	boolean atStartOfImport = this._atStartOfImport;
	this._atStartOfImport = false;
// SH}
	switch (data[index]) {
		case 'a' :
			switch(length) {
//{ObjectTeams: keyword 'as':
				case 2: //as
					if (   this._isOTSource
						&& (data[++index] == 's')) {
						return TokenNameas;
					} else {
						return TokenNameIdentifier;
					}
// MW}
				case 8: //abstract
					if ((data[++index] == 'b')
						&& (data[++index] == 's')
						&& (data[++index] == 't')
						&& (data[++index] == 'r')
						&& (data[++index] == 'a')
						&& (data[++index] == 'c')
						&& (data[++index] == 't')) {
							return TokenNameabstract;
						} else {
							return TokenNameIdentifier;
						}
//{ObjectTeams: 'after' (only if after "<-" or "precedence"):
				case 5:
					if (callinSeen || precedenceSeen) {
						if (   (data[++index] == 'f')
							&& (data[++index] == 't')
							&& (data[++index] == 'e')
							&& (data[++index] == 'r'))
							return TokenNameafter;
					}
					return TokenNameIdentifier;
// SH}
				case 6: // assert
					if ((data[++index] == 's')
						&& (data[++index] == 's')
						&& (data[++index] == 'e')
						&& (data[++index] == 'r')
						&& (data[++index] == 't')) {
							if (this.sourceLevel >= ClassFileConstants.JDK1_4) {
								this.containsAssertKeyword = true;
								return TokenNameassert;
							} else {
								this.useAssertAsAnIndentifier = true;
								return TokenNameIdentifier;
							}
						} else {
							return TokenNameIdentifier;
						}
				default:
					return TokenNameIdentifier;
			}
		case 'b' : //boolean break byte (before)
			switch (length) {
				case 4 :
					if ((data[++index] == 'y') && (data[++index] == 't') && (data[++index] == 'e'))
						return TokenNamebyte;
					else
//{ObjectTeams: check for base keyword
						/*@original
						return TokenNameIdentifier;
						 */
						{
						if (   baseIsKeyword(atStartOfImport)
							&& (data[index] == 'a')
							&& (data[++index] == 's')
							&& (data[++index] == 'e'))
									return TokenNamebase;
							else
								return TokenNameIdentifier;
						}
//Markus Witte}
				case 5 :
					if ((data[++index] == 'r')
						&& (data[++index] == 'e')
						&& (data[++index] == 'a')
						&& (data[++index] == 'k'))
						return TokenNamebreak;
					else
						return TokenNameIdentifier;
//{ObjectTeams: 'before' (only if after "<-"):
				case 6:
					if (callinSeen) {
						if (   (data[++index] == 'e')
							&& (data[++index] == 'f')
							&& (data[++index] == 'o')
							&& (data[++index] == 'r')
							&& (data[++index] == 'e'))
							return TokenNamebefore;
					}
					return TokenNameIdentifier;
// SH}
				case 7 :
					if ((data[++index] == 'o')
						&& (data[++index] == 'o')
						&& (data[++index] == 'l')
						&& (data[++index] == 'e')
						&& (data[++index] == 'a')
						&& (data[++index] == 'n'))
						return TokenNameboolean;
					else
						return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}

		case 'c' : //case char catch const class continue
			switch (length) {
				case 4 :
					if (data[++index] == 'a')
						if ((data[++index] == 's') && (data[++index] == 'e'))
							return TokenNamecase;
						else
							return TokenNameIdentifier;
					else
						if ((data[index] == 'h') && (data[++index] == 'a') && (data[++index] == 'r'))
							return TokenNamechar;
						else
							return TokenNameIdentifier;
				case 5 :
					if (data[++index] == 'a')
						if ((data[++index] == 't') && (data[++index] == 'c') && (data[++index] == 'h'))
							return TokenNamecatch;
						else
							return TokenNameIdentifier;
					else
						if (data[index] == 'l')
							if ((data[++index] == 'a')
								&& (data[++index] == 's')
								&& (data[++index] == 's'))
//{ObjectTeams: advance scanner state:
							{
								if (this._teamKeywordSeen)
									enterOTSource(); // either in team class or in ROFI class
// orig:
								return TokenNameclass;
// :giro
							}
// SH}
							else
								return TokenNameIdentifier;
						else if ((data[index] == 'o')
							&& (data[++index] == 'n')
							&& (data[++index] == 's')
							&& (data[++index] == 't'))
							return TokenNameconst; //const is not used in java ???????
						else
							return TokenNameIdentifier;
//{ObjectTeams: check for callin keyword
				case 6: //callin
					if (   this._isOTSource
						&& (data[++index] == 'a')
						&& (data[++index] == 'l')
						&& (data[++index] == 'l')
						&& (data[++index] == 'i')
						&& (data[++index] == 'n'))
						return TokenNamecallin;
					else
						return TokenNameIdentifier;

//Markus Witte}
				case 8 :
					if ((data[++index] == 'o')
						&& (data[++index] == 'n')
						&& (data[++index] == 't')
						&& (data[++index] == 'i')
						&& (data[++index] == 'n')
						&& (data[++index] == 'u')
						&& (data[++index] == 'e'))
						return TokenNamecontinue;
					else
						return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}

		case 'd' : //default do double
			switch (length) {
				case 2 :
					if ((data[++index] == 'o'))
						return TokenNamedo;
					else
						return TokenNameIdentifier;
				case 6 :
					if ((data[++index] == 'o')
						&& (data[++index] == 'u')
						&& (data[++index] == 'b')
						&& (data[++index] == 'l')
						&& (data[++index] == 'e'))
						return TokenNamedouble;
					else
						return TokenNameIdentifier;
				case 7 :
					if ((data[++index] == 'e')
						&& (data[++index] == 'f')
						&& (data[++index] == 'a')
						&& (data[++index] == 'u')
						&& (data[++index] == 'l')
						&& (data[++index] == 't'))
						return TokenNamedefault;
					else
						return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}
		case 'e' : //else extends exports
			switch (length) {
				case 4 :
					if (data[++index] == 'l') {
						if ((data[++index] == 's') && (data[++index] == 'e')) {
							return TokenNameelse;
						} else {
							return TokenNameIdentifier;
						}
					} else if ((data[index] == 'n')
							&& (data[++index] == 'u')
							&& (data[++index] == 'm')) {
						if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
							return TokenNameenum;
						} else {
							this.useEnumAsAnIndentifier = true;
							return TokenNameIdentifier;
						}
					}
					return TokenNameIdentifier;
				case 7 :
						if ((data[++index] == 'x')) {
							if ((data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'n')
									&& (data[++index] == 'd') && (data[++index] == 's')) {
								return TokenNameextends;
							} else if (areRestrictedModuleKeywordsActive()
									&& (data[index] == 'p') && (data[++index] == 'o') && (data[++index] == 'r')
									&& (data[++index] == 't') && (data[++index] == 's')) {
								return TokenNameexports;
							} else
								return TokenNameIdentifier;
						} else
							return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}

		case 'f' : //final finally float for false
			switch (length) {
				case 3 :
					if ((data[++index] == 'o') && (data[++index] == 'r'))
						return TokenNamefor;
					else
						return TokenNameIdentifier;
				case 5 :
					if (data[++index] == 'i')
						if ((data[++index] == 'n')
							&& (data[++index] == 'a')
							&& (data[++index] == 'l')) {
							return TokenNamefinal;
						} else
							return TokenNameIdentifier;
					else
						if (data[index] == 'l')
							if ((data[++index] == 'o')
								&& (data[++index] == 'a')
								&& (data[++index] == 't'))
								return TokenNamefloat;
							else
								return TokenNameIdentifier;
						else
							if ((data[index] == 'a')
								&& (data[++index] == 'l')
								&& (data[++index] == 's')
								&& (data[++index] == 'e'))
								return TokenNamefalse;
							else
								return TokenNameIdentifier;
				case 7 :
					if ((data[++index] == 'i')
						&& (data[++index] == 'n')
						&& (data[++index] == 'a')
						&& (data[++index] == 'l')
						&& (data[++index] == 'l')
						&& (data[++index] == 'y'))
						return TokenNamefinally;
					else
						return TokenNameIdentifier;

				default :
					return TokenNameIdentifier;
			}
		case 'g' :
//{ObjectTeams: 'get':
			if (length == 3 && calloutSeen) {
				if (   (data[++index] == 'e')
					&& (data[++index] == 't'))
					return TokenNameget;
			}
// SH}
			//goto
			if (length == 4) {
				if ((data[++index] == 'o')
					&& (data[++index] == 't')
					&& (data[++index] == 'o')) {
					return TokenNamegoto;
				}
			} //no goto in java are allowed, so why java removes this keyword ???
			return TokenNameIdentifier;

		case 'i' : //if implements import instanceof int interface
			switch (length) {
				case 2 :
					if (data[++index] == 'f')
						return TokenNameif;
					else
						return TokenNameIdentifier;
				case 3 :
					if ((data[++index] == 'n') && (data[++index] == 't'))
						return TokenNameint;
					else
						return TokenNameIdentifier;
				case 6 :
					if ((data[++index] == 'm')
						&& (data[++index] == 'p')
						&& (data[++index] == 'o')
						&& (data[++index] == 'r')
						&& (data[++index] == 't'))
//{ObjectTeams: support 'base' as the very next word:
					{
						this._atStartOfImport = true;
// orig:
						return TokenNameimport;
// :giro
					}
// SH}
					else
						return TokenNameIdentifier;
				case 9 :
					if ((data[++index] == 'n')
						&& (data[++index] == 't')
						&& (data[++index] == 'e')
						&& (data[++index] == 'r')
						&& (data[++index] == 'f')
						&& (data[++index] == 'a')
						&& (data[++index] == 'c')
						&& (data[++index] == 'e'))
//{ObjectTeams: advance scanner state:
					{
						if (this._teamKeywordSeen)
							enterOTSource(); // in ROFI interface
// orig:
						return TokenNameinterface;
// :giro
					}
// SH}
					else
						return TokenNameIdentifier;
				case 10 :
					if (data[++index] == 'm')
						if ((data[++index] == 'p')
							&& (data[++index] == 'l')
							&& (data[++index] == 'e')
							&& (data[++index] == 'm')
							&& (data[++index] == 'e')
							&& (data[++index] == 'n')
							&& (data[++index] == 't')
							&& (data[++index] == 's'))
							return TokenNameimplements;
						else
							return TokenNameIdentifier;
					else
						if ((data[index] == 'n')
							&& (data[++index] == 's')
							&& (data[++index] == 't')
							&& (data[++index] == 'a')
							&& (data[++index] == 'n')
							&& (data[++index] == 'c')
							&& (data[++index] == 'e')
							&& (data[++index] == 'o')
							&& (data[++index] == 'f'))
							return TokenNameinstanceof;
						else
							return TokenNameIdentifier;

				default :
					return TokenNameIdentifier;
			}

		case 'l' : //long
			if (length == 4) {
				if ((data[++index] == 'o')
					&& (data[++index] == 'n')
					&& (data[++index] == 'g')) {
					return TokenNamelong;
				}
			}
			return TokenNameIdentifier;

		case 'm': //module
			switch (length) {
				case 6 :
					if (areRestrictedModuleKeywordsActive()
						&& (data[++index] == 'o')
						&& (data[++index] == 'd')
						&& (data[++index] == 'u')
						&& (data[++index] == 'l')
						&& (data[++index] == 'e'))
						return TokenNamemodule;
					else
						return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}

		case 'n' : //native new null
			switch (length) {
				case 3 :
					if ((data[++index] == 'e') && (data[++index] == 'w'))
						return TokenNamenew;
					else {
						int token = checkFor_KeyWord(index - 1, length, data);
						return token != TokenNameNotAToken ? token : TokenNameIdentifier;
					}
				case 4 :
					if ((data[++index] == 'u') && (data[++index] == 'l') && (data[++index] == 'l'))
						return TokenNamenull;
					else
						return TokenNameIdentifier;
				case 6 :
					if ((data[++index] == 'a')
						&& (data[++index] == 't')
						&& (data[++index] == 'i')
						&& (data[++index] == 'v')
						&& (data[++index] == 'e')) {
						return TokenNamenative;
					} else
						return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}

		case 'o':
			switch (length) {
				case 4 :
					if (areRestrictedModuleKeywordsActive() && (data[++index] == 'p') && (data[++index] == 'e') && (data[++index] == 'n'))
						return TokenNameopen;
					else
						return TokenNameIdentifier;
				case 5 :
					if (areRestrictedModuleKeywordsActive()
							&& (data[++index] == 'p')
							&& (data[++index] == 'e')
							&& (data[++index] == 'n')
							&& (data[++index] == 's'))
						return TokenNameopens;
					else
						return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}
		case 'p' : //package private protected public provides
			switch (length) {
				case 6 :
					if ((data[++index] == 'u')
						&& (data[++index] == 'b')
						&& (data[++index] == 'l')
						&& (data[++index] == 'i')
						&& (data[++index] == 'c')) {
						return TokenNamepublic;
					} else
						return TokenNameIdentifier;
				case 7 :
					if (data[++index] == 'a') {
						if ((data[++index] == 'c')
							&& (data[++index] == 'k')
							&& (data[++index] == 'a')
							&& (data[++index] == 'g')
							&& (data[++index] == 'e'))
							return TokenNamepackage;
						else
							return TokenNameIdentifier;
					} else {
						if ((data[index] == 'r')
							&& (data[++index] == 'i')
							&& (data[++index] == 'v')
							&& (data[++index] == 'a')
							&& (data[++index] == 't')
							&& (data[++index] == 'e')) {
							return TokenNameprivate;
						} else if ((data[index] == 'e')
								&& (data[++index] == 'r')
								&& (data[++index] == 'm')
								&& (data[++index] == 'i')
								&& (data[++index] == 't')
								&& (data[++index] == 's')) {
							return disambiguatedRestrictedIdentifierpermits(TokenNameRestrictedIdentifierpermits);
							} else
							return TokenNameIdentifier;
					}
				case 8 :
					if (areRestrictedModuleKeywordsActive()
						&& (data[++index] == 'r')
						&& (data[++index] == 'o')
						&& (data[++index] == 'v')
						&& (data[++index] == 'i')
						&& (data[++index] == 'd')
						&& (data[++index] == 'e')
						&& (data[++index] == 's')) {
						return TokenNameprovides;
					} else
//{ObjectTeams: check for playedBy/precedence keywords
/* orig:
						return TokenNameIdentifier;
  :giro */
					if (   this._isOTSource
						&& (data[++index] == 'l')
						&& (data[++index] == 'a')
						&& (data[++index] == 'y')
						&& (data[++index] == 'e')
						&& (data[++index] == 'd')
						&& (data[++index] == 'B')
						&& (data[++index] == 'y')) {
						return TokenNameplayedBy;
					} else
						return TokenNameIdentifier;
				case 10 :
					if (   this._isOTSource
						&& (data[++index] == 'r')
						&& (data[++index] == 'e')
						&& (data[++index] == 'c')
						&& (data[++index] == 'e')
						&& (data[++index] == 'd')
						&& (data[++index] == 'e')
						&& (data[++index] == 'n')
						&& (data[++index] == 'c')
						&& (data[++index] == 'e')) {
						this._precedenceSeen = true;
						return TokenNameprecedence;
					} else
						return TokenNameIdentifier;
//Markus Witte/SH}
				case 9 :
					if ((data[++index] == 'r')
						&& (data[++index] == 'o')
						&& (data[++index] == 't')
						&& (data[++index] == 'e')
						&& (data[++index] == 'c')
						&& (data[++index] == 't')
						&& (data[++index] == 'e')
						&& (data[++index] == 'd')) {
						return TokenNameprotected;
					} else
						return TokenNameIdentifier;

				default :
					return TokenNameIdentifier;
			}

		case 'r' : //return requires
			switch (length) {
				case 6:
					if (data[++index] == 'e') {
						if ((data[++index] == 't')
							&& (data[++index] == 'u')
							&& (data[++index] == 'r')
							&& (data[++index] == 'n'))
								return TokenNamereturn;
						else if ((data[index] == 'c')
							&& (data[++index] == 'o')
							&& (data[++index] == 'r')
							&& (data[++index] == 'd'))
								return disambiguatedRestrictedIdentifierrecord(TokenNameRestrictedIdentifierrecord);
					}
					return TokenNameIdentifier;
				case 8:
					if (areRestrictedModuleKeywordsActive()
						&& (data[++index] == 'e')
						&& (data[++index] == 'q')
						&& (data[++index] == 'u')
						&& (data[++index] == 'i')
						&& (data[++index] == 'r')
						&& (data[++index] == 'e')
						&& (data[++index] == 's')) {
						return TokenNamerequires;
					} else
						return TokenNameIdentifier;
//{ObjectTeams: 'replace' (only if after "<-"):
				case 7:
					if (callinSeen) {
						if (   (data[++index] == 'e')
							&& (data[++index] == 'p')
							&& (data[++index] == 'l')
							&& (data[++index] == 'a')
							&& (data[++index] == 'c')
							&& (data[++index] == 'e'))
							return TokenNamereplace;
					}
// SH}
			}
			return TokenNameIdentifier;

		case 's' : //short static super switch synchronized strictfp
			switch (length) {
//{ObjectTeams: 'set' (after '->')
				case 3:
					if (calloutSeen) {
						if (   (data[++index] == 'e')
					        && (data[++index] == 't'))
								return TokenNameset;
					}
					return TokenNameIdentifier;
// SH}
				case 5 :
					if (data[++index] == 'h')
						if ((data[++index] == 'o') && (data[++index] == 'r') && (data[++index] == 't'))
							return TokenNameshort;
						else
							return TokenNameIdentifier;
					else
						if ((data[index] == 'u')
							&& (data[++index] == 'p')
							&& (data[++index] == 'e')
							&& (data[++index] == 'r'))
							return TokenNamesuper;
						else
							return TokenNameIdentifier;

				case 6 :
					if (data[++index] == 't')
						if ((data[++index] == 'a')
							&& (data[++index] == 't')
							&& (data[++index] == 'i')
							&& (data[++index] == 'c')) {
							return TokenNamestatic;
						} else
							return TokenNameIdentifier;
					else
						if ((data[index] == 'w')
							&& (data[++index] == 'i')
							&& (data[++index] == 't')
							&& (data[++index] == 'c')
							&& (data[++index] == 'h')) {
							return TokenNameswitch;
						} else if ((data[index] == 'e')
							&& (data[++index] == 'a')
							&& (data[++index] == 'l')
							&& (data[++index] == 'e')
							&& (data[++index] == 'd')) {
								return disambiguatedRestrictedIdentifiersealed(TokenNameRestrictedIdentifiersealed);
						} else
							return TokenNameIdentifier;
				case 8 :
					if ((data[++index] == 't')
						&& (data[++index] == 'r')
						&& (data[++index] == 'i')
						&& (data[++index] == 'c')
						&& (data[++index] == 't')
						&& (data[++index] == 'f')
						&& (data[++index] == 'p'))
						return TokenNamestrictfp;
					else
						return TokenNameIdentifier;
				case 12 :
					if ((data[++index] == 'y')
						&& (data[++index] == 'n')
						&& (data[++index] == 'c')
						&& (data[++index] == 'h')
						&& (data[++index] == 'r')
						&& (data[++index] == 'o')
						&& (data[++index] == 'n')
						&& (data[++index] == 'i')
						&& (data[++index] == 'z')
						&& (data[++index] == 'e')
						&& (data[++index] == 'd')) {
						return TokenNamesynchronized;
					} else
						return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}

		case 't' : //try throw throws transient this true
			switch (length) {
				case 2:
					if (areRestrictedModuleKeywordsActive() && data[++index] == 'o')
						return TokenNameto;
					else
						return TokenNameIdentifier;
				case 3 :
					if ((data[++index] == 'r') && (data[++index] == 'y'))
						return TokenNametry;
					else
						return TokenNameIdentifier;
				case 4 :
					if (data[++index] == 'h')
						if ((data[++index] == 'i') && (data[++index] == 's'))
							return TokenNamethis;
						else
							return TokenNameIdentifier;
					else
						if ((data[index] == 'r') && (data[++index] == 'u') && (data[++index] == 'e'))
							return TokenNametrue;
						else
//{ObjectTeams: check for team keyword (always checked except after '.' -- if seen set isOTsource)
							if ((data[index] == 'e')
								&& (data[++index] == 'a')
								&& (data[++index] == 'm')
								&& (this._isOTSource || this._dotSeen == 0)
								&& !this.parsePureJavaOnly)
							{
								this._teamKeywordSeen = true;
								return TokenNameteam;
							} else
//Markus Witte}
							return TokenNameIdentifier;
				case 5 :
					if ((data[++index] == 'h')
						&& (data[++index] == 'r')
						&& (data[++index] == 'o')
						&& (data[++index] == 'w'))
						return TokenNamethrow;
					else
						return TokenNameIdentifier;
				case 6 :
//{ObjectTeams: check for tsuper keyword
/* orig:
					if ((data[++index] == 'h')
						&& (data[++index] == 'r')
 :giro */
				  if ((data[++index] == 'h')) {
					if ((data[++index] == 'r')
// orig:
						&& (data[++index] == 'o')
						&& (data[++index] == 'w')
						&& (data[++index] == 's'))
						return TokenNamethrows;
					else
						return TokenNameIdentifier;
// :giro
				  } else {
					if (   this._isOTSource
						&& (data[index] == 's')
						&& (data[++index] == 'u')
						&& (data[++index] == 'p')
						&& (data[++index] == 'e')
						&& (data[++index] == 'r'))
							return TokenNametsuper;
					else
						return TokenNameIdentifier;
				  }
//Markus Witte}
				case 9 :
					if ((data[++index] == 'r')
						&& (data[++index] == 'a')
						&& (data[++index] == 'n')
						&& (data[++index] == 's')
						&& (data[++index] == 'i')
						&& (data[++index] == 'e')
						&& (data[++index] == 'n')
						&& (data[++index] == 't')) {
						return TokenNametransient;
					} else
						return TokenNameIdentifier;
				case 10:
					if (areRestrictedModuleKeywordsActive() && (data[++index] == 'r')
						&& (data[++index] == 'a')
						&& (data[++index] == 'n')
						&& (data[++index] == 's')
						&& (data[++index] == 'i')
						&& (data[++index] == 't')
						&& (data[++index] == 'i')
						&& (data[++index] == 'v')
						&& (data[++index] == 'e')) {
						return TokenNametransitive;
					} else
						return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}
		case 'u' : //uses
			switch(length) {
				case 4 :
					if (areRestrictedModuleKeywordsActive()
							&& (data[++index] == 's') && (data[++index] == 'e') && (data[++index] == 's'))
						return TokenNameuses;
					else
						return TokenNameIdentifier;
				default :
					return TokenNameIdentifier;
			}
		case 'v' : //void volatile
			switch (length) {
				case 4 :
					if ((data[++index] == 'o') && (data[++index] == 'i') && (data[++index] == 'd'))
						return TokenNamevoid;
					else
						return TokenNameIdentifier;
				case 8 :
					if ((data[++index] == 'o')
						&& (data[++index] == 'l')
						&& (data[++index] == 'a')
						&& (data[++index] == 't')
						&& (data[++index] == 'i')
						&& (data[++index] == 'l')
						&& (data[++index] == 'e')) {
						return TokenNamevolatile;
					} else
						return TokenNameIdentifier;

				default :
					return TokenNameIdentifier;
			}

		case 'w' : //while widefp with
			switch (length) {
				case 4:
					if (areRestrictedModuleKeywordsActive()
						&& (data[++index] == 'i')
						&& (data[++index] == 't')
						&& (data[++index] == 'h'))
						return TokenNamewith;
					else
//{ObjectTeams: check for with, when keywords
					switch (data[++index]) {
					case 'i':
						if (   this._isOTSource
							&& (data[++index] == 't')
						    && (data[++index] == 'h'))
							return TokenNamewith;
						break;
					case 'h':
						if (   this._isOTSource
							&& (data[++index] == 'e')
						    && (data[++index] == 'n'))
							return TokenNamewhen;
					}
//Markus Witte}
					return TokenNameIdentifier;
				case 5 :
					if ((data[++index] == 'h')
						&& (data[++index] == 'i')
						&& (data[++index] == 'l')
						&& (data[++index] == 'e'))
						return TokenNamewhile;
					else
						return TokenNameIdentifier;
					//case 6:if ( (data[++index] =='i') && (data[++index]=='d') && (data[++index]=='e') && (data[++index]=='f')&& (data[++index]=='p'))
					//return TokenNamewidefp ;
					//else
					//return TokenNameIdentifier;
//{ObjectTeams: check for within keyword (also in std-Java files).
				case 6 :
					if ((data[++index] == 'i')
						&& (data[++index] == 't')
						&& (data[++index] == 'h')
						&& (data[++index] == 'i')
						&& (data[++index] == 'n')
						&& !this.parsePureJavaOnly)
						return TokenNamewithin;
					else
						return TokenNameIdentifier;

//Markus Witte}
				default :
					return TokenNameIdentifier;
			}

		case 'y' :
			switch (length) {
				case 5 :
					if ((data[++index] == 'i')
						&& (data[++index] == 'e')
						&& (data[++index] == 'l')
						&& (data[++index] == 'd'))
						return disambiguatedRestrictedIdentifierYield(TokenNameRestrictedIdentifierYield);
					//$FALL-THROUGH$
				default :
					return TokenNameIdentifier;
			}

		default :
			return TokenNameIdentifier;
	}
}


private int checkFor_KeyWord(int index, int length, char[] data) {
	if (this._Keywords == null) {
		this._Keywords = new HashMap<>(0);
		if (JavaFeature.RECORDS.isSupported(this.complianceLevel, this.previewEnabled)) {
			this._Keywords.put("non-sealed", TerminalTokens.TokenNamenon_sealed); //$NON-NLS-1$
		}
	}
	for (String key : this._Keywords.keySet()) {
		if (CharOperation.prefixEquals(key.toCharArray(), data, true /* isCaseSensitive */, index)) {
			this.currentPosition = this.currentPosition - length + key.length();
			if (this.currentPosition < this.eofPosition)
				this.currentCharacter = data[this.currentPosition];
			return this._Keywords.get(key);
		}
	}
	return TokenNameNotAToken;
}

public int scanNumber(boolean dotPrefix) throws InvalidInputException {

	//when entering this method the currentCharacter is the first
	//digit of the number. It may be preceeded by a '.' when
	//dotPrefix is true

	boolean floating = dotPrefix;
	if (!dotPrefix && (this.currentCharacter == '0')) {
		if (getNextChar('x', 'X') >= 0) { //----------hexa-----------------
			int start = this.currentPosition;
			consumeDigits(16, true);
			int end = this.currentPosition;
			if (getNextChar('l', 'L') >= 0) {
				if (end == start) {
					throw new InvalidInputException(INVALID_HEXA);
				}
				return TokenNameLongLiteral;
			} else if (getNextChar('.')) {
				// hexadecimal floating point literal
				// read decimal part
				boolean hasNoDigitsBeforeDot = end == start;
				start = this.currentPosition;
				consumeDigits(16, true);
				end = this.currentPosition;
				if (hasNoDigitsBeforeDot && end == start) {
					if (this.sourceLevel < ClassFileConstants.JDK1_5) {
						throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
					}
					throw new InvalidInputException(INVALID_HEXA);
				}

				if (getNextChar('p', 'P') >= 0) { // consume next character
					this.unicodeAsBackSlash = false;
					if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
							&& (this.source[this.currentPosition] == 'u')) {
						getNextUnicodeChar();
					} else {
						if (this.withoutUnicodePtr != 0) {
							unicodeStore();
						}
					}

					if ((this.currentCharacter == '-')
							|| (this.currentCharacter == '+')) { // consume next character
						this.unicodeAsBackSlash = false;
						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
								&& (this.source[this.currentPosition] == 'u')) {
							getNextUnicodeChar();
						} else {
							if (this.withoutUnicodePtr != 0) {
								unicodeStore();
							}
						}
					}
					if (!ScannerHelper.isDigit(this.currentCharacter)) {
						if (this.sourceLevel < ClassFileConstants.JDK1_5) {
							throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
						}
						if (this.currentCharacter == '_') {
							// wrongly place '_'
							consumeDigits(10);
							throw new InvalidInputException(INVALID_UNDERSCORE);
						}
						throw new InvalidInputException(INVALID_HEXA);
					}
					consumeDigits(10);
					if (getNextChar('f', 'F') >= 0) {
						if (this.sourceLevel < ClassFileConstants.JDK1_5) {
							throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
						}
						return TokenNameFloatingPointLiteral;
					}
					if (getNextChar('d', 'D') >= 0) {
						if (this.sourceLevel < ClassFileConstants.JDK1_5) {
							throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
						}
						return TokenNameDoubleLiteral;
					}
					if (getNextChar('l', 'L') >= 0) {
						if (this.sourceLevel < ClassFileConstants.JDK1_5) {
							throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
						}
						throw new InvalidInputException(INVALID_HEXA);
					}
					if (this.sourceLevel < ClassFileConstants.JDK1_5) {
						throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
					}
					return TokenNameDoubleLiteral;
				} else {
					if (this.sourceLevel < ClassFileConstants.JDK1_5) {
						throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
					}
					throw new InvalidInputException(INVALID_HEXA);
				}
			} else if (getNextChar('p', 'P') >= 0) { // consume next character
				if (end == start) { // Has no digits before exponent
					if (this.sourceLevel < ClassFileConstants.JDK1_5) {
						throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
					}
					throw new InvalidInputException(INVALID_HEXA);
				}
				this.unicodeAsBackSlash = false;
				if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
						&& (this.source[this.currentPosition] == 'u')) {
					getNextUnicodeChar();
				} else {
					if (this.withoutUnicodePtr != 0) {
						unicodeStore();
					}
				}

				if ((this.currentCharacter == '-')
						|| (this.currentCharacter == '+')) { // consume next character
					this.unicodeAsBackSlash = false;
					if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
							&& (this.source[this.currentPosition] == 'u')) {
						getNextUnicodeChar();
					} else {
						if (this.withoutUnicodePtr != 0) {
							unicodeStore();
						}
					}
				}
				if (!ScannerHelper.isDigit(this.currentCharacter)) {
					if (this.sourceLevel < ClassFileConstants.JDK1_5) {
						throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
					}
					if (this.currentCharacter == '_') {
						// wrongly place '_'
						consumeDigits(10);
						throw new InvalidInputException(INVALID_UNDERSCORE);
					}
					throw new InvalidInputException(INVALID_FLOAT);
				}
				consumeDigits(10);
				if (getNextChar('f', 'F') >= 0) {
					if (this.sourceLevel < ClassFileConstants.JDK1_5) {
						throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
					}
					return TokenNameFloatingPointLiteral;
				}
				if (getNextChar('d', 'D') >= 0) {
					if (this.sourceLevel < ClassFileConstants.JDK1_5) {
						throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
					}
					return TokenNameDoubleLiteral;
				}
				if (getNextChar('l', 'L') >= 0) {
					if (this.sourceLevel < ClassFileConstants.JDK1_5) {
						throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
					}
					throw new InvalidInputException(INVALID_HEXA);
				}
				if (this.sourceLevel < ClassFileConstants.JDK1_5) {
					throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
				}
				return TokenNameDoubleLiteral;
			} else {
				if (end == start)
					throw new InvalidInputException(INVALID_HEXA);
				return TokenNameIntegerLiteral;
			}
		} else if (getNextChar('b', 'B') >= 0) { //----------binary-----------------
			int start = this.currentPosition;
			consumeDigits(2, true);
			int end = this.currentPosition;
			if (end == start) {
				if (this.sourceLevel < ClassFileConstants.JDK1_7) {
					throw new InvalidInputException(BINARY_LITERAL_NOT_BELOW_17);
				}
				throw new InvalidInputException(INVALID_BINARY);
			}
			if (getNextChar('l', 'L') >= 0) {
				if (this.sourceLevel < ClassFileConstants.JDK1_7) {
					throw new InvalidInputException(BINARY_LITERAL_NOT_BELOW_17);
				}
				return TokenNameLongLiteral;
			}
			if (this.sourceLevel < ClassFileConstants.JDK1_7) {
				throw new InvalidInputException(BINARY_LITERAL_NOT_BELOW_17);
			}
			return TokenNameIntegerLiteral;
		}

		//there is no x or X nor b or B in the number
		//potential octal
		if (getNextCharAsDigit()) { //-------------potential octal-----------------
			consumeDigits(10);

			if (getNextChar('l', 'L') >= 0) {
				return TokenNameLongLiteral;
			}

			if (getNextChar('f', 'F') >= 0) {
				return TokenNameFloatingPointLiteral;
			}

			if (getNextChar('d', 'D') >= 0) {
				return TokenNameDoubleLiteral;
			} else { //make the distinction between octal and float ....
				boolean isInteger = true;
				if (getNextChar('.')) {
					isInteger = false;
					consumeDigits(10);
				}
				if (getNextChar('e', 'E') >= 0) { // consume next character
					isInteger = false;
					this.unicodeAsBackSlash = false;
					if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
							&& (this.source[this.currentPosition] == 'u')) {
						getNextUnicodeChar();
					} else {
						if (this.withoutUnicodePtr != 0) {
							unicodeStore();
						}
					}

					if ((this.currentCharacter == '-')
							|| (this.currentCharacter == '+')) { // consume next character
						this.unicodeAsBackSlash = false;
						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
								&& (this.source[this.currentPosition] == 'u')) {
							getNextUnicodeChar();
						} else {
							if (this.withoutUnicodePtr != 0) {
								unicodeStore();
							}
						}
					}
					if (!ScannerHelper.isDigit(this.currentCharacter)) {
						if (this.currentCharacter == '_') {
							// wrongly place '_'
							consumeDigits(10);
							throw new InvalidInputException(INVALID_UNDERSCORE);
						}
						throw new InvalidInputException(INVALID_FLOAT);
					}
					consumeDigits(10);
				}
				if (getNextChar('f', 'F') >= 0)
					return TokenNameFloatingPointLiteral;
				if (getNextChar('d', 'D') >= 0 || !isInteger)
					return TokenNameDoubleLiteral;
				return TokenNameIntegerLiteral;
			}
		} else {
			/* carry on */
		}
	}

	consumeDigits(10);

	if ((!dotPrefix) && (getNextChar('l', 'L') >= 0))
		return TokenNameLongLiteral;

	if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty
		consumeDigits(10, true);
		floating = true;
	}

	//if floating is true both exponant and suffix may be optional

	if (getNextChar('e', 'E') >= 0) {
		floating = true;
		// consume next character
		this.unicodeAsBackSlash = false;
		if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
				&& (this.source[this.currentPosition] == 'u')) {
			getNextUnicodeChar();
		} else {
			if (this.withoutUnicodePtr != 0) {
				unicodeStore();
			}
		}

		if ((this.currentCharacter == '-')
				|| (this.currentCharacter == '+')) { // consume next character
			this.unicodeAsBackSlash = false;
			if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
					&& (this.source[this.currentPosition] == 'u')) {
				getNextUnicodeChar();
			} else {
				if (this.withoutUnicodePtr != 0) {
					unicodeStore();
				}
			}
		}
		if (!ScannerHelper.isDigit(this.currentCharacter)) {
			if (this.currentCharacter == '_') {
				// wrongly place '_'
				consumeDigits(10);
				throw new InvalidInputException(INVALID_UNDERSCORE);
			}
			throw new InvalidInputException(INVALID_FLOAT);
		}
		// current character is a digit so we expect no digit first (the next character could be an underscore)
		consumeDigits(10);
	}

	if (getNextChar('d', 'D') >= 0)
		return TokenNameDoubleLiteral;
	if (getNextChar('f', 'F') >= 0)
		return TokenNameFloatingPointLiteral;

	//the long flag has been tested before

	return floating ? TokenNameDoubleLiteral : TokenNameIntegerLiteral;
}

/**
 * Search the line number corresponding to a specific position
 * @param position int
 * @return int
 */
public final int getLineNumber(int position) {
	return Util.getLineNumber(position, this.lineEnds, 0, this.linePtr);
}
public final void setSource(char[] sourceString){
	//the source-buffer is set to sourceString

	int sourceLength;
	if (sourceString == null) {
		this.source = CharOperation.NO_CHAR;
		sourceLength = 0;
	} else {
		this.source = sourceString;
		sourceLength = sourceString.length;
	}
	this.startPosition = -1;
	this.eofPosition = sourceLength;
	this.initialPosition = this.currentPosition = 0;
	this.containsAssertKeyword = false;
	this.linePtr = -1;
//{ObjectTeams: reset to default mode (std-Java).
	resetOTFlags();
// SH}
	this.scanContext = null;
	this.yieldColons = -1;
	this.insideModuleInfo = false;
}
/*
 * Should be used if a parse (usually a diet parse) has already been performed on the unit,
 * so as to get the already computed line end positions.
 */
public final void setSource(char[] contents, CompilationResult compilationResult) {
	if (contents == null) {
		char[] cuContents = compilationResult.compilationUnit.getContents();
		setSource(cuContents);
	} else {
		setSource(contents);
	}
	int[] lineSeparatorPositions = compilationResult.lineSeparatorPositions;
	if (lineSeparatorPositions != null) {
		this.lineEnds = lineSeparatorPositions;
		this.linePtr = lineSeparatorPositions.length - 1;
	}
}
/*
 * Should be used if a parse (usually a diet parse) has already been performed on the unit,
 * so as to get the already computed line end positions.
 */
public final void setSource(CompilationResult compilationResult) {
	setSource(null, compilationResult);
}
@Override
public String toString() {
	if (this.startPosition == this.eofPosition)
		return "EOF\n\n" + new String(this.source); //$NON-NLS-1$
	if (this.currentPosition > this.eofPosition)
		return "behind the EOF\n\n" + new String(this.source); //$NON-NLS-1$
	if (this.currentPosition <= 0)
		return "NOT started!\n\n"+ (this.source != null ? new String(this.source) : ""); //$NON-NLS-1$ //$NON-NLS-2$

	StringBuilder buffer = new StringBuilder();
	if (this.startPosition < 1000) {
		buffer.append(this.source, 0, this.startPosition);
	} else {
		buffer.append("<source beginning>\n...\n"); //$NON-NLS-1$
		int line = Util.getLineNumber(this.startPosition-1000, this.lineEnds, 0, this.linePtr);
		int lineStart = getLineStart(line);
		buffer.append(this.source, lineStart, this.startPosition-lineStart);
	}

	buffer.append("\n===============================\nStarts here -->"); //$NON-NLS-1$
	int middleLength = (this.currentPosition - 1) - this.startPosition + 1;
	if (middleLength > -1) {
		buffer.append(this.source, this.startPosition, middleLength);
	}
	if (this.nextToken != TerminalTokens.TokenNameNotAToken) {
		buffer.append("<-- Ends here [in pipeline " + toStringAction(this.nextToken) + "]\n===============================\n"); //$NON-NLS-1$ //$NON-NLS-2$
	} else {
		buffer.append("<-- Ends here\n===============================\n"); //$NON-NLS-1$
	}

	buffer.append(this.source, (this.currentPosition - 1) + 1, this.eofPosition - (this.currentPosition - 1) - 1);

	return buffer.toString();
}
public String toStringAction(int act) {
	switch (act) {
		case TokenNameIdentifier :
			return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		case TokenNameRestrictedIdentifierYield :
			return "yield"; //$NON-NLS-1$
		case TokenNameRestrictedIdentifierrecord :
			return "record"; //$NON-NLS-1$
		case TokenNameabstract :
			return "abstract"; //$NON-NLS-1$
//{ObjectTeams: deal with OT-specific identifiers
		case TokenNameas :
			return "as";  //$NON-NLS-1$
		case TokenNamecallin :
			return "callin"; //$NON-NLS-1$
		case TokenNameplayedBy :
			return "playedBy"; //$NON-NLS-1$
		case TokenNameprecedence :
			return "precedence"; //$NON-NLS-1$
		case TokenNameteam :
			return "team"; //$NON-NLS-1$
		case TokenNamewith :
			return "with"; //$NON-NLS-1$
		case TokenNamewithin :
			return "within";  //$NON-NLS-1$
		case TokenNamereplace:
			return "replace"; //$NON-NLS-1$
		case TokenNamebefore:
			return "before"; //$NON-NLS-1$
		case TokenNameafter:
			return "after"; //$NON-NLS-1$
		case TokenNameget:
			return "get"; //$NON-NLS-1$
		case TokenNameset:
			return "set"; //$NON-NLS-1$
// Markus Witte}
		case TokenNameboolean :
			return "boolean"; //$NON-NLS-1$
		case TokenNamebreak :
			return "break"; //$NON-NLS-1$
		case TokenNamebyte :
			return "byte"; //$NON-NLS-1$
		case TokenNamecase :
			return "case"; //$NON-NLS-1$
		case TokenNamecatch :
			return "catch"; //$NON-NLS-1$
		case TokenNamechar :
			return "char"; //$NON-NLS-1$
		case TokenNameclass :
			return "class"; //$NON-NLS-1$
		case TokenNamecontinue :
			return "continue"; //$NON-NLS-1$
		case TokenNamedefault :
			return "default"; //$NON-NLS-1$
		case TokenNamedo :
			return "do"; //$NON-NLS-1$
		case TokenNamedouble :
			return "double"; //$NON-NLS-1$
		case TokenNameelse :
			return "else"; //$NON-NLS-1$
		case TokenNameextends :
			return "extends"; //$NON-NLS-1$
		case TokenNamefalse :
			return "false"; //$NON-NLS-1$
		case TokenNamefinal :
			return "final"; //$NON-NLS-1$
		case TokenNamefinally :
			return "finally"; //$NON-NLS-1$
		case TokenNamefloat :
			return "float"; //$NON-NLS-1$
		case TokenNamefor :
			return "for"; //$NON-NLS-1$
		case TokenNameif :
			return "if"; //$NON-NLS-1$
		case TokenNameimplements :
			return "implements"; //$NON-NLS-1$
		case TokenNameimport :
			return "import"; //$NON-NLS-1$
		case TokenNameinstanceof :
			return "instanceof"; //$NON-NLS-1$
		case TokenNameint :
			return "int"; //$NON-NLS-1$
		case TokenNameinterface :
			return "interface"; //$NON-NLS-1$
		case TokenNamelong :
			return "long"; //$NON-NLS-1$
		case TokenNamenative :
			return "native"; //$NON-NLS-1$
		case TokenNamenew :
			return "new"; //$NON-NLS-1$
		case TokenNamenon_sealed:
			return "non-sealed"; //$NON-NLS-1$
		case TokenNamenull :
			return "null"; //$NON-NLS-1$
		case TokenNamepackage :
			return "package"; //$NON-NLS-1$
		case TokenNameRestrictedIdentifierpermits:
			return "permits"; //$NON-NLS-1$
		case TokenNameprivate :
			return "private"; //$NON-NLS-1$
		case TokenNameprotected :
			return "protected"; //$NON-NLS-1$
		case TokenNamepublic :
			return "public"; //$NON-NLS-1$
		case TokenNamereturn :
			return "return"; //$NON-NLS-1$
		case TokenNameRestrictedIdentifiersealed:
			return "sealed"; //$NON-NLS-1$
		case TokenNameshort :
			return "short"; //$NON-NLS-1$
		case TokenNamestatic :
			return "static"; //$NON-NLS-1$
		case TokenNamesuper :
			return "super"; //$NON-NLS-1$
		case TokenNameswitch :
			return "switch"; //$NON-NLS-1$
		case TokenNamesynchronized :
			return "synchronized"; //$NON-NLS-1$
		case TokenNamethis :
			return "this"; //$NON-NLS-1$
		case TokenNamethrow :
			return "throw"; //$NON-NLS-1$
		case TokenNamethrows :
			return "throws"; //$NON-NLS-1$
		case TokenNametransient :
			return "transient"; //$NON-NLS-1$
		case TokenNametrue :
			return "true"; //$NON-NLS-1$
		case TokenNametry :
			return "try"; //$NON-NLS-1$
		case TokenNamevoid :
			return "void"; //$NON-NLS-1$
		case TokenNamevolatile :
			return "volatile"; //$NON-NLS-1$
		case TokenNamewhile :
			return "while"; //$NON-NLS-1$
		case TokenNamemodule :
			return "module"; //$NON-NLS-1$
		case TokenNamerequires :
			return "requires"; //$NON-NLS-1$
		case TokenNameexports :
			return "exports"; //$NON-NLS-1$

		case TokenNameIntegerLiteral :
			return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		case TokenNameLongLiteral :
			return "Long(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		case TokenNameFloatingPointLiteral :
			return "Float(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		case TokenNameDoubleLiteral :
			return "Double(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		case TokenNameCharacterLiteral :
			return "Char(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		case TokenNameStringLiteral :
			return "String(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		case TokenNameTextBlock :
			return "String(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		case TokenNamePLUS_PLUS :
			return "++"; //$NON-NLS-1$
		case TokenNameMINUS_MINUS :
			return "--"; //$NON-NLS-1$
		case TokenNameEQUAL_EQUAL :
			return "=="; //$NON-NLS-1$
//{ObjectTeams: deal with callins/callouts
		case TokenNameBINDIN :
			return "<-"; //$NON-NLS-1$
		case TokenNameCALLOUT_OVERRIDE :
			return "=>"; //$NON-NLS-1$
// Markus Witte}
		case TokenNameLESS_EQUAL :
			return "<="; //$NON-NLS-1$
		case TokenNameGREATER_EQUAL :
			return ">="; //$NON-NLS-1$
		case TokenNameNOT_EQUAL :
			return "!="; //$NON-NLS-1$
		case TokenNameLEFT_SHIFT :
			return "<<"; //$NON-NLS-1$
		case TokenNameRIGHT_SHIFT :
			return ">>"; //$NON-NLS-1$
		case TokenNameUNSIGNED_RIGHT_SHIFT :
			return ">>>"; //$NON-NLS-1$
		case TokenNamePLUS_EQUAL :
			return "+="; //$NON-NLS-1$
		case TokenNameMINUS_EQUAL :
			return "-="; //$NON-NLS-1$
		case TokenNameARROW :
			return "->"; //$NON-NLS-1$
		case TokenNameMULTIPLY_EQUAL :
			return "*="; //$NON-NLS-1$
		case TokenNameDIVIDE_EQUAL :
			return "/="; //$NON-NLS-1$
		case TokenNameAND_EQUAL :
			return "&="; //$NON-NLS-1$
		case TokenNameOR_EQUAL :
			return "|="; //$NON-NLS-1$
		case TokenNameXOR_EQUAL :
			return "^="; //$NON-NLS-1$
		case TokenNameREMAINDER_EQUAL :
			return "%="; //$NON-NLS-1$
		case TokenNameLEFT_SHIFT_EQUAL :
			return "<<="; //$NON-NLS-1$
		case TokenNameRIGHT_SHIFT_EQUAL :
			return ">>="; //$NON-NLS-1$
		case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL :
			return ">>>="; //$NON-NLS-1$
		case TokenNameOR_OR :
			return "||"; //$NON-NLS-1$
		case TokenNameAND_AND :
			return "&&"; //$NON-NLS-1$
		case TokenNamePLUS :
			return "+"; //$NON-NLS-1$
		case TokenNameMINUS :
			return "-"; //$NON-NLS-1$
		case TokenNameNOT :
			return "!"; //$NON-NLS-1$
		case TokenNameREMAINDER :
			return "%"; //$NON-NLS-1$
		case TokenNameXOR :
			return "^"; //$NON-NLS-1$
		case TokenNameAND :
			return "&"; //$NON-NLS-1$
		case TokenNameMULTIPLY :
			return "*"; //$NON-NLS-1$
		case TokenNameOR :
			return "|"; //$NON-NLS-1$
		case TokenNameTWIDDLE :
			return "~"; //$NON-NLS-1$
		case TokenNameDIVIDE :
			return "/"; //$NON-NLS-1$
		case TokenNameGREATER :
			return ">"; //$NON-NLS-1$
		case TokenNameLESS :
			return "<"; //$NON-NLS-1$
		case TokenNameLPAREN :
			return "("; //$NON-NLS-1$
		case TokenNameRPAREN :
			return ")"; //$NON-NLS-1$
		case TokenNameLBRACE :
			return "{"; //$NON-NLS-1$
		case TokenNameRBRACE :
			return "}"; //$NON-NLS-1$
		case TokenNameLBRACKET :
			return "["; //$NON-NLS-1$
		case TokenNameRBRACKET :
			return "]"; //$NON-NLS-1$
		case TokenNameSEMICOLON :
			return ";"; //$NON-NLS-1$
		case TokenNameQUESTION :
			return "?"; //$NON-NLS-1$
		case TokenNameCOLON :
			return ":"; //$NON-NLS-1$
		case TokenNameCOLON_COLON :
			return "::"; //$NON-NLS-1$
		case TokenNameCOMMA :
			return ","; //$NON-NLS-1$
		case TokenNameDOT :
			return "."; //$NON-NLS-1$
		case TokenNameEQUAL :
			return "="; //$NON-NLS-1$
		case TokenNameEOF :
			return "EOF"; //$NON-NLS-1$
		case TokenNameWHITESPACE :
			return "white_space(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		default :
			return "not-a-token"; //$NON-NLS-1$
	}
}
public void unicodeInitializeBuffer(int length) {
	this.withoutUnicodePtr = length;
	if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[length+(1+10)];
	int bLength = this.withoutUnicodeBuffer.length;
	if (1+length >= bLength) {
		System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length + (1+10)], 0, bLength);
	}
	System.arraycopy(this.source, this.startPosition, this.withoutUnicodeBuffer, 1, length);
}
public void unicodeStore() {
	int pos = ++this.withoutUnicodePtr;
	if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[10];
	int length = this.withoutUnicodeBuffer.length;
	if (pos == length) {
		System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length * 2], 0, length);
	}
	this.withoutUnicodeBuffer[pos] = this.currentCharacter;
}
public void unicodeStore(char character) {
	int pos = ++this.withoutUnicodePtr;
	if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[10];
	int length = this.withoutUnicodeBuffer.length;
	if (pos == length) {
		System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length * 2], 0, length);
	}
	this.withoutUnicodeBuffer[pos] = character;
}

public static boolean isIdentifier(int token) {
	return token == TerminalTokens.TokenNameIdentifier;
}

public static boolean isLiteral(int token) {
	switch(token) {
		case TerminalTokens.TokenNameIntegerLiteral:
		case TerminalTokens.TokenNameLongLiteral:
		case TerminalTokens.TokenNameFloatingPointLiteral:
		case TerminalTokens.TokenNameDoubleLiteral:
		case TerminalTokens.TokenNameStringLiteral:
		case TerminalTokens.TokenNameTextBlock:
		case TerminalTokens.TokenNameCharacterLiteral:
			return true;
		default:
			return false;
	}
}

public static boolean isKeyword(int token) {
	switch(token) {
		case TerminalTokens.TokenNameabstract:
		case TerminalTokens.TokenNameassert:
		case TerminalTokens.TokenNamebyte:
		case TerminalTokens.TokenNamebreak:
		case TerminalTokens.TokenNameboolean:
		case TerminalTokens.TokenNamecase:
		case TerminalTokens.TokenNamechar:
		case TerminalTokens.TokenNamecatch:
		case TerminalTokens.TokenNameclass:
		case TerminalTokens.TokenNamecontinue:
		case TerminalTokens.TokenNamedo:
		case TerminalTokens.TokenNamedouble:
		case TerminalTokens.TokenNamedefault:
		case TerminalTokens.TokenNameelse:
		case TerminalTokens.TokenNameextends:
		case TerminalTokens.TokenNamefor:
		case TerminalTokens.TokenNamefinal:
		case TerminalTokens.TokenNamefloat:
		case TerminalTokens.TokenNamefalse:
		case TerminalTokens.TokenNamefinally:
		case TerminalTokens.TokenNameif:
		case TerminalTokens.TokenNameint:
		case TerminalTokens.TokenNameimport:
		case TerminalTokens.TokenNameinterface:
		case TerminalTokens.TokenNameimplements:
		case TerminalTokens.TokenNameinstanceof:
		case TerminalTokens.TokenNamelong:
		case TerminalTokens.TokenNamenew:
		case TerminalTokens.TokenNamenon_sealed:
		case TerminalTokens.TokenNamenull:
		case TerminalTokens.TokenNamenative:
		case TerminalTokens.TokenNamepublic:
		case TerminalTokens.TokenNamepackage:
		case TerminalTokens.TokenNameprivate:
		case TerminalTokens.TokenNameprotected:
		case TerminalTokens.TokenNamereturn:
		case TerminalTokens.TokenNameshort:
		case TerminalTokens.TokenNamesuper:
		case TerminalTokens.TokenNamestatic:
		case TerminalTokens.TokenNameswitch:
		case TerminalTokens.TokenNamestrictfp:
		case TerminalTokens.TokenNamesynchronized:
		case TerminalTokens.TokenNametry:
		case TerminalTokens.TokenNamethis:
		case TerminalTokens.TokenNametrue:
		case TerminalTokens.TokenNamethrow:
		case TerminalTokens.TokenNamethrows:
		case TerminalTokens.TokenNametransient:
		case TerminalTokens.TokenNamevoid:
		case TerminalTokens.TokenNamevolatile:
		case TerminalTokens.TokenNamewhile:
			return true;
		case TerminalTokens.TokenNameRestrictedIdentifierYield:
		case TerminalTokens.TokenNameRestrictedIdentifierrecord:
		case TerminalTokens.TokenNameRestrictedIdentifiersealed:
		case TerminalTokens.TokenNameRestrictedIdentifierpermits:
			// making explicit - not a (restricted) keyword but restricted identifier.
			//$FALL-THROUGH$
		default:
			return false;
	}
}

// Vanguard Scanner - A Private utility helper class for the scanner.
private static final class VanguardScanner extends Scanner {

	public VanguardScanner(long sourceLevel, long complianceLevel, boolean previewEnabled) {
		super (false /*comment*/, false /*whitespace*/, false /*nls*/, sourceLevel, complianceLevel, null/*taskTag*/,
				null/*taskPriorities*/, false /*taskCaseSensitive*/, previewEnabled);
	}

	@Override
	public int getNextToken() throws InvalidInputException {
		int token;
		if (this.nextToken != TokenNameNotAToken) {
			token = this.nextToken;
			this.nextToken = TokenNameNotAToken;
			return token; // presumed to be unambiguous.
		}
		if (this.scanContext == null) { // init lazily, since isInModuleDeclaration may need the parser to be known
			this.scanContext = isInModuleDeclaration() ? ScanContext.EXPECTING_KEYWORD : ScanContext.INACTIVE;
		}
		token = getNextToken0();
		if (areRestrictedModuleKeywordsActive()) {
			if (isRestrictedKeyword(token))
				token = disambiguatedRestrictedKeyword(token);
			updateScanContext(token);
		} else if (mayBeAtCasePattern(token)) {
			token = disambiguateCasePattern(token, this);
		} else
		if (token == TokenNameAT && atTypeAnnotation()) {
			if (((VanguardParser) this.activeParser).currentGoal == Goal.LambdaParameterListGoal) {
				token = disambiguatedToken(token, this);
			} else {
				token = TokenNameAT308;
			}
		}
		return token == TokenNameEOF ? TokenNameNotAToken : token;
	}
}

private static class Goal {

	int first;      // steer the parser towards a single minded pursuit.
	int [] follow;  // the definite terminal symbols that signal the successful reduction to goal.
	int[] rules;

	static int LambdaParameterListRule = 0;
	static int IntersectionCastRule = 0;
	static int ReferenceExpressionRule = 0;
	static int VarargTypeAnnotationsRule  = 0;
	static int BlockStatementoptRule = 0;
	static int YieldStatementRule = 0;
	static int SwitchLabelCaseLhsRule = 0;
	static int[] RestrictedIdentifierSealedRule;
	static int[] RestrictedIdentifierPermitsRule;
	static int[] PatternRules;

	static Goal LambdaParameterListGoal;
	static Goal IntersectionCastGoal;
	static Goal VarargTypeAnnotationGoal;
	static Goal ReferenceExpressionGoal;
	static Goal BlockStatementoptGoal;
	static Goal YieldStatementGoal;
	static Goal SwitchLabelCaseLhsGoal;
	static Goal RestrictedIdentifierSealedGoal;
	static Goal RestrictedIdentifierPermitsGoal;
	static Goal PatternGoal;

	static int[] RestrictedIdentifierSealedFollow =  { TokenNameclass, TokenNameinterface,
			TokenNameenum, TokenNameRestrictedIdentifierrecord };// Note: enum/record allowed as error flagging rules.
	static int[] RestrictedIdentifierPermitsFollow =  { TokenNameLBRACE };
	static int[] PatternCaseLabelFollow = {TokenNameCOLON, TokenNameARROW, TokenNameCOMMA};

	static {

		List<Integer> ridSealed = new ArrayList<>(2);
		List<Integer> ridPermits = new ArrayList<>();
		List<Integer> patternStates = new ArrayList<>();
		for (int i = 1; i <= ParserBasicInformation.NUM_RULES; i++) {  // 0 == $acc
			// TODO: Change to switch
			if ("ParenthesizedLambdaParameterList".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				LambdaParameterListRule = i;
			else
			if ("ParenthesizedCastNameAndBounds".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				IntersectionCastRule = i;
			else
			if ("ReferenceExpressionTypeArgumentsAndTrunk".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				ReferenceExpressionRule = i;
			else
			if ("TypeAnnotations".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				VarargTypeAnnotationsRule = i;
			else
			if ("BlockStatementopt".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				BlockStatementoptRule = i;
			else
			if ("YieldStatement".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				YieldStatementRule = i;
			else
			if ("Modifiersopt".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				ridSealed.add(i);
			else
			if ("PermittedSubclasses".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				ridPermits.add(i);
			else
			if ("SwitchLabelCaseLhs".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				SwitchLabelCaseLhsRule = i;
			else
			if ("TypePattern".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				patternStates.add(i);
			else
			if ("PrimaryPattern".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				patternStates.add(i);
			else
			if ("GuardedPattern".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				patternStates.add(i);
			else
			if ("Pattern".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				patternStates.add(i);
			else
			if ("ParenthesizedPattern".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
				patternStates.add(i);
		}
		RestrictedIdentifierSealedRule = ridSealed.stream().mapToInt(Integer :: intValue).toArray(); // overkill but future-proof
		RestrictedIdentifierPermitsRule = ridPermits.stream().mapToInt(Integer :: intValue).toArray();
		PatternRules = patternStates.stream().mapToInt(Integer :: intValue).toArray();

		LambdaParameterListGoal =  new Goal(TokenNameARROW, new int[] { TokenNameARROW }, LambdaParameterListRule);
		IntersectionCastGoal =     new Goal(TokenNameLPAREN, followSetOfCast(), IntersectionCastRule);
		VarargTypeAnnotationGoal = new Goal(TokenNameAT, new int[] { TokenNameELLIPSIS }, VarargTypeAnnotationsRule);
		ReferenceExpressionGoal =  new Goal(TokenNameLESS, new int[] { TokenNameCOLON_COLON }, ReferenceExpressionRule);
		BlockStatementoptGoal =    new Goal(TokenNameLBRACE, new int [0], BlockStatementoptRule);
		YieldStatementGoal =       new Goal(TokenNameARROW, new int [0], YieldStatementRule);
		SwitchLabelCaseLhsGoal =   new Goal(TokenNameARROW, new int [0], SwitchLabelCaseLhsRule);
		RestrictedIdentifierSealedGoal = new Goal(TokenNameRestrictedIdentifiersealed, RestrictedIdentifierSealedFollow, RestrictedIdentifierSealedRule);
		RestrictedIdentifierPermitsGoal = new Goal(TokenNameRestrictedIdentifierpermits, RestrictedIdentifierPermitsFollow, RestrictedIdentifierPermitsRule);
		PatternGoal = new Goal(TokenNameBeginCaseElement, PatternCaseLabelFollow, PatternRules);
	}


	Goal(int first, int [] follow, int rule) {
		this.first = first;
		this.follow = follow;
		this.rules = new int[] {rule};
	}

	Goal(int first, int [] follow, int[] rules) {
		this.first = first;
		this.follow = follow;
		this.rules = rules;
	}

	boolean hasBeenReached(int act, int token) {
		/*
		System.out.println("[Goal = " + Parser.name[Parser.non_terminal_index[Parser.lhs[this.rule]]] + "]  " + "Saw: " + Parser.name[Parser.non_terminal_index[Parser.lhs[act]]] + "::" +  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
					Parser.name[Parser.terminal_index[token]]);
		*/
		boolean foundRule = false;
		for (int i : this.rules) {
			if (act == i) {
				foundRule = true;
				break;
			}
		}
		if (foundRule) {
			final int length = this.follow.length;
			if (length == 0)
				return true;
			for (int i = 0; i < length; i++)
				if (this.follow[i] == token)
					return true;
		}
		return false;
	}

	private static int [] followSetOfCast() {
		return new int [] { TokenNameIdentifier, TokenNamenew, TokenNamesuper, TokenNamethis,
				TokenNamefalse, TokenNametrue, TokenNamenull,
				TokenNameIntegerLiteral, TokenNameLongLiteral, TokenNameFloatingPointLiteral, TokenNameDoubleLiteral, TokenNameCharacterLiteral, TokenNameStringLiteral, TokenNameTextBlock,
				TokenNameNOT, TokenNameTWIDDLE, TokenNameLPAREN
		};
	}
}
// Vanguard Parser - A Private utility helper class for the scanner.
private static class VanguardParser extends Parser {

	public static final boolean SUCCESS = true;
	public static final boolean FAILURE = false;

	Goal currentGoal;

	public VanguardParser(VanguardScanner scanner) {
		this.scanner = scanner;
	}

	public VanguardParser(ProblemReporter reporter) {
		super(reporter, false);
	}

	// Canonical LALR pushdown automaton identical to Parser.parse() minus side effects of any kind, returns the rule reduced.
	protected boolean parse(Goal goal) {
		this.currentGoal = goal;
		try {
			int act = START_STATE;
			this.stateStackTop = -1;
			this.currentToken = goal.first;
			ProcessTerminals : for (;;) {
				int stackLength = this.stack.length;
				if (++this.stateStackTop >= stackLength) {
					System.arraycopy(
						this.stack, 0,
						this.stack = new int[stackLength + StackIncrement], 0,
						stackLength);
				}
				this.stack[this.stateStackTop] = act;

				act = Parser.tAction(act, this.currentToken);
				if (act == ERROR_ACTION) {
					return FAILURE;
				}
				if (act <= NUM_RULES) {
					this.stateStackTop--;
				} else if (act > ERROR_ACTION) { /* shift-reduce */
					this.unstackedAct = act;
					try {
					this.currentToken = this.scanner.getNextToken();
					} finally {
						this.unstackedAct = ERROR_ACTION;
					}
					act -= ERROR_ACTION;
				} else {
				    if (act < ACCEPT_ACTION) { /* shift */
				    	this.unstackedAct = act;
						try {
				    	this.currentToken = this.scanner.getNextToken();
						} finally {
							this.unstackedAct = ERROR_ACTION;
						}
						continue ProcessTerminals;
					}
				    return FAILURE; // accept - we should never reach this state, we accept at reduce with a right member of follow set below.
				}

				// ProcessNonTerminals :
				do { /* reduce */
					if (goal.hasBeenReached(act, this.currentToken))
						return SUCCESS;
					this.stateStackTop -= (Parser.rhs[act] - 1);
					act = Parser.ntAction(this.stack[this.stateStackTop], Parser.lhs[act]);
				} while (act <= NUM_RULES);
			}
		} catch (Exception e) {
			return FAILURE;
		}
	}
	@Override
	public String toString() {
		return "\n\n\n----------------Scanner--------------\n" + this.scanner.toString(); //$NON-NLS-1$;
	}
}

private class ScanContextDetector extends VanguardParser {
	ScanContextDetector(CompilerOptions options) {
		super(new ProblemReporter(
					DefaultErrorHandlingPolicies.ignoreAllProblems(),
					options,
					new DefaultProblemFactory()));
		this.problemReporter.options.performStatementsRecovery = false;
		this.reportSyntaxErrorIsRequired = false;
		this.reportOnlyOneSyntaxError = false;
	}

	@Override
	public void initializeScanner(){
		this.scanner = new Scanner(
			false /*comment*/,
			false /*whitespace*/,
			false, /* will be set in initialize(boolean) */
			this.options.sourceLevel /*sourceLevel*/,
			this.options.complianceLevel /*complianceLevel*/,
			this.options.taskTags/*taskTags*/,
			this.options.taskPriorities/*taskPriorities*/,
			this.options.isTaskCaseSensitive/*taskCaseSensitive*/,
			this.options.enablePreviewFeatures /*isPreviewEnabled*/)
		{
			@Override
			void updateScanContext(int token) {
				if (token != TokenNameEOF)
					super.updateScanContext(token);
			}
		};
		this.scanner.recordLineSeparator = false;
		this.scanner.setActiveParser(this);
		this.scanner.previewEnabled = this.options.enablePreviewFeatures;
	}

	@Override
	public boolean isParsingModuleDeclaration() {
		return true;
	}

	public ScanContext getScanContext(char[] src, int begin) {
		this.scanner.setSource(src);
		this.scanner.resetTo(0, begin);
		goForCompilationUnit();
		Goal goal = new Goal(TokenNamePLUS_PLUS, null, 0) {
			@Override
			boolean hasBeenReached(int act, int token) {
				return token == TokenNameEOF;
			}
		};
		parse(goal);
		return this.scanner.scanContext;
	}
}

private VanguardParser getVanguardParser() {
	if (this.vanguardParser == null) {
		this.vanguardScanner = new VanguardScanner(this.sourceLevel, this.complianceLevel, this.previewEnabled);
		this.vanguardParser = new VanguardParser(this.vanguardScanner);
		this.vanguardScanner.setActiveParser(this.vanguardParser);
	}
	this.vanguardScanner.setSource(this.source);
	this.vanguardScanner.resetTo(this.startPosition, this.eofPosition - 1, isInModuleDeclaration(), this.scanContext);
//{ObjectTeams: init OT-state:
	this.vanguardScanner._isOTSource = this._isOTSource;
	this.vanguardScanner._dotSeen = this._dotSeen;
	this.vanguardScanner._calloutSeen = this._calloutSeen;
	this.vanguardScanner._callinSeen = this._callinSeen;
	this.vanguardScanner._insideParameterMapping = this._insideParameterMapping;
	this.vanguardScanner._forceBaseIsIdentifier = this._forceBaseIsIdentifier;
// SH}
	return this.vanguardParser;
}
private VanguardParser getNewVanguardParser() {
	VanguardScanner vs = getNewVanguardScanner();
	VanguardParser vp = new VanguardParser(vs);
	vs.setActiveParser(vp);
	return vp;
}
private VanguardScanner getNewVanguardScanner() {
	VanguardScanner vs = new VanguardScanner(this.sourceLevel, this.complianceLevel, this.previewEnabled);
	vs.setSource(this.source);
	vs.resetTo(this.startPosition, this.eofPosition - 1, isInModuleDeclaration(), this.scanContext);
	return vs;
}
protected final boolean mayBeAtCasePattern(int token) {
	return (!isInModuleDeclaration() && this.complianceLevel == ClassFileConstants.JDK17 && this.previewEnabled)
			&& (token == TokenNamecase || this.multiCaseLabelComma);
}
protected final boolean mayBeAtBreakPreview() {
	return !isInModuleDeclaration() && this.breakPreviewAllowed && this.lookBack[1] != TokenNameARROW;
}

protected final boolean maybeAtLambdaOrCast() { // Could the '(' we saw just now herald a lambda parameter list or a cast expression ? (the possible locations for both are identical.)

	if (isInModuleDeclaration())
		return false;
	switch (this.lookBack[1]) {
		case TokenNameIdentifier:
		case TokenNamecatch:
		case TokenNamethis:
		case TokenNamesuper:
		case TokenNameif:
		case TokenNameswitch:
		case TokenNamewhile:
		case TokenNamefor:
		case TokenNamesynchronized:
		case TokenNametry:
			return false; // not a viable prefix for cast or lambda.
		default:
			return this.activeParser.atConflictScenario(TokenNameLPAREN);
	}
}


protected final boolean maybeAtReferenceExpression() { // Did the '<' we saw just now herald a reference expression's type arguments and trunk ?
	if (isInModuleDeclaration())
		return false;
	switch (this.lookBack[1]) {
		case TokenNameIdentifier:
			switch (this.lookBack[0]) {
				case TokenNameSEMICOLON:  // for (int i = 0; i < 10; i++);
				case TokenNameRBRACE:     // class X { void foo() {} X<String> x = null; }
				case TokenNameclass:      // class X<T> {}
				case TokenNameinterface:  // interface I<T> {}
				case TokenNameenum:       // enum E<T> {}
				case TokenNamefinal:      // final Collection<String>
				case TokenNameLESS:       // Collection<IScalarData<AbstractData>>
				case TokenNameGREATER:    // public <T> List<T> foo() { /* */ }
				case TokenNameRIGHT_SHIFT:// static <T extends SelfType<T>> List<T> makeSingletonList(T t) { /* */ }
				case TokenNamenew:        // new ArrayList<String>();
				case TokenNamenon_sealed: // non-sealed X<T>
				case TokenNameRestrictedIdentifiersealed: // sealed X<T>
				case TokenNamepublic:     // public List<String> foo() {}
				case TokenNameabstract:   // abstract List<String> foo() {}
				case TokenNameprivate:    // private List<String> foo() {}
				case TokenNameprotected:  // protected List<String> foo() {}
				case TokenNamestatic:     // public static List<String> foo() {}
				case TokenNameextends:    // <T extends Y<Z>>
				case TokenNamesuper:      // ? super Context<N>
				case TokenNameAND:        // T extends Object & Comparable<? super T>
				case TokenNameimplements: // class A implements I<Z>
				case TokenNameRestrictedIdentifierpermits: // class A permits I<Z>
				case TokenNamethrows:     // throws Y<Z>
				case TokenNameAT:         // @Deprecated <T> void foo() {}
				case TokenNameinstanceof: // if (o instanceof List<E>[])
				case TokenNamedefault:
					return false;
				default:
					break;
			}
			break;
		case TokenNameNotAToken: // Not kosher, don't touch.
			break;
		default:
			return false;
	}
	return this.activeParser.atConflictScenario(TokenNameLESS);
}
private final boolean maybeAtEllipsisAnnotationsStart() { // Did the '@' we saw just now herald a type annotation on a ... ? Presumed to be at type annotation already.
	if (this.consumingEllipsisAnnotations)
		return false;
	switch (this.lookBack[1]) {
		case TokenNamenew:
		case TokenNameCOMMA:
		case TokenNameextends:
		case TokenNamesuper:
		case TokenNameimplements:
		case TokenNameRestrictedIdentifierpermits:
		case TokenNameDOT:
		case TokenNameLBRACE:
		case TokenNameinstanceof:
		case TokenNameLESS:
		case TokenNameAND:
		case TokenNamethrows:
			return false;
		default:
			return true;
	}
}
protected final boolean atTypeAnnotation() { // Did the '@' we saw just now herald a type annotation ? We should not ask the parser whether it would shift @308 !
	return !this.activeParser.atConflictScenario(TokenNameAT);
}
//{ObjectTeams: one more variant of '@' to check:
protected final boolean atTypeAnchor() { // Did the '@' we saw just now herald a type anchor ?
	// Note: if we proceed with ATOT while actually a normal type annotation is present,
	// the erroneous TypeAnchorReference is deconstructed again in Parser.convertTypeAnchor()!
	return this.activeParser.atConflictScenario(TokenNameATOT);
}
// SH}

public void setActiveParser(ConflictedParser parser) {
	this.activeParser  = parser;
	this.lookBack[0] = this.lookBack[1] = TokenNameNotAToken;  // no hand me downs please.
	if (parser != null) {
		this.insideModuleInfo = parser.isParsingModuleDeclaration();
	}
	this.multiCaseLabelComma = false;
}
public static boolean isRestrictedKeyword(int token) {
	switch(token) {
		case TokenNameopen:
		case TokenNamemodule:
		case TokenNamerequires:
		case TokenNametransitive:
		case TokenNameexports:
		case TokenNameto:
		case TokenNameopens:
		case TokenNameuses:
		case TokenNameprovides:
		case TokenNamewith:
			return true;
		default:
			return false;
	}
}
private boolean mayBeAtAnYieldStatement() {
	if (isInModuleDeclaration())
		return false;
	// preceded by ;, {, }, ), or -> [Ref: http://mail.openjdk.java.net/pipermail/amber-spec-experts/2019-May/001401.html]
	// above comment is super-seded by http://mail.openjdk.java.net/pipermail/amber-spec-experts/2019-May/001414.html
	switch (this.lookBack[1]) {
		case TokenNameLBRACE:
		case TokenNameRBRACE:
		case TokenNameRPAREN:
		case TokenNameSEMICOLON:
		case TokenNameelse:
		case TokenNamedo:
			return true;
		case TokenNameCOLON:
			return this.lookBack[0] == TokenNamedefault || this.yieldColons == 1;
		case TokenNameDOT:
		case TokenNameARROW:
		default:
			return false;
	}
}
private boolean mayBeAtASealedRestricedIdentifier(int restrictedIdentifier) {
	if (isInModuleDeclaration())
		return false;
	switch (restrictedIdentifier) {
		case TokenNameRestrictedIdentifiersealed:
			break;
		case TokenNameRestrictedIdentifierpermits:
			break;
	}
	return true;
}
int disambiguatedRestrictedIdentifierrecord(int restrictedIdentifierToken) {
	// and here's the kludge
	if (restrictedIdentifierToken != TokenNameRestrictedIdentifierrecord)
		return restrictedIdentifierToken;
	if (!JavaFeature.RECORDS.isSupported(this.complianceLevel, this.previewEnabled))
		return TokenNameIdentifier;

	return disambiguaterecordWithLookAhead() ?
			restrictedIdentifierToken : TokenNameIdentifier;
}
private int getNextTokenAfterTypeParameterHeader() {
	int count = 1;
	try {
		int token;
		while ((token = this.vanguardScanner.getNextToken()) != TokenNameNotAToken) {
			if (token == TokenNameEOF)
				break;
			if (token == TokenNameLESS)
				++count;
			if (token == TokenNameGREATER)
				--count;
			if (token == TokenNameRIGHT_SHIFT)
				count= count -2;
			if (token == TokenNameUNSIGNED_RIGHT_SHIFT)
				count= count -3;
			if (count <= 0)
				return this.vanguardScanner.getNextToken();
		}
	} catch (InvalidInputException e) {
		if (e.getMessage().equals(INVALID_CHAR_IN_STRING)) {
			//Ignore
		} else {
			// Shouldn't happen, but log the error
			e.printStackTrace();
		}
	}
	return TokenNameEOF;
}
private boolean disambiguaterecordWithLookAhead() {
	if (isInModuleDeclaration())
		return false;
	getVanguardParser();
	this.vanguardScanner.resetTo(this.currentPosition, this.eofPosition - 1);
	try {
		int lookAhead1 = this.vanguardScanner.getNextToken();
		if (lookAhead1 == TokenNameIdentifier) {
			int lookAhead2 = this.vanguardScanner.getNextToken();
			lookAhead2 = lookAhead2 == TokenNameLESS ? getNextTokenAfterTypeParameterHeader() : lookAhead2;
			if (lookAhead2 == TokenNameLBRACE) {
				// record X {} is considered a record (albeit illegal),
				// This is so that we can issue an appropriate syntax error
				return true;
			}
			return lookAhead2 == TokenNameLPAREN;
		}
	} catch (InvalidInputException e) {
		if (e.getMessage().equals(INVALID_CHAR_IN_STRING)) {
			//Ignore
		} else {
			// Shouldn't happen, but log the error
			e.printStackTrace();
		}
	}
	return false; // IIE event;
}
private boolean disambiguateYieldWithLookAhead() {
	getVanguardParser();
	this.vanguardScanner.resetTo(this.currentPosition, this.eofPosition - 1);
	try {
		int lookAhead1 = this.vanguardScanner.getNextToken();
		switch (lookAhead1) {
			case TokenNameEQUAL_EQUAL :
			case TokenNameLESS_EQUAL :
			case TokenNameGREATER_EQUAL :
			case TokenNameNOT_EQUAL :
			case TokenNameLEFT_SHIFT :
			case TokenNameRIGHT_SHIFT :
			case TokenNameUNSIGNED_RIGHT_SHIFT :
			case TokenNamePLUS_EQUAL :
			case TokenNameMINUS_EQUAL :
			case TokenNameMULTIPLY_EQUAL :
			case TokenNameDIVIDE_EQUAL :
			case TokenNameAND_EQUAL :
			case TokenNameOR_EQUAL :
			case TokenNameXOR_EQUAL :
			case TokenNameREMAINDER_EQUAL :
			case TokenNameLEFT_SHIFT_EQUAL :
			case TokenNameRIGHT_SHIFT_EQUAL :
			case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL :
			case TokenNameOR_OR :
			case TokenNameAND_AND :
			case TokenNameREMAINDER :
			case TokenNameXOR :
			case TokenNameAND :
			case TokenNameMULTIPLY :
			case TokenNameOR :
			case TokenNameTWIDDLE :
			case TokenNameDIVIDE :
			case TokenNameGREATER :
			case TokenNameLESS :
			case TokenNameLBRACE :
			case TokenNameRBRACE :
			case TokenNameLBRACKET :
			case TokenNameRBRACKET :
			case TokenNameSEMICOLON :
			case TokenNameQUESTION :
			case TokenNameCOLON :
			case TokenNameCOMMA :
			case TokenNameDOT :
			case TokenNameEQUAL :
			case TokenNameAT :
			case TokenNameELLIPSIS :
			case TokenNameARROW :
			case TokenNameCOLON_COLON :
				return false;
			case TokenNameMINUS_MINUS :
			case TokenNamePLUS_PLUS :
				int lookAhead2 = this.vanguardScanner.getNextToken();
				return lookAhead2 == TokenNameIdentifier;
			default : return true;
		}
	} catch (InvalidInputException e) {
		if (e.getMessage().equals(INVALID_CHAR_IN_STRING)) {
			//Ignore
		} else {
			// Shouldn't happen, but log the error
			e.printStackTrace();
		}
	}
	return false; // IIE event;
}
int disambiguatedRestrictedIdentifierpermits(int restrictedIdentifierToken) {
	// and here's the kludge
	if (restrictedIdentifierToken != TokenNameRestrictedIdentifierpermits)
		return restrictedIdentifierToken;
	if (!JavaFeature.RECORDS.isSupported(this.complianceLevel, this.previewEnabled))
		return TokenNameIdentifier;

	return disambiguatesRestrictedIdentifierWithLookAhead(this::mayBeAtASealedRestricedIdentifier,
			restrictedIdentifierToken, Goal.RestrictedIdentifierPermitsGoal);
}
int disambiguatedRestrictedIdentifiersealed(int restrictedIdentifierToken) {
	// and here's the kludge
	if (restrictedIdentifierToken != TokenNameRestrictedIdentifiersealed)
		return restrictedIdentifierToken;
	if (!JavaFeature.RECORDS.isSupported(this.complianceLevel, this.previewEnabled))
		return TokenNameIdentifier;

	return disambiguatesRestrictedIdentifierWithLookAhead(this::mayBeAtASealedRestricedIdentifier,
			restrictedIdentifierToken, Goal.RestrictedIdentifierSealedGoal);
}
int disambiguatedRestrictedIdentifierYield(int restrictedIdentifierToken) {
	// and here's the kludge
	if (restrictedIdentifierToken != TokenNameRestrictedIdentifierYield)
		return restrictedIdentifierToken;
	if (this.sourceLevel < ClassFileConstants.JDK14)
		return TokenNameIdentifier;

	return mayBeAtAnYieldStatement() && disambiguateYieldWithLookAhead() ?
			restrictedIdentifierToken : TokenNameIdentifier;
}
int disambiguatedRestrictedKeyword(int restrictedKeywordToken) {
	int token = restrictedKeywordToken;
	if (this.scanContext == ScanContext.EXPECTING_IDENTIFIER)
		return TokenNameIdentifier;

	switch(restrictedKeywordToken) {
		case TokenNametransitive:
			if (this.scanContext != ScanContext.AFTER_REQUIRES) {
				token = TokenNameIdentifier;
			} else {
				getVanguardParser();
				this.vanguardScanner.resetTo(this.currentPosition, this.eofPosition - 1, true, ScanContext.EXPECTING_IDENTIFIER);
				try {
					int lookAhead = this.vanguardScanner.getNextToken();
					if (lookAhead == TokenNameSEMICOLON)
						token = TokenNameIdentifier;
				} catch (InvalidInputException e) {
					//
				}
			}
			break;
		case TokenNameopen:
		case TokenNamemodule:
		case TokenNameexports:
		case TokenNameopens:
		case TokenNamerequires:
		case TokenNameprovides:
		case TokenNameuses:
		case TokenNameto:
		case TokenNamewith:
			if (this.scanContext != ScanContext.EXPECTING_KEYWORD) {
				token = TokenNameIdentifier;
			}
			break;
	}
	return token;
}
int disambiguatesRestrictedIdentifierWithLookAhead(Predicate<Integer> checkPrecondition, int restrictedIdentifierToken, Goal goal) {
	if (checkPrecondition.test(restrictedIdentifierToken)) {
		VanguardParser vp = getNewVanguardParser();
		VanguardScanner vs = (VanguardScanner) vp.scanner;
		vs.resetTo(this.currentPosition, this.eofPosition - 1);
		if (vp.parse(goal) == VanguardParser.SUCCESS)
			return restrictedIdentifierToken;
	}
	return TokenNameIdentifier;
}

private VanguardScanner getNewVanguardScanner(char[] src) {
	VanguardScanner vs = new VanguardScanner(this.sourceLevel, this.complianceLevel, this.previewEnabled);
	vs.setSource(src);
	vs.resetTo(0, src.length, isInModuleDeclaration(), this.scanContext);
	return vs;
}
private VanguardParser getNewVanguardParser(char[] src) {
	VanguardScanner vs = getNewVanguardScanner(src);
	VanguardParser vp = new VanguardParser(vs);
	vs.setActiveParser(vp);
	return vp;
}
int disambiguatedToken(int token, Scanner scanner) {
	final VanguardParser parser = getVanguardParser();
	if (token == TokenNameARROW  &&  mayBeAtCaseLabelExpr() &&
//{ObjectTeams: don't be confused by unset caseStartPosition (JDT bug?)
			this.caseStartPosition != -1 &&
// SH}
			this.caseStartPosition < this.startPosition) {
		// this.caseStartPosition > this.startPositionpossible on recovery - bother only about correct ones.
		// add fake token of TokenNameCOLON, call vanguard on this modified source
		// TODO: Inefficient method due to redoing of the same source, investigate alternate
		// Can we do a dup of parsing/check the transition of the state?
		char[] nSource = CharOperation.append(Arrays.copyOfRange(scanner.source, scanner.caseStartPosition, scanner.startPosition), ':');
		VanguardParser vp = getNewVanguardParser(nSource);
		if (vp.parse(Goal.SwitchLabelCaseLhsGoal) == VanguardParser.SUCCESS) {
			scanner.nextToken = TokenNameARROW;
			return TokenNameBeginCaseExpr;
		}
	} else	if (token == TokenNameLPAREN  && maybeAtLambdaOrCast()) {
		if (parser.parse(Goal.LambdaParameterListGoal) == VanguardParser.SUCCESS) {
			scanner.nextToken = TokenNameLPAREN;
			return TokenNameBeginLambda;
		}
		scanner.vanguardScanner.resetTo(scanner.startPosition, scanner.eofPosition - 1);
		if (parser.parse(Goal.IntersectionCastGoal) == VanguardParser.SUCCESS) {
			scanner.nextToken = TokenNameLPAREN;
			return TokenNameBeginIntersectionCast;
		}
	} else if (token == TokenNameLESS && maybeAtReferenceExpression()) {
		if (parser.parse(Goal.ReferenceExpressionGoal) == VanguardParser.SUCCESS) {
			scanner.nextToken = TokenNameLESS;
			return TokenNameBeginTypeArguments;
		}
	} else if (token == TokenNameAT && atTypeAnnotation()) {
//{ObjectTeams: '@' can mean 3 things now:
	  if (atTypeAnchor()) {
		token = TokenNameATOT;
	  } else {
// orig:
		token = TokenNameAT308;
		if (maybeAtEllipsisAnnotationsStart()) {
			if (parser.parse(Goal.VarargTypeAnnotationGoal) == VanguardParser.SUCCESS) {
				scanner.consumingEllipsisAnnotations = true;
				scanner.nextToken = TokenNameAT308;
				return TokenNameAT308DOTDOTDOT;
			}
		}
// :giro
	  }
// SH
	}
	return token;
}
/*
 * Assumption: mayBeAtCasePattern(token) is true before calling this method.
 */
int disambiguateCasePattern(int token, Scanner scanner) {
	assert mayBeAtCasePattern(token);
	int delta = token == TokenNamecase ? 4 : 0; // 4 for case.
	final VanguardParser parser = getNewVanguardParser();
	parser.scanner.resetTo(parser.scanner.currentPosition + delta, parser.scanner.eofPosition);
	if (parser.parse(Goal.PatternGoal) == VanguardParser.SUCCESS) {
		if (token == TokenNamecase) {
			scanner.nextToken = TokenNameBeginCaseElement;
		} else {
			scanner.nextToken = token;
			token = TokenNameBeginCaseElement;
		}
	}
	return token;
}

private boolean mayBeAtCaseLabelExpr() {
	if (isInModuleDeclaration() || this.caseStartPosition <= 0)
		return false;
	if (this.lookBack[1] == TokenNamedefault) {
		return this.complianceLevel == ClassFileConstants.JDK17 && this.previewEnabled ?
				(this.lookBack[0] == TerminalTokens.TokenNamecase || this.lookBack[0] == TerminalTokens.TokenNameCOMMA)
				: false;
	}
	return true;
}

protected boolean isAtAssistIdentifier() {
	return false;
}

// Position the scanner at the next block statement and return the start token. We recognize empty statements.
public int fastForward(Statement unused) {

	int token;

	while (true) {
		try {
			token = getNextToken();
		} catch (InvalidInputException e) {
			return TokenNameEOF;
		}
		/* FOLLOW map of BlockStatement, since the non-terminal is recursive is a super set of its own FIRST set.
	   	   We use FOLLOW rather than FIRST since we want to recognize empty statements. i.e if (x > 10) {  x = 0 }
		*/
		switch(token) {
			case TokenNameIdentifier:
				if (isAtAssistIdentifier()) // do not fast forward past the assist identifier ! We don't handle collections as of now.
					return token;
				//$FALL-THROUGH$
			case TokenNameabstract:
			case TokenNameassert:
			case TokenNameboolean:
			case TokenNamebreak:
			case TokenNamebyte:
			case TokenNamecase:
			case TokenNamechar:
			case TokenNameclass:
			case TokenNamecontinue:
			case TokenNamedefault:
			case TokenNamedo:
			case TokenNamedouble:
			case TokenNameenum:
			case TokenNamefalse:
			case TokenNamefinal:
			case TokenNamefloat:
			case TokenNamefor:
			case TokenNameif:
			case TokenNameint:
			case TokenNameinterface:
			case TokenNamelong:
			case TokenNamenative:
			case TokenNamenew:
			case TokenNamenon_sealed:
			case TokenNamenull:
			case TokenNameprivate:
			case TokenNameprotected:
			case TokenNamepublic:
			case TokenNameRestrictedIdentifiersealed:
			case TokenNamereturn:
			case TokenNameshort:
			case TokenNamestatic:
			case TokenNamestrictfp:
			case TokenNamesuper:
			case TokenNameswitch:
			case TokenNamesynchronized:
			case TokenNamethis:
			case TokenNamethrow:
			case TokenNametransient:
			case TokenNametrue:
			case TokenNametry:
			case TokenNamevoid:
			case TokenNamevolatile:
			case TokenNamewhile:
			case TokenNameIntegerLiteral: // ??!
			case TokenNameLongLiteral:
			case TokenNameFloatingPointLiteral:
			case TokenNameDoubleLiteral:
			case TokenNameCharacterLiteral:
			case TokenNameStringLiteral:
			case TokenNameTextBlock:
			case TokenNamePLUS_PLUS:
			case TokenNameMINUS_MINUS:
			case TokenNameLESS:
			case TokenNameLPAREN:
			case TokenNameLBRACE:
			case TokenNameAT:
			case TokenNameBeginLambda:
			case TokenNameBeginCaseExpr:
			case TokenNameAT308:
			case TokenNameRestrictedIdentifierYield: // can be in FOLLOW of Block
				if(getVanguardParser().parse(Goal.BlockStatementoptGoal) == VanguardParser.SUCCESS)
					return token;
				break;
			case TokenNameSEMICOLON:
			case TokenNameEOF:
				return token;
			case TokenNameRBRACE: // simulate empty statement.
				ungetToken(token);
				return TokenNameSEMICOLON;
			default:
				break;
		}
	}
}

/** Overridable hook, to allow CompletionScanner to hide a faked identifier token. */
protected int getNextNotFakedToken() throws InvalidInputException {
	return getNextToken();
}
}
