/*******************************************************************************
 * Copyright (c) 2000, 2003 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 net.sourceforge.phpdt.internal.compiler;

import net.sourceforge.phpdt.core.compiler.IProblem;
import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;


/*
 * A document element parser extracts structural information
 * from a piece of source, providing detailed source positions info.
 *
 * also see @IDocumentElementRequestor
 *
 * The structural investigation includes:
 * - the package statement
 * - import statements
 * - top-level types: package member, member types (member types of member types...)
 * - fields
 * - methods
 *
 * Any (parsing) problem encountered is also provided.
 */
public class DocumentElementParser extends UnitParser {
	IDocumentElementRequestor requestor;
	private int localIntPtr;
	private int lastFieldEndPosition;
	private int lastFieldBodyEndPosition;	
	private int typeStartPosition;
	private long selectorSourcePositions;
	private int typeDims;
	private int extendsDim;
	private int declarationSourceStart;

	/* int[] stack for storing javadoc positions */
	int[][] intArrayStack;
	int intArrayPtr;
	
//	CompilerOptions options;
	
public DocumentElementParser(
	final IDocumentElementRequestor requestor, 
	IProblemFactory problemFactory,
 	CompilerOptions options) {
	super(new ProblemReporter(
		DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
 		options, 
		problemFactory) {
		public void record(IProblem problem, CompilationResult unitResult) {
			requestor.acceptProblem(problem);
		}
	});
//	false,
//	options.sourceLevel >= CompilerOptions.JDK1_4);
	this.requestor = requestor;
	intArrayStack = new int[30][];
 	this.options = options;
}

/**
 *
 * INTERNAL USE-ONLY
 */
//protected void adjustInterfaceModifiers() {
//	intStack[intPtr - 2] |= AccInterface;
//}
/*
 * Will clear the comment stack when looking
 * for a potential JavaDoc which might contain @deprecated.
 *
 * Additionally, before investigating for @deprecated, retrieve the positions
 * of the JavaDoc comments so as to notify requestor with them.
 */
//public void checkAnnotation() {
//
//	/* persisting javadoc positions */
//	pushOnIntArrayStack(this.getJavaDocPositions());
//	boolean deprecated = false;
//	int lastAnnotationIndex = -1;
//	int commentPtr = scanner.commentPtr;
//
//	//since jdk1.2 look only in the last java doc comment...
//	nextComment : for (lastAnnotationIndex = scanner.commentPtr; lastAnnotationIndex >= 0; lastAnnotationIndex--){
//		//look for @deprecated into the first javadoc comment preceeding the declaration
//		int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
//		// javadoc only (non javadoc comment have negative end positions.)
//		if (modifiersSourceStart != -1 && modifiersSourceStart < commentSourceStart) {
//			continue nextComment;
//		}
//		if (scanner.commentStops[lastAnnotationIndex] < 0) {
//			continue nextComment;
//		}
//		int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1; //stop is one over
//		char[] comment = scanner.source;
//
//		deprecated =
//			checkDeprecation(
//				commentSourceStart,
//				commentSourceEnd,
//				comment);
//		break nextComment;
//	}
//	if (deprecated) {
//		checkAndSetModifiers(AccDeprecated);
//	}
//	// modify the modifier source start to point at the first comment
//	if (commentPtr >= 0) {
//		declarationSourceStart = scanner.commentStarts[0];
//	}
//}
/**
 *
 * INTERNAL USE-ONLY
 */
//protected void consumeClassBodyDeclaration() {
//	// ClassBodyDeclaration ::= Diet Block
//	//push an Initializer
//	//optimize the push/pop
//
//	super.consumeClassBodyDeclaration();
//	Initializer initializer = (Initializer) astStack[astPtr];
//	requestor.acceptInitializer(
//		initializer.declarationSourceStart,
//		initializer.declarationSourceEnd,
//		intArrayStack[intArrayPtr--], 
//		0,
//		modifiersSourceStart, 
//		initializer.block.sourceStart,
//		initializer.block.sourceEnd);
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeClassDeclaration() {
//	super.consumeClassDeclaration();
//	// we know that we have a TypeDeclaration on the top of the astStack
//	if (isLocalDeclaration()) {
//		// we ignore the local variable declarations
//		return;
//	}
//	requestor.exitClass(endStatementPosition, // '}' is the end of the body 
//	 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeClassHeader() {
//	//ClassHeader ::= $empty
//	super.consumeClassHeader();
//	if (isLocalDeclaration()) {
//		// we ignore the local variable declarations
//		intArrayPtr--;
//		return;
//	}
//	TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
//	TypeReference[] superInterfaces = typeDecl.superInterfaces;
//	char[][] interfaceNames = null;
//	int[] interfaceNameStarts = null;
//	int[] interfaceNameEnds = null;
//	if (superInterfaces != null) {
//		int superInterfacesLength = superInterfaces.length;
//		interfaceNames = new char[superInterfacesLength][];
//		interfaceNameStarts = new int[superInterfacesLength];
//		interfaceNameEnds = new int[superInterfacesLength];
//		for (int i = 0; i < superInterfacesLength; i++) {
//			TypeReference superInterface = superInterfaces[i];
//			interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.'); 
//			interfaceNameStarts[i] = superInterface.sourceStart;
//			interfaceNameEnds[i] = superInterface.sourceEnd;
//		}
//	}
//	// flush the comments related to the class header
//	scanner.commentPtr = -1;
//	TypeReference superclass = typeDecl.superclass;
//	if (superclass == null) {
//		requestor.enterClass(
//			typeDecl.declarationSourceStart, 
//			intArrayStack[intArrayPtr--], 
//			typeDecl.modifiers, 
//			typeDecl.modifiersSourceStart, 
//			typeStartPosition, 
//			typeDecl.name, 
//			typeDecl.sourceStart, 
//			typeDecl.sourceEnd, 
//			null, 
//			-1, 
//			-1, 
//			interfaceNames, 
//			interfaceNameStarts, 
//			interfaceNameEnds, 
//			scanner.currentPosition - 1); 
//	} else {
//		requestor.enterClass(
//			typeDecl.declarationSourceStart, 
//			intArrayStack[intArrayPtr--], 
//			typeDecl.modifiers, 
//			typeDecl.modifiersSourceStart, 
//			typeStartPosition, 
//			typeDecl.name, 
//			typeDecl.sourceStart, 
//			typeDecl.sourceEnd, 
//			CharOperation.concatWith(superclass.getTypeName(), '.'), 
//			superclass.sourceStart, 
//			superclass.sourceEnd, 
//			interfaceNames, 
//			interfaceNameStarts, 
//			interfaceNameEnds, 
//			scanner.currentPosition - 1); 
//
//	}
//}
//protected void consumeClassHeaderName() {
//	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
//	TypeDeclaration typeDecl;
//	if (nestedMethod[nestedType] == 0) {
//		if (nestedType != 0) {
//			typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
//		} else {
//			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
//		}
//	} else {
//		// Record that the block has a declaration for local types
//		typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
//		markEnclosingMemberWithLocalType();
//		blockReal();
//	}
//
//	//highlight the name of the type
//	long pos = identifierPositionStack[identifierPtr];
//	typeDecl.sourceEnd = (int) pos;
//	typeDecl.sourceStart = (int) (pos >>> 32);
//	typeDecl.name = identifierStack[identifierPtr--];
//	identifierLengthPtr--;
//
//	//compute the declaration source too
//	// 'class' and 'interface' push an int position
//	typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
//	intPtr--;
//	int declarationSourceStart = intStack[intPtr--];
//	typeDecl.modifiersSourceStart = intStack[intPtr--];
//	typeDecl.modifiers = intStack[intPtr--];
//	if (typeDecl.declarationSourceStart > declarationSourceStart) {
//		typeDecl.declarationSourceStart = declarationSourceStart;
//	}
//	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
//	pushOnAstStack(typeDecl);
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeCompilationUnit() {
//	// CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
//	requestor.exitCompilationUnit(scanner.source.length - 1);
//}
/**
 *
 * INTERNAL USE-ONLY
 */
//protected void consumeConstructorDeclaration() {
//	// ConstructorDeclaration ::= ConstructorHeader ConstructorBody
//	super.consumeConstructorDeclaration();
//	if (isLocalDeclaration()) {
//		// we ignore the local variable declarations
//		return;
//	}
//	ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
//	requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeConstructorHeader() {
//	// ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
//	super.consumeConstructorHeader();
//	if (isLocalDeclaration()) {
//		// we ignore the local variable declarations
//		intArrayPtr--;
//		return;
//	}
//	ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
//	Argument[] arguments = cd.arguments;
//	char[][] argumentTypes = null;
//	char[][] argumentNames = null;
//	int[] argumentTypeStarts = null;
//	int[] argumentTypeEnds = null;
//	int[] argumentNameStarts = null;
//	int[] argumentNameEnds = null;
//	if (arguments != null) {
//		int argumentLength = arguments.length;
//		argumentTypes = new char[argumentLength][];
//		argumentNames = new char[argumentLength][];
//		argumentNameStarts = new int[argumentLength];
//		argumentNameEnds = new int[argumentLength];
//		argumentTypeStarts = new int[argumentLength];
//		argumentTypeEnds = new int[argumentLength];
//		for (int i = 0; i < argumentLength; i++) {
//			Argument argument = arguments[i];
//			TypeReference argumentType = argument.type;
//			argumentTypes[i] = returnTypeName(argumentType);
//			argumentNames[i] = argument.name;
//			argumentNameStarts[i] = argument.sourceStart;
//			argumentNameEnds[i] = argument.sourceEnd;
//			argumentTypeStarts[i] = argumentType.sourceStart;
//			argumentTypeEnds[i] = argumentType.sourceEnd;
//		}
//	}
//	TypeReference[] thrownExceptions = cd.thrownExceptions;
//	char[][] exceptionTypes = null;
//	int[] exceptionTypeStarts = null;
//	int[] exceptionTypeEnds = null;
//	if (thrownExceptions != null) {
//		int thrownExceptionLength = thrownExceptions.length;
//		exceptionTypes = new char[thrownExceptionLength][];
//		exceptionTypeStarts = new int[thrownExceptionLength];
//		exceptionTypeEnds = new int[thrownExceptionLength];
//		for (int i = 0; i < thrownExceptionLength; i++) {
//			TypeReference exception = thrownExceptions[i];
//			exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
//			exceptionTypeStarts[i] = exception.sourceStart;
//			exceptionTypeEnds[i] = exception.sourceEnd;
//		}
//	}
//	requestor
//		.enterConstructor(
//			cd.declarationSourceStart, 
//			intArrayStack[intArrayPtr--], 
//			cd.modifiers,
//			cd.modifiersSourceStart, 
//			cd.selector, 
//			cd.sourceStart, 
//			(int) (selectorSourcePositions & 0xFFFFFFFFL), 
//			// retrieve the source end of the name
//			argumentTypes, 
//			argumentTypeStarts, 
//			argumentTypeEnds, 
//			argumentNames, 
//			argumentNameStarts, 
//			argumentNameEnds, 
//			rParenPos, 
//			// right parenthesis
//			exceptionTypes, 
//			exceptionTypeStarts, 
//			exceptionTypeEnds, 
//			scanner.currentPosition - 1); 
//}
//protected void consumeConstructorHeaderName() {
//	// ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
//	ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
//
//	//name -- this is not really revelant but we do .....
//	cd.selector = identifierStack[identifierPtr];
//	selectorSourcePositions = identifierPositionStack[identifierPtr--];
//	identifierLengthPtr--;
//
//	//modifiers
//	cd.declarationSourceStart = intStack[intPtr--];
//	cd.modifiersSourceStart = intStack[intPtr--];
//	cd.modifiers = intStack[intPtr--];
//
//	//highlight starts at the selector starts
//	cd.sourceStart = (int) (selectorSourcePositions >>> 32);
//	pushOnAstStack(cd);
//
//	cd.sourceEnd = lParenPos;
//	cd.bodyStart = lParenPos + 1;
//}
//protected void consumeDefaultModifiers() {
//	checkAnnotation(); // might update modifiers with AccDeprecated
//	pushOnIntStack(modifiers); // modifiers
//	pushOnIntStack(-1);
//	pushOnIntStack(
//		declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
//	resetModifiers();
//}
//protected void consumeDiet() {
//	// Diet ::= $empty
//	super.consumeDiet();
//	/* persisting javadoc positions
//	 * Will be consume in consumeClassBodyDeclaration
//	 */
//	pushOnIntArrayStack(this.getJavaDocPositions());	
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeEnterCompilationUnit() {
//	// EnterCompilationUnit ::= $empty
//	requestor.enterCompilationUnit();
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeEnterVariable() {
//	// EnterVariable ::= $empty
//	boolean isLocalDeclaration = isLocalDeclaration();
//	if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
//		requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
//	}
//	char[] name = identifierStack[identifierPtr];
//	long namePosition = identifierPositionStack[identifierPtr--];
//	int extendedTypeDimension = intStack[intPtr--];
//
//	AbstractVariableDeclaration declaration;
//	if (nestedMethod[nestedType] != 0) {
//		// create the local variable declarations
//		declaration = 
//			new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
//	} else {
//		// create the field declaration
//		declaration = 
//			new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
//	}
//	identifierLengthPtr--;
//	TypeReference type;
//	int variableIndex = variablesCounter[nestedType];
//	int typeDim = 0;
//	if (variableIndex == 0) {
//		// first variable of the declaration (FieldDeclaration or LocalDeclaration)
//		if (nestedMethod[nestedType] != 0) {
//			// local declaration
//			declaration.declarationSourceStart = intStack[intPtr--];
//			declaration.modifiersSourceStart = intStack[intPtr--];
//			declaration.modifiers = intStack[intPtr--];
//			type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
//			pushOnAstStack(type);
//		} else {
//			// field declaration
//			type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
//			pushOnAstStack(type);
//			declaration.declarationSourceStart = intStack[intPtr--];
//			declaration.modifiersSourceStart = intStack[intPtr--];
//			declaration.modifiers = intStack[intPtr--];
//		}
//	} else {
//		type = (TypeReference) astStack[astPtr - variableIndex];
//		typeDim = type.dimensions();
//		AbstractVariableDeclaration previousVariable = 
//			(AbstractVariableDeclaration) astStack[astPtr]; 
//		declaration.declarationSourceStart = previousVariable.declarationSourceStart;
//		declaration.modifiers = previousVariable.modifiers;
//		declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
//	}
//
//	localIntPtr = intPtr;
//
//	if (extendedTypeDimension == 0) {
//		declaration.type = type;
//	} else {
//		int dimension = typeDim + extendedTypeDimension;
//		//on the identifierLengthStack there is the information about the type....
//		int baseType;
//		if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
//			//it was a baseType
//			declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
//			declaration.type.sourceStart = type.sourceStart;
//			declaration.type.sourceEnd = type.sourceEnd;
//		} else {
//			declaration.type = this.copyDims(type, dimension);
//		}
//	}
//	variablesCounter[nestedType]++;
//	nestedMethod[nestedType]++;
//	pushOnAstStack(declaration);
//
//	int[] javadocPositions = intArrayStack[intArrayPtr];
//	if (!isLocalDeclaration) {
//		requestor
//			.enterField(
//				declaration.declarationSourceStart, 
//				javadocPositions, 
//				declaration.modifiers, 
//				declaration.modifiersSourceStart, 
//				returnTypeName(declaration.type), 
//				type.sourceStart, 
//				type.sourceEnd, 
//				typeDims, 
//				name, 
//				(int) (namePosition >>> 32), 
//				(int) namePosition, 
//				extendedTypeDimension, 
//				extendedTypeDimension == 0 ? -1 : endPosition); 
//	}
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeExitVariableWithInitialization() {
//	// ExitVariableWithInitialization ::= $empty
//	// the scanner is located after the comma or the semi-colon.
//	// we want to include the comma or the semi-colon
//	super.consumeExitVariableWithInitialization();
//	nestedMethod[nestedType]--;	
//	lastFieldEndPosition = scanner.currentPosition - 1;
//	lastFieldBodyEndPosition = 	((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd;
//}
//protected void consumeExitVariableWithoutInitialization() {
//	// ExitVariableWithoutInitialization ::= $empty
//	// do nothing by default
//	super.consumeExitVariableWithoutInitialization();
//	nestedMethod[nestedType]--;	
//	lastFieldEndPosition = scanner.currentPosition - 1;
//	lastFieldBodyEndPosition = scanner.startPosition - 1;
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeFieldDeclaration() {
//	// See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
//	// FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
//	// the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]	
//	int variableIndex = variablesCounter[nestedType];
//	super.consumeFieldDeclaration();
//	intArrayPtr--;
//	if (isLocalDeclaration())
//		return;
//	if (variableIndex != 0) {
//		requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
//	}
//}
//protected void consumeFormalParameter() {
//	// FormalParameter ::= Type VariableDeclaratorId ==> false
//	// FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
//	/*
//	astStack : 
//	identifierStack : type identifier
//	intStack : dim dim
//	 ==>
//	astStack : Argument
//	identifierStack :  
//	intStack :  
//	*/
//
//	identifierLengthPtr--;
//	char[] name = identifierStack[identifierPtr];
//	long namePositions = identifierPositionStack[identifierPtr--];
//	TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
//	intPtr -= 3;
//	Argument arg = 
//		new Argument(
//			name, 
//			namePositions, 
//			type, 
//			intStack[intPtr + 1]); // modifiers
//	pushOnAstStack(arg);
//	intArrayPtr--;
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeInterfaceDeclaration() {
//	super.consumeInterfaceDeclaration();
//	// we know that we have a TypeDeclaration on the top of the astStack
//	if (isLocalDeclaration()) {
//		// we ignore the local variable declarations
//		return;
//	}
//	requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
//	 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeInterfaceHeader() {
//	//InterfaceHeader ::= $empty
//	super.consumeInterfaceHeader();
//	if (isLocalDeclaration()) {
//		// we ignore the local variable declarations
//		intArrayPtr--;
//		return;
//	}
//	TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
//	TypeReference[] superInterfaces = typeDecl.superInterfaces;
//	char[][] interfaceNames = null;
//	int[] interfaceNameStarts = null;
//	int[] interfacenameEnds = null;
//	int superInterfacesLength = 0;
//	if (superInterfaces != null) {
//		superInterfacesLength = superInterfaces.length;
//		interfaceNames = new char[superInterfacesLength][];
//		interfaceNameStarts = new int[superInterfacesLength];
//		interfacenameEnds = new int[superInterfacesLength];
//	}
//	if (superInterfaces != null) {
//		for (int i = 0; i < superInterfacesLength; i++) {
//			TypeReference superInterface = superInterfaces[i];
//			interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.'); 
//			interfaceNameStarts[i] = superInterface.sourceStart;
//			interfacenameEnds[i] = superInterface.sourceEnd;
//		}
//	}
//	// flush the comments related to the interface header
//	scanner.commentPtr = -1;
//	requestor.enterInterface(
//		typeDecl.declarationSourceStart, 
//		intArrayStack[intArrayPtr--], 
//		typeDecl.modifiers, 
//		typeDecl.modifiersSourceStart, 
//		typeStartPosition, 
//		typeDecl.name, 
//		typeDecl.sourceStart, 
//		typeDecl.sourceEnd, 
//		interfaceNames, 
//		interfaceNameStarts, 
//		interfacenameEnds, 
//		scanner.currentPosition - 1); 
//}
//protected void consumeInterfaceHeaderName() {
//	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
//	TypeDeclaration typeDecl;
//	if (nestedMethod[nestedType] == 0) {
//		if (nestedType != 0) {
//			typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
//		} else {
//			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
//		}
//	} else {
//		// Record that the block has a declaration for local types
//		typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
//		markEnclosingMemberWithLocalType();
//		blockReal();
//	}
//
//	//highlight the name of the type
//	long pos = identifierPositionStack[identifierPtr];
//	typeDecl.sourceEnd = (int) pos;
//	typeDecl.sourceStart = (int) (pos >>> 32);
//	typeDecl.name = identifierStack[identifierPtr--];
//	identifierLengthPtr--;
//
//	//compute the declaration source too
//	// 'class' and 'interface' push an int position
//	typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
//	intPtr--;
//	int declarationSourceStart = intStack[intPtr--];
//	typeDecl.modifiersSourceStart = intStack[intPtr--];
//	typeDecl.modifiers = intStack[intPtr--];
//	if (typeDecl.declarationSourceStart > declarationSourceStart) {
//		typeDecl.declarationSourceStart = declarationSourceStart;
//	}
//	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
//	pushOnAstStack(typeDecl);
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeLocalVariableDeclaration() {
//	// See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
//	// FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
//
//	super.consumeLocalVariableDeclaration();
//	intArrayPtr--;
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeMethodDeclaration(boolean isNotAbstract) {
//	// MethodDeclaration ::= MethodHeader MethodBody
//	// AbstractMethodDeclaration ::= MethodHeader ';'
//	super.consumeMethodDeclaration(isNotAbstract);
//	if (isLocalDeclaration()) {
//		// we ignore the local variable declarations
//		return;
//	}
//	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
//	requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeMethodHeader() {
//	// MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
//	super.consumeMethodHeader();
//	if (isLocalDeclaration()) {
//		// we ignore the local variable declarations
//		intArrayPtr--;
//		return;
//	}
//	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
//
//	TypeReference returnType = md.returnType;
//	char[] returnTypeName = returnTypeName(returnType);
//	Argument[] arguments = md.arguments;
//	char[][] argumentTypes = null;
//	char[][] argumentNames = null;
//	int[] argumentTypeStarts = null;
//	int[] argumentTypeEnds = null;
//	int[] argumentNameStarts = null;
//	int[] argumentNameEnds = null;
//	if (arguments != null) {
//		int argumentLength = arguments.length;
//		argumentTypes = new char[argumentLength][];
//		argumentNames = new char[argumentLength][];
//		argumentNameStarts = new int[argumentLength];
//		argumentNameEnds = new int[argumentLength];
//		argumentTypeStarts = new int[argumentLength];
//		argumentTypeEnds = new int[argumentLength];
//		for (int i = 0; i < argumentLength; i++) {
//			Argument argument = arguments[i];
//			TypeReference argumentType = argument.type;
//			argumentTypes[i] = returnTypeName(argumentType);
//			argumentNames[i] = argument.name;
//			argumentNameStarts[i] = argument.sourceStart;
//			argumentNameEnds[i] = argument.sourceEnd;
//			argumentTypeStarts[i] = argumentType.sourceStart;
//			argumentTypeEnds[i] = argumentType.sourceEnd;
//		}
//	}
//	TypeReference[] thrownExceptions = md.thrownExceptions;
//	char[][] exceptionTypes = null;
//	int[] exceptionTypeStarts = null;
//	int[] exceptionTypeEnds = null;
//	if (thrownExceptions != null) {
//		int thrownExceptionLength = thrownExceptions.length;
//		exceptionTypeStarts = new int[thrownExceptionLength];
//		exceptionTypeEnds = new int[thrownExceptionLength];
//		exceptionTypes = new char[thrownExceptionLength][];
//		for (int i = 0; i < thrownExceptionLength; i++) {
//			TypeReference exception = thrownExceptions[i];
//			exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
//			exceptionTypeStarts[i] = exception.sourceStart;
//			exceptionTypeEnds[i] = exception.sourceEnd;
//		}
//	}
//	requestor
//		.enterMethod(
//			md.declarationSourceStart, 
//			intArrayStack[intArrayPtr--], 
//			md.modifiers, 
//			md.modifiersSourceStart, 
//			returnTypeName, 
//			returnType.sourceStart, 
//			returnType.sourceEnd, 
//			typeDims, 
//			md.selector, 
//			md.sourceStart, 
//			(int) (selectorSourcePositions & 0xFFFFFFFFL), 
//			argumentTypes, 
//			argumentTypeStarts, 
//			argumentTypeEnds, 
//			argumentNames, 
//			argumentNameStarts, 
//			argumentNameEnds, 
//			rParenPos, 
//			extendsDim, 
//			extendsDim == 0 ? -1 : endPosition, 
//			exceptionTypes, 
//			exceptionTypeStarts, 
//			exceptionTypeEnds, 
//			scanner.currentPosition - 1); 
//}
//protected void consumeMethodHeaderExtendedDims() {
//	// MethodHeaderExtendedDims ::= Dimsopt
//	// now we update the returnType of the method
//	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
//	int extendedDims = intStack[intPtr--];
//	extendsDim = extendedDims;
//	if (extendedDims != 0) {
//		TypeReference returnType = md.returnType;
//		md.sourceEnd = endPosition;
//		int dims = returnType.dimensions() + extendedDims;
//		int baseType;
//		if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
//			//it was a baseType
//			int sourceStart = returnType.sourceStart;
//			int sourceEnd = returnType.sourceEnd;
//			returnType = TypeReference.baseTypeReference(-baseType, dims);
//			returnType.sourceStart = sourceStart;
//			returnType.sourceEnd = sourceEnd;
//			md.returnType = returnType;
//		} else {
//			md.returnType = this.copyDims(md.returnType, dims);
//		}
//		if (currentToken == TokenNameLBRACE) {
//			md.bodyStart = endPosition + 1;
//		}
//	}
//}
//protected void consumeMethodHeaderName() {
//	// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
//	MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
//
//	//name
//	md.selector = identifierStack[identifierPtr];
//	selectorSourcePositions = identifierPositionStack[identifierPtr--];
//	identifierLengthPtr--;
//	//type
//	md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
//	//modifiers
//	md.declarationSourceStart = intStack[intPtr--];
//	md.modifiersSourceStart = intStack[intPtr--];
//	md.modifiers = intStack[intPtr--];
//
//	//highlight starts at selector start
//	md.sourceStart = (int) (selectorSourcePositions >>> 32);
//	pushOnAstStack(md);
//	md.bodyStart = scanner.currentPosition-1;
//}
//protected void consumeModifiers() {
//	checkAnnotation(); // might update modifiers with AccDeprecated
//	pushOnIntStack(modifiers); // modifiers
//	pushOnIntStack(modifiersSourceStart);
//	pushOnIntStack(
//		declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
//	resetModifiers();
//}
/**
 *
 * INTERNAL USE-ONLY
 */
//protected void consumePackageDeclarationName() {
//	/* persisting javadoc positions */
//	pushOnIntArrayStack(this.getJavaDocPositions());
//
//	super.consumePackageDeclarationName();
//	ImportReference importReference = compilationUnit.currentPackage;
//
//	requestor.acceptPackage(
//		importReference.declarationSourceStart, 
//		importReference.declarationSourceEnd, 
//		intArrayStack[intArrayPtr--], 
//		CharOperation.concatWith(importReference.getImportName(), '.'),
//		importReference.sourceStart);
//}
//protected void consumePushModifiers() {
//	checkAnnotation(); // might update modifiers with AccDeprecated
//	pushOnIntStack(modifiers); // modifiers
//	if (modifiersSourceStart < 0) {
//		pushOnIntStack(-1);
//		pushOnIntStack(
//			declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
//	} else {
//		pushOnIntStack(modifiersSourceStart);
//		pushOnIntStack(
//			declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
//	}
//	resetModifiers();
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeSingleTypeImportDeclarationName() {
//	// SingleTypeImportDeclarationName ::= 'import' Name
//
//	/* persisting javadoc positions */
//	pushOnIntArrayStack(this.getJavaDocPositions());
//
//	super.consumeSingleTypeImportDeclarationName();
//	ImportReference importReference = (ImportReference) astStack[astPtr];
//	requestor.acceptImport(
//		importReference.declarationSourceStart, 
//		importReference.declarationSourceEnd,
//		intArrayStack[intArrayPtr--],
//		CharOperation.concatWith(importReference.getImportName(), '.'),
//		importReference.sourceStart,
//		false);
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeStaticInitializer() {
//	// StaticInitializer ::=  StaticOnly Block
//	//push an Initializer
//	//optimize the push/pop
//	super.consumeStaticInitializer();
//	Initializer initializer = (Initializer) astStack[astPtr];
//	requestor.acceptInitializer(
//		initializer.declarationSourceStart,
//		initializer.declarationSourceEnd,
//		intArrayStack[intArrayPtr--],
//		AccStatic, 
//		intStack[intPtr--], 
//		initializer.block.sourceStart,
//		initializer.declarationSourceEnd);
//}
//protected void consumeStaticOnly() {
//	// StaticOnly ::= 'static'
//	checkAnnotation(); // might update declaration source start
//	pushOnIntStack(modifiersSourceStart);
//	pushOnIntStack(
//		declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
//	jumpOverMethodBody();
//	nestedMethod[nestedType]++;
//	resetModifiers();
//}
///**
// *
// * INTERNAL USE-ONLY
// */
//protected void consumeTypeImportOnDemandDeclarationName() {
//	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
//
//	/* persisting javadoc positions */
//	pushOnIntArrayStack(this.getJavaDocPositions());
//
//	super.consumeTypeImportOnDemandDeclarationName();
//	ImportReference importReference = (ImportReference) astStack[astPtr];
//	requestor.acceptImport(
//		importReference.declarationSourceStart, 
//		importReference.declarationSourceEnd,
//		intArrayStack[intArrayPtr--],
//		CharOperation.concatWith(importReference.getImportName(), '.'), 
//		importReference.sourceStart,
//		true);
//}
public CompilationUnitDeclaration endParse(int act) {
	if (scanner.recordLineSeparator) {
		requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
	}
	return super.endParse(act);
}
/*
 * Flush annotations defined prior to a given positions.
 *
 * Note: annotations are stacked in syntactical order
 *
 * Either answer given <position>, or the end position of a comment line 
 * immediately following the <position> (same line)
 *
 * e.g.
 * void foo(){
 * } // end of method foo
 */
 
//public int flushAnnotationsDefinedPriorTo(int position) {
//
//	return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
//}
//protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
//This variable is a type reference and dim will be its dimensions*/
//
//	int length;
//	TypeReference ref;
//	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
//		// single variable reference
//		if (dim == 0) {
//			ref = 
//				new SingleTypeReference(
//					identifierStack[identifierPtr], 
//					identifierPositionStack[identifierPtr--]); 
//		} else {
//			ref = 
//				new ArrayTypeReference(
//					identifierStack[identifierPtr], 
//					dim, 
//					identifierPositionStack[identifierPtr--]); 
//			ref.sourceEnd = endPosition;
//		}
//	} else {
//		if (length < 0) { //flag for precompiled type reference on base types
//			ref = TypeReference.baseTypeReference(-length, dim);
//			ref.sourceStart = intStack[intPtr--];
//			if (dim == 0) {
//				ref.sourceEnd = intStack[intPtr--];
//			} else {
//				intPtr--;
//				ref.sourceEnd = endPosition;
//			}
//		} else { //Qualified variable reference
//			char[][] tokens = new char[length][];
//			identifierPtr -= length;
//			long[] positions = new long[length];
//			System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
//			System.arraycopy(
//				identifierPositionStack, 
//				identifierPtr + 1, 
//				positions, 
//				0, 
//				length); 
//			if (dim == 0) {
//				ref = new QualifiedTypeReference(tokens, positions);
//			} else {
//				ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
//				ref.sourceEnd = endPosition;
//			}
//		}
//	};
//	return ref;
//}
public void initialize() {
	//positionning the parser for a new compilation unit
	//avoiding stack reallocation and all that....
	super.initialize(false);
	intArrayPtr = -1;
}
/**
 *
 * INTERNAL USE-ONLY
 */
//private boolean isLocalDeclaration() {
//	int nestedDepth = nestedType;
//	while (nestedDepth >= 0) {
//		if (nestedMethod[nestedDepth] != 0) {
//			return true;
//		}
//		nestedDepth--;
//	}
//	return false;
//}
/*
 * Investigate one entire unit.
 */
public void parseCompilationUnit(ICompilationUnit unit) {
	char[] regionSource = unit.getContents();
	try {
		initialize();
		goForCompilationUnit();
		referenceContext =
			compilationUnit = 
				compilationUnit = 
					new CompilationUnitDeclaration(
						problemReporter(), 
						new CompilationResult(unit, 0, 0, 10), //this.options.maxProblemsPerUnit), 
						regionSource.length); 
		scanner.resetTo(0, regionSource.length);
		scanner.setSource(regionSource);
		parse();
	} catch (AbortCompilation ex) {
	}
}
/*
 * Investigate one constructor declaration.
 */
//public void parseConstructor(char[] regionSource) {
//	try {
//		initialize();
//		goForClassBodyDeclarations();
//		referenceContext = 
//			compilationUnit = 
//				compilationUnit = 
//					new CompilationUnitDeclaration(
//						problemReporter(), 
//						new CompilationResult(regionSource, 0, 0, 10), //this.options.maxProblemsPerUnit), 
//						regionSource.length); 
//		scanner.resetTo(0, regionSource.length);
//		scanner.setSource(regionSource);
//		parse();
//	} catch (AbortCompilation ex) {
//	}
//}
/*
 * Investigate one field declaration statement (might have multiple declarations in it).
 */
//public void parseField(char[] regionSource) {
//	try {
//		initialize();
//		goForFieldDeclaration();
//		referenceContext = 
//			compilationUnit = 
//				compilationUnit = 
//					new CompilationUnitDeclaration(
//						problemReporter(), 
//						new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
//						regionSource.length); 
//		scanner.resetTo(0, regionSource.length);
//		scanner.setSource(regionSource);
//		parse();
//	} catch (AbortCompilation ex) {
//	}
//
//}
///*
// * Investigate one import statement declaration.
// */
//public void parseImport(char[] regionSource) {
//	try {
//		initialize();
//		goForImportDeclaration();
//		referenceContext = 
//			compilationUnit = 
//				compilationUnit = 
//					new CompilationUnitDeclaration(
//						problemReporter(), 
//						new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
//						regionSource.length); 
//		scanner.resetTo(0, regionSource.length);
//		scanner.setSource(regionSource);
//		parse();
//	} catch (AbortCompilation ex) {
//	}
//
//}
///*
// * Investigate one initializer declaration.
// * regionSource need to content exactly an initializer declaration.
// * e.g: static { i = 4; }
// * { name = "test"; }
// */
//public void parseInitializer(char[] regionSource) {
//	try {
//		initialize();
//		goForInitializer();
//		referenceContext = 
//			compilationUnit = 
//				compilationUnit = 
//					new CompilationUnitDeclaration(
//						problemReporter(), 
//						new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
//						regionSource.length); 
//		scanner.resetTo(0, regionSource.length);
//		scanner.setSource(regionSource);
//		parse();
//	} catch (AbortCompilation ex) {
//	}
//
//}
///*
// * Investigate one method declaration.
// */
//public void parseMethod(char[] regionSource) {
//	try {
//		initialize();
//		goForGenericMethodDeclaration();
//		referenceContext = 
//			compilationUnit = 
//				compilationUnit = 
//					new CompilationUnitDeclaration(
//						problemReporter(), 
//						new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
//						regionSource.length); 
//		scanner.resetTo(0, regionSource.length);
//		scanner.setSource(regionSource);
//		parse();
//	} catch (AbortCompilation ex) {
//	}
//
//}
///*
// * Investigate one package statement declaration.
// */
//public void parsePackage(char[] regionSource) {
//	try {
//		initialize();
//		goForPackageDeclaration();
//		referenceContext = 
//			compilationUnit = 
//				compilationUnit = 
//					new CompilationUnitDeclaration(
//						problemReporter(), 
//						new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
//						regionSource.length); 
//		scanner.resetTo(0, regionSource.length);
//		scanner.setSource(regionSource);
//		parse();
//	} catch (AbortCompilation ex) {
//	}
//
//}
///*
// * Investigate one type declaration, its fields, methods and member types.
// */
//public void parseType(char[] regionSource) {
//	try {
//		initialize();
//		goForTypeDeclaration();
//		referenceContext = 
//			compilationUnit = 
//				compilationUnit = 
//					new CompilationUnitDeclaration(
//						problemReporter(), 
//						new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
//						regionSource.length); 
//		scanner.resetTo(0, regionSource.length);
//		scanner.setSource(regionSource);
//		parse();
//	} catch (AbortCompilation ex) {
//	}
//
//}
/**
 * Returns this parser's problem reporter initialized with its reference context.
 * Also it is assumed that a problem is going to be reported, so initializes
 * the compilation result's line positions.
 */
public ProblemReporter problemReporter() {
	problemReporter.referenceContext = referenceContext;
	return problemReporter;
}
protected void pushOnIntArrayStack(int[] positions) {

	try {
		intArrayStack[++intArrayPtr] = positions;
	} catch (IndexOutOfBoundsException e) {
		//intPtr is correct 
		int oldStackLength = intArrayStack.length;
		int oldStack[][] = intArrayStack;
		intArrayStack = new int[oldStackLength + StackIncrement][];
		System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
		intArrayStack[intArrayPtr] = positions;
	}
}
//protected void resetModifiers() {
//	super.resetModifiers();
//	declarationSourceStart = -1;
//}
/*
 * Syntax error was detected. Will attempt to perform some recovery action in order
 * to resume to the regular parse loop.
 */
protected boolean resumeOnSyntaxError() {
	return false;
}
/*
 * Answer a char array representation of the type name formatted like:
 * - type name + dimensions
 * Example:
 * "A[][]".toCharArray()
 * "java.lang.String".toCharArray()
 */
//private char[] returnTypeName(TypeReference type) {
//	int dimension = type.dimensions();
//	if (dimension != 0) {
//		char[] dimensionsArray = new char[dimension * 2];
//		for (int i = 0; i < dimension; i++) {
//			dimensionsArray[i*2] = '[';
//			dimensionsArray[(i*2) + 1] = ']';
//		}
//		return CharOperation.concat(
//			CharOperation.concatWith(type.getTypeName(), '.'), 
//			dimensionsArray); 
//	}
//	return CharOperation.concatWith(type.getTypeName(), '.');
//}
//public String toString() {
//	StringBuffer buffer = new StringBuffer();
//	buffer.append("intArrayPtr = " + intArrayPtr + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
//	buffer.append(super.toString());
//	return buffer.toString();
//}
///**
// * INTERNAL USE ONLY
// */
//protected TypeReference typeReference(
//	int dim,
//	int localIdentifierPtr, 
//	int localIdentifierLengthPtr) {
//	/* build a Reference on a variable that may be qualified or not
//	 * This variable is a type reference and dim will be its dimensions.
//	 * We don't have any side effect on the stacks' pointers.
//	 */
//
//	int length;
//	TypeReference ref;
//	if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
//		// single variable reference
//		if (dim == 0) {
//			ref = 
//				new SingleTypeReference(
//					identifierStack[localIdentifierPtr], 
//					identifierPositionStack[localIdentifierPtr--]); 
//		} else {
//			ref = 
//				new ArrayTypeReference(
//					identifierStack[localIdentifierPtr], 
//					dim, 
//					identifierPositionStack[localIdentifierPtr--]); 
//			ref.sourceEnd = endPosition;				
//		}
//	} else {
//		if (length < 0) { //flag for precompiled type reference on base types
//			ref = TypeReference.baseTypeReference(-length, dim);
//			ref.sourceStart = intStack[localIntPtr--];
//			if (dim == 0) {
//				ref.sourceEnd = intStack[localIntPtr--];
//			} else {
//				localIntPtr--;
//				ref.sourceEnd = endPosition;
//			}
//		} else { //Qualified variable reference
//			char[][] tokens = new char[length][];
//			localIdentifierPtr -= length;
//			long[] positions = new long[length];
//			System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
//			System.arraycopy(
//				identifierPositionStack, 
//				localIdentifierPtr + 1, 
//				positions, 
//				0, 
//				length); 
//			if (dim == 0)
//				ref = new QualifiedTypeReference(tokens, positions);
//			else
//				ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
//		}
//	};
//	return ref;
//}
}