--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.wst.jsdt.core.Signature;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchConstants;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.AssistParser;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.Engine;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionNodeFound;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionOnImportReference;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionOnPackageReference;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionOnQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionOnSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionParser;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ProgramElement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.env.ISourceType;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalFunctionBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MemberTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.wst.jsdt.internal.compiler.parser.SourceTypeConverter;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.core.SearchableEnvironment;
+import org.eclipse.wst.jsdt.internal.core.SelectionRequestor;
+import org.eclipse.wst.jsdt.internal.core.SourceType;
+import org.eclipse.wst.jsdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.wst.jsdt.internal.core.util.ASTNodeFinder;
+
+/**
+ * The selection engine is intended to infer the nature of a selected name in some
+ * source code. This name can be qualified.
+ *
+ * Selection is resolving context using a name environment (no need to search), assuming
+ * the source where selection occurred is correct and will not perform any completion
+ * attempt. If this was the desired behavior, a call to the CompletionEngine should be
+ * performed instead.
+ */
+public final class SelectionEngine extends Engine implements ISearchRequestor {
+
+ public static boolean DEBUG = false;
+ public static boolean PERF = false;
+
+ SelectionParser parser;
+ ISelectionRequestor requestor;
+
+ boolean acceptedAnswer;
+
+ private int actualSelectionStart;
+ private int actualSelectionEnd;
+ private char[] selectedIdentifier;
+
+ private char[][][] acceptedClasses;
+ private int[] acceptedClassesModifiers;
+ private char[][][] acceptedInterfaces;
+ private int[] acceptedInterfacesModifiers;
+ private char[][][] acceptedEnums;
+ private int[] acceptedEnumsModifiers;
+ private char[][][] acceptedAnnotations;
+ private int[] acceptedAnnotationsModifiers;
+ int acceptedClassesCount;
+ int acceptedInterfacesCount;
+ int acceptedEnumsCount;
+ int acceptedAnnotationsCount;
+
+ boolean noProposal = true;
+ CategorizedProblem problem = null;
+
+ /**
+ * The SelectionEngine is responsible for computing the selected object.
+ *
+ * It requires a searchable name environment, which supports some
+ * specific search APIs, and a requestor to feed back the results to a UI.
+ *
+ * @param nameEnvironment org.eclipse.wst.jsdt.internal.core.SearchableEnvironment
+ * used to resolve type/package references and search for types/packages
+ * based on partial names.
+ *
+ * @param requestor org.eclipse.wst.jsdt.internal.codeassist.ISelectionRequestor
+ * since the engine might produce answers of various forms, the engine
+ * is associated with a requestor able to accept all possible completions.
+ *
+ * @param settings java.util.Map
+ * set of options used to configure the code assist engine.
+ */
+ public SelectionEngine(
+ SearchableEnvironment nameEnvironment,
+ ISelectionRequestor requestor,
+ Map settings) {
+
+ super(settings);
+
+ this.requestor = requestor;
+ this.nameEnvironment = nameEnvironment;
+
+ ProblemReporter problemReporter =
+ new ProblemReporter(
+ DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+ this.compilerOptions,
+ new DefaultProblemFactory(Locale.getDefault())) {
+
+ public CategorizedProblem createProblem(
+ char[] fileName,
+ int problemId,
+ String[] problemArguments,
+ String[] messageArguments,
+ int severity,
+ int problemStartPosition,
+ int problemEndPosition,
+ int lineNumber,
+ int columnNumber) {
+ CategorizedProblem pb = super.createProblem(
+ fileName,
+ problemId,
+ problemArguments,
+ messageArguments,
+ severity,
+ problemStartPosition,
+ problemEndPosition,
+ lineNumber,
+ columnNumber);
+ if (SelectionEngine.this.problem == null && pb.isError() && (pb.getID() & IProblem.Syntax) == 0) {
+ SelectionEngine.this.problem = pb;
+ }
+
+ return pb;
+ }
+ };
+ this.lookupEnvironment =
+ new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
+ this.parser = new SelectionParser(problemReporter);
+ }
+
+ public void acceptType(char[] packageName, char[] fileName, char[] simpleTypeName, char[][] enclosingTypeNames, int modifiers, AccessRestriction accessRestriction) {
+ char[] typeName = enclosingTypeNames == null ?
+ simpleTypeName :
+ CharOperation.concat(
+ CharOperation.concatWith(enclosingTypeNames, '.'),
+ simpleTypeName,
+ '.');
+
+ if (CharOperation.equals(simpleTypeName, this.selectedIdentifier)) {
+ char[] flatEnclosingTypeNames =
+ enclosingTypeNames == null || enclosingTypeNames.length == 0 ?
+ null :
+ CharOperation.concatWith(enclosingTypeNames, '.');
+ if (mustQualifyType(packageName, simpleTypeName, flatEnclosingTypeNames, modifiers)) {
+ int length = 0;
+ int kind = 0;
+ switch (kind) {
+ default:
+ char[][] acceptedClass = new char[3][];
+ acceptedClass[0] = packageName;
+ acceptedClass[1] = typeName;
+ acceptedClass[2] = fileName;
+
+ if (this.acceptedClasses == null) {
+ this.acceptedClasses = new char[10][][];
+ this.acceptedClassesModifiers = new int[10];
+ this.acceptedClassesCount = 0;
+ }
+ length = this.acceptedClasses.length;
+ if (length == this.acceptedClassesCount) {
+ int newLength = (length + 1) * 2;
+ System.arraycopy(this.acceptedClasses, 0, this.acceptedClasses = new char[newLength][][], 0, length);
+ System.arraycopy(this.acceptedClassesModifiers, 0, this.acceptedClassesModifiers = new int[newLength], 0, length);
+ }
+ this.acceptedClassesModifiers[this.acceptedClassesCount] = modifiers;
+ this.acceptedClasses[this.acceptedClassesCount++] = acceptedClass;
+ break;
+ }
+ } else {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ packageName,
+ fileName,
+ typeName,
+ modifiers,
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ this.acceptedAnswer = true;
+ }
+ }
+ }
+
+ public void acceptBinding(char[] packageName, char[] filename, char[] simpleTypeName, int bindingType, int modifiers, AccessRestriction accessRestriction) {
+ char[] typeName = simpleTypeName;
+
+ if (CharOperation.equals(simpleTypeName, this.selectedIdentifier)) {
+ char[] flatEnclosingTypeNames = null;
+ if (mustQualifyType(packageName, simpleTypeName, flatEnclosingTypeNames, modifiers)) {
+ int length = 0;
+ int kind = 0;
+ switch (kind) {
+ default:
+ char[][] acceptedClass = new char[2][];
+ acceptedClass[0] = packageName;
+ acceptedClass[1] = typeName;
+
+ if (this.acceptedClasses == null) {
+ this.acceptedClasses = new char[10][][];
+ this.acceptedClassesModifiers = new int[10];
+ this.acceptedClassesCount = 0;
+ }
+ length = this.acceptedClasses.length;
+ if (length == this.acceptedClassesCount) {
+ int newLength = (length + 1) * 2;
+ System.arraycopy(this.acceptedClasses, 0, this.acceptedClasses = new char[newLength][][], 0, length);
+ System.arraycopy(this.acceptedClassesModifiers, 0, this.acceptedClassesModifiers = new int[newLength], 0, length);
+ }
+ this.acceptedClassesModifiers[this.acceptedClassesCount] = modifiers;
+ this.acceptedClasses[this.acceptedClassesCount++] = acceptedClass;
+ break;
+ }
+ } else {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ packageName,
+ filename,
+ typeName,
+ modifiers,
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ this.acceptedAnswer = true;
+ }
+ }
+ }
+
+ /**
+ * One result of the search consists of a new package.
+ * @param packageName char[]
+ *
+ * NOTE - All package names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * The default package is represented by an empty array.
+ */
+ public void acceptPackage(char[] packageName) {
+ // implementation of interface method
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.codeassist.ISearchRequestor#acceptConstructor(
+ * int, char[], char[][], char[][], java.lang.String, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction)
+ */
+ public void acceptConstructor(int modifiers, char[] typeName,
+ char[][] parameterTypes,
+ char[][] parameterNames, String path,
+ AccessRestriction access) {
+
+ // do nothing
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.codeassist.ISearchRequestor#acceptFunction(char[], char[][], char[][], char[], char[], char[], char[], int, java.lang.String)
+ */
+ public void acceptFunction(char[] signature, char[][] parameterFullyQualifedTypeNames,
+ char[][] parameterNames, char[] returnQualification, char[] returnSimpleName,
+ char[] declaringQualification, char[] declaringSimpleName, int modifiers, String path) {
+
+ //do nothing
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.codeassist.ISearchRequestor#acceptVariable(char[], char[], char[], char[], char[], int, java.lang.String)
+ */
+ public void acceptVariable(char[] signature,
+ char[] typeQualification, char[] typeSimpleName,
+ char[] declaringQualification, char[] declaringSimpleName,
+ int modifiers, String path) {
+
+ //do nothing
+ }
+
+ private void acceptQualifiedTypes() {
+ if (this.acceptedClasses != null) {
+ this.acceptedAnswer = true;
+ for (int i = 0; i < this.acceptedClassesCount; i++) {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ this.acceptedClasses[i][0],
+ this.acceptedClasses[i][2],
+ this.acceptedClasses[i][1],
+ this.acceptedClassesModifiers[i],
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedClasses = null;
+ this.acceptedClassesModifiers = null;
+ this.acceptedClassesCount = 0;
+ }
+ if (this.acceptedInterfaces != null) {
+ this.acceptedAnswer = true;
+ for (int i = 0; i < this.acceptedInterfacesCount; i++) {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ this.acceptedInterfaces[i][0],
+ null,
+ this.acceptedInterfaces[i][1],
+ this.acceptedInterfacesModifiers[i],
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedInterfaces = null;
+ this.acceptedInterfacesModifiers = null;
+ this.acceptedInterfacesCount = 0;
+ }
+ if (this.acceptedAnnotations != null) {
+ this.acceptedAnswer = true;
+ for (int i = 0; i < this.acceptedAnnotationsCount; i++) {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ this.acceptedAnnotations[i][0],
+ null,
+ this.acceptedAnnotations[i][1],
+ this.acceptedAnnotationsModifiers[i],
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedAnnotations = null;
+ this.acceptedAnnotationsModifiers = null;
+ this.acceptedAnnotationsCount = 0;
+ }
+ if (this.acceptedEnums != null) {
+ this.acceptedAnswer = true;
+ for (int i = 0; i < this.acceptedEnumsCount; i++) {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ this.acceptedEnums[i][0],
+ null,
+ this.acceptedEnums[i][1],
+ this.acceptedEnumsModifiers[i],
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedEnums = null;
+ this.acceptedEnumsModifiers = null;
+ this.acceptedEnumsCount = 0;
+ }
+ }
+
+ private boolean checkSelection(
+ char[] source,
+ int selectionStart,
+ int selectionEnd) {
+
+ Scanner scanner = new Scanner();
+ scanner.setSource(source);
+
+ int lastIdentifierStart = -1;
+ int lastIdentifierEnd = -1;
+ char[] lastIdentifier = null;
+ int token;
+
+ if (selectionStart > selectionEnd) {
+
+ // compute end position of the selection
+ int end = selectionEnd + 1 == source.length ? selectionEnd : selectionEnd + 1;
+ // compute start position of current line
+ int currentPosition = selectionStart - 1;
+ int nextCharacterPosition = selectionStart;
+ char currentCharacter = ' ';
+ boolean brokeLoop = false;
+ try {
+ lineLoop: while (currentPosition > 0) {
+
+ if (source[currentPosition] == '\\' && source[currentPosition + 1] == 'u') {
+ int pos = currentPosition + 2;
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ while (source[pos] == 'u') {
+ pos++;
+ }
+ int endOfUnicode = pos + 3;
+ if (end < endOfUnicode) {
+ if (endOfUnicode < source.length) {
+ end = endOfUnicode;
+ } else {
+ return false; // not enough characters to decode an unicode
+ }
+ }
+
+ if ((c1 = ScannerHelper.getNumericValue(source[pos++])) > 15
+ || c1 < 0
+ || (c2 = ScannerHelper.getNumericValue(source[pos++])) > 15
+ || c2 < 0
+ || (c3 = ScannerHelper.getNumericValue(source[pos++])) > 15
+ || c3 < 0
+ || (c4 = ScannerHelper.getNumericValue(source[pos++])) > 15
+ || c4 < 0) {
+ return false;
+ } else {
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ nextCharacterPosition = pos;
+ }
+ } else {
+ currentCharacter = source[currentPosition];
+ nextCharacterPosition = currentPosition + 1;
+ }
+
+ switch (currentCharacter) {
+ case '\r':
+ case '\n':
+ case '/':
+ case '"':
+ case '\'':
+ brokeLoop = true;
+ break lineLoop;
+ }
+ currentPosition--;
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return false;
+ }
+ if (!brokeLoop)
+ nextCharacterPosition = currentPosition;
+
+ // compute start and end of the last token
+ scanner.resetTo(nextCharacterPosition, end);
+ do {
+ try {
+ token = scanner.getNextToken();
+ } catch (InvalidInputException e) {
+ return false;
+ }
+ switch (token) {
+ case TerminalTokens.TokenNamethis:
+ case TerminalTokens.TokenNamesuper:
+ case TerminalTokens.TokenNameIdentifier:
+ if (scanner.startPosition <= selectionStart && selectionStart <= scanner.currentPosition) {
+ if (scanner.currentPosition == scanner.eofPosition) {
+ int temp = scanner.eofPosition;
+ scanner.eofPosition = scanner.source.length;
+ while (scanner.getNextCharAsJavaIdentifierPart()) {/*empty*/
+ }
+ scanner.eofPosition = temp;
+ }
+ lastIdentifierStart = scanner.startPosition;
+ lastIdentifierEnd = scanner.currentPosition - 1;
+ lastIdentifier = scanner.getCurrentTokenSource();
+ }
+ break;
+ }
+ } while (token != TerminalTokens.TokenNameEOF);
+ } else {
+ scanner.resetTo(selectionStart, selectionEnd);
+
+ boolean expectingIdentifier = true;
+ try {
+ do {
+ token = scanner.getNextToken();
+
+ switch (token) {
+ case TerminalTokens.TokenNamethis:
+ case TerminalTokens.TokenNamesuper:
+ case TerminalTokens.TokenNameIdentifier:
+ if (!expectingIdentifier)
+ return false;
+ lastIdentifier = scanner.getCurrentTokenSource();
+ lastIdentifierStart = scanner.startPosition;
+ lastIdentifierEnd = scanner.currentPosition - 1;
+ if (lastIdentifierEnd > selectionEnd) {
+ lastIdentifierEnd = selectionEnd;
+ lastIdentifier = CharOperation.subarray(lastIdentifier, 0, lastIdentifierEnd - lastIdentifierStart + 1);
+ }
+
+ expectingIdentifier = false;
+ break;
+ case TerminalTokens.TokenNameDOT:
+ if (expectingIdentifier)
+ return false;
+ expectingIdentifier = true;
+ break;
+ case TerminalTokens.TokenNameEOF:
+ if (expectingIdentifier)
+ return false;
+ break;
+ case TerminalTokens.TokenNameLESS:
+ if (!checkTypeArgument(scanner))
+ return false;
+ break;
+ default:
+ return false;
+ }
+ } while (token != TerminalTokens.TokenNameEOF);
+ } catch (InvalidInputException e) {
+ return false;
+ }
+ }
+ if (lastIdentifierStart >= 0) {
+ this.actualSelectionStart = lastIdentifierStart;
+ this.actualSelectionEnd = lastIdentifierEnd;
+ this.selectedIdentifier = lastIdentifier;
+ return true;
+ }
+ return false;
+ }
+
+ private boolean checkTypeArgument(Scanner scanner) throws InvalidInputException {
+ int depth = 1;
+ int token;
+ StringBuffer buffer = new StringBuffer();
+ do {
+ token = scanner.getNextToken();
+
+ switch (token) {
+ case TerminalTokens.TokenNameLESS:
+ depth++;
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+ case TerminalTokens.TokenNameGREATER:
+ depth--;
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+ case TerminalTokens.TokenNameRIGHT_SHIFT:
+ depth -= 2;
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT:
+ depth -= 3;
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+ case TerminalTokens.TokenNameextends:
+ case TerminalTokens.TokenNamesuper:
+ buffer.append(' ');
+ buffer.append(scanner.getCurrentTokenSource());
+ buffer.append(' ');
+ break;
+ case TerminalTokens.TokenNameCOMMA:
+ if (depth == 1) {
+ int length = buffer.length();
+ char[] typeRef = new char[length];
+ buffer.getChars(0, length, typeRef, 0);
+ try {
+ Signature.createTypeSignature(typeRef, true);
+ buffer = new StringBuffer();
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+ break;
+ default:
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+
+ }
+ if (depth < 0) {
+ return false;
+ }
+ } while (depth != 0 && token != TerminalTokens.TokenNameEOF);
+
+ if (depth == 0) {
+ int length = buffer.length() - 1;
+ char[] typeRef = new char[length];
+ buffer.getChars(0, length, typeRef, 0);
+ try {
+ Signature.createTypeSignature(typeRef, true);
+ return true;
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ public AssistParser getParser() {
+ return this.parser;
+ }
+
+ /*
+ * Returns whether the given binding is a local/anonymous reference binding, or if its declaring class is
+ * local.
+ */
+ private boolean isLocal(ReferenceBinding binding) {
+ if (!(binding instanceof SourceTypeBinding))
+ return false;
+ if (binding instanceof LocalTypeBinding)
+ return true;
+ if (binding instanceof MemberTypeBinding) {
+ return isLocal(((MemberTypeBinding) binding).enclosingType);
+ }
+ return false;
+ }
+
+ /**
+ * Ask the engine to compute the selection at the specified position
+ * of the given compilation unit.
+
+ * @param sourceUnit org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit
+ * the source of the current compilation unit.
+ *
+ * @param selectionSourceStart int
+ * @param selectionSourceEnd int
+ * a range in the source where the selection is.
+ */
+ public void select(
+ ICompilationUnit sourceUnit,
+ int selectionSourceStart,
+ int selectionSourceEnd) {
+
+ char[] source = sourceUnit.getContents();
+
+ if (DEBUG) {
+ System.out.print("SELECTION IN "); //$NON-NLS-1$
+ System.out.print(sourceUnit.getFileName());
+ System.out.print(" FROM "); //$NON-NLS-1$
+ System.out.print(selectionSourceStart);
+ System.out.print(" TO "); //$NON-NLS-1$
+ System.out.println(selectionSourceEnd);
+ System.out.println("SELECTION - Source :"); //$NON-NLS-1$
+ System.out.println(source);
+ }
+ if (!checkSelection(source, selectionSourceStart, selectionSourceEnd)) {
+ return;
+ }
+ if (DEBUG) {
+ System.out.print("SELECTION - Checked : \""); //$NON-NLS-1$
+ System.out.print(new String(source, actualSelectionStart, actualSelectionEnd - actualSelectionStart + 1));
+ System.out.println('"');
+ }
+ try {
+ this.acceptedAnswer = false;
+ CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ CompilationUnitDeclaration parsedUnit =
+ this.parser.dietParse(sourceUnit, result, this.actualSelectionStart, this.actualSelectionEnd);
+
+ if (parsedUnit != null) {
+ if (DEBUG) {
+ System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
+ System.out.println(parsedUnit.toString());
+ }
+
+ // check for inferred types declared with their names in the selection
+ this.parser.inferTypes(parsedUnit, this.compilerOptions);
+ for (int i = 0; i < parsedUnit.numberInferredTypes; i++) {
+ if (parsedUnit.inferredTypes[i] != null && parsedUnit.inferredTypes[i].isDefinition() && parsedUnit.inferredTypes[i].getNameStart() <= selectionSourceEnd && selectionSourceStart <= parsedUnit.inferredTypes[i].getNameStart() + parsedUnit.inferredTypes[i].getName().length) {
+ this.requestor.acceptType(CharOperation.NO_CHAR, sourceUnit.getFileName(), parsedUnit.inferredTypes[i].getName(), 0, parsedUnit.inferredTypes[i].isDefinition(), CharOperation.NO_CHAR, parsedUnit.inferredTypes[i].sourceStart, parsedUnit.inferredTypes[i].sourceEnd);
+ }
+ }
+ // scan the package & import statements first
+ if (parsedUnit.currentPackage instanceof SelectionOnPackageReference) {
+ char[][] tokens =
+ ((SelectionOnPackageReference) parsedUnit.currentPackage).tokens;
+ this.noProposal = false;
+ this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
+ return;
+ }
+ ImportReference[] imports = parsedUnit.imports;
+ if (imports != null) {
+ for (int i = 0, length = imports.length; i < length; i++) {
+ ImportReference importReference = imports[i];
+ if (importReference instanceof SelectionOnImportReference) {
+ char[][] tokens = ((SelectionOnImportReference) importReference).tokens;
+ this.noProposal = false;
+ this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
+ this.nameEnvironment.findTypes(CharOperation.concatWith(tokens, '.'), false, false, IJavaScriptSearchConstants.TYPE, this);
+
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+ if ((this.unitScope = parsedUnit.scope) != null) {
+ int tokenCount = tokens.length;
+ char[] lastToken = tokens[tokenCount - 1];
+ char[][] qualifierTokens = CharOperation.subarray(tokens, 0, tokenCount - 1);
+
+ if (qualifierTokens != null && qualifierTokens.length > 0) {
+ Binding binding = this.unitScope.getTypeOrPackage(qualifierTokens);
+ if (binding != null && binding instanceof ReferenceBinding) {
+ ReferenceBinding ref = (ReferenceBinding) binding;
+ selectMemberTypeFromImport(parsedUnit, lastToken, ref);
+ }
+ }
+ }
+
+ // accept qualified types only if no unqualified type was accepted
+ if (!this.acceptedAnswer) {
+ acceptQualifiedTypes();
+ if (!this.acceptedAnswer) {
+ this.nameEnvironment.findTypes(this.selectedIdentifier, false, false, IJavaScriptSearchConstants.TYPE, this);
+ // try with simple type name
+ if (!this.acceptedAnswer) {
+ acceptQualifiedTypes();
+ }
+ }
+ }
+ if (this.noProposal && this.problem != null) {
+ this.requestor.acceptError(this.problem);
+ }
+ return;
+ }
+ }
+ }
+ if (parsedUnit.statements != null || parsedUnit.isPackageInfo()) {
+ if (selectDeclaration(parsedUnit))
+ return;
+ try {
+ /* We must build bindings to be able to resolve a reference (might not
+ * require completing), however this may itself cause SelectionNodeFound
+ * to be thrown */
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/, true);
+ if ((this.unitScope = parsedUnit.scope) != null) {
+ this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
+ parsedUnit.scope.faultInTypes();
+ ASTNode node = null;
+ if (parsedUnit.types != null)
+ node = parseBlockStatements(parsedUnit, selectionSourceStart);
+ if (DEBUG) {
+ System.out.println("SELECTION - AST :"); //$NON-NLS-1$
+ System.out.println(parsedUnit.toString());
+ }
+ parsedUnit.resolve();
+ if (node != null) {
+ selectLocalDeclaration(node);
+ }
+ }
+ } catch (SelectionNodeFound e) {
+ if (e.binding != null) {
+ if (DEBUG) {
+ System.out.println("SELECTION - Selection binding:"); //$NON-NLS-1$
+ System.out.println(e.binding.toString());
+ }
+ // if null then we found a problem in the selection node
+ selectFrom(e.binding, parsedUnit, e.isDeclaration);
+ }
+ }
+ }
+ }
+ // only reaches here if no selection could be derived from the parsed tree
+ // thus use the selected source and perform a textual type search
+ if (!this.acceptedAnswer) {
+ this.nameEnvironment.findTypes(this.selectedIdentifier, false, false, IJavaScriptSearchConstants.TYPE, this);
+
+ // accept qualified types only if no unqualified type was accepted
+ if (!this.acceptedAnswer) {
+ acceptQualifiedTypes();
+ }
+ }
+ if (this.noProposal && this.problem != null) {
+ this.requestor.acceptError(this.problem);
+ }
+ } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
+ if (DEBUG) {
+ System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+ if (DEBUG) {
+ System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } finally {
+ reset();
+ }
+ }
+
+ private void selectMemberTypeFromImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref) {
+ int fieldLength = lastToken.length;
+ ReferenceBinding[] memberTypes = ref.memberTypes();
+ next: for (int j = 0; j < memberTypes.length; j++) {
+ ReferenceBinding memberType = memberTypes[j];
+
+ if (fieldLength > memberType.sourceName.length)
+ continue next;
+
+ if (!CharOperation.equals(lastToken, memberType.sourceName, true))
+ continue next;
+
+ this.selectFrom(memberType, parsedUnit, false);
+ }
+ }
+
+ private void selectFrom(Binding binding, CompilationUnitDeclaration parsedUnit, boolean isDeclaration) {
+ if (binding instanceof ReferenceBinding) {
+ ReferenceBinding typeBinding = (ReferenceBinding) binding;
+ if (typeBinding instanceof ProblemReferenceBinding) {
+ typeBinding = typeBinding.closestMatch();
+ }
+ if (typeBinding == null)
+ return;
+ if (isLocal(typeBinding) && this.requestor instanceof SelectionRequestor) {
+ this.noProposal = false;
+ ((SelectionRequestor) this.requestor).acceptLocalType(typeBinding);
+ } else {
+ this.noProposal = false;
+
+ this.requestor.acceptType(
+ typeBinding.qualifiedPackageName(),
+ typeBinding.getFileName(),
+ typeBinding.qualifiedSourceName(),
+ typeBinding.modifiers,
+ false,
+ typeBinding.computeUniqueKey(),
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedAnswer = true;
+ } else if (binding instanceof MethodBinding) {
+ MethodBinding methodBinding = (MethodBinding) binding;
+ this.noProposal = false;
+
+ boolean isValuesOrValueOf = false;
+
+ if (!isValuesOrValueOf) {
+ TypeBinding[] parameterTypes = methodBinding.original().parameters;
+ int length = parameterTypes.length;
+ char[][] parameterPackageNames = new char[length][];
+ char[][] parameterTypeNames = new char[length][];
+ String[] parameterSignatures = new String[length];
+ for (int i = 0; i < length; i++) {
+ parameterPackageNames[i] = parameterTypes[i].qualifiedPackageName();
+ parameterTypeNames[i] = parameterTypes[i].qualifiedSourceName();
+ parameterSignatures[i] = new String(getSignature(parameterTypes[i])).replace('/', '.');
+ }
+
+ char[][] typeParameterNames = new char[length][];
+ char[][][] typeParameterBoundNames = new char[length][][];
+
+ ReferenceBinding declaringClass = methodBinding.declaringClass;
+ if (((methodBinding instanceof LocalFunctionBinding || isLocal(declaringClass))
+ && this.requestor instanceof SelectionRequestor)
+ || declaringClass.qualifiedSourceName() == null) {
+ ((SelectionRequestor) this.requestor).acceptLocalMethod(methodBinding);
+ } else {
+ this.requestor.acceptMethod(
+ /*declaringClass.qualifiedPackageName()*/CharOperation.NO_CHAR,
+ declaringClass.getFileName(),
+ declaringClass.qualifiedSourceName(),
+ declaringClass.enclosingType() == null ? null : new String(getSignature(declaringClass.enclosingType())),
+ methodBinding.isConstructor()
+ ? declaringClass.sourceName()
+ : methodBinding.selector,
+ parameterPackageNames,
+ parameterTypeNames,
+ parameterSignatures,
+ typeParameterNames,
+ typeParameterBoundNames,
+ methodBinding.isConstructor(),
+ isDeclaration,
+ methodBinding.computeUniqueKey(),
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ }
+ this.acceptedAnswer = true;
+ } else if (binding instanceof FieldBinding) {
+ FieldBinding fieldBinding = (FieldBinding) binding;
+ ReferenceBinding declaringClass = fieldBinding.declaringClass;
+ if (declaringClass != null) { // arraylength
+ this.noProposal = false;
+ if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) {
+ ((SelectionRequestor) this.requestor).acceptLocalField(fieldBinding);
+ } else {
+ this.requestor.acceptField(
+ declaringClass.qualifiedPackageName(),
+ declaringClass.getFileName(),
+ declaringClass.qualifiedSourceName(),
+ fieldBinding.name,
+ false,
+ fieldBinding.computeUniqueKey(),
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedAnswer = true;
+ }
+ } else if (binding instanceof LocalVariableBinding) {
+ this.noProposal = false;
+ if (this.requestor instanceof SelectionRequestor) {
+ ((SelectionRequestor) this.requestor).acceptLocalVariable((LocalVariableBinding) binding);
+ this.acceptedAnswer = true;
+ } else {
+ // open on the type of the variable
+ selectFrom(((LocalVariableBinding) binding).type, parsedUnit, false);
+ }
+ } else if (binding instanceof ArrayBinding) {
+ selectFrom(((ArrayBinding) binding).leafComponentType, parsedUnit, false);
+ // open on the type of the array
+ } else if (binding instanceof PackageBinding) {
+ PackageBinding packageBinding = (PackageBinding) binding;
+ this.noProposal = false;
+ this.requestor.acceptPackage(packageBinding.readableName());
+ this.acceptedAnswer = true;
+ } else if (binding instanceof BaseTypeBinding) {
+ this.acceptedAnswer = true;
+ }
+ }
+
+ /*
+ * Checks if a local declaration got selected in this method/initializer/field.
+ */
+ private void selectLocalDeclaration(ASTNode node) {
+ // the selected identifier is not identical to the parser one (equals but not identical),
+ // for traversing the parse tree, the parser assist identifier is necessary for identitiy checks
+ final char[] assistIdentifier = this.getParser().assistIdentifier();
+ if (assistIdentifier == null)
+ return;
+
+ class Visitor extends ASTVisitor {
+ public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
+ if (constructorDeclaration.getName() == assistIdentifier) {
+ if (constructorDeclaration.getBinding() != null) {
+ throw new SelectionNodeFound(constructorDeclaration.getBinding());
+ } else {
+ if (constructorDeclaration.getScope() != null) {
+ throw new SelectionNodeFound(new MethodBinding(constructorDeclaration.modifiers, constructorDeclaration.getName(), null, null, constructorDeclaration.getScope().referenceType().binding));
+ }
+ }
+ }
+ return true;
+ }
+
+ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+ if (fieldDeclaration.name == assistIdentifier) {
+ throw new SelectionNodeFound(fieldDeclaration.binding);
+ }
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+ if (localTypeDeclaration.name == assistIdentifier) {
+ throw new SelectionNodeFound(localTypeDeclaration.binding);
+ }
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+ if (memberTypeDeclaration.name == assistIdentifier) {
+ throw new SelectionNodeFound(memberTypeDeclaration.binding);
+ }
+ return true;
+ }
+
+ public boolean visit(MethodDeclaration methodDeclaration, Scope scope) {
+ if (methodDeclaration.getName() == assistIdentifier) {
+ if (methodDeclaration.getBinding() != null) {
+ throw new SelectionNodeFound(methodDeclaration.getBinding());
+ } else {
+ if (methodDeclaration.getScope() != null) {
+ throw new SelectionNodeFound(new MethodBinding(methodDeclaration.modifiers, methodDeclaration.getName(), null, null, methodDeclaration.getScope().referenceType().binding));
+ }
+ }
+ }
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
+ if (typeDeclaration.name == assistIdentifier) {
+ throw new SelectionNodeFound(typeDeclaration.binding);
+ }
+ return true;
+ }
+ }
+
+ if (node instanceof AbstractMethodDeclaration) {
+ ((AbstractMethodDeclaration) node).traverse(new Visitor(), (ClassScope) null);
+ } else {
+ ((FieldDeclaration) node).traverse(new Visitor(), (MethodScope) null);
+ }
+ }
+
+ /**
+ * Asks the engine to compute the selection of the given type
+ * from the source type.
+ *
+ * @param sourceType org.eclipse.wst.jsdt.internal.compiler.env.ISourceType
+ * a source form of the current type in which code assist is invoked.
+ *
+ * @param typeName char[]
+ * a type name which is to be resolved in the context of a compilation unit.
+ * NOTE: the type name is supposed to be correctly reduced (no whitespaces, no unicodes left)
+ *
+ * @param topLevelTypes SourceTypeElementInfo[]
+ * a source form of the top level types of the compilation unit in which code assist is invoked.
+
+ * @param searchInEnvironment
+ * if <code>true</code> and no selection could be found in context then search type in environment.
+ */
+ public void selectType(ISourceType sourceType, char[] typeName, SourceTypeElementInfo[] topLevelTypes, boolean searchInEnvironment) {
+ try {
+ this.acceptedAnswer = false;
+
+ // only the type erasure are returned by IType.resolvedType(...)
+ if (CharOperation.indexOf('<', typeName) != -1) {
+ char[] typeSig = Signature.createCharArrayTypeSignature(typeName, false/*not resolved*/);
+ typeName = Signature.toCharArray(typeSig);
+ }
+
+ // find the outer most type
+ ISourceType outerType = sourceType;
+ ISourceType parent = sourceType.getEnclosingType();
+ while (parent != null) {
+ outerType = parent;
+ parent = parent.getEnclosingType();
+ }
+ // compute parse tree for this most outer type
+ CompilationResult result = new CompilationResult(outerType.getFileName(), outerType.getPackageName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ if (!(sourceType instanceof SourceTypeElementInfo))
+ return;
+ SourceType typeHandle = (SourceType) ((SourceTypeElementInfo) sourceType).getHandle();
+ int flags = SourceTypeConverter.FIELD_AND_METHOD | SourceTypeConverter.MEMBER_TYPE;
+ if (typeHandle.isAnonymous() || typeHandle.isLocal())
+ flags |= SourceTypeConverter.LOCAL_TYPE;
+ CompilationUnitDeclaration parsedUnit =
+ SourceTypeConverter.buildCompilationUnit(
+ topLevelTypes,
+ flags,
+ this.parser.problemReporter(),
+ result);
+
+ if (parsedUnit != null && parsedUnit.types != null) {
+ if (DEBUG) {
+ System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
+ System.out.println(parsedUnit.toString());
+ }
+ // find the type declaration that corresponds to the original source type
+ TypeDeclaration typeDecl = new ASTNodeFinder(parsedUnit).findType(typeHandle);
+
+ if (typeDecl != null) {
+
+ // add fake field with the type we're looking for
+ // note: since we didn't ask for fields above, there is no field defined yet
+ FieldDeclaration field = new FieldDeclaration();
+ int dot;
+ if ((dot = CharOperation.lastIndexOf('.', typeName)) == -1) {
+ this.selectedIdentifier = typeName;
+ field.type = new SelectionOnSingleTypeReference(typeName, -1);
+ // position not used
+ } else {
+ char[][] previousIdentifiers = CharOperation.splitOn('.', typeName, 0, dot);
+ char[] selectionIdentifier =
+ CharOperation.subarray(typeName, dot + 1, typeName.length);
+ this.selectedIdentifier = selectionIdentifier;
+ field.type =
+ new SelectionOnQualifiedTypeReference(
+ previousIdentifiers,
+ selectionIdentifier,
+ new long[previousIdentifiers.length + 1]);
+ }
+ field.name = "<fakeField>".toCharArray(); //$NON-NLS-1$
+ typeDecl.fields = new FieldDeclaration[] { field };
+
+ // build bindings
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+ if ((this.unitScope = parsedUnit.scope) != null) {
+ try {
+ // build fields
+ // note: this builds fields only in the parsed unit (the buildFieldsAndMethods flag is not passed along)
+ this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
+
+ // resolve
+ parsedUnit.scope.faultInTypes();
+ parsedUnit.resolve();
+ } catch (SelectionNodeFound e) {
+ if (e.binding != null) {
+ if (DEBUG) {
+ System.out.println("SELECTION - Selection binding :"); //$NON-NLS-1$
+ System.out.println(e.binding.toString());
+ }
+ // if null then we found a problem in the selection node
+ selectFrom(e.binding, parsedUnit, e.isDeclaration);
+ }
+ }
+ }
+ }
+ }
+ // only reaches here if no selection could be derived from the parsed tree
+ // thus use the selected source and perform a textual type search
+ if (!this.acceptedAnswer && searchInEnvironment) {
+ if (this.selectedIdentifier != null) {
+ this.nameEnvironment.findTypes(typeName, false, false, IJavaScriptSearchConstants.TYPE, this);
+
+ // accept qualified types only if no unqualified type was accepted
+ if (!this.acceptedAnswer) {
+ acceptQualifiedTypes();
+ }
+ }
+ }
+ if (this.noProposal && this.problem != null) {
+ this.requestor.acceptError(this.problem);
+ }
+ } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+ } finally {
+ reset();
+ }
+ }
+
+ // Check if a declaration got selected in this unit
+ private boolean selectDeclaration(CompilationUnitDeclaration compilationUnit) {
+
+ // the selected identifier is not identical to the parser one (equals but not identical),
+ // for traversing the parse tree, the parser assist identifier is necessary for identity checks
+ char[] assistIdentifier = this.getParser().assistIdentifier();
+ if (assistIdentifier == null)
+ return false;
+
+ ImportReference currentPackage = compilationUnit.currentPackage;
+ char[] packageName = currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(currentPackage.tokens, '.');
+ // iterate over the types
+ TypeDeclaration[] types = compilationUnit.types;
+ for (int i = 0, length = types == null ? 0 : types.length; i < length; i++) {
+ if (selectDeclaration(types[i], assistIdentifier, packageName))
+ return true;
+ }
+ ProgramElement[] statements = compilationUnit.statements;
+ for (int i = 0, length = statements == null ? 0 : statements.length; i < length; i++) {
+ if (statements[i] instanceof FieldDeclaration)
+ {
+ FieldDeclaration field = (FieldDeclaration) statements[i];
+
+ if (field.name == assistIdentifier) {
+ char[] qualifiedSourceName = null;
+
+ this.requestor.acceptField(
+ packageName,
+ compilationUnit.getFileName(),
+ qualifiedSourceName,
+ field.name,
+ true,
+ field.binding != null ? field.binding.computeUniqueKey() : null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+ }
+ else if (statements[i] instanceof AbstractMethodDeclaration)
+ {
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) statements[i];
+
+ if (method.getName() == assistIdentifier) {
+ char[] qualifiedSourceName = compilationUnit.getFileName();
+
+ this.requestor.acceptMethod(
+ packageName,
+ compilationUnit.getFileName(),
+ qualifiedSourceName,
+ null, // SelectionRequestor does not need of declaring type signature for method declaration
+ method.getName(),
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, null,
+ method.isConstructor(),
+ true,
+ method.hasBinding() ? method.getBinding().computeUniqueKey() : null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+
+ }
+
+ }
+ return false;
+ }
+
+ // Check if a declaration got selected in this type
+ private boolean selectDeclaration(TypeDeclaration typeDeclaration, char[] assistIdentifier, char[] packageName) {
+
+ if (typeDeclaration.name == assistIdentifier) {
+ char[] qualifiedSourceName = null;
+
+ TypeDeclaration enclosingType = typeDeclaration;
+ while (enclosingType != null) {
+ qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
+ enclosingType = enclosingType.enclosingType;
+ }
+ char[] uniqueKey = typeDeclaration.binding != null ? typeDeclaration.binding.computeUniqueKey() : null;
+
+ this.requestor.acceptType(
+ packageName,
+ null,
+ qualifiedSourceName,
+ typeDeclaration.modifiers,
+ true,
+ uniqueKey,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+ TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
+ for (int i = 0, length = memberTypes == null ? 0 : memberTypes.length; i < length; i++) {
+ if (selectDeclaration(memberTypes[i], assistIdentifier, packageName))
+ return true;
+ }
+ FieldDeclaration[] fields = typeDeclaration.fields;
+ for (int i = 0, length = fields == null ? 0 : fields.length; i < length; i++) {
+ if (fields[i].name == assistIdentifier) {
+ char[] qualifiedSourceName = null;
+
+ TypeDeclaration enclosingType = typeDeclaration;
+ while (enclosingType != null) {
+ qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
+ enclosingType = enclosingType.enclosingType;
+ }
+ FieldDeclaration field = fields[i];
+ this.requestor.acceptField(
+ packageName,
+ null,
+ qualifiedSourceName,
+ field.name,
+ true,
+ field.binding != null ? field.binding.computeUniqueKey() : null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+ }
+ AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+ for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++) {
+ AbstractMethodDeclaration method = methods[i];
+
+ if (method.getName() == assistIdentifier) {
+ char[] qualifiedSourceName = null;
+
+ TypeDeclaration enclosingType = typeDeclaration;
+ while (enclosingType != null) {
+ qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
+ enclosingType = enclosingType.enclosingType;
+ }
+
+ this.requestor.acceptMethod(
+ packageName,
+ null,
+ qualifiedSourceName,
+ null, // SelectionRequestor does not need of declaring type signature for method declaration
+ method.getName(),
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of type parameters name for method declaration
+ null, // SelectionRequestor does not need of type parameters bounds for method declaration
+ method.isConstructor(),
+ true,
+ method.hasBinding() ? method.getBinding().computeUniqueKey() : null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
+ public CompilationUnitDeclaration doParse(ICompilationUnit unit, AccessRestriction accessRestriction) {
+ CompilationResult unitResult =
+ new CompilationResult(unit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ try {
+ Parser localParser = new Parser(this.parser.problemReporter(), this.compilerOptions.parseLiteralExpressionsAsConstants);
+
+ CompilationUnitDeclaration parsedUnit = localParser.parse(unit, unitResult);
+ localParser.inferTypes(parsedUnit, this.compilerOptions);
+ return parsedUnit;
+ } catch (AbortCompilationUnit e) {
+ throw e; // want to abort enclosing request to compile
+ }
+
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Etienne Pfister <epfister@hsr.ch> bug 224333
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.parser;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.PerformanceStats;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.wst.jsdt.core.JavaScriptCore;
+import org.eclipse.wst.jsdt.core.ast.IDoStatement;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.core.infer.IInferEngine;
+import org.eclipse.wst.jsdt.core.infer.IInferEngineExtension;
+import org.eclipse.wst.jsdt.core.infer.InferOptions;
+import org.eclipse.wst.jsdt.core.infer.InferrenceManager;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AND_AND_Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Assignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Block;
+import org.eclipse.wst.jsdt.internal.compiler.ast.BreakStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CaseStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CombinedBinaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompoundAssignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConditionalExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ContinueStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.DebuggerStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.DoStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.DoubleLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.EmptyExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.EmptyStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FalseLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForInStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.IfStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteralMinValue;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LabeledStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ListExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.NameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.OR_OR_Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectGetterSetterField;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteralField;
+import org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.wst.jsdt.internal.compiler.ast.PostfixExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.PrefixExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ProgramElement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Reference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.RegExLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Statement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SuperReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThrowStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TrueLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UnaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UndefinedLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.WhileStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.WithStatement;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.wst.jsdt.internal.compiler.parser.diagnose.DiagnoseParser;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.wst.jsdt.internal.compiler.util.Messages;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+public class Parser implements ParserBasicInformation, TerminalTokens, OperatorIds, TypeIds {
+
+ private static final String PERFORMANCE__INFER_TYPES = "org.eclipse.wst.jsdt.core/perf/Parser/inferTypes"; //$NON-NLS-1$
+ private static final boolean REPORT_PERFORMANCE__INFER_TYPES = Boolean.valueOf(Platform.getDebugOption("org.eclipse.wst.jsdt.core/perfReport/Parser/inferTypes")).booleanValue(); //$NON-NLS-1$
+
+ public static final boolean DO_DIET_PARSE = false;
+
+ protected static final int THIS_CALL = ExplicitConstructorCall.This;
+
+ public static char asb[] = null;
+ public static char asr[] = null;
+ //ast stack
+ protected final static int AstStackIncrement = 100;
+ public static char base_action[] = null;
+ public static final int BracketKinds = 3;
+
+ public static short check_table[] = null;
+ public static final int CurlyBracket = 2;
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_AUTOMATON = false;
+ private static final String EOF_TOKEN = "$eof"; //$NON-NLS-1$
+ private static final String ERROR_TOKEN = "$error"; //$NON-NLS-1$
+ //expression stack
+ protected final static int ExpressionStackIncrement = 100;
+
+ protected final static int GenericsStackIncrement = 10;
+
+ private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
+ public static char in_symb[] = null;
+ private static final String INVALID_CHARACTER = "Invalid Character"; //$NON-NLS-1$
+ public static char lhs[] = null;
+
+ public static String name[] = null;
+ public static char nasb[] = null;
+ public static char nasr[] = null;
+ public static char non_terminal_index[] = null;
+ private final static String READABLE_NAMES_FILE = "readableNames"; //$NON-NLS-1$
+ private final static String READABLE_NAMES_FILE_NAME =
+ "org.eclipse.wst.jsdt.internal.compiler.parser." + READABLE_NAMES_FILE; //$NON-NLS-1$
+ public static String readableName[] = null;
+
+ public static byte rhs[] = null;
+
+ public static int[] reverse_index = null;
+ public static char[] recovery_templates_index = null;
+ public static char[] recovery_templates = null;
+ public static char[] statements_recovery_filter = null;
+ public static byte[] state_flags = null;
+
+ public static long rules_compliance[] = null;
+
+ public static final int RoundBracket = 0;
+
+ public static byte scope_la[] = null;
+ public static char scope_lhs[] = null;
+
+ public static char scope_prefix[] = null;
+ public static char scope_rhs[] = null;
+ public static char scope_state[] = null;
+
+ public static char scope_state_set[] = null;
+ public static char scope_suffix[] = null;
+ public static final int SquareBracket = 1;
+
+ //internal data for the automat
+ protected final static int StackIncrement = 255;
+
+ public static char term_action[] = null;
+ public static byte term_check[] = null;
+
+ public static char terminal_index[] = null;
+
+ private static final String UNEXPECTED_EOF = "Unexpected End Of File"; //$NON-NLS-1$
+ public static boolean VERBOSE_RECOVERY = false;
+
+ static boolean optionalSemicolonState[] = null;
+
+ protected int astLengthPtr;
+ protected int[] astLengthStack;
+ protected int astPtr;
+ protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
+ public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
+ protected RecoveredElement currentElement;
+ public int currentToken;
+ protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
+ protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
+ protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
+ protected int endStatementPosition;
+ protected int expressionLengthPtr;
+ protected int[] expressionLengthStack;
+ protected int expressionPtr;
+ protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
+ public int firstToken; // handle for multiple parsing goals
+
+ // generics management
+ protected int genericsIdentifiersLengthPtr;
+ protected int[] genericsIdentifiersLengthStack = new int[GenericsStackIncrement];
+ protected int genericsLengthPtr;
+ protected int[] genericsLengthStack = new int[GenericsStackIncrement];
+ protected int genericsPtr;
+ protected ASTNode[] genericsStack = new ASTNode[GenericsStackIncrement];
+
+ protected boolean hasError;
+ protected boolean hasReportedError;
+
+ //identifiers stacks
+ protected int identifierLengthPtr;
+ protected int[] identifierLengthStack;
+ protected long[] identifierPositionStack;
+ protected int identifierPtr;
+ protected char[][] identifierStack;
+
+ protected boolean ignoreNextOpeningBrace;
+ //positions , dimensions , .... (int stacks)
+ protected int intPtr;
+ protected int[] intStack;
+ public int lastAct; //handle for multiple parsing goals
+
+ //error recovery management
+ protected int lastCheckPoint;
+ protected int lastErrorEndPosition;
+ protected int lastErrorEndPositionBeforeRecovery = -1;
+ protected int lastIgnoredToken, nextIgnoredToken;
+ protected int listLength; // for recovering some incomplete list (interfaces, throws or parameters)
+ protected int listTypeParameterLength; // for recovering some incomplete list (type parameters)
+ protected int lParenPos, rParenPos; //accurate only when used !
+ protected int modifiers;
+ protected int modifiersSourceStart;
+ protected int[] nestedMethod; //the ptr is nestedType
+ protected int nestedType, dimensions;
+ ASTNode[] noAstNodes = new ASTNode[AstStackIncrement];
+ Expression[] noExpressions = new Expression[ExpressionStackIncrement];
+ //modifiers dimensions nestedType etc.......
+ protected boolean optimizeStringLiterals = true;
+ protected CompilerOptions options;
+ protected ProblemReporter problemReporter;
+ protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
+ protected int realBlockPtr;
+ protected int[] realBlockStack;
+ protected int recoveredStaticInitializerStart;
+ public ReferenceContext referenceContext;
+ public boolean reportOnlyOneSyntaxError = false;
+ public boolean reportSyntaxErrorIsRequired = true;
+ protected boolean restartRecovery;
+
+ // statement recovery
+ // public boolean statementRecoveryEnabled = true;
+ public boolean methodRecoveryActivated = false;
+ protected boolean statementRecoveryActivated = false;
+ protected TypeDeclaration[] recoveredTypes;
+ protected int recoveredTypePtr;
+ protected int nextTypeStart;
+ protected TypeDeclaration pendingRecoveredType;
+
+ public RecoveryScanner recoveryScanner;
+
+ //scanner token
+ public Scanner scanner;
+ protected int[] stack = new int[StackIncrement];
+ protected int stateStackTop;
+ // protected int synchronizedBlockSourceStart;
+ protected int[] variablesCounter;
+
+ protected boolean checkExternalizeStrings;
+ protected boolean recordStringLiterals;
+
+ // javadoc
+ public Javadoc javadoc;
+ public JavadocParser javadocParser;
+ // used for recovery
+ protected int lastJavadocEnd;
+
+ private boolean enteredRecoverStatements;
+
+ private int insertedSemicolonPosition = -1;
+
+ private Set errorAction = new HashSet();
+
+ private static final int UNCONSUMED_LIT_ELEMENT = 0x4;
+ private static final int UNCONSUMED_ELISION = 0x2;
+ private static final int WAS_ARRAY_LIT_ELEMENT = 0x1;
+
+ public static final byte FLAG_EMPTY_STATEMENT = 1;
+
+ public IInferEngine[] inferenceEngines;
+
+ static {
+ try {
+ initTables();
+ } catch (java.io.IOException ex) {
+ throw new ExceptionInInitializerError(ex.getMessage());
+ }
+ }
+
+ public static int asi(int state) {
+
+ return asb[original_state(state)];
+ }
+
+ public final static short base_check(int i) {
+ return check_table[i - (NUM_RULES + 1)];
+ }
+
+ private final static void buildFile(String filename, List listToDump) {
+ BufferedWriter writer = null;
+ try {
+ writer = new BufferedWriter(new FileWriter(filename));
+ for (Iterator iterator = listToDump.iterator(); iterator.hasNext();) {
+ writer.write(String.valueOf(iterator.next()));
+ }
+ writer.flush();
+ } catch (IOException e) {
+ // ignore
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e1) {
+ // ignore
+ }
+ }
+ }
+ System.out.println(filename + " creation complete"); //$NON-NLS-1$
+ }
+
+ private final static String[] buildFileForName(String filename, String contents) {
+ String[] result = new String[contents.length()];
+ result[0] = null;
+ int resultCount = 1;
+
+ StringBuffer buffer = new StringBuffer();
+
+ int start = contents.indexOf("name[]"); //$NON-NLS-1$
+ start = contents.indexOf('\"', start);
+ int end = contents.indexOf("};", start); //$NON-NLS-1$
+
+ contents = contents.substring(start, end);
+
+ boolean addLineSeparator = false;
+ int tokenStart = -1;
+ StringBuffer currentToken = new StringBuffer();
+ for (int i = 0; i < contents.length(); i++) {
+ char c = contents.charAt(i);
+ if (c == '\"') {
+ if (tokenStart == -1) {
+ tokenStart = i + 1;
+ } else {
+ if (addLineSeparator) {
+ buffer.append('\n');
+ result[resultCount++] = currentToken.toString();
+ currentToken = new StringBuffer();
+ }
+ String token = contents.substring(tokenStart, i);
+ if (token.equals(ERROR_TOKEN)) {
+ token = INVALID_CHARACTER;
+ } else if (token.equals(EOF_TOKEN)) {
+ token = UNEXPECTED_EOF;
+ }
+ buffer.append(token);
+ currentToken.append(token);
+ addLineSeparator = true;
+ tokenStart = -1;
+ }
+ }
+ if (tokenStart == -1 && c == '+') {
+ addLineSeparator = false;
+ }
+ }
+ if (currentToken.length() > 0) {
+ result[resultCount++] = currentToken.toString();
+ }
+
+ buildFileForTable(filename, buffer.toString().toCharArray());
+
+ System.arraycopy(result, 0, result = new String[resultCount], 0, resultCount);
+ return result;
+ }
+
+ private static void buildFileForReadableName(
+ String file,
+ char[] newLhs,
+ char[] newNonTerminalIndex,
+ String[] newName,
+ String[] tokens) {
+
+ ArrayList entries = new ArrayList();
+
+ boolean[] alreadyAdded = new boolean[newName.length];
+
+ for (int i = 0; i < tokens.length; i = i + 3) {
+ if ("1".equals(tokens[i])) { //$NON-NLS-1$
+ int index = newNonTerminalIndex[newLhs[Integer.parseInt(tokens[i + 1])]];
+ StringBuffer buffer = new StringBuffer();
+ if (!alreadyAdded[index]) {
+ alreadyAdded[index] = true;
+ buffer.append(newName[index]);
+ buffer.append('=');
+ buffer.append(tokens[i + 2].trim());
+ buffer.append('\n');
+ entries.add(String.valueOf(buffer));
+ }
+ }
+ }
+ int i = 1;
+ while (!INVALID_CHARACTER.equals(newName[i]))
+ i++;
+ i++;
+ for (; i < alreadyAdded.length; i++) {
+ if (!alreadyAdded[i]) {
+ System.out.println(newName[i] + " has no readable name"); //$NON-NLS-1$
+ }
+ }
+ Collections.sort(entries);
+ buildFile(file, entries);
+ }
+
+ private static void buildFilesForRecoveryTemplates(
+ String indexFilename,
+ String templatesFilename,
+ char[] newTerminalIndex,
+ char[] newNonTerminalIndex,
+ String[] newName,
+ char[] newLhs,
+ String[] tokens) {
+
+ int[] newReverse = computeReverseTable(newTerminalIndex, newNonTerminalIndex, newName);
+
+ char[] newRecoveyTemplatesIndex = new char[newNonTerminalIndex.length];
+ char[] newRecoveyTemplates = new char[newNonTerminalIndex.length];
+ int newRecoveyTemplatesPtr = 0;
+
+ for (int i = 0; i < tokens.length; i = i + 3) {
+ if ("3".equals(tokens[i])) { //$NON-NLS-1$
+ int length = newRecoveyTemplates.length;
+ if (length == newRecoveyTemplatesPtr + 1) {
+ System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[length * 2], 0, length);
+ }
+ newRecoveyTemplates[newRecoveyTemplatesPtr++] = 0;
+
+ int index = newLhs[Integer.parseInt(tokens[i + 1])];
+
+ newRecoveyTemplatesIndex[index] = (char) newRecoveyTemplatesPtr;
+
+ String token = tokens[i + 2].trim();
+ java.util.StringTokenizer st = new java.util.StringTokenizer(new String(token), " "); //$NON-NLS-1$
+ String[] terminalNames = new String[st.countTokens()];
+ int t = 0;
+ while (st.hasMoreTokens()) {
+ terminalNames[t++] = st.nextToken();
+ }
+
+ for (int j = 0; j < terminalNames.length; j++) {
+ int symbol = getSymbol(terminalNames[j], newName, newReverse);
+ if (symbol > -1) {
+ length = newRecoveyTemplates.length;
+ if (length == newRecoveyTemplatesPtr + 1) {
+ System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[length * 2], 0, length);
+ }
+ newRecoveyTemplates[newRecoveyTemplatesPtr++] = (char) symbol;
+ }
+ }
+ }
+ }
+ newRecoveyTemplates[newRecoveyTemplatesPtr++] = 0;
+ System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[newRecoveyTemplatesPtr], 0, newRecoveyTemplatesPtr);
+
+ buildFileForTable(indexFilename, newRecoveyTemplatesIndex);
+ buildFileForTable(templatesFilename, newRecoveyTemplates);
+ }
+
+ private static void buildFilesForStatementsRecoveryFilter(
+ String filename,
+ char[] newNonTerminalIndex,
+ char[] newLhs,
+ String[] tokens) {
+
+ char[] newStatementsRecoveryFilter = new char[newNonTerminalIndex.length];
+
+ for (int i = 0; i < tokens.length; i = i + 3) {
+ if ("4".equals(tokens[i])) { //$NON-NLS-1$
+ int index = newLhs[Integer.parseInt(tokens[i + 1])];
+
+ newStatementsRecoveryFilter[index] = 1;
+ }
+ }
+ buildFileForTable(filename, newStatementsRecoveryFilter);
+ }
+
+ private static void buildFilesForFlags(
+ String filename,
+ int size,
+ String[] tokens) {
+
+ byte[] flags = new byte[size];
+
+ for (int i = 0; i < tokens.length; i = i + 3) {
+ if ("5".equals(tokens[i])) { //$NON-NLS-1$
+ int index = Integer.parseInt(tokens[i + 1]);
+ byte value = (byte) Integer.parseInt(tokens[i + 2].trim());
+ flags[index] = value;
+ }
+ }
+ buildFileForTable(filename, flags);
+ }
+
+ private static void buildFileForCompliance(
+ String file,
+ int length,
+ String[] tokens) {
+
+ byte[] result = new byte[length * 8];
+
+ for (int i = 0; i < tokens.length; i = i + 3) {
+ if ("2".equals(tokens[i])) { //$NON-NLS-1$
+ int index = Integer.parseInt(tokens[i + 1]);
+ String token = tokens[i + 2].trim();
+ long compliance = 0;
+ if ("1.4".equals(token)) { //$NON-NLS-1$
+ compliance = ClassFileConstants.JDK1_4;
+ } else if ("1.5".equals(token)) { //$NON-NLS-1$
+ compliance = ClassFileConstants.JDK1_5;
+ } else if ("recovery".equals(token)) { //$NON-NLS-1$
+ compliance = ClassFileConstants.JDK_DEFERRED;
+ }
+
+ int j = index * 8;
+ result[j] = (byte) (compliance >>> 56);
+ result[j + 1] = (byte) (compliance >>> 48);
+ result[j + 2] = (byte) (compliance >>> 40);
+ result[j + 3] = (byte) (compliance >>> 32);
+ result[j + 4] = (byte) (compliance >>> 24);
+ result[j + 5] = (byte) (compliance >>> 16);
+ result[j + 6] = (byte) (compliance >>> 8);
+ result[j + 7] = (byte) (compliance);
+ }
+ }
+
+ buildFileForTable(file, result);
+ }
+
+ private final static void buildFileForTable(String filename, byte[] bytes) {
+ java.io.FileOutputStream stream = null;
+ try {
+ stream = new java.io.FileOutputStream(filename);
+ stream.write(bytes);
+ } catch (IOException e) {
+ // ignore
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e1) {
+ // ignore
+ }
+ }
+ }
+ System.out.println(filename + " creation complete"); //$NON-NLS-1$
+ }
+
+ private final static void buildFileForTable(String filename, char[] chars) {
+ byte[] bytes = new byte[chars.length * 2];
+ for (int i = 0; i < chars.length; i++) {
+ bytes[2 * i] = (byte) (chars[i] >>> 8);
+ bytes[2 * i + 1] = (byte) (chars[i] & 0xFF);
+ }
+
+ java.io.FileOutputStream stream = null;
+ try {
+ stream = new java.io.FileOutputStream(filename);
+ stream.write(bytes);
+ } catch (IOException e) {
+ // ignore
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e1) {
+ // ignore
+ }
+ }
+ }
+ System.out.println(filename + " creation complete"); //$NON-NLS-1$
+ }
+
+ private final static byte[] buildFileOfByteFor(String filename, String tag, String[] tokens) {
+
+ //transform the String tokens into chars before dumping then into file
+
+ int i = 0;
+ //read upto the tag
+ while (!tokens[i++].equals(tag)) {/*empty*/
+ }
+ //read upto the }
+
+ byte[] bytes = new byte[tokens.length]; //can't be bigger
+ int ic = 0;
+ String token;
+ while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+ int c = Integer.parseInt(token);
+ bytes[ic++] = (byte) c;
+ }
+
+ //resize
+ System.arraycopy(bytes, 0, bytes = new byte[ic], 0, ic);
+
+ buildFileForTable(filename, bytes);
+ return bytes;
+ }
+
+ private final static char[] buildFileOfIntFor(String filename, String tag, String[] tokens) {
+
+ //transform the String tokens into chars before dumping then into file
+
+ int i = 0;
+ //read upto the tag
+ while (!tokens[i++].equals(tag)) {/*empty*/
+ }
+ //read upto the }
+
+ char[] chars = new char[tokens.length]; //can't be bigger
+ int ic = 0;
+ String token;
+ while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+ int c = Integer.parseInt(token);
+ chars[ic++] = (char) c;
+ }
+
+ //resize
+ System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
+
+ buildFileForTable(filename, chars);
+ return chars;
+ }
+
+ private final static void buildFileOfShortFor(String filename, String tag, String[] tokens) {
+
+ //transform the String tokens into chars before dumping then into file
+
+ int i = 0;
+ //read upto the tag
+ while (!tokens[i++].equals(tag)) {/*empty*/
+ }
+ //read upto the }
+
+ char[] chars = new char[tokens.length]; //can't be bigger
+ int ic = 0;
+ String token;
+ while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+ int c = Integer.parseInt(token);
+ chars[ic++] = (char) (c + 32768);
+ }
+
+ //resize
+ System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
+
+ buildFileForTable(filename, chars);
+ }
+
+ public final static void buildFilesFromLPG(String dataFilename, String dataFilename2) {
+
+ //RUN THIS METHOD TO GENERATE PARSER*.RSC FILES
+
+ //build from the lpg javadcl.java files that represents the parser tables
+ //lhs check_table asb asr symbol_index
+
+ //[org.eclipse.wst.jsdt.internal.compiler.parser.Parser.buildFilesFromLPG("d:/leapfrog/grammar/javadcl.java")]
+ char[] contents = CharOperation.NO_CHAR;
+ try {
+ contents = Util.getFileCharContent(new File(dataFilename), null);
+ } catch (IOException ex) {
+ System.out.println(Messages.parser_incorrectPath);
+ return;
+ }
+ java.util.StringTokenizer st =
+ new java.util.StringTokenizer(new String(contents), " \t\n\r[]={,;"); //$NON-NLS-1$
+ String[] tokens = new String[st.countTokens()];
+ int j = 0;
+ while (st.hasMoreTokens()) {
+ tokens[j++] = st.nextToken();
+ }
+ final String prefix = FILEPREFIX;
+ int i = 0;
+
+ char[] newLhs = buildFileOfIntFor(prefix + (++i) + ".rsc", "lhs", tokens); //$NON-NLS-1$ //$NON-NLS-2$
+ buildFileOfShortFor(prefix + (++i) + ".rsc", "check_table", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "asb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "asr", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "nasb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "nasr", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ char[] newTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "terminal_index", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ char[] newNonTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "non_terminal_index", tokens); //$NON-NLS-1$ //$NON-NLS-2$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "term_action", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_prefix", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_suffix", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_lhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state_set", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfIntFor(prefix + (++i) + ".rsc", "in_symb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+
+ byte[] newRhs = buildFileOfByteFor(prefix + (++i) + ".rsc", "rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfByteFor(prefix + (++i) + ".rsc", "term_check", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileOfByteFor(prefix + (++i) + ".rsc", "scope_la", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+
+ String[] newName = buildFileForName(prefix + (++i) + ".rsc", new String(contents)); //$NON-NLS-1$
+
+ contents = CharOperation.NO_CHAR;
+ try {
+ contents = Util.getFileCharContent(new File(dataFilename2), null);
+ } catch (IOException ex) {
+ System.out.println(Messages.parser_incorrectPath);
+ return;
+ }
+ st = new java.util.StringTokenizer(new String(contents), "\t\n\r#"); //$NON-NLS-1$
+ tokens = new String[st.countTokens()];
+ j = 0;
+ while (st.hasMoreTokens()) {
+ tokens[j++] = st.nextToken();
+ }
+
+ buildFileForCompliance(prefix + (++i) + ".rsc", newRhs.length, tokens);//$NON-NLS-1$
+ buildFileForReadableName(READABLE_NAMES_FILE + ".properties", newLhs, newNonTerminalIndex, newName, tokens);//$NON-NLS-1$
+
+ buildFilesForRecoveryTemplates(
+ prefix + (++i) + ".rsc", //$NON-NLS-1$
+ prefix + (++i) + ".rsc", //$NON-NLS-1$
+ newTerminalIndex,
+ newNonTerminalIndex,
+ newName,
+ newLhs,
+ tokens);
+
+ buildFilesForStatementsRecoveryFilter(
+ prefix + (++i) + ".rsc", //$NON-NLS-1$
+ newNonTerminalIndex,
+ newLhs,
+ tokens);
+
+ buildFilesForFlags(
+ prefix + (++i) + ".rsc", //$NON-NLS-1$
+ rhs.length,
+ tokens);
+
+ System.out.println(Messages.parser_moveFiles);
+ }
+
+ public static int in_symbol(int state) {
+ return in_symb[original_state(state)];
+ }
+
+ public final static void initTables() throws java.io.IOException {
+
+ final String prefix = FILEPREFIX;
+ int i = 0;
+ lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ char[] chars = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ check_table = new short[chars.length];
+ for (int c = chars.length; c-- > 0;) {
+ check_table[c] = (short) (chars[c] - 32768);
+ }
+ asb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ asr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ nasb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ nasr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ non_terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ term_action = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ scope_prefix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_suffix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_state_set = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_rhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_state = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ in_symb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ rhs = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ term_check = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_la = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ name = readNameTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ rules_compliance = readLongTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ readableName = readReadableNameTable(READABLE_NAMES_FILE_NAME);
+
+ reverse_index = computeReverseTable(terminal_index, non_terminal_index, name);
+
+ recovery_templates_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ recovery_templates = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ statements_recovery_filter = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ state_flags = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ base_action = lhs;
+
+ optionalSemicolonState = new boolean[base_action.length];
+ for (i = 0; i < optionalSemicolonState.length; i++) {
+ if (base_action[i] + TokenNameSEMICOLON < term_check.length
+ && (term_check[base_action[i] + TokenNameSEMICOLON] == TokenNameSEMICOLON))
+ {
+ int act = term_action[base_action[i] + TokenNameSEMICOLON];
+ if (act > ERROR_ACTION)
+ act -= ERROR_ACTION;
+ boolean isEmptyStatementsState = false;
+ if (act < NUM_RULES)
+ isEmptyStatementsState = (state_flags[act] & FLAG_EMPTY_STATEMENT) > 0;
+ if (!isEmptyStatementsState)
+ optionalSemicolonState[i] = true;
+ }
+ }
+
+ }
+
+ public static int nasi(int state) {
+ return nasb[original_state(state)];
+ }
+
+ public static int ntAction(int state, int sym) {
+ return base_action[state + sym];
+ }
+
+ protected static int original_state(int state) {
+ return -base_check(state);
+ }
+
+ protected static int[] computeReverseTable(char[] newTerminalIndex, char[] newNonTerminalIndex, String[] newName) {
+ int[] newReverseTable = new int[newName.length];
+ for (int j = 0; j < newName.length; j++) {
+ found: {
+ for (int k = 0; k < newTerminalIndex.length; k++) {
+ if (newTerminalIndex[k] == j) {
+ newReverseTable[j] = k;
+ break found;
+ }
+ }
+ for (int k = 0; k < newNonTerminalIndex.length; k++) {
+ if (newNonTerminalIndex[k] == j) {
+ newReverseTable[j] = -k;
+ break found;
+ }
+ }
+ }
+ }
+ return newReverseTable;
+ }
+
+ private static int getSymbol(String terminalName, String[] newName, int[] newReverse) {
+ for (int j = 0; j < newName.length; j++) {
+ if (terminalName.equals(newName[j])) {
+ return newReverse[j];
+ }
+ }
+ return -1;
+ }
+
+ protected static byte[] readByteTable(String filename) throws java.io.IOException {
+
+ //files are located at Parser.class directory
+
+ InputStream stream = Parser.class.getResourceAsStream(filename);
+ if (stream == null) {
+ throw new java.io.IOException(Messages.bind(Messages.parser_missingFile, filename));
+ }
+ byte[] bytes = null;
+ try {
+ stream = new BufferedInputStream(stream);
+ bytes = Util.getInputStreamAsByteArray(stream, -1);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ return bytes;
+ }
+
+ protected static String[] readNameTable(String filename) throws java.io.IOException {
+ char[] contents = readTable(filename);
+ char[][] nameAsChar = CharOperation.splitOn('\n', contents);
+
+ String[] result = new String[nameAsChar.length + 1];
+ result[0] = null;
+ for (int i = 0; i < nameAsChar.length; i++) {
+ result[i + 1] = new String(nameAsChar[i]);
+ }
+
+ return result;
+ }
+
+ protected static String[] readReadableNameTable(String filename) {
+ String[] result = new String[name.length];
+
+ ResourceBundle bundle;
+ try {
+ bundle = ResourceBundle.getBundle(filename, Locale.getDefault());
+ } catch (MissingResourceException e) {
+ System.out.println("Missing resource : " + filename.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+ throw e;
+ }
+ for (int i = 0; i < NT_OFFSET + 1; i++) {
+ result[i] = name[i];
+ }
+ for (int i = NT_OFFSET; i < name.length; i++) {
+ try {
+ String n = bundle.getString(name[i]);
+ if (n != null && n.length() > 0) {
+ result[i] = n;
+ } else {
+ result[i] = name[i];
+ }
+ } catch (MissingResourceException e) {
+ result[i] = name[i];
+ }
+ }
+ return result;
+ }
+
+ protected static char[] readTable(String filename) throws java.io.IOException {
+
+ //files are located at Parser.class directory
+
+ InputStream stream = Parser.class.getResourceAsStream(filename);
+ if (stream == null) {
+ throw new java.io.IOException(Messages.bind(Messages.parser_missingFile, filename));
+ }
+ byte[] bytes = null;
+ try {
+ stream = new BufferedInputStream(stream);
+ bytes = Util.getInputStreamAsByteArray(stream, -1);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+
+ //minimal integrity check (even size expected)
+ int length = bytes.length;
+ if ((length & 1) != 0)
+ throw new java.io.IOException(Messages.bind(Messages.parser_corruptedFile, filename));
+
+ // convert bytes into chars
+ char[] chars = new char[length / 2];
+ int i = 0;
+ int charIndex = 0;
+
+ while (true) {
+ chars[charIndex++] = (char) (((bytes[i++] & 0xFF) << 8) + (bytes[i++] & 0xFF));
+ if (i == length)
+ break;
+ }
+ return chars;
+ }
+
+ protected static long[] readLongTable(String filename) throws java.io.IOException {
+
+ //files are located at Parser.class directory
+
+ InputStream stream = Parser.class.getResourceAsStream(filename);
+ if (stream == null) {
+ throw new java.io.IOException(Messages.bind(Messages.parser_missingFile, filename));
+ }
+ byte[] bytes = null;
+ try {
+ stream = new BufferedInputStream(stream);
+ bytes = Util.getInputStreamAsByteArray(stream, -1);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+
+ //minimal integrity check (even size expected)
+ int length = bytes.length;
+ if (length % 8 != 0)
+ throw new java.io.IOException(Messages.bind(Messages.parser_corruptedFile, filename));
+
+ // convert bytes into longs
+ long[] longs = new long[length / 8];
+ int i = 0;
+ int longIndex = 0;
+
+ while (true) {
+ longs[longIndex++] =
+ (((long) (bytes[i++] & 0xFF)) << 56)
+ + (((long) (bytes[i++] & 0xFF)) << 48)
+ + (((long) (bytes[i++] & 0xFF)) << 40)
+ + (((long) (bytes[i++] & 0xFF)) << 32)
+ + (((long) (bytes[i++] & 0xFF)) << 24)
+ + (((long) (bytes[i++] & 0xFF)) << 16)
+ + (((long) (bytes[i++] & 0xFF)) << 8)
+ + (bytes[i++] & 0xFF);
+
+ if (i == length)
+ break;
+ }
+ return longs;
+ }
+
+ public static int tAction(int state, int sym) {
+ return term_action[term_check[base_action[state] + sym] == sym ? base_action[state] + sym : base_action[state]];
+ }
+
+ public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
+
+ this.problemReporter = problemReporter;
+ this.options = problemReporter.options;
+ this.optimizeStringLiterals = optimizeStringLiterals;
+ this.initializeScanner();
+ this.astLengthStack = new int[50];
+ this.expressionLengthStack = new int[30];
+ this.intStack = new int[50];
+ this.identifierStack = new char[30][];
+ this.identifierLengthStack = new int[30];
+ this.nestedMethod = new int[30];
+ this.realBlockStack = new int[30];
+ this.identifierPositionStack = new long[30];
+ this.variablesCounter = new int[30];
+
+ // javadoc support
+ this.javadocParser = createJavadocParser();
+
+ }
+
+ protected void annotationRecoveryCheckPoint(int start, int end) {
+ if (this.lastCheckPoint > start && this.lastCheckPoint < end) {
+ this.lastCheckPoint = end + 1;
+ }
+ }
+
+ public void arrayInitializer(int length) {
+ //length is the size of the array Initializer
+ //expressionPtr points on the last elt of the arrayInitializer,
+ // in other words, it has not been decremented yet.
+
+ ArrayInitializer ai = new ArrayInitializer();
+ if (length != 0) {
+ this.expressionPtr -= length;
+ System.arraycopy(this.expressionStack, this.expressionPtr + 1, ai.expressions = new Expression[length], 0, length);
+ }
+ pushOnExpressionStack(ai);
+ //positionning
+ ai.sourceEnd = this.endStatementPosition;
+ ai.sourceStart = this.intStack[this.intPtr--];
+ }
+
+ protected void blockReal() {
+ // See consumeLocalVariableDeclarationStatement in case of change: duplicated code
+ // increment the amount of declared variables for this block
+ this.realBlockStack[this.realBlockPtr]++;
+ }
+
+ /*
+ * Build initial recovery state.
+ * Recovery state is inferred from the current state of the parser (reduced node stack).
+ */
+ public RecoveredElement buildInitialRecoveryState() {
+
+ /* initialize recovery by retrieving available reduced nodes
+ * also rebuild bracket balance
+ */
+ this.lastCheckPoint = 0;
+ this.lastErrorEndPositionBeforeRecovery = this.scanner.currentPosition;
+
+ RecoveredElement element = null;
+ if (this.referenceContext instanceof CompilationUnitDeclaration) {
+ if (!DO_DIET_PARSE)
+ {
+ this.methodRecoveryActivated = true;
+ // this.statementRecoveryActivated=true;
+ }
+ element = new RecoveredUnit(this.compilationUnit, 0, this);
+
+ /* ignore current stack state, since restarting from the beginnning
+ since could not trust simple brace count */
+ if (false) { // experimenting restart recovery from scratch
+ this.compilationUnit.currentPackage = null;
+ this.compilationUnit.imports = null;
+ this.compilationUnit.types = null;
+ this.compilationUnit.statements = null;
+ this.currentToken = 0;
+ this.listLength = 0;
+ this.listTypeParameterLength = 0;
+ this.endPosition = 0;
+ this.endStatementPosition = 0;
+ return element;
+ }
+ else
+ {
+ this.currentToken = 0;
+ // if (this.astPtr<0&&this.compilationUnit.sourceEnd>0)
+ // this.lastCheckPoint = this.compilationUnit.sourceEnd;
+
+ }
+
+ if (this.compilationUnit.currentPackage != null) {
+ this.lastCheckPoint = this.compilationUnit.currentPackage.declarationSourceEnd + 1;
+ }
+ if (this.compilationUnit.imports != null) {
+ this.lastCheckPoint = this.compilationUnit.imports[this.compilationUnit.imports.length - 1].declarationSourceEnd + 1;
+ }
+ } else {
+ if (this.referenceContext instanceof AbstractMethodDeclaration) {
+ element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this);
+ this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart;
+ if (this.statementRecoveryActivated) {
+ element = element.add(new Block(0), 0);
+ }
+ } 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;
+ for (int i = 0; i < type.fields.length; i++) {
+ FieldDeclaration field = type.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;
+
+ element = recoverAST(element);
+ if (this.statementRecoveryActivated) {
+ if (this.pendingRecoveredType != null &&
+ this.scanner.startPosition - 1 <= this.pendingRecoveredType.declarationSourceEnd) {
+ // Add the pending type to the AST if this type isn't already added in the AST.
+ element = element.add(this.pendingRecoveredType, 0);
+ this.lastCheckPoint = this.pendingRecoveredType.declarationSourceEnd + 1;
+ this.pendingRecoveredType = null;
+ }
+ }
+ ProgramElement[] compUnitStatments = this.compilationUnit.statements;
+ if (compUnitStatments != null && compUnitStatments.length > 0 &&
+ this.lastCheckPoint < compUnitStatments[compUnitStatments.length - 1].sourceEnd)
+ {
+ ProgramElement programElement = compUnitStatments[compUnitStatments.length - 1];
+
+ this.lastCheckPoint = ((programElement instanceof Expression) ? ((Expression) programElement).statementEnd : programElement.sourceEnd) + 1;
+ }
+ return element;
+ }
+
+ public RecoveredElement recoverAST(RecoveredElement element) {
+ for (int i = 0; i <= this.astPtr; i++) {
+ ASTNode node = this.astStack[i];
+ if (node instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
+ if (method.getName() != null)
+ {
+ if (method.declarationSourceEnd == 0) {
+ element = element.add(method, 0);
+ this.lastCheckPoint = method.bodyStart;
+ } else {
+ element = element.add(method, 0);
+ this.lastCheckPoint = method.declarationSourceEnd + 1;
+ }
+ }
+ else
+ element = recoverFunctionExpression(element, method);
+ 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 LocalDeclaration) {
+ LocalDeclaration localDecl = (LocalDeclaration) node;
+ if (localDecl.declarationSourceEnd == 0) {
+ element = element.add(localDecl, 0);
+ if (localDecl.initialization == null) {
+ this.lastCheckPoint = localDecl.sourceEnd + 1;
+ } else {
+ this.lastCheckPoint = localDecl.initialization.sourceEnd + 1;
+ }
+ } else {
+ element = element.add(localDecl, 0);
+ this.lastCheckPoint = localDecl.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 (node instanceof Statement) {
+ Statement statement = (Statement) node;
+ if (statement.sourceEnd == 0) {
+ element = element.add(statement, 1);
+ this.lastCheckPoint = statement.sourceStart;
+ } else {
+ element = element.add(statement, 0);
+ this.lastCheckPoint = statement.sourceEnd + 1;
+ }
+ continue;
+ }
+ if (node instanceof ImportReference) {
+ ImportReference importRef = (ImportReference) node;
+ element = element.add(importRef, 0);
+ this.lastCheckPoint = importRef.declarationSourceEnd + 1;
+ }
+ if (this.statementRecoveryActivated) {
+ if (node instanceof Block) {
+ Block block = (Block) node;
+ element = element.add(block, 0);
+ this.lastCheckPoint = block.sourceEnd + 1;
+ } else if (node instanceof LocalDeclaration) {
+ LocalDeclaration statement = (LocalDeclaration) node;
+ element = element.add(statement, 0);
+ this.lastCheckPoint = statement.declarationSourceEnd + 1;
+ } else if (node instanceof Expression) {
+ if (node instanceof Assignment ||
+ node instanceof PrefixExpression ||
+ node instanceof PostfixExpression ||
+ node instanceof MessageSend ||
+ node instanceof AllocationExpression) {
+ // recover only specific expressions
+ Expression statement = (Expression) node;
+ element = element.add(statement, 0);
+ if (statement.statementEnd != -1) {
+ this.lastCheckPoint = statement.statementEnd + 1;
+ } else {
+ this.lastCheckPoint = statement.sourceEnd + 1;
+ }
+ }
+ } else if (node instanceof Statement) {
+ Statement statement = (Statement) node;
+ element = element.add(statement, 0);
+ this.lastCheckPoint = statement.sourceEnd + 1;
+ }
+ }
+ }
+ return element;
+ }
+
+ protected RecoveredElement recoverFunctionExpression(RecoveredElement element, AbstractMethodDeclaration method) {
+ int start = method.exprStackPtr;
+ // int end=this.expressionPtr;
+ boolean isAssignment = true;
+ Statement expression = null;
+
+ FunctionExpression funcExpr = new FunctionExpression((MethodDeclaration) method);
+ funcExpr.sourceEnd = method.declarationSourceEnd;
+ funcExpr.sourceStart = method.sourceStart;
+
+ if (isAssignment && start >= 0)
+ {
+ expression = new Assignment(this.expressionStack[start], funcExpr, method.sourceEnd);
+ }
+ if (expression != null)
+ {
+ element = element.add(expression, 1);
+ if (method.declarationSourceEnd == 0) {
+ element = element.add(method, 0);
+ this.lastCheckPoint = method.bodyStart;
+ } else {
+ element = element.add(method, 0);
+ this.lastCheckPoint = method.declarationSourceEnd + 1;
+ }
+ if (element instanceof RecoveredMethod)
+ element.add(new Block(0), 0);
+ }
+
+ return element;
+ }
+
+ protected void checkAndSetModifiers(int flag) {
+ /*modify the current modifiers buffer.
+ When the startPosition of the modifiers is 0
+ it means that the modifier being parsed is the first
+ of a list of several modifiers. The startPosition
+ is zeroed when a copy of modifiers-buffer is push
+ onto the this.astStack. */
+
+ if ((this.modifiers & flag) != 0) { // duplicate modifier
+ this.modifiers |= ExtraCompilerModifiers.AccAlternateModifierProblem;
+ }
+ this.modifiers |= flag;
+
+ if (this.modifiersSourceStart < 0)
+ this.modifiersSourceStart = this.scanner.startPosition;
+ }
+
+ public void checkComment() {
+
+ // discard obsolete comments while inside methods or fields initializer (see bug 74369)
+ // don't discard if the expression being worked on is an ObjectLiteral (see bug 322412 )
+ if (!(this.diet && this.dietInt == 0) && this.scanner.commentPtr >= 0 && !(expressionPtr >= 0 && expressionStack[expressionPtr] instanceof ObjectLiteral)) {
+ flushCommentsDefinedPriorTo(this.endStatementPosition);
+ }
+
+ int lastComment = this.scanner.commentPtr;
+
+ // if (this.modifiersSourceStart >= 0) {
+ // // eliminate comments located after modifierSourceStart if positionned
+ // while (lastComment >= 0 && this.scanner.commentStarts[lastComment] > this.modifiersSourceStart) lastComment--;
+ // }
+ if (lastComment >= 0) {
+ // consider all remaining leading comments to be part of current declaration
+ this.modifiersSourceStart = this.scanner.commentStarts[0];
+
+ // check deprecation in last comment if javadoc (can be followed by non-javadoc comments which are simply ignored)
+ while (lastComment >= 0 && this.scanner.commentStops[lastComment] < 0)
+ lastComment--; // non javadoc comment have negative end positions
+ if (lastComment >= 0 && this.javadocParser != null) {
+ int commentEnd = this.scanner.commentStops[lastComment] - 1; //stop is one over,
+ // do not report problem before last parsed comment while recovering code...
+ this.javadocParser.reportProblems = this.currentElement == null || commentEnd > this.lastJavadocEnd;
+ if (this.javadocParser.checkDeprecation(lastComment)) {
+ checkAndSetModifiers(ClassFileConstants.AccDeprecated);
+ }
+ this.javadoc = this.javadocParser.docComment; // null if check javadoc is not activated
+ if (currentElement == null)
+ this.lastJavadocEnd = commentEnd;
+ }
+ }
+ }
+
+ protected void checkNonNLSAfterBodyEnd(int declarationEnd) {
+ if (this.scanner.currentPosition - 1 <= declarationEnd) {
+ this.scanner.eofPosition = declarationEnd < Integer.MAX_VALUE ? declarationEnd + 1 : declarationEnd;
+ try {
+ while (this.scanner.getNextToken() != TokenNameEOF) {/*empty*/
+ }
+ } catch (InvalidInputException e) {
+ // Nothing to do
+ }
+ }
+ }
+
+ protected void classInstanceCreation(boolean isQualified, boolean isShort) {
+ // 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 = new AllocationExpression();
+ int length;
+ // if (((length = this.astLengthStack[this.astLengthPtr--]) == 1)
+ // && (this.astStack[this.astPtr] == null)) {
+ // //NO ClassBody
+ // this.astPtr--;
+ // if (isQualified) {
+ // alloc = new QualifiedAllocationExpression();
+ // } else {
+ alloc = new AllocationExpression();
+ // }
+
+ alloc.isShort = isShort;
+ if (!isShort)
+ {
+ alloc.sourceEnd = this.intStack[this.intPtr--]; //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.member = this.expressionStack[this.expressionPtr--];
+ this.expressionLengthPtr--;
+
+ //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--];
+ if (isShort)
+ alloc.sourceEnd = alloc.member.sourceEnd;
+ pushOnExpressionStack(alloc);
+ // } else {
+ // dispatchDeclarationInto(length);
+ // TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration)this.astStack[this.astPtr];
+ // anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
+ // anonymousTypeDeclaration.bodyEnd = this.endStatementPosition;
+ // if (anonymousTypeDeclaration.allocation != null) {
+ // anonymousTypeDeclaration.allocation.sourceEnd = this.endStatementPosition;
+ // }
+ // if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
+ // anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlock;
+ // }
+ // this.astPtr--;
+ // this.astLengthPtr--;
+ //
+ // // mark initializers with local type mark if needed
+ // markInitializersWithLocalType(anonymousTypeDeclaration);
+ // }
+ }
+
+ protected void concatExpressionLists() {
+ this.expressionLengthStack[--this.expressionLengthPtr]++;
+ }
+
+ protected void concatNodeLists() {
+ /*
+ * This is a case where you have two sublists into the this.astStack that you want
+ * to merge in one list. There is no action required on the this.astStack. The only
+ * thing you need to do is merge the two lengths specified on the astStackLength.
+ * The top two length are for example:
+ * ... p n
+ * and you want to result in a list like:
+ * ... n+p
+ * This means that the p could be equals to 0 in case there is no astNode pushed
+ * on the this.astStack.
+ * Look at the InterfaceMemberDeclarations for an example.
+ */
+
+ this.astLengthStack[this.astLengthPtr - 1] += this.astLengthStack[this.astLengthPtr--];
+ }
+
+ protected void consumeAnnotationAsModifier() {
+ Expression expression = this.expressionStack[this.expressionPtr];
+ int sourceStart = expression.sourceStart;
+ if (this.modifiersSourceStart < 0) {
+ this.modifiersSourceStart = sourceStart;
+ }
+ }
+
+ protected void consumeArgumentList() {
+ // ArgumentList ::= ArgumentList ',' Expression
+ concatExpressionLists();
+ }
+
+ protected void consumeArguments() {
+ // Arguments ::= '(' ArgumentListopt ')'
+ // nothing to do, the expression stack is already updated
+ pushOnIntStack(rParenPos);
+ }
+
+ protected void consumeAssignment() {
+ // Assignment ::= LeftHandSide AssignmentOperator AssignmentExpression
+ //optimize the push/pop
+
+ int op = this.intStack[this.intPtr--]; //<--the encoded operator
+
+ this.expressionPtr--;
+ this.expressionLengthPtr--;
+ checkComment();
+
+ if (op != EQUAL) {
+ CompoundAssignment compoundAssignment = new CompoundAssignment(
+ this.expressionStack[this.expressionPtr],
+ this.expressionStack[this.expressionPtr + 1],
+ op,
+ this.scanner.startPosition - 1);
+ if (this.javadoc != null) {
+ compoundAssignment.javadoc = this.javadoc;
+ this.javadoc = null;
+ }
+ this.expressionStack[this.expressionPtr] = compoundAssignment;
+ }
+ else {
+ Assignment assignment = new Assignment(
+ this.expressionStack[this.expressionPtr],
+ this.expressionStack[this.expressionPtr + 1],
+ this.scanner.startPosition - 1);
+ if (this.javadoc != null) {
+ assignment.javadoc = this.javadoc;
+ this.javadoc = null;
+ }
+ this.expressionStack[this.expressionPtr] = assignment;
+ }
+
+ if (this.pendingRecoveredType != null) {
+ // Used only in statements recovery.
+ // This is not a real assignment but a placeholder for an existing anonymous type.
+ // The assignment must be replace by the anonymous type.
+ if (this.pendingRecoveredType.allocation != null &&
+ this.scanner.startPosition - 1 <= this.pendingRecoveredType.declarationSourceEnd) {
+ this.expressionStack[this.expressionPtr] = this.pendingRecoveredType.allocation;
+ this.pendingRecoveredType = null;
+ return;
+ }
+ this.pendingRecoveredType = null;
+ }
+ }
+
+ protected void consumeAssignmentOperator(int pos) {
+ // AssignmentOperator ::= '='
+ // AssignmentOperator ::= '*='
+ // AssignmentOperator ::= '/='
+ // AssignmentOperator ::= '%='
+ // AssignmentOperator ::= '+='
+ // AssignmentOperator ::= '-='
+ // AssignmentOperator ::= '<<='
+ // AssignmentOperator ::= '>>='
+ // AssignmentOperator ::= '>>>='
+ // AssignmentOperator ::= '&='
+ // AssignmentOperator ::= '^='
+ // AssignmentOperator ::= '|='
+
+ pushOnIntStack(pos);
+ }
+
+ protected void consumeBinaryExpression(int op) {
+ // MultiplicativeExpression ::= MultiplicativeExpression '*' UnaryExpression
+ // MultiplicativeExpression ::= MultiplicativeExpression '/' UnaryExpression
+ // MultiplicativeExpression ::= MultiplicativeExpression '%' UnaryExpression
+ // AdditiveExpression ::= AdditiveExpression '+' MultiplicativeExpression
+ // AdditiveExpression ::= AdditiveExpression '-' MultiplicativeExpression
+ // ShiftExpression ::= ShiftExpression '<<' AdditiveExpression
+ // ShiftExpression ::= ShiftExpression '>>' AdditiveExpression
+ // ShiftExpression ::= ShiftExpression '>>>' AdditiveExpression
+ // RelationalExpression ::= RelationalExpression '<' ShiftExpression
+ // RelationalExpression ::= RelationalExpression '>' ShiftExpression
+ // RelationalExpression ::= RelationalExpression '<=' ShiftExpression
+ // RelationalExpression ::= RelationalExpression '>=' ShiftExpression
+ // AndExpression ::= AndExpression '&' EqualityExpression
+ // ExclusiveOrExpression ::= ExclusiveOrExpression '^' AndExpression
+ // InclusiveOrExpression ::= InclusiveOrExpression '|' ExclusiveOrExpression
+ // ConditionalAndExpression ::= ConditionalAndExpression '&&' InclusiveOrExpression
+ // ConditionalOrExpression ::= ConditionalOrExpression '||' ConditionalAndExpression
+
+ //optimize the push/pop
+
+ this.expressionPtr--;
+ this.expressionLengthPtr--;
+ Expression expr1 = this.expressionStack[this.expressionPtr];
+ Expression expr2 = this.expressionStack[this.expressionPtr + 1];
+ switch (op) {
+ case OR_OR:
+ this.expressionStack[this.expressionPtr] =
+ new OR_OR_Expression(
+ expr1,
+ expr2,
+ op);
+ break;
+ case AND_AND:
+ this.expressionStack[this.expressionPtr] =
+ new AND_AND_Expression(
+ expr1,
+ expr2,
+ op);
+ break;
+ case PLUS:
+ // look for "string1" + "string2"
+ // look for "string1" + "string2"
+ if (this.optimizeStringLiterals) {
+ if (expr1 instanceof StringLiteral) {
+ if (expr2 instanceof StringLiteral) { //string+string
+ this.expressionStack[this.expressionPtr] =
+ ((StringLiteral) expr1).extendWith((StringLiteral) expr2);
+ } else {
+ this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+ }
+ } else if (expr1 instanceof CombinedBinaryExpression) {
+ CombinedBinaryExpression cursor;
+ // left branch is comprised of PLUS BEs
+ // cursor is shifted upwards, while needed BEs are added
+ // on demand; past the arityMax-th
+ // consecutive BE, a CBE is inserted that holds a
+ // full-fledged references table
+ if ((cursor = (CombinedBinaryExpression) expr1).arity < cursor.arityMax) {
+ cursor.left = new BinaryExpression(cursor.left,
+ cursor.right, PLUS);
+ cursor.arity++;
+ } else {
+ cursor.left = new CombinedBinaryExpression(cursor.left,
+ cursor.right, PLUS, cursor.arity);
+ cursor.arity = 0;
+ cursor.tuneArityMax();
+ }
+ cursor.right = expr2;
+ cursor.sourceEnd = expr2.sourceEnd;
+ this.expressionStack[this.expressionPtr] = cursor;
+ // BE_INSTRUMENTATION: neutralized in the released code
+ // cursor.depthTracker = ((BinaryExpression)cursor.left).
+ // depthTracker + 1;
+ } else if (expr1 instanceof BinaryExpression &&
+ // single out the a + b case, which is a BE
+ // instead of a CBE (slightly more than a half of
+ // strings concatenation are one-deep binary
+ // expressions)
+ ((expr1.bits & ASTNode.OperatorMASK) >>
+ ASTNode.OperatorSHIFT) == OperatorIds.PLUS) {
+ this.expressionStack[this.expressionPtr] =
+ new CombinedBinaryExpression(expr1, expr2, PLUS, 1);
+ } else {
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(expr1, expr2, PLUS);
+ }
+ } else if (expr1 instanceof StringLiteral) {
+ if (expr2 instanceof StringLiteral) {
+ // string + string
+ this.expressionStack[this.expressionPtr] =
+ ((StringLiteral) expr1).extendsWith((StringLiteral) expr2);
+ } else {
+ // single out the a + b case
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(expr1, expr2, PLUS);
+ }
+ } else if (expr1 instanceof CombinedBinaryExpression) {
+ CombinedBinaryExpression cursor;
+ // shift cursor; create BE/CBE as needed
+ if ((cursor = (CombinedBinaryExpression) expr1).arity < cursor.arityMax) {
+ cursor.left = new BinaryExpression(cursor.left,
+ cursor.right, PLUS);
+ cursor.arity++;
+ } else {
+ cursor.left = new CombinedBinaryExpression(cursor.left,
+ cursor.right, PLUS, cursor.arity);
+ cursor.arity = 0;
+ cursor.tuneArityMax();
+ }
+ cursor.right = expr2;
+ cursor.sourceEnd = expr2.sourceEnd;
+ // BE_INSTRUMENTATION: neutralized in the released code
+ // cursor.depthTracker = ((BinaryExpression)cursor.left).
+ // depthTracker + 1;
+ this.expressionStack[this.expressionPtr] = cursor;
+ } else if (expr1 instanceof BinaryExpression &&
+ // single out the a + b case
+ ((expr1.bits & ASTNode.OperatorMASK) >>
+ ASTNode.OperatorSHIFT) == OperatorIds.PLUS) {
+ this.expressionStack[this.expressionPtr] =
+ new CombinedBinaryExpression(expr1, expr2, PLUS, 1);
+ } else {
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(expr1, expr2, PLUS);
+ }
+ break;
+ case LESS:
+ this.intPtr--;
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(
+ expr1,
+ expr2,
+ op);
+ break;
+ default:
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(
+ expr1,
+ expr2,
+ op);
+ }
+ }
+
+ protected void consumeBlock() {
+ // Block ::= OpenBlock '{' BlockStatementsopt '}'
+ // simpler action for empty blocks
+
+ int statementsLength = this.astLengthStack[this.astLengthPtr--];
+ Block block;
+ if (statementsLength == 0) { // empty block
+ block = new Block(0);
+ block.sourceStart = this.intStack[this.intPtr--];
+ block.sourceEnd = this.endStatementPosition;
+ // check whether this block at least contains some comment in it
+ if (!containsComment(block.sourceStart, block.sourceEnd)) {
+ block.bits |= ASTNode.UndocumentedEmptyBlock;
+ }
+ this.realBlockPtr--; // still need to pop the block variable counter
+ } else {
+ block = new Block(this.realBlockStack[this.realBlockPtr--]);
+ this.astPtr -= statementsLength;
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + 1,
+ block.statements = new Statement[statementsLength],
+ 0,
+ statementsLength);
+ block.sourceStart = this.intStack[this.intPtr--];
+ block.sourceEnd = this.endStatementPosition;
+ }
+ pushOnAstStack(block);
+ }
+
+ protected void consumeBlockStatements() {
+ // BlockStatements ::= BlockStatements BlockStatement
+ concatNodeLists();
+ }
+
+ protected void consumeProgramElements() {
+ // BlockStatements ::= BlockStatements BlockStatement
+ concatNodeLists();
+ }
+
+ protected void consumeCallExpressionWithArguments() {
+ //optimize the push/pop
+ //FunctionInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
+
+ MessageSend m = newMessageSend();
+ // m.sourceStart =
+ // (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32);
+ // m.selector = this.identifierStack[this.identifierPtr--];
+ // this.identifierLengthPtr--;
+
+ Expression receiver = this.expressionStack[this.expressionPtr];
+ m.sourceStart = receiver.sourceStart;
+ if (receiver instanceof SingleNameReference)
+ {
+ SingleNameReference singleNameReference = (SingleNameReference) receiver;
+ m.selector = singleNameReference.token;
+ m.nameSourcePosition = (((long) singleNameReference.sourceStart) << 32) + (singleNameReference.sourceStart + m.selector.length - 1);
+ receiver = null;
+
+ } else if (receiver instanceof FieldReference) {
+ FieldReference fieldReference = (FieldReference) receiver;
+ m.selector = fieldReference.token;
+ m.nameSourcePosition = (((long) (fieldReference.sourceEnd - (m.selector.length - 1))) << 32) + (fieldReference.sourceEnd);
+ receiver = fieldReference.receiver;
+ }
+
+ m.receiver = receiver;
+ m.sourceEnd = this.intStack[this.intPtr--];
+ this.expressionStack[this.expressionPtr] = m;
+ }
+
+ protected void consumeCallExpressionWithArrayReference() {
+ this.expressionPtr--;
+ this.expressionLengthPtr--;
+ Expression exp =
+ this.expressionStack[this.expressionPtr] =
+ new ArrayReference(
+ this.expressionStack[this.expressionPtr],
+ this.expressionStack[this.expressionPtr + 1]);
+ exp.sourceEnd = this.endPosition;
+ }
+
+ protected void consumeCallExpressionWithSimpleName() {
+ FieldReference fr =
+ new FieldReference(
+ this.identifierStack[this.identifierPtr],
+ this.identifierPositionStack[this.identifierPtr--]);
+ this.identifierLengthPtr--;
+ //optimize push/pop
+ fr.receiver = this.expressionStack[this.expressionPtr];
+ //fieldreference begins at the receiver
+ fr.sourceStart = fr.receiver.sourceStart;
+ this.expressionStack[this.expressionPtr] = fr;
+ }
+
+ protected void consumeCaseLabel() {
+ // SwitchLabel ::= 'case' ConstantExpression ':'
+ this.expressionLengthPtr--;
+ Expression expression = this.expressionStack[this.expressionPtr--];
+ pushOnAstStack(new CaseStatement(expression, expression.sourceEnd, this.intStack[this.intPtr--]));
+ }
+
+ protected void consumeCatches() {
+ // Catches ::= Catches CatchClause
+ optimizedConcatNodeLists();
+ }
+
+ protected void consumeCatchHeader() {
+ // CatchDeclaration ::= 'catch' '(' FormalParameter ')' '{'
+
+ if (this.currentElement == null) {
+ return; // should never occur, this consumeRule is only used in recovery mode
+ }
+ // current element should be a block due to the presence of the opening brace
+ if (!(this.currentElement instanceof RecoveredBlock)) {
+ if (!(this.currentElement instanceof RecoveredMethod)) {
+ return;
+ }
+ RecoveredMethod rMethod = (RecoveredMethod) this.currentElement;
+ if (!(rMethod.methodBody == null && rMethod.bracketBalance > 0)) {
+ return;
+ }
+ }
+
+ Argument arg = (Argument) this.astStack[this.astPtr--];
+ // convert argument to local variable
+ LocalDeclaration localDeclaration = new LocalDeclaration(arg.name, arg.sourceStart, arg.sourceEnd);
+ localDeclaration.type = arg.type;
+ localDeclaration.declarationSourceStart = arg.declarationSourceStart;
+ localDeclaration.declarationSourceEnd = arg.declarationSourceEnd;
+
+ this.currentElement = this.currentElement.add(localDeclaration, 0);
+ this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
+ this.restartRecovery = true; // request to restart from here on
+ this.lastIgnoredToken = -1;
+ }
+
+ protected void consumeClassOrInterfaceName() {
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ pushOnGenericsLengthStack(0); // handle type arguments
+ }
+
+ protected void consumeCompilationUnit() {
+ // JavaScriptUnit ::= EnterCompilationUnit InternalCompilationUnit
+ // do nothing by default
+ }
+
+ protected void consumeConditionalExpression(int op) {
+ // ConditionalExpression ::= ConditionalOrExpression '?' Expression ':' ConditionalExpression
+ //optimize the push/pop
+ this.intPtr -= 2;//consume position of the question mark
+ this.expressionPtr -= 2;
+ this.expressionLengthPtr -= 2;
+ this.expressionStack[this.expressionPtr] =
+ new ConditionalExpression(
+ this.expressionStack[this.expressionPtr],
+ this.expressionStack[this.expressionPtr + 1],
+ this.expressionStack[this.expressionPtr + 2]);
+ }
+
+ protected void consumeDefaultLabel() {
+ // SwitchLabel ::= 'default' ':'
+ pushOnAstStack(new CaseStatement(null, this.intStack[this.intPtr--], this.intStack[this.intPtr--]));
+ }
+
+ protected void consumeDefaultModifiers() {
+ checkComment(); // might update modifiers with AccDeprecated
+ pushOnIntStack(this.modifiers); // modifiers
+ pushOnIntStack(this.modifiersSourceStart >= 0 ? this.modifiersSourceStart : this.scanner.startPosition);
+ resetModifiers();
+ // pushOnExpressionStackLengthStack(0); // no annotation
+ }
+
+ protected void consumeDiet() {
+ // Diet ::= $empty
+ checkComment();
+ pushOnIntStack(this.modifiersSourceStart); // push the start position of a javadoc comment if there is one
+ resetModifiers();
+ jumpOverMethodBody();
+ }
+
+ protected void consumeDebuggerStatement() {
+ pushOnAstStack(new DebuggerStatement(this.intStack[this.intPtr--], this.endStatementPosition));
+ }
+
+ protected void consumeEmptyArgumentListopt() {
+ // ArgumentListopt ::= $empty
+ pushOnExpressionStackLengthStack(0);
+ }
+
+ protected void consumeEmptyArguments() {
+ // Argumentsopt ::= $empty
+ final FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr];
+ pushOnIntStack(fieldDeclaration.sourceEnd);
+ pushOnExpressionStackLengthStack(0);
+ }
+
+ protected void consumeEmptyBlockStatementsopt() {
+ // BlockStatementsopt ::= $empty
+ pushOnAstLengthStack(0);
+ }
+
+ protected void consumeEmptyCatchesopt() {
+ // Catchesopt ::= $empty
+ pushOnAstLengthStack(0);
+ }
+
+ protected void consumeEmptyExpression() {
+ // Expressionopt ::= $empty
+ pushOnExpressionStackLengthStack(0);
+ }
+
+ protected void consumeEmptyForInitopt() {
+ // ForInitopt ::= $empty
+ pushOnAstLengthStack(0);
+ }
+
+ protected void consumeEmptyForUpdateopt() {
+ // ForUpdateopt ::= $empty
+ pushOnExpressionStackLengthStack(0);
+ }
+
+ protected void consumeEmptyInternalCompilationUnit() {
+ // InternalCompilationUnit ::= $empty
+ // nothing to do by default
+ if (this.compilationUnit.isPackageInfo()) {
+ this.compilationUnit.types = new TypeDeclaration[1];
+ // create a fake interface declaration
+ TypeDeclaration declaration = new TypeDeclaration(compilationUnit.compilationResult);
+ declaration.name = TypeConstants.PACKAGE_INFO_NAME;
+ declaration.modifiers = ClassFileConstants.AccDefault;
+ this.compilationUnit.types[0] = declaration;
+ declaration.javadoc = this.compilationUnit.javadoc;
+ }
+ }
+
+ protected void consumeEmptyProgramElements() {
+ pushOnAstLengthStack(0);
+ }
+
+ protected void consumeEmptyObjectLiteral() {
+ ObjectLiteral objectLiteral = new ObjectLiteral();
+ objectLiteral.sourceEnd = this.endStatementPosition;
+ objectLiteral.sourceStart = this.intStack[this.intPtr--];
+
+ pushOnExpressionStack(objectLiteral);
+ }
+
+ protected void consumeEmptyPropertySetParameterList() {
+ pushOnExpressionStackLengthStack(0);
+ }
+
+ protected void consumeEmptyStatement() {
+ this.intPtr--;
+ // EmptyStatement ::= ';'
+ char[] source = this.scanner.source;
+ if (this.endStatementPosition >= source.length) {
+ // this would be inserted as a fake empty statement
+ pushOnAstStack(new EmptyStatement(this.endStatementPosition, this.endStatementPosition));
+ return;
+ }
+ int sourceStart = this.endStatementPosition;
+
+ if (source[this.endStatementPosition] != ';') {
+ if (source.length > 5 && this.endStatementPosition >= 4) {
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ int pos = this.endStatementPosition - 4;
+ while (source[pos] == 'u') {
+ pos--;
+ }
+ if (source[pos] == '\\' &&
+ !((c1 = ScannerHelper.getNumericValue(source[this.endStatementPosition - 3])) > 15
+ || c1 < 0
+ || (c2 = ScannerHelper.getNumericValue(source[this.endStatementPosition - 2])) > 15
+ || c2 < 0
+ || (c3 = ScannerHelper.getNumericValue(source[this.endStatementPosition - 1])) > 15
+ || c3 < 0
+ || (c4 = ScannerHelper.getNumericValue(source[this.endStatementPosition])) > 15
+ || c4 < 0) &&
+ ((char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4)) == ';') {
+ // we have a Unicode for the ';' (/u003B)
+ sourceStart = pos;
+ }
+ }
+ }
+ if (this.astPtr > -1) {
+ if (this.astStack[this.astPtr] instanceof IDoStatement) {
+ ASTNode node = this.astStack[this.astPtr];
+ node.setSourceEnd(this.endStatementPosition);
+ pushOnAstLengthStack(0);
+ return;
+ }
+ }
+ pushOnAstStack(new EmptyStatement(sourceStart, this.endStatementPosition));
+ }
+
+ protected void consumeEmptySwitchBlock() {
+ // SwitchBlock ::= '{' '}'
+ pushOnAstLengthStack(0);
+ }
+
+ protected void consumeEnterCompilationUnit() {
+ // EnterCompilationUnit ::= $empty
+ // do nothing by default
+ }
+
+ protected void consumeEnterVariable() {
+ // EnterVariable ::= $empty
+ // do nothing by default
+ checkComment();
+ resetModifiers();
+
+ char[] identifierName = this.identifierStack[this.identifierPtr];
+ long namePosition = this.identifierPositionStack[this.identifierPtr];
+ // int extendedDimension = this.intStack[this.intPtr--];
+ AbstractVariableDeclaration declaration;
+ // create the ast node
+ // boolean isLocalDeclaration = this.nestedMethod[this.nestedType] != 0;
+ // if (isLocalDeclaration) {
+ // // create the local variable declarations
+ declaration =
+ this.createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
+ // } else {
+ // create the field declaration
+ // declaration =
+ // this.createFieldDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
+ // }
+
+ this.identifierPtr--;
+ this.identifierLengthPtr--;
+ // TypeReference type;
+ int variableIndex = this.variablesCounter[this.nestedType];
+ // int typeDim = 0;
+ if (variableIndex == 0) {
+ // first variable of the declaration (FieldDeclaration or LocalDeclaration)
+ // if (isLocalDeclaration) {
+ // declaration.declarationSourceStart = this.intStack[this.intPtr--];
+ // declaration.modifiers = this.intStack[this.intPtr--];
+ // // consume annotations
+ // int length;
+ // if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ // System.arraycopy(
+ // this.expressionStack,
+ // (this.expressionPtr -= length) + 1,
+ // declaration.annotations = new Annotation[length],
+ // 0,
+ // length);
+ // }
+ // type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension
+ // if (declaration.declarationSourceStart == -1) {
+ // // this is true if there is no modifiers for the local variable declaration
+ // declaration.declarationSourceStart = type.sourceStart;
+ // }
+ // pushOnAstStack(type);
+ // } else {
+ // type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension
+ // pushOnAstStack(type);
+ int modifiersStart = this.intStack[this.intPtr--];
+ declaration.modifiers = this.intStack[this.intPtr--];
+ int varPosition = this.intStack[this.intPtr--];
+ declaration.declarationSourceStart = (modifiersStart >= 0) ? modifiersStart : varPosition;
+ this.expressionLengthPtr--;
+
+ // Store javadoc only on first declaration as it is the same for all ones
+ LocalDeclaration fieldDeclaration = (LocalDeclaration) declaration;
+ fieldDeclaration.javadoc = this.javadoc;
+ this.javadoc = null;
+ // }
+ } else {
+ // type = (TypeReference) this.astStack[this.astPtr - variableIndex];
+ // typeDim = type.dimensions();
+ AbstractVariableDeclaration previousVariable =
+ (AbstractVariableDeclaration) this.astStack[this.astPtr];
+ declaration.declarationSourceStart = previousVariable.declarationSourceStart;
+ declaration.modifiers = previousVariable.modifiers;
+ // final Annotation[] annotations = previousVariable.annotations;
+ // if (annotations != null) {
+ // final int annotationsLength = annotations.length;
+ // System.arraycopy(annotations, 0, declaration.annotations = new Annotation[annotationsLength], 0, annotationsLength);
+ // }
+ }
+
+ // if (extendedDimension == 0) {
+ // declaration.type = type;
+ // } else {
+ // int dimension = typeDim + extendedDimension;
+ // declaration.type = this.copyDims(type, dimension);
+ // }
+ this.variablesCounter[this.nestedType]++;
+ pushOnAstStack(declaration);
+ // recovery
+ if (this.currentElement != null) {
+ if (!(this.currentElement instanceof RecoveredUnit)
+ && (this.currentToken == TokenNameDOT
+ //|| declaration.modifiers != 0
+ || (Util.getLineNumber(declaration.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr)
+ != Util.getLineNumber((int) (namePosition >>> 32), this.scanner.lineEnds, 0, this.scanner.linePtr)))) {
+ this.lastCheckPoint = (int) (namePosition >>> 32);
+ this.restartRecovery = true;
+ return;
+ }
+ // if (isLocalDeclaration){
+ // LocalDeclaration localDecl = (LocalDeclaration) this.astStack[this.astPtr];
+ // this.lastCheckPoint = localDecl.sourceEnd + 1;
+ // this.currentElement = this.currentElement.add(localDecl, 0);
+ // } else {
+ LocalDeclaration fieldDecl = (LocalDeclaration) this.astStack[this.astPtr];
+ this.lastCheckPoint = fieldDecl.sourceEnd + 1;
+ this.currentElement = this.currentElement.add(fieldDecl, 0);
+ // }
+ this.lastIgnoredToken = -1;
+ }
+ }
+
+ protected void consumeEqualityExpression(int op) {
+ // EqualityExpression ::= EqualityExpression '==' RelationalExpression
+ // EqualityExpression ::= EqualityExpression '!=' RelationalExpression
+
+ //optimize the push/pop
+
+ this.expressionPtr--;
+ this.expressionLengthPtr--;
+ this.expressionStack[this.expressionPtr] =
+ new EqualExpression(
+ this.expressionStack[this.expressionPtr],
+ this.expressionStack[this.expressionPtr + 1],
+ op);
+ }
+
+ protected void consumeExitTryBlock() {
+ //ExitTryBlock ::= $empty
+ if (this.currentElement != null) {
+ this.restartRecovery = true;
+ }
+ }
+
+ protected void consumeExitVariableWithInitialization() {
+ // ExitVariableWithInitialization ::= $empty
+ // do nothing by default
+ this.expressionLengthPtr--;
+ AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) this.astStack[this.astPtr];
+ variableDecl.initialization = this.expressionStack[this.expressionPtr--];
+ // we need to update the declarationSourceEnd of the local variable declaration to the
+ // source end position of the initialization expression
+ variableDecl.declarationSourceEnd = variableDecl.initialization.sourceEnd;
+ variableDecl.declarationEnd = variableDecl.initialization.sourceEnd;
+
+ this.recoveryExitFromVariable();
+ }
+
+ protected void consumeExitVariableWithoutInitialization() {
+ // ExitVariableWithoutInitialization ::= $empty
+ // do nothing by default
+
+ AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) this.astStack[this.astPtr];
+ variableDecl.declarationSourceEnd = variableDecl.declarationEnd;
+ if (this.currentElement != null && this.currentElement instanceof RecoveredField) {
+ if (this.endStatementPosition > variableDecl.sourceEnd) {
+ this.currentElement.updateSourceEndIfNecessary(this.endStatementPosition);
+ }
+ }
+ this.recoveryExitFromVariable();
+ }
+
+ protected void consumeExpressionStatement() {
+ // ExpressionStatement ::= StatementExpression ';'
+ this.expressionLengthPtr--;
+ Expression expression = this.expressionStack[this.expressionPtr--];
+ expression.statementEnd = this.endStatementPosition;
+ pushOnAstStack(expression);
+ }
+
+ protected void consumeForceNoDiet() {
+ // ForceNoDiet ::= $empty
+ this.dietInt++;
+ }
+
+ protected void consumeForInit() {
+ // ForInit ::= StatementExpressionList
+ pushOnAstLengthStack(-1);
+ }
+
+ protected void consumeFormalParameter(boolean isVarArgs) {
+ // FormalParameter ::= Type VariableDeclaratorId ==> false
+ // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
+ /*
+ this.astStack :
+ this.identifierStack : type identifier
+ this.intStack : dim dim
+ ==>
+ this.astStack : Argument
+ this.identifierStack :
+ this.intStack :
+ */
+
+ this.identifierLengthPtr--;
+ char[] identifierName = this.identifierStack[this.identifierPtr];
+ long namePositions = this.identifierPositionStack[this.identifierPtr--];
+ // int extendedDimensions = this.intStack[this.intPtr--];
+ // int endOfEllipsis = 0;
+ // if (isVarArgs) {
+ // endOfEllipsis = this.intStack[this.intPtr--];
+ // }
+ // int firstDimensions = this.intStack[this.intPtr--];
+ // final int typeDimensions = firstDimensions + extendedDimensions;
+ // TypeReference type = getTypeReference(typeDimensions);
+ // if (isVarArgs) {
+ // type = copyDims(type, typeDimensions + 1);
+ // if (extendedDimensions == 0) {
+ // type.sourceEnd = endOfEllipsis;
+ // }
+ // type.bits |= ASTNode.IsVarArgs; // set isVarArgs
+ // }
+ // int modifierPositions = this.intStack[this.intPtr--];
+ // this.intPtr--;
+ int modifierPositions = (int) (namePositions >>> 32);
+ Argument arg =
+ new Argument(
+ identifierName,
+ namePositions,
+ null,
+ ClassFileConstants.AccDefault);
+ // this.intStack[this.intPtr + 1] & ~ClassFileConstants.AccDeprecated); // modifiers
+ arg.declarationSourceStart = modifierPositions;
+ // consume annotations
+ // int length;
+ // if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ // System.arraycopy(
+ // this.expressionStack,
+ // (this.expressionPtr -= length) + 1,
+ // arg.annotations = new Annotation[length],
+ // 0,
+ // length);
+ // }
+ if (this.options.inferOptions.saveArgumentComments)
+ {
+ handleArgumentComment(arg);
+ }
+
+ pushOnAstStack(arg);
+
+ /* if incomplete method header, this.listLength counter will not have been reset,
+ indicating that some arguments are available on the stack */
+ this.listLength++;
+ }
+
+ protected void handleArgumentComment(Argument arg)
+ {
+ int lastComment = this.scanner.commentPtr;
+
+ // if (this.modifiersSourceStart >= 0) {
+ // // eliminate comments located after modifierSourceStart if positionned
+ // while (lastComment >= 0 && this.scanner.commentStarts[lastComment] > this.modifiersSourceStart) lastComment--;
+ // }
+ if (lastComment >= 0 && this.scanner.commentStops[0] < 0) {
+ // consider all remaining leading comments to be part of current declaration
+ int start = this.scanner.commentStarts[0];
+ int end = this.scanner.commentStops[0];
+ arg.comment = CharOperation.subarray(this.scanner.source, start + 2, (-end) - 2);
+ this.scanner.commentPtr = -1;
+ }
+ }
+
+ protected void consumeFormalParameterList() {
+ // FormalParameterList ::= FormalParameterList ',' FormalParameter
+ optimizedConcatNodeLists();
+ }
+
+ protected void consumeFormalParameterListopt() {
+ // FormalParameterListopt ::= $empty
+ pushOnAstLengthStack(0);
+ }
+
+ protected void consumeGetSetPropertyAssignment(boolean isSetter) {
+ // remove two expressions property name/remove an optional property set parameter list
+ // remove all statement from function body
+ this.intPtr -= 2; // int pushed by consumeNestedMethod() and consumeOpenBlock() (called inside consumeMethodBody())
+ int length = this.astLengthStack[this.astLengthPtr--];
+ Statement[] statements = new Statement[length];
+ this.astPtr -= length;
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + 1,
+ statements,
+ 0,
+ length);
+ Expression varName = null;
+ if (isSetter) {
+ this.expressionLengthPtr--;
+ varName = this.expressionStack[this.expressionPtr--];
+ }
+ // property name
+ this.expressionLengthPtr--;
+ Expression propertyName = this.expressionStack[this.expressionPtr--];
+ // set or get
+ this.expressionLengthPtr--;
+ Expression expression = this.expressionStack[this.expressionPtr--];
+ int end = this.endStatementPosition;
+ int start = expression.sourceStart;
+
+ if (expression instanceof SingleNameReference) {
+ SingleNameReference reference = (SingleNameReference) expression;
+ if (isSetter) {
+ if (!CharOperation.equals(reference.token, "set".toCharArray())) {
+ // report error
+ //this.problemReporter().invalidValueForGetterSetter(expression, true);
+ }
+ } else {
+ if (!CharOperation.equals(reference.token, "get".toCharArray())) {
+ // report error
+ //this.problemReporter().invalidValueForGetterSetter(expression, false);
+ }
+ }
+ }
+ ObjectGetterSetterField getterSetterField = new ObjectGetterSetterField(propertyName, statements, varName, start, end);
+ pushOnExpressionStack(getterSetterField);
+ }
+
+ protected void consumeInternalCompilationUnitWithTypes() {
+ // InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports TypeDeclarations
+ // InternalCompilationUnit ::= PackageDeclaration TypeDeclarations
+ // InternalCompilationUnit ::= TypeDeclarations
+ // InternalCompilationUnit ::= ImportDeclarations ReduceImports TypeDeclarations
+ // consume type declarations
+ int length;
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ this.compilationUnit.statements = new ProgramElement[length];
+ this.astPtr -= length;
+ System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.statements, 0, length);
+ }
+ }
+
+ protected void consumeLabel() {
+ // Do nothing
+ }
+
+ protected void consumeLeftParen() {
+ // PushLPAREN ::= '('
+ pushOnIntStack(this.lParenPos);
+ }
+
+ protected void consumeLocalVariableDeclaration() {
+ // LocalVariableDeclaration ::= Modifiers Type VariableDeclarators ';'
+
+ /*
+ this.astStack :
+ this.expressionStack: Expression Expression ...... Expression
+ this.identifierStack : type identifier identifier ...... identifier
+ this.intStack : typeDim dim dim dim
+ ==>
+ this.astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
+ this.expressionStack :
+ this.identifierStack :
+ this.intStack :
+
+ */
+ // int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
+ //
+ // // update the this.astStack, this.astPtr and this.astLengthStack
+ // int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1;
+ // System.arraycopy(
+ // this.astStack,
+ // startIndex,
+ // this.astStack,
+ // startIndex - 1,
+ // variableDeclaratorsCounter);
+ // this.astPtr--; // remove the type reference
+ // this.astLengthStack[--this.astLengthPtr] = variableDeclaratorsCounter;
+ this.variablesCounter[this.nestedType] = 0;
+ }
+
+ protected void consumeLocalVariableDeclarationStatement() {
+ // LocalVariableDeclarationStatement ::= LocalVariableDeclaration ';'
+ // see blockReal in case of change: duplicated code
+ // increment the amount of declared variables for this block
+ this.realBlockStack[this.realBlockPtr]++;
+
+ // update source end to include the semi-colon
+ int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
+ AbstractVariableDeclaration nextDeclaration = null;
+ for (int i = 0; i < variableDeclaratorsCounter; i++) {
+ AbstractVariableDeclaration localDeclaration = (AbstractVariableDeclaration) this.astStack[this.astPtr - i];
+ localDeclaration.declarationSourceEnd = this.endStatementPosition;
+ localDeclaration.declarationEnd = this.endStatementPosition; // semi-colon included
+ localDeclaration.nextLocal = nextDeclaration;
+ nextDeclaration = localDeclaration;
+ }
+ this.astPtr -= variableDeclaratorsCounter - 1;
+ this.astLengthStack[this.astLengthPtr] = 1;
+ this.lastCheckPoint = endStatementPosition + 1;
+
+ }
+
+ protected void consumeMemberExpressionWithArrayReference() {
+ this.expressionPtr--;
+ this.expressionLengthPtr--;
+ Expression exp =
+ this.expressionStack[this.expressionPtr] =
+ new ArrayReference(
+ this.expressionStack[this.expressionPtr],
+ this.expressionStack[this.expressionPtr + 1]);
+ exp.sourceEnd = this.endPosition;
+ }
+
+ protected void consumeMemberExpressionWithSimpleName() {
+ FieldReference fr =
+ new FieldReference(
+ this.identifierStack[this.identifierPtr],
+ this.identifierPositionStack[this.identifierPtr--]);
+ this.identifierLengthPtr--;
+ //optimize push/pop
+ fr.receiver = this.expressionStack[this.expressionPtr];
+ //fieldreference begins at the receiver
+ fr.sourceStart = fr.receiver.sourceStart;
+ this.expressionStack[this.expressionPtr] = fr;
+ }
+
+ protected void consumeMethodBody() {
+ // MethodBody ::= NestedMethod '{' BlockStatementsopt '}'
+ this.nestedMethod[this.nestedType]--;
+ }
+
+ protected void consumeMethodDeclaration(boolean isNotAbstract) {
+ // FunctionDeclaration ::= MethodHeader MethodBody
+ // AbstractMethodDeclaration ::= MethodHeader ';'
+
+ /*
+ this.astStack : modifiers arguments throws statements
+ this.identifierStack : type name
+ this.intStack : dim dim dim
+ ==>
+ this.astStack : FunctionDeclaration
+ this.identifierStack :
+ this.intStack :
+ */
+
+ this.nestedType--;
+ int length;
+ if (isNotAbstract) {
+ // pop the position of the { (body of the method) pushed in block decl
+ this.intPtr--;
+ this.intPtr--;
+ }
+
+ int explicitDeclarations = 0;
+ Statement[] statements = null;
+ if (isNotAbstract) {
+ //statements
+ explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.astStack,
+ (this.astPtr -= length) + 1,
+ statements = new Statement[length],
+ 0,
+ length);
+ }
+ }
+
+ // now we know that we have a method declaration at the top of the ast stack
+ MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
+ md.statements = statements;
+ md.explicitDeclarations = explicitDeclarations;
+
+ // cannot be done in consumeMethodHeader because we have no idea whether or not there
+ // is a body when we reduce the method header
+ if (!isNotAbstract) { //remember the fact that the method has a semicolon body
+ md.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
+ } else if (!(this.diet && this.dietInt == 0) && statements == null && !containsComment(md.bodyStart, this.endPosition)) {
+ md.bits |= ASTNode.UndocumentedEmptyBlock;
+ }
+ // store the this.endPosition (position just before the '}') in case there is
+ // a trailing comment behind the end of the method
+ md.bodyEnd = this.endPosition;
+ md.sourceEnd = this.endPosition;
+ md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+ }
+
+ protected void consumeMethodHeader() {
+ // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
+ // AnnotationMethodHeader ::= AnnotationMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt
+ // RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt
+ // RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims MethodHeaderThrowsClause
+
+ // retrieve end position of method declarator
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) this.astStack[this.astPtr];
+
+ if (this.currentToken == TokenNameLBRACE) {
+ method.bodyStart = this.scanner.currentPosition;
+ }
+ else if (currentToken != TokenNameSEMICOLON) { // insert semicolon
+ currentToken = TokenNameSEMICOLON;
+ scanner.pushBack();
+ }
+ // recovery
+ if (this.currentElement != null) {
+ // if(method.isAnnotationMethod()) {
+ // method.modifiers |= AccSemicolonBody;
+ // method.declarationSourceEnd = this.scanner.currentPosition-1;
+ // method.bodyEnd = this.scanner.currentPosition-1;
+ // this.currentElement = this.currentElement.parent;
+ // } else
+ if (this.currentToken == TokenNameSEMICOLON /*&& !method.isAnnotationMethod()*/) {
+ method.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
+ method.declarationSourceEnd = this.scanner.currentPosition - 1;
+ method.bodyEnd = this.scanner.currentPosition - 1;
+ // if (this.currentElement.parseTree() == method && this.currentElement.parent != null) {
+ // this.currentElement = this.currentElement.parent;
+ // }
+ } else if (this.currentToken == TokenNameLBRACE) {
+ if (this.currentElement instanceof RecoveredMethod &&
+ ((RecoveredMethod) this.currentElement).methodDeclaration != method) {
+ this.ignoreNextOpeningBrace = true;
+ this.currentElement.bracketBalance++;
+ }
+ }
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
+ }
+
+ protected void consumeMethodHeaderName(boolean isAnonymous) {
+ // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ // AnnotationMethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ // RecoveryMethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ MethodDeclaration md = null;
+ // if(isAnnotationMethod) {
+ // md = new AnnotationMethodDeclaration(this.compilationUnit.compilationResult);
+ // this.recordStringLiterals = false;
+ // } else {
+ md = new MethodDeclaration(this.compilationUnit.compilationResult);
+ // }
+
+ md.exprStackPtr = this.expressionPtr;
+ //name
+ long selectorSource = -1;
+ if (!isAnonymous)
+ {
+ md.setSelector(this.identifierStack[this.identifierPtr]);
+ selectorSource = this.identifierPositionStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+ }
+
+ if (this.nestedType > 0)
+ markEnclosingMemberWithLocalType();
+
+ //type
+ // md.returnType = getTypeReference(this.intStack[this.intPtr--]);
+ //modifiers
+ int functionPos = this.intStack[this.intPtr--];
+ int modifierPos = this.intStack[this.intPtr--];
+ md.declarationSourceStart = (functionPos > modifierPos) ? modifierPos : functionPos;
+ md.modifiers = this.intStack[this.intPtr--];
+ // consume annotations
+ // int length;
+ // if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ // System.arraycopy(
+ // this.expressionStack,
+ // (this.expressionPtr -= length) + 1,
+ // md.annotations = new Annotation[length],
+ // 0,
+ // length);
+ // }
+ // javadoc
+ md.javadoc = this.javadoc;
+ this.javadoc = null;
+
+ //highlight starts at selector start
+ if (selectorSource >= 0)
+ md.sourceStart = (int) (selectorSource >>> 32);
+ else
+ md.sourceStart = md.declarationSourceStart;
+ pushOnAstStack(md);
+ md.sourceEnd = this.lParenPos;
+ md.bodyStart = this.lParenPos + 1;
+ this.listLength = 0; // initialize this.listLength before reading parameters/throws
+
+ incrementNestedType();
+
+ // recovery
+ if (this.currentElement != null) {
+ if (this.currentElement instanceof RecoveredType
+ //|| md.modifiers != 0
+ || true/* (this.scanner.getLineNumber(md.returnType.sourceStart)
+ == this.scanner.getLineNumber(md.sourceStart))*/) {
+ this.lastCheckPoint = md.bodyStart;
+ this.currentElement = this.currentElement.add(md, 0);
+ this.lastIgnoredToken = -1;
+ } else {
+ this.lastCheckPoint = md.sourceStart;
+ this.restartRecovery = true;
+ }
+ }
+ }
+
+ protected void consumeMethodHeaderRightParen() {
+ // MethodHeaderParameters ::= FormalParameterListopt ')'
+ int length = this.astLengthStack[this.astLengthPtr--];
+ this.astPtr -= length;
+ AbstractMethodDeclaration md = (AbstractMethodDeclaration) this.astStack[this.astPtr];
+ md.sourceEnd = this.rParenPos;
+ //arguments
+ if (length != 0) {
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + 1,
+ md.arguments = new Argument[length],
+ 0,
+ length);
+ }
+ md.bodyStart = this.rParenPos + 1;
+ this.listLength = 0; // reset this.listLength after having read all parameters
+ // recovery
+ if (this.currentElement != null) {
+ this.lastCheckPoint = md.bodyStart;
+ if (this.currentElement.parseTree() == md)
+ return;
+
+ // might not have been attached yet - in some constructor scenarii
+ if (md.isConstructor()) {
+ if ((length != 0)
+ || (this.currentToken == TokenNameLBRACE)
+ || (this.currentToken == TokenNamethrows)) {
+ this.currentElement = this.currentElement.add(md, 0);
+ this.lastIgnoredToken = -1;
+ }
+ }
+ }
+ }
+
+ protected void consumeModifiers2() {
+ this.expressionLengthStack[this.expressionLengthPtr - 1] += this.expressionLengthStack[this.expressionLengthPtr--];
+ }
+
+ protected void consumeNestedMethod() {
+ // NestedMethod ::= $empty
+ jumpOverMethodBody();
+ this.nestedMethod[this.nestedType]++;
+ pushOnIntStack(this.scanner.currentPosition);
+ consumeOpenBlock();
+ }
+
+ protected void consumeNestedType() {
+ // NestedType ::= $empty
+ incrementNestedType();
+ }
+
+ protected void incrementNestedType() {
+ int length = this.nestedMethod.length;
+ if (++this.nestedType >= length) {
+ System.arraycopy(
+ this.nestedMethod, 0,
+ this.nestedMethod = new int[length + 30], 0,
+ length);
+ // increase the size of the variablesCounter as well. It has to be consistent with the size of the nestedMethod collection
+ System.arraycopy(
+ this.variablesCounter, 0,
+ this.variablesCounter = new int[length + 30], 0,
+ length);
+ }
+ this.nestedMethod[this.nestedType] = 0;
+ this.variablesCounter[this.nestedType] = 0;
+ }
+
+ protected void consumeNewExpression() {
+ classInstanceCreation(false, true);
+ }
+
+ protected void consumeNewMemberExpressionWithArguments() {
+ classInstanceCreation(false, false);
+ }
+
+ protected void consumeOpenBlock() {
+ // OpenBlock ::= $empty
+
+ pushOnIntStack(this.scanner.startPosition);
+ int stackLength = this.realBlockStack.length;
+ if (++this.realBlockPtr >= stackLength) {
+ System.arraycopy(
+ this.realBlockStack, 0,
+ this.realBlockStack = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ this.realBlockStack[this.realBlockPtr] = 0;
+ }
+
+ protected void consumePostfixExpression() {
+ // PostfixExpression ::= Name
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+ }
+
+ protected void consumePrimaryNoNewArray() {
+ // PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN
+ final Expression parenthesizedExpression = this.expressionStack[this.expressionPtr];
+ updateSourcePosition(parenthesizedExpression);
+ int numberOfParenthesis = (parenthesizedExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+ parenthesizedExpression.bits &= ~ASTNode.ParenthesizedMASK;
+ parenthesizedExpression.bits |= (numberOfParenthesis + 1) << ASTNode.ParenthesizedSHIFT;
+ }
+
+ protected void consumePrimaryNoNewArrayThis() {
+ // PrimaryNoNewArray ::= 'this'
+ pushOnExpressionStack(new ThisReference(this.intStack[this.intPtr--], this.endPosition));
+ }
+
+ protected void consumePrimarySimpleName() {
+ // PrimaryNoNewArray ::= SimpleName
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+ }
+
+ protected void consumePropertyAssignment() {
+ // MemberValuePair ::= SimpleName '=' MemberValue
+ this.modifiersSourceStart = -1;
+ this.checkComment();
+ this.resetModifiers();
+
+ Expression value = this.expressionStack[this.expressionPtr--];
+ this.expressionLengthPtr--;
+
+ Expression field = this.expressionStack[this.expressionPtr--];
+ this.expressionLengthPtr--;
+ int end = value.sourceEnd;
+ int start = field.sourceStart;
+
+ ObjectLiteralField literalField = new ObjectLiteralField(field, value, start, end);
+ pushOnExpressionStack(literalField);
+
+ if (this.javadoc != null) {
+ literalField.javaDoc = this.javadoc;
+ }
+ else if (value instanceof FunctionExpression)
+ {
+ MethodDeclaration methodDeclaration = ((FunctionExpression) value).methodDeclaration;
+ literalField.javaDoc = methodDeclaration.javadoc;
+ methodDeclaration.javadoc = null;
+ }
+ this.javadoc = null;
+
+ // discard obsolete comments while inside methods or fields initializer (see bug 74369)
+ if (!(this.diet && this.dietInt == 0) && this.scanner.commentPtr >= 0) {
+ flushCommentsDefinedPriorTo(literalField.sourceEnd);
+ }
+ resetModifiers();
+ }
+
+ protected void consumePropertyName() {
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+ }
+
+ protected void consumePropertyNameAndValueList() {
+ concatExpressionLists();
+ }
+
+ protected void consumePropertySetParameterList() {
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+ }
+
+ protected void consumePushLeftBrace() {
+ pushOnIntStack(this.endPosition); // modifiers
+ }
+
+ protected void consumeArrayLiteralHeader() {
+ pushOnIntStack(this.endPosition); // modifiers
+ pushOnIntStack(0); // numExprs
+ }
+
+ protected void consumePushModifiers() {
+ checkComment(); // might update modifiers with AccDeprecated
+ pushOnIntStack(this.modifiers); // modifiers
+ pushOnIntStack(this.modifiersSourceStart);
+ resetModifiers();
+ pushOnExpressionStackLengthStack(0);
+ }
+
+ protected void consumePushPosition() {
+ // for source managment purpose
+ // PushPosition ::= $empty
+ pushOnIntStack(this.endPosition);
+ }
+
+ protected void consumeQualifiedName() {
+ // QualifiedName ::= Name '.' SimpleName
+ /*back from the recursive loop of QualifiedName.
+ Updates identifier length into the length stack*/
+
+ this.identifierLengthStack[--this.identifierLengthPtr]++;
+ }
+
+ protected void consumeRecoveryMethodHeaderName() {
+ // this method is call only inside recovery
+ // boolean isAnnotationMethod = false;
+ // if(this.currentElement instanceof RecoveredType) {
+ // isAnnotationMethod = (((RecoveredType)this.currentElement).typeDeclaration.modifiers & ClassFileConstants.AccAnnotation) != 0;
+ // } else {
+ // RecoveredType recoveredType = this.currentElement.enclosingType();
+ // if(recoveredType != null) {
+ // isAnnotationMethod = (recoveredType.typeDeclaration.modifiers & ClassFileConstants.AccAnnotation) != 0;
+ // }
+ // }
+ this.consumeMethodHeaderName(false);
+ }
+
+ protected void consumeRestoreDiet() {
+ // RestoreDiet ::= $empty
+ this.dietInt--;
+ }
+
+ protected void consumeRightParen() {
+ // PushRPAREN ::= ')'
+ pushOnIntStack(this.rParenPos);
+ }
+
+ private void consumeFunctionExpression() {
+
+ consumeMethodDeclaration(true);
+ MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr--];
+ this.astLengthPtr--;
+ FunctionExpression funcExpr = new FunctionExpression(md);
+ funcExpr.sourceEnd = md.declarationSourceEnd;
+ funcExpr.sourceStart = md.declarationSourceStart;
+ pushOnExpressionStack(funcExpr);
+ }
+
+ private void consumeStatementForIn() {
+ // int length;
+ Expression collection = null;
+ Statement iteratorVar;
+ boolean scope = true;
+
+ //statements
+ this.astLengthPtr--;
+ Statement statement = (Statement) this.astStack[this.astPtr--];
+
+ if (this.expressionLengthStack[this.expressionLengthPtr--] != 0)
+ collection = this.expressionStack[this.expressionPtr--];
+
+ this.astLengthPtr--;
+ iteratorVar = (Statement) this.astStack[this.astPtr--];
+ pushOnAstStack(new ForInStatement(
+ iteratorVar,
+ collection,
+ statement,
+ scope,
+ this.intStack[this.intPtr--],
+ this.endStatementPosition));
+
+ }
+
+ private void consumeArrayLiteralList() {
+ concatExpressionLists();
+ this.intStack[this.intPtr] &= ~(UNCONSUMED_ELISION | UNCONSUMED_LIT_ELEMENT);
+ }
+
+ private void consumeArrayLiteralListOne() {
+ if ((this.intStack[this.intPtr] & UNCONSUMED_ELISION) != 0)
+ {
+ concatExpressionLists();
+ this.intStack[this.intPtr] &= ~(UNCONSUMED_ELISION | UNCONSUMED_LIT_ELEMENT);
+ }
+
+ }
+
+ private void consumeListExpression() {
+ this.expressionPtr--;
+ this.expressionLengthPtr--;
+ Expression expr1 = this.expressionStack[this.expressionPtr];
+ Expression expr2 = this.expressionStack[this.expressionPtr + 1];
+ this.expressionStack[this.expressionPtr] =
+ new ListExpression(
+ expr1,
+ expr2);
+
+ }
+
+ protected void consumePostDoc() {
+
+ if (this.options.inferOptions.docLocation == InferOptions.DOC_LOCATION_AFTER)
+ {
+
+ }
+ }
+
+ //This method is part of an automatic generation : do NOT edit-modify
+ protected void consumeRule(int act) {
+ switch (act) {
+ case 23:
+ if (DEBUG) {
+ System.out.println("CompilationUnit ::= EnterCompilationUnit...");} //$NON-NLS-1$
+ consumeCompilationUnit();
+ break;
+
+ case 24:
+ if (DEBUG) {
+ System.out.println("InternalCompilationUnit ::= ProgramElements");} //$NON-NLS-1$
+ consumeInternalCompilationUnitWithTypes();
+ break;
+
+ case 25:
+ if (DEBUG) {
+ System.out.println("InternalCompilationUnit ::=");} //$NON-NLS-1$
+ consumeEmptyInternalCompilationUnit();
+ break;
+
+ case 26:
+ if (DEBUG) {
+ System.out.println("EnterCompilationUnit ::=");} //$NON-NLS-1$
+ consumeEnterCompilationUnit();
+ break;
+
+ case 30:
+ if (DEBUG) {
+ System.out.println("CatchHeader ::= catch LPAREN FormalParameter RPAREN...");} //$NON-NLS-1$
+ consumeCatchHeader();
+ break;
+
+ case 32:
+ if (DEBUG) {
+ System.out.println("VariableDeclarators ::= VariableDeclarators COMMA...");} //$NON-NLS-1$
+ consumeVariableDeclarators();
+ break;
+
+ case 34:
+ if (DEBUG) {
+ System.out.println("VariableDeclaratorsNoIn ::= VariableDeclaratorsNoIn COMMA");} //$NON-NLS-1$
+ consumeVariableDeclarators();
+ break;
+
+ case 39:
+ if (DEBUG) {
+ System.out.println("EnterVariable ::=");} //$NON-NLS-1$
+ consumeEnterVariable();
+ break;
+
+ case 40:
+ if (DEBUG) {
+ System.out.println("ExitVariableWithInitialization ::=");} //$NON-NLS-1$
+ consumeExitVariableWithInitialization();
+ break;
+
+ case 41:
+ if (DEBUG) {
+ System.out.println("ExitVariableWithoutInitialization ::=");} //$NON-NLS-1$
+ consumeExitVariableWithoutInitialization();
+ break;
+
+ case 42:
+ if (DEBUG) {
+ System.out.println("ForceNoDiet ::=");} //$NON-NLS-1$
+ consumeForceNoDiet();
+ break;
+
+ case 43:
+ if (DEBUG) {
+ System.out.println("RestoreDiet ::=");} //$NON-NLS-1$
+ consumeRestoreDiet();
+ break;
+
+ case 47:
+ if (DEBUG) {
+ System.out.println("FunctionExpression ::= FunctionExpressionHeader...");} //$NON-NLS-1$
+ // set to true to consume a method with a body
+ consumeFunctionExpression();
+ break;
+
+ case 48:
+ if (DEBUG) {
+ System.out.println("FunctionExpressionHeader ::= FunctionExpressionHeaderName");} //$NON-NLS-1$
+ consumeMethodHeader();
+ break;
+
+ case 49:
+ if (DEBUG) {
+ System.out.println("FunctionExpressionHeaderName ::= Modifiersopt function...");} //$NON-NLS-1$
+ consumeMethodHeaderName(false);
+ break;
+
+ case 50:
+ if (DEBUG) {
+ System.out.println("FunctionExpressionHeaderName ::= Modifiersopt function...");} //$NON-NLS-1$
+ consumeMethodHeaderName(true);
+ break;
+
+ case 52:
+ if (DEBUG) {
+ System.out.println("MethodDeclaration ::= MethodHeader MethodBody");} //$NON-NLS-1$
+ // set to true to consume a method with a body
+ consumeMethodDeclaration(true);
+ break;
+
+ case 53:
+ if (DEBUG) {
+ System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON");} //$NON-NLS-1$
+ // set to false to consume a method without body
+ consumeMethodDeclaration(false);
+ break;
+
+ case 54:
+ if (DEBUG) {
+ System.out.println("MethodHeader ::= MethodHeaderName FormalParameterListopt");} //$NON-NLS-1$
+ consumeMethodHeader();
+ break;
+
+ case 55:
+ if (DEBUG) {
+ System.out.println("MethodHeaderName ::= Modifiersopt function Identifier...");} //$NON-NLS-1$
+ consumeMethodHeaderName(false);
+ break;
+
+ case 56:
+ if (DEBUG) {
+ System.out.println("MethodHeaderRightParen ::= RPAREN");} //$NON-NLS-1$
+ consumeMethodHeaderRightParen();
+ break;
+
+ case 58:
+ if (DEBUG) {
+ System.out.println("FormalParameterList ::= FormalParameterList COMMA...");} //$NON-NLS-1$
+ consumeFormalParameterList();
+ break;
+
+ case 59:
+ if (DEBUG) {
+ System.out.println("FormalParameter ::= VariableDeclaratorId");} //$NON-NLS-1$
+ consumeFormalParameter(false);
+ break;
+
+ case 60:
+ if (DEBUG) {
+ System.out.println("MethodBody ::= NestedMethod LBRACE PostDoc...");} //$NON-NLS-1$
+ consumeMethodBody();
+ break;
+
+ case 61:
+ if (DEBUG) {
+ System.out.println("NestedMethod ::=");} //$NON-NLS-1$
+ consumeNestedMethod();
+ break;
+
+ case 62:
+ if (DEBUG) {
+ System.out.println("PostDoc ::=");} //$NON-NLS-1$
+ consumePostDoc();
+ break;
+
+ case 63:
+ if (DEBUG) {
+ System.out.println("PushLeftBraceObjectLiteral ::=");} //$NON-NLS-1$
+ consumePushLeftBrace();
+ break;
+
+ case 64:
+ if (DEBUG) {
+ System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE");} //$NON-NLS-1$
+ consumeBlock();
+ break;
+
+ case 65:
+ if (DEBUG) {
+ System.out.println("OpenBlock ::=");} //$NON-NLS-1$
+ consumeOpenBlock();
+ break;
+
+ case 67:
+ if (DEBUG) {
+ System.out.println("ProgramElements ::= ProgramElements ProgramElement");} //$NON-NLS-1$
+ consumeProgramElements();
+ break;
+
+ case 70:
+ if (DEBUG) {
+ System.out.println("BlockStatements ::= BlockStatements BlockStatement");} //$NON-NLS-1$
+ consumeBlockStatements();
+ break;
+
+ case 74:
+ if (DEBUG) {
+ System.out.println("LocalVariableDeclarationStatement ::=...");} //$NON-NLS-1$
+ consumeLocalVariableDeclarationStatement();
+ break;
+
+ case 75:
+ if (DEBUG) {
+ System.out.println("LocalVariableDeclaration ::= var PushModifiers...");} //$NON-NLS-1$
+ consumeLocalVariableDeclaration();
+ break;
+
+ case 76:
+ if (DEBUG) {
+ System.out.println("LocalVariableDeclarationNoIn ::= var PushModifiers...");} //$NON-NLS-1$
+ consumeLocalVariableDeclaration();
+ break;
+
+ case 77:
+ if (DEBUG) {
+ System.out.println("PushModifiers ::=");} //$NON-NLS-1$
+ consumePushModifiers();
+ break;
+
+ case 102:
+ if (DEBUG) {
+ System.out.println("EmptyStatement ::= PushPosition SEMICOLON");} //$NON-NLS-1$
+ consumeEmptyStatement();
+ break;
+
+ case 103:
+ if (DEBUG) {
+ System.out.println("LabeledStatement ::= Label COLON Statement");} //$NON-NLS-1$
+ consumeStatementLabel();
+ break;
+
+ case 104:
+ if (DEBUG) {
+ System.out.println("LabeledStatementNoShortIf ::= Label COLON...");} //$NON-NLS-1$
+ consumeStatementLabel();
+ break;
+
+ case 105:
+ if (DEBUG) {
+ System.out.println("Label ::= Identifier");} //$NON-NLS-1$
+ consumeLabel();
+ break;
+
+ case 106:
+ if (DEBUG) {
+ System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON");} //$NON-NLS-1$
+ consumeExpressionStatement();
+ break;
+
+ case 108:
+ if (DEBUG) {
+ System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN...");} //$NON-NLS-1$
+ consumeStatementIfNoElse();
+ break;
+
+ case 109:
+ if (DEBUG) {
+ System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN...");} //$NON-NLS-1$
+ consumeStatementIfWithElse();
+ break;
+
+ case 110:
+ if (DEBUG) {
+ System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression...");} //$NON-NLS-1$
+ consumeStatementIfWithElse();
+ break;
+
+ case 111:
+ if (DEBUG) {
+ System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN...");} //$NON-NLS-1$
+ consumeStatementIfWithElse();
+ break;
+
+ case 112:
+ if (DEBUG) {
+ System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression...");} //$NON-NLS-1$
+ consumeStatementIfWithElse();
+ break;
+
+ case 113:
+ if (DEBUG) {
+ System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN...");} //$NON-NLS-1$
+ consumeStatementSwitch();
+ break;
+
+ case 114:
+ if (DEBUG) {
+ System.out.println("SwitchBlock ::= LBRACE RBRACE");} //$NON-NLS-1$
+ consumeEmptySwitchBlock();
+ break;
+
+ case 117:
+ if (DEBUG) {
+ System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements...");} //$NON-NLS-1$
+ consumeSwitchBlock();
+ break;
+
+ case 119:
+ if (DEBUG) {
+ System.out.println("SwitchBlockStatements ::= SwitchBlockStatements...");} //$NON-NLS-1$
+ consumeSwitchBlockStatements();
+ break;
+
+ case 120:
+ if (DEBUG) {
+ System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements");} //$NON-NLS-1$
+ consumeSwitchBlockStatement();
+ break;
+
+ case 122:
+ if (DEBUG) {
+ System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel");} //$NON-NLS-1$
+ consumeSwitchLabels();
+ break;
+
+ case 123:
+ if (DEBUG) {
+ System.out.println("SwitchLabel ::= case ConstantExpression COLON");} //$NON-NLS-1$
+ consumeCaseLabel();
+ break;
+
+ case 124:
+ if (DEBUG) {
+ System.out.println("SwitchLabel ::= default COLON");} //$NON-NLS-1$
+ consumeDefaultLabel();
+ break;
+
+ case 125:
+ if (DEBUG) {
+ System.out.println("WhileStatement ::= while LPAREN Expression RPAREN...");} //$NON-NLS-1$
+ consumeStatementWhile();
+ break;
+
+ case 126:
+ if (DEBUG) {
+ System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression...");} //$NON-NLS-1$
+ consumeStatementWhile();
+ break;
+
+ case 127:
+ if (DEBUG) {
+ System.out.println("WithStatement ::= with LPAREN Expression RPAREN...");} //$NON-NLS-1$
+ consumeStatementWith();
+ break;
+
+ case 128:
+ if (DEBUG) {
+ System.out.println("WithStatementNoShortIf ::= with LPAREN Expression RPAREN");} //$NON-NLS-1$
+ consumeStatementWith();
+ break;
+
+ case 129:
+ if (DEBUG) {
+ System.out.println("DoStatement ::= do Statement while LPAREN Expression...");} //$NON-NLS-1$
+ consumeStatementDo();
+ break;
+
+ case 130:
+ if (DEBUG) {
+ System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON...");} //$NON-NLS-1$
+ consumeStatementFor();
+ break;
+
+ case 131:
+ if (DEBUG) {
+ System.out.println("ForStatement ::= for LPAREN ForInInit in Expression...");} //$NON-NLS-1$
+ consumeStatementForIn();
+ break;
+
+ case 132:
+ if (DEBUG) {
+ System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt...");} //$NON-NLS-1$
+ consumeStatementFor();
+ break;
+
+ case 133:
+ if (DEBUG) {
+ System.out.println("ForStatementNoShortIf ::= for LPAREN ForInInit in...");} //$NON-NLS-1$
+ consumeStatementForIn();
+ break;
+
+ case 134:
+ if (DEBUG) {
+ System.out.println("ForInInit ::= LeftHandSideExpression");} //$NON-NLS-1$
+ consumeForInInit();
+ break;
+
+ case 136:
+ if (DEBUG) {
+ System.out.println("ForInit ::= ExpressionNoIn");} //$NON-NLS-1$
+ consumeForInit();
+ break;
+
+ case 140:
+ if (DEBUG) {
+ System.out.println("StatementExpressionList ::= StatementExpressionList...");} //$NON-NLS-1$
+ consumeStatementExpressionList();
+ break;
+
+ case 141:
+ if (DEBUG) {
+ System.out.println("BreakStatement ::= break SEMICOLON");} //$NON-NLS-1$
+ consumeStatementBreak();
+ break;
+
+ case 142:
+ if (DEBUG) {
+ System.out.println("BreakStatement ::= break Identifier SEMICOLON");} //$NON-NLS-1$
+ consumeStatementBreakWithLabel();
+ break;
+
+ case 143:
+ if (DEBUG) {
+ System.out.println("ContinueStatement ::= continue SEMICOLON");} //$NON-NLS-1$
+ consumeStatementContinue();
+ break;
+
+ case 144:
+ if (DEBUG) {
+ System.out.println("ContinueStatement ::= continue Identifier SEMICOLON");} //$NON-NLS-1$
+ consumeStatementContinueWithLabel();
+ break;
+
+ case 145:
+ if (DEBUG) {
+ System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON");} //$NON-NLS-1$
+ consumeStatementReturn();
+ break;
+
+ case 146:
+ if (DEBUG) {
+ System.out.println("ThrowStatement ::= throw Expression SEMICOLON");} //$NON-NLS-1$
+ consumeStatementThrow();
+ break;
+
+ case 147:
+ if (DEBUG) {
+ System.out.println("TryStatement ::= try TryBlock Catches");} //$NON-NLS-1$
+ consumeStatementTry(false);
+ break;
+
+ case 148:
+ if (DEBUG) {
+ System.out.println("TryStatement ::= try TryBlock Catchesopt Finally");} //$NON-NLS-1$
+ consumeStatementTry(true);
+ break;
+
+ case 150:
+ if (DEBUG) {
+ System.out.println("ExitTryBlock ::=");} //$NON-NLS-1$
+ consumeExitTryBlock();
+ break;
+
+ case 152:
+ if (DEBUG) {
+ System.out.println("Catches ::= Catches CatchClause");} //$NON-NLS-1$
+ consumeCatches();
+ break;
+
+ case 153:
+ if (DEBUG) {
+ System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN...");} //$NON-NLS-1$
+ consumeStatementCatch();
+ break;
+
+ case 155:
+ if (DEBUG) {
+ System.out.println("DebuggerStatement ::= debugger SEMICOLON");} //$NON-NLS-1$
+ consumeDebuggerStatement();
+ break;
+
+ case 156:
+ if (DEBUG) {
+ System.out.println("PushLPAREN ::= LPAREN");} //$NON-NLS-1$
+ consumeLeftParen();
+ break;
+
+ case 157:
+ if (DEBUG) {
+ System.out.println("PushRPAREN ::= RPAREN");} //$NON-NLS-1$
+ consumeRightParen();
+ break;
+
+ case 162:
+ if (DEBUG) {
+ System.out.println("PrimaryNoNewArray ::= SimpleName");} //$NON-NLS-1$
+ consumePrimarySimpleName();
+ break;
+
+ case 163:
+ if (DEBUG) {
+ System.out.println("PrimaryNoNewArray ::= this");} //$NON-NLS-1$
+ consumePrimaryNoNewArrayThis();
+ break;
+
+ case 164:
+ if (DEBUG) {
+ System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN");} //$NON-NLS-1$
+ consumePrimaryNoNewArray();
+ break;
+
+ case 165:
+ if (DEBUG) {
+ System.out.println("ObjectLiteral ::= LBRACE PushLeftBraceObjectLiteral...");} //$NON-NLS-1$
+ consumeEmptyObjectLiteral();
+ break;
+
+ case 166:
+ if (DEBUG) {
+ System.out.println("ObjectLiteral ::= LBRACE PushLeftBraceObjectLiteral...");} //$NON-NLS-1$
+ consumeObjectLiteral();
+ break;
+
+ case 167:
+ if (DEBUG) {
+ System.out.println("ObjectLiteral ::= LBRACE PushLeftBraceObjectLiteral...");} //$NON-NLS-1$
+ consumeObjectLiteral();
+ break;
+
+ case 169:
+ if (DEBUG) {
+ System.out.println("PropertyNameAndValueList ::= PropertyNameAndValueList...");} //$NON-NLS-1$
+ consumePropertyNameAndValueList();
+ break;
+
+ case 170:
+ if (DEBUG) {
+ System.out.println("PropertyAssignment ::= PropertyName COLON...");} //$NON-NLS-1$
+ consumePropertyAssignment();
+ break;
+
+ case 171:
+ if (DEBUG) {
+ System.out.println("PropertyAssignment ::= PropertyName PropertyName LPAREN");} //$NON-NLS-1$
+ consumeGetSetPropertyAssignment(false);
+ break;
+
+ case 172:
+ if (DEBUG) {
+ System.out.println("PropertyAssignment ::= PropertyName PropertyName LPAREN");} //$NON-NLS-1$
+ consumeGetSetPropertyAssignment(true);
+ break;
+
+ case 173:
+ if (DEBUG) {
+ System.out.println("PropertySetParameterList ::= SimpleName");} //$NON-NLS-1$
+ consumePropertySetParameterList();
+ break;
+
+ case 174:
+ if (DEBUG) {
+ System.out.println("FunctionBody ::= NestedMethod LBRACE PostDoc...");} //$NON-NLS-1$
+ consumeMethodBody();
+ break;
+
+ case 175:
+ if (DEBUG) {
+ System.out.println("ProgramElementsopt ::=");} //$NON-NLS-1$
+ consumeEmptyProgramElements();
+ break;
+
+ case 177:
+ if (DEBUG) {
+ System.out.println("PropertyName ::= SimpleName");} //$NON-NLS-1$
+ consumePropertyName();
+ break;
+
+ case 181:
+ if (DEBUG) {
+ System.out.println("ArrayLiteral ::= ArrayLiteralHeader ElisionOpt RBRACKET");} //$NON-NLS-1$
+ consumeArrayLiteral(false);
+ break;
+
+ case 182:
+ if (DEBUG) {
+ System.out.println("ArrayLiteral ::= ArrayLiteralHeader...");} //$NON-NLS-1$
+ consumeArrayLiteral(false);
+ break;
+
+ case 183:
+ if (DEBUG) {
+ System.out.println("ArrayLiteral ::= ArrayLiteralHeader...");} //$NON-NLS-1$
+ consumeArrayLiteral(true);
+ break;
+
+ case 184:
+ if (DEBUG) {
+ System.out.println("ArrayLiteralHeader ::= LBRACKET");} //$NON-NLS-1$
+ consumeArrayLiteralHeader();
+ break;
+
+ case 185:
+ if (DEBUG) {
+ System.out.println("ElisionOpt ::=");} //$NON-NLS-1$
+ consumeElisionEmpty();
+ break;
+
+ case 187:
+ if (DEBUG) {
+ System.out.println("Elision ::= COMMA");} //$NON-NLS-1$
+ consumeElisionOne();
+ break;
+
+ case 188:
+ if (DEBUG) {
+ System.out.println("Elision ::= Elision COMMA");} //$NON-NLS-1$
+ consumeElisionList();
+ break;
+
+ case 189:
+ if (DEBUG) {
+ System.out.println("ArrayLiteralElementList ::= ElisionOpt...");} //$NON-NLS-1$
+ consumeArrayLiteralListOne();
+ break;
+
+ case 190:
+ if (DEBUG) {
+ System.out.println("ArrayLiteralElementList ::= ArrayLiteralElementList...");} //$NON-NLS-1$
+ consumeArrayLiteralList();
+ break;
+
+ case 191:
+ if (DEBUG) {
+ System.out.println("ArrayLiteralElement ::= AssignmentExpression");} //$NON-NLS-1$
+ consumeArrayLiteralElement();
+ break;
+
+ case 194:
+ if (DEBUG) {
+ System.out.println("MemberExpression ::= MemberExpression LBRACKET...");} //$NON-NLS-1$
+ consumeMemberExpressionWithArrayReference();
+ break;
+
+ case 195:
+ if (DEBUG) {
+ System.out.println("MemberExpression ::= MemberExpression DOT SimpleName");} //$NON-NLS-1$
+ consumeMemberExpressionWithSimpleName();
+ break;
+
+ case 196:
+ if (DEBUG) {
+ System.out.println("MemberExpression ::= new MemberExpression Arguments");} //$NON-NLS-1$
+ consumeNewMemberExpressionWithArguments();
+ break;
+
+ case 198:
+ if (DEBUG) {
+ System.out.println("NewExpression ::= new NewExpression");} //$NON-NLS-1$
+ consumeNewExpression();
+ break;
+
+ case 199:
+ if (DEBUG) {
+ System.out.println("CallExpression ::= MemberExpression Arguments");} //$NON-NLS-1$
+ consumeCallExpressionWithArguments();
+ break;
+
+ case 200:
+ if (DEBUG) {
+ System.out.println("CallExpression ::= CallExpression Arguments");} //$NON-NLS-1$
+ consumeCallExpressionWithArguments();
+ break;
+
+ case 201:
+ if (DEBUG) {
+ System.out.println("CallExpression ::= CallExpression LBRACKET Expression...");} //$NON-NLS-1$
+ consumeCallExpressionWithArrayReference();
+ break;
+
+ case 202:
+ if (DEBUG) {
+ System.out.println("CallExpression ::= CallExpression DOT SimpleName");} //$NON-NLS-1$
+ consumeCallExpressionWithSimpleName();
+ break;
+
+ case 206:
+ if (DEBUG) {
+ System.out.println("PostfixExpression ::= LeftHandSideExpression PLUS_PLUS");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS, true);
+ break;
+
+ case 207:
+ if (DEBUG) {
+ System.out.println("PostfixExpression ::= LeftHandSideExpression MINUS_MINUS");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS, true);
+ break;
+
+ case 209:
+ if (DEBUG) {
+ System.out.println("ListExpression ::= ListExpression COMMA...");} //$NON-NLS-1$
+ consumeListExpression();
+ break;
+
+ case 211:
+ if (DEBUG) {
+ System.out.println("ListExpressionNoIn ::= ListExpressionNoIn COMMA...");} //$NON-NLS-1$
+ consumeListExpression();
+ break;
+
+ case 213:
+ if (DEBUG) {
+ System.out.println("ListExpressionStmt ::= ListExpressionStmt COMMA...");} //$NON-NLS-1$
+ consumeListExpression();
+ break;
+
+ case 215:
+ if (DEBUG) {
+ System.out.println("ArgumentList ::= ArgumentList COMMA AssignmentExpression");} //$NON-NLS-1$
+ consumeArgumentList();
+ break;
+
+ case 216:
+ if (DEBUG) {
+ System.out.println("PushPosition ::=");} //$NON-NLS-1$
+ consumePushPosition();
+ break;
+
+ case 219:
+ if (DEBUG) {
+ System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS);
+ break;
+
+ case 220:
+ if (DEBUG) {
+ System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS);
+ break;
+
+ case 222:
+ if (DEBUG) {
+ System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS, false);
+ break;
+
+ case 223:
+ if (DEBUG) {
+ System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS, false);
+ break;
+
+ case 225:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.TWIDDLE);
+ break;
+
+ case 226:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.NOT);
+ break;
+
+ case 227:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinus ::= delete PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.DELETE);
+ break;
+
+ case 228:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinus ::= void PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.VOID);
+ break;
+
+ case 229:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinus ::= typeof PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.TYPEOF);
+ break;
+
+ case 231:
+ if (DEBUG) {
+ System.out.println("MultiplicativeExpression ::= MultiplicativeExpression...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.MULTIPLY);
+ break;
+
+ case 232:
+ if (DEBUG) {
+ System.out.println("MultiplicativeExpression ::= MultiplicativeExpression...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.DIVIDE);
+ break;
+
+ case 233:
+ if (DEBUG) {
+ System.out.println("MultiplicativeExpression ::= MultiplicativeExpression...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.REMAINDER);
+ break;
+
+ case 235:
+ if (DEBUG) {
+ System.out.println("AdditiveExpression ::= AdditiveExpression PLUS...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.PLUS);
+ break;
+
+ case 236:
+ if (DEBUG) {
+ System.out.println("AdditiveExpression ::= AdditiveExpression MINUS...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.MINUS);
+ break;
+
+ case 238:
+ if (DEBUG) {
+ System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LEFT_SHIFT);
+ break;
+
+ case 239:
+ if (DEBUG) {
+ System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);
+ break;
+
+ case 240:
+ if (DEBUG) {
+ System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);
+ break;
+
+ case 242:
+ if (DEBUG) {
+ System.out.println("RelationalExpression ::= RelationalExpression LESS...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS);
+ break;
+
+ case 243:
+ if (DEBUG) {
+ System.out.println("RelationalExpression ::= RelationalExpression GREATER...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER);
+ break;
+
+ case 244:
+ if (DEBUG) {
+ System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS_EQUAL);
+ break;
+
+ case 245:
+ if (DEBUG) {
+ System.out.println("RelationalExpression ::= RelationalExpression...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER_EQUAL);
+ break;
+
+ case 246:
+ if (DEBUG) {
+ System.out.println("RelationalExpression ::= RelationalExpression instanceof");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.INSTANCEOF);
+ break;
+
+ case 247:
+ if (DEBUG) {
+ System.out.println("RelationalExpression ::= RelationalExpression in...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.IN);
+ break;
+
+ case 249:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionNoIn ::= RelationalExpressionNoIn...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS);
+ break;
+
+ case 250:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionNoIn ::= RelationalExpressionNoIn...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER);
+ break;
+
+ case 251:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionNoIn ::= RelationalExpressionNoIn...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS_EQUAL);
+ break;
+
+ case 252:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionNoIn ::= RelationalExpressionNoIn...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER_EQUAL);
+ break;
+
+ case 253:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionNoIn ::= RelationalExpressionNoIn...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.INSTANCEOF);
+ break;
+
+ case 255:
+ if (DEBUG) {
+ System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);
+ break;
+
+ case 256:
+ if (DEBUG) {
+ System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.NOT_EQUAL);
+ break;
+
+ case 257:
+ if (DEBUG) {
+ System.out.println("EqualityExpression ::= EqualityExpression...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL_EQUAL);
+ break;
+
+ case 258:
+ if (DEBUG) {
+ System.out.println("EqualityExpression ::= EqualityExpression...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.NOT_EQUAL_EQUAL);
+ break;
+
+ case 260:
+ if (DEBUG) {
+ System.out.println("EqualityExpressionNoIn ::= EqualityExpressionNoIn...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);
+ break;
+
+ case 261:
+ if (DEBUG) {
+ System.out.println("EqualityExpressionNoIn ::= EqualityExpressionNoIn...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.NOT_EQUAL);
+ break;
+
+ case 262:
+ if (DEBUG) {
+ System.out.println("EqualityExpressionNoIn ::= EqualityExpressionNoIn...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL_EQUAL);
+ break;
+
+ case 263:
+ if (DEBUG) {
+ System.out.println("EqualityExpressionNoIn ::= EqualityExpressionNoIn...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.NOT_EQUAL_EQUAL);
+ break;
+
+ case 265:
+ if (DEBUG) {
+ System.out.println("AndExpression ::= AndExpression AND EqualityExpression");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND);
+ break;
+
+ case 267:
+ if (DEBUG) {
+ System.out.println("AndExpressionNoIn ::= AndExpressionNoIn AND...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND);
+ break;
+
+ case 269:
+ if (DEBUG) {
+ System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.XOR);
+ break;
+
+ case 271:
+ if (DEBUG) {
+ System.out.println("ExclusiveOrExpressionNoIn ::= ExclusiveOrExpressionNoIn");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.XOR);
+ break;
+
+ case 273:
+ if (DEBUG) {
+ System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR);
+ break;
+
+ case 275:
+ if (DEBUG) {
+ System.out.println("InclusiveOrExpressionNoIn ::= InclusiveOrExpressionNoIn");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR);
+ break;
+
+ case 277:
+ if (DEBUG) {
+ System.out.println("ConditionalAndExpression ::= ConditionalAndExpression...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND_AND);
+ break;
+
+ case 279:
+ if (DEBUG) {
+ System.out.println("ConditionalAndExpressionNoIn ::=...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND_AND);
+ break;
+
+ case 281:
+ if (DEBUG) {
+ System.out.println("ConditionalOrExpression ::= ConditionalOrExpression...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR_OR);
+ break;
+
+ case 283:
+ if (DEBUG) {
+ System.out.println("ConditionalOrExpressionNoIn ::=...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR_OR);
+ break;
+
+ case 285:
+ if (DEBUG) {
+ System.out.println("ConditionalExpression ::= ConditionalOrExpression...");} //$NON-NLS-1$
+ consumeConditionalExpression(OperatorIds.QUESTIONCOLON);
+ break;
+
+ case 287:
+ if (DEBUG) {
+ System.out.println("ConditionalExpressionNoIn ::=...");} //$NON-NLS-1$
+ consumeConditionalExpression(OperatorIds.QUESTIONCOLON);
+ break;
+
+ case 292:
+ if (DEBUG) {
+ System.out.println("Assignment ::= PostfixExpression AssignmentOperator...");} //$NON-NLS-1$
+ consumeAssignment();
+ break;
+
+ case 293:
+ if (DEBUG) {
+ System.out.println("AssignmentNoIn ::= PostfixExpression AssignmentOperator");} //$NON-NLS-1$
+ consumeAssignment();
+ break;
+
+ case 294:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(EQUAL);
+ break;
+
+ case 295:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(MULTIPLY);
+ break;
+
+ case 296:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= DIVIDE_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(DIVIDE);
+ break;
+
+ case 297:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= REMAINDER_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(REMAINDER);
+ break;
+
+ case 298:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= PLUS_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(PLUS);
+ break;
+
+ case 299:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= MINUS_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(MINUS);
+ break;
+
+ case 300:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(LEFT_SHIFT);
+ break;
+
+ case 301:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(RIGHT_SHIFT);
+ break;
+
+ case 302:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);
+ break;
+
+ case 303:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= AND_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(AND);
+ break;
+
+ case 304:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= XOR_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(XOR);
+ break;
+
+ case 305:
+ if (DEBUG) {
+ System.out.println("AssignmentOperator ::= OR_EQUAL");} //$NON-NLS-1$
+ consumeAssignmentOperator(OR);
+ break;
+
+ case 308:
+ if (DEBUG) {
+ System.out.println("Expressionopt ::=");} //$NON-NLS-1$
+ consumeEmptyExpression();
+ break;
+
+ case 314:
+ if (DEBUG) {
+ System.out.println("PrimaryNoNewArrayStmt ::= SimpleName");} //$NON-NLS-1$
+ consumePrimarySimpleName();
+ break;
+
+ case 315:
+ if (DEBUG) {
+ System.out.println("PrimaryNoNewArrayStmt ::= this");} //$NON-NLS-1$
+ consumePrimaryNoNewArrayThis();
+ break;
+
+ case 316:
+ if (DEBUG) {
+ System.out.println("PrimaryNoNewArrayStmt ::= PushLPAREN Expression...");} //$NON-NLS-1$
+ consumePrimaryNoNewArray();
+ break;
+
+ case 318:
+ if (DEBUG) {
+ System.out.println("MemberExpressionStmt ::= MemberExpressionStmt LBRACKET");} //$NON-NLS-1$
+ consumeMemberExpressionWithArrayReference();
+ break;
+
+ case 319:
+ if (DEBUG) {
+ System.out.println("MemberExpressionStmt ::= MemberExpressionStmt DOT...");} //$NON-NLS-1$
+ consumeMemberExpressionWithSimpleName();
+ break;
+
+ case 320:
+ if (DEBUG) {
+ System.out.println("MemberExpressionStmt ::= new MemberExpression Arguments");} //$NON-NLS-1$
+ consumeNewMemberExpressionWithArguments();
+ break;
+
+ case 322:
+ if (DEBUG) {
+ System.out.println("NewExpressionStmt ::= new NewExpression");} //$NON-NLS-1$
+ consumeNewExpression();
+ break;
+
+ case 323:
+ if (DEBUG) {
+ System.out.println("CallExpressionStmt ::= MemberExpressionStmt Arguments");} //$NON-NLS-1$
+ consumeCallExpressionWithArguments();
+ break;
+
+ case 324:
+ if (DEBUG) {
+ System.out.println("CallExpressionStmt ::= CallExpressionStmt Arguments");} //$NON-NLS-1$
+ consumeCallExpressionWithArguments();
+ break;
+
+ case 325:
+ if (DEBUG) {
+ System.out.println("CallExpressionStmt ::= CallExpressionStmt LBRACKET...");} //$NON-NLS-1$
+ consumeCallExpressionWithArrayReference();
+ break;
+
+ case 326:
+ if (DEBUG) {
+ System.out.println("CallExpressionStmt ::= CallExpressionStmt DOT SimpleName");} //$NON-NLS-1$
+ consumeCallExpressionWithSimpleName();
+ break;
+
+ case 327:
+ if (DEBUG) {
+ System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN");} //$NON-NLS-1$
+ consumeArguments();
+ break;
+
+ case 331:
+ if (DEBUG) {
+ System.out.println("PostfixExpressionStmt ::= LeftHandSideExpressionStmt...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS, true);
+ break;
+
+ case 332:
+ if (DEBUG) {
+ System.out.println("PostfixExpressionStmt ::= LeftHandSideExpressionStmt...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS, true);
+ break;
+
+ case 333:
+ if (DEBUG) {
+ System.out.println("PreIncrementExpressionStmt ::= PLUS_PLUS PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS, false);
+ break;
+
+ case 334:
+ if (DEBUG) {
+ System.out.println("PreDecrementExpressionStmt ::= MINUS_MINUS PushPosition");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS, false);
+ break;
+
+ case 337:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionStmt ::= PLUS PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS);
+ break;
+
+ case 338:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionStmt ::= MINUS PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS);
+ break;
+
+ case 341:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinusStmt ::= TWIDDLE PushPosition");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.TWIDDLE);
+ break;
+
+ case 342:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinusStmt ::= NOT PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.NOT);
+ break;
+
+ case 343:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinusStmt ::= delete PushPosition");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.DELETE);
+ break;
+
+ case 344:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinusStmt ::= void PushPosition...");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.VOID);
+ break;
+
+ case 345:
+ if (DEBUG) {
+ System.out.println("UnaryExpressionNotPlusMinusStmt ::= typeof PushPosition");} //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.TYPEOF);
+ break;
+
+ case 347:
+ if (DEBUG) {
+ System.out.println("MultiplicativeExpressionStmt ::=...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.MULTIPLY);
+ break;
+
+ case 348:
+ if (DEBUG) {
+ System.out.println("MultiplicativeExpressionStmt ::=...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.DIVIDE);
+ break;
+
+ case 349:
+ if (DEBUG) {
+ System.out.println("MultiplicativeExpressionStmt ::=...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.REMAINDER);
+ break;
+
+ case 351:
+ if (DEBUG) {
+ System.out.println("AdditiveExpressionStmt ::= AdditiveExpressionStmt PLUS");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.PLUS);
+ break;
+
+ case 352:
+ if (DEBUG) {
+ System.out.println("AdditiveExpressionStmt ::= AdditiveExpressionStmt MINUS");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.MINUS);
+ break;
+
+ case 354:
+ if (DEBUG) {
+ System.out.println("ShiftExpressionStmt ::= ShiftExpressionStmt LEFT_SHIFT");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LEFT_SHIFT);
+ break;
+
+ case 355:
+ if (DEBUG) {
+ System.out.println("ShiftExpressionStmt ::= ShiftExpressionStmt RIGHT_SHIFT");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);
+ break;
+
+ case 356:
+ if (DEBUG) {
+ System.out.println("ShiftExpressionStmt ::= ShiftExpressionStmt...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);
+ break;
+
+ case 358:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionStmt ::= RelationalExpressionStmt...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS);
+ break;
+
+ case 359:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionStmt ::= RelationalExpressionStmt...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER);
+ break;
+
+ case 360:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionStmt ::= RelationalExpressionStmt...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS_EQUAL);
+ break;
+
+ case 361:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionStmt ::= RelationalExpressionStmt...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER_EQUAL);
+ break;
+
+ case 362:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionStmt ::= RelationalExpressionStmt...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.INSTANCEOF);
+ break;
+
+ case 363:
+ if (DEBUG) {
+ System.out.println("RelationalExpressionStmt ::= RelationalExpressionStmt in");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.IN);
+ break;
+
+ case 365:
+ if (DEBUG) {
+ System.out.println("EqualityExpressionStmt ::= EqualityExpressionStmt...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);
+ break;
+
+ case 366:
+ if (DEBUG) {
+ System.out.println("EqualityExpressionStmt ::= EqualityExpressionStmt...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.NOT_EQUAL);
+ break;
+
+ case 367:
+ if (DEBUG) {
+ System.out.println("EqualityExpressionStmt ::= EqualityExpressionStmt...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL_EQUAL);
+ break;
+
+ case 368:
+ if (DEBUG) {
+ System.out.println("EqualityExpressionStmt ::= EqualityExpressionStmt...");} //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.NOT_EQUAL_EQUAL);
+ break;
+
+ case 370:
+ if (DEBUG) {
+ System.out.println("AndExpressionStmt ::= AndExpressionStmt AND...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND);
+ break;
+
+ case 372:
+ if (DEBUG) {
+ System.out.println("ExclusiveOrExpressionStmt ::= ExclusiveOrExpressionStmt");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.XOR);
+ break;
+
+ case 374:
+ if (DEBUG) {
+ System.out.println("InclusiveOrExpressionStmt ::= InclusiveOrExpressionStmt");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR);
+ break;
+
+ case 376:
+ if (DEBUG) {
+ System.out.println("ConditionalAndExpressionStmt ::=...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND_AND);
+ break;
+
+ case 378:
+ if (DEBUG) {
+ System.out.println("ConditionalOrExpressionStmt ::=...");} //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR_OR);
+ break;
+
+ case 380:
+ if (DEBUG) {
+ System.out.println("ConditionalExpressionStmt ::=...");} //$NON-NLS-1$
+ consumeConditionalExpression(OperatorIds.QUESTIONCOLON);
+ break;
+
+ case 383:
+ if (DEBUG) {
+ System.out.println("AssignmentStmt ::= PostfixExpressionStmt...");} //$NON-NLS-1$
+ consumeAssignment();
+ break;
+
+ case 384:
+ if (DEBUG) {
+ System.out.println("Modifiersopt ::=");} //$NON-NLS-1$
+ consumeDefaultModifiers();
+ break;
+
+ case 385:
+ if (DEBUG) {
+ System.out.println("BlockStatementsopt ::=");} //$NON-NLS-1$
+ consumeEmptyBlockStatementsopt();
+ break;
+
+ case 387:
+ if (DEBUG) {
+ System.out.println("ArgumentListopt ::=");} //$NON-NLS-1$
+ consumeEmptyArgumentListopt();
+ break;
+
+ case 389:
+ if (DEBUG) {
+ System.out.println("FormalParameterListopt ::=");} //$NON-NLS-1$
+ consumeFormalParameterListopt();
+ break;
+
+ case 391:
+ if (DEBUG) {
+ System.out.println("ForInitopt ::=");} //$NON-NLS-1$
+ consumeEmptyForInitopt();
+ break;
+
+ case 393:
+ if (DEBUG) {
+ System.out.println("ForUpdateopt ::=");} //$NON-NLS-1$
+ consumeEmptyForUpdateopt();
+ break;
+
+ case 395:
+ if (DEBUG) {
+ System.out.println("Catchesopt ::=");} //$NON-NLS-1$
+ consumeEmptyCatchesopt();
+ break;
+
+ case 397:
+ if (DEBUG) {
+ System.out.println("RecoveryMethodHeaderName ::= Modifiersopt function...");} //$NON-NLS-1$
+ consumeRecoveryMethodHeaderName();
+ break;
+
+ case 398:
+ if (DEBUG) {
+ System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName...");} //$NON-NLS-1$
+ consumeMethodHeader();
+ break;
+
+ }
+ }
+
+ private void consumeElisionList() {
+ int flag = this.intStack[this.intPtr];
+ if ((flag & UNCONSUMED_ELISION) != 0)
+ {
+ pushOnExpressionStack(new EmptyExpression(this.endPosition, this.endPosition));
+ }
+ concatExpressionLists();
+ // this.intStack[this.intPtr]&= ~(UNCONSUMED_ELISION|UNCONSUMED_LIT_ELEMENT);
+ }
+
+ private void consumeElisionOne() {
+ pushOnExpressionStack(new EmptyExpression(this.endPosition, this.endPosition));
+ if ((this.intStack[this.intPtr] & UNCONSUMED_LIT_ELEMENT) != 0 || (this.intStack[this.intPtr] & WAS_ARRAY_LIT_ELEMENT) != 0)
+ concatExpressionLists();
+ this.intStack[this.intPtr] |= (WAS_ARRAY_LIT_ELEMENT | UNCONSUMED_ELISION);
+
+ }
+
+ private void consumeArrayLiteralElement() {
+ this.intStack[this.intPtr] |= (WAS_ARRAY_LIT_ELEMENT | UNCONSUMED_LIT_ELEMENT);
+ }
+
+ private void consumeElisionEmpty() {
+ }
+
+ private void consumeForInInit() {
+ Expression expression = this.expressionStack[this.expressionPtr--];
+ this.expressionLengthPtr--;
+ Statement var = expression;
+ pushOnAstStack(var);
+
+ }
+
+ private void consumeStatementWith() {
+ this.expressionLengthPtr--;
+ Statement statement = (Statement) this.astStack[this.astPtr];
+ this.astStack[this.astPtr] =
+ new WithStatement(
+ this.expressionStack[this.expressionPtr--],
+ statement,
+ this.intStack[this.intPtr--],
+ this.endStatementPosition);
+ }
+
+ private void consumeArrayLiteral(boolean addElision) {
+ int flag = this.intStack[this.intPtr--];
+ if (addElision || (flag & UNCONSUMED_ELISION) != 0)
+ {
+ pushOnExpressionStack(new EmptyExpression(this.endPosition, this.endPosition));
+ concatExpressionLists();
+ }
+ int length = ((flag & WAS_ARRAY_LIT_ELEMENT) > 0) ? this.expressionLengthStack[this.expressionLengthPtr--] : 0;
+ arrayInitializer(length);
+
+ }
+
+ private void consumeObjectLiteral() {
+ ObjectLiteral objectLiteral = new ObjectLiteral();
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ this.expressionPtr -= length;
+ System.arraycopy(
+ this.expressionStack,
+ this.expressionPtr + 1,
+ objectLiteral.fields = new ObjectLiteralField[length],
+ 0,
+ length);
+ }
+ objectLiteral.sourceEnd = this.endStatementPosition;
+ objectLiteral.sourceStart = this.intStack[this.intPtr--];
+
+ pushOnExpressionStack(objectLiteral);
+ }
+
+ protected void consumeStatementBreak() {
+ // BreakStatement ::= 'break' ';'
+ // break pushs a position on this.intStack in case there is no label
+
+ pushOnAstStack(new BreakStatement(null, this.intStack[this.intPtr--], this.endStatementPosition));
+ if (this.pendingRecoveredType != null) {
+ // Used only in statements recovery.
+ // This is not a real break statement but a placeholder for an existing local type.
+ // The break statement must be replace by the local type.
+ if (this.pendingRecoveredType.allocation == null &&
+ this.endPosition <= this.pendingRecoveredType.declarationSourceEnd) {
+ this.astStack[this.astPtr] = this.pendingRecoveredType;
+ this.pendingRecoveredType = null;
+ return;
+ }
+ this.pendingRecoveredType = null;
+ }
+ }
+
+ protected void consumeStatementBreakWithLabel() {
+ // BreakStatement ::= 'break' Identifier ';'
+ // break pushs a position on this.intStack in case there is no label
+
+ pushOnAstStack(new BreakStatement(
+ this.identifierStack[this.identifierPtr--],
+ this.intStack[this.intPtr--],
+ this.endStatementPosition));
+ this.identifierLengthPtr--;
+ }
+
+ protected void consumeStatementCatch() {
+ // CatchClause ::= 'catch' '(' FormalParameter ')' Block
+
+ //catch are stored directly into the Try
+ //has they always comes two by two....
+ //we remove one entry from the astlengthPtr.
+ //The construction of the try statement must
+ //then fetch the catches using 2*i and 2*i + 1
+
+ this.astLengthPtr--;
+ this.listLength = 0; // reset formalParameter counter (incremented for catch variable)
+ }
+
+ protected void consumeStatementContinue() {
+ // ContinueStatement ::= 'continue' ';'
+ // continue pushs a position on this.intStack in case there is no label
+
+ pushOnAstStack(new ContinueStatement(
+ null,
+ this.intStack[this.intPtr--],
+ this.endStatementPosition));
+ }
+
+ protected void consumeStatementContinueWithLabel() {
+ // ContinueStatement ::= 'continue' Identifier ';'
+ // continue pushs a position on this.intStack in case there is no label
+
+ pushOnAstStack(new ContinueStatement(
+ this.identifierStack[this.identifierPtr--],
+ this.intStack[this.intPtr--],
+ this.endStatementPosition));
+ this.identifierLengthPtr--;
+ }
+
+ protected void consumeStatementDo() {
+ // DoStatement ::= 'do' Statement 'while' '(' Expression ')' ';'
+
+ //the 'while' pushes a value on this.intStack that we need to remove
+ this.intPtr--;
+
+ Statement statement = (Statement) this.astStack[this.astPtr];
+ this.expressionLengthPtr--;
+ this.astStack[this.astPtr] =
+ new DoStatement(
+ this.expressionStack[this.expressionPtr--],
+ statement,
+ this.intStack[this.intPtr--],
+ this.endStatementPosition);
+ }
+
+ protected void consumeStatementExpressionList() {
+ // StatementExpressionList ::= StatementExpressionList ',' StatementExpression
+ concatExpressionLists();
+ }
+
+ protected void consumeStatementFor() {
+ // ForStatement ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' Statement
+ // ForStatementNoShortIf ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' StatementNoShortIf
+
+ int length;
+ Expression cond = null;
+ Statement[] inits, updates;
+ boolean scope = true;
+
+ //statements
+ this.astLengthPtr--;
+ Statement statement = (Statement) this.astStack[this.astPtr--];
+
+ //updates are on the expresion stack
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) == 0) {
+ updates = null;
+ } else {
+ this.expressionPtr -= length;
+ System.arraycopy(
+ this.expressionStack,
+ this.expressionPtr + 1,
+ updates = new Statement[length],
+ 0,
+ length);
+ }
+
+ if (this.expressionLengthStack[this.expressionLengthPtr--] != 0)
+ cond = this.expressionStack[this.expressionPtr--];
+
+ //inits may be on two different stacks
+ if ((length = this.astLengthStack[this.astLengthPtr--]) == 0) {
+ inits = null;
+ scope = false;
+ } else {
+ if (length == -1) { //on this.expressionStack
+ scope = false;
+ length = this.expressionLengthStack[this.expressionLengthPtr--];
+ this.expressionPtr -= length;
+ System.arraycopy(
+ this.expressionStack,
+ this.expressionPtr + 1,
+ inits = new Statement[length],
+ 0,
+ length);
+ } else { //on this.astStack
+ this.astPtr -= length;
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + 1,
+ inits = new Statement[length],
+ 0,
+ length);
+ }
+ }
+ pushOnAstStack(new ForStatement(
+ inits,
+ cond,
+ updates,
+ statement,
+ scope,
+ this.intStack[this.intPtr--],
+ this.endStatementPosition));
+ }
+
+ protected void consumeStatementIfNoElse() {
+ // IfThenStatement ::= 'if' '(' Expression ')' Statement
+
+ //optimize the push/pop
+ this.expressionLengthPtr--;
+ Statement thenStatement = (Statement) this.astStack[this.astPtr];
+ this.astStack[this.astPtr] =
+ new IfStatement(
+ this.expressionStack[this.expressionPtr--],
+ thenStatement,
+ this.intStack[this.intPtr--],
+ this.endStatementPosition);
+ }
+
+ protected void consumeStatementIfWithElse() {
+ // IfThenElseStatement ::= 'if' '(' Expression ')' StatementNoShortIf 'else' Statement
+ // IfThenElseStatementNoShortIf ::= 'if' '(' Expression ')' StatementNoShortIf 'else' StatementNoShortIf
+
+ this.expressionLengthPtr--;
+
+ // optimized {..., Then, Else } ==> {..., If }
+ this.astLengthPtr--;
+
+ //optimize the push/pop
+ this.astStack[--this.astPtr] =
+ new IfStatement(
+ this.expressionStack[this.expressionPtr--],
+ (Statement) this.astStack[this.astPtr],
+ (Statement) this.astStack[this.astPtr + 1],
+ this.intStack[this.intPtr--],
+ this.endStatementPosition);
+ }
+
+ protected void consumeStatementLabel() {
+ // LabeledStatement ::= 'Identifier' ':' Statement
+ // LabeledStatementNoShortIf ::= 'Identifier' ':' StatementNoShortIf
+
+ //optimize push/pop
+ Statement statement = (Statement) this.astStack[this.astPtr];
+ this.astStack[this.astPtr] =
+ new LabeledStatement(
+ this.identifierStack[this.identifierPtr],
+ statement,
+ this.identifierPositionStack[this.identifierPtr--],
+ this.endStatementPosition);
+ this.identifierLengthPtr--;
+ }
+
+ protected void consumeStatementReturn() {
+ // ReturnStatement ::= 'return' Expressionopt ';'
+ // return pushs a position on this.intStack in case there is no expression
+
+ if (this.expressionLengthStack[this.expressionLengthPtr--] != 0) {
+ pushOnAstStack(new ReturnStatement(
+ this.expressionStack[this.expressionPtr--],
+ this.intStack[this.intPtr--],
+ this.endStatementPosition));
+ } else {
+ pushOnAstStack(new ReturnStatement(null, this.intStack[this.intPtr--], this.endStatementPosition));
+ }
+ }
+
+ protected void consumeStatementSwitch() {
+ // SwitchStatement ::= 'switch' OpenBlock '(' Expression ')' SwitchBlock
+
+ //OpenBlock just makes the semantic action blockStart()
+ //the block is inlined but a scope need to be created
+ //if some declaration occurs.
+
+ int length;
+ SwitchStatement switchStatement = new SwitchStatement();
+ this.expressionLengthPtr--;
+ switchStatement.expression = this.expressionStack[this.expressionPtr--];
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ this.astPtr -= length;
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + 1,
+ switchStatement.statements = new Statement[length],
+ 0,
+ length);
+ }
+ switchStatement.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+ pushOnAstStack(switchStatement);
+ switchStatement.blockStart = this.intStack[this.intPtr--];
+ switchStatement.sourceStart = this.intStack[this.intPtr--];
+ switchStatement.sourceEnd = this.endStatementPosition;
+ if (length == 0 && !containsComment(switchStatement.blockStart, switchStatement.sourceEnd)) {
+ switchStatement.bits |= ASTNode.UndocumentedEmptyBlock;
+ }
+ }
+
+ protected void consumeStatementThrow() {
+ // ThrowStatement ::= 'throw' Expression ';'
+ this.expressionLengthPtr--;
+ pushOnAstStack(new ThrowStatement(this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--], this.endStatementPosition));
+ }
+
+ protected void consumeStatementTry(boolean withFinally) {
+ //TryStatement ::= 'try' Block Catches
+ //TryStatement ::= 'try' Block Catchesopt Finally
+
+ int length;
+ TryStatement tryStmt = new TryStatement();
+ //finally
+ if (withFinally) {
+ this.astLengthPtr--;
+ tryStmt.finallyBlock = (Block) this.astStack[this.astPtr--];
+ }
+ //catches are handle by two <argument-block> [see statementCatch]
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ if (length == 1) {
+ tryStmt.catchBlocks = new Block[] { (Block) this.astStack[this.astPtr--] };
+ tryStmt.catchArguments = new Argument[] { (Argument) this.astStack[this.astPtr--] };
+ } else {
+ Block[] bks = (tryStmt.catchBlocks = new Block[length]);
+ Argument[] args = (tryStmt.catchArguments = new Argument[length]);
+ while (length-- > 0) {
+ bks[length] = (Block) this.astStack[this.astPtr--];
+ args[length] = (Argument) this.astStack[this.astPtr--];
+ }
+ }
+ }
+ //try
+ this.astLengthPtr--;
+ tryStmt.tryBlock = (Block) this.astStack[this.astPtr--];
+
+ //positions
+ tryStmt.sourceEnd = this.endStatementPosition;
+ tryStmt.sourceStart = this.intStack[this.intPtr--];
+ pushOnAstStack(tryStmt);
+ }
+
+ protected void consumeStatementWhile() {
+ // WhileStatement ::= 'while' '(' Expression ')' Statement
+ // WhileStatementNoShortIf ::= 'while' '(' Expression ')' StatementNoShortIf
+
+ this.expressionLengthPtr--;
+ Statement statement = (Statement) this.astStack[this.astPtr];
+ this.astStack[this.astPtr] =
+ new WhileStatement(
+ this.expressionStack[this.expressionPtr--],
+ statement,
+ this.intStack[this.intPtr--],
+ this.endStatementPosition);
+ }
+
+ protected void consumeSwitchBlock() {
+ // SwitchBlock ::= '{' SwitchBlockStatements SwitchLabels '}'
+ concatNodeLists();
+ }
+
+ protected void consumeSwitchBlockStatement() {
+ // SwitchBlockStatement ::= SwitchLabels BlockStatements
+ concatNodeLists();
+ }
+
+ protected void consumeSwitchBlockStatements() {
+ // SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement
+ concatNodeLists();
+ }
+
+ protected void consumeSwitchLabels() {
+ // SwitchLabels ::= SwitchLabels SwitchLabel
+ optimizedConcatNodeLists();
+ }
+
+ protected void consumeToken(int type) {
+ /* remember the last consumed value */
+ /* try to minimize the number of build values */
+ // // clear the commentPtr of the scanner in case we read something different from a modifier
+ // switch(type) {
+ // case TokenNameabstract :
+ // case TokenNamestrictfp :
+ // case TokenNamefinal :
+ // case TokenNamenative :
+ // case TokenNameprivate :
+ // case TokenNameprotected :
+ // case TokenNamepublic :
+ // case TokenNametransient :
+ // case TokenNamevolatile :
+ // case TokenNamestatic :
+ // case TokenNamesynchronized :
+ // break;
+ // default:
+ // this.scanner.commentPtr = -1;
+ // }
+ //System.out.println(this.scanner.toStringAction(type));
+ switch (type) {
+ case TokenNameIdentifier:
+ pushIdentifier();
+ break;
+ case TokenNameinterface:
+ //'class' is pushing two int (positions) on the stack ==> 'interface' needs to do it too....
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNameabstract:
+ checkAndSetModifiers(ClassFileConstants.AccAbstract);
+ pushOnExpressionStackLengthStack(0);
+ break;
+ case TokenNamefinal:
+ checkAndSetModifiers(ClassFileConstants.AccFinal);
+ pushOnExpressionStackLengthStack(0);
+ break;
+ case TokenNamenative:
+ checkAndSetModifiers(ClassFileConstants.AccNative);
+ pushOnExpressionStackLengthStack(0);
+ break;
+ case TokenNameprivate:
+ checkAndSetModifiers(ClassFileConstants.AccPrivate);
+ pushOnExpressionStackLengthStack(0);
+ break;
+ case TokenNameprotected:
+ checkAndSetModifiers(ClassFileConstants.AccProtected);
+ pushOnExpressionStackLengthStack(0);
+ break;
+ case TokenNamepublic:
+ checkAndSetModifiers(ClassFileConstants.AccPublic);
+ pushOnExpressionStackLengthStack(0);
+ break;
+ case TokenNametransient:
+ pushOnExpressionStackLengthStack(0);
+ break;
+ case TokenNamevolatile:
+ pushOnExpressionStackLengthStack(0);
+ break;
+ case TokenNamestatic:
+ checkAndSetModifiers(ClassFileConstants.AccStatic);
+ pushOnExpressionStackLengthStack(0);
+ break;
+ // case TokenNamesynchronized :
+ // this.synchronizedBlockSourceStart = this.scanner.startPosition;
+ // checkAndSetModifiers(ClassFileConstants.AccSynchronized);
+ // pushOnExpressionStackLengthStack(0);
+ // break;
+ //==============================
+ // case TokenNamevoid :
+ // pushIdentifier(-T_void);
+ // pushOnIntStack(this.scanner.currentPosition - 1);
+ // pushOnIntStack(this.scanner.startPosition);
+ // break;
+ //push a default dimension while void is not part of the primitive
+ //declaration baseType and so takes the place of a type without getting into
+ //regular type parsing that generates a dimension on this.intStack
+ case TokenNameboolean:
+ pushIdentifier(-T_boolean);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNamechar:
+ pushIdentifier(-T_char);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNamedouble:
+ pushIdentifier(-T_double);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNamefloat:
+ pushIdentifier(-T_float);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNameint:
+ pushIdentifier(-T_int);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNamelong:
+ pushIdentifier(-T_long);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNameshort:
+ pushIdentifier(-T_short);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ //==============================
+ case TokenNameIntegerLiteral:
+ pushOnExpressionStack(new IntLiteral(
+ this.scanner.getCurrentTokenSource(),
+ this.scanner.startPosition,
+ this.scanner.currentPosition - 1));
+ break;
+ case TokenNameLongLiteral:
+ case TokenNameFloatingPointLiteral:
+ case TokenNameDoubleLiteral:
+ pushOnExpressionStack(new DoubleLiteral(
+ this.scanner.getCurrentTokenSource(),
+ this.scanner.startPosition,
+ this.scanner.currentPosition - 1));
+ break;
+ case TokenNameCharacterLiteral:
+ StringLiteral stringLiteral;
+ if (this.recordStringLiterals && this.checkExternalizeStrings && !this.statementRecoveryActivated) {
+ stringLiteral = this.createStringLiteral(
+ this.scanner.getCurrentTokenSourceString(),
+ this.scanner.startPosition,
+ this.scanner.currentPosition - 1,
+ Util.getLineNumber(this.scanner.startPosition, this.scanner.lineEnds, 0, this.scanner.linePtr));
+ this.compilationUnit.recordStringLiteral(stringLiteral);
+ } else {
+ stringLiteral = this.createStringLiteral(
+ this.scanner.getCurrentTokenSourceString(),
+ this.scanner.startPosition,
+ this.scanner.currentPosition - 1,
+ 0);
+ }
+ pushOnExpressionStack(stringLiteral);
+ break;
+ case TokenNameRegExLiteral:
+ pushOnExpressionStack(new RegExLiteral(
+ this.scanner.getCurrentTokenSource(),
+ this.scanner.startPosition,
+ this.scanner.currentPosition - 1));
+ break;
+
+ case TokenNameStringLiteral:
+ if (this.recordStringLiterals && this.checkExternalizeStrings && !this.statementRecoveryActivated) {
+ stringLiteral = this.createStringLiteral(
+ this.scanner.getCurrentTokenSourceString(),
+ this.scanner.startPosition,
+ this.scanner.currentPosition - 1,
+ Util.getLineNumber(this.scanner.startPosition, this.scanner.lineEnds, 0, this.scanner.linePtr));
+ this.compilationUnit.recordStringLiteral(stringLiteral);
+ } else {
+ stringLiteral = this.createStringLiteral(
+ this.scanner.getCurrentTokenSourceString(),
+ this.scanner.startPosition,
+ this.scanner.currentPosition - 1,
+ 0);
+ }
+ pushOnExpressionStack(stringLiteral);
+ break;
+ case TokenNamefalse:
+ pushOnExpressionStack(new FalseLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1));
+ break;
+ case TokenNametrue:
+ pushOnExpressionStack(new TrueLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1));
+ break;
+ case TokenNamenull:
+ pushOnExpressionStack(new NullLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1));
+ break;
+ case TokenNameundefined:
+ pushOnExpressionStack(new UndefinedLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1));
+ break;
+ //============================
+ case TokenNamesuper:
+ case TokenNamethis:
+ this.endPosition = this.scanner.currentPosition - 1;
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ // case TokenNameassert :
+ case TokenNameimport:
+ case TokenNamepackage:
+ case TokenNamethrow:
+ case TokenNamedo:
+ case TokenNameif:
+ case TokenNamefor:
+ case TokenNameswitch:
+ case TokenNametry:
+ case TokenNamewhile:
+ case TokenNamebreak:
+ case TokenNamecontinue:
+ case TokenNamereturn:
+ case TokenNamecase:
+ case TokenNamedebugger:
+ case TokenNameexport:
+ case TokenNamefunction:
+ case TokenNamevar:
+ // case TokenNamein :
+ // case TokenNameinfinity :
+ case TokenNamewith:
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNamenew:
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=40954
+ resetModifiers();
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNameclass:
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNameenum:
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNamedefault:
+ pushOnIntStack(this.scanner.startPosition);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ break;
+ //let extra semantic action decide when to push
+ case TokenNameRBRACKET:
+ this.endPosition = this.scanner.startPosition;
+ this.endStatementPosition = this.scanner.currentPosition - 1;
+ break;
+ case TokenNameLBRACKET:
+ this.endPosition = this.scanner.startPosition;
+ break;
+ case TokenNameLBRACE:
+ this.endStatementPosition = this.scanner.currentPosition - 1;
+ case TokenNamePLUS:
+ case TokenNameMINUS:
+ case TokenNameNOT:
+ case TokenNameTWIDDLE:
+ case TokenNamedelete:
+ case TokenNamevoid:
+ case TokenNametypeof:
+ this.endPosition = this.scanner.startPosition;
+ break;
+ case TokenNamePLUS_PLUS:
+ case TokenNameMINUS_MINUS:
+ this.endPosition = this.scanner.startPosition;
+ this.endStatementPosition = this.scanner.currentPosition - 1;
+ break;
+ case TokenNameSEMICOLON:
+ if (this.insertedSemicolonPosition > 0)
+ {
+ if (this.insertedSemicolonPosition >= this.scanner.source.length)
+ this.insertedSemicolonPosition--;
+ this.endStatementPosition = this.insertedSemicolonPosition;
+ this.endPosition = this.insertedSemicolonPosition;
+ this.insertedSemicolonPosition = -1;
+ this.problemReporter().missingSemiColon(null, this.endPosition - 1, this.endPosition);
+ break;
+ }// else fallthru
+ case TokenNameRBRACE:
+ this.endStatementPosition = this.scanner.currentPosition - 1;
+ this.endPosition = this.scanner.startPosition - 1;
+ //the item is not part of the potential future expression/statement
+ break;
+ case TokenNameRPAREN:
+ // in order to handle ( expression) ////// (cast)expression///// foo(x)
+ this.rParenPos = this.scanner.currentPosition - 1; // position of the end of right parenthesis (in case of unicode \u0029) lex00101
+ break;
+ case TokenNameLPAREN:
+ this.lParenPos = this.scanner.startPosition;
+ break;
+ case TokenNameQUESTION:
+ pushOnIntStack(this.scanner.startPosition);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ break;
+ case TokenNameLESS:
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ // case TokenNameELLIPSIS :
+ // pushOnIntStack(this.scanner.currentPosition - 1);
+ // break;
+ // case TokenNameCOMMA :
+ // case TokenNameCOLON :
+ // case TokenNameEQUAL :
+ // case TokenNameLBRACKET :
+ // case TokenNameDOT :
+ // case TokenNameERROR :
+ // case TokenNameEOF :
+ // case TokenNamecase :
+ // case TokenNamecatch :
+ // case TokenNameelse :
+ // case TokenNameextends :
+ // case TokenNamefinally :
+ // case TokenNameimplements :
+ // case TokenNamethrows :
+ // case TokenNameinstanceof :
+ // case TokenNameEQUAL_EQUAL :
+ // case TokenNameLESS_EQUAL :
+ // case TokenNameGREATER_EQUAL :
+ // case TokenNameNOT_EQUAL :
+ // case TokenNameLEFT_SHIFT :
+ // case TokenNameRIGHT_SHIFT :
+ // case TokenNameUNSIGNED_RIGHT_SHIFT :
+ // case TokenNamePLUS_EQUAL :
+ // case TokenNameMINUS_EQUAL :
+ // case TokenNameMULTIPLY_EQUAL :
+ // case TokenNameDIVIDE_EQUAL :
+ // case TokenNameAND_EQUAL :
+ // case TokenNameOR_EQUAL :
+ // case TokenNameXOR_EQUAL :
+ // case TokenNameREMAINDER_EQUAL :
+ // case TokenNameLEFT_SHIFT_EQUAL :
+ // case TokenNameRIGHT_SHIFT_EQUAL :
+ // case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL :
+ // case TokenNameOR_OR :
+ // case TokenNameAND_AND :
+ // case TokenNameREMAINDER :
+ // case TokenNameXOR :
+ // case TokenNameAND :
+ // case TokenNameMULTIPLY :
+ // case TokenNameOR :
+ // case TokenNameDIVIDE :
+ // case TokenNameGREATER :
+ }
+ }
+
+ protected void consumeUnaryExpression(int op) {
+ // UnaryExpression ::= '+' PushPosition UnaryExpression
+ // UnaryExpression ::= '-' PushPosition UnaryExpression
+ // UnaryExpressionNotPlusMinus ::= '~' PushPosition UnaryExpression
+ // UnaryExpressionNotPlusMinus ::= '!' PushPosition UnaryExpression
+
+ //optimize the push/pop
+
+ //handle manually the -2147483648 while it is not a real
+ //computation of an - and 2147483648 (notice that 2147483648
+ //is Integer.MAX_VALUE+1.....)
+ //Same for -9223372036854775808L ............
+
+ //this.intStack have the position of the operator
+
+ Expression r, exp = this.expressionStack[this.expressionPtr];
+ if (op == MINUS) {
+ if ((exp instanceof IntLiteral) && (((IntLiteral) exp).mayRepresentMIN_VALUE())) {
+ r = this.expressionStack[this.expressionPtr] = new IntLiteralMinValue();
+ } else {
+ r = this.expressionStack[this.expressionPtr] = new UnaryExpression(exp, op);
+ }
+ } else {
+ r = this.expressionStack[this.expressionPtr] = new UnaryExpression(exp, op);
+ }
+ r.sourceStart = this.intStack[this.intPtr--];
+ r.sourceEnd = exp.sourceEnd;
+ }
+
+ protected void consumeUnaryExpression(int op, boolean post) {
+ // PreIncrementExpression ::= '++' PushPosition UnaryExpression
+ // PreDecrementExpression ::= '--' PushPosition UnaryExpression
+
+ // ++ and -- operators
+ //optimize the push/pop
+
+ //this.intStack has the position of the operator when prefix
+
+ Expression leftHandSide = this.expressionStack[this.expressionPtr];
+ if (leftHandSide instanceof Reference) {
+ // ++foo()++ is unvalid
+ if (post) {
+ this.expressionStack[this.expressionPtr] =
+ new PostfixExpression(
+ leftHandSide,
+ IntLiteral.getOne(),
+ op,
+ this.endStatementPosition);
+ } else {
+ this.expressionStack[this.expressionPtr] =
+ new PrefixExpression(
+ leftHandSide,
+ IntLiteral.getOne(),
+ op,
+ this.intStack[this.intPtr--]);
+ }
+ } else {
+ //the ++ or the -- is NOT taken into account if code gen proceeds
+ if (!post) {
+ this.intPtr--;
+ }
+ if (!this.statementRecoveryActivated)
+ problemReporter().invalidUnaryExpression(leftHandSide);
+ }
+ }
+
+ protected void consumeVariableDeclarators() {
+ // VariableDeclarators ::= VariableDeclarators ',' VariableDeclarator
+ optimizedConcatNodeLists();
+ }
+
+ protected void consumeVariableInitializers() {
+ // VariableInitializers ::= VariableInitializers ',' VariableInitializer
+ concatExpressionLists();
+ }
+
+ /**
+ * Given the current comment stack, answer whether some comment is available in a certain exclusive range
+ *
+ * @param sourceStart int
+ * @param sourceEnd int
+ * @return boolean
+ */
+ public boolean containsComment(int sourceStart, int sourceEnd) {
+ int iComment = this.scanner.commentPtr;
+ for (; iComment >= 0; iComment--) {
+ int commentStart = this.scanner.commentStarts[iComment];
+ // ignore comments before start
+ if (commentStart < sourceStart)
+ continue;
+ // ignore comments after end
+ if (commentStart > sourceEnd)
+ continue;
+ return true;
+ }
+ return false;
+ }
+
+ public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
+ MethodDeclaration m = new MethodDeclaration(compilationResult);
+ m.sourceStart = c.sourceStart;
+ m.sourceEnd = c.sourceEnd;
+ m.bodyStart = c.bodyStart;
+ m.bodyEnd = c.bodyEnd;
+ m.declarationSourceEnd = c.declarationSourceEnd;
+ m.declarationSourceStart = c.declarationSourceStart;
+ m.setSelector(c.getName());
+ m.statements = c.statements;
+ m.modifiers = c.modifiers;
+ m.arguments = c.arguments;
+ m.explicitDeclarations = c.explicitDeclarations;
+ m.returnType = null;
+ m.javadoc = c.javadoc;
+ return m;
+ }
+
+ protected TypeReference copyDims(TypeReference typeRef, int dim) {
+ return typeRef.copyDims(dim);
+ }
+
+ protected FieldDeclaration createFieldDeclaration(char[] fieldDeclarationName, int sourceStart, int sourceEnd) {
+ return new FieldDeclaration(fieldDeclarationName, sourceStart, sourceEnd);
+ }
+
+ protected JavadocParser createJavadocParser() {
+ return new JavadocParser(this);
+ }
+
+ protected LocalDeclaration createLocalDeclaration(char[] localDeclarationName, int sourceStart, int sourceEnd) {
+ return new LocalDeclaration(localDeclarationName, sourceStart, sourceEnd);
+ }
+
+ protected StringLiteral createStringLiteral(char[] token, int start, int end, int lineNumber) {
+ return new StringLiteral(token, start, end, lineNumber);
+ }
+
+ protected RecoveredType currentRecoveryType() {
+ if (this.currentElement != null) {
+ if (this.currentElement instanceof RecoveredType) {
+ return (RecoveredType) this.currentElement;
+ } else {
+ return this.currentElement.enclosingType();
+ }
+ }
+ return null;
+ }
+
+ public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
+
+ CompilationUnitDeclaration parsedUnit;
+ boolean old = this.diet;
+ try {
+ this.diet = DO_DIET_PARSE;
+ parsedUnit = parse(sourceUnit, compilationResult);
+ } finally {
+ this.diet = old;
+ }
+ return parsedUnit;
+ }
+
+ protected void dispatchDeclarationInto(int length) {
+ /* they are length on this.astStack that should go into
+ methods fields constructors lists of the typeDecl
+
+ Return if there is a constructor declaration in the methods declaration */
+
+ // Looks for the size of each array .
+
+ if (length == 0)
+ return;
+ int[] flag = new int[length + 1]; //plus one -- see <HERE>
+ int size1 = 0, size2 = 0, size3 = 0;
+ boolean hasAbstractMethods = false;
+ for (int i = length - 1; i >= 0; i--) {
+ ASTNode astNode = this.astStack[this.astPtr--];
+ if (astNode instanceof AbstractMethodDeclaration) {
+ //methods and constructors have been regrouped into one single list
+ flag[i] = 2;
+ size2++;
+ if (((AbstractMethodDeclaration) astNode).isAbstract()) {
+ hasAbstractMethods = true;
+ }
+ } else if (astNode instanceof TypeDeclaration) {
+ flag[i] = 3;
+ size3++;
+ } else {
+ //field
+ flag[i] = 1;
+ size1++;
+ }
+ }
+
+ //arrays creation
+ TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+ if (size1 != 0) {
+ typeDecl.fields = new FieldDeclaration[size1];
+ }
+ if (size2 != 0) {
+ typeDecl.methods = new AbstractMethodDeclaration[size2];
+ if (hasAbstractMethods)
+ typeDecl.bits |= ASTNode.HasAbstractMethods;
+ }
+ if (size3 != 0) {
+ typeDecl.memberTypes = new TypeDeclaration[size3];
+ }
+
+ //arrays fill up
+ size1 = size2 = size3 = 0;
+ int flagI = flag[0], start = 0;
+ int length2;
+ for (int end = 0; end <= length; end++) //<HERE> the plus one allows to
+ {
+ if (flagI != flag[end]) //treat the last element as a ended flag.....
+ { //array copy
+ switch (flagI) {
+ case 1:
+ size1 += (length2 = end - start);
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + start + 1,
+ typeDecl.fields,
+ size1 - length2,
+ length2);
+ break;
+ case 2:
+ size2 += (length2 = end - start);
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + start + 1,
+ typeDecl.methods,
+ size2 - length2,
+ length2);
+ break;
+ case 3:
+ size3 += (length2 = end - start);
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + start + 1,
+ typeDecl.memberTypes,
+ size3 - length2,
+ length2);
+ break;
+ }
+ flagI = flag[start = end];
+ }
+ }
+
+ if (typeDecl.memberTypes != null) {
+ for (int i = typeDecl.memberTypes.length - 1; i >= 0; i--) {
+ typeDecl.memberTypes[i].enclosingType = typeDecl;
+ }
+ }
+ }
+
+ protected void dispatchDeclarationIntoEnumDeclaration(int length) {
+
+ if (length == 0)
+ return;
+ int[] flag = new int[length + 1]; //plus one -- see <HERE>
+ int size1 = 0, size2 = 0, size3 = 0;
+ TypeDeclaration enumDeclaration = (TypeDeclaration) this.astStack[this.astPtr - length];
+ boolean hasAbstractMethods = false;
+ for (int i = length - 1; i >= 0; i--) {
+ ASTNode astNode = this.astStack[this.astPtr--];
+ if (astNode instanceof AbstractMethodDeclaration) {
+ //methods and constructors have been regrouped into one single list
+ flag[i] = 2;
+ size2++;
+ if (((AbstractMethodDeclaration) astNode).isAbstract()) {
+ hasAbstractMethods = true;
+ }
+ } else if (astNode instanceof TypeDeclaration) {
+ flag[i] = 3;
+ size3++;
+ } else if (astNode instanceof FieldDeclaration) {
+ flag[i] = 1;
+ size1++;
+ // if(astNode instanceof EnumConstant) {
+ // EnumConstant constant = (EnumConstant) astNode;
+ // ((AllocationExpression)constant.initialization).type = new SingleTypeReference(enumDeclaration.name,
+ // (((long) enumDeclaration.sourceStart) << 32) + enumDeclaration.sourceEnd);
+ // }
+ }
+ }
+
+ //arrays creation
+ if (size1 != 0) {
+ enumDeclaration.fields = new FieldDeclaration[size1];
+ }
+ if (size2 != 0) {
+ enumDeclaration.methods = new AbstractMethodDeclaration[size2];
+ if (hasAbstractMethods)
+ enumDeclaration.bits |= ASTNode.HasAbstractMethods;
+ }
+ if (size3 != 0) {
+ enumDeclaration.memberTypes = new TypeDeclaration[size3];
+ }
+
+ //arrays fill up
+ size1 = size2 = size3 = 0;
+ int flagI = flag[0], start = 0;
+ int length2;
+ for (int end = 0; end <= length; end++) //<HERE> the plus one allows to
+ {
+ if (flagI != flag[end]) //treat the last element as a ended flag.....
+ { //array copy
+ switch (flagI) {
+ case 1:
+ size1 += (length2 = end - start);
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + start + 1,
+ enumDeclaration.fields,
+ size1 - length2,
+ length2);
+ break;
+ case 2:
+ size2 += (length2 = end - start);
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + start + 1,
+ enumDeclaration.methods,
+ size2 - length2,
+ length2);
+ break;
+ case 3:
+ size3 += (length2 = end - start);
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + start + 1,
+ enumDeclaration.memberTypes,
+ size3 - length2,
+ length2);
+ break;
+ }
+ flagI = flag[start = end];
+ }
+ }
+
+ if (enumDeclaration.memberTypes != null) {
+ for (int i = enumDeclaration.memberTypes.length - 1; i >= 0; i--) {
+ enumDeclaration.memberTypes[i].enclosingType = enumDeclaration;
+ }
+ }
+ }
+
+ protected CompilationUnitDeclaration endParse(int act) {
+
+ this.lastAct = act;
+
+ if (this.statementRecoveryActivated) {
+ RecoveredElement recoveredElement = this.buildInitialRecoveryState();
+ recoveredElement.topElement().updateParseTree();
+ if (this.hasError)
+ this.resetStacks();
+ } else if (this.currentElement != null) {
+ if (VERBOSE_RECOVERY) {
+ System.out.print(Messages.parser_syntaxRecovery);
+ System.out.println("--------------------------"); //$NON-NLS-1$
+ System.out.println(this.compilationUnit);
+ System.out.println("----------------------------------"); //$NON-NLS-1$
+ }
+ recoverAST(this.currentElement);
+ this.currentElement.topElement().updateParseTree();
+ } else {
+ if (this.diet & VERBOSE_RECOVERY) {
+ System.out.print(Messages.parser_regularParse);
+ System.out.println("--------------------------"); //$NON-NLS-1$
+ System.out.println(this.compilationUnit);
+ System.out.println("----------------------------------"); //$NON-NLS-1$
+ }
+ }
+ persistLineSeparatorPositions();
+ for (int i = 0; i < this.scanner.foundTaskCount; i++) {
+ if (!this.statementRecoveryActivated)
+ problemReporter().task(
+ new String(this.scanner.foundTaskTags[i]),
+ new String(this.scanner.foundTaskMessages[i]),
+ this.scanner.foundTaskPriorities[i] == null ? null : new String(this.scanner.foundTaskPriorities[i]),
+ this.scanner.foundTaskPositions[i][0],
+ this.scanner.foundTaskPositions[i][1]);
+ }
+ if (this.compilationUnit.statements == null)
+ this.compilationUnit.statements = new ProgramElement[0];
+ return this.compilationUnit;
+ }
+
+ /*
+ * Flush comments defined prior to a given positions.
+ *
+ * Note: comments 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 flushCommentsDefinedPriorTo(int position) {
+
+ int lastCommentIndex = this.scanner.commentPtr;
+ if (lastCommentIndex < 0)
+ return position; // no comment
+
+ // compute the index of the first obsolete comment
+ int index = lastCommentIndex;
+ int validCount = 0;
+ while (index >= 0) {
+ int commentEnd = this.scanner.commentStops[index];
+ if (commentEnd < 0)
+ commentEnd = -commentEnd; // negative end position for non-javadoc comments
+ if (commentEnd <= position) {
+ break;
+ }
+ index--;
+ validCount++;
+ }
+ // if the source at <position> is immediately followed by a line comment, then
+ // flush this comment and shift <position> to the comment end.
+ if (validCount > 0) {
+ int immediateCommentEnd = -this.scanner.commentStops[index + 1]; //non-javadoc comment end positions are negative
+ if (immediateCommentEnd > 0) { // only tolerating non-javadoc comments
+ // is there any line break until the end of the immediate comment ? (thus only tolerating line comment)
+ immediateCommentEnd--; // comment end in one char too far
+ if (Util.getLineNumber(position, this.scanner.lineEnds, 0, this.scanner.linePtr)
+ == Util.getLineNumber(immediateCommentEnd, this.scanner.lineEnds, 0, this.scanner.linePtr)) {
+ position = immediateCommentEnd;
+ validCount--; // flush this comment
+ index++;
+ }
+ }
+ }
+
+ if (index < 0)
+ return position; // no obsolete comment
+
+ switch (validCount) {
+ case 0:
+ // do nothing
+ break;
+ // move valid comment infos, overriding obsolete comment infos
+ case 2:
+ this.scanner.commentStarts[0] = this.scanner.commentStarts[index + 1];
+ this.scanner.commentStops[0] = this.scanner.commentStops[index + 1];
+ this.scanner.commentTagStarts[0] = this.scanner.commentTagStarts[index + 1];
+ this.scanner.commentStarts[1] = this.scanner.commentStarts[index + 2];
+ this.scanner.commentStops[1] = this.scanner.commentStops[index + 2];
+ this.scanner.commentTagStarts[1] = this.scanner.commentTagStarts[index + 2];
+ break;
+ case 1:
+ this.scanner.commentStarts[0] = this.scanner.commentStarts[index + 1];
+ this.scanner.commentStops[0] = this.scanner.commentStops[index + 1];
+ this.scanner.commentTagStarts[0] = this.scanner.commentTagStarts[index + 1];
+ break;
+ default:
+ System.arraycopy(this.scanner.commentStarts, index + 1, this.scanner.commentStarts, 0, validCount);
+ System.arraycopy(this.scanner.commentStops, index + 1, this.scanner.commentStops, 0, validCount);
+ System.arraycopy(this.scanner.commentTagStarts, index + 1, this.scanner.commentTagStarts, 0, validCount);
+ }
+ this.scanner.commentPtr = validCount - 1;
+ return position;
+ }
+
+ public int getFirstToken() {
+ // the first token is a virtual token that
+ // allows the parser to parse several goals
+ // even if they aren't LALR(1)....
+ // Goal ::= '++' JavaScriptUnit
+ // Goal ::= '--' MethodBody
+ // Goal ::= '==' ConstructorBody
+ // -- Initializer
+ // Goal ::= '>>' StaticInitializer
+ // Goal ::= '>>' Block
+ // -- error recovery
+ // Goal ::= '>>>' Headers
+ // Goal ::= '*' BlockStatements
+ // Goal ::= '*' MethodPushModifiersHeader
+ // -- JDOM
+ // Goal ::= '&&' FieldDeclaration
+ // Goal ::= '||' ImportDeclaration
+ // Goal ::= '?' PackageDeclaration
+ // Goal ::= '+' TypeDeclaration
+ // Goal ::= '/' GenericMethodDeclaration
+ // Goal ::= '&' ClassBodyDeclaration
+ // -- code snippet
+ // Goal ::= '%' Expression
+ // -- completion parser
+ // Goal ::= '!' ConstructorBlockStatementsopt
+ // Goal ::= '~' BlockStatementsopt
+
+ return this.firstToken;
+ }
+
+ /*
+ * Answer back an array of sourceStart/sourceEnd positions of the available JavaDoc comments.
+ * The array is a flattened structure: 2*n entries with consecutives start and end positions.
+ *
+ * If no JavaDoc is available, then null is answered instead of an empty array.
+ *
+ * e.g. { 10, 20, 25, 45 } --> javadoc1 from 10 to 20, javadoc2 from 25 to 45
+ */
+ public int[] getJavaDocPositions() {
+
+ int javadocCount = 0;
+ for (int i = 0, max = this.scanner.commentPtr; i <= max; i++) {
+ // javadoc only (non javadoc comment have negative end positions.)
+ if (this.scanner.commentStops[i] > 0) {
+ javadocCount++;
+ }
+ }
+ if (javadocCount == 0)
+ return null;
+
+ int[] positions = new int[2 * javadocCount];
+ int index = 0;
+ for (int i = 0, max = this.scanner.commentPtr; i <= max; i++) {
+ // javadoc only (non javadoc comment have negative end positions.)
+ if (this.scanner.commentStops[i] > 0) {
+ positions[index++] = this.scanner.commentStarts[i];
+ positions[index++] = this.scanner.commentStops[i] - 1; //stop is one over
+ }
+ }
+ return positions;
+ }
+
+ public void getMethodBodies(CompilationUnitDeclaration unit) {
+ //fill the methods bodies in order for the code to be generated
+
+ if (unit == null)
+ return;
+
+ if (unit.ignoreMethodBodies) {
+ unit.ignoreFurtherInvestigation = true;
+ return;
+ // if initial diet parse did not work, no need to dig into method bodies.
+ }
+
+ if ((unit.bits & ASTNode.HasAllMethodBodies) != 0)
+ return; //work already done ...
+
+ // save existing values to restore them at the end of the parsing process
+ // see bug 47079 for more details
+ int[] oldLineEnds = this.scanner.lineEnds;
+ int oldLinePtr = this.scanner.linePtr;
+
+ //real parse of the method....
+ CompilationResult compilationResult = unit.compilationResult;
+ char[] contents = compilationResult.compilationUnit.getContents();
+ this.scanner.setSource(contents, compilationResult);
+
+ if (this.javadocParser != null && this.javadocParser.checkDocComment) {
+ this.javadocParser.scanner.setSource(contents);
+ }
+ if (unit.types != null) {
+ for (int i = unit.types.length; --i >= 0;)
+ unit.types[i].parseMethod(this, unit);
+ }
+
+ // tag unit has having read bodies
+ unit.bits |= ASTNode.HasAllMethodBodies;
+
+ // this is done to prevent any side effects on the compilation unit result
+ // line separator positions array.
+ this.scanner.lineEnds = oldLineEnds;
+ this.scanner.linePtr = oldLinePtr;
+ }
+
+ protected char getNextCharacter(char[] comment, int[] index) {
+ char nextCharacter = comment[index[0]++];
+ switch (nextCharacter) {
+ case '\\':
+ int c1,
+ c2,
+ c3,
+ c4;
+ index[0]++;
+ while (comment[index[0]] == 'u')
+ index[0]++;
+ if (!(((c1 = ScannerHelper.getNumericValue(comment[index[0]++])) > 15
+ || c1 < 0)
+ || ((c2 = ScannerHelper.getNumericValue(comment[index[0]++])) > 15 || c2 < 0)
+ || ((c3 = ScannerHelper.getNumericValue(comment[index[0]++])) > 15 || c3 < 0)
+ || ((c4 = ScannerHelper.getNumericValue(comment[index[0]++])) > 15 || c4 < 0))) {
+ nextCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ break;
+ }
+ return nextCharacter;
+ }
+
+ protected Expression getTypeReference(Expression exp) {
+
+ exp.bits &= ~ASTNode.RestrictiveFlagMASK;
+ exp.bits |= Binding.TYPE;
+ return exp;
+ }
+
+ 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*/
+
+ TypeReference ref;
+ int length = this.identifierLengthStack[this.identifierLengthPtr--];
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = this.intStack[this.intPtr--];
+ if (dim == 0) {
+ ref.sourceEnd = this.intStack[this.intPtr--];
+ } else {
+ this.intPtr--;
+ ref.sourceEnd = this.endPosition;
+ }
+ } else {
+ int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
+ if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
+ ref = null;
+ } else if (length == 1) {
+ // single variable reference
+ this.genericsLengthPtr--; // pop the 0
+ if (dim == 0) {
+ ref =
+ new SingleTypeReference(
+ this.identifierStack[this.identifierPtr],
+ this.identifierPositionStack[this.identifierPtr--]);
+ } else {
+ ref =
+ new ArrayTypeReference(
+ this.identifierStack[this.identifierPtr],
+ dim,
+ this.identifierPositionStack[this.identifierPtr--]);
+ ref.sourceEnd = this.endPosition;
+ }
+ } else {
+ this.genericsLengthPtr--;
+ //Qualified variable reference
+ char[][] tokens = new char[length][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ this.identifierPositionStack,
+ this.identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0) {
+ ref = new QualifiedTypeReference(tokens, positions);
+ } else {
+ ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+ ref.sourceEnd = this.endPosition;
+ }
+ }
+ }
+ return ref;
+ }
+
+ protected NameReference getUnspecifiedReference() {
+ /* build a (unspecified) NameReference which may be qualified*/
+
+ int length;
+ NameReference ref;
+ if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1)
+ // single variable reference
+ ref =
+ new SingleNameReference(
+ this.identifierStack[this.identifierPtr],
+ this.identifierPositionStack[this.identifierPtr--]);
+ 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 QualifiedNameReference(tokens,
+ positions,
+ (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
+ (int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd
+ }
+ return ref;
+ }
+
+ 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 */
+
+ int length;
+ NameReference ref;
+ if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
+ // single variable reference
+ ref =
+ new SingleNameReference(
+ this.identifierStack[this.identifierPtr],
+ this.identifierPositionStack[this.identifierPtr--]);
+ ref.bits &= ~ASTNode.RestrictiveFlagMASK;
+ ref.bits |= Binding.LOCAL | Binding.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 QualifiedNameReference(
+ tokens,
+ positions,
+ (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
+ (int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd
+ ref.bits &= ~ASTNode.RestrictiveFlagMASK;
+ ref.bits |= Binding.LOCAL | Binding.FIELD;
+ return ref;
+ }
+
+ public void goForBlockStatementsopt() {
+ //tells the scanner to go for block statements opt parsing
+
+ this.firstToken = TokenNameTWIDDLE;
+ this.scanner.recordLineSeparator = false;
+ }
+
+ public void goForProgramElements() {
+ //tells the scanner to go for block statements opt parsing
+
+ this.firstToken = TokenNamePLUS;
+ this.scanner.recordLineSeparator = true;
+ }
+
+ public void goForBlockStatementsOrCatchHeader() {
+ //tells the scanner to go for block statements or method headers parsing
+
+ this.firstToken = TokenNameMULTIPLY;
+ this.scanner.recordLineSeparator = false;
+ }
+
+ public void goForClassBodyDeclarations() {
+ //tells the scanner to go for any body declarations parsing
+
+ // this.firstToken = TokenNameAND;
+ this.firstToken = TokenNamePLUS;
+ this.scanner.recordLineSeparator = true;
+ }
+
+ public void goForCompilationUnit() {
+ //tells the scanner to go for compilation unit parsing
+
+ this.firstToken = TokenNamePLUS_PLUS;
+ this.scanner.foundTaskCount = 0;
+ this.scanner.recordLineSeparator = true;
+ }
+
+ public void goForExpression() {
+ //tells the scanner to go for an expression parsing
+
+ this.firstToken = TokenNameREMAINDER;
+ this.scanner.recordLineSeparator = true; // recovery goals must record line separators
+ }
+
+ public void goForFieldDeclaration() {
+ //tells the scanner to go for field declaration parsing
+
+ this.firstToken = TokenNameAND_AND;
+ this.scanner.recordLineSeparator = true;
+ }
+
+ public void goForHeaders() {
+ //tells the scanner to go for headers only parsing
+ // RecoveredType currentType = this.currentRecoveryType();
+ // if(currentType != null && currentType.insideEnumConstantPart) {
+ // this.firstToken = TokenNameNOT;
+ // } else {
+ this.firstToken = TokenNameUNSIGNED_RIGHT_SHIFT;
+ // }
+ this.scanner.recordLineSeparator = true; // recovery goals must record line separators
+ }
+
+ public void goForInitializer() {
+ //tells the scanner to go for initializer parsing
+
+ this.firstToken = TokenNameRIGHT_SHIFT;
+ this.scanner.recordLineSeparator = false;
+ }
+
+ public void goForMemberValue() {
+ //tells the scanner to go for a member value parsing
+
+ this.firstToken = TokenNameOR_OR;
+ this.scanner.recordLineSeparator = true; // recovery goals must record line separators
+ }
+
+ public void goForMethodBody() {
+ //tells the scanner to go for method body parsing
+
+ this.firstToken = TokenNameMINUS_MINUS;
+ this.scanner.recordLineSeparator = false;
+ }
+
+ public void goForTypeDeclaration() {
+ //tells the scanner to go for type (interface or class) declaration parsing
+
+ this.firstToken = TokenNamePLUS;
+ this.scanner.recordLineSeparator = true;
+ }
+
+ protected void ignoreExpressionAssignment() {
+ // Assignment ::= InvalidArrayInitializerAssignement
+ // encoded operator would be: this.intStack[this.intPtr]
+ this.intPtr--;
+ ArrayInitializer arrayInitializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--];
+ this.expressionLengthPtr--;
+ }
+
+ public void initialize() {
+ this.initialize(false);
+ }
+
+ public void initialize(boolean initializeNLS) {
+ //positionning the parser for a new compilation unit
+ //avoiding stack reallocation and all that....
+ this.astPtr = -1;
+ this.astLengthPtr = -1;
+ this.expressionPtr = -1;
+ this.expressionLengthPtr = -1;
+ this.identifierPtr = -1;
+ this.identifierLengthPtr = -1;
+ this.intPtr = -1;
+ this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse
+ this.variablesCounter[this.nestedType] = 0;
+ this.dimensions = 0;
+ this.realBlockPtr = 0;
+ this.compilationUnit = null;
+ this.referenceContext = null;
+ this.endStatementPosition = 0;
+
+ //remove objects from stack too, while the same parser/compiler couple is
+ //re-used between two compilations ....
+
+ int astLength = this.astStack.length;
+ if (this.noAstNodes.length < astLength) {
+ this.noAstNodes = new ASTNode[astLength];
+ //System.out.println("Resized AST stacks : "+ astLength);
+
+ }
+ System.arraycopy(this.noAstNodes, 0, this.astStack, 0, astLength);
+
+ int expressionLength = this.expressionStack.length;
+ if (this.noExpressions.length < expressionLength) {
+ this.noExpressions = new Expression[expressionLength];
+ //System.out.println("Resized EXPR stacks : "+ expressionLength);
+ }
+ System.arraycopy(this.noExpressions, 0, this.expressionStack, 0, expressionLength);
+
+ // reset this.scanner state
+ this.scanner.commentPtr = -1;
+ this.scanner.foundTaskCount = 0;
+ this.scanner.eofPosition = Integer.MAX_VALUE;
+ this.recordStringLiterals = true;
+ final boolean checkNLS = this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore;
+ this.checkExternalizeStrings = checkNLS;
+ this.scanner.checkNonExternalizedStringLiterals = initializeNLS && checkNLS;
+
+ resetModifiers();
+
+ // recovery
+ this.lastCheckPoint = -1;
+ this.currentElement = null;
+ this.restartRecovery = false;
+ this.hasReportedError = false;
+ this.recoveredStaticInitializerStart = 0;
+ this.lastIgnoredToken = -1;
+ this.lastErrorEndPosition = -1;
+ this.lastErrorEndPositionBeforeRecovery = -1;
+ this.lastJavadocEnd = -1;
+ this.listLength = 0;
+ this.listTypeParameterLength = 0;
+
+ this.rBraceStart = 0;
+ this.rBraceEnd = 0;
+ this.rBraceSuccessorStart = 0;
+
+ this.genericsIdentifiersLengthPtr = -1;
+ this.genericsLengthPtr = -1;
+ this.genericsPtr = -1;
+
+ this.errorAction = new HashSet();
+
+ }
+
+ public void initializeScanner() {
+ this.scanner = new Scanner(
+ false /*comment*/,
+ false /*whitespace*/,
+ false, /* will be set in initialize(boolean) */
+ this.options.sourceLevel /*sourceLevel*/,
+ this.options.complianceLevel /*complianceLevel*/,
+ this.options.taskTags/*taskTags*/,
+ this.options.taskPriorites/*taskPriorities*/,
+ this.options.isTaskCaseSensitive/*taskCaseSensitive*/);
+ }
+
+ public void jumpOverMethodBody() {
+ //on diet parsing.....do not buffer method statements
+
+ //the scanner.diet is reinitialized to false
+ //automatically by the scanner once it has jumped over
+ //the statements
+
+ if (this.diet && (this.dietInt == 0))
+ this.scanner.diet = true;
+ }
+
+ private void jumpOverType() {
+ if (this.recoveredTypes != null && this.nextTypeStart > -1 && this.nextTypeStart < this.scanner.currentPosition) {
+
+ if (DEBUG_AUTOMATON) {
+ System.out.println("Jump -"); //$NON-NLS-1$
+ }
+
+ TypeDeclaration typeDeclaration = this.recoveredTypes[this.recoveredTypePtr];
+ boolean isAnonymous = typeDeclaration.allocation != null;
+
+ int end = this.scanner.eofPosition;
+ this.scanner.resetTo(typeDeclaration.declarationSourceEnd + 1, end - 1);
+ if (!isAnonymous) {
+ ((RecoveryScanner) this.scanner).setPendingTokens(new int[] { TokenNameSEMICOLON, TokenNamebreak });
+ } else {
+ ((RecoveryScanner) this.scanner).setPendingTokens(new int[] { TokenNameIdentifier, TokenNameEQUAL, TokenNameIdentifier });
+ }
+
+ this.pendingRecoveredType = typeDeclaration;
+
+ try {
+ this.currentToken = this.scanner.getNextToken();
+ } catch (InvalidInputException e) {
+ // it's impossible because we added pending tokens before
+ }
+
+ if (++this.recoveredTypePtr < this.recoveredTypes.length) {
+ TypeDeclaration nextTypeDeclaration = this.recoveredTypes[this.recoveredTypePtr];
+ this.nextTypeStart =
+ nextTypeDeclaration.allocation == null
+ ? nextTypeDeclaration.declarationSourceStart
+ : nextTypeDeclaration.allocation.sourceStart;
+ } else {
+ this.nextTypeStart = Integer.MAX_VALUE;
+ }
+ }
+ }
+
+ protected void markEnclosingMemberWithLocalType() {
+ if (this.currentElement != null)
+ return; // this is already done in the recovery code
+ for (int i = this.astPtr; i >= 0; i--) {
+ ASTNode node = this.astStack[i];
+ if (node instanceof AbstractMethodDeclaration
+ || node instanceof FieldDeclaration
+ || (node instanceof TypeDeclaration // mark type for now: all initializers will be marked when added to this type
+ // and enclosing type must not be closed (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=147485)
+ && ((TypeDeclaration) node).declarationSourceEnd == 0)) {
+ node.bits |= ASTNode.HasLocalType;
+ return;
+ }
+ }
+ // default to reference context (case of parse method body)
+ if (this.referenceContext instanceof AbstractMethodDeclaration
+ || this.referenceContext instanceof TypeDeclaration) {
+ ((ASTNode) this.referenceContext).bits |= ASTNode.HasLocalType;
+ }
+ }
+
+ protected void markInitializersWithLocalType(TypeDeclaration type) {
+ if (type.fields == null || (type.bits & ASTNode.HasLocalType) == 0)
+ return;
+ for (int i = 0, length = type.fields.length; i < length; i++) {
+ FieldDeclaration field = type.fields[i];
+ if (field instanceof Initializer) {
+ field.bits |= ASTNode.HasLocalType;
+ }
+ }
+ }
+
+ /*
+ * Move checkpoint location (current implementation is moving it by one token)
+ *
+ * Answers true if successfully moved checkpoint (in other words, it did not attempt to move it
+ * beyond end of file).
+ */
+ protected boolean moveRecoveryCheckpoint() {
+
+ int pos = this.lastCheckPoint;
+ /* reset this.scanner, and move checkpoint by one token */
+ this.scanner.startPosition = pos;
+ this.scanner.currentPosition = pos;
+ this.scanner.currentToken = this.scanner.currentNonWhitespaceToken = TokenNameUNKNOWN;
+ this.scanner.diet = false; // quit jumping over method bodies
+
+ /* if about to restart, then no need to shift token */
+ if (this.restartRecovery) {
+ this.lastIgnoredToken = -1;
+ this.scanner.insideRecovery = true;
+ return true;
+ }
+
+ /* protect against shifting on an invalid token */
+ this.lastIgnoredToken = this.nextIgnoredToken;
+ this.nextIgnoredToken = -1;
+ do {
+ try {
+ this.nextIgnoredToken = this.scanner.getNextToken();
+ if (this.scanner.currentPosition == this.scanner.startPosition) {
+ this.scanner.currentPosition++; // on fake completion identifier
+ this.nextIgnoredToken = -1;
+ }
+
+ } catch (InvalidInputException e) {
+ pos = this.scanner.currentPosition;
+ }
+ } while (this.nextIgnoredToken < 0);
+
+ if (this.nextIgnoredToken == TokenNameEOF) { // no more recovery after this point
+ if (this.currentToken == TokenNameEOF) { // already tried one iteration on EOF
+ return false;
+ }
+ }
+ this.lastCheckPoint = this.scanner.currentPosition;
+
+ /* reset this.scanner again to previous checkpoint location*/
+ this.scanner.startPosition = pos;
+ this.scanner.currentPosition = pos;
+ this.scanner.currentToken = TokenNameUNKNOWN;
+ this.scanner.commentPtr = -1;
+ this.scanner.foundTaskCount = 0;
+ return true;
+
+ /*
+ The following implementation moves the checkpoint location by one line:
+
+ int pos = this.lastCheckPoint;
+ // reset this.scanner, and move checkpoint by one token
+ this.scanner.startPosition = pos;
+ this.scanner.currentPosition = pos;
+ this.scanner.diet = false; // quit jumping over method bodies
+
+ // if about to restart, then no need to shift token
+ if (this.restartRecovery){
+ this.lastIgnoredToken = -1;
+ return true;
+ }
+
+ // protect against shifting on an invalid token
+ this.lastIgnoredToken = this.nextIgnoredToken;
+ this.nextIgnoredToken = -1;
+
+ boolean wasTokenizingWhiteSpace = this.scanner.tokenizeWhiteSpace;
+ this.scanner.tokenizeWhiteSpace = true;
+ checkpointMove:
+ do {
+ try {
+ this.nextIgnoredToken = this.scanner.getNextToken();
+ switch(this.nextIgnoredToken){
+ case Scanner.TokenNameWHITESPACE :
+ if(this.scanner.getLineNumber(this.scanner.startPosition)
+ == this.scanner.getLineNumber(this.scanner.currentPosition)){
+ this.nextIgnoredToken = -1;
+ }
+ break;
+ case TokenNameSEMICOLON :
+ case TokenNameLBRACE :
+ case TokenNameRBRACE :
+ break;
+ case TokenNameIdentifier :
+ if(this.scanner.currentPosition == this.scanner.startPosition){
+ this.scanner.currentPosition++; // on fake completion identifier
+ }
+ default:
+ this.nextIgnoredToken = -1;
+ break;
+ case TokenNameEOF :
+ break checkpointMove;
+ }
+ } catch(InvalidInputException e){
+ pos = this.scanner.currentPosition;
+ }
+ } while (this.nextIgnoredToken < 0);
+ this.scanner.tokenizeWhiteSpace = wasTokenizingWhiteSpace;
+
+ if (this.nextIgnoredToken == TokenNameEOF) { // no more recovery after this point
+ if (this.currentToken == TokenNameEOF) { // already tried one iteration on EOF
+ return false;
+ }
+ }
+ this.lastCheckPoint = this.scanner.currentPosition;
+
+ // reset this.scanner again to previous checkpoint location
+ this.scanner.startPosition = pos;
+ this.scanner.currentPosition = pos;
+ this.scanner.commentPtr = -1;
+
+ return true;
+ */
+ }
+
+ protected MessageSend newMessageSend() {
+ // '(' ArgumentListopt ')'
+ // the arguments are on the expression stack
+
+ MessageSend m = new MessageSend();
+ 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;
+ }
+
+ protected void optimizedConcatNodeLists() {
+ /*back from a recursive loop. Virtualy group the
+ astNode into an array using this.astLengthStack*/
+
+ /*
+ * This is a case where you have two sublists into the this.astStack that you want
+ * to merge in one list. There is no action required on the this.astStack. The only
+ * thing you need to do is merge the two lengths specified on the astStackLength.
+ * The top two length are for example:
+ * ... p n
+ * and you want to result in a list like:
+ * ... n+p
+ * This means that the p could be equals to 0 in case there is no astNode pushed
+ * on the this.astStack.
+ * Look at the InterfaceMemberDeclarations for an example.
+ * This case optimizes the fact that p == 1.
+ */
+
+ this.astLengthStack[--this.astLengthPtr]++;
+ }
+
+ protected boolean isErrorState(int act) {
+ int stackTop = this.stateStackTop;
+ int[] tempStack = new int[this.stack.length + 2];
+ System.arraycopy(this.stack, 0, tempStack, 0, this.stack.length);
+ boolean first = true;
+ int currentAction = act;
+ ProcessTerminals: for (;;) {
+ int stackLength = tempStack.length;
+ if (!first)
+ {
+ if (++stackTop >= stackLength) {
+ System.arraycopy(
+ tempStack, 0,
+ tempStack = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ tempStack[stackTop] = currentAction;
+ }
+ first = false;
+ currentAction = tAction(currentAction, this.currentToken);
+ if (currentAction == ERROR_ACTION) {
+ return true;
+ }
+ if (currentAction <= NUM_RULES) {
+ stackTop--;
+
+ } else if (currentAction > ERROR_ACTION) { /* shift-reduce */
+ if (DEBUG)
+ System.out.println("<<shift-reduce consume Token: " + scanner.toStringAction(this.currentToken)); //$NON-NLS-1$
+ return false;
+ // consumeToken(this.currentToken);
+ // if (this.currentElement != null) this.recoveryTokenCheck();
+ // try {
+ // prevPos = scanner.currentPosition;
+ // prevToken = currentToken;
+ // insertedSemicolon = false;
+ // this.currentToken = this.scanner.getNextToken();
+ // if (DEBUG) System.out.println(">>shift-reduce Next Token: "+scanner.dumpCurrent());
+ // } catch(InvalidInputException e){
+ // if (!this.hasReportedError){
+ // this.problemReporter().scannerError(this, e.getMessage());
+ // this.hasReportedError = true;
+ // }
+ // this.lastCheckPoint = this.scanner.currentPosition;
+ // this.restartRecovery = true;
+ // }
+ // if(this.statementRecoveryActivated) {
+ // jumpOverTypeAfterReduce = true;
+ // }
+ // act -= ERROR_ACTION;
+
+ } else {
+ if (currentAction < ACCEPT_ACTION) { /* shift */
+ if (DEBUG)
+ System.out.println("<<shift consume Token: " + scanner.toStringAction(this.currentToken)); //$NON-NLS-1$
+ return false;
+ // consumeToken(this.currentToken);
+ // if (this.currentElement != null) this.recoveryTokenCheck();
+ // try{
+ // prevPos = scanner.currentPosition;
+ // prevToken = currentToken;
+ // insertedSemicolon = false;
+ // this.currentToken = this.scanner.getNextToken();
+ // if (DEBUG) System.out.println(">>shift next Token: "+scanner.dumpCurrent());
+ // } catch(InvalidInputException e){
+ // if (!this.hasReportedError){
+ // this.problemReporter().scannerError(this, e.getMessage());
+ // this.hasReportedError = true;
+ // }
+ // this.lastCheckPoint = this.scanner.currentPosition;
+ // this.restartRecovery = true;
+ // }
+ // if(this.statementRecoveryActivated) {
+ // this.jumpOverType();
+ // }
+ // continue ProcessTerminals;
+ }
+ break ProcessTerminals;
+ }
+
+ // ProcessNonTerminals :
+ do { /* reduce */
+ stackTop -= (rhs[currentAction] - 1);
+ currentAction = ntAction(tempStack[stackTop], lhs[currentAction]);
+ } while (currentAction <= NUM_RULES);
+ }
+ return false;
+ }
+
+ /*main loop of the automat
+ When a rule is reduced, the method consumeRule(int) is called with the number
+ of the consumed rule. When a terminal is consumed, the method consumeToken(int) is
+ called in order to remember (when needed) the consumed token */
+ // (int)asr[asi(act)]
+ // name[symbol_index[currentKind]]
+ protected void parse() {
+ if (DEBUG)
+ System.out.println("-- ENTER INSIDE PARSE METHOD --"); //$NON-NLS-1$
+
+ if (DEBUG_AUTOMATON) {
+ System.out.println("- Start --------------------------------"); //$NON-NLS-1$
+ }
+
+ boolean isDietParse = this.diet;
+ int oldFirstToken = getFirstToken();
+ this.hasError = false;
+
+ this.hasReportedError = false;
+ boolean insertedSemicolon = false;
+ int prevAct = START_STATE, prevToken = getFirstToken(), prevPos = scanner.startPosition;
+
+ int act = START_STATE;
+ this.stateStackTop = -1;
+ this.currentToken = getFirstToken();
+ ProcessTerminals: for (;;) {
+ int stackLength = this.stack.length;
+ if (++this.stateStackTop >= stackLength) {
+ System.arraycopy(
+ this.stack, 0,
+ this.stack = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ this.stack[this.stateStackTop] = act;
+
+ if (DEBUG)
+ System.out.println("action=" + act + ((term_check[base_action[act] + this.currentToken] == this.currentToken) ? "" : " - take default")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ prevAct = act;
+
+ if (optionalSemicolonState[act])
+ {
+ if (term_check[base_action[act] + this.currentToken] != this.currentToken)
+ {
+ if (isErrorState(act))
+ {
+ if (!insertedSemicolon && shouldInsertSemicolon(prevPos, prevToken))
+ {
+ currentToken = TokenNameSEMICOLON;
+ this.insertedSemicolonPosition = prevPos;
+ scanner.pushBack();
+ insertedSemicolon = true;
+
+ }
+ }
+ }
+ }
+
+ act = tAction(act, this.currentToken);
+ if (act == ERROR_ACTION || this.restartRecovery) {
+ // if ( act == ERROR_ACTION &&
+ // !insertedSemicolon &&
+ // shouldInsertSemicolon(prevPos, prevToken)
+ // ) {
+ // act = prevAct;
+ // --stateStackTop;
+ // currentToken = TokenNameSEMICOLON;
+ // scanner.pushBack();
+ // insertedSemicolon = true;
+ // continue ProcessTerminals;
+ // }
+
+ if (DEBUG_AUTOMATON) {
+ if (this.restartRecovery) {
+ System.out.println("Restart - "); //$NON-NLS-1$
+ } else {
+ System.out.println("Error - "); //$NON-NLS-1$
+ }
+ }
+
+ int errorPos = this.scanner.currentPosition;
+ if (!this.hasReportedError) {
+ this.hasError = true;
+ }
+ if (resumeOnSyntaxError()) {
+ if (act == ERROR_ACTION)
+ this.lastErrorEndPosition = errorPos;
+ act = START_STATE;
+ this.stateStackTop = -1;
+ this.currentToken = getFirstToken();
+ if (DEBUG)
+ System.out.println("!! Resume on syntax error"); //$NON-NLS-1$
+ continue ProcessTerminals;
+ }
+ act = ERROR_ACTION;
+ break ProcessTerminals;
+ }
+ if (act <= NUM_RULES) {
+ insertedSemicolon = false;
+ this.stateStackTop--;
+
+ if (DEBUG_AUTOMATON) {
+ System.out.print("Reduce - "); //$NON-NLS-1$
+ }
+
+ } else if (act > ERROR_ACTION) { /* shift-reduce */
+ if (DEBUG)
+ System.out.println("<<shift-reduce consume Token: " + scanner.toStringAction(this.currentToken)); //$NON-NLS-1$
+ consumeToken(this.currentToken);
+ if (this.currentElement != null)
+ this.recoveryTokenCheck();
+ try {
+ prevPos = scanner.currentPosition;
+ prevToken = currentToken;
+ insertedSemicolon = false;
+ this.currentToken = this.scanner.getNextToken();
+ if (DEBUG)
+ System.out.println(">>shift-reduce Next Token: " + scanner.dumpCurrent()); //$NON-NLS-1$
+ } catch (InvalidInputException e) {
+ if (!this.hasReportedError) {
+ this.problemReporter().scannerError(this, e.getMessage());
+ this.hasReportedError = true;
+ }
+ this.lastCheckPoint = this.scanner.currentPosition;
+ this.restartRecovery = true;
+ }
+ if (this.statementRecoveryActivated) {
+ this.jumpOverType();
+ }
+ act -= ERROR_ACTION;
+
+ if (DEBUG_AUTOMATON) {
+ System.out.print("Shift/Reduce - (" + name[terminal_index[this.currentToken]] + ") "); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ } else {
+ if (act < ACCEPT_ACTION) { /* shift */
+ if (DEBUG)
+ System.out.println("<<shift consume Token: " + scanner.toStringAction(this.currentToken)); //$NON-NLS-1$
+ consumeToken(this.currentToken);
+ if (this.currentElement != null)
+ this.recoveryTokenCheck();
+ try {
+ prevPos = scanner.currentPosition;
+ prevToken = currentToken;
+ insertedSemicolon = false;
+ this.currentToken = this.scanner.getNextToken();
+ if (DEBUG)
+ System.out.println(">>shift next Token: " + scanner.dumpCurrent()); //$NON-NLS-1$
+ } catch (InvalidInputException e) {
+ if (!this.hasReportedError) {
+ this.problemReporter().scannerError(this, e.getMessage());
+ this.hasReportedError = true;
+ }
+ this.lastCheckPoint = this.scanner.currentPosition;
+ this.restartRecovery = true;
+ }
+ if (this.statementRecoveryActivated) {
+ this.jumpOverType();
+ }
+ if (DEBUG_AUTOMATON) {
+ System.out.println("Shift - (" + name[terminal_index[this.currentToken]] + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ continue ProcessTerminals;
+ }
+ break ProcessTerminals;
+ }
+
+ // ProcessNonTerminals :
+ do { /* reduce */
+
+ if (DEBUG_AUTOMATON) {
+ System.out.println(name[non_terminal_index[lhs[act]]]);
+ }
+
+ consumeRule(act);
+ this.stateStackTop -= (rhs[act] - 1);
+ act = ntAction(this.stack[this.stateStackTop], lhs[act]);
+ if (DEBUG_AUTOMATON && act <= NUM_RULES) {
+ System.out.print(" - "); //$NON-NLS-1$
+ }
+
+ } while (act <= NUM_RULES);
+ if (DEBUG_AUTOMATON) {
+ System.out.println("----------------------------------------"); //$NON-NLS-1$
+ }
+ }
+ if (DEBUG_AUTOMATON) {
+ System.out.println("- End ----------------------------------"); //$NON-NLS-1$
+ }
+
+ endParse(act);
+ // record all nls tags in the corresponding compilation unit
+ final NLSTag[] tags = this.scanner.getNLSTags();
+ if (tags != null) {
+ this.compilationUnit.nlsTags = tags;
+ }
+
+ this.scanner.checkNonExternalizedStringLiterals = false;
+ if (this.reportSyntaxErrorIsRequired && this.hasError && !(this.statementRecoveryActivated && DO_DIET_PARSE)) {
+ if (!this.options.performStatementsRecovery) {
+ reportSyntaxErrors(isDietParse, oldFirstToken);
+ } else {
+ RecoveryScannerData data = this.referenceContext.compilationResult().recoveryScannerData;
+
+ if (this.recoveryScanner == null) {
+ this.recoveryScanner = new RecoveryScanner(this.scanner, data);
+ } else {
+ this.recoveryScanner.setData(data);
+ }
+
+ this.recoveryScanner.setSource(scanner.source);
+ this.recoveryScanner.lineEnds = this.scanner.lineEnds;
+ this.recoveryScanner.linePtr = this.scanner.linePtr;
+
+ reportSyntaxErrors(isDietParse, oldFirstToken);
+
+ if (data == null) {
+ this.referenceContext.compilationResult().recoveryScannerData =
+ this.recoveryScanner.getData();
+ }
+
+ if (this.methodRecoveryActivated && this.options.performStatementsRecovery && !this.enteredRecoverStatements) {
+ this.methodRecoveryActivated = false;
+ this.enteredRecoverStatements = true;
+ this.recoverStatements();
+ this.methodRecoveryActivated = true;
+
+ this.lastAct = ERROR_ACTION;
+ }
+ }
+ }
+
+ if (DEBUG)
+ System.out.println("-- EXIT FROM PARSE METHOD --"); //$NON-NLS-1$
+ }
+
+ public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
+ parse(cd, unit, false);
+ }
+
+ public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit, boolean recordLineSeparator) {
+ //only parse the method body of cd
+ //fill out its statements
+
+ //convert bugs into parse error
+
+ boolean oldMethodRecoveryActivated = this.methodRecoveryActivated;
+ if (this.options.performMethodsFullRecovery) {
+ this.methodRecoveryActivated = true;
+ }
+
+ initialize();
+ goForBlockStatementsopt();
+ if (recordLineSeparator) {
+ this.scanner.recordLineSeparator = true;
+ }
+ this.nestedMethod[this.nestedType]++;
+ pushOnRealBlockStack(0);
+
+ this.referenceContext = cd;
+ this.compilationUnit = unit;
+
+ this.scanner.resetTo(cd.bodyStart, cd.bodyEnd);
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
+ } finally {
+ this.nestedMethod[this.nestedType]--;
+ if (this.options.performStatementsRecovery) {
+ this.methodRecoveryActivated = oldMethodRecoveryActivated;
+ }
+ }
+
+ checkNonNLSAfterBodyEnd(cd.declarationSourceEnd);
+
+ if (this.lastAct == ERROR_ACTION) {
+ initialize();
+ return;
+ }
+
+ //statements
+ cd.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+ int length;
+ if (astLengthPtr > -1 && (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);
+ 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;
+ }
+ }
+
+ // A P I
+
+ public void parse(
+ FieldDeclaration field,
+ TypeDeclaration type,
+ CompilationUnitDeclaration unit,
+ char[] initializationSource) {
+ //only parse the initializationSource of the given field
+
+ //convert bugs into parse error
+
+ initialize();
+ goForExpression();
+ this.nestedMethod[this.nestedType]++;
+
+ this.referenceContext = type;
+ this.compilationUnit = unit;
+
+ this.scanner.setSource(initializationSource);
+ this.scanner.resetTo(0, initializationSource.length - 1);
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
+ } finally {
+ this.nestedMethod[this.nestedType]--;
+ }
+
+ if (this.lastAct == ERROR_ACTION) {
+ return;
+ }
+
+ field.initialization = this.expressionStack[this.expressionPtr];
+
+ // mark field with local type if one was found during parsing
+ if ((type.bits & ASTNode.HasLocalType) != 0) {
+ field.bits |= ASTNode.HasLocalType;
+ }
+ }
+
+ // A P I
+
+ public CompilationUnitDeclaration parse(
+ ICompilationUnit sourceUnit,
+ CompilationResult compilationResult) {
+ // parses a compilation unit and manages error handling (even bugs....)
+
+ return parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
+ }
+
+ // A P I
+
+ public CompilationUnitDeclaration parse(
+ ICompilationUnit sourceUnit,
+ CompilationResult compilationResult,
+ int start,
+ int end) {
+ // parses a compilation unit and manages error handling (even bugs....)
+
+ CompilationUnitDeclaration unit;
+ try {
+ /* automaton initialization */
+ initialize(true);
+ goForCompilationUnit();
+
+ /* unit creation */
+ this.referenceContext =
+ this.compilationUnit =
+ new CompilationUnitDeclaration(
+ this.problemReporter,
+ compilationResult,
+ 0);
+
+ initializeInferenceEngine(this.compilationUnit);
+
+ /* scanners initialization */
+ char[] contents;
+ try {
+ contents = sourceUnit.getContents();
+ } catch (AbortCompilationUnit abortException) {
+ this.problemReporter().cannotReadSource(this.compilationUnit, abortException, this.options.verbose);
+ contents = CharOperation.NO_CHAR; // pretend empty from thereon
+ }
+ this.scanner.setSource(contents);
+ this.compilationUnit.sourceEnd = this.scanner.source.length - 1;
+ if (end != -1)
+ this.scanner.resetTo(start, end);
+ if (this.javadocParser != null && this.javadocParser.checkDocComment) {
+ this.javadocParser.scanner.setSource(contents);
+ if (end != -1) {
+ this.javadocParser.scanner.resetTo(start, end);
+ }
+ }
+ /* run automaton */
+ if (false)
+ System.out.println("parsing " + new String(sourceUnit.getFileName())); //$NON-NLS-1$
+ parse();
+ } finally {
+ unit = this.compilationUnit;
+ this.compilationUnit = null; // reset parser
+ // tag unit has having read bodies
+ if (!this.diet)
+ unit.bits |= ASTNode.HasAllMethodBodies;
+ }
+ return unit;
+ }
+
+ public void initializeInferenceEngine(CompilationUnitDeclaration compilationUnitDeclaration) {
+ if (this.inferenceEngines == null)
+ this.inferenceEngines = InferrenceManager.getInstance().getInferenceEngines(compilationUnitDeclaration);
+ for (int i = 0; i < this.inferenceEngines.length; i++) {
+ this.inferenceEngines[i].initializeOptions(this.options.inferOptions);
+ }
+ }
+
+ public void parse(
+ Initializer initializer,
+ TypeDeclaration type,
+ CompilationUnitDeclaration unit) {
+ //only parse the method body of md
+ //fill out method statements
+
+ //convert bugs into parse error
+
+ boolean oldMethodRecoveryActivated = this.methodRecoveryActivated;
+ if (this.options.performMethodsFullRecovery) {
+ this.methodRecoveryActivated = true;
+ }
+
+ initialize();
+ goForBlockStatementsopt();
+ this.nestedMethod[this.nestedType]++;
+ pushOnRealBlockStack(0);
+
+ this.referenceContext = type;
+ this.compilationUnit = unit;
+
+ this.scanner.resetTo(initializer.bodyStart, initializer.bodyEnd); // just on the beginning {
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
+ } finally {
+ this.nestedMethod[this.nestedType]--;
+ if (this.options.performStatementsRecovery) {
+ this.methodRecoveryActivated = oldMethodRecoveryActivated;
+ }
+ }
+
+ checkNonNLSAfterBodyEnd(initializer.declarationSourceEnd);
+
+ if (this.lastAct == ERROR_ACTION) {
+ return;
+ }
+
+ //refill statements
+ initializer.block.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+ int length;
+ if (astLengthPtr > -1 && (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;
+ }
+ }
+
+ // A P I
+ public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
+ //only parse the method body of md
+ //fill out method statements
+
+ //convert bugs into parse error
+
+ if (md.isAbstract())
+ return;
+ if ((md.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0)
+ return;
+
+ boolean oldMethodRecoveryActivated = this.methodRecoveryActivated;
+ if (this.options.performMethodsFullRecovery) {
+ this.methodRecoveryActivated = true;
+ this.rParenPos = md.sourceEnd;
+ }
+ initialize();
+ goForBlockStatementsopt();
+ this.nestedMethod[this.nestedType]++;
+ pushOnRealBlockStack(0);
+
+ this.referenceContext = md;
+ this.compilationUnit = unit;
+
+ this.scanner.resetTo(md.bodyStart, md.bodyEnd);
+ // reset the scanner to parser from { down to }
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
+ } finally {
+ this.nestedMethod[this.nestedType]--;
+ if (this.options.performStatementsRecovery) {
+ this.methodRecoveryActivated = oldMethodRecoveryActivated;
+ }
+ }
+
+ checkNonNLSAfterBodyEnd(md.declarationSourceEnd);
+
+ if (this.lastAct == ERROR_ACTION) {
+ return;
+ }
+
+ //refill statements
+ md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+ int length;
+ if (astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.astStack,
+ (this.astPtr -= length) + 1,
+ md.statements = new Statement[length],
+ 0,
+ length);
+ } else {
+ if (!containsComment(md.bodyStart, md.bodyEnd)) {
+ md.bits |= ASTNode.UndocumentedEmptyBlock;
+ }
+ }
+ }
+
+ public ASTNode[] parseClassBodyDeclarations(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
+ /* automaton initialization */
+ initialize();
+ goForClassBodyDeclarations();
+ /* scanner initialization */
+ this.scanner.setSource(source);
+ this.scanner.resetTo(offset, offset + length - 1);
+ if (this.javadocParser != null && this.javadocParser.checkDocComment) {
+ this.javadocParser.scanner.setSource(source);
+ this.javadocParser.scanner.resetTo(offset, offset + length - 1);
+ }
+
+ /* type declaration should be parsed as member type declaration */
+ this.nestedType = 1;
+
+ /* unit creation */
+ this.referenceContext = unit;
+ this.compilationUnit = unit;
+
+ /* run automaton */
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
+ }
+
+ if (this.lastAct == ERROR_ACTION || this.hasError) {
+ return null;
+ }
+ int astLength;
+ if (astLengthPtr > -1 && (astLength = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ ASTNode[] result = new ASTNode[astLength];
+ this.astPtr -= astLength;
+ System.arraycopy(this.astStack, this.astPtr + 1, result, 0, astLength);
+ return result;
+ }
+ return null;
+ }
+
+ public Expression parseExpression(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
+
+ initialize();
+ goForExpression();
+ this.nestedMethod[this.nestedType]++;
+
+ this.referenceContext = unit;
+ this.compilationUnit = unit;
+
+ this.scanner.setSource(source);
+ this.scanner.resetTo(offset, offset + length - 1);
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
+ } finally {
+ this.nestedMethod[this.nestedType]--;
+ }
+
+ if (this.lastAct == ERROR_ACTION) {
+ return null;
+ }
+
+ return this.expressionStack[this.expressionPtr];
+ }
+
+ public Expression parseMemberValue(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
+
+ initialize();
+ goForMemberValue();
+ this.nestedMethod[this.nestedType]++;
+
+ this.referenceContext = unit;
+ this.compilationUnit = unit;
+
+ this.scanner.setSource(source);
+ this.scanner.resetTo(offset, offset + length - 1);
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
+ } finally {
+ this.nestedMethod[this.nestedType]--;
+ }
+
+ if (this.lastAct == ERROR_ACTION) {
+ return null;
+ }
+
+ return this.expressionStack[this.expressionPtr];
+ }
+
+ public void parseStatements(ReferenceContext rc, int start, int end, TypeDeclaration[] types, CompilationUnitDeclaration unit) {
+ boolean oldStatementRecoveryEnabled = this.statementRecoveryActivated;
+ this.statementRecoveryActivated = true;
+
+ initialize();
+
+ if (rc instanceof CompilationUnitDeclaration)
+ goForCompilationUnit();
+ else
+ goForBlockStatementsopt();
+ this.nestedMethod[this.nestedType]++;
+ pushOnRealBlockStack(0);
+
+ //pushOnAstLengthStack(0);
+
+ this.referenceContext = rc;
+ this.compilationUnit = unit;
+
+ this.pendingRecoveredType = null;
+
+ if (types != null && types.length > 0) {
+ this.recoveredTypes = types;
+ this.recoveredTypePtr = 0;
+ this.nextTypeStart =
+ this.recoveredTypes[0].allocation == null
+ ? this.recoveredTypes[0].declarationSourceStart
+ : this.recoveredTypes[0].allocation.sourceStart;
+ } else {
+ this.recoveredTypes = null;
+ this.recoveredTypePtr = -1;
+ this.nextTypeStart = -1;
+ }
+
+ this.scanner.resetTo(start, end);
+ // reset the scanner to parser from { down to }
+
+ this.lastCheckPoint = this.scanner.initialPosition;
+
+ this.stateStackTop = -1;
+
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
+ } finally {
+ this.nestedMethod[this.nestedType]--;
+ this.recoveredTypes = null;
+ this.statementRecoveryActivated = oldStatementRecoveryEnabled;
+ }
+
+ checkNonNLSAfterBodyEnd(end);
+ }
+
+ public void persistLineSeparatorPositions() {
+ if (this.scanner.recordLineSeparator) {
+ this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
+ }
+ }
+
+ /*
+ * Prepares the state of the parser to go for BlockStatements.
+ */
+ protected void prepareForBlockStatements() {
+ this.nestedMethod[this.nestedType = 0] = 1;
+ this.variablesCounter[this.nestedType] = 0;
+ this.realBlockStack[this.realBlockPtr = 1] = 0;
+ }
+
+ /**
+ * 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.
+ *
+ * @return ProblemReporter
+ */
+ public ProblemReporter problemReporter() {
+ if (this.scanner.recordLineSeparator) {
+ if (this.compilationUnit != null)
+ this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
+ }
+ this.problemReporter.referenceContext = this.referenceContext;
+ return this.problemReporter;
+ }
+
+ protected void pushIdentifier() {
+ /*push the consumeToken on the identifier stack.
+ Increase the total number of identifier in the stack.
+ identifierPtr points on the next top */
+
+ int stackLength = this.identifierStack.length;
+ if (++this.identifierPtr >= stackLength) {
+ System.arraycopy(
+ this.identifierStack, 0,
+ this.identifierStack = new char[stackLength + 20][], 0,
+ stackLength);
+ System.arraycopy(
+ this.identifierPositionStack, 0,
+ this.identifierPositionStack = new long[stackLength + 20], 0,
+ stackLength);
+ }
+ this.identifierStack[this.identifierPtr] = this.scanner.getCurrentIdentifierSource();
+ this.identifierPositionStack[this.identifierPtr] =
+ (((long) this.scanner.startPosition) << 32) + (this.scanner.currentPosition - 1);
+
+ stackLength = this.identifierLengthStack.length;
+ if (++this.identifierLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.identifierLengthStack, 0,
+ this.identifierLengthStack = new int[stackLength + 10], 0,
+ stackLength);
+ }
+ this.identifierLengthStack[this.identifierLengthPtr] = 1;
+ }
+
+ protected void pushIdentifier(int flag) {
+ /*push a special flag on the stack :
+ -zero stands for optional Name
+ -negative number for direct ref to base types.
+ identifierLengthPtr points on the top */
+
+ int stackLength = this.identifierLengthStack.length;
+ if (++this.identifierLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.identifierLengthStack, 0,
+ this.identifierLengthStack = new int[stackLength + 10], 0,
+ stackLength);
+ }
+ this.identifierLengthStack[this.identifierLengthPtr] = flag;
+ }
+
+ protected void pushOnAstLengthStack(int pos) {
+
+ int stackLength = this.astLengthStack.length;
+ if (++this.astLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.astLengthStack, 0,
+ this.astLengthStack = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ this.astLengthStack[this.astLengthPtr] = pos;
+ }
+
+ protected void pushOnAstStack(ASTNode node) {
+ /*add a new obj on top of the ast stack
+ astPtr points on the top*/
+
+ int stackLength = this.astStack.length;
+ if (++this.astPtr >= stackLength) {
+ System.arraycopy(
+ this.astStack, 0,
+ this.astStack = new ASTNode[stackLength + AstStackIncrement], 0,
+ stackLength);
+ this.astPtr = stackLength;
+ }
+ this.astStack[this.astPtr] = node;
+
+ stackLength = this.astLengthStack.length;
+ if (++this.astLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.astLengthStack, 0,
+ this.astLengthStack = new int[stackLength + AstStackIncrement], 0,
+ stackLength);
+ }
+ this.astLengthStack[this.astLengthPtr] = 1;
+ }
+
+ protected void pushOnExpressionStack(Expression expr) {
+
+ int stackLength = this.expressionStack.length;
+ if (++this.expressionPtr >= stackLength) {
+ System.arraycopy(
+ this.expressionStack, 0,
+ this.expressionStack = new Expression[stackLength + ExpressionStackIncrement], 0,
+ stackLength);
+ }
+ this.expressionStack[this.expressionPtr] = expr;
+
+ stackLength = this.expressionLengthStack.length;
+ if (++this.expressionLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.expressionLengthStack, 0,
+ this.expressionLengthStack = new int[stackLength + ExpressionStackIncrement], 0,
+ stackLength);
+ }
+ this.expressionLengthStack[this.expressionLengthPtr] = 1;
+ }
+
+ protected void pushOnExpressionStackLengthStack(int pos) {
+
+ int stackLength = this.expressionLengthStack.length;
+ if (++this.expressionLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.expressionLengthStack, 0,
+ this.expressionLengthStack = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ this.expressionLengthStack[this.expressionLengthPtr] = pos;
+ }
+
+ protected void pushOnGenericsStack(ASTNode node) {
+ /*add a new obj on top of the generics stack
+ genericsPtr points on the top*/
+
+ int stackLength = this.genericsStack.length;
+ if (++this.genericsPtr >= stackLength) {
+ System.arraycopy(
+ this.genericsStack, 0,
+ this.genericsStack = new ASTNode[stackLength + GenericsStackIncrement], 0,
+ stackLength);
+ }
+ this.genericsStack[this.genericsPtr] = node;
+
+ stackLength = this.genericsLengthStack.length;
+ if (++this.genericsLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.genericsLengthStack, 0,
+ this.genericsLengthStack = new int[stackLength + GenericsStackIncrement], 0,
+ stackLength);
+ }
+ this.genericsLengthStack[this.genericsLengthPtr] = 1;
+ }
+
+ protected void pushOnGenericsIdentifiersLengthStack(int pos) {
+ int stackLength = this.genericsIdentifiersLengthStack.length;
+ if (++this.genericsIdentifiersLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.genericsIdentifiersLengthStack, 0,
+ this.genericsIdentifiersLengthStack = new int[stackLength + GenericsStackIncrement], 0,
+ stackLength);
+ }
+ this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] = pos;
+ }
+
+ protected void pushOnGenericsLengthStack(int pos) {
+ int stackLength = this.genericsLengthStack.length;
+ if (++this.genericsLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.genericsLengthStack, 0,
+ this.genericsLengthStack = new int[stackLength + GenericsStackIncrement], 0,
+ stackLength);
+ }
+ this.genericsLengthStack[this.genericsLengthPtr] = pos;
+ }
+
+ protected void pushOnIntStack(int pos) {
+
+ int stackLength = this.intStack.length;
+ if (++this.intPtr >= stackLength) {
+ System.arraycopy(
+ this.intStack, 0,
+ this.intStack = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ this.intStack[this.intPtr] = pos;
+ }
+
+ protected void pushOnRealBlockStack(int i) {
+
+ int stackLength = this.realBlockStack.length;
+ if (++this.realBlockPtr >= stackLength) {
+ System.arraycopy(
+ this.realBlockStack, 0,
+ this.realBlockStack = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ this.realBlockStack[this.realBlockPtr] = i;
+ }
+
+ protected void recoverStatements() {
+ class MethodVisitor extends ASTVisitor {
+ public ASTVisitor typeVisitor;
+
+ TypeDeclaration enclosingType; // used only for initializer
+
+ TypeDeclaration[] types = new TypeDeclaration[0];
+ int typePtr = -1;
+
+ public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
+ typePtr = -1;
+ return true;
+ }
+
+ public boolean visit(Initializer initializer, MethodScope scope) {
+ typePtr = -1;
+ return true;
+ }
+
+ public boolean visit(MethodDeclaration methodDeclaration, Scope scope) {
+ typePtr = -1;
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
+ return this.visit(typeDeclaration);
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration, Scope scope) {
+ return this.visit(typeDeclaration);
+ }
+
+ private boolean visit(TypeDeclaration typeDeclaration) {
+ if (this.types.length <= ++this.typePtr) {
+ int length = this.typePtr;
+ System.arraycopy(this.types, 0, this.types = new TypeDeclaration[length * 2 + 1], 0, length);
+ }
+ this.types[this.typePtr] = typeDeclaration;
+ return false;
+ }
+
+ public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
+ this.endVisitMethod(constructorDeclaration, scope);
+ }
+
+ public void endVisit(MethodDeclaration methodDeclaration, Scope scope) {
+ this.endVisitMethod(methodDeclaration, scope);
+ }
+
+ private void endVisitMethod(AbstractMethodDeclaration methodDeclaration, Scope scope) {
+ TypeDeclaration[] foundTypes = null;
+ // int length = 0;
+ // if(this.typePtr > -1) {
+ // length = this.typePtr + 1;
+ // foundTypes = new TypeDeclaration[length];
+ // System.arraycopy(this.types, 0, foundTypes, 0, length);
+ // }
+ ReferenceContext oldContext = Parser.this.referenceContext;
+ Parser.this.recoveryScanner.resetTo(methodDeclaration.bodyStart, methodDeclaration.bodyEnd);
+ Scanner oldScanner = Parser.this.scanner;
+ Parser.this.scanner = Parser.this.recoveryScanner;
+ Parser.this.parseStatements(
+ methodDeclaration,
+ methodDeclaration.bodyStart,
+ methodDeclaration.bodyEnd,
+ foundTypes,
+ compilationUnit);
+ Parser.this.scanner = oldScanner;
+ Parser.this.referenceContext = oldContext;
+
+ // for (int i = 0; i < length; i++) {
+ // foundTypes[i].traverse(typeVisitor, scope);
+ // }
+ }
+
+ public void endVisit(Initializer initializer, MethodScope scope) {
+ TypeDeclaration[] foundTypes = null;
+ int length = 0;
+ if (this.typePtr > -1) {
+ length = this.typePtr + 1;
+ foundTypes = new TypeDeclaration[length];
+ System.arraycopy(this.types, 0, foundTypes, 0, length);
+ }
+ ReferenceContext oldContext = Parser.this.referenceContext;
+ Parser.this.recoveryScanner.resetTo(initializer.bodyStart, initializer.bodyEnd);
+ Scanner oldScanner = Parser.this.scanner;
+ Parser.this.scanner = Parser.this.recoveryScanner;
+ Parser.this.parseStatements(
+ this.enclosingType,
+ initializer.bodyStart,
+ initializer.bodyEnd,
+ foundTypes,
+ compilationUnit);
+ Parser.this.scanner = oldScanner;
+ Parser.this.referenceContext = oldContext;
+
+ for (int i = 0; i < length; i++) {
+ foundTypes[i].traverse(typeVisitor, scope);
+ }
+ }
+ }
+ class TypeVisitor extends ASTVisitor {
+ public MethodVisitor methodVisitor;
+
+ TypeDeclaration[] types = new TypeDeclaration[0];
+ int typePtr = -1;
+
+ public void endVisit(TypeDeclaration typeDeclaration, BlockScope scope) {
+ endVisitType();
+ }
+
+ public void endVisit(TypeDeclaration typeDeclaration, ClassScope scope) {
+ endVisitType();
+ }
+
+ private void endVisitType() {
+ this.typePtr--;
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
+ return this.visit(typeDeclaration);
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
+ return this.visit(typeDeclaration);
+ }
+
+ private boolean visit(TypeDeclaration typeDeclaration) {
+ if (this.types.length <= ++this.typePtr) {
+ int length = this.typePtr;
+ System.arraycopy(this.types, 0, this.types = new TypeDeclaration[length * 2 + 1], 0, length);
+ }
+ this.types[this.typePtr] = typeDeclaration;
+ return true;
+ }
+
+ public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
+ if (constructorDeclaration.isDefaultConstructor())
+ return false;
+
+ constructorDeclaration.traverse(methodVisitor, scope);
+ return false;
+ }
+
+ public boolean visit(Initializer initializer, MethodScope scope) {
+ methodVisitor.enclosingType = this.types[typePtr];
+ initializer.traverse(methodVisitor, scope);
+ return false;
+ }
+
+ public boolean visit(MethodDeclaration methodDeclaration, Scope scope) {
+ methodDeclaration.traverse(methodVisitor, scope);
+ return false;
+ }
+ }
+
+ if (false)
+ {
+ MethodVisitor methodVisitor = new MethodVisitor();
+ TypeVisitor typeVisitor = new TypeVisitor();
+ methodVisitor.typeVisitor = typeVisitor;
+ typeVisitor.methodVisitor = methodVisitor;
+
+ if (this.referenceContext instanceof AbstractMethodDeclaration) {
+ ((AbstractMethodDeclaration) this.referenceContext).traverse(methodVisitor, (Scope) null);
+ } else if (this.referenceContext instanceof CompilationUnitDeclaration) {
+ CompilationUnitDeclaration compilationUnitDeclaration = (CompilationUnitDeclaration) this.referenceContext;
+ if (compilationUnitDeclaration.statements != null)
+ for (int i = 0; i < compilationUnitDeclaration.statements.length; i++) {
+ if (compilationUnitDeclaration.statements[i] instanceof AbstractMethodDeclaration)
+ ((AbstractMethodDeclaration) compilationUnitDeclaration.statements[i]).traverse(methodVisitor, (Scope) null);
+ }
+ } else if (this.referenceContext instanceof TypeDeclaration) {
+ TypeDeclaration typeContext = (TypeDeclaration) this.referenceContext;
+
+ int length = typeContext.fields.length;
+ for (int i = 0; i < length; i++) {
+ final FieldDeclaration fieldDeclaration = typeContext.fields[i];
+ switch (fieldDeclaration.getKind()) {
+ case AbstractVariableDeclaration.INITIALIZER:
+ methodVisitor.enclosingType = typeContext;
+ ((Initializer) fieldDeclaration).traverse(methodVisitor, (MethodScope) null);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ CompilationUnitDeclaration compilationUnitDeclaration = (CompilationUnitDeclaration) this.referenceContext;
+
+ ReferenceContext oldContext = Parser.this.referenceContext;
+ int start = compilationUnitDeclaration.sourceStart;
+ int end = compilationUnitDeclaration.sourceEnd;
+ Parser.this.recoveryScanner.resetTo(start, end);
+ Scanner oldScanner = Parser.this.scanner;
+ Parser.this.scanner = Parser.this.recoveryScanner;
+ /* unit creation */
+ this.referenceContext =
+ this.compilationUnit = compilationUnitDeclaration =
+ new CompilationUnitDeclaration(
+ this.problemReporter,
+ compilationUnitDeclaration.compilationResult,
+ end);
+
+ Parser.this.parseStatements(
+ compilationUnitDeclaration,
+ start,
+ end,
+ null,
+ compilationUnit);
+ Parser.this.scanner = oldScanner;
+ Parser.this.referenceContext = oldContext;
+ }
+
+ }
+
+ public void recoveryExitFromVariable() {
+ if (this.currentElement != null && this.currentElement.parent != null) {
+ if (this.currentElement instanceof RecoveredLocalVariable) {
+
+ int end = ((RecoveredLocalVariable) this.currentElement).localDeclaration.sourceEnd;
+ this.currentElement.updateSourceEndIfNecessary(end);
+ this.currentElement = this.currentElement.parent;
+ } else if (this.currentElement instanceof RecoveredField
+ && !(this.currentElement instanceof RecoveredInitializer)) {
+
+ int end = ((RecoveredField) this.currentElement).fieldDeclaration.sourceEnd;
+ this.currentElement.updateSourceEndIfNecessary(end);
+ this.currentElement = this.currentElement.parent;
+ }
+ }
+ }
+
+ /* Token check performed on every token shift once having entered
+ * recovery mode.
+ */
+ public void recoveryTokenCheck() {
+ switch (this.currentToken) {
+ case TokenNameLBRACE:
+ RecoveredElement newElement = null;
+ if (!this.ignoreNextOpeningBrace) {
+ newElement = this.currentElement.updateOnOpeningBrace(this.scanner.startPosition - 1, this.scanner.currentPosition - 1);
+ }
+ this.lastCheckPoint = this.scanner.currentPosition;
+ if (newElement != null) { // null means nothing happened
+ this.restartRecovery = true; // opening brace detected
+ this.currentElement = newElement;
+ }
+ break;
+
+ case TokenNameRBRACE:
+ this.rBraceStart = this.scanner.startPosition - 1;
+ this.rBraceEnd = this.scanner.currentPosition - 1;
+ this.endPosition = this.flushCommentsDefinedPriorTo(this.rBraceEnd);
+ newElement =
+ this.currentElement.updateOnClosingBrace(this.scanner.startPosition, this.rBraceEnd);
+ this.lastCheckPoint = this.scanner.currentPosition;
+ if (newElement != this.currentElement) {
+ this.currentElement = newElement;
+ // if (newElement instanceof RecoveredField && this.dietInt <= 0) {
+ // if (((RecoveredField)newElement).fieldDeclaration.type == null) { // enum constant
+ // this.isInsideEnumConstantPart = true; // restore status
+ // }
+ // }
+ }
+ break;
+ case TokenNameSEMICOLON:
+ this.endStatementPosition = this.scanner.currentPosition - 1;
+ this.endPosition = this.scanner.startPosition - 1;
+ this.lastCheckPoint = this.scanner.currentPosition;
+ // RecoveredType currentType = this.currentRecoveryType();
+ // if(currentType != null) {
+ // currentType.insideEnumConstantPart = false;
+ // }
+ // fall through
+ default: {
+ if (this.rBraceEnd > this.rBraceSuccessorStart && this.scanner.currentPosition != this.scanner.startPosition) {
+ this.rBraceSuccessorStart = this.scanner.startPosition;
+ }
+ break;
+ }
+ }
+ this.ignoreNextOpeningBrace = false;
+ }
+
+ protected boolean shouldInsertSemicolon(int prevpos, int prevtoken) {
+ Integer position = new Integer(prevpos);
+ if (this.errorAction.contains(position)) {
+ // should not insert a semi-colon at a location that has already be tried
+ return false;
+ }
+ this.errorAction.add(position);
+ return this.currentToken == TokenNameRBRACE
+ || scanner.getLineNumber(scanner.currentPosition) > scanner.getLineNumber(prevpos)
+ || this.currentToken == TokenNameEOF;
+ }
+
+ // A P I
+ protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) {
+ if (this.referenceContext instanceof MethodDeclaration) {
+ MethodDeclaration methodDeclaration = (MethodDeclaration) this.referenceContext;
+ if (methodDeclaration.errorInSignature) {
+ return;
+ }
+ }
+ this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
+ this.scanner.recordLineSeparator = false;
+
+ int start = this.scanner.initialPosition;
+ int end = this.scanner.eofPosition == Integer.MAX_VALUE ? this.scanner.eofPosition : this.scanner.eofPosition - 1;
+ if (isDietParse) {
+ ProgramElement[] statements = this.compilationUnit.statements;
+ // TypeDeclaration[] types = this.compilationUnit.types;
+ int[][] intervalToSkip = org.eclipse.wst.jsdt.internal.compiler.parser.diagnose.RangeUtil.computeDietRange(statements);
+ // int[][] intervalToSkip = org.eclipse.wst.jsdt.internal.compiler.parser.diagnose.RangeUtil.computeDietRange(types);
+ DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, intervalToSkip[0], intervalToSkip[1], intervalToSkip[2], this.options);
+ diagnoseParser.diagnoseParse(false);
+
+ reportSyntaxErrorsForSkippedMethod(statements);
+ // reportSyntaxErrorsForSkippedMethod(types);
+ this.scanner.resetTo(start, end);
+ } else {
+ DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, this.options);
+ diagnoseParser.diagnoseParse(this.options.performStatementsRecovery);
+ }
+ }
+
+ private void reportSyntaxErrorsForSkippedMethod(ProgramElement[] statements) {
+ if (statements != null) {
+ for (int i = 0; i < statements.length; i++) {
+ // TypeDeclaration[] memberTypes = types[i].memberTypes;
+ // if(memberTypes != null) {
+ // reportSyntaxErrorsForSkippedMethod(memberTypes);
+ // }
+ //
+ // AbstractMethodDeclaration[] methods = types[i].methods;
+ // if(methods != null) {
+ // for (int j = 0; j < methods.length; j++) {
+ if (statements[i] instanceof AbstractMethodDeclaration)
+ {
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) statements[i];
+ if (method.errorInSignature) {
+ DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameDIVIDE, method.declarationSourceStart, method.declarationSourceEnd, this.options);
+ diagnoseParser.diagnoseParse(this.options.performStatementsRecovery);
+ }
+ // }
+ }
+ else if (statements[i] instanceof FieldDeclaration)
+ {
+ // FieldDeclaration field =(FieldDeclaration) statements[i] ;
+ // if (fields != null) {
+ // int length = fields.length;
+ // for (int j = 0; j < length; j++) {
+ // if (fields[j] instanceof Initializer) {
+ // Initializer initializer = (Initializer)fields[j];
+ // if(initializer.errorInSignature){
+ // DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameRIGHT_SHIFT, initializer.declarationSourceStart, initializer.declarationSourceEnd, this.options);
+ // diagnoseParser.diagnoseParse(this.options.performStatementsRecovery);
+ // }
+ // }
+ // }
+ }
+ }
+ }
+ }
+
+ protected void resetModifiers() {
+ this.modifiers = ClassFileConstants.AccDefault;
+ this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
+ this.scanner.commentPtr = -1;
+ }
+
+ /*
+ * Reset context so as to resume to regular parse loop
+ */
+ protected void resetStacks() {
+
+ this.astPtr = -1;
+ this.astLengthPtr = -1;
+ this.expressionPtr = -1;
+ this.expressionLengthPtr = -1;
+ this.identifierPtr = -1;
+ this.identifierLengthPtr = -1;
+ this.intPtr = -1;
+ this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse
+ this.variablesCounter[this.nestedType] = 0;
+ this.dimensions = 0;
+ this.realBlockStack[this.realBlockPtr = 0] = 0;
+ this.recoveredStaticInitializerStart = 0;
+ this.listLength = 0;
+ this.listTypeParameterLength = 0;
+
+ this.genericsIdentifiersLengthPtr = -1;
+ this.genericsLengthPtr = -1;
+ this.genericsPtr = -1;
+ this.errorAction = new HashSet();
+ }
+
+ /*
+ * 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.
+ */
+ protected boolean resumeAfterRecovery() {
+ if (!this.methodRecoveryActivated && !this.statementRecoveryActivated) {
+
+ // reset internal stacks
+ this.resetStacks();
+ this.resetModifiers();
+
+ /* attempt to move checkpoint location */
+ if (!this.moveRecoveryCheckpoint()) {
+ return false;
+ }
+
+ // only look for headers
+ if (this.referenceContext instanceof CompilationUnitDeclaration) {
+ if (DO_DIET_PARSE)
+ {
+ goForHeaders();
+ this.diet = true; // passed this point, will not consider method bodies
+ }
+ else
+ goForProgramElements();
+ return true;
+ }
+
+ // does not know how to restart
+ return false;
+ } else if (!this.statementRecoveryActivated || !DO_DIET_PARSE) {
+
+ // reset internal stacks
+ this.resetStacks();
+ this.resetModifiers();
+
+ /* attempt to move checkpoint location */
+ if (!this.moveRecoveryCheckpoint()) {
+ return false;
+ }
+
+ // only look for headers
+ if (DO_DIET_PARSE)
+ goForHeaders();
+ else
+ goForProgramElements();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected boolean resumeOnSyntaxError() {
+ this.checkExternalizeStrings = false;
+ this.scanner.checkNonExternalizedStringLiterals = false;
+ /* request recovery initialization */
+ if (this.currentElement == null) {
+ // Reset javadoc before restart parsing after recovery
+ this.javadoc = null;
+
+ // do not investigate deeper in statement recovery
+ if (this.statementRecoveryActivated)
+ return false;
+
+ // build some recovered elements
+ this.currentElement = buildInitialRecoveryState();
+ }
+ /* do not investigate deeper in recovery when no recovered element */
+ if (this.currentElement == null)
+ return false;
+
+ /* manual forced recovery restart - after headers */
+ if (this.restartRecovery) {
+ this.restartRecovery = false;
+ }
+ /* update recovery state with current error state of the parser */
+ this.updateRecoveryState();
+
+ /* attempt to reset state in order to resume to parse loop */
+ return this.resumeAfterRecovery();
+ }
+
+ public void setMethodsFullRecovery(boolean enabled) {
+ this.options.performMethodsFullRecovery = enabled;
+ }
+
+ public void setStatementsRecovery(boolean enabled) {
+ if (enabled)
+ this.options.performMethodsFullRecovery = true;
+ this.options.performStatementsRecovery = enabled;
+ }
+
+ public String toString() {
+
+ String s = "lastCheckpoint : int = " + String.valueOf(this.lastCheckPoint) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ s = s + "identifierStack : char[" + (this.identifierPtr + 1) + "][] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+ for (int i = 0; i <= this.identifierPtr; i++) {
+ s = s + "\"" + String.valueOf(this.identifierStack[i]) + "\","; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "identifierLengthStack : int[" + (this.identifierLengthPtr + 1) + "] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+ for (int i = 0; i <= this.identifierLengthPtr; i++) {
+ s = s + this.identifierLengthStack[i] + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "astLengthStack : int[" + (this.astLengthPtr + 1) + "] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+ for (int i = 0; i <= this.astLengthPtr; i++) {
+ s = s + this.astLengthStack[i] + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+ s = s + "astPtr : int = " + String.valueOf(this.astPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ s = s + "intStack : int[" + (this.intPtr + 1) + "] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+ for (int i = 0; i <= this.intPtr; i++) {
+ s = s + this.intStack[i] + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+ s = s + "intPtr : int = " + String.valueOf(this.intPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ s = s + "expressionLengthStack : int[" + (this.expressionLengthPtr + 1) + "] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+ for (int i = 0; i <= this.expressionLengthPtr; i++) {
+ s = s + this.expressionLengthStack[i] + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "expressionPtr : int = " + String.valueOf(this.expressionPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ s = s + "genericsIdentifiersLengthStack : int[" + (this.genericsIdentifiersLengthPtr + 1) + "] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+ for (int i = 0; i <= this.genericsIdentifiersLengthPtr; i++) {
+ s = s + this.genericsIdentifiersLengthStack[i] + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "genericsLengthStack : int[" + (this.genericsLengthPtr + 1) + "] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+ for (int i = 0; i <= this.genericsLengthPtr; i++) {
+ s = s + this.genericsLengthStack[i] + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "genericsPtr : int = " + String.valueOf(this.genericsPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ s = s + "\n\n\n----------------Scanner--------------\n" + this.scanner.toString(); //$NON-NLS-1$
+ return s;
+
+ }
+
+ /*
+ * Update recovery state based on current parser/scanner state
+ */
+ protected void updateRecoveryState() {
+
+ /* expose parser state to recovery state */
+ this.currentElement.updateFromParserState();
+
+ /* check and update recovered state based on current token,
+ this action is also performed when shifting token after recovery
+ got activated once.
+ */
+ this.recoveryTokenCheck();
+ }
+
+ protected void updateSourceDeclarationParts(int variableDeclaratorsCounter) {
+ //fields is a definition of fields that are grouped together like in
+ //public int[] a, b[], c
+ //which results into 3 fields.
+
+ FieldDeclaration field;
+ int endTypeDeclarationPosition =
+ -1 + this.astStack[this.astPtr - variableDeclaratorsCounter + 1].sourceStart;
+ for (int i = 0; i < variableDeclaratorsCounter - 1; i++) {
+ //last one is special(see below)
+ field = (FieldDeclaration) this.astStack[this.astPtr - i - 1];
+ field.endPart1Position = endTypeDeclarationPosition;
+ field.endPart2Position = -1 + this.astStack[this.astPtr - i].sourceStart;
+ }
+ //last one
+ (field = (FieldDeclaration) this.astStack[this.astPtr]).endPart1Position =
+ endTypeDeclarationPosition;
+ field.endPart2Position = field.declarationSourceEnd;
+
+ }
+
+ protected void updateSourcePosition(Expression exp) {
+ //update the source Position of the expression
+
+ //this.intStack : int int
+ //-->
+ //this.intStack :
+
+ exp.sourceEnd = this.intStack[this.intPtr--];
+ exp.sourceStart = this.intStack[this.intPtr--];
+ }
+
+ public void inferTypes(CompilationUnitDeclaration parsedUnit, CompilerOptions compileOptions) {
+ if (parsedUnit.typesHaveBeenInferred)
+ return;
+ if (compileOptions == null)
+ compileOptions = this.options;
+
+ if (this.inferenceEngines == null)
+ initializeInferenceEngine(parsedUnit);
+ // InferEngine inferEngine=compileOptions.inferOptions.createEngine();
+ for (int i = 0; i < this.inferenceEngines.length; i++)
+ {
+ IInferEngine engine = this.inferenceEngines[i];
+ PerformanceStats stats = PerformanceStats.getStats(PERFORMANCE__INFER_TYPES, engine);
+ try {
+ stats.startRun(new String(parsedUnit.getFileName()));
+
+ engine.initialize();
+ if (engine instanceof IInferEngineExtension)
+ ((IInferEngineExtension) engine).setCompilationUnit(parsedUnit, this.scanner.getSource());
+ else
+ engine.setCompilationUnit(parsedUnit);
+
+ engine.doInfer();
+ } catch (RuntimeException e) {
+ org.eclipse.wst.jsdt.internal.core.util.Util.log(e, "error during type inferencing"); //$NON-NLS-1$
+ } finally {
+ stats.endRun();
+ if (REPORT_PERFORMANCE__INFER_TYPES && stats.isFailure()) {
+ IStatus status = new Status(IStatus.WARNING, JavaScriptCore.PLUGIN_ID, IStatus.OK, "Inference Engine took too long: " + engine, null); //$NON-NLS-1$
+ Platform.getLog(Platform.getBundle(JavaScriptCore.PLUGIN_ID)).log(status);
+ }
+ }
+ }
+ parsedUnit.typesHaveBeenInferred = true;
+ }
+
+}