Changes for 3.x
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / UnitParser.java
1 package net.sourceforge.phpdt.internal.compiler.parser;
2
3 import net.sourceforge.phpdt.core.IJavaModelMarker;
4 import net.sourceforge.phpdt.core.compiler.IProblem;
5 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
6 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
7 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
8 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
9 import net.sourceforge.phpdt.internal.compiler.util.Util;
10 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
11 import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
12 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
13 import net.sourceforge.phpeclipse.internal.compiler.ast.Initializer;
14 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
15 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
16
17 import org.eclipse.core.resources.IMarker;
18 import org.eclipse.core.resources.IResource;
19 import org.eclipse.core.runtime.CoreException;
20
21 /**
22  * @author jsurfer
23  *
24  * 
25  */
26 public class UnitParser extends Parser {
27
28   public UnitParser(ProblemReporter problemReporter) { //, boolean optimizeStringLiterals, boolean assertMode) {
29     super();
30     nestedMethod = new int[30];
31     this.problemReporter = problemReporter;
32     //          this.optimizeStringLiterals = optimizeStringLiterals;
33     //          this.assertMode = assertMode;
34     //          this.initializeScanner();
35     astLengthStack = new int[50];
36     //          expressionLengthStack = new int[30];
37     //          intStack = new int[50];
38     //          identifierStack = new char[30][];
39     //          identifierLengthStack = new int[30];
40     //          nestedMethod = new int[30];
41     //          realBlockStack = new int[30];
42     //          identifierPositionStack = new long[30];
43     //          variablesCounter = new int[30];
44   }
45
46   public void goForConstructorBody() {
47     //tells the scanner to go for compilation unit parsing
48
49     firstToken = TokenNameEQUAL_EQUAL;
50     scanner.recordLineSeparator = false;
51   }
52   public void goForExpression() {
53     //tells the scanner to go for an expression parsing
54
55     firstToken = TokenNameREMAINDER;
56     scanner.recordLineSeparator = false;
57   }
58   public void goForCompilationUnit() {
59     //tells the scanner to go for compilation unit parsing
60
61     firstToken = TokenNamePLUS_PLUS;
62     scanner.linePtr = -1;
63     scanner.foundTaskCount = 0;
64     scanner.recordLineSeparator = true;
65     //          scanner.currentLine= null;
66   }
67   public void goForInitializer() {
68     //tells the scanner to go for initializer parsing
69
70     firstToken = TokenNameRIGHT_SHIFT;
71     scanner.recordLineSeparator = false;
72   }
73   public void goForMethodBody() {
74     //tells the scanner to go for method body parsing
75
76     firstToken = TokenNameMINUS_MINUS;
77     scanner.recordLineSeparator = false;
78   }
79   public void initialize(boolean phpMode) {
80     super.initialize(phpMode);
81     //positionning the parser for a new compilation unit
82     //avoiding stack reallocation and all that....
83     //          astPtr = -1;
84     //          astLengthPtr = -1;
85     //          expressionPtr = -1;
86     //          expressionLengthPtr = -1;
87     //          identifierPtr = -1;     
88     //          identifierLengthPtr     = -1;
89     //          intPtr = -1;
90     //          nestedMethod[nestedType = 0] = 0; // need to reset for further reuse
91     //          variablesCounter[nestedType] = 0;
92     //          dimensions = 0 ;
93     //          realBlockPtr = -1;
94     //          endStatementPosition = 0;
95
96     //remove objects from stack too, while the same parser/compiler couple is
97     //re-used between two compilations ....
98
99     //          int astLength = astStack.length;
100     //          if (noAstNodes.length < astLength){
101     //                  noAstNodes = new AstNode[astLength];
102     //                  //System.out.println("Resized AST stacks : "+ astLength);
103     //          
104     //          }
105     //          System.arraycopy(noAstNodes, 0, astStack, 0, astLength);
106     //
107     //          int expressionLength = expressionStack.length;
108     //          if (noExpressions.length < expressionLength){
109     //                  noExpressions = new Expression[expressionLength];
110     //                  //System.out.println("Resized EXPR stacks : "+ expressionLength);
111     //          }
112     //          System.arraycopy(noExpressions, 0, expressionStack, 0, expressionLength);
113
114     // reset scanner state
115     scanner.commentPtr = -1;
116     scanner.foundTaskCount = 0;
117     scanner.eofPosition = Integer.MAX_VALUE;
118
119     //          resetModifiers();
120     //
121     //          // recovery
122     //          lastCheckPoint = -1;
123     //          currentElement = null;
124     //          restartRecovery = false;
125     //          hasReportedError = false;
126     //          recoveredStaticInitializerStart = 0;
127     //          lastIgnoredToken = -1;
128     //          lastErrorEndPosition = -1;
129     //          listLength = 0;
130   }
131
132   // A P I
133
134   public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
135     // parses a compilation unit and manages error handling (even bugs....)
136
137     CompilationUnitDeclaration unit;
138     try {
139       /* automaton initialization */
140       initialize(phpMode);
141       goForCompilationUnit();
142
143       /* scanner initialization */
144       scanner.setSource(sourceUnit.getContents());
145
146       /* unit creation */
147       referenceContext =
148         compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
149       // TODO TypeDeclaration test
150       //      TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
151       //      typeDecl.sourceStart = 0;
152       //      typeDecl.sourceEnd = 10;
153       //      typeDecl.name = new char[]{'t', 'e','s','t'};
154       //      this.compilationUnit.types = new ArrayList();
155       //      this.compilationUnit.types.add(typeDecl);
156       /* run automaton */
157       super.parse();
158 //      //              TODO jsurfer start 
159 //      if (sourceUnit instanceof BasicCompilationUnit) {
160 //        storeProblemsFor(((BasicCompilationUnit)sourceUnit).getResource(), compilationResult.getAllProblems());
161 //      }
162 //      // jsurfer end
163     
164     } finally {
165       unit = compilationUnit;
166       compilationUnit = null; // reset parser
167     }
168     return unit;
169   }
170   /**
171                  * Creates a marker from each problem and adds it to the resource.
172                  * The marker is as follows:
173                  *   - its type is T_PROBLEM
174                  *   - its plugin ID is the JavaBuilder's plugin ID
175                  *       - its message is the problem's message
176                  *       - its priority reflects the severity of the problem
177                  *       - its range is the problem's range
178                  *       - it has an extra attribute "ID" which holds the problem's id
179                  */
180   protected void storeProblemsFor(IResource resource, IProblem[] problems) throws CoreException {
181     if (resource == null || problems == null || problems.length == 0)
182       return;
183
184     for (int i = 0, l = problems.length; i < l; i++) {
185       IProblem problem = problems[i];
186       int id = problem.getID();
187       if (id != IProblem.Task) {
188         IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
189         marker.setAttributes(
190           new String[] {
191             IMarker.MESSAGE,
192             IMarker.SEVERITY,
193             IJavaModelMarker.ID,
194             IMarker.CHAR_START,
195             IMarker.CHAR_END,
196             IMarker.LINE_NUMBER,
197             IJavaModelMarker.ARGUMENTS },
198           new Object[] {
199             problem.getMessage(),
200             new Integer(problem.isError() ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING),
201             new Integer(id),
202             new Integer(problem.getSourceStart()),
203             new Integer(problem.getSourceEnd() + 1),
204             new Integer(problem.getSourceLineNumber()),
205             net.sourceforge.phpdt.internal.core.Util.getProblemArgumentsForMarker(problem.getArguments())});
206       }
207
208     }
209   }
210   protected CompilationUnitDeclaration endParse(int act) {
211
212     this.lastAct = act;
213
214     if (currentElement != null) {
215       currentElement.topElement().updateParseTree();
216       if (VERBOSE_RECOVERY) {
217         System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
218         System.out.println("--------------------------"); //$NON-NLS-1$
219         System.out.println(compilationUnit);
220         System.out.println("----------------------------------"); //$NON-NLS-1$
221       }
222     } else {
223       if (diet & VERBOSE_RECOVERY) {
224         System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
225         System.out.println("--------------------------"); //$NON-NLS-1$
226         System.out.println(compilationUnit);
227         System.out.println("----------------------------------"); //$NON-NLS-1$
228       }
229     }
230     if (scanner.recordLineSeparator) {
231       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
232     }
233     if (scanner.taskTags != null) {
234       for (int i = 0; i < scanner.foundTaskCount; i++) {
235         problemReporter().task(
236           new String(scanner.foundTaskTags[i]),
237           new String(scanner.foundTaskMessages[i]),
238           scanner.foundTaskPriorities[i] == null ? null : new String(scanner.foundTaskPriorities[i]),
239           scanner.foundTaskPositions[i][0],
240           scanner.foundTaskPositions[i][1]);
241       }
242     }
243     return compilationUnit;
244   }
245
246   // A P I
247
248   public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
249     //only parse the method body of cd
250     //fill out its statements
251
252     //convert bugs into parse error
253
254     initialize(false);
255     goForConstructorBody();
256     nestedMethod[nestedType]++;
257
258     referenceContext = cd;
259     compilationUnit = unit;
260
261     scanner.resetTo(cd.sourceEnd + 1, cd.declarationSourceEnd);
262     try {
263       parse();
264     } catch (AbortCompilation ex) {
265       lastAct = ERROR_ACTION;
266     
267     } finally {
268       nestedMethod[nestedType]--;
269     }
270
271     if (lastAct == ERROR_ACTION) {
272       initialize(false);
273       return;
274     }
275
276     //statements
277     //  cd.explicitDeclarations = realBlockStack[realBlockPtr--];
278     //  int length;
279     //  if ((length = astLengthStack[astLengthPtr--]) != 0) {
280     //          astPtr -= length;
281     //          if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
282     //                  //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
283     //                  {
284     //                  System.arraycopy(
285     //                          astStack, 
286     //                          astPtr + 2, 
287     //                          cd.statements = new Statement[length - 1], 
288     //                          0, 
289     //                          length - 1); 
290     //                  cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
291     //          } else { //need to add explicitly the super();
292     //                  System.arraycopy(
293     //                          astStack, 
294     //                          astPtr + 1, 
295     //                          cd.statements = new Statement[length], 
296     //                          0, 
297     //                          length); 
298     //                  cd.constructorCall = SuperReference.implicitSuperConstructorCall();
299     //          }
300     //  } else {
301     //          cd.constructorCall = SuperReference.implicitSuperConstructorCall();
302     //  }
303     //
304     //  if (cd.constructorCall.sourceEnd == 0) {
305     //          cd.constructorCall.sourceEnd = cd.sourceEnd;
306     //          cd.constructorCall.sourceStart = cd.sourceStart;
307     //  }
308   }
309   // A P I
310
311   public void parse(FieldDeclaration field, TypeDeclaration type, CompilationUnitDeclaration unit, char[] initializationSource) {
312     //only parse the initializationSource of the given field
313
314     //convert bugs into parse error
315
316     initialize(false);
317     goForExpression();
318     nestedMethod[nestedType]++;
319
320     referenceContext = type;
321     compilationUnit = unit;
322
323     scanner.setSource(initializationSource);
324     scanner.resetTo(0, initializationSource.length - 1);
325     try {
326       parse();
327     } catch (AbortCompilation ex) {
328       lastAct = ERROR_ACTION;
329     } finally {
330       nestedMethod[nestedType]--;
331     }
332
333     //  if (lastAct == ERROR_ACTION) {
334     //          return;
335     //  }
336     //
337     //  field.initialization = expressionStack[expressionPtr];
338     //  
339     //  // mark field with local type if one was found during parsing
340     //  if ((type.bits & AstNode.HasLocalTypeMASK) != 0) {
341     //          field.bits |= AstNode.HasLocalTypeMASK;
342     //  }       
343   }
344   // A P I
345
346   public void parse(Initializer ini, TypeDeclaration type, CompilationUnitDeclaration unit) {
347     //only parse the method body of md
348     //fill out method statements
349
350     //convert bugs into parse error
351
352     initialize(false);
353     goForInitializer();
354     nestedMethod[nestedType]++;
355
356     referenceContext = type;
357     compilationUnit = unit;
358
359     scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the beginning {
360     try {
361       parse();
362     } catch (AbortCompilation ex) {
363       lastAct = ERROR_ACTION;
364     } finally {
365       nestedMethod[nestedType]--;
366     }
367
368     //  if (lastAct == ERROR_ACTION) {
369     //          return;
370     //  }
371     //
372     //  ini.block = ((Initializer) astStack[astPtr]).block;
373     //  
374     //  // mark initializer with local type if one was found during parsing
375     //  if ((type.bits & AstNode.HasLocalTypeMASK) != 0) {
376     //          ini.bits |= AstNode.HasLocalTypeMASK;
377     //  }       
378   }
379   // A P I
380
381   public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
382     //only parse the method body of md
383     //fill out method statements
384
385     //convert bugs into parse error
386
387     if (md.isAbstract())
388       return;
389     //  if (md.isNative())
390     //          return;
391     //  if ((md.modifiers & AccSemicolonBody) != 0)
392     //          return;
393
394     initialize(false);
395     goForMethodBody();
396     nestedMethod[nestedType]++;
397
398     referenceContext = md;
399     compilationUnit = unit;
400
401     scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd);
402     // reset the scanner to parser from { down to }
403     try {
404       parse();
405     } catch (AbortCompilation ex) {
406       lastAct = ERROR_ACTION;
407     } finally {
408       nestedMethod[nestedType]--;
409     }
410
411     //  if (lastAct == ERROR_ACTION) {
412     //          return;
413     //  }
414     //
415     //  //refill statements
416     //  md.explicitDeclarations = realBlockStack[realBlockPtr--];
417     //  int length;
418     //  if ((length = astLengthStack[astLengthPtr--]) != 0)
419     //          System.arraycopy(
420     //                  astStack, 
421     //                  (astPtr -= length) + 1, 
422     //                  md.statements = new Statement[length], 
423     //                  0, 
424     //                  length); 
425   }
426
427   // A P I
428
429   public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
430     // parses a compilation unit and manages error handling (even bugs....)
431
432     CompilationUnitDeclaration unit;
433     try {
434       /* automaton initialization */
435       initialize(false);
436       goForCompilationUnit();
437
438       /* scanner initialization */
439       scanner.setSource(sourceUnit.getContents());
440       scanner.resetTo(start, end);
441       /* unit creation */
442       referenceContext =
443         compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
444       /* run automaton */
445       parse();
446     } catch (SyntaxError syntaxError) {
447       // 
448     } finally {
449       unit = compilationUnit;
450       compilationUnit = null; // reset parser
451     }
452     return unit;
453   }
454
455   public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
456         return dietParse(sourceUnit, compilationResult, false);
457   }
458   public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
459
460     CompilationUnitDeclaration parsedUnit;
461     boolean old = diet;
462     try {
463       diet = true;
464       parsedUnit = parse(sourceUnit, compilationResult, phpMode);
465     } finally {
466       diet = old;
467     }
468     return parsedUnit;
469   }
470 }