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