/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.eval;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.Util;

/**
 * A parser for code snippets.
 */
public class CodeSnippetParser extends Parser implements EvaluationConstants {
	int codeSnippetStart, codeSnippetEnd;
	boolean hasRecoveredOnExpression;
	int problemCountBeforeRecovery = 0;
	int lastStatement = -1; // end of last top level statement

	EvaluationContext evaluationContext;
/**
 * Creates a new code snippet parser.
 */
public CodeSnippetParser(ProblemReporter problemReporter, EvaluationContext evaluationContext, boolean optimizeStringLiterals, int codeSnippetStart, int codeSnippetEnd) {
	super(problemReporter, optimizeStringLiterals);
	this.codeSnippetStart = codeSnippetStart;
	this.codeSnippetEnd = codeSnippetEnd;
	this.evaluationContext = evaluationContext;
	this.reportOnlyOneSyntaxError = true;
	this.javadocParser.checkDocComment = false;
}
protected void classInstanceCreation(boolean alwaysQualified) {
	// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt

	// ClassBodyopt produces a null item on the astStak if it produces NO class body
	// An empty class body produces a 0 on the length stack.....

	AllocationExpression alloc;
	int length;
	if (((length = this.astLengthStack[this.astLengthPtr--]) == 1)
		&& (this.astStack[this.astPtr] == null)) {
		//NO ClassBody
		this.astPtr--;
		if (alwaysQualified) {
			alloc = new QualifiedAllocationExpression();
		} else {
			alloc = new CodeSnippetAllocationExpression(this.evaluationContext);
		}
		alloc.sourceEnd = this.endPosition; //the position has been stored explicitly

		if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
			this.expressionPtr -= length;
			System.arraycopy(
				this.expressionStack, 
				this.expressionPtr + 1, 
				alloc.arguments = new Expression[length], 
				0, 
				length); 
		}
		alloc.type = getTypeReference(0);
		//the default constructor with the correct number of argument
		//will be created and added by the TC (see createsInternalConstructorWithBinding)
		alloc.sourceStart = this.intStack[this.intPtr--];
		pushOnExpressionStack(alloc);
	} else {
		dispatchDeclarationInto(length);
		TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration) this.astStack[this.astPtr];
		anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
		if (anonymousTypeDeclaration.allocation != null) {
			anonymousTypeDeclaration.allocation.sourceEnd = this.endStatementPosition;
		}		
		this.astPtr--;
		this.astLengthPtr--;

