misc parser bugfixes; still very ugly state
[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.phpdt.internal.core.BasicCompilationUnit;
11 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
12 import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
13 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
14 import net.sourceforge.phpeclipse.internal.compiler.ast.Initializer;
15 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
16 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
17
18 import org.eclipse.core.resources.IMarker;
19 import org.eclipse.core.resources.IResource;
20 import org.eclipse.core.runtime.CoreException;
21
22 /**
23  * @author jsurfer
24  *
25  * 
26  */
27 public class UnitParser extends Parser {
28
29   public UnitParser(ProblemReporter problemReporter) { //, boolean optimizeStringLiterals, boolean assertMode) {
30     super();
31     nestedMethod = new int[30];
32     this.problemReporter = problemReporter;
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];
45   }
46
47   public void goForConstructorBody() {
48     //tells the scanner to go for compilation unit parsing
49
50     firstToken = TokenNameEQUAL_EQUAL;
51     scanner.recordLineSeparator = false;
52   }
53   public void goForExpression() {
54     //tells the scanner to go for an expression parsing
55
56     firstToken = TokenNameREMAINDER;
57     scanner.recordLineSeparator = false;
58   }
59   public void goForCompilationUnit() {
60     //tells the scanner to go for compilation unit parsing
61
62     firstToken = TokenNamePLUS_PLUS;
63     scanner.linePtr = -1;
64     scanner.foundTaskCount = 0;
65     scanner.recordLineSeparator = true;
66     //          scanner.currentLine= null;
67   }
68   public void goForInitializer() {
69     //tells the scanner to go for initializer parsing
70
71     firstToken = TokenNameRIGHT_SHIFT;
72     scanner.recordLineSeparator = false;
73   }
74   public void goForMethodBody() {
75     //tells the scanner to go for method body parsing
76
77     firstToken = TokenNameMINUS_MINUS;
78     scanner.recordLineSeparator = false;
79   }
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....
84     //          astPtr = -1;
85     //          astLengthPtr = -1;
86     //          expressionPtr = -1;
87     //          expressionLengthPtr = -1;
88     //          identifierPtr = -1;     
89     //          identifierLengthPtr     = -1;
90     //          intPtr = -1;
91     //          nestedMethod[nestedType = 0] = 0; // need to reset for further reuse
92     //          variablesCounter[nestedType] = 0;
93     //          dimensions = 0 ;
94     //          realBlockPtr = -1;
95     //          endStatementPosition = 0;
96
97     //remove objects from stack too, while the same parser/compiler couple is
98     //re-used between two compilations ....
99
100     //          int astLength = astStack.length;
101     //          if (noAstNodes.length < astLength){
102     //                  noAstNodes = new AstNode[astLength];
103     //                  //System.out.println("Resized AST stacks : "+ astLength);
104     //          
105     //          }
106     //          System.arraycopy(noAstNodes, 0, astStack, 0, astLength);
107     //
108     //          int expressionLength = expressionStack.length;
109     //          if (noExpressions.length < expressionLength){
110     //                  noExpressions = new Expression[expressionLength];
111     //                  //System.out.println("Resized EXPR stacks : "+ expressionLength);
112     //          }
113     //          System.arraycopy(noExpressions, 0, expressionStack, 0, expressionLength);
114
115     // reset scanner state
116     scanner.commentPtr = -1;
117     scanner.foundTaskCount = 0;
118     scanner.eofPosition = Integer.MAX_VALUE;
119
120     //          resetModifiers();
121     //
122     //          // recovery
123     //          lastCheckPoint = -1;
124     //          currentElement = null;
125     //          restartRecovery = false;
126     //          hasReportedError = false;
127     //          recoveredStaticInitializerStart = 0;
128     //          lastIgnoredToken = -1;
129     //          lastErrorEndPosition = -1;
130     //          listLength = 0;
131   }
132
133   // A P I
134
135   public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
136     // parses a compilation unit and manages error handling (even bugs....)
137
138     CompilationUnitDeclaration unit;
139     try {
140       /* automaton initialization */
141       initialize(phpMode);
142       goForCompilationUnit();
143
144       /* scanner initialization */
145       scanner.setSource(sourceUnit.getContents());
146
147       /* unit creation */
148       referenceContext =
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);
157       /* run automaton */
158       super.parse();
159 //      //              TODO jsurfer start 
160 //      if (sourceUnit instanceof BasicCompilationUnit) {
161 //        storeProblemsFor(((BasicCompilationUnit)sourceUnit).getResource(), compilationResult.getAllProblems());
162 //      }
163 //      // jsurfer end
164     } catch (CoreException e) {
165       e.printStackTrace();
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     } catch (CoreException e) {
269       // TODO Auto-generated catch block
270       e.printStackTrace();
271     } finally {
272       nestedMethod[nestedType]--;
273     }
274
275     if (lastAct == ERROR_ACTION) {
276       initialize(false);
277       return;
278     }
279
280     //statements
281     //  cd.explicitDeclarations = realBlockStack[realBlockPtr--];
282     //  int length;
283     //  if ((length = astLengthStack[astLengthPtr--]) != 0) {
284     //          astPtr -= length;
285     //          if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
286     //                  //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
287     //                  {
288     //                  System.arraycopy(
289     //                          astStack, 
290     //                          astPtr + 2, 
291     //                          cd.statements = new Statement[length - 1], 
292     //                          0, 
293     //                          length - 1); 
294     //                  cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
295     //          } else { //need to add explicitly the super();
296     //                  System.arraycopy(
297     //                          astStack, 
298     //                          astPtr + 1, 
299     //                          cd.statements = new Statement[length], 
300     //                          0, 
301     //                          length); 
302     //                  cd.constructorCall = SuperReference.implicitSuperConstructorCall();
303     //          }
304     //  } else {
305     //          cd.constructorCall = SuperReference.implicitSuperConstructorCall();
306     //  }
307     //
308     //  if (cd.constructorCall.sourceEnd == 0) {
309     //          cd.constructorCall.sourceEnd = cd.sourceEnd;
310     //          cd.constructorCall.sourceStart = cd.sourceStart;
311     //  }
312   }
313   // A P I
314
315   public void parse(FieldDeclaration field, TypeDeclaration type, CompilationUnitDeclaration unit, char[] initializationSource) {
316     //only parse the initializationSource of the given field
317
318     //convert bugs into parse error
319
320     initialize(false);
321     goForExpression();
322     nestedMethod[nestedType]++;
323
324     referenceContext = type;
325     compilationUnit = unit;
326
327     scanner.setSource(initializationSource);
328     scanner.resetTo(0, initializationSource.length - 1);
329     try {
330       parse();
331     } catch (AbortCompilation ex) {
332       lastAct = ERROR_ACTION;
333     } catch (CoreException e) {
334       // TODO Auto-generated catch block
335       e.printStackTrace();
336     } finally {
337       nestedMethod[nestedType]--;
338     }
339
340     //  if (lastAct == ERROR_ACTION) {
341     //          return;
342     //  }
343     //
344     //  field.initialization = expressionStack[expressionPtr];
345     //  
346     //  // mark field with local type if one was found during parsing
347     //  if ((type.bits & AstNode.HasLocalTypeMASK) != 0) {
348     //          field.bits |= AstNode.HasLocalTypeMASK;
349     //  }       
350   }
351   // A P I
352
353   public void parse(Initializer ini, TypeDeclaration type, CompilationUnitDeclaration unit) {
354     //only parse the method body of md
355     //fill out method statements
356
357     //convert bugs into parse error
358
359     initialize(false);
360     goForInitializer();
361     nestedMethod[nestedType]++;
362
363     referenceContext = type;
364     compilationUnit = unit;
365
366     scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the beginning {
367     try {
368       parse();
369     } catch (AbortCompilation ex) {
370       lastAct = ERROR_ACTION;
371     } catch (CoreException e) {
372       // TODO Auto-generated catch block
373       e.printStackTrace();
374     } finally {
375       nestedMethod[nestedType]--;
376     }
377
378     //  if (lastAct == ERROR_ACTION) {
379     //          return;
380     //  }
381     //
382     //  ini.block = ((Initializer) astStack[astPtr]).block;
383     //  
384     //  // mark initializer with local type if one was found during parsing
385     //  if ((type.bits & AstNode.HasLocalTypeMASK) != 0) {
386     //          ini.bits |= AstNode.HasLocalTypeMASK;
387     //  }       
388   }
389   // A P I
390
391   public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
392     //only parse the method body of md
393     //fill out method statements
394
395     //convert bugs into parse error
396
397     if (md.isAbstract())
398       return;
399     //  if (md.isNative())
400     //          return;
401     //  if ((md.modifiers & AccSemicolonBody) != 0)
402     //          return;
403
404     initialize(false);
405     goForMethodBody();
406     nestedMethod[nestedType]++;
407
408     referenceContext = md;
409     compilationUnit = unit;
410
411     scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd);
412     // reset the scanner to parser from { down to }
413     try {
414       parse();
415     } catch (AbortCompilation ex) {
416       lastAct = ERROR_ACTION;
417     } catch (CoreException e) {
418       // TODO Auto-generated catch block
419       e.printStackTrace();
420     } finally {
421       nestedMethod[nestedType]--;
422     }
423
424     //  if (lastAct == ERROR_ACTION) {
425     //          return;
426     //  }
427     //
428     //  //refill statements
429     //  md.explicitDeclarations = realBlockStack[realBlockPtr--];
430     //  int length;
431     //  if ((length = astLengthStack[astLengthPtr--]) != 0)
432     //          System.arraycopy(
433     //                  astStack, 
434     //                  (astPtr -= length) + 1, 
435     //                  md.statements = new Statement[length], 
436     //                  0, 
437     //                  length); 
438   }
439
440   // A P I
441
442   public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
443     // parses a compilation unit and manages error handling (even bugs....)
444
445     CompilationUnitDeclaration unit;
446     try {
447       /* automaton initialization */
448       initialize(false);
449       goForCompilationUnit();
450
451       /* scanner initialization */
452       scanner.setSource(sourceUnit.getContents());
453       scanner.resetTo(start, end);
454       /* unit creation */
455       referenceContext =
456         compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
457       /* run automaton */
458       parse();
459     } catch (CoreException e) {
460       // TODO Auto-generated catch block
461       e.printStackTrace();
462     } catch (SyntaxError syntaxError) {
463       // 
464     } finally {
465       unit = compilationUnit;
466       compilationUnit = null; // reset parser
467     }
468     return unit;
469   }
470
471   public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
472         return dietParse(sourceUnit, compilationResult, false);
473   }
474   public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
475
476     CompilationUnitDeclaration parsedUnit;
477     boolean old = diet;
478     try {
479       diet = true;
480       parsedUnit = parse(sourceUnit, compilationResult, phpMode);
481     } finally {
482       diet = old;
483     }
484     return parsedUnit;
485   }
486 }