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