		// mark initializers with local type mark if needed
		markInitializersWithLocalType(anonymousTypeDeclaration);
	}
}
protected void consumeClassDeclaration() {
	super.consumeClassDeclaration();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeClassHeaderName() {
	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
	TypeDeclaration typeDecl;
	if (this.nestedMethod[this.nestedType] == 0) {
		if (this.nestedType != 0) {
			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
			typeDecl.bits |= ASTNode.IsMemberTypeMASK;
		} else {
			typeDecl = new CodeSnippetTypeDeclaration(this.compilationUnit.compilationResult);
		}
	} else {
		// Record that the block has a declaration for local types
		typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
		typeDecl.bits |= ASTNode.IsLocalTypeMASK;
		markEnclosingMemberWithLocalType();
		blockReal();
	}

	//highlight the name of the type
	long pos = this.identifierPositionStack[this.identifierPtr];
	typeDecl.sourceEnd = (int) pos;
	typeDecl.sourceStart = (int) (pos >>> 32);
	typeDecl.name = this.identifierStack[this.identifierPtr--];
	this.identifierLengthPtr--;

	//compute the declaration source too
	typeDecl.declarationSourceStart = this.intStack[this.intPtr--]; 
	this.intPtr--;
	// 'class' and 'interface' push an int position
	typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
	typeDecl.modifiers = this.intStack[this.intPtr--];
	if (typeDecl.modifiersSourceStart >= 0) {
		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
	}
	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;
	}
	// javadoc
	typeDecl.javadoc = this.javadoc;
	this.javadoc = null;
}
protected void consumeEmptyStatement() {
	super.consumeEmptyStatement();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeExpressionStatement() {
	super.consumeExpressionStatement();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeFieldAccess(boolean isSuperAccess) {
	// FieldAccess ::= Primary '.' 'Identifier'
	// FieldAccess ::= 'super' '.' 'Identifier'

	FieldReference fr =
		new CodeSnippetFieldReference(
			this.identifierStack[this.identifierPtr],
			this.identifierPositionStack[this.identifierPtr--],
			this.evaluationContext);
	this.identifierLengthPtr--;
	if (isSuperAccess) {
		//considerates the fieldReference beginning at the 'super' ....	
		fr.sourceStart = this.intStack[this.intPtr--];
		problemReporter().codeSnippetMissingClass(null,0, 0);
		fr.receiver = new CodeSnippetSuperReference(fr.sourceStart, this.endPosition, this.evaluationContext);
		pushOnExpressionStack(fr);
	} else {
		//optimize push/pop
		if ((fr.receiver = this.expressionStack[this.expressionPtr]).isThis()) {
			//fieldreference begins at the this
			fr.sourceStart = fr.receiver.sourceStart;
		}
		this.expressionStack[this.expressionPtr] = fr;
	}
}
protected void consumeInterfaceHeaderName() {
	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
	TypeDeclaration typeDecl;
	if (this.nestedMethod[this.nestedType] == 0) {
		if (this.nestedType != 0) {
			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
			typeDecl.bits |= ASTNode.IsMemberTypeMASK;
		} else {
			typeDecl = new CodeSnippetTypeDeclaration(this.compilationUnit.compilationResult);
		}
	} else {
		// Record that the block has a declaration for local types
		typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
		typeDecl.bits |= ASTNode.IsLocalTypeMASK;
		markEnclosingMemberWithLocalType(); 
		blockReal();
	}

	//highlight the name of the type
	long pos = this.identifierPositionStack[this.identifierPtr];
	typeDecl.sourceEnd = (int) pos;
	typeDecl.sourceStart = (int) (pos >>> 32);
	typeDecl.name = this.identifierStack[this.identifierPtr--];
	this.identifierLengthPtr--;

	//compute the declaration source too
	typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
	this.intPtr--;
	// 'class' and 'interface' push an int position
	typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
	typeDecl.modifiers = this.intStack[this.intPtr--];
	if (typeDecl.modifiersSourceStart >= 0) {
		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
	}
	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
	pushOnAstStack(typeDecl);
	this.listLength = 0; // will be updated when reading super-interfaces
	// recovery
	if (this.currentElement != null){ // is recovering
		this.lastCheckPoint = typeDecl.bodyStart;
		this.currentElement = this.currentElement.add(typeDecl, 0);
		this.lastIgnoredToken = -1;		
	}
	// javadoc
	typeDecl.javadoc = this.javadoc;
	this.javadoc = null;
}
protected void consumeLocalVariableDeclarationStatement() {
	super.consumeLocalVariableDeclarationStatement();
	/* recovery */
	recordLastStatementIfNeeded();
}
/**
 * In case emulating local variables, wrap the (recovered) statements inside a 
 * try statement so as to achieve local state commiting (copy local vars back to fields).
 * The CSToCuMapper could not be used, since it could have interfered with
 * the syntax recovery specific to code snippets.
 */
protected void consumeMethodDeclaration(boolean isNotAbstract) {
	// MethodDeclaration ::= MethodHeader MethodBody
	// AbstractMethodDeclaration ::= MethodHeader ';'

	super.consumeMethodDeclaration(isNotAbstract);
	
	// now we know that we have a method declaration at the top of the ast stack
	MethodDeclaration methodDecl = (MethodDeclaration) this.astStack[this.astPtr];

	// automatically wrap the last statement inside a return statement, if it is an expression
	// support have to be defined at toplevel only
	if (this.isTopLevelType()) {
		int last = methodDecl.statements == null ? -1 : methodDecl.statements.length - 1;
		if (last >= 0 && methodDecl.statements[last] instanceof Expression){
			Expression lastExpression = (Expression) methodDecl.statements[last];
			methodDecl.statements[last] = new CodeSnippetReturnStatement(
											lastExpression, 
											lastExpression.sourceStart, 
											lastExpression.sourceEnd);
		}
	}
	
	int start = methodDecl.bodyStart-1, end = start;
	long position = (start << 32) + end;
	long[] positions = new long[]{position};
	if (this.evaluationContext.localVariableNames != null) {

		int varCount = this.evaluationContext.localVariableNames.length; // n local decls+ try statement

		// generate n local variable declarations: [type] [name] = val$[name];
		Statement[] newStatements = new Statement[varCount+1];
		for (int i = 0; i < varCount; i++){
			char[] trimmedTypeName = this.evaluationContext.localVariableTypeNames[i];
			int nameEnd = CharOperation.indexOf('[', trimmedTypeName);
			if (nameEnd >= 0) {
				trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
			}
			nameEnd = CharOperation.indexOf(' ', trimmedTypeName);
			if (nameEnd >= 0) {
				trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
			}
			TypeReference typeReference = new QualifiedTypeReference(
				CharOperation.splitOn('.', trimmedTypeName),
				positions);
			int dimCount = CharOperation.occurencesOf('[', this.evaluationContext.localVariableTypeNames[i]);
			if (dimCount > 0) {
				typeReference = this.copyDims(typeReference, dimCount);
			}
			NameReference init = new SingleNameReference(
									CharOperation.concat(LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]), position);
			LocalDeclaration declaration = new LocalDeclaration(this.evaluationContext.localVariableNames[i], start, end);
			declaration.initialization = init;
			declaration.type = typeReference;
			declaration.modifiers = this.evaluationContext.localVariableModifiers[i];
			newStatements[i] = declaration;
		}

		// generate try { [snippet] } finally { [save locals to fields] }
		// try block
		TryStatement tryStatement = new TryStatement();
		Block tryBlock = new Block(methodDecl.explicitDeclarations);
		tryBlock.sourceStart = start;
		tryBlock.sourceEnd = end;
		tryBlock.statements = methodDecl.statements; // snippet statements
		tryStatement.tryBlock = tryBlock;
		// finally block
		Block finallyBlock = new Block(0);
		finallyBlock.sourceStart = start;
		finallyBlock.sourceEnd = end;
		finallyBlock.statements = new Statement[varCount];
		for (int i = 0; i < varCount; i++){
			finallyBlock.statements[i] = new Assignment(
				new SingleNameReference(CharOperation.concat(LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]), position),
				new SingleNameReference(this.evaluationContext.localVariableNames[i], position),
				(int) position);
		}
		tryStatement.finallyBlock = finallyBlock;

		newStatements[varCount] = tryStatement;
		methodDecl.statements = newStatements;
	}
}

protected void consumeMethodInvocationName() {
	// MethodInvocation ::= Name '(' ArgumentListopt ')'

	if (this.scanner.startPosition >= this.codeSnippetStart
		&& this.scanner.startPosition <= this.codeSnippetEnd + 1 + Util.LINE_SEPARATOR_CHARS.length // 14838
		&& isTopLevelType()) {
			
		// when the name is only an identifier...we have a message send to "this" (implicit)

		MessageSend m = newMessageSend();
		m.sourceEnd = this.rParenPos;
		m.sourceStart = 
			(int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32); 
		m.selector = this.identifierStack[this.identifierPtr--];
		if (this.identifierLengthStack[this.identifierLengthPtr] == 1) {
			m.receiver = new CodeSnippetThisReference(0,0,this.evaluationContext, true);
			this.identifierLengthPtr--;
		} else {
			this.identifierLengthStack[this.identifierLengthPtr]--;
			m.receiver = getUnspecifiedReference();
			m.sourceStart = m.receiver.sourceStart;		
		}
		pushOnExpressionStack(m);
	} else {
		super.consumeMethodInvocationName();
	}
}

protected void consumeMethodInvocationSuper() {
	// MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'

	MessageSend m = newMessageSend();
	m.sourceStart = this.intStack[this.intPtr--];
	m.sourceEnd = this.rParenPos;
	m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr];
	m.selector = this.identifierStack[this.identifierPtr--];
	this.identifierLengthPtr--;
	m.receiver = new CodeSnippetSuperReference(m.sourceStart, this.endPosition, this.evaluationContext);
	pushOnExpressionStack(m);
}

protected void consumePrimaryNoNewArrayThis() {
	// PrimaryNoNewArray ::= 'this'

	if (this.scanner.startPosition >= this.codeSnippetStart
		&& this.scanner.startPosition <= this.codeSnippetEnd + 1 + Util.LINE_SEPARATOR_CHARS.length // 14838
		&& isTopLevelType()) {
		pushOnExpressionStack(
			new CodeSnippetThisReference(this.intStack[this.intPtr--], this.endPosition, this.evaluationContext, false));
	} else {
		super.consumePrimaryNoNewArrayThis();
	}
}
protected void consumeStatementBreak() {
	super.consumeStatementBreak();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementBreakWithLabel() {
	super.consumeStatementBreakWithLabel();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementCatch() {
	super.consumeStatementCatch();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementContinue() {
	super.consumeStatementContinue();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementContinueWithLabel() {
	super.consumeStatementContinueWithLabel();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementDo() {
	super.consumeStatementDo();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementFor() {
	super.consumeStatementFor();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementIfNoElse() {
	super.consumeStatementIfNoElse();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementIfWithElse() {
	super.consumeStatementIfWithElse();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementLabel() {
	super.consumeStatementLabel();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementReturn() {
	// ReturnStatement ::= 'return' Expressionopt ';'

	// returned value intercepted by code snippet 
	// support have to be defined at toplevel only
	if ((this.hasRecoveredOnExpression
			|| (this.scanner.startPosition >= this.codeSnippetStart && this.scanner.startPosition <= this.codeSnippetEnd+1+Util.LINE_SEPARATOR_CHARS.length /* 14838*/))
		&& this.expressionLengthStack[this.expressionLengthPtr] != 0
		&& isTopLevelType()) {
		this.expressionLengthPtr--;
		Expression expression = this.expressionStack[this.expressionPtr--];
		pushOnAstStack(
			new CodeSnippetReturnStatement(
				expression, 
				expression.sourceStart, 
				expression.sourceEnd));
	} else {
		super.consumeStatementReturn();
	}
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementSwitch() {
	super.consumeStatementSwitch();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementSynchronized() {
	super.consumeStatementSynchronized();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementThrow() {
	super.consumeStatementThrow();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementTry(boolean arg_0) {
	super.consumeStatementTry(arg_0);
	/* recovery */
	recordLastStatementIfNeeded();
}
protected void consumeStatementWhile() {
	super.consumeStatementWhile();
	/* recovery */
	recordLastStatementIfNeeded();
}
protected CompilationUnitDeclaration endParse(int act) {
	if (this.hasRecoveredOnExpression) {
		CompilationResult unitResult = this.compilationUnit.compilationResult;
		if (act != ERROR_ACTION) { // expression recovery worked
			// flush previously recorded problems
			for (int i = 0; i < unitResult.problemCount; i++) {
				unitResult.problems[i] = null; // discard problem
			}
			unitResult.problemCount = 0;
			if (this.referenceContext instanceof AbstractMethodDeclaration) {
				((AbstractMethodDeclaration)this.referenceContext).ignoreFurtherInvestigation = false;
			}
			if (this.referenceContext instanceof CompilationUnitDeclaration) {
				((CompilationUnitDeclaration)this.referenceContext).ignoreFurtherInvestigation = false;
			}

			// consume expresion as a return statement
			consumeStatementReturn();
			int fieldsCount = 
				(this.evaluationContext.localVariableNames == null ? 0 : this.evaluationContext.localVariableNames.length)
				+ (this.evaluationContext.declaringTypeName == null ? 0 : 1);
			if (this.astPtr > (this.diet ? 0 : 2 + fieldsCount)) { 
					// in diet mode, the ast stack was empty when we went for method body
					// otherwise it contained the type, the generated fields for local variables, 
					// the generated field for 'this' and the method
				consumeBlockStatements();
			}
			consumeMethodBody();
			if (!this.diet) {
				consumeMethodDeclaration(true);
				if (fieldsCount > 0) {
					consumeClassBodyDeclarations();
				}
				consumeClassBodyDeclarationsopt();
				consumeClassDeclaration();
				consumeTypeDeclarationsopt();
				consumeCompilationUnit();
			}
			this.lastAct = ACCEPT_ACTION;
		} else {
			// might have more than one error recorded:
			// 1. during regular parse
			// 2. during expression recovery
			// -> must filter out one of them, the earliest one is less accurate
			int maxRegularPos = 0, problemCount = unitResult.problemCount;
			for (int i = 0; i < this.problemCountBeforeRecovery; i++) {
				// skip unmatched bracket problems
				if (unitResult.problems[i].getID() == IProblem.UnmatchedBracket) continue;
				
				int start = unitResult.problems[i].getSourceStart();
				if (start > maxRegularPos && start <= this.codeSnippetEnd) {
					maxRegularPos = start;
				}
			}
			int maxRecoveryPos = 0;
			for (int i = this.problemCountBeforeRecovery; i < problemCount; i++) {
				// skip unmatched bracket problems
				if (unitResult.problems[i].getID() == IProblem.UnmatchedBracket) continue;
				
				int start = unitResult.problems[i].getSourceStart();
				if (start > maxRecoveryPos && start <= this.codeSnippetEnd) {
					maxRecoveryPos = start;
				}
			}
			if (maxRecoveryPos > maxRegularPos) {
				System.arraycopy(unitResult.problems, this.problemCountBeforeRecovery, unitResult.problems, 0, problemCount - this.problemCountBeforeRecovery);
				unitResult.problemCount -= this.problemCountBeforeRecovery;				
			} else {
				unitResult.problemCount -= (problemCount - this.problemCountBeforeRecovery);
			}
			for (int i = unitResult.problemCount; i < problemCount; i++) {
				unitResult.problems[i] = null; // discard problem
			}

		}
	}
	return super.endParse(act);
}
protected NameReference getUnspecifiedReference() {
	/* build a (unspecified) NameReference which may be qualified*/

	if (this.scanner.startPosition >= this.codeSnippetStart 
		&& this.scanner.startPosition <= this.codeSnippetEnd+1+Util.LINE_SEPARATOR_CHARS.length /*14838*/){
		int length;
		NameReference ref;
		if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
			// single variable reference
			ref = 
				new CodeSnippetSingleNameReference(
					this.identifierStack[this.identifierPtr], 
					this.identifierPositionStack[this.identifierPtr--],
					this.evaluationContext); 
		} else {
			//Qualified variable reference
			char[][] tokens = new char[length][];
			this.identifierPtr -= length;
			System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
			long[] positions = new long[length];
			System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
			ref = 
				new CodeSnippetQualifiedNameReference(tokens,
					positions, 
					(int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
					(int) this.identifierPositionStack[this.identifierPtr + length],
					this.evaluationContext); // sourceEnd
		}
		return ref;
	} else {
		return super.getUnspecifiedReference();
	}
}
protected NameReference getUnspecifiedReferenceOptimized() {
	/* build a (unspecified) NameReference which may be qualified
	The optimization occurs for qualified reference while we are
	certain in this case the last item of the qualified name is
	a field access. This optimization is IMPORTANT while it results
	that when a NameReference is build, the type checker should always
	look for that it is not a type reference */

	if (this.scanner.startPosition >= this.codeSnippetStart 
		&& this.scanner.startPosition <= this.codeSnippetEnd+1+Util.LINE_SEPARATOR_CHARS.length /*14838*/){
		int length;
		NameReference ref;
		if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
			// single variable reference
			ref = 
				new CodeSnippetSingleNameReference(
					this.identifierStack[this.identifierPtr], 
					this.identifierPositionStack[this.identifierPtr--],
					this.evaluationContext); 
			ref.bits &= ~ASTNode.RestrictiveFlagMASK;
			ref.bits |= LOCAL | FIELD;
			return ref;
		}

		//Qualified-variable-reference
		//In fact it is variable-reference DOT field-ref , but it would result in a type
		//conflict tha can be only reduce by making a superclass (or inetrface ) between
		//nameReference and FiledReference or putting FieldReference under NameReference
		//or else..........This optimisation is not really relevant so just leave as it is

		char[][] tokens = new char[length][];
		this.identifierPtr -= length;
		System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
		long[] positions = new long[length];
		System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
		ref = new CodeSnippetQualifiedNameReference(
				tokens,
				positions, 
				(int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
				(int) this.identifierPositionStack[this.identifierPtr + length],
				this.evaluationContext); // sourceEnd
		ref.bits &= ~ASTNode.RestrictiveFlagMASK;
		ref.bits |= LOCAL | FIELD;
		return ref;
	} else {
		return super.getUnspecifiedReferenceOptimized();
	}
}
protected void ignoreExpressionAssignment() {
	super.ignoreExpressionAssignment();
	/* recovery */
	recordLastStatementIfNeeded();
}
/**
 * Returns whether we are parsing a top level type or not.
 */
private boolean isTopLevelType() {
	return this.nestedType == (this.diet ? 0 : 1);
}
protected MessageSend newMessageSend() {
	// '(' ArgumentListopt ')'
	// the arguments are on the expression stack

	CodeSnippetMessageSend m = new CodeSnippetMessageSend(this.evaluationContext);
	int length;
	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
		this.expressionPtr -= length;
		System.arraycopy(
			this.expressionStack, 
			this.expressionPtr + 1, 
			m.arguments = new Expression[length], 
			0, 
			length); 
	}
	return m;
}
/**
 * Records the scanner position if we're parsing a top level type.
 */
private void recordLastStatementIfNeeded() {
	if ((isTopLevelType()) && (this.scanner.startPosition <= this.codeSnippetEnd+Util.LINE_SEPARATOR_CHARS.length /*14838*/)) {
		this.lastStatement = this.scanner.startPosition;
	}
}
protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) {
	if (!isDietParse) {
		this.scanner.initialPosition = this.lastStatement;
		this.scanner.eofPosition = this.codeSnippetEnd + 1; // stop after expression 
		oldFirstToken = TokenNameTWIDDLE;//TokenNameREMAINDER; // first token of th expression parse
	}
	super.reportSyntaxErrors(isDietParse, oldFirstToken);
}

/*
 * A syntax error was detected. If a method is being parsed, records the number of errors and
 * attempts to restart from the last statement by going for an expression.
 */
protected boolean resumeOnSyntaxError() {
	if (this.diet || this.hasRecoveredOnExpression) { // no reentering inside expression recovery
		return false;
	}
	
	// record previous error, in case more accurate than potential one in expression recovery
	// e.g. "return foo(a a); 1+3"
	this.problemCountBeforeRecovery = this.compilationUnit.compilationResult.problemCount;

	// reposition for expression parsing
	if (this.lastStatement < 0) {
		this.lastStatement = this.codeSnippetStart; // no statement reduced prior to error point
	}
	this.scanner.initialPosition = this.lastStatement;
	this.scanner.startPosition = this.lastStatement;
	this.scanner.currentPosition = this.lastStatement;
	this.scanner.eofPosition = this.codeSnippetEnd < Integer.MAX_VALUE ? this.codeSnippetEnd + 1 : this.codeSnippetEnd; // stop after expression 
	this.scanner.commentPtr = -1;

	// reset stacks in consistent state
	this.expressionPtr = -1;
	this.identifierPtr = -1;
	this.identifierLengthPtr = -1;

	// go for the expression
	goForExpression();
	this.hasRecoveredOnExpression = true;
	this.hasReportedError = false;
	this.hasError = false;
	return true;
}
}
