/*******************************************************************************
 * Copyright (c) 2000, 2019 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
 *******************************************************************************/
package org.eclipse.jdt.internal.codeassist.impl;

/*
 * Parser extension for code assist task
 *
 */

import java.util.HashSet;

import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock;
import org.eclipse.jdt.internal.compiler.parser.RecoveredElement;
import org.eclipse.jdt.internal.compiler.parser.RecoveredExportsStatement;
import org.eclipse.jdt.internal.compiler.parser.RecoveredField;
import org.eclipse.jdt.internal.compiler.parser.RecoveredInitializer;
import org.eclipse.jdt.internal.compiler.parser.RecoveredLocalVariable;
import org.eclipse.jdt.internal.compiler.parser.RecoveredMethod;
import org.eclipse.jdt.internal.compiler.parser.RecoveredStatement;
import org.eclipse.jdt.internal.compiler.parser.RecoveredType;
import org.eclipse.jdt.internal.compiler.parser.RecoveredUnit;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.objectteams.otdt.core.compiler.OTNameUtils;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ParameterMapping;

public abstract class AssistParser extends Parser {
	public ASTNode assistNode;
	public boolean isOrphanCompletionNode;
	private boolean resumedAfterRepair = false;
	// last modifiers info
	protected int lastModifiers = ClassFileConstants.AccDefault;
	protected int lastModifiersStart = -1;
	/* recovery */
	int[] blockStarts = new int[30];

	// the previous token read by the scanner
	protected int previousToken;

	// the index in the identifier stack of the previous identifier
	protected int previousIdentifierPtr;
	
	// depth of '(', '{' and '[]'
	protected int bracketDepth;

	// element stack
	protected static final int ElementStackIncrement = 100;
	protected int elementPtr;
	protected int[] elementKindStack = new int[ElementStackIncrement];
	protected int[] elementInfoStack = new int[ElementStackIncrement];
	protected Object[] elementObjectInfoStack = new Object[ElementStackIncrement];
	protected int previousKind;
	protected int previousInfo;
	protected Object previousObjectInfo;

	// OWNER
	protected static final int ASSIST_PARSER = 512;

	// KIND : all values known by AssistParser are between 513 and 1023
	protected static final int K_SELECTOR = ASSIST_PARSER + 1; // whether we are inside a message send
	protected static final int K_TYPE_DELIMITER = ASSIST_PARSER + 2; // whether we are inside a type declaration
	protected static final int K_METHOD_DELIMITER = ASSIST_PARSER + 3; // whether we are inside a method declaration
	protected static final int K_FIELD_INITIALIZER_DELIMITER = ASSIST_PARSER + 4; // whether we are inside a field initializer
	protected static final int K_ATTRIBUTE_VALUE_DELIMITER = ASSIST_PARSER + 5; // whether we are inside a annotation attribute valuer
	protected static final int K_ENUM_CONSTANT_DELIMITER = ASSIST_PARSER + 6; // whether we are inside a field initializer
	protected static final int K_LAMBDA_EXPRESSION_DELIMITER = ASSIST_PARSER + 7; // whether we are inside a lambda expression
	protected static final int K_MODULE_INFO_DELIMITER = ASSIST_PARSER + 8; // whether we are inside a module info declaration
	protected static final int K_SWITCH_EXPRESSION_DELIMITTER = ASSIST_PARSER + 9; // whether we are inside a switch expression

	// selector constants
	protected static final int THIS_CONSTRUCTOR = -1;
	protected static final int SUPER_CONSTRUCTOR = -2;

	// enum constant constants
	protected static final int NO_BODY = 0;
	protected static final int WITH_BODY = 1;

	protected static final int EXPRESSION_BODY = 0;
	protected static final int BLOCK_BODY = 1;

	protected boolean isFirst = false;

	/**
	 * Each nested block may capture a snapshot at its start, which may be updated during commit().
	 * {@link #snapShotPositions} is a matching stack of bodyStart positions.
	 * Both stacks are indexed by their shared stack pointer {@link #snapShotPtr}.
	 */
	AssistParser[] snapShotStack = new AssistParser[3];
	int[] snapShotPositions = new int[3];
	int snapShotPtr = -1;

