1 package net.sourceforge.phpdt.internal.compiler.parser;
4 import net.sourceforge.phpdt.core.IJavaModelMarker;
5 import net.sourceforge.phpdt.core.compiler.IProblem;
6 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
7 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
8 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
9 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
10 import net.sourceforge.phpdt.internal.core.BasicCompilationUnit;
11 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
12 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
13 import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
14 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
15 import net.sourceforge.phpeclipse.internal.compiler.ast.Initializer;
16 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
17 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
19 import org.eclipse.core.resources.IMarker;
20 import org.eclipse.core.resources.IResource;
21 import org.eclipse.core.runtime.CoreException;
27 public class UnitParser extends Parser {
29 public UnitParser(ProblemReporter problemReporter) { //, boolean optimizeStringLiterals, boolean assertMode) {
30 super(problemReporter);
31 nestedMethod = new int[30];
33 // this.optimizeStringLiterals = optimizeStringLiterals;
34 // this.assertMode = assertMode;
35 // this.initializeScanner();
36 astLengthStack = new int[50];
37 // expressionLengthStack = new int[30];
38 // intStack = new int[50];
39 // identifierStack = new char[30][];
40 // identifierLengthStack = new int[30];
41 // nestedMethod = new int[30];
42 // realBlockStack = new int[30];
43 // identifierPositionStack = new long[30];
44 // variablesCounter = new int[30];
47 public void goForConstructorBody() {
48 //tells the scanner to go for compilation unit parsing
50 firstToken = TokenNameEQUAL_EQUAL;
51 scanner.recordLineSeparator = false;
53 public void goForExpression() {
54 //tells the scanner to go for an expression parsing
56 firstToken = TokenNameREMAINDER;
57 scanner.recordLineSeparator = false;
59 public void goForCompilationUnit() {
60 //tells the scanner to go for compilation unit parsing
62 firstToken = TokenNamePLUS_PLUS;
64 scanner.foundTaskCount = 0;
65 scanner.recordLineSeparator = true;
66 // scanner.currentLine= null;
68 public void goForInitializer() {
69 //tells the scanner to go for initializer parsing
71 firstToken = TokenNameRIGHT_SHIFT;
72 scanner.recordLineSeparator = false;
74 public void goForMethodBody() {
75 //tells the scanner to go for method body parsing
77 firstToken = TokenNameMINUS_MINUS;
78 scanner.recordLineSeparator = false;
80 public void initialize(boolean phpMode) {
81 super.initialize(phpMode);
82 //positionning the parser for a new compilation unit
83 //avoiding stack reallocation and all that....
86 // expressionPtr = -1;
87 // expressionLengthPtr = -1;
88 // identifierPtr = -1;
89 // identifierLengthPtr = -1;
91 // nestedMethod[nestedType = 0] = 0; // need to reset for further reuse
92 // variablesCounter[nestedType] = 0;
95 // endStatementPosition = 0;
97 //remove objects from stack too, while the same parser/compiler couple is
98 //re-used between two compilations ....
100 // int astLength = astStack.length;
101 // if (noAstNodes.length < astLength){
102 // noAstNodes = new ASTNode[astLength];
103 // //System.out.println("Resized AST stacks : "+ astLength);
106 // System.arraycopy(noAstNodes, 0, astStack, 0, astLength);
108 // int expressionLength = expressionStack.length;
109 // if (noExpressions.length < expressionLength){
110 // noExpressions = new Expression[expressionLength];
111 // //System.out.println("Resized EXPR stacks : "+ expressionLength);
113 // System.arraycopy(noExpressions, 0, expressionStack, 0, expressionLength);
115 // reset scanner state
116 scanner.commentPtr = -1;
117 scanner.foundTaskCount = 0;
118 scanner.eofPosition = Integer.MAX_VALUE;
123 // lastCheckPoint = -1;
124 // currentElement = null;
125 // restartRecovery = false;
126 // hasReportedError = false;
127 // recoveredStaticInitializerStart = 0;
128 // lastIgnoredToken = -1;
129 // lastErrorEndPosition = -1;
135 public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
136 // parses a compilation unit and manages error handling (even bugs....)
138 CompilationUnitDeclaration unit;
140 /* automaton initialization */
142 goForCompilationUnit();
144 /* scanner initialization */
145 scanner.setSource(sourceUnit, sourceUnit.getContents());
149 compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
150 // TODO TypeDeclaration test
151 // TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
152 // typeDecl.sourceStart = 0;
153 // typeDecl.sourceEnd = 10;
154 // typeDecl.name = new char[]{'t', 'e','s','t'};
155 // this.compilationUnit.types = new ArrayList();
156 // this.compilationUnit.types.add(typeDecl);
159 // // TODO jsurfer start
160 // if (sourceUnit instanceof BasicCompilationUnit) {
161 // storeProblemsFor(((BasicCompilationUnit)sourceUnit).getResource(), compilationResult.getAllProblems());
166 unit = compilationUnit;
167 compilationUnit = null; // reset parser
172 * Creates a marker from each problem and adds it to the resource.
173 * The marker is as follows:
174 * - its type is T_PROBLEM
175 * - its plugin ID is the JavaBuilder's plugin ID
176 * - its message is the problem's message
177 * - its priority reflects the severity of the problem
178 * - its range is the problem's range
179 * - it has an extra attribute "ID" which holds the problem's id
181 protected void storeProblemsFor(IResource resource, IProblem[] problems) throws CoreException {
182 if (resource == null || problems == null || problems.length == 0)
185 for (int i = 0, l = problems.length; i < l; i++) {
186 IProblem problem = problems[i];
187 int id = problem.getID();
188 if (id != IProblem.Task) {
189 IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
190 marker.setAttributes(
198 IJavaModelMarker.ARGUMENTS },
200 problem.getMessage(),
201 new Integer(problem.isError() ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING),
203 new Integer(problem.getSourceStart()),
204 new Integer(problem.getSourceEnd() + 1),
205 new Integer(problem.getSourceLineNumber()),
206 net.sourceforge.phpdt.internal.core.util.Util.getProblemArgumentsForMarker(problem.getArguments())});
215 public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
216 //only parse the method body of cd
217 //fill out its statements
219 //convert bugs into parse error
222 goForConstructorBody();
223 nestedMethod[nestedType]++;
225 referenceContext = cd;
226 compilationUnit = unit;
228 scanner.resetTo(cd.sourceEnd + 1, cd.declarationSourceEnd);
231 } catch (AbortCompilation ex) {
232 lastAct = ERROR_ACTION;
235 nestedMethod[nestedType]--;
238 if (lastAct == ERROR_ACTION) {
244 // cd.explicitDeclarations = realBlockStack[realBlockPtr--];
246 // if ((length = astLengthStack[astLengthPtr--]) != 0) {
248 // if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
249 // //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
254 // cd.statements = new Statement[length - 1],
257 // cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
258 // } else { //need to add explicitly the super();
262 // cd.statements = new Statement[length],
265 // cd.constructorCall = SuperReference.implicitSuperConstructorCall();
268 // cd.constructorCall = SuperReference.implicitSuperConstructorCall();
271 // if (cd.constructorCall.sourceEnd == 0) {
272 // cd.constructorCall.sourceEnd = cd.sourceEnd;
273 // cd.constructorCall.sourceStart = cd.sourceStart;
278 public void parse(FieldDeclaration field, TypeDeclaration type, CompilationUnitDeclaration unit, char[] initializationSource) {
279 //only parse the initializationSource of the given field
281 //convert bugs into parse error
285 nestedMethod[nestedType]++;
287 referenceContext = type;
288 compilationUnit = unit;
290 scanner.setSource(initializationSource);
291 scanner.resetTo(0, initializationSource.length - 1);
294 } catch (AbortCompilation ex) {
295 lastAct = ERROR_ACTION;
297 nestedMethod[nestedType]--;
300 // if (lastAct == ERROR_ACTION) {
304 // field.initialization = expressionStack[expressionPtr];
306 // // mark field with local type if one was found during parsing
307 // if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
308 // field.bits |= ASTNode.HasLocalTypeMASK;
313 public void parse(Initializer ini, TypeDeclaration type, CompilationUnitDeclaration unit) {
314 //only parse the method body of md
315 //fill out method statements
317 //convert bugs into parse error
321 nestedMethod[nestedType]++;
323 referenceContext = type;
324 compilationUnit = unit;
326 scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the beginning {
329 } catch (AbortCompilation ex) {
330 lastAct = ERROR_ACTION;
332 nestedMethod[nestedType]--;
335 // if (lastAct == ERROR_ACTION) {
339 // ini.block = ((Initializer) astStack[astPtr]).block;
341 // // mark initializer with local type if one was found during parsing
342 // if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
343 // ini.bits |= ASTNode.HasLocalTypeMASK;
348 public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
349 // TODO jsurfer - make the parse process work on methods ?
352 // //only parse the method body of md
353 // //fill out method statements
355 // //convert bugs into parse error
357 // if (md.isAbstract())
359 // // if (md.isNative())
361 // // if ((md.modifiers & AccSemicolonBody) != 0)
364 // initialize(false);
365 // goForMethodBody();
366 // nestedMethod[nestedType]++;
368 // referenceContext = md;
369 // compilationUnit = unit;
371 // scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd);
373 // // reset the scanner to parser from { down to }
376 // } catch (AbortCompilation ex) {
377 // lastAct = ERROR_ACTION;
379 // nestedMethod[nestedType]--;
382 // // if (lastAct == ERROR_ACTION) {
386 // // //refill statements
387 // // md.explicitDeclarations = realBlockStack[realBlockPtr--];
389 // // if ((length = astLengthStack[astLengthPtr--]) != 0)
390 // // System.arraycopy(
392 // // (astPtr -= length) + 1,
393 // // md.statements = new Statement[length],
400 public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
401 // parses a compilation unit and manages error handling (even bugs....)
403 CompilationUnitDeclaration unit;
405 /* automaton initialization */
407 goForCompilationUnit();
409 /* scanner initialization */
410 scanner.setSource(sourceUnit, sourceUnit.getContents());
411 scanner.resetTo(start, end);
414 compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
418 } catch (SyntaxError syntaxError) {
421 unit = compilationUnit;
422 compilationUnit = null; // reset parser
427 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
428 return dietParse(sourceUnit, compilationResult, false);
430 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
432 CompilationUnitDeclaration parsedUnit;
436 parsedUnit = parse(sourceUnit, compilationResult, phpMode);
443 public void getMethodBodies(CompilationUnitDeclaration unit) {
444 //fill the methods bodies in order for the code to be generated
446 if (unit == null) return;
448 if (unit.ignoreMethodBodies) {
449 unit.ignoreFurtherInvestigation = true;
451 // if initial diet parse did not work, no need to dig into method bodies.
454 if ((unit.bits & ASTNode.HasAllMethodBodies) != 0)
455 return; //work already done ...
457 //real parse of the method....
458 char[] contents = unit.compilationResult.compilationUnit.getContents();
459 this.scanner.setSource(contents);
461 // save existing values to restore them at the end of the parsing process
462 // see bug 47079 for more details
463 int[] oldLineEnds = this.scanner.lineEnds;
464 int oldLinePtr = this.scanner.linePtr;
466 final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
467 this.scanner.lineEnds = lineSeparatorPositions;
468 this.scanner.linePtr = lineSeparatorPositions.length - 1;
470 // if (this.javadocParser != null && this.javadocParser.checkDocComment) {
471 // this.javadocParser.scanner.setSource(contents);
473 if (unit.types != null) {
474 for (int i = unit.types.size(); --i >= 0;)
475 ((TypeDeclaration)unit.types.get(i)).parseMethod(this, unit);
478 // tag unit has having read bodies
479 unit.bits |= ASTNode.HasAllMethodBodies;
481 // this is done to prevent any side effects on the compilation unit result
482 // line separator positions array.
483 this.scanner.lineEnds = oldLineEnds;
484 this.scanner.linePtr = oldLinePtr;