Added new syntax error "Assignment operator not allowed after identifier..."
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / UnitParser.java
1 package net.sourceforge.phpdt.internal.compiler.parser;
2
3
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.phpeclipse.internal.compiler.ast.ASTNode;
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  * 
24  * 
25  */
26 public class UnitParser extends Parser {
27
28   public UnitParser(ProblemReporter problemReporter) { //, boolean optimizeStringLiterals, boolean assertMode) {
29     super(problemReporter);
30     nestedMethod = new int[30];
31     
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, 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.Util.getProblemArgumentsForMarker(problem.getArguments())});
206       }
207
208     }
209   }
210
211
212   // A P I
213
214   public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
215     //only parse the method body of cd
216     //fill out its statements
217
218     //convert bugs into parse error
219
220     initialize(false);
221     goForConstructorBody();
222     nestedMethod[nestedType]++;
223
224     referenceContext = cd;
225     compilationUnit = unit;
226     
227     scanner.resetTo(cd.sourceEnd + 1, cd.declarationSourceEnd);
228     try {
229       parse();
230     } catch (AbortCompilation ex) {
231       lastAct = ERROR_ACTION;
232     
233     } finally {
234       nestedMethod[nestedType]--;
235     }
236
237     if (lastAct == ERROR_ACTION) {
238       initialize(false);
239       return;
240     }
241
242     //statements
243     //  cd.explicitDeclarations = realBlockStack[realBlockPtr--];
244     //  int length;
245     //  if ((length = astLengthStack[astLengthPtr--]) != 0) {
246     //          astPtr -= length;
247     //          if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
248     //                  //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
249     //                  {
250     //                  System.arraycopy(
251     //                          astStack, 
252     //                          astPtr + 2, 
253     //                          cd.statements = new Statement[length - 1], 
254     //                          0, 
255     //                          length - 1); 
256     //                  cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
257     //          } else { //need to add explicitly the super();
258     //                  System.arraycopy(
259     //                          astStack, 
260     //                          astPtr + 1, 
261     //                          cd.statements = new Statement[length], 
262     //                          0, 
263     //                          length); 
264     //                  cd.constructorCall = SuperReference.implicitSuperConstructorCall();
265     //          }
266     //  } else {
267     //          cd.constructorCall = SuperReference.implicitSuperConstructorCall();
268     //  }
269     //
270     //  if (cd.constructorCall.sourceEnd == 0) {
271     //          cd.constructorCall.sourceEnd = cd.sourceEnd;
272     //          cd.constructorCall.sourceStart = cd.sourceStart;
273     //  }
274   }
275   // A P I
276
277   public void parse(FieldDeclaration field, TypeDeclaration type, CompilationUnitDeclaration unit, char[] initializationSource) {
278     //only parse the initializationSource of the given field
279
280     //convert bugs into parse error
281
282     initialize(false);
283     goForExpression();
284     nestedMethod[nestedType]++;
285
286     referenceContext = type;
287     compilationUnit = unit;
288     
289     scanner.setSource(initializationSource);
290     scanner.resetTo(0, initializationSource.length - 1);
291     try {
292       parse();
293     } catch (AbortCompilation ex) {
294       lastAct = ERROR_ACTION;
295     } finally {
296       nestedMethod[nestedType]--;
297     }
298
299     //  if (lastAct == ERROR_ACTION) {
300     //          return;
301     //  }
302     //
303     //  field.initialization = expressionStack[expressionPtr];
304     //  
305     //  // mark field with local type if one was found during parsing
306     //  if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
307     //          field.bits |= ASTNode.HasLocalTypeMASK;
308     //  }       
309   }
310   // A P I
311
312   public void parse(Initializer ini, TypeDeclaration type, CompilationUnitDeclaration unit) {
313     //only parse the method body of md
314     //fill out method statements
315
316     //convert bugs into parse error
317
318     initialize(false);
319     goForInitializer();
320     nestedMethod[nestedType]++;
321
322     referenceContext = type;
323     compilationUnit = unit;
324     
325     scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the beginning {
326     try {
327       parse();
328     } catch (AbortCompilation ex) {
329       lastAct = ERROR_ACTION;
330     } finally {
331       nestedMethod[nestedType]--;
332     }
333
334     //  if (lastAct == ERROR_ACTION) {
335     //          return;
336     //  }
337     //
338     //  ini.block = ((Initializer) astStack[astPtr]).block;
339     //  
340     //  // mark initializer with local type if one was found during parsing
341     //  if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
342     //          ini.bits |= ASTNode.HasLocalTypeMASK;
343     //  }       
344   }
345   // A P I
346
347   public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
348 //  TODO jsurfer - make the parse process work on methods ?
349     return; 
350     
351 //    //only parse the method body of md
352 //    //fill out method statements
353 //
354 //    //convert bugs into parse error
355 //
356 //    if (md.isAbstract())
357 //      return;
358 //    //        if (md.isNative())
359 //    //                return;
360 //    //        if ((md.modifiers & AccSemicolonBody) != 0)
361 //    //                return;
362 //
363 //    initialize(false);
364 //    goForMethodBody();
365 //    nestedMethod[nestedType]++;
366 //
367 //    referenceContext = md;
368 //    compilationUnit = unit;
369 //
370 //    scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd);
371 //   
372 //    // reset the scanner to parser from { down to }
373 //    try {
374 //      parse();
375 //    } catch (AbortCompilation ex) {
376 //      lastAct = ERROR_ACTION;
377 //    } finally {
378 //      nestedMethod[nestedType]--;
379 //    }
380 //
381 //    //        if (lastAct == ERROR_ACTION) {
382 //    //                return;
383 //    //        }
384 //    //
385 //    //        //refill statements
386 //    //        md.explicitDeclarations = realBlockStack[realBlockPtr--];
387 //    //        int length;
388 //    //        if ((length = astLengthStack[astLengthPtr--]) != 0)
389 //    //                System.arraycopy(
390 //    //                        astStack, 
391 //    //                        (astPtr -= length) + 1, 
392 //    //                        md.statements = new Statement[length], 
393 //    //                        0, 
394 //    //                        length); 
395   }
396
397   // A P I
398
399   public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
400     // parses a compilation unit and manages error handling (even bugs....)
401
402     CompilationUnitDeclaration unit;
403     try {
404       /* automaton initialization */
405       initialize(false);
406       goForCompilationUnit();
407
408       /* scanner initialization */
409       scanner.setSource(sourceUnit, sourceUnit.getContents());
410       scanner.resetTo(start, end);
411       /* unit creation */
412       referenceContext =
413         compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
414       
415       /* run automaton */
416       parse();
417     } catch (SyntaxError syntaxError) {
418       // 
419     } finally {
420       unit = compilationUnit;
421       compilationUnit = null; // reset parser
422     }
423     return unit;
424   }
425
426   public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
427         return dietParse(sourceUnit, compilationResult, false);
428   }
429   public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
430
431     CompilationUnitDeclaration parsedUnit;
432     boolean old = diet;
433     try {
434       diet = true;
435       parsedUnit = parse(sourceUnit, compilationResult, phpMode);
436     } finally {
437       diet = old;
438     }
439     return parsedUnit;
440   }
441   
442   public void getMethodBodies(CompilationUnitDeclaration unit) {
443         //fill the methods bodies in order for the code to be generated
444
445         if (unit == null) return;
446         
447         if (unit.ignoreMethodBodies) {
448                 unit.ignoreFurtherInvestigation = true;
449                 return;
450                 // if initial diet parse did not work, no need to dig into method bodies.
451         }
452
453         if ((unit.bits & ASTNode.HasAllMethodBodies) != 0)
454                 return; //work already done ...
455
456         //real parse of the method....
457         char[] contents = unit.compilationResult.compilationUnit.getContents();
458         this.scanner.setSource(contents);
459         
460         // save existing values to restore them at the end of the parsing process
461         // see bug 47079 for more details
462         int[] oldLineEnds = this.scanner.lineEnds;
463         int oldLinePtr = this.scanner.linePtr;
464
465         final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
466         this.scanner.lineEnds = lineSeparatorPositions;
467         this.scanner.linePtr = lineSeparatorPositions.length - 1;
468
469 //      if (this.javadocParser != null && this.javadocParser.checkDocComment) {
470 //              this.javadocParser.scanner.setSource(contents);
471 //      }
472         if (unit.types != null) {
473                 for (int i = unit.types.size(); --i >= 0;)
474                         ((TypeDeclaration)unit.types.get(i)).parseMethod(this, unit);
475         }
476         
477         // tag unit has having read bodies
478         unit.bits |= ASTNode.HasAllMethodBodies;
479
480         // this is done to prevent any side effects on the compilation unit result
481         // line separator positions array.
482         this.scanner.lineEnds = oldLineEnds;
483         this.scanner.linePtr = oldLinePtr;
484 }
485 }