	protected static final int[] RECOVERY_TOKENS = { TokenNameSEMICOLON, TokenNameRPAREN, TokenNameRBRACE, TokenNameRBRACKET};


public AssistParser(ProblemReporter problemReporter) {
	super(problemReporter, true);
	this.javadocParser.checkDocComment = false;

	setMethodsFullRecovery(false);
	setStatementsRecovery(false);
}

public abstract char[] assistIdentifier();

@Override
public void copyState(Parser from) {
	
	super.copyState(from);

	AssistParser parser = (AssistParser) from;
	
	this.previousToken = parser.previousToken;
	this.previousIdentifierPtr = parser.previousIdentifierPtr;
	
	this.lastModifiers = parser.lastModifiers;
	this.lastModifiersStart = parser.lastModifiersStart;
	
	this.bracketDepth = parser.bracketDepth;
	this.elementPtr = parser.elementPtr;
	
	int length;
	System.arraycopy(parser.blockStarts, 0, this.blockStarts = new int [length = parser.blockStarts.length], 0, length);
	System.arraycopy(parser.elementKindStack, 0, this.elementKindStack = new int [length = parser.elementKindStack.length], 0, length);
	System.arraycopy(parser.elementInfoStack, 0, this.elementInfoStack = new int [length = parser.elementInfoStack.length], 0, length);
	System.arraycopy(parser.elementObjectInfoStack, 0, this.elementObjectInfoStack = new Object [length = parser.elementObjectInfoStack.length], 0, length);
	
	this.previousKind = parser.previousKind;
	this.previousInfo = parser.previousInfo;
	this.previousObjectInfo = parser.previousObjectInfo;
}
/**
 * The parser become a simple parser which behave like a Parser
 * @return the state of the assist parser to be able to restore the assist parser state
 */
public Object becomeSimpleParser() {
	return null;
}
/**
 * Restore the parser as an assist parser
 * @param parserState
 */
public void restoreAssistParser(Object parserState) {
	//Do nothing
}
public int bodyEnd(AbstractMethodDeclaration method){
	return method.bodyEnd;
}
//{ObjectTeams: monkey see...
public int bodyEnd(AbstractMethodMappingDeclaration mapping){
	return mapping.declarationSourceEnd;
}
// SH}
public int bodyEnd(Initializer initializer){
	return initializer.declarationSourceEnd;
}
/*
 * Build initial recovery state.
 * Recovery state is inferred from the current state of the parser (reduced node stack).
 */
@Override
public RecoveredElement buildInitialRecoveryState(){
	/* recovery in unit structure */
	if (this.referenceContext instanceof CompilationUnitDeclaration){
		RecoveredElement element = super.buildInitialRecoveryState();
		flushAssistState();
		flushElementStack();
		this.snapShotPtr = -1;
		initModuleInfo(element);
		return element;
	}

	/* recovery in method body */
	this.lastCheckPoint = 0;

	RecoveredElement element = null;
	if (this.referenceContext instanceof AbstractMethodDeclaration){
		element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this);
		this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart;
	} else {
		/* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
		if (this.referenceContext instanceof TypeDeclaration){
			TypeDeclaration type = (TypeDeclaration) this.referenceContext;
			FieldDeclaration[] fields = type.fields;
			int length = fields == null ? 0 : fields.length;
			for (int i = 0; i < length; i++){
				FieldDeclaration field = fields[i];
				if (field != null
						&& field.getKind() == AbstractVariableDeclaration.INITIALIZER
						&& field.declarationSourceStart <= this.scanner.initialPosition
						&& this.scanner.initialPosition <= field.declarationSourceEnd
						&& this.scanner.eofPosition <= field.declarationSourceEnd+1){
					element = new RecoveredInitializer(field, null, 1, this);
					this.lastCheckPoint = field.declarationSourceStart;
					break;
				}
			}
		}
	}

	if (element == null) return element;

	/* add initial block */
	Block block = new Block(0);
	int lastStart = this.blockStarts[0];
	block.sourceStart = lastStart;
	element = element.add(block, 1);
	int blockIndex = 1;	// ignore first block start, since manually rebuilt here

	ASTNode node = null, lastNode = null;
	for (int i = 0; i <= this.astPtr; i++, lastNode = node) {
		node = this.astStack[i];
		/* check for intermediate block creation, so recovery can properly close them afterwards */
		int nodeStart = node.sourceStart;
		for (int j = blockIndex; j <= this.realBlockPtr; j++){
			if (this.blockStarts[j] >= 0) {
				if (this.blockStarts[j] > nodeStart){
					blockIndex = j; // shift the index to the new block
					break;
				}
				if (this.blockStarts[j] != lastStart){ // avoid multiple block if at same position
					block = new Block(0);
					block.sourceStart = lastStart = this.blockStarts[j];
					element = element.add(block, 1);
				}
			} else {
				if (-this.blockStarts[j] > nodeStart){
					blockIndex = j; // shift the index to the new block
					break;
				}
				block = new Block(0);
				block.sourceStart = lastStart = -this.blockStarts[j];
				element = element.add(block, 1);
			}
			blockIndex = j+1; // shift the index to the new block
		}
		
		if (node instanceof LocalDeclaration){
			LocalDeclaration local = (LocalDeclaration) node;
			if (local.declarationSourceEnd == 0){
				element = element.add(local, 0);
				if (local.initialization == null){
					this.lastCheckPoint = local.sourceEnd + 1;
				} else {
					this.lastCheckPoint = local.initialization.sourceEnd + 1;
				}
			} else {
				if (!local.isArgument()) {
					element = element.add(local, 0);
				} else {
					// Bug 442868 - For arguments, let the method continue to be the current element.
					element.add(local, 0);
				}
				this.lastCheckPoint = local.declarationSourceEnd + 1;
			}
			continue;
		}
		if (node instanceof AbstractMethodDeclaration){
			AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
			if (method.declarationSourceEnd == 0){
				element = element.add(method, 0);
				this.lastCheckPoint = method.bodyStart;
			} else {
				element = element.add(method, 0);
				this.lastCheckPoint = method.declarationSourceEnd + 1;
			}
			continue;
		}
		if (node instanceof Initializer){
			Initializer initializer = (Initializer) node;
			if (initializer.declarationSourceEnd == 0){
				element = element.add(initializer, 1);
				this.lastCheckPoint = initializer.sourceStart;
			} else {
				element = element.add(initializer, 0);
				this.lastCheckPoint = initializer.declarationSourceEnd + 1;
			}
			continue;
		}
		if (node instanceof FieldDeclaration){
			FieldDeclaration field = (FieldDeclaration) node;
			if (field.declarationSourceEnd == 0){
				element = element.add(field, 0);
				if (field.initialization == null){
					this.lastCheckPoint = field.sourceEnd + 1;
				} else {
					this.lastCheckPoint = field.initialization.sourceEnd + 1;
				}
			} else {
				element = element.add(field, 0);
				this.lastCheckPoint = field.declarationSourceEnd + 1;
			}
			continue;
		}
		if (node instanceof TypeDeclaration){
			TypeDeclaration type = (TypeDeclaration) node;
			if (type.declarationSourceEnd == 0){
				element = element.add(type, 0);
				this.lastCheckPoint = type.bodyStart;
			} else {
				element = element.add(type, 0);
				this.lastCheckPoint = type.declarationSourceEnd + 1;
			}
			continue;
		}
		if (this.assistNode != null && node instanceof Statement) {
			Statement stmt = (Statement) node;
			if (!(stmt instanceof Expression && ((Expression) stmt).isTrulyExpression()) || ((Expression) stmt).statementExpression()) {
				if (this.assistNode.sourceStart >= stmt.sourceStart && this.assistNode.sourceEnd <= stmt.sourceEnd) {
					element.add(stmt, 0);
					this.lastCheckPoint = stmt.sourceEnd + 1;
					this.isOrphanCompletionNode = false;
				} else if ((stmt instanceof ForeachStatement) && ((ForeachStatement) stmt).action == null) {
					element = element.add(stmt, 0);
					this.lastCheckPoint = stmt.sourceEnd + 1;
				}
			}
			continue;
		}
		if (node instanceof ImportReference){
			ImportReference importRef = (ImportReference) node;
			element = element.add(importRef, 0);
			this.lastCheckPoint = importRef.declarationSourceEnd + 1;
		}
	}
	if (this.currentToken == TokenNameRBRACE) {
		 if (isIndirectlyInsideLambdaExpression())
			 this.ignoreNextClosingBrace = true;
		 else 
			 this.currentToken = 0; // closing brace has already been taken care of
	}

	/* might need some extra block (after the last reduced node) */
	/* For block bodied lambdas we should create a block even though the lambda header appears before it, so elements from within don't get misattributed. */
	int pos = this.assistNode == null ? this.lastCheckPoint : this.assistNode.sourceStart;
	boolean createLambdaBlock = lastNode instanceof LambdaExpression && ((LambdaExpression) node).body() instanceof Block;
	for (int j = blockIndex; j <= this.realBlockPtr; j++){
		if (this.blockStarts[j] >= 0) {
			if ((this.blockStarts[j] < pos || createLambdaBlock) && (this.blockStarts[j] != lastStart)){ // avoid multiple block if at same position
				block = new Block(0);
				block.sourceStart = lastStart = this.blockStarts[j];
				element = element.add(block, 1);
				createLambdaBlock = false;
			}
		} else {
			if ((this.blockStarts[j] < pos)){ // avoid multiple block if at same position
				block = new Block(0);
				block.sourceStart = lastStart = -this.blockStarts[j];
				element = element.add(block, 1);
			}
		}
	}

	return element;
}

private void initModuleInfo(RecoveredElement element) {
	if (element  instanceof RecoveredUnit) {
		RecoveredUnit unit = (RecoveredUnit) element;
		if (unit.unitDeclaration.isModuleInfo()) {
			ASTNode node = null;
			int i = 0;
			for (; i <= this.astPtr; i++) {
				if ((node = this.astStack[i]) instanceof ModuleDeclaration) {
					unit.add((ModuleDeclaration) node, this.bracketDepth); 
					break;
				}
			}
		}
	}
}
@Override
protected void consumeAnnotationTypeDeclarationHeader() {
	super.consumeAnnotationTypeDeclarationHeader();
	pushOnElementStack(K_TYPE_DELIMITER);
}
@Override
protected void consumeClassBodyDeclaration() {
	popElement(K_METHOD_DELIMITER);
	super.consumeClassBodyDeclaration();
}
@Override
protected void consumeClassBodyopt() {
	super.consumeClassBodyopt();
	popElement(K_SELECTOR);
}
@Override
protected void consumeClassHeader() {
	super.consumeClassHeader();
	pushOnElementStack(K_TYPE_DELIMITER);
}
@Override
protected void consumeConstructorBody() {
	super.consumeConstructorBody();
	popElement(K_METHOD_DELIMITER);
}
@Override
protected void consumeConstructorHeader() {
	super.consumeConstructorHeader();
	pushOnElementStack(K_METHOD_DELIMITER);
}
@Override
protected void consumeEnhancedForStatementHeaderInit(boolean hasModifiers) {
	super.consumeEnhancedForStatementHeaderInit(hasModifiers);

	if (this.currentElement != null) {
		LocalDeclaration localDecl = ((ForeachStatement)this.astStack[this.astPtr]).elementVariable;
		this.lastCheckPoint = localDecl.sourceEnd + 1;
		this.currentElement = this.currentElement.add(localDecl, 0);
	}
}
@Override
protected void consumeEnterAnonymousClassBody(boolean qualified) {
	super.consumeEnterAnonymousClassBody(qualified);
	popElement(K_SELECTOR);
	pushOnElementStack(K_TYPE_DELIMITER);
}
@Override
protected void consumeEnterMemberValue() {
	super.consumeEnterMemberValue();
	pushOnElementStack(K_ATTRIBUTE_VALUE_DELIMITER, this.identifierPtr);
}
@Override
protected void consumeEnumConstantHeader() {
	if(this.currentToken == TokenNameLBRACE) {
		popElement(K_ENUM_CONSTANT_DELIMITER);
		pushOnElementStack(K_ENUM_CONSTANT_DELIMITER, WITH_BODY);
		pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
		pushOnElementStack(K_TYPE_DELIMITER);
	}
	super.consumeEnumConstantHeader();
	if (triggerRecoveryUponLambdaClosure((Statement) this.astStack[this.astPtr], true) && this.currentElement != null)
		this.restartRecovery = true;
}
@Override
protected void consumeEnumConstantHeaderName() {
	super.consumeEnumConstantHeaderName();
	pushOnElementStack(K_ENUM_CONSTANT_DELIMITER);
}
@Override
protected void consumeEnumConstantWithClassBody() {
	popElement(K_TYPE_DELIMITER);
	popElement(K_FIELD_INITIALIZER_DELIMITER);
	popElement(K_ENUM_CONSTANT_DELIMITER);
	super.consumeEnumConstantWithClassBody();
}
@Override
protected void consumeEnumConstantNoClassBody() {
	popElement(K_ENUM_CONSTANT_DELIMITER);
	super.consumeEnumConstantNoClassBody();
}
@Override
protected void consumeEnumHeader() {
	super.consumeEnumHeader();
	pushOnElementStack(K_TYPE_DELIMITER);
}
@Override
protected void consumeExitMemberValue() {
	super.consumeExitMemberValue();
	popElement(K_ATTRIBUTE_VALUE_DELIMITER);
}

@Override
protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
	super.consumeExplicitConstructorInvocation(flag, recFlag);
	popElement(K_SELECTOR);
}

protected boolean triggerRecoveryUponLambdaClosure(Statement statement, boolean shouldCommit) {
	// Last block statement reduced is required to be on the AST stack top.
	boolean lambdaClosed = false;
	int statementStart, statementEnd;
	statementStart = statement.sourceStart;
	statementEnd = statement instanceof AbstractVariableDeclaration ? ((AbstractVariableDeclaration)statement).declarationSourceEnd : statement.sourceEnd;
	for (int i = this.elementPtr; i >= 0; --i) {
		if (this.elementKindStack[i] != K_LAMBDA_EXPRESSION_DELIMITER)
			continue;
		LambdaExpression expression = (LambdaExpression) this.elementObjectInfoStack[i];
		if (expression == null)
			return false;
		if (expression.sourceStart >= statementStart && expression.sourceEnd <= statementEnd) {
			this.elementPtr = i - 1;
			lambdaClosed = true;
		} else {
			if (shouldCommit) {
				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] = this.unstackedAct;
				commit(false);
				this.stateStackTop --;
			}
			return false;
		}
	}

	if (lambdaClosed && this.currentElement != null && !(this.currentElement instanceof RecoveredField)) {
		if (!(statement instanceof AbstractVariableDeclaration)) { // added already as part of standard recovery since these contribute a name to the scope prevailing at the cursor.
			/* See if CompletionParser.attachOrphanCompletionNode has already added bits and pieces of AST to the recovery tree. If so, we want to
			   replace those fragments with the fuller statement that provides target type for the lambda that got closed just now. There is prior
			   art/precedent in the Java 7 world to this: Search for recoveredBlock.statements[--recoveredBlock.statementCount] = null;
			   See also that this concern does not arise in the case of field/local initialization since the initializer is replaced with full tree by consumeExitVariableWithInitialization.
			*/
			/*
			 * All the above comments will not work if the assist node is buried deeper. This happens when there the 
			 * lambda was part of a complex statement, such as it was one of the arguments to a method invocation. In which case,
			 * we start from the topmost recovery element and look for assist nodes. If the operation is successful, the method
			 * replaceAssistStatement() returns null. Else, it returns the original statement, thus falling back to replacing the
			 * last statement in the current recovered element.
			 */
			statement = replaceAssistStatement(this.currentElement.topElement(),
					this.assistNodeParent(), statementStart, statementEnd, statement);
			
			if (statement != null) {
				RecoveredBlock recoveredBlock = (RecoveredBlock) (this.currentElement instanceof RecoveredBlock ? this.currentElement : 
					(this.currentElement.parent instanceof RecoveredBlock) ? this.currentElement.parent : 
						this.currentElement instanceof RecoveredMethod ? ((RecoveredMethod) this.currentElement).methodBody : null);
				if (recoveredBlock != null) {
					RecoveredStatement recoveredStatement = recoveredBlock.statementCount > 0 ? recoveredBlock.statements[recoveredBlock.statementCount - 1] : null;
					ASTNode parseTree = recoveredStatement != null ? recoveredStatement.updatedStatement(0, new HashSet<TypeDeclaration>()) : null;
					if (parseTree != null) {
						if ((parseTree.sourceStart == 0 || parseTree.sourceEnd == 0) || (parseTree.sourceStart >= statementStart && parseTree.sourceEnd <= statementEnd)) {
							recoveredBlock.statements[recoveredBlock.statementCount - 1] = new RecoveredStatement(statement, recoveredBlock, 0);
							statement = null;
						} else if (recoveredStatement instanceof RecoveredLocalVariable && statement instanceof Expression &&
								((Expression) statement).isTrulyExpression()) {
							RecoveredLocalVariable local = (RecoveredLocalVariable) recoveredStatement;
							if (local.localDeclaration != null && local.localDeclaration.initialization != null) {
								if ((local.localDeclaration.initialization.sourceStart == 0 || local.localDeclaration.initialization.sourceEnd == 0) || 
								        (local.localDeclaration.initialization.sourceStart >= statementStart && local.localDeclaration.initialization.sourceEnd <= statementEnd) ){
									local.localDeclaration.initialization = (Expression) statement;
									local.localDeclaration.declarationSourceEnd = statement.sourceEnd;
									local.localDeclaration.declarationEnd = statement.sourceEnd;
									statement = null;
								}
							}
						}
					}
				}
			}
			if (statement != null) {
				while (this.currentElement != null) {
					ASTNode tree = this.currentElement.parseTree();
					if (tree.sourceStart < statement.sourceStart) {
						this.currentElement.add(statement, 0);
						break;
					}
					this.currentElement = this.currentElement.parent;
				}
			}
		}
	}
	if (this.snapShotPtr > -1)
		popSnapShot();
	return lambdaClosed;
}
public Statement replaceAssistStatement(RecoveredElement top, ASTNode assistParent, int start, int end, Statement stmt) {
	if (top == null) return null;
	if (top instanceof RecoveredBlock) {
		RecoveredBlock blk = (RecoveredBlock) top;
		RecoveredStatement[] statements = blk.statements;
		boolean found = false;
		if (statements != null) {
			for(int i = 0; i < statements.length; i++) {
				if (statements[i] == null) break;
				ASTNode node = statements[i].parseTree();
				if ((node.sourceStart >= start && node.sourceEnd <= end)) {
					if (!found) {
						statements[i] = new RecoveredStatement(stmt, blk, 0);
						found = true;
						blk.statementCount = i + 1;
					} else {
						// Proceed to wipe out the nodes after the assist node. Most likely
						// these are wrapped inside the just-closed-lambda. Even otherwise,
						// they are not much useful for completion.
						statements[i] = null;
					}
				}
			}
			if (found) return null;
		}
	} else if (top instanceof RecoveredMethod) {
		stmt = replaceAssistStatement(((RecoveredMethod) top).methodBody, assistParent, start, end, stmt);
	} else if (top instanceof RecoveredInitializer) {
		stmt = replaceAssistStatement(((RecoveredInitializer) top).initializerBody, assistParent, start, end, stmt);
	}
	return stmt;
}
protected ASTNode assistNodeParent() {
	return null;
}
protected ASTNode enclosingNode() {
	return null;
}

//{ObjectTeams: make public (was protected)
@Override
public boolean isAssistParser() {
//SH}
	return true;
}
@Override
protected void consumeBlockStatement() {
	super.consumeBlockStatement();
	if (triggerRecoveryUponLambdaClosure((Statement) this.astStack[this.astPtr], true) && this.currentElement != null)
		this.restartRecovery = true;
}
@Override
protected void consumeBlockStatements() {
	super.consumeBlockStatements();
	if (triggerRecoveryUponLambdaClosure((Statement) this.astStack[this.astPtr], true) && this.currentElement != null) {
		this.restartRecovery = true;
	}
}
@Override
protected void consumeBlock() {
	super.consumeBlock();
	if (this.snapShotPtr > -1) {
		ASTNode top = this.astStack[this.astPtr];
		if (top instanceof Block) {
			// check positions for sanity:
			assert this.snapShotPositions[this.snapShotPtr] == top.sourceStart : "Block positions should be consistent"; //$NON-NLS-1$
			popSnapShot();
		}
	}
}
@Override
protected void consumeFieldDeclaration() {
	super.consumeFieldDeclaration();
	if (triggerRecoveryUponLambdaClosure((Statement) this.astStack[this.astPtr], true)) {
		if (this.currentElement instanceof RecoveredType)
			popUntilElement(K_TYPE_DELIMITER);
		if (this.currentElement != null)
			this.restartRecovery = true;
	}
}
@Override
protected void consumeForceNoDiet() {
	super.consumeForceNoDiet();
	// if we are not in a method (i.e. we are not in a local variable initializer)
	// then we are entering a field initializer
	if (!isInsideMethod()) {
		if(topKnownElementKind(ASSIST_PARSER) != K_ENUM_CONSTANT_DELIMITER) {
			if(topKnownElementKind(ASSIST_PARSER, 2) != K_ENUM_CONSTANT_DELIMITER) {
				pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
			}
		} else {
			int info = topKnownElementInfo(ASSIST_PARSER);
			if(info != NO_BODY) {
				pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
			}
		}

	}
}
@Override
protected void consumeInterfaceHeader() {
	super.consumeInterfaceHeader();
	pushOnElementStack(K_TYPE_DELIMITER);
}
@Override
protected void consumeNestedLambda() {
	super.consumeNestedLambda();
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr];
	pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, EXPRESSION_BODY, lexp);
}
@Override
protected void consumeMethodBody() {
	super.consumeMethodBody();
	popElement(K_METHOD_DELIMITER);
}
@Override
protected void consumeMethodDeclaration(boolean isNotAbstract, boolean isDefaultMethod) {
	if (!isNotAbstract) {
		popElement(K_METHOD_DELIMITER);
	}
	super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
	if (this.snapShotPtr > -1) {
		ASTNode top = this.astStack[this.astPtr];
		if (top instanceof AbstractMethodDeclaration) {
			// check positions for sanity:
			assert this.snapShotPositions[this.snapShotPtr] + 1 == ((AbstractMethodDeclaration) top).bodyStart : "Method positions should be consistent"; //$NON-NLS-1$
			popSnapShot();
		}
	}
}
@Override
protected void consumeMethodHeader() {
	super.consumeMethodHeader();
	pushOnElementStack(K_METHOD_DELIMITER);
}
@Override
protected void consumeMethodInvocationName() {
	super.consumeMethodInvocationName();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
@Override
protected void consumeMethodInvocationNameWithTypeArguments() {
	super.consumeMethodInvocationNameWithTypeArguments();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
@Override
protected void consumeMethodInvocationPrimary() {
	super.consumeMethodInvocationPrimary();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
@Override
protected void consumeMethodInvocationPrimaryWithTypeArguments() {
	super.consumeMethodInvocationPrimaryWithTypeArguments();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
@Override
protected void consumeMethodInvocationSuper() {
	super.consumeMethodInvocationSuper();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
@Override
protected void consumeMethodInvocationSuperWithTypeArguments() {
	super.consumeMethodInvocationSuperWithTypeArguments();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
@Override
protected void consumeModuleHeader() {
	pushOnElementStack(K_MODULE_INFO_DELIMITER);
	// ModuleHeader ::= 'module' Name
	/* build an ImportRef build from the last name
	stored in the identifier stack. */

	int index;

	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumeModuleHeader();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
	should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
			this.identifierPositionStack,
			this.identifierPtr + 1,
			positions,
			0,
			length);
	ModuleDeclaration typeDecl = createAssistModuleDeclaration(this.compilationUnit.compilationResult, subset, positions);

	this.compilationUnit.moduleDeclaration = typeDecl;
	this.assistNode = typeDecl;
	this.lastCheckPoint = typeDecl.sourceEnd + 1;

	//compute the declaration source too
	typeDecl.declarationSourceStart = this.intStack[this.intPtr--];

	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
	pushOnAstStack(typeDecl);

	this.listLength = 0; // will be updated when reading super-interfaces
	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = typeDecl.bodyStart;
		this.currentElement = this.currentElement.add(typeDecl, 0);
		this.lastIgnoredToken = -1;
	}
}

@Override
protected void consumeModuleDeclaration() {
	super.consumeModuleDeclaration();
	popElement(K_MODULE_INFO_DELIMITER);
}
@Override
protected void consumeNestedMethod() {
	super.consumeNestedMethod();
	if(!isInsideMethod()) pushOnElementStack(K_METHOD_DELIMITER);
}
@Override
protected void consumeOpenBlock() {
	// OpenBlock ::= $empty
	super.consumeOpenBlock();

	int stackLength = this.blockStarts.length;
	if (this.realBlockPtr >= stackLength) {
		System.arraycopy(
				this.blockStarts, 0,
				this.blockStarts = new int[stackLength + StackIncrement], 0,
				stackLength);
	}
	this.blockStarts[this.realBlockPtr] = this.scanner.startPosition;
	if (requireExtendedRecovery()) {
		// This is an epsilon production: We are in the state with kernel item: Block ::= .OpenBlock LBRACE BlockStatementsopt RBRACE
		if (this.currentToken == TokenNameLBRACE && this.unstackedAct > NUM_RULES) { // wait for chain reductions to finish before commit.
			stackLength = this.stack.length;
			if (++this.stateStackTop >= stackLength - 1) {   // Need two slots.
				System.arraycopy(
						this.stack, 0,
						this.stack = new int[stackLength + StackIncrement], 0,
						stackLength);
			}
			this.stack[this.stateStackTop++] = this.unstackedAct; // transition to Block ::= OpenBlock  .LBRACE BlockStatementsopt RBRACE
			this.stack[this.stateStackTop] = tAction(this.unstackedAct, this.currentToken); // transition to Block ::= OpenBlock LBRACE  .BlockStatementsopt RBRACE 
			commit(true);
			this.stateStackTop -= 2;
		}
	}
}
protected void consumeOpenFakeBlock() {
	// OpenBlock ::= $empty

	super.consumeOpenBlock();
	int stackLength = this.blockStarts.length;
	if (this.realBlockPtr >= stackLength) {
		System.arraycopy(
			this.blockStarts, 0,
			this.blockStarts = new int[stackLength + StackIncrement], 0,
			stackLength);
	}
	this.blockStarts[this.realBlockPtr] = -this.scanner.startPosition;
}
@Override
protected void consumePackageDeclarationName() {
	// PackageDeclarationName ::= 'package' Name
	/* build an ImportRef build from the last name
	stored in the identifier stack. */

	int index;

	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumePackageDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on package statement */
//{ObjectTeams: support for team packages
/* orig:
	ImportReference reference = createAssistPackageReference(subset, positions);
 :giro */
	ImportReference reference = createAssistPackageReference(subset, positions, this.modifiers);
	boolean isTeamPackage = (this.modifiers & ExtraCompilerModifiers.AccTeam) != 0;
	resetModifiers();
	this.currentIsRole = isTeamPackage; // the type declaration to follow a team package must be a role.
//carp}

	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	this.compilationUnit.currentPackage = reference;

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush comments defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
@Override
protected void consumePackageDeclarationNameWithModifiers() {
	// PackageDeclarationName ::= Modifiers 'package' PushRealModifiers Name
	/* build an ImportRef build from the last name
	stored in the identifier stack. */

	int index;

	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumePackageDeclarationNameWithModifiers();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	this.intPtr--; // we don't need the modifiers start
//{ObjectTeams: yes we want the team modifier!
/* orig:
	this.intPtr--; // we don't need the package modifiers
	ImportReference reference = createAssistPackageReference(subset, positions);
  :giro*/
	ImportReference reference = createAssistPackageReference(subset, positions, this.intStack[this.intPtr--]);
// SH}
	// consume annotations
	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
		System.arraycopy(
			this.expressionStack,
			(this.expressionPtr -= length) + 1,
			reference.annotations = new Annotation[length],
			0,
			length);
	}
	/* build specific assist node on package statement */
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	this.compilationUnit.currentPackage = reference;

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush comments defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
@Override
protected void consumeRestoreDiet() {
	super.consumeRestoreDiet();
	// if we are not in a method (i.e. we were not in a local variable initializer)
	// then we are exiting a field initializer
	if (!isInsideMethod()) {
		popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
		popElement(K_FIELD_INITIALIZER_DELIMITER);
	}
}
@Override
protected void consumeSingleStaticImportDeclarationName() {
	// SingleTypeImportDeclarationName ::= 'import' 'static' Name
	/* push an ImportRef build from the last name
	stored in the identifier stack. */

	int index;

	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumeSingleStaticImportDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on import statement */
	ImportReference reference = createAssistImportReference(subset, positions, ClassFileConstants.AccStatic);
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush annotations defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.currentElement = this.currentElement.add(reference, 0);
		this.lastIgnoredToken = -1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
@Override
protected void consumeSinglePkgName() {
	int index;
	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumeSinglePkgName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
	should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
			this.identifierPositionStack,
			this.identifierPtr + 1,
			positions,
			0,
			length);

	/* build specific assist node on import statement */
	ImportReference reference = createAssistPackageVisibilityReference(subset, positions);
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON) {
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
}
@Override
protected void consumeSingleTargetModuleName() {
	int index;
	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumeSingleTargetModuleName();
		return;
	}

	/* build specific assist node on targetted exports statement */
	ModuleReference reference = createAssistModuleReference(index);
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	pushOnAstStack(reference);

	// recovery - TBD
	if (this.currentElement instanceof RecoveredExportsStatement){
		// TODO
		this.lastCheckPoint = reference.sourceEnd+1;
		this.currentElement = ((RecoveredExportsStatement) this.currentElement).add(reference, 0);
		this.lastIgnoredToken = -1;
		//this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}

}
@Override
protected void consumeSingleRequiresModuleName() {

	int index = indexOfAssistIdentifier();
	/* no need to take action if not inside assist identifiers */
	if (index < 0) {
		super.consumeSingleRequiresModuleName();
		return;
	}

	/* build specific assist node on requires statement */
	ModuleReference reference = createAssistModuleReference(index);
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	RequiresStatement req = new RequiresStatement(reference);
	if (this.currentToken == TokenNameSEMICOLON){
		req.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		req.declarationSourceEnd = reference.sourceEnd;
	}
	req.sourceStart = req.declarationSourceStart;
	req.declarationEnd = req.declarationSourceEnd;
	req.modifiersSourceStart = this.intStack[this.intPtr--];
	req.modifiers |= this.intStack[this.intPtr--];
	req.declarationSourceStart = this.intStack[this.intPtr--];
	if (req.modifiersSourceStart >= 0) {
		req.declarationSourceStart = req.modifiersSourceStart;
	}
	req.sourceEnd = reference.sourceEnd;
	pushOnAstStack(req);

	// recovery TBD

	if (this.currentElement != null){
		this.lastCheckPoint = req.declarationSourceEnd + 1;
		this.currentElement = this.currentElement.add(req, 0);
		this.lastIgnoredToken = -1;
	}

}

@Override
protected void consumeSingleTypeImportDeclarationName() {
	// SingleTypeImportDeclarationName ::= 'import' Name
	/* push an ImportRef build from the last name
	stored in the identifier stack. */

	int index;

	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumeSingleTypeImportDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on import statement */
	ImportReference reference = createAssistImportReference(subset, positions, ClassFileConstants.AccDefault);
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush comments defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.currentElement = this.currentElement.add(reference, 0);
		this.lastIgnoredToken = -1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
//{ObjectTeams: base import (copied basically from consumeSingleTypeImportDeclarationName):
@Override
protected void consumeSingleBaseImportDeclarationName() {
	// SingleTypeImportDeclarationName ::= 'import' 'base' Name
	/* push an ImportRef build from the last name
	stored in the identifier stack. */

	int index;

	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumeSingleBaseImportDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on import statement */
//OT/J:	specific flag AccBase:
	ImportReference reference = createAssistImportReference(subset, positions, ExtraCompilerModifiers.AccBase);
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
//	OT/J: consume start and end position of base:
	this.intPtr-=2;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush comments defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.currentElement = this.currentElement.add(reference, 0);
		this.lastIgnoredToken = -1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
// SH}
@Override
protected void consumeStaticImportOnDemandDeclarationName() {
	// TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
	/* push an ImportRef build from the last name
	stored in the identifier stack. */

	int index;

	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumeStaticImportOnDemandDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on import statement */
	ImportReference reference = createAssistImportReference(subset, positions, ClassFileConstants.AccStatic);
	reference.bits |= ASTNode.OnDemand;
	// star end position
	reference.trailingStarPosition = this.intStack[this.intPtr--];
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush annotations defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.currentElement = this.currentElement.add(reference, 0);
		this.lastIgnoredToken = -1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
@Override
protected void consumeStaticInitializer() {
	super.consumeStaticInitializer();
	popElement(K_METHOD_DELIMITER);
}
@Override
protected void consumeStaticOnly() {
	super.consumeStaticOnly();
	pushOnElementStack(K_METHOD_DELIMITER);
}
private void adjustBracket(int token) {
	switch (token) {
		case TokenNameLPAREN :
		case TokenNameLBRACE:
		case TokenNameLBRACKET:
			this.bracketDepth++;
			break;
		case TokenNameRBRACE:
		case TokenNameRBRACKET:
		case TokenNameRPAREN:
			this.bracketDepth--;
			break;
	}
}
@Override
protected void consumeToken(int token) {
	super.consumeToken(token);

	if(this.isFirst) {
		this.isFirst = false;
		return;
	}
	// register message send selector only if inside a method or if looking at a field initializer
	// and if the current token is an open parenthesis
	if (isInsideMethod() || isInsideFieldInitialization() || isInsideAttributeValue() || isInsideEnumConstantnitialization()) {
		adjustBracket(token);
		switch (token) {
			case TokenNameLPAREN :
				switch (this.previousToken) {
					case TokenNameIdentifier:
						this.pushOnElementStack(K_SELECTOR, this.identifierPtr);
						break;
					case TokenNamethis: // explicit constructor invocation, e.g. this(1, 2)
						this.pushOnElementStack(K_SELECTOR, THIS_CONSTRUCTOR);
						break;
					case TokenNamesuper: // explicit constructor invocation, e.g. super(1, 2)
						this.pushOnElementStack(K_SELECTOR, SUPER_CONSTRUCTOR);
						break;
					case TokenNameGREATER: // explicit constructor invocation, e.g. Fred<X>[(]1, 2)
					case TokenNameRIGHT_SHIFT: // or fred<X<X>>[(]1, 2)
					case TokenNameUNSIGNED_RIGHT_SHIFT: //or Fred<X<X<X>>>[(]1, 2)
						if(this.identifierPtr > -1) {
							this.pushOnElementStack(K_SELECTOR, this.identifierPtr);
						}
						break;
				}
				break;
			case TokenNameLBRACE:
				if (this.previousToken == TokenNameARROW) {
					popElement(K_LAMBDA_EXPRESSION_DELIMITER);
					if (topKnownElementKind(ASSIST_PARSER, 1) != K_SWITCH_EXPRESSION_DELIMITTER)
						pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, BLOCK_BODY, this.previousObjectInfo);
				}
				break;
		}
	} else if (isInsideModuleInfo()) { 
		adjustBracket(token);
	} else {
		switch (token) {
			case TokenNameRBRACE :
				if(topKnownElementKind(ASSIST_PARSER) == K_TYPE_DELIMITER) {
					popElement(K_TYPE_DELIMITER);
				}
				break;
		}
	}
	this.previousToken = token;
	if (token == TokenNameIdentifier) {
		this.previousIdentifierPtr = this.identifierPtr;
	}
}
@Override
protected void consumeTypeImportOnDemandDeclarationName() {
	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
	/* push an ImportRef build from the last name
	stored in the identifier stack. */

	int index;

	/* no need to take action if not inside assist identifiers */
	if ((index = indexOfAssistIdentifier()) < 0) {
		super.consumeTypeImportOnDemandDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on import statement */
	ImportReference reference = createAssistImportReference(subset, positions, ClassFileConstants.AccDefault);
	reference.bits |= ASTNode.OnDemand;
	// star end position
	reference.trailingStarPosition = this.intStack[this.intPtr--];
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush comments defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.currentElement = this.currentElement.add(reference, 0);
		this.lastIgnoredToken = -1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}

// TODO : Change to ExportsReference/PackageReference once we have the new compiler ast.node
public abstract ImportReference createAssistPackageVisibilityReference(char[][] tokens, long[] positions);
public abstract ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod);
public abstract ModuleReference createAssistModuleReference(int index);
//{ObjectTeams: added modifiers:
public abstract ImportReference createAssistPackageReference(char[][] tokens, long[] positions, int modifiers);
// SH}
public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
public abstract TypeReference createParameterizedQualifiedAssistTypeReference(char[][] previousIdentifiers, TypeReference[][] typeArguments, char[] asistIdentifier, TypeReference[] assistTypeArguments, long[] positions);
public abstract NameReference createSingleAssistNameReference(char[] assistName, long position);
public abstract TypeReference createSingleAssistTypeReference(char[] assistName, long position);
public abstract TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position);
public abstract ModuleDeclaration createAssistModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions);
/*
 * Flush parser/scanner state regarding to code assist
 */
public void flushAssistState(){
	this.assistNode = null;
	this.isOrphanCompletionNode = false;
	setAssistIdentifier(null);
}
protected void flushElementStack() {
	for (int j = 0; j <= this.elementPtr; j++) {
		this.elementObjectInfoStack[j] = null;
	}

	this.elementPtr = -1;
	this.previousKind = 0;
	this.previousInfo = 0;
	this.previousObjectInfo = null;
}
/*
 * Build specific type reference nodes in case the cursor is located inside the type reference
 */
@Override
protected TypeReference getTypeReference(int dim) {
//{ObjectTeams: wrap to introduce 2nd parameter
	return getTypeReference(dim, false);  
}
@Override
protected TypeReference getTypeReference(int dim, boolean liftingTypeAllowed) {
// orig:

	int index;

	/* no need to take action if not inside completed identifiers */
	if ((index = indexOfAssistIdentifier(true)) < 0) {
/* orig: 
		return super.getTypeReference(dim);
 :giro */
		return super.getTypeReference(dim, liftingTypeAllowed);
// SH}
	}
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	TypeReference reference;
	int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
	if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
		this.identifierLengthPtr--;
		// generic type
		reference = getAssistTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
	} else {
		/* retrieve identifiers subset and whole positions, the assist node positions
			should include the entire replaced source. */

		char[][] subset = identifierSubSet(index);
		this.identifierLengthPtr--;
		this.identifierPtr -= length;
		long[] positions = new long[length];
		System.arraycopy(
			this.identifierPositionStack,
			this.identifierPtr + 1,
			positions,
			0,
			length);

		/* build specific assist on type reference */

		if (index == 0) {
//			genericsIdentifiersLengthPtr--;
			this.genericsLengthPtr--;
			/* assist inside first identifier */
			reference = createSingleAssistTypeReference(
							assistIdentifier(),
							positions[0]);
		} else {
//			genericsIdentifiersLengthPtr--;
			this.genericsLengthPtr--;
			/* assist inside subsequent identifier */
			reference =	createQualifiedAssistTypeReference(
							subset,
							assistIdentifier(),
							positions);
		}
		this.assistNode = reference;
		this.lastCheckPoint = reference.sourceEnd + 1;
	}
	return reference;
}
protected TypeReference getAssistTypeReferenceForGenericType(int dim, int identifierLength, int numberOfIdentifiers) {
	/* no need to take action if not inside completed identifiers */
	if (/*(indexOfAssistIdentifier()) < 0 ||*/ (identifierLength == 1 && numberOfIdentifiers == 1)) {
		int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
		TypeReference[] typeArguments;
		if (currentTypeArgumentsLength > -1) {
			typeArguments = new TypeReference[currentTypeArgumentsLength];
			this.genericsPtr -= currentTypeArgumentsLength;
			System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments, 0, currentTypeArgumentsLength);
		} else {
			typeArguments = TypeReference.NO_TYPE_ARGUMENTS;
		}
		long[] positions = new long[identifierLength];
		System.arraycopy(
			this.identifierPositionStack,
			this.identifierPtr,
			positions,
			0,
			identifierLength);

		this.identifierPtr--;

		TypeReference reference = createParameterizedSingleAssistTypeReference(
				typeArguments,
				assistIdentifier(),
				positions[0]);

		this.assistNode = reference;
		this.lastCheckPoint = reference.sourceEnd + 1;
		return reference;
	}

	TypeReference[][] typeArguments = new TypeReference[numberOfIdentifiers][];
	char[][] tokens = new char[numberOfIdentifiers][];
	long[] positions = new long[numberOfIdentifiers];
	int index = numberOfIdentifiers;
	int currentIdentifiersLength = identifierLength;
	while (index > 0) {
		int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
		if (currentTypeArgumentsLength > 0) {
			this.genericsPtr -= currentTypeArgumentsLength;
			System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments[index - 1] = new TypeReference[currentTypeArgumentsLength], 0, currentTypeArgumentsLength);
		}
		switch(currentIdentifiersLength) {
			case 1 :
				// we are in a case A<B>.C<D> or A<B>.C<D>
				tokens[index - 1] = this.identifierStack[this.identifierPtr];
				positions[index - 1] = this.identifierPositionStack[this.identifierPtr--];
				break;
			default:
				// we are in a case A.B.C<B>.C<D> or A.B.C<B>...
				this.identifierPtr -= currentIdentifiersLength;
				System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, index - currentIdentifiersLength, currentIdentifiersLength);
				System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, index - currentIdentifiersLength, currentIdentifiersLength);
		}
		index -= currentIdentifiersLength;
		if (index > 0) {
			currentIdentifiersLength = this.identifierLengthStack[this.identifierLengthPtr--];
		}
	}

	// remove completion token
	int realLength = numberOfIdentifiers;
	for (int i = 0; i < numberOfIdentifiers; i++) {
		if(tokens[i] == assistIdentifier()) {
			realLength = i;
		}
	}
	TypeReference reference;
	if(realLength == 0) {
		if(typeArguments[0] != null && typeArguments[0].length > 0) {
			reference = createParameterizedSingleAssistTypeReference(typeArguments[0], assistIdentifier(), positions[0]);
		} else {
			reference = createSingleAssistTypeReference(assistIdentifier(), positions[0]);
		}
	} else {
		TypeReference[] assistTypeArguments = typeArguments[realLength];
		System.arraycopy(tokens, 0, tokens = new char[realLength][], 0, realLength);
		System.arraycopy(typeArguments, 0, typeArguments = new TypeReference[realLength][], 0, realLength);

		boolean isParameterized = false;
		for (int i = 0; i < typeArguments.length; i++) {
			if(typeArguments[i] != null) {
				isParameterized = true;
			}
		}
		if(isParameterized || (assistTypeArguments != null && assistTypeArguments.length > 0)) {
			reference = createParameterizedQualifiedAssistTypeReference(tokens, typeArguments, assistIdentifier(), assistTypeArguments, positions);
		} else {
			reference = createQualifiedAssistTypeReference(tokens, assistIdentifier(), positions);
		}
	}

	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	return reference;
}
/*
 * Copy of code from superclass with the following change:
 * In the case of qualified name reference if the cursor location is on the
 * qualified name reference, then create a CompletionOnQualifiedNameReference
 * instead.
 */
@Override
protected NameReference getUnspecifiedReferenceOptimized() {

	int completionIndex;

	/* no need to take action if not inside completed identifiers */
	if ((completionIndex = indexOfAssistIdentifier()) < 0) {
		return super.getUnspecifiedReferenceOptimized();
	}

	consumeNonTypeUseName();
	
	/* retrieve identifiers subset and whole positions, the completion node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(completionIndex);
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific completion on name reference */
	NameReference reference;
	if (completionIndex == 0) {
		/* completion inside first identifier */
		reference = createSingleAssistNameReference(assistIdentifier(), positions[0]);
	} else {
		/* completion inside subsequent identifier */
		reference = createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
	}
	reference.bits &= ~ASTNode.RestrictiveFlagMASK;
	reference.bits |= Binding.LOCAL | Binding.FIELD;

	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	return reference;
}
@Override
public void goForBlockStatementsopt() {
	super.goForBlockStatementsopt();
	this.isFirst = true;
}
@Override
public void goForHeaders(){
	super.goForHeaders();
	this.isFirst = true;
}
@Override
public void goForCompilationUnit(){
	super.goForCompilationUnit();
	this.isFirst = true;
}
@Override
public void goForBlockStatementsOrCatchHeader() {
	super.goForBlockStatementsOrCatchHeader();
	this.isFirst = true;
}
/*
 * Retrieve a partial subset of a qualified name reference up to the completion point.
 * It does not pop the actual awaiting identifiers, so as to be able to retrieve position
 * information afterwards.
 */
protected char[][] identifierSubSet(int subsetLength){

	if (subsetLength == 0) return null;

	char[][] subset;
	System.arraycopy(
		this.identifierStack,
		this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + 1,
		(subset = new char[subsetLength][]),
		0,
		subsetLength);
	return subset;
}

protected int indexOfAssistIdentifier(){
	return this.indexOfAssistIdentifier(false);
}
//{ObjectTeams: cope with lookahead tricks in our scanner:

// somehow the restarting parser (recovery) and our lookahead caused
// that the assistIdentifier could nowhere be found for identity comparison.

// 1. when consuming the lookahead identifier after '->' store it here:
char[] pendingBindoutId;
@Override
protected void pushIdentifier() {
	this.pendingBindoutId = this.scanner.peekPendingIdentifier();
	super.pushIdentifier();
}
// 2. record when we are consuming a 'expr -> id' parameter mapping
boolean insideParamMappingOut;
@Override
protected void consumeParameterMappingOut() {
	this.insideParamMappingOut = true;
	super.consumeParameterMappingOut();
	this.insideParamMappingOut = false;
}
// 3. to be continued in indexOfAssistIdentifier(boolean) below ...
// SH}

/*
 * Iterate the most recent group of awaiting identifiers (grouped for qualified name reference (e.g. aa.bb.cc)
 * so as to check whether one of them is the assist identifier.
 * If so, then answer the index of the assist identifier (0 being the first identifier of the set).
 *	e.g. aa(0).bb(1).cc(2)
 * If no assist identifier was found, answers -1.
 */
protected int indexOfAssistIdentifier(boolean useGenericsStack){

	if (this.identifierLengthPtr < 0){
		return -1; // no awaiting identifier
	}

	char[] assistIdentifier ;
	if ((assistIdentifier = assistIdentifier()) == null){
		return -1; // no assist identifier found yet
	}

	// iterate awaiting identifiers backwards
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	if(useGenericsStack && length > 0 && this.genericsIdentifiersLengthPtr > -1 ) {
		length = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
	}
	for (int i = 0; i < length; i++){
		if (this.identifierStack[this.identifierPtr - i] == assistIdentifier){
			return length - i - 1;
		}
	}
//{ObjectTeams: ...check info remembered above...
	if (this.insideParamMappingOut && this.pendingBindoutId == assistIdentifier)
		// we are in a 'expr -> id' parameter mapping and the 'id' is our assistIdentifier
		return 0; // always a single identifier, so answer index 0
// SH}
	// none of the awaiting identifiers is the completion one
	return -1;
}
@Override
public void initialize() {
	super.initialize();
	flushAssistState();
	flushElementStack();
	this.previousIdentifierPtr = -1;
	this.bracketDepth = 0;
}
@Override
public void initialize(boolean parsingCompilationUnit) {
	super.initialize(parsingCompilationUnit);
	flushAssistState();
	flushElementStack();
	this.previousIdentifierPtr = -1;
	this.bracketDepth = 0;
}
@Override
public abstract void initializeScanner();
protected boolean isIndirectlyInsideFieldInitialization(){
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == K_FIELD_INITIALIZER_DELIMITER)
			return true;
		i--;
	}
	return false;
}
protected boolean isIndirectlyInsideEnumConstantnitialization(){
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == K_ENUM_CONSTANT_DELIMITER)
			return true;
		i--;
	}
	return false;
}
protected boolean isIndirectlyInsideMethod(){
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == K_METHOD_DELIMITER)
			return true;
		i--;
	}
	return false;
}
@Override
protected boolean isIndirectlyInsideLambdaExpression(){
	int i = this.elementPtr;
	while (i > -1) {
		if (this.elementKindStack[i] == K_LAMBDA_EXPRESSION_DELIMITER)
			return true;
		i--;
	}
	return false;
}
protected boolean isIndirectlyInsideLambdaBlock(){
	int i = this.elementPtr;
	while (i > -1) {
		if (this.elementKindStack[i] == K_LAMBDA_EXPRESSION_DELIMITER && this.elementInfoStack[i] == BLOCK_BODY)
			return true;
		i--;
	}
	return false;
}
protected boolean isIndirectlyInsideType(){
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == K_TYPE_DELIMITER)
			return true;
		i--;
	}
	return false;
}
protected boolean isInsideAttributeValue(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return false;
			case K_METHOD_DELIMITER : return false;
			case K_FIELD_INITIALIZER_DELIMITER : return false;
			case K_ATTRIBUTE_VALUE_DELIMITER : return true;
		}
		i--;
	}
	return false;
}
protected boolean isInsideFieldInitialization(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return false;
			case K_METHOD_DELIMITER : return false;
			case K_FIELD_INITIALIZER_DELIMITER : 
				return true;
		}
		i--;
	}
	return false;
}
protected boolean isInsideEnumConstantnitialization(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return false;
			case K_METHOD_DELIMITER : return false;
			case K_ENUM_CONSTANT_DELIMITER :
				return true;
		}
		i--;
	}
	return false;
}
protected boolean isInsideModuleInfo(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : 
			case K_METHOD_DELIMITER :
			case K_FIELD_INITIALIZER_DELIMITER : 
				return false;
			case K_MODULE_INFO_DELIMITER:
				return true;
		}
		i--;
	}
	return false;
}
protected boolean isInsideMethod(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return false;
			case K_METHOD_DELIMITER : return true;
			case K_FIELD_INITIALIZER_DELIMITER : return false;
		}
		i--;
	}
	return false;
}
protected boolean isInsideType(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return true;
			case K_METHOD_DELIMITER : return false;
			case K_FIELD_INITIALIZER_DELIMITER : return false;
		}
		i--;
	}
	return false;
}
protected int lastIndexOfElement(int kind) {
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == kind) return i;
		i--;
	}
	return -1;
}
/**
 * Parse the block statements inside the given method declaration and try to complete at the
 * cursor location.
 */
public void parseBlockStatements(AbstractMethodDeclaration md, CompilationUnitDeclaration unit) {
	if (md instanceof MethodDeclaration) {
		parseBlockStatements((MethodDeclaration) md, unit);
	} else if (md instanceof ConstructorDeclaration) {
		parseBlockStatements((ConstructorDeclaration) md, unit);
	}
}
/**
 * Parse the block statements inside the given constructor declaration and try to complete at the
 * cursor location.
 */
public void parseBlockStatements(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
	//only parse the method body of cd
	//fill out its statements

	//convert bugs into parse error

	initialize();
	// set the lastModifiers to reflect the modifiers of the constructor whose
	// block statements are being parsed
	// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202634
	this.lastModifiers = cd.modifiers;
	this.lastModifiersStart = cd.modifiersSourceStart;
	// simulate goForConstructorBody except that we don't want to balance brackets because they are not going to be balanced
	goForBlockStatementsopt();

	this.referenceContext = cd;
	this.compilationUnit = unit;

	this.scanner.resetTo(cd.bodyStart, bodyEnd(cd));
	consumeNestedMethod();
	try {
		parse();
	} catch (AbortCompilation ex) {
		this.lastAct = ERROR_ACTION;
	}

	if (this.lastAct == ERROR_ACTION) {
		cd.bits |= ASTNode.HasSyntaxErrors;
		return;
	}

	// attach the statements as we might be searching for a reference to a local type
	cd.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
	int length;
	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
		this.astPtr -= length;
		if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall)
			//avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
			{
			System.arraycopy(
				this.astStack,
				this.astPtr + 2,
				cd.statements = new Statement[length - 1],
				0,
				length - 1);
//{ObjectTeams: new flag:
			cd.hasParsedStatements = true;
// SH}

			cd.constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1];
		} else { //need to add explicitly the super();
			System.arraycopy(
				this.astStack,
				this.astPtr + 1,
				cd.statements = new Statement[length],
				0,
				length);
			cd.constructorCall = SuperReference.implicitSuperConstructorCall();
		}
	} else {
		cd.constructorCall = SuperReference.implicitSuperConstructorCall();
		if (!containsComment(cd.bodyStart, cd.bodyEnd)) {
			cd.bits |= ASTNode.UndocumentedEmptyBlock;
		}
	}

	if (cd.constructorCall.sourceEnd == 0) {
		cd.constructorCall.sourceEnd = cd.sourceEnd;
		cd.constructorCall.sourceStart = cd.sourceStart;
	}
}
/**
 * Parse the block statements inside the given initializer and try to complete at the
 * cursor location.
 */
public void parseBlockStatements(
	Initializer initializer,
	TypeDeclaration type,
	CompilationUnitDeclaration unit) {

	initialize();
	// set the lastModifiers to reflect the modifiers of the initializer whose
	// block statements are being parsed
	// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202634
	this.lastModifiers = initializer.modifiers;
	this.lastModifiersStart = initializer.modifiersSourceStart;
	// simulate goForInitializer except that we don't want to balance brackets because they are not going to be balanced
	goForBlockStatementsopt();

	this.referenceContext = type;
	this.compilationUnit = unit;

	this.scanner.resetTo(initializer.sourceStart, bodyEnd(initializer)); // just after the beginning {
	consumeNestedMethod();
	try {
		parse();
	} catch (AbortCompilation ex) {
		this.lastAct = ERROR_ACTION;
	} finally {
		this.nestedMethod[this.nestedType]--;
	}

	if (this.lastAct == ERROR_ACTION) {
		initializer.bits |= ASTNode.HasSyntaxErrors;
		return;
	}

	// attach the statements as we might be searching for a reference to a local type
	initializer.block.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
	int length;
	if ((length = this.astLengthStack[this.astLengthPtr--]) > 0) {
		System.arraycopy(this.astStack, (this.astPtr -= length) + 1, initializer.block.statements = new Statement[length], 0, length);
	} else {
		// check whether this block at least contains some comment in it
		if (!containsComment(initializer.block.sourceStart, initializer.block.sourceEnd)) {
			initializer.block.bits |= ASTNode.UndocumentedEmptyBlock;
		}
	}

	// mark initializer with local type if one was found during parsing
	if ((type.bits & ASTNode.HasLocalType) != 0) {
		initializer.bits |= ASTNode.HasLocalType;
	}
}

/**
 * Parse the block statements inside the given method declaration and try to complete at the
 * cursor location.
 */
public void parseBlockStatements(MethodDeclaration md, CompilationUnitDeclaration unit) {
	//only parse the method body of md
	//fill out method statements

	//convert bugs into parse error

	if (md.isNative())
		return;
	if ((md.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0)
		return;

//{ObjectTeams: trying to re-parse predicate?
	// predicate methods are already parsed regardless of diet parsing
	if(OTNameUtils.isPredicate(md.selector))
		return; // already parsed in diet mode, assistNode should already be set, don't destroy this.
// SH}

	initialize();
	// set the lastModifiers to reflect the modifiers of the method whose
	// block statements are being parsed
	// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202634
	this.lastModifiers = md.modifiers;
	this.lastModifiersStart = md.modifiersSourceStart;
	// simulate goForMethodBody except that we don't want to balance brackets because they are not going to be balanced
	goForBlockStatementsopt();

	this.referenceContext = md;
	this.compilationUnit = unit;

	this.scanner.resetTo(md.bodyStart, bodyEnd(md)); // reset the scanner to parser from { down to the cursor location
	consumeNestedMethod();
	try {
		parse();
	} catch (AbortCompilation ex) {
		this.lastAct = ERROR_ACTION;
	} finally {
		this.nestedMethod[this.nestedType]--;
	}

	if (this.lastAct == ERROR_ACTION) {
		md.bits |= ASTNode.HasSyntaxErrors;
		return;
	}

	// attach the statements as we might be searching for a reference to a local type
	md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
	int length;
	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
		System.arraycopy(
			this.astStack,
			(this.astPtr -= length) + 1,
			md.statements = new Statement[length],
			0,
			length);
//{ObjectTeams: new flag:
		md.hasParsedStatements = true;
// SH}

	} else {
		if (!containsComment(md.bodyStart, md.bodyEnd)) {
			md.bits |= ASTNode.UndocumentedEmptyBlock;
		}
	}

}
//{ObjectTeams: new method
public void parseBlockStatements(AbstractMethodMappingDeclaration mapping, CompilationUnitDeclaration unit) {
	if (mapping.mappings != AbstractMethodMappingDeclaration.PENDING_MAPPINGS)
		return;
	initialize();
	goForParameterMappings(mapping.isCallin());

	this.referenceContext = mapping;
	this.compilationUnit = unit;

	// reset the scanner to parser from { down to }
	this.scanner.resetTo(mapping.bodyStart, bodyEnd(mapping));
	consumeNestedParamMappings();
	try {
		parse();
	} catch (AbortCompilation ex) {
		this.lastAct = ERROR_ACTION;
	} finally {
		// this.nestedMethod[this.nestedType]--;
		mapping.hasParsedParamMappings = true;
	}

// SH: no return on ERROR_ACTION, which would spoil completion in (incomplete) parameter mappings.

	// mapping has no explicitDeclarations:
	// mapping.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
//{ObjectTeams: partial param mapping?
	if (   this.expressionLengthPtr > -1 && (this.expressionLengthStack[this.expressionLengthPtr] == 1)
		&& this.expressionPtr > -1) // extra safety, expressionLenghtStack seems not to be cleared correctly?
	{
		long pos= (((long)this.endPosition)<<32) + this.endPosition;
		// assume: "expr -> <MISSING>"
		char[] ident= "<MISSING>".toCharArray();  //$NON-NLS-1$
		int direction= TerminalTokens.TokenNameBINDOUT;
		if (this.identifierLengthPtr > -1 && this.identifierLengthStack[0] == 1) { // unconsumed single identifier at the bottom of the stack?
			// it's: "ident <- expr"
			pos= this.identifierPositionStack[0]; // don't bother with clearing stacks, parsing aborts right now
			ident= this.identifierStack[0];
			direction= TerminalTokens.TokenNameBINDIN;
		}
		pushOnAstStack(new ParameterMapping(direction,
										    this.expressionStack[this.expressionPtr--],
										    new SingleNameReference(ident, pos)));
		concatNodeLists();
	}
// SH}

	int length;
	if (this.astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) {
		System.arraycopy(
			this.astStack,
			(this.astPtr -= length) + 1,
			mapping.mappings= new ParameterMapping[length],
			0,
			length);
	} else {
		if (!containsComment(mapping.bodyStart, mapping.bodyEnd)) {
			mapping.bits |= ASTNode.UndocumentedEmptyBlock;
		}
	}
	mapping.analyzeParameterMappings(this);
}
// SH}

// the name is a misnomer, we allow "pop"s not just at the TOS. Lambda wants to be sticky till fully reduced, however we do want other elements popped at the right point, so ... 
protected void popElement(int kind) {
	
	if (this.elementPtr < 0)
		return;
	
	int stackPointer = this.elementPtr;

	if (kind != K_LAMBDA_EXPRESSION_DELIMITER) {
		while (this.elementKindStack[stackPointer] == K_LAMBDA_EXPRESSION_DELIMITER) {
			if (--stackPointer < 0) break;
		}
	}
	if (stackPointer < 0 || this.elementKindStack[stackPointer] != kind)
		return;
	
	this.previousKind = this.elementKindStack[stackPointer];
	this.previousInfo = this.elementInfoStack[stackPointer];
	this.previousObjectInfo = this.elementObjectInfoStack[stackPointer];

	final int length = this.elementPtr - stackPointer;
	if (length > 0) {
		System.arraycopy(this.elementKindStack, stackPointer + 1, this.elementKindStack, stackPointer, length);
		System.arraycopy(this.elementInfoStack, stackPointer + 1, this.elementInfoStack, stackPointer, length);
		System.arraycopy(this.elementObjectInfoStack, stackPointer + 1, this.elementObjectInfoStack, stackPointer, length);
	}
	this.elementObjectInfoStack[this.elementPtr] = null;
	this.elementPtr--;
}
protected void popUntilElement(int kind){
	if(this.elementPtr < 0) return;
	int i = this.elementPtr;
	while (i >= 0 && this.elementKindStack[i] != kind) {
		i--;
	}
	if(i >= 0) {
		if(i < this.elementPtr) {
			this.previousKind = this.elementKindStack[i+1];
			this.previousInfo = this.elementInfoStack[i+1];
			this.previousObjectInfo = this.elementObjectInfoStack[i+1];

			for (int j = i + 1; j <= this.elementPtr; j++) {
				this.elementObjectInfoStack[j] = null;
			}
		}
		this.elementPtr = i;
	}
}
/*
 * Prepares the state of the parser to go for BlockStatements.
 */
@Override
protected void prepareForBlockStatements() {
	this.nestedMethod[this.nestedType = 0] = 1;
	this.variablesCounter[this.nestedType] = 0;
	this.realBlockStack[this.realBlockPtr = 1] = 0;

	// initialize element stack
	int fieldInitializerIndex = lastIndexOfElement(K_FIELD_INITIALIZER_DELIMITER);
	int methodIndex = lastIndexOfElement(K_METHOD_DELIMITER);
	if(methodIndex == fieldInitializerIndex) {
		// there is no method and no field initializer
		flushElementStack();
	} else if(methodIndex > fieldInitializerIndex) {
		popUntilElement(K_METHOD_DELIMITER);
	} else {
		popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
	}
}
/*
 * Prepares the state of the parser to go for Headers.
 */
protected void prepareForHeaders() {
	this.nestedMethod[this.nestedType = 0] = 0;
	this.variablesCounter[this.nestedType] = 0;
	this.realBlockStack[this.realBlockPtr = 0] = 0;

	popUntilElement(K_TYPE_DELIMITER);

	if(this.topKnownElementKind(ASSIST_PARSER) != K_TYPE_DELIMITER) {
		// is outside a type and inside a compilation unit.
		// remove all elements.
		flushElementStack();
	}
}

public boolean requireExtendedRecovery() {
	return lastIndexOfElement(K_LAMBDA_EXPRESSION_DELIMITER) >= 0;
}

protected void pushOnElementStack(int kind){
	this.pushOnElementStack(kind, 0, null);
}
protected void pushOnElementStack(int kind, int info){
	this.pushOnElementStack(kind, info, null);
}
protected void pushOnElementStack(int kind, int info, Object objectInfo){
	if (this.elementPtr < -1) return;

	this.previousKind = 0;
	this.previousInfo = 0;
	this.previousObjectInfo = null;

	int stackLength = this.elementKindStack.length;
	if (++this.elementPtr >= stackLength) {
		System.arraycopy(
			this.elementKindStack, 0,
			this.elementKindStack = new int[stackLength + StackIncrement], 0,
			stackLength);
		System.arraycopy(
			this.elementInfoStack, 0,
			this.elementInfoStack = new int[stackLength + StackIncrement], 0,
			stackLength);
		System.arraycopy(
			this.elementObjectInfoStack, 0,
			this.elementObjectInfoStack = new Object[stackLength + StackIncrement], 0,
			stackLength);
	}
	this.elementKindStack[this.elementPtr] = kind;
	this.elementInfoStack[this.elementPtr] = info;
	this.elementObjectInfoStack[this.elementPtr] = objectInfo;
}
@Override
public void recoveryExitFromVariable() {
	if(this.currentElement != null && this.currentElement instanceof RecoveredField
		&& !(this.currentElement instanceof RecoveredInitializer)) {
		RecoveredElement oldElement = this.currentElement;
		super.recoveryExitFromVariable();
		if(oldElement != this.currentElement) {
			popElement(K_FIELD_INITIALIZER_DELIMITER);
		}
	} else {
		super.recoveryExitFromVariable();
	}
}
@Override
public void recoveryTokenCheck() {
	RecoveredElement oldElement = this.currentElement;
	switch (this.currentToken) {
		case TokenNameLBRACE :
			super.recoveryTokenCheck();
			if(this.currentElement instanceof RecoveredInitializer) {
				if(oldElement instanceof RecoveredField) {
					popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
					popElement(K_FIELD_INITIALIZER_DELIMITER);
				}
				if(this.currentElement != oldElement
					&& topKnownElementKind(ASSIST_PARSER) != K_METHOD_DELIMITER) {
					pushOnElementStack(K_METHOD_DELIMITER);
				}
			}
			break;
		case TokenNameRBRACE :
			super.recoveryTokenCheck();
			if(this.currentElement != oldElement && !isInsideAttributeValue() && !isIndirectlyInsideLambdaExpression()) {
				if(oldElement instanceof RecoveredInitializer
					|| oldElement instanceof RecoveredMethod
					|| (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredInitializer)
					|| (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredMethod)) {
					popUntilElement(K_METHOD_DELIMITER);
					popElement(K_METHOD_DELIMITER);
				} else if(oldElement instanceof RecoveredType) {
					popUntilElement(K_TYPE_DELIMITER);
					if(!(this.referenceContext instanceof CompilationUnitDeclaration)
							|| isIndirectlyInsideFieldInitialization()
							|| this.currentElement instanceof RecoveredUnit) {
						popElement(K_TYPE_DELIMITER);
					}
				}
			}
			break;
		default :
			super.recoveryTokenCheck();
			break;
	}
}
public void reset(){
	flushAssistState();
}

void commit(boolean isStart) {
	int newSnapShotPosition = this.scanner.startPosition;
	if (this.snapShotPtr == -1) {
		// first commit:
		addNewSnapShot(newSnapShotPosition);
	} else {
		// already have a snapshot, does it match the current position and can thus be reused?
		int currentStartPosition = isStart ? newSnapShotPosition : this.blockStarts[this.realBlockPtr];
		if (currentStartPosition != this.snapShotPositions[this.snapShotPtr])
			addNewSnapShot(newSnapShotPosition); // no match, create a new one
	}
	this.snapShotStack[this.snapShotPtr].copyState(this);
}

void addNewSnapShot(int newSnapShotPosition) {
	if (++this.snapShotPtr >= this.snapShotStack.length) {
		int len = this.snapShotStack.length;
		System.arraycopy(this.snapShotStack, 0, this.snapShotStack = new AssistParser[len+3], 0, len);
		System.arraycopy(this.snapShotPositions, 0, this.snapShotPositions = new int[len+3], 0, len);
	}
	this.snapShotStack[this.snapShotPtr] = createSnapShotParser();
	this.snapShotPositions[this.snapShotPtr] = newSnapShotPosition;
}

void popSnapShot() {
	this.snapShotStack[this.snapShotPtr--] = null;
}

protected boolean assistNodeNeedsStacking() {
	return false;
}

protected void shouldStackAssistNode() {
	// Not relevant here.
}

protected int getNextToken() {
	try {
		return this.scanner.getNextToken();
	} catch (InvalidInputException e) {
		return TokenNameEOF;
	}
}

protected abstract AssistParser createSnapShotParser();

// We get here on real syntax error or syntax error triggered by fake EOF at completion site, never due to triggered recovery.
protected int fallBackToSpringForward(Statement unused) {
	int nextToken;
	int automatonState = automatonState();
			
	// If triggered fake EOF at completion site, see if the real next token would have passed muster.
	if (this.currentToken == TokenNameEOF) {
		int extendedEnd = this.scanner.source.length;
		if (this.referenceContext instanceof AbstractMethodDeclaration)
			extendedEnd = ((AbstractMethodDeclaration) this.referenceContext).bodyEnd; // no use parsing beyond the method's body end
		if (this.scanner.eofPosition < extendedEnd) {
			shouldStackAssistNode();
			this.scanner.eofPosition = extendedEnd;
			nextToken = getNextToken();
			if (automatonWillShift(nextToken, automatonState)) {
				this.currentToken = nextToken;
				return RESUME;
			}
			this.scanner.ungetToken(nextToken); // spit out what has been bitten more than we can chew.
		} else {
			return HALT; // don't know how to proceed.
		}
	} else {
		nextToken = this.currentToken;
		this.scanner.ungetToken(nextToken);
		if (nextToken == TokenNameRBRACE)
			ignoreNextClosingBrace(); // having ungotten it, recoveryTokenCheck will see this again. 
	}
	// OK, next token is no good to resume "in place", attempt some local repair. FIXME: need to make sure we don't get stuck keep reducing empty statements !!
	for (int i = 0, length = RECOVERY_TOKENS.length; i < length; i++) {
		if (automatonWillShift(RECOVERY_TOKENS[i], automatonState)) {
			this.currentToken = RECOVERY_TOKENS[i];
			return RESUME;
		}
	}
	// OK, no in place resumption, no local repair, fast forward to next statement.
	if (this.snapShotPtr == -1)
		return RESTART;

	this.copyState(this.snapShotStack[this.snapShotPtr]);
	if (assistNodeNeedsStacking()) {
		this.currentToken = TokenNameSEMICOLON;
		return RESUME;
	}
	this.currentToken = this.scanner.fastForward(unused);
	return RESUME;
}


/*
 * Reset context so as to resume to regular parse loop
 * If unable to reset for resuming, answers false.
 *
 * Move checkpoint location, reset internal stacks and
 * decide which grammar goal is activated.
 */
@Override
protected int resumeAfterRecovery() {
	if (requireExtendedRecovery()) {
		if (this.unstackedAct == ERROR_ACTION) {
			int mode = fallBackToSpringForward((Statement) null);
			this.resumedAfterRepair = mode == RESUME;
			if (mode == RESUME || mode == HALT)
				return mode;
			// else fall through and RESTART
		} else {
			if (this.currentToken == TokenNameLBRACE)
				this.ignoreNextOpeningBrace = true;  // already accounted for in recovery token check.
			return RESUME;
		}
	}
		
	// reset internal stacks
	this.astPtr = -1;
	this.astLengthPtr = -1;
	this.expressionPtr = -1;
	this.expressionLengthPtr = -1;
	this.typeAnnotationLengthPtr = -1;
	this.typeAnnotationPtr = -1;
	
	this.identifierPtr = -1;
	this.identifierLengthPtr	= -1;
	this.intPtr = -1;
	
	
	this.dimensions = 0 ;
	this.recoveredStaticInitializerStart = 0;

	this.genericsIdentifiersLengthPtr = -1;
	this.genericsLengthPtr = -1;
	this.genericsPtr = -1;
	
	this.valueLambdaNestDepth = -1;

	this.modifiers = ClassFileConstants.AccDefault;
	this.modifiersSourceStart = -1;

	// if in diet mode, reset the diet counter because we're going to restart outside an initializer.
	if (this.diet) this.dietInt = 0;

	/* attempt to move checkpoint location */
	if (this.unstackedAct != ERROR_ACTION && this.resumedAfterRepair) {
		this.scanner.ungetToken(this.currentToken);  // effectively move recovery checkpoint *backwards*.
	} else {
		if (!moveRecoveryCheckpoint()) return HALT;
	}
	this.resumedAfterRepair = false;

	// only look for headers
	if (this.referenceContext instanceof CompilationUnitDeclaration
		|| this.assistNode != null){
		if(isInsideMethod() &&
			isIndirectlyInsideFieldInitialization() &&
			this.assistNode == null
			){
			prepareForBlockStatements();
			goForBlockStatementsOrCatchHeader();
		} else if((isInsideArrayInitializer()) &&
				isIndirectlyInsideFieldInitialization() &&
				this.assistNode == null){
			prepareForBlockStatements();
			goForBlockStatementsopt();
		} else {
			prepareForHeaders();
			if (this.referenceContext instanceof CompilationUnitDeclaration) {
				CompilationUnitDeclaration unit = (CompilationUnitDeclaration) this.referenceContext;
				if (unit.isModuleInfo()) {
					pushOnElementStack(K_MODULE_INFO_DELIMITER);
				}
			}
			goForHeaders();
			this.diet = true; // passed this point, will not consider method bodies
			this.dietInt = 0;
		}
		return RESTART;
	}
	if (this.referenceContext instanceof AbstractMethodDeclaration
		|| this.referenceContext instanceof TypeDeclaration){

		if (this.currentElement instanceof RecoveredType){
			prepareForHeaders();
			goForHeaders();
		} else {
			prepareForBlockStatements();
			goForBlockStatementsOrCatchHeader();
		}
		return RESTART;
	}
	// does not know how to restart
	return HALT;
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292087
// To be implemented in children viz. CompletionParser that are aware of array initializers
protected boolean isInsideArrayInitializer() {
	return false;
}
public abstract void setAssistIdentifier(char[] assistIdent);
protected int topKnownElementInfo(int owner) {
	return topKnownElementInfo(owner, 0);
}
protected int topKnownElementInfo(int owner, int offSet) {
	int i = this.elementPtr;
	while(i > -1) {
		if((this.elementKindStack[i] & owner) != 0) {
			if(offSet <= 0) return this.elementInfoStack[i];
			offSet--;
		}
		i--;
	}
	return 0;
}
protected int topKnownElementKind(int owner) {
	return topKnownElementKind(owner, 0);
}
protected int topKnownElementKind(int owner, int offSet) {
	int i = this.elementPtr;
	while(i > -1) {
		if((this.elementKindStack[i] & owner) != 0) {
			if(offSet <= 0) return this.elementKindStack[i];
			offSet--;
		}
		i--;
	}
	return 0;
}
protected Object topKnownElementObjectInfo(int owner, int offSet) {
	int i = this.elementPtr;
	while(i > -1) {
		if((this.elementKindStack[i] & owner) != 0) {
			if(offSet <= 0) return this.elementObjectInfoStack[i];
			offSet--;
		}
		i--;
	}
	return null;
}
protected Object topKnownElementObjectInfo(int owner) {
	return topKnownElementObjectInfo(owner, 0);
}
/**
 * If the given ast node is inside an explicit constructor call
 * then wrap it with a fake constructor call.
 * Returns the wrapped completion node or the completion node itself.
 */
protected ASTNode wrapWithExplicitConstructorCallIfNeeded(ASTNode ast) {
	int selector;
	if (ast != null && topKnownElementKind(ASSIST_PARSER) == K_SELECTOR && ast instanceof Expression &&
			((Expression) ast).isTrulyExpression() && 
			(((selector = topKnownElementInfo(ASSIST_PARSER)) == THIS_CONSTRUCTOR) ||
			(selector == SUPER_CONSTRUCTOR))) {
		ExplicitConstructorCall call = new ExplicitConstructorCall(
			(selector == THIS_CONSTRUCTOR) ?
				ExplicitConstructorCall.This :
				ExplicitConstructorCall.Super
		);
		call.arguments = new Expression[] {(Expression)ast};
		call.sourceStart = ast.sourceStart;
		call.sourceEnd = ast.sourceEnd;
		return call;
	} else {
		return ast;
	}
}
}
