b27c78ce7f466ed79d57fe4276ec6d09aef27d60
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Parser.java
1 /***********************************************************************************************************************************
2  * Copyright (c) 2002 www.phpeclipse.de All rights reserved. This program and the accompanying material are made available under the
3  * terms of the Common Public License v1.0 which accompanies this distribution, and is available at
4  * http://www.eclipse.org/legal/cpl-v10.html
5  *
6  * Contributors: www.phpeclipse.de
7  **********************************************************************************************************************************/
8 package net.sourceforge.phpdt.internal.compiler.parser;
9
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.HashSet;
13
14 import net.sourceforge.phpdt.core.compiler.CharOperation;
15 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
16 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
17 import net.sourceforge.phpdt.internal.compiler.ast.AND_AND_Expression;
18 import net.sourceforge.phpdt.internal.compiler.ast.ASTNode;
19 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression;
21 import net.sourceforge.phpdt.internal.compiler.ast.Block;
22 import net.sourceforge.phpdt.internal.compiler.ast.BreakStatement;
23 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
24 import net.sourceforge.phpdt.internal.compiler.ast.ConditionalExpression;
25 import net.sourceforge.phpdt.internal.compiler.ast.ContinueStatement;
26 import net.sourceforge.phpdt.internal.compiler.ast.EqualExpression;
27 import net.sourceforge.phpdt.internal.compiler.ast.Expression;
28 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
29 import net.sourceforge.phpdt.internal.compiler.ast.FieldReference;
30 import net.sourceforge.phpdt.internal.compiler.ast.IfStatement;
31 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
32 import net.sourceforge.phpdt.internal.compiler.ast.InstanceOfExpression;
33 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
34 import net.sourceforge.phpdt.internal.compiler.ast.OR_OR_Expression;
35 import net.sourceforge.phpdt.internal.compiler.ast.OperatorIds;
36 import net.sourceforge.phpdt.internal.compiler.ast.ReturnStatement;
37 import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
38 import net.sourceforge.phpdt.internal.compiler.ast.Statement;
39 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteral;
40 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteralDQ;
41 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteralSQ;
42 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
43 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
44 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
45 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
46 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
47 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
48 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
49 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
50 import net.sourceforge.phpdt.internal.compiler.util.Util;
51 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
52 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
53 import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
54
55 import org.eclipse.core.resources.IFile;
56 import org.eclipse.core.resources.IProject;
57 import org.eclipse.core.resources.IResource;
58 import org.eclipse.core.runtime.IPath;
59
60 public class Parser implements ITerminalSymbols, CompilerModifiers,
61                 ParserBasicInformation {
62         protected final static int StackIncrement = 255;
63
64         protected int stateStackTop;
65
66         // protected int[] stack = new int[StackIncrement];
67
68         public int firstToken; // handle for multiple parsing goals
69
70         public int lastAct; // handle for multiple parsing goals
71
72         // protected RecoveredElement currentElement;
73
74         public static boolean VERBOSE_RECOVERY = false;
75
76         protected boolean diet = false; // tells the scanner to jump over some
77
78         /**
79          * the PHP token scanner
80          */
81         public Scanner scanner;
82
83         int token;
84
85         protected int modifiers;
86
87         protected int modifiersSourceStart;
88
89         protected Parser(ProblemReporter problemReporter) {
90                 this.problemReporter = problemReporter;
91                 this.options = problemReporter.options;
92                 this.token = TokenNameEOF;
93                 this.initializeScanner();
94         }
95
96         public void setFileToParse(IFile fileToParse) {
97                 this.token = TokenNameEOF;
98                 this.initializeScanner();
99         }
100
101         /**
102          * ClassDeclaration Constructor.
103          * 
104          * @param s
105          * @param sess
106          *            Description of Parameter
107          * @see
108          */
109         public Parser(IFile fileToParse) {
110                 // if (keywordMap == null) {
111                 // keywordMap = new HashMap();
112                 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
113                 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
114                 // }
115                 // }
116                 // this.currentPHPString = 0;
117                 // PHPParserSuperclass.fileToParse = fileToParse;
118                 // this.phpList = null;
119                 this.includesList = null;
120                 // this.str = "";
121                 this.token = TokenNameEOF;
122                 // this.chIndx = 0;
123                 // this.rowCount = 1;
124                 // this.columnCount = 0;
125                 // this.phpEnd = false;
126                 // getNextToken();
127                 this.initializeScanner();
128         }
129
130         public void initializeScanner() {
131                 this.scanner = new Scanner(
132                                 false /* comment */,
133                                 false /* whitespace */,
134                                 this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */,
135                                 false, false, this.options.taskTags/* taskTags */,
136                                 this.options.taskPriorites/* taskPriorities */, true/* isTaskCaseSensitive */);
137         }
138
139         /**
140          * Create marker for the parse error
141          */
142         // private void setMarker(String message, int charStart, int charEnd, int
143         // errorLevel) {
144         // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
145         // }
146         /**
147          * This method will throw the SyntaxError. It will add the good lines and
148          * columns to the Error
149          * 
150          * @param error
151          *            the error message
152          * @throws SyntaxError
153          *             the error raised
154          */
155         private void throwSyntaxError(String error) {
156                 int problemStartPosition = scanner.getCurrentTokenStartPosition();
157                 int problemEndPosition = scanner.getCurrentTokenEndPosition() + 1;
158                 if (scanner.source.length <= problemEndPosition
159                                 && problemEndPosition > 0) {
160                         problemEndPosition = scanner.source.length - 1;
161                         if (problemStartPosition > 0
162                                         && problemStartPosition >= problemEndPosition
163                                         && problemEndPosition > 0) {
164                                 problemStartPosition = problemEndPosition - 1;
165                         }
166                 }
167                 throwSyntaxError(error, problemStartPosition, problemEndPosition);
168         }
169
170         /**
171          * This method will throw the SyntaxError. It will add the good lines and
172          * columns to the Error
173          * 
174          * @param error
175          *            the error message
176          * @throws SyntaxError
177          *             the error raised
178          */
179         // private void throwSyntaxError(String error, int startRow) {
180         // throw new SyntaxError(startRow, 0, " ", error);
181         // }
182         private void throwSyntaxError(String error, int problemStartPosition,
183                         int problemEndPosition) {
184                 if (referenceContext != null) {
185                         problemReporter.phpParsingError(new String[] { error },
186                                         problemStartPosition, problemEndPosition, referenceContext,
187                                         compilationUnit.compilationResult);
188                 }
189                 throw new SyntaxError(1, 0, " ", error);
190         }
191
192         private void reportSyntaxError(String error) {
193                 int problemStartPosition = scanner.getCurrentTokenStartPosition();
194                 int problemEndPosition = scanner.getCurrentTokenEndPosition();
195                 reportSyntaxError(error, problemStartPosition, problemEndPosition + 1);
196         }
197
198         private void reportSyntaxError(String error, int problemStartPosition,
199                         int problemEndPosition) {
200                 if (referenceContext != null) {
201                         problemReporter.phpParsingError(new String[] { error },
202                                         problemStartPosition, problemEndPosition, referenceContext,
203                                         compilationUnit.compilationResult);
204                 }
205         }
206
207         // private void reportSyntaxWarning(String error, int problemStartPosition,
208         // int problemEndPosition) {
209         // if (referenceContext != null) {
210         // problemReporter.phpParsingWarning(new String[] { error },
211         // problemStartPosition, problemEndPosition, referenceContext,
212         // compilationUnit.compilationResult);
213         // }
214         // }
215
216         /**
217          * gets the next token from input
218          */
219         private void getNextToken() {
220                 try {
221                         token = scanner.getNextToken();
222                         if (Scanner.DEBUG) {
223                                 int currentEndPosition = scanner.getCurrentTokenEndPosition();
224                                 int currentStartPosition = scanner
225                                                 .getCurrentTokenStartPosition();
226                                 System.out.print(currentStartPosition + ","
227                                                 + currentEndPosition + ": ");
228                                 System.out.println(scanner.toStringAction(token));
229                         }
230                 } catch (InvalidInputException e) {
231                         token = TokenNameERROR;
232                         String detailedMessage = e.getMessage();
233
234                         if (detailedMessage == Scanner.UNTERMINATED_STRING) {
235                                 throwSyntaxError("Unterminated string.");
236                         } else if (detailedMessage == Scanner.UNTERMINATED_COMMENT) {
237                                 throwSyntaxError("Unterminated commment.");
238                         }
239                 }
240                 return;
241         }
242
243         public void init(String s) {
244                 // this.str = s;
245                 this.token = TokenNameEOF;
246                 this.includesList = new ArrayList();
247                 // this.chIndx = 0;
248                 // this.rowCount = 1;
249                 // this.columnCount = 0;
250                 // this.phpEnd = false;
251                 // this.phpMode = false;
252                 /* scanner initialization */
253                 scanner.setSource(s.toCharArray());
254                 scanner.setPHPMode(false);
255                 astPtr = 0;
256         }
257
258         protected void initialize(boolean phpMode) {
259                 initialize(phpMode, null);
260         }
261
262         protected void initialize(boolean phpMode,
263                         IdentifierIndexManager indexManager) {
264                 compilationUnit = null;
265                 referenceContext = null;
266                 this.includesList = new ArrayList();
267                 // this.indexManager = indexManager;
268                 // this.str = "";
269                 this.token = TokenNameEOF;
270                 // this.chIndx = 0;
271                 // this.rowCount = 1;
272                 // this.columnCount = 0;
273                 // this.phpEnd = false;
274                 // this.phpMode = phpMode;
275                 scanner.setPHPMode(phpMode);
276                 astPtr = 0;
277         }
278
279         /**
280          * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
281          * &lt;/body&gt;'
282          */
283         public void parse(String s) {
284                 parse(s, null);
285         }
286
287         /**
288          * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
289          * &lt;/body&gt;'
290          */
291         public void parse(String s, HashMap variables) {
292                 fMethodVariables = variables;
293                 fStackUnassigned = new ArrayList();
294                 init(s);
295                 parse();
296         }
297
298         /**
299          * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
300          * &lt;/body&gt;'
301          */
302         protected void parse() {
303                 if (scanner.compilationUnit != null) {
304                         IResource resource = scanner.compilationUnit.getResource();
305                         if (resource != null && resource instanceof IFile) {
306                                 // set the package name
307                                 consumePackageDeclarationName((IFile) resource);
308                         }
309                 }
310                 getNextToken();
311                 do {
312                         try {
313                                 if (token != TokenNameEOF && token != TokenNameERROR) {
314                                         statementList();
315                                 }
316                                 if (token != TokenNameEOF) {
317                                         if (token == TokenNameERROR) {
318                                                 throwSyntaxError("Scanner error (Found unknown token: "
319                                                                 + scanner.toStringAction(token) + ")");
320                                         }
321                                         if (token == TokenNameRPAREN) {
322                                                 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
323                                         }
324                                         if (token == TokenNameRBRACE) {
325                                                 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
326                                         }
327                                         if (token == TokenNameRBRACKET) {
328                                                 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
329                                         }
330                                         if (token == TokenNameLPAREN) {
331                                                 throwSyntaxError("Read character '('; end-of-file not reached.");
332                                         }
333                                         if (token == TokenNameLBRACE) {
334                                                 throwSyntaxError("Read character '{';  end-of-file not reached.");
335                                         }
336                                         if (token == TokenNameLBRACKET) {
337                                                 throwSyntaxError("Read character '[';  end-of-file not reached.");
338                                         }
339                                         throwSyntaxError("End-of-file not reached.");
340                                 }
341                                 break;
342                         } catch (SyntaxError syntaxError) {
343                                 // syntaxError.printStackTrace();
344                                 break;
345                         }
346                 } while (true);
347
348                 endParse(0);
349         }
350
351         /**
352          * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
353          * &lt;/body&gt;'
354          */
355         public void parseFunction(String s, HashMap variables) {
356                 init(s);
357                 scanner.phpMode = true;
358                 parseFunction(variables);
359         }
360
361         /**
362          * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
363          * &lt;/body&gt;'
364          */
365         protected void parseFunction(HashMap variables) {
366                 getNextToken();
367                 boolean hasModifiers = member_modifiers();
368                 if (token == TokenNamefunction) {
369                         if (!hasModifiers) {
370                                 checkAndSetModifiers(AccPublic);
371                         }
372                         this.fMethodVariables = variables;
373
374                         MethodDeclaration methodDecl = new MethodDeclaration(null);
375                         methodDecl.declarationSourceStart = scanner
376                                         .getCurrentTokenStartPosition();
377                         methodDecl.modifiers = this.modifiers;
378                         methodDecl.type = MethodDeclaration.METHOD_DEFINITION;
379                         try {
380                                 getNextToken();
381                                 functionDefinition(methodDecl);
382                         } catch (SyntaxError sytaxErr1) {
383                                 return;
384                         } finally {
385                                 int sourceEnd = methodDecl.sourceEnd;
386                                 if (sourceEnd <= 0
387                                                 || methodDecl.declarationSourceStart > sourceEnd) {
388                                         sourceEnd = methodDecl.declarationSourceStart + 1;
389                                 }
390                                 methodDecl.sourceEnd = sourceEnd;
391                                 methodDecl.declarationSourceEnd = sourceEnd;
392                         }
393                 }
394         }
395
396         protected CompilationUnitDeclaration endParse(int act) {
397
398                 this.lastAct = act;
399
400                 // if (currentElement != null) {
401                 // currentElement.topElement().updateParseTree();
402                 // if (VERBOSE_RECOVERY) {
403                 // System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
404                 // System.out.println("--------------------------"); //$NON-NLS-1$
405                 // System.out.println(compilationUnit);
406                 // System.out.println("----------------------------------");
407                 // //$NON-NLS-1$
408                 // }
409                 // } else {
410                 if (diet & VERBOSE_RECOVERY) {
411                         System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
412                         System.out.println("--------------------------"); //$NON-NLS-1$
413                         System.out.println(compilationUnit);
414                         System.out.println("----------------------------------"); //$NON-NLS-1$
415                 }
416                 // }
417                 if (scanner.recordLineSeparator) {
418                         compilationUnit.compilationResult.lineSeparatorPositions = scanner
419                                         .getLineEnds();
420                 }
421                 if (scanner.taskTags != null) {
422                         for (int i = 0; i < scanner.foundTaskCount; i++) {
423                                 problemReporter().task(
424                                                 new String(scanner.foundTaskTags[i]),
425                                                 new String(scanner.foundTaskMessages[i]),
426                                                 scanner.foundTaskPriorities[i] == null ? null
427                                                                 : new String(scanner.foundTaskPriorities[i]),
428                                                 scanner.foundTaskPositions[i][0],
429                                                 scanner.foundTaskPositions[i][1]);
430                         }
431                 }
432                 compilationUnit.imports = new ImportReference[includesList.size()];
433                 for (int i = 0; i < includesList.size(); i++) {
434                         compilationUnit.imports[i] = (ImportReference) includesList.get(i);
435                 }
436                 return compilationUnit;
437         }
438
439         private Block statementList() {
440                 boolean branchStatement = false;
441                 Statement statement;
442                 int blockStart = scanner.getCurrentTokenStartPosition();
443                 ArrayList blockStatements = new ArrayList();
444                 do {
445                         try {
446                                 statement = statement();
447                                 blockStatements.add(statement);
448                                 if (token == TokenNameEOF) {
449                                         return null;
450                                 }
451                                 if (branchStatement && statement != null) {
452                                         // reportSyntaxError("Unreachable code",
453                                         // statement.sourceStart,
454                                         // statement.sourceEnd);
455                                         if (!(statement instanceof BreakStatement)) {
456                                                 /*
457                                                  * don't give an error for break statement following
458                                                  * return statement Technically it's unreachable code,
459                                                  * but in switch-case it's recommended to avoid
460                                                  * accidental fall-through later when editing the code
461                                                  */
462                                                 problemReporter.unreachableCode(new String(scanner
463                                                                 .getCurrentIdentifierSource()),
464                                                                 statement.sourceStart, statement.sourceEnd,
465                                                                 referenceContext,
466                                                                 compilationUnit.compilationResult);
467                                         }
468                                 }
469                                 if ((token == TokenNameRBRACE) || (token == TokenNamecase)
470                                                 || (token == TokenNamedefault)
471                                                 || (token == TokenNameelse)
472                                                 || (token == TokenNameelseif)
473                                                 || (token == TokenNameendif)
474                                                 || (token == TokenNameendfor)
475                                                 || (token == TokenNameendforeach)
476                                                 || (token == TokenNameendwhile)
477                                                 || (token == TokenNameendswitch)
478                                                 || (token == TokenNameenddeclare)
479                                                 || (token == TokenNameEOF) || (token == TokenNameERROR)) {
480                                         return createBlock(blockStart, blockStatements);
481                                 }
482                                 branchStatement = checkUnreachableStatements(statement);
483                         } catch (SyntaxError sytaxErr1) {
484                                 // if an error occured,
485                                 // try to find keywords
486                                 // to parse the rest of the string
487                                 boolean tokenize = scanner.tokenizeStrings;
488                                 if (!tokenize) {
489                                         scanner.tokenizeStrings = true;
490                                 }
491                                 try {
492                                         while (token != TokenNameEOF) {
493                                                 if ((token == TokenNameRBRACE)
494                                                                 || (token == TokenNamecase)
495                                                                 || (token == TokenNamedefault)
496                                                                 || (token == TokenNameelse)
497                                                                 || (token == TokenNameelseif)
498                                                                 || (token == TokenNameendif)
499                                                                 || (token == TokenNameendfor)
500                                                                 || (token == TokenNameendforeach)
501                                                                 || (token == TokenNameendwhile)
502                                                                 || (token == TokenNameendswitch)
503                                                                 || (token == TokenNameenddeclare)
504                                                                 || (token == TokenNameEOF)
505                                                                 || (token == TokenNameERROR)) {
506                                                         return createBlock(blockStart, blockStatements);
507                                                 }
508                                                 if (token == TokenNameif || token == TokenNameswitch
509                                                                 || token == TokenNamefor
510                                                                 || token == TokenNamewhile
511                                                                 || token == TokenNamedo
512                                                                 || token == TokenNameforeach
513                                                                 || token == TokenNamecontinue
514                                                                 || token == TokenNamebreak
515                                                                 || token == TokenNamereturn
516                                                                 || token == TokenNameexit
517                                                                 || token == TokenNameecho
518                                                                 || token == TokenNameECHO_INVISIBLE
519                                                                 || token == TokenNameglobal
520                                                                 || token == TokenNamestatic
521                                                                 || token == TokenNameunset
522                                                                 || token == TokenNamefunction
523                                                                 || token == TokenNamedeclare
524                                                                 || token == TokenNametry
525                                                                 || token == TokenNamecatch
526                                                                 || token == TokenNamethrow
527                                                                 || token == TokenNamefinal
528                                                                 || token == TokenNameabstract
529                                                                 || token == TokenNameclass
530                                                                 || token == TokenNameinterface) {
531                                                         break;
532                                                 }
533                                                 // System.out.println(scanner.toStringAction(token));
534                                                 getNextToken();
535                                                 // System.out.println(scanner.toStringAction(token));
536                                         }
537                                         if (token == TokenNameEOF) {
538                                                 throw sytaxErr1;
539                                         }
540                                 } finally {
541                                         scanner.tokenizeStrings = tokenize;
542                                 }
543                         }
544                 } while (true);
545         }
546
547         /**
548          * @param statement
549          * @return
550          */
551         private boolean checkUnreachableStatements(Statement statement) {
552                 if (statement instanceof ReturnStatement
553                                 || statement instanceof ContinueStatement
554                                 || statement instanceof BreakStatement) {
555                         return true;
556                 } else if (statement instanceof IfStatement
557                                 && ((IfStatement) statement).checkUnreachable) {
558                         return true;
559                 }
560                 return false;
561         }
562
563         /**
564          * @param blockStart
565          * @param blockStatements
566          * @return
567          */
568         private Block createBlock(int blockStart, ArrayList blockStatements) {
569                 int blockEnd = scanner.getCurrentTokenEndPosition();
570                 Block b = Block.EmptyWith(blockStart, blockEnd);
571                 b.statements = new Statement[blockStatements.size()];
572                 blockStatements.toArray(b.statements);
573                 return b;
574         }
575
576         private void functionBody(MethodDeclaration methodDecl) {
577                 // '{' [statement-list] '}'
578                 if (token == TokenNameLBRACE) {
579                         getNextToken();
580                 } else {
581                         methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
582                         throwSyntaxError("'{' expected in compound-statement.");
583                 }
584                 if (token != TokenNameRBRACE) {
585                         statementList();
586                 }
587                 if (token == TokenNameRBRACE) {
588                         methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
589                         getNextToken();
590                 } else {
591                         methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
592                         throwSyntaxError("'}' expected in compound-statement.");
593                 }
594         }
595
596         private Statement statement() {
597                 Statement statement = null;
598                 Expression expression;
599                 int sourceStart = scanner.getCurrentTokenStartPosition();
600                 int sourceEnd;
601                 if (token == TokenNameif) {
602                         // T_IF '(' expr ')' statement elseif_list else_single
603                         // T_IF '(' expr ')' ':' inner_statement_list new_elseif_list
604                         // new_else_single T_ENDIF ';'
605                         getNextToken();
606                         if (token == TokenNameLPAREN) {
607                                 getNextToken();
608                         } else {
609                                 throwSyntaxError("'(' expected after 'if' keyword.");
610                         }
611                         expression = expr();
612                         if (token == TokenNameRPAREN) {
613                                 getNextToken();
614                         } else {
615                                 throwSyntaxError("')' expected after 'if' condition.");
616                         }
617                         // create basic IfStatement
618                         IfStatement ifStatement = new IfStatement(expression, null, null,
619                                         sourceStart, -1);
620                         if (token == TokenNameCOLON) {
621                                 getNextToken();
622                                 ifStatementColon(ifStatement);
623                         } else {
624                                 ifStatement(ifStatement);
625                         }
626                         return ifStatement;
627                 } else if (token == TokenNameswitch) {
628                         getNextToken();
629                         if (token == TokenNameLPAREN) {
630                                 getNextToken();
631                         } else {
632                                 throwSyntaxError("'(' expected after 'switch' keyword.");
633                         }
634                         expr();
635                         if (token == TokenNameRPAREN) {
636                                 getNextToken();
637                         } else {
638                                 throwSyntaxError("')' expected after 'switch' condition.");
639                         }
640                         switchStatement();
641                         return statement;
642                 } else if (token == TokenNamefor) {
643                         getNextToken();
644                         if (token == TokenNameLPAREN) {
645                                 getNextToken();
646                         } else {
647                                 throwSyntaxError("'(' expected after 'for' keyword.");
648                         }
649                         if (token == TokenNameSEMICOLON) {
650                                 getNextToken();
651                         } else {
652                                 expressionList();
653                                 if (token == TokenNameSEMICOLON) {
654                                         getNextToken();
655                                 } else {
656                                         throwSyntaxError("';' expected after 'for'.");
657                                 }
658                         }
659                         if (token == TokenNameSEMICOLON) {
660                                 getNextToken();
661                         } else {
662                                 expressionList();
663                                 if (token == TokenNameSEMICOLON) {
664                                         getNextToken();
665                                 } else {
666                                         throwSyntaxError("';' expected after 'for'.");
667                                 }
668                         }
669                         if (token == TokenNameRPAREN) {
670                                 getNextToken();
671                         } else {
672                                 expressionList();
673                                 if (token == TokenNameRPAREN) {
674                                         getNextToken();
675                                 } else {
676                                         throwSyntaxError("')' expected after 'for'.");
677                                 }
678                         }
679                         forStatement();
680                         return statement;
681                 } else if (token == TokenNamewhile) {
682                         getNextToken();
683                         if (token == TokenNameLPAREN) {
684                                 getNextToken();
685                         } else {
686                                 throwSyntaxError("'(' expected after 'while' keyword.");
687                         }
688                         expr();
689                         if (token == TokenNameRPAREN) {
690                                 getNextToken();
691                         } else {
692                                 throwSyntaxError("')' expected after 'while' condition.");
693                         }
694                         whileStatement();
695                         return statement;
696                 } else if (token == TokenNamedo) {
697                         getNextToken();
698                         if (token == TokenNameLBRACE) {
699                                 getNextToken();
700                                 if (token != TokenNameRBRACE) {
701                                         statementList();
702                                 }
703                                 if (token == TokenNameRBRACE) {
704                                         getNextToken();
705                                 } else {
706                                         throwSyntaxError("'}' expected after 'do' keyword.");
707                                 }
708                         } else {
709                                 statement();
710                         }
711                         if (token == TokenNamewhile) {
712                                 getNextToken();
713                                 if (token == TokenNameLPAREN) {
714                                         getNextToken();
715                                 } else {
716                                         throwSyntaxError("'(' expected after 'while' keyword.");
717                                 }
718                                 expr();
719                                 if (token == TokenNameRPAREN) {
720                                         getNextToken();
721                                 } else {
722                                         throwSyntaxError("')' expected after 'while' condition.");
723                                 }
724                         } else {
725                                 throwSyntaxError("'while' expected after 'do' keyword.");
726                         }
727                         if (token == TokenNameSEMICOLON) {
728                                 getNextToken();
729                         } else {
730                                 if (token != TokenNameINLINE_HTML) {
731                                         throwSyntaxError("';' expected after do-while statement.");
732                                 }
733                                 getNextToken();
734                         }
735                         return statement;
736                 } else if (token == TokenNameforeach) {
737                         getNextToken();
738                         if (token == TokenNameLPAREN) {
739                                 getNextToken();
740                         } else {
741                                 throwSyntaxError("'(' expected after 'foreach' keyword.");
742                         }
743                         expr();
744                         if (token == TokenNameas) {
745                                 getNextToken();
746                         } else {
747                                 throwSyntaxError("'as' expected after 'foreach' exxpression.");
748                         }
749                         // variable();
750                         foreach_variable();
751                         foreach_optional_arg();
752                         if (token == TokenNameEQUAL_GREATER) {
753                                 getNextToken();
754                                 variable(false, false);
755                         }
756                         if (token == TokenNameRPAREN) {
757                                 getNextToken();
758                         } else {
759                                 throwSyntaxError("')' expected after 'foreach' expression.");
760                         }
761                         foreachStatement();
762                         return statement;
763                 } else if (token == TokenNamebreak) {
764                         expression = null;
765                         getNextToken();
766                         if (token != TokenNameSEMICOLON) {
767                                 expression = expr();
768                         }
769                         if (token == TokenNameSEMICOLON) {
770                                 sourceEnd = scanner.getCurrentTokenEndPosition();
771                                 getNextToken();
772                         } else {
773                                 if (token != TokenNameINLINE_HTML) {
774                                         throwSyntaxError("';' expected after 'break'.");
775                                 }
776                                 sourceEnd = scanner.getCurrentTokenEndPosition();
777                                 getNextToken();
778                         }
779                         return new BreakStatement(null, sourceStart, sourceEnd);
780                 } else if (token == TokenNamecontinue) {
781                         expression = null;
782                         getNextToken();
783                         if (token != TokenNameSEMICOLON) {
784                                 expression = expr();
785                         }
786                         if (token == TokenNameSEMICOLON) {
787                                 sourceEnd = scanner.getCurrentTokenEndPosition();
788                                 getNextToken();
789                         } else {
790                                 if (token != TokenNameINLINE_HTML) {
791                                         throwSyntaxError("';' expected after 'continue'.");
792                                 }
793                                 sourceEnd = scanner.getCurrentTokenEndPosition();
794                                 getNextToken();
795                         }
796                         return new ContinueStatement(null, sourceStart, sourceEnd);
797                 } else if (token == TokenNamereturn) {
798                         expression = null;
799                         getNextToken();
800                         if (token != TokenNameSEMICOLON) {
801                                 expression = expr();
802                         }
803                         if (token == TokenNameSEMICOLON) {
804                                 sourceEnd = scanner.getCurrentTokenEndPosition();
805                                 getNextToken();
806                         } else {
807                                 if (token != TokenNameINLINE_HTML) {
808                                         throwSyntaxError("';' expected after 'return'.");
809                                 }
810                                 sourceEnd = scanner.getCurrentTokenEndPosition();
811                                 getNextToken();
812                         }
813                         return new ReturnStatement(expression, sourceStart, sourceEnd);
814                 } else if (token == TokenNameecho) {
815                         getNextToken();
816                         expressionList();
817                         if (token == TokenNameSEMICOLON) {
818                                 getNextToken();
819                         } else {
820                                 if (token != TokenNameINLINE_HTML) {
821                                         throwSyntaxError("';' expected after 'echo' statement.");
822                                 }
823                                 getNextToken();
824                         }
825                         return statement;
826                 } else if (token == TokenNameECHO_INVISIBLE) {
827                         // 0-length token directly after PHP short tag &lt;?=
828                         getNextToken();
829                         expressionList();
830                         if (token == TokenNameSEMICOLON) {
831                                 getNextToken();
832                                 // if (token != TokenNameINLINE_HTML) {
833                                 // // TODO should this become a configurable warning?
834                                 // reportSyntaxError("Probably '?>' expected after PHP short tag
835                                 // expression (only the first expression will be echoed).");
836                                 // }
837                         } else {
838                                 if (token != TokenNameINLINE_HTML) {
839                                         throwSyntaxError("';' expected after PHP short tag '<?=' expression.");
840                                 }
841                                 getNextToken();
842                         }
843                         return statement;
844                 } else if (token == TokenNameINLINE_HTML) {
845                         getNextToken();
846                         return statement;
847                 } else if (token == TokenNameglobal) {
848                         getNextToken();
849                         global_var_list();
850                         if (token == TokenNameSEMICOLON) {
851                                 getNextToken();
852                         } else {
853                                 if (token != TokenNameINLINE_HTML) {
854                                         throwSyntaxError("';' expected after 'global' statement.");
855                                 }
856                                 getNextToken();
857                         }
858                         return statement;
859                 } else if (token == TokenNamestatic) {
860                         getNextToken();
861                         static_var_list();
862                         if (token == TokenNameSEMICOLON) {
863                                 getNextToken();
864                         } else {
865                                 if (token != TokenNameINLINE_HTML) {
866                                         throwSyntaxError("';' expected after 'static' statement.");
867                                 }
868                                 getNextToken();
869                         }
870                         return statement;
871                 } else if (token == TokenNameunset) {
872                         getNextToken();
873                         if (token == TokenNameLPAREN) {
874                                 getNextToken();
875                         } else {
876                                 throwSyntaxError("'(' expected after 'unset' statement.");
877                         }
878                         unset_variables();
879                         if (token == TokenNameRPAREN) {
880                                 getNextToken();
881                         } else {
882                                 throwSyntaxError("')' expected after 'unset' statement.");
883                         }
884                         if (token == TokenNameSEMICOLON) {
885                                 getNextToken();
886                         } else {
887                                 if (token != TokenNameINLINE_HTML) {
888                                         throwSyntaxError("';' expected after 'unset' statement.");
889                                 }
890                                 getNextToken();
891                         }
892                         return statement;
893                 } else if (token == TokenNamefunction) {
894                         MethodDeclaration methodDecl = new MethodDeclaration(
895                                         this.compilationUnit.compilationResult);
896                         methodDecl.declarationSourceStart = scanner
897                                         .getCurrentTokenStartPosition();
898                         methodDecl.modifiers = AccDefault;
899                         methodDecl.type = MethodDeclaration.FUNCTION_DEFINITION;
900                         try {
901                                 getNextToken();
902                                 functionDefinition(methodDecl);
903                         } finally {
904                                 sourceEnd = methodDecl.sourceEnd;
905                                 if (sourceEnd <= 0
906                                                 || methodDecl.declarationSourceStart > sourceEnd) {
907                                         sourceEnd = methodDecl.declarationSourceStart + 1;
908                                 }
909                                 methodDecl.declarationSourceEnd = sourceEnd;
910                                 methodDecl.sourceEnd = sourceEnd;
911                         }
912                         return statement;
913                 } else if (token == TokenNamedeclare) {
914                         // T_DECLARE '(' declare_list ')' declare_statement
915                         getNextToken();
916                         if (token != TokenNameLPAREN) {
917                                 throwSyntaxError("'(' expected in 'declare' statement.");
918                         }
919                         getNextToken();
920                         declare_list();
921                         if (token != TokenNameRPAREN) {
922                                 throwSyntaxError("')' expected in 'declare' statement.");
923                         }
924                         getNextToken();
925                         declare_statement();
926                         return statement;
927                 } else if (token == TokenNametry) {
928                         getNextToken();
929                         if (token != TokenNameLBRACE) {
930                                 throwSyntaxError("'{' expected in 'try' statement.");
931                         }
932                         getNextToken();
933                         statementList();
934                         if (token != TokenNameRBRACE) {
935                                 throwSyntaxError("'}' expected in 'try' statement.");
936                         }
937                         getNextToken();
938                         return statement;
939                 } else if (token == TokenNamecatch) {
940                         getNextToken();
941                         if (token != TokenNameLPAREN) {
942                                 throwSyntaxError("'(' expected in 'catch' statement.");
943                         }
944                         getNextToken();
945                         fully_qualified_class_name();
946                         if (token != TokenNameVariable) {
947                                 throwSyntaxError("Variable expected in 'catch' statement.");
948                         }
949                         addVariableSet();
950                         getNextToken();
951                         if (token != TokenNameRPAREN) {
952                                 throwSyntaxError("')' expected in 'catch' statement.");
953                         }
954                         getNextToken();
955                         if (token != TokenNameLBRACE) {
956                                 throwSyntaxError("'{' expected in 'catch' statement.");
957                         }
958                         getNextToken();
959                         if (token != TokenNameRBRACE) {
960                                 statementList();
961                                 if (token != TokenNameRBRACE) {
962                                         throwSyntaxError("'}' expected in 'catch' statement.");
963                                 }
964                         }
965                         getNextToken();
966                         additional_catches();
967                         return statement;
968                 } else if (token == TokenNamethrow) {
969                         getNextToken();
970                         expr();
971                         if (token == TokenNameSEMICOLON) {
972                                 getNextToken();
973                         } else {
974                                 throwSyntaxError("';' expected after 'throw' exxpression.");
975                         }
976                         return statement;
977                 } else if (token == TokenNamefinal || token == TokenNameabstract
978                                 || token == TokenNameclass || token == TokenNameinterface) {
979                         try {
980                                 TypeDeclaration typeDecl = new TypeDeclaration(
981                                                 this.compilationUnit.compilationResult);
982                                 typeDecl.declarationSourceStart = scanner
983                                                 .getCurrentTokenStartPosition();
984                                 typeDecl.declarationSourceEnd = scanner
985                                                 .getCurrentTokenEndPosition();
986                                 typeDecl.name = new char[] { ' ' };
987                                 // default super class
988                                 typeDecl.superclass = new SingleTypeReference(
989                                                 TypeConstants.OBJECT, 0);
990                                 compilationUnit.types.add(typeDecl);
991                                 pushOnAstStack(typeDecl);
992                                 unticked_class_declaration_statement(typeDecl);
993                         } finally {
994                                 // reduce stack:
995                                 astPtr--;
996                                 astLengthPtr--;
997                         }
998                         return statement;
999                         // } else {
1000                         // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1001                 } else if (token == TokenNameLBRACE) {
1002                         getNextToken();
1003                         if (token != TokenNameRBRACE) {
1004                                 statement = statementList();
1005                         }
1006                         if (token == TokenNameRBRACE) {
1007                                 getNextToken();
1008                                 return statement;
1009                         } else {
1010                                 throwSyntaxError("'}' expected.");
1011                         }
1012                 } else {
1013                         if (token != TokenNameSEMICOLON) {
1014                                 expr();
1015                         }
1016                         if (token == TokenNameSEMICOLON) {
1017                                 getNextToken();
1018                                 return statement;
1019                         } else {
1020                                 if (token == TokenNameRBRACE) {
1021                                         reportSyntaxError("';' expected after expression (Found token: "
1022                                                         + scanner.toStringAction(token) + ")");
1023                                 } else {
1024                                         if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
1025                                                 throwSyntaxError("';' expected after expression (Found token: "
1026                                                                 + scanner.toStringAction(token) + ")");
1027                                         }
1028                                         getNextToken();
1029                                 }
1030                         }
1031                 }
1032                 // may be null
1033                 return statement;
1034         }
1035
1036         private void declare_statement() {
1037                 // statement
1038                 // | ':' inner_statement_list T_ENDDECLARE ';'
1039                 // ;
1040                 if (token == TokenNameCOLON) {
1041                         getNextToken();
1042                         // TODO: implement inner_statement_list();
1043                         statementList();
1044                         if (token != TokenNameenddeclare) {
1045                                 throwSyntaxError("'enddeclare' expected in 'declare' statement.");
1046                         }
1047                         getNextToken();
1048                         if (token != TokenNameSEMICOLON) {
1049                                 throwSyntaxError("';' expected after 'enddeclare' keyword.");
1050                         }
1051                         getNextToken();
1052                 } else {
1053                         statement();
1054                 }
1055         }
1056
1057         private void declare_list() {
1058                 // T_STRING '=' static_scalar
1059                 // | declare_list ',' T_STRING '=' static_scalar
1060                 while (true) {
1061                         if (token != TokenNameIdentifier) {
1062                                 throwSyntaxError("Identifier expected in 'declare' list.");
1063                         }
1064                         getNextToken();
1065                         if (token != TokenNameEQUAL) {
1066                                 throwSyntaxError("'=' expected in 'declare' list.");
1067                         }
1068                         getNextToken();
1069                         static_scalar();
1070                         if (token != TokenNameCOMMA) {
1071                                 break;
1072                         }
1073                         getNextToken();
1074                 }
1075         }
1076
1077         private void additional_catches() {
1078                 while (token == TokenNamecatch) {
1079                         getNextToken();
1080                         if (token != TokenNameLPAREN) {
1081                                 throwSyntaxError("'(' expected in 'catch' statement.");
1082                         }
1083                         getNextToken();
1084                         fully_qualified_class_name();
1085                         if (token != TokenNameVariable) {
1086                                 throwSyntaxError("Variable expected in 'catch' statement.");
1087                         }
1088                         addVariableSet();
1089                         getNextToken();
1090                         if (token != TokenNameRPAREN) {
1091                                 throwSyntaxError("')' expected in 'catch' statement.");
1092                         }
1093                         getNextToken();
1094                         if (token != TokenNameLBRACE) {
1095                                 throwSyntaxError("'{' expected in 'catch' statement.");
1096                         }
1097                         getNextToken();
1098                         if (token != TokenNameRBRACE) {
1099                                 statementList();
1100                         }
1101                         if (token != TokenNameRBRACE) {
1102                                 throwSyntaxError("'}' expected in 'catch' statement.");
1103                         }
1104                         getNextToken();
1105                 }
1106         }
1107
1108         private void foreach_variable() {
1109                 // w_variable
1110                 // | '&' w_variable
1111                 if (token == TokenNameAND) {
1112                         getNextToken();
1113                 }
1114                 w_variable(true);
1115         }
1116
1117         private void foreach_optional_arg() {
1118                 // /* empty */
1119                 // | T_DOUBLE_ARROW foreach_variable
1120                 if (token == TokenNameEQUAL_GREATER) {
1121                         getNextToken();
1122                         foreach_variable();
1123                 }
1124         }
1125
1126         private void global_var_list() {
1127                 // global_var_list:
1128                 // global_var_list ',' global_var
1129                 // | global_var
1130                 HashSet set = peekVariableSet();
1131                 while (true) {
1132                         global_var(set);
1133                         if (token != TokenNameCOMMA) {
1134                                 break;
1135                         }
1136                         getNextToken();
1137                 }
1138         }
1139
1140         private void global_var(HashSet set) {
1141                 // global_var:
1142                 // T_VARIABLE
1143                 // | '$' r_variable
1144                 // | '$' '{' expr '}'
1145                 if (token == TokenNameVariable) {
1146                         if (fMethodVariables != null) {
1147                                 VariableInfo info = new VariableInfo(scanner
1148                                                 .getCurrentTokenStartPosition(),
1149                                                 VariableInfo.LEVEL_GLOBAL_VAR);
1150                                 fMethodVariables.put(new String(scanner
1151                                                 .getCurrentIdentifierSource()), info);
1152                         }
1153                         addVariableSet(set);
1154                         getNextToken();
1155                 } else if (token == TokenNameDOLLAR) {
1156                         getNextToken();
1157                         if (token == TokenNameLBRACE) {
1158                                 getNextToken();
1159                                 expr();
1160                                 if (token != TokenNameRBRACE) {
1161                                         throwSyntaxError("'}' expected in global variable.");
1162                                 }
1163                                 getNextToken();
1164                         } else {
1165                                 r_variable();
1166                         }
1167                 }
1168         }
1169
1170         private void static_var_list() {
1171                 // static_var_list:
1172                 // static_var_list ',' T_VARIABLE
1173                 // | static_var_list ',' T_VARIABLE '=' static_scalar
1174                 // | T_VARIABLE
1175                 // | T_VARIABLE '=' static_scalar,
1176                 HashSet set = peekVariableSet();
1177                 while (true) {
1178                         if (token == TokenNameVariable) {
1179                                 if (fMethodVariables != null) {
1180                                         VariableInfo info = new VariableInfo(scanner
1181                                                         .getCurrentTokenStartPosition(),
1182                                                         VariableInfo.LEVEL_STATIC_VAR);
1183                                         fMethodVariables.put(new String(scanner
1184                                                         .getCurrentIdentifierSource()), info);
1185                                 }
1186                                 addVariableSet(set);
1187                                 getNextToken();
1188                                 if (token == TokenNameEQUAL) {
1189                                         getNextToken();
1190                                         static_scalar();
1191                                 }
1192                                 if (token != TokenNameCOMMA) {
1193                                         break;
1194                                 }
1195                                 getNextToken();
1196                         } else {
1197                                 break;
1198                         }
1199                 }
1200         }
1201
1202         private void unset_variables() {
1203                 // unset_variables:
1204                 // unset_variable
1205                 // | unset_variables ',' unset_variable
1206                 // unset_variable:
1207                 // variable
1208                 while (true) {
1209                         variable(false, false);
1210                         if (token != TokenNameCOMMA) {
1211                                 break;
1212                         }
1213                         getNextToken();
1214                 }
1215         }
1216
1217         private final void initializeModifiers() {
1218                 this.modifiers = 0;
1219                 this.modifiersSourceStart = -1;
1220         }
1221
1222         private final void checkAndSetModifiers(int flag) {
1223                 this.modifiers |= flag;
1224                 if (this.modifiersSourceStart < 0)
1225                         this.modifiersSourceStart = this.scanner.startPosition;
1226         }
1227
1228         private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1229                 initializeModifiers();
1230                 if (token == TokenNameinterface) {
1231                         // interface_entry T_STRING
1232                         // interface_extends_list
1233                         // '{' class_statement_list '}'
1234                         checkAndSetModifiers(AccInterface);
1235                         getNextToken();
1236                         typeDecl.modifiers = this.modifiers;
1237                         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1238                         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1239                         if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1240                                 typeDecl.name = scanner.getCurrentIdentifierSource();
1241                                 if (token > TokenNameKEYWORD) {
1242                                         problemReporter.phpKeywordWarning(new String[] { scanner
1243                                                         .toStringAction(token) }, scanner
1244                                                         .getCurrentTokenStartPosition(), scanner
1245                                                         .getCurrentTokenEndPosition(), referenceContext,
1246                                                         compilationUnit.compilationResult);
1247                                         // throwSyntaxError("Don't use a keyword for interface
1248                                         // declaration ["
1249                                         // + scanner.toStringAction(token) + "].",
1250                                         // typeDecl.sourceStart, typeDecl.sourceEnd);
1251                                 }
1252                                 getNextToken();
1253                                 interface_extends_list(typeDecl);
1254                         } else {
1255                                 typeDecl.name = new char[] { ' ' };
1256                                 throwSyntaxError(
1257                                                 "Interface name expected after keyword 'interface'.",
1258                                                 typeDecl.sourceStart, typeDecl.sourceEnd);
1259                                 return;
1260                         }
1261                 } else {
1262                         // class_entry_type T_STRING extends_from
1263                         // implements_list
1264                         // '{' class_statement_list'}'
1265                         class_entry_type();
1266                         typeDecl.modifiers = this.modifiers;
1267                         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1268                         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1269                         // identifier
1270                         // identifier 'extends' identifier
1271                         if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1272                                 typeDecl.name = scanner.getCurrentIdentifierSource();
1273                                 if (token > TokenNameKEYWORD) {
1274                                         problemReporter.phpKeywordWarning(new String[] { scanner
1275                                                         .toStringAction(token) }, scanner
1276                                                         .getCurrentTokenStartPosition(), scanner
1277                                                         .getCurrentTokenEndPosition(), referenceContext,
1278                                                         compilationUnit.compilationResult);
1279                                         // throwSyntaxError("Don't use a keyword for class
1280                                         // declaration [" +
1281                                         // scanner.toStringAction(token) + "].",
1282                                         // typeDecl.sourceStart, typeDecl.sourceEnd);
1283                                 }
1284                                 getNextToken();
1285                                 // extends_from:
1286                                 // /* empty */
1287                                 // | T_EXTENDS fully_qualified_class_name
1288                                 if (token == TokenNameextends) {
1289                                         class_extends_list(typeDecl);
1290                                         // getNextToken();
1291                                         // if (token != TokenNameIdentifier) {
1292                                         // throwSyntaxError("Class name expected after keyword
1293                                         // 'extends'.",
1294                                         // scanner.getCurrentTokenStartPosition(), scanner
1295                                         // .getCurrentTokenEndPosition());
1296                                         // }
1297                                 }
1298                                 implements_list(typeDecl);
1299                         } else {
1300                                 typeDecl.name = new char[] { ' ' };
1301                                 throwSyntaxError("Class name expected after keyword 'class'.",
1302                                                 typeDecl.sourceStart, typeDecl.sourceEnd);
1303                                 return;
1304                         }
1305                 }
1306                 // '{' class_statement_list '}'
1307                 if (token == TokenNameLBRACE) {
1308                         getNextToken();
1309                         if (token != TokenNameRBRACE) {
1310                                 ArrayList list = new ArrayList();
1311                                 class_statement_list(list);
1312                                 typeDecl.fields = new FieldDeclaration[list.size()];
1313                                 for (int i = 0; i < list.size(); i++) {
1314                                         typeDecl.fields[i] = (FieldDeclaration) list.get(i);
1315                                 }
1316                         }
1317                         if (token == TokenNameRBRACE) {
1318                                 typeDecl.declarationSourceEnd = scanner
1319                                                 .getCurrentTokenEndPosition();
1320                                 getNextToken();
1321                         } else {
1322                                 throwSyntaxError("'}' expected at end of class body.");
1323                         }
1324                 } else {
1325                         throwSyntaxError("'{' expected at start of class body.");
1326                 }
1327         }
1328
1329         private void class_entry_type() {
1330                 // T_CLASS
1331                 // | T_ABSTRACT T_CLASS
1332                 // | T_FINAL T_CLASS
1333                 if (token == TokenNameclass) {
1334                         getNextToken();
1335                 } else if (token == TokenNameabstract) {
1336                         checkAndSetModifiers(AccAbstract);
1337                         getNextToken();
1338                         if (token != TokenNameclass) {
1339                                 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1340                         }
1341                         getNextToken();
1342                 } else if (token == TokenNamefinal) {
1343                         checkAndSetModifiers(AccFinal);
1344                         getNextToken();
1345                         if (token != TokenNameclass) {
1346                                 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1347                         }
1348                         getNextToken();
1349                 } else {
1350                         throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1351                 }
1352         }
1353
1354         // private void class_extends(TypeDeclaration typeDecl) {
1355         // // /* empty */
1356         // // | T_EXTENDS interface_list
1357         // if (token == TokenNameextends) {
1358         // getNextToken();
1359         //
1360         // if (token == TokenNameIdentifier) {
1361         // getNextToken();
1362         // } else {
1363         // throwSyntaxError("Class name expected after keyword 'extends'.");
1364         // }
1365         // }
1366         // }
1367
1368         private void interface_extends_list(TypeDeclaration typeDecl) {
1369                 // /* empty */
1370                 // | T_EXTENDS interface_list
1371                 if (token == TokenNameextends) {
1372                         getNextToken();
1373                         interface_list(typeDecl);
1374                 }
1375         }
1376
1377         private void class_extends_list(TypeDeclaration typeDecl) {
1378                 // /* empty */
1379                 // | T_EXTENDS interface_list
1380                 if (token == TokenNameextends) {
1381                         getNextToken();
1382                         class_list(typeDecl);
1383                 }
1384         }
1385
1386         private void implements_list(TypeDeclaration typeDecl) {
1387                 // /* empty */
1388                 // | T_IMPLEMENTS interface_list
1389                 if (token == TokenNameimplements) {
1390                         getNextToken();
1391                         interface_list(typeDecl);
1392                 }
1393         }
1394
1395         private void class_list(TypeDeclaration typeDecl) {
1396                 // class_list:
1397                 // fully_qualified_class_name
1398                 do {
1399                         if (token == TokenNameIdentifier) {
1400                                 char[] ident = scanner.getCurrentIdentifierSource();
1401                                 // TODO make this code working better:
1402                                 // SingleTypeReference ref =
1403                                 // ParserUtil.getTypeReference(scanner,
1404                                 // includesList, ident);
1405                                 // if (ref != null) {
1406                                 // typeDecl.superclass = ref;
1407                                 // }
1408                                 getNextToken();
1409                         } else {
1410                                 throwSyntaxError("Classname expected after keyword 'extends'.");
1411                         }
1412                         if (token == TokenNameCOMMA) {
1413                                 reportSyntaxError("No multiple inheritance allowed. Expected token 'implements' or '{'.");
1414                                 getNextToken();
1415                                 continue;
1416                         } else {
1417                                 break;
1418                         }
1419                 } while (true);
1420         }
1421
1422         private void interface_list(TypeDeclaration typeDecl) {
1423                 // interface_list:
1424                 // fully_qualified_class_name
1425                 // | interface_list ',' fully_qualified_class_name
1426                 do {
1427                         if (token == TokenNameIdentifier) {
1428                                 getNextToken();
1429                         } else {
1430                                 throwSyntaxError("Interfacename expected after keyword 'implements'.");
1431                         }
1432                         if (token != TokenNameCOMMA) {
1433                                 return;
1434                         }
1435                         getNextToken();
1436                 } while (true);
1437         }
1438
1439         // private void classBody(TypeDeclaration typeDecl) {
1440         // //'{' [class-element-list] '}'
1441         // if (token == TokenNameLBRACE) {
1442         // getNextToken();
1443         // if (token != TokenNameRBRACE) {
1444         // class_statement_list();
1445         // }
1446         // if (token == TokenNameRBRACE) {
1447         // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1448         // getNextToken();
1449         // } else {
1450         // throwSyntaxError("'}' expected at end of class body.");
1451         // }
1452         // } else {
1453         // throwSyntaxError("'{' expected at start of class body.");
1454         // }
1455         // }
1456         private void class_statement_list(ArrayList list) {
1457                 do {
1458                         try {
1459                                 class_statement(list);
1460                                 if (token == TokenNamepublic || token == TokenNameprotected
1461                                                 || token == TokenNameprivate
1462                                                 || token == TokenNamestatic
1463                                                 || token == TokenNameabstract
1464                                                 || token == TokenNamefinal
1465                                                 || token == TokenNamefunction || token == TokenNamevar
1466                                                 || token == TokenNameconst) {
1467                                         continue;
1468                                 }
1469                                 if (token == TokenNameRBRACE) {
1470                                         break;
1471                                 }
1472                                 throwSyntaxError("'}' at end of class statement.");
1473                         } catch (SyntaxError sytaxErr1) {
1474                                 boolean tokenize = scanner.tokenizeStrings;
1475                                 if (!tokenize) {
1476                                         scanner.tokenizeStrings = true;
1477                                 }
1478                                 try {
1479                                         // if an error occured,
1480                                         // try to find keywords
1481                                         // to parse the rest of the string
1482                                         while (token != TokenNameEOF) {
1483                                                 if (token == TokenNamepublic
1484                                                                 || token == TokenNameprotected
1485                                                                 || token == TokenNameprivate
1486                                                                 || token == TokenNamestatic
1487                                                                 || token == TokenNameabstract
1488                                                                 || token == TokenNamefinal
1489                                                                 || token == TokenNamefunction
1490                                                                 || token == TokenNamevar
1491                                                                 || token == TokenNameconst) {
1492                                                         break;
1493                                                 }
1494                                                 // System.out.println(scanner.toStringAction(token));
1495                                                 getNextToken();
1496                                         }
1497                                         if (token == TokenNameEOF) {
1498                                                 throw sytaxErr1;
1499                                         }
1500                                 } finally {
1501                                         scanner.tokenizeStrings = tokenize;
1502                                 }
1503                         }
1504                 } while (true);
1505         }
1506
1507         private void class_statement(ArrayList list) {
1508                 // class_statement:
1509                 // variable_modifiers class_variable_declaration ';'
1510                 // | class_constant_declaration ';'
1511                 // | method_modifiers T_FUNCTION is_reference T_STRING
1512                 // '(' parameter_list ')' method_body
1513                 initializeModifiers();
1514                 int declarationSourceStart = scanner.getCurrentTokenStartPosition();
1515
1516                 if (token == TokenNamevar) {
1517                         checkAndSetModifiers(AccPublic);
1518                         problemReporter.phpVarDeprecatedWarning(scanner
1519                                         .getCurrentTokenStartPosition(), scanner
1520                                         .getCurrentTokenEndPosition(), referenceContext,
1521                                         compilationUnit.compilationResult);
1522                         getNextToken();
1523                         class_variable_declaration(declarationSourceStart, list);
1524                 } else if (token == TokenNameconst) {
1525                         checkAndSetModifiers(AccFinal | AccPublic);
1526                         class_constant_declaration(declarationSourceStart, list);
1527                         if (token != TokenNameSEMICOLON) {
1528                                 throwSyntaxError("';' expected after class const declaration.");
1529                         }
1530                         getNextToken();
1531                 } else {
1532                         boolean hasModifiers = member_modifiers();
1533                         if (token == TokenNamefunction) {
1534                                 if (!hasModifiers) {
1535                                         checkAndSetModifiers(AccPublic);
1536                                 }
1537                                 MethodDeclaration methodDecl = new MethodDeclaration(
1538                                                 this.compilationUnit.compilationResult);
1539                                 methodDecl.declarationSourceStart = scanner
1540                                                 .getCurrentTokenStartPosition();
1541                                 methodDecl.modifiers = this.modifiers;
1542                                 methodDecl.type = MethodDeclaration.METHOD_DEFINITION;
1543                                 try {
1544                                         getNextToken();
1545                                         functionDefinition(methodDecl);
1546                                 } finally {
1547                                         int sourceEnd = methodDecl.sourceEnd;
1548                                         if (sourceEnd <= 0
1549                                                         || methodDecl.declarationSourceStart > sourceEnd) {
1550                                                 sourceEnd = methodDecl.declarationSourceStart + 1;
1551                                         }
1552                                         methodDecl.declarationSourceEnd = sourceEnd;
1553                                         methodDecl.sourceEnd = sourceEnd;
1554                                 }
1555                         } else {
1556                                 if (!hasModifiers) {
1557                                         throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1558                                 }
1559                                 class_variable_declaration(declarationSourceStart, list);
1560                         }
1561                 }
1562         }
1563
1564         private void class_constant_declaration(int declarationSourceStart,
1565                         ArrayList list) {
1566                 // class_constant_declaration ',' T_STRING '=' static_scalar
1567                 // | T_CONST T_STRING '=' static_scalar
1568                 if (token != TokenNameconst) {
1569                         throwSyntaxError("'const' keyword expected in class declaration.");
1570                 } else {
1571                         getNextToken();
1572                 }
1573                 while (true) {
1574                         if (token != TokenNameIdentifier) {
1575                                 throwSyntaxError("Identifier expected in class const declaration.");
1576                         }
1577                         FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner
1578                                         .getCurrentIdentifierSource(), scanner
1579                                         .getCurrentTokenStartPosition(), scanner
1580                                         .getCurrentTokenEndPosition());
1581                         fieldDeclaration.modifiers = this.modifiers;
1582                         fieldDeclaration.declarationSourceStart = declarationSourceStart;
1583                         fieldDeclaration.declarationSourceEnd = scanner
1584                                         .getCurrentTokenEndPosition();
1585                         fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1586                         // fieldDeclaration.type
1587                         list.add(fieldDeclaration);
1588                         getNextToken();
1589                         if (token != TokenNameEQUAL) {
1590                                 throwSyntaxError("'=' expected in class const declaration.");
1591                         }
1592                         getNextToken();
1593                         static_scalar();
1594                         if (token != TokenNameCOMMA) {
1595                                 break; // while(true)-loop
1596                         }
1597                         getNextToken();
1598                 }
1599         }
1600
1601         // private void variable_modifiers() {
1602         // // variable_modifiers:
1603         // // non_empty_member_modifiers
1604         // //| T_VAR
1605         // initializeModifiers();
1606         // if (token == TokenNamevar) {
1607         // checkAndSetModifiers(AccPublic);
1608         // reportSyntaxError(
1609         // "Keyword 'var' is deprecated. Please use 'public' 'private' or
1610         // 'protected'
1611         // modifier for field declarations.",
1612         // scanner.getCurrentTokenStartPosition(), scanner
1613         // .getCurrentTokenEndPosition());
1614         // getNextToken();
1615         // } else {
1616         // if (!member_modifiers()) {
1617         // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1618         // field declarations.");
1619         // }
1620         // }
1621         // }
1622         // private void method_modifiers() {
1623         // //method_modifiers:
1624         // // /* empty */
1625         // //| non_empty_member_modifiers
1626         // initializeModifiers();
1627         // if (!member_modifiers()) {
1628         // checkAndSetModifiers(AccPublic);
1629         // }
1630         // }
1631         private boolean member_modifiers() {
1632                 // T_PUBLIC
1633                 // | T_PROTECTED
1634                 // | T_PRIVATE
1635                 // | T_STATIC
1636                 // | T_ABSTRACT
1637                 // | T_FINAL
1638                 boolean foundToken = false;
1639                 while (true) {
1640                         if (token == TokenNamepublic) {
1641                                 checkAndSetModifiers(AccPublic);
1642                                 getNextToken();
1643                                 foundToken = true;
1644                         } else if (token == TokenNameprotected) {
1645                                 checkAndSetModifiers(AccProtected);
1646                                 getNextToken();
1647                                 foundToken = true;
1648                         } else if (token == TokenNameprivate) {
1649                                 checkAndSetModifiers(AccPrivate);
1650                                 getNextToken();
1651                                 foundToken = true;
1652                         } else if (token == TokenNamestatic) {
1653                                 checkAndSetModifiers(AccStatic);
1654                                 getNextToken();
1655                                 foundToken = true;
1656                         } else if (token == TokenNameabstract) {
1657                                 checkAndSetModifiers(AccAbstract);
1658                                 getNextToken();
1659                                 foundToken = true;
1660                         } else if (token == TokenNamefinal) {
1661                                 checkAndSetModifiers(AccFinal);
1662                                 getNextToken();
1663                                 foundToken = true;
1664                         } else {
1665                                 break;
1666                         }
1667                 }
1668                 return foundToken;
1669         }
1670
1671         private void class_variable_declaration(int declarationSourceStart,
1672                         ArrayList list) {
1673                 // class_variable_declaration:
1674                 // class_variable_declaration ',' T_VARIABLE
1675                 // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1676                 // | T_VARIABLE
1677                 // | T_VARIABLE '=' static_scalar
1678                 char[] classVariable;
1679                 do {
1680                         if (token == TokenNameVariable) {
1681                                 classVariable = scanner.getCurrentIdentifierSource();
1682                                 // indexManager.addIdentifierInformation('v', classVariable,
1683                                 // buf, -1,
1684                                 // -1);
1685                                 FieldDeclaration fieldDeclaration = new FieldDeclaration(
1686                                                 classVariable, scanner.getCurrentTokenStartPosition(),
1687                                                 scanner.getCurrentTokenEndPosition());
1688                                 fieldDeclaration.modifiers = this.modifiers;
1689                                 fieldDeclaration.declarationSourceStart = declarationSourceStart;
1690                                 fieldDeclaration.declarationSourceEnd = scanner
1691                                                 .getCurrentTokenEndPosition();
1692                                 fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1693                                 list.add(fieldDeclaration);
1694                                 if (fTypeVariables != null) {
1695                                         VariableInfo info = new VariableInfo(scanner
1696                                                         .getCurrentTokenStartPosition(),
1697                                                         VariableInfo.LEVEL_CLASS_UNIT);
1698                                         fTypeVariables.put(new String(scanner
1699                                                         .getCurrentIdentifierSource()), info);
1700                                 }
1701                                 getNextToken();
1702                                 if (token == TokenNameEQUAL) {
1703                                         getNextToken();
1704                                         static_scalar();
1705                                 }
1706                         } else {
1707                                 // if (token == TokenNamethis) {
1708                                 // throwSyntaxError("'$this' not allowed after keyword 'public'
1709                                 // 'protected' 'private' 'var'.");
1710                                 // }
1711                                 throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1712                         }
1713                         if (token != TokenNameCOMMA) {
1714                                 break;
1715                         }
1716                         getNextToken();
1717                 } while (true);
1718                 if (token != TokenNameSEMICOLON) {
1719                         throwSyntaxError("';' expected after field declaration.");
1720                 }
1721                 getNextToken();
1722         }
1723
1724         private void functionDefinition(MethodDeclaration methodDecl) {
1725                 boolean isAbstract = false;
1726                 if (astPtr == 0) {
1727                         if (compilationUnit != null) {
1728                                 compilationUnit.types.add(methodDecl);
1729                         }
1730                 } else {
1731                         ASTNode node = astStack[astPtr];
1732                         if (node instanceof TypeDeclaration) {
1733                                 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1734                                 if (typeDecl.methods == null) {
1735                                         typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
1736                                 } else {
1737                                         AbstractMethodDeclaration[] newMethods;
1738                                         System
1739                                                         .arraycopy(
1740                                                                         typeDecl.methods,
1741                                                                         0,
1742                                                                         newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1743                                                                         0, typeDecl.methods.length);
1744                                         newMethods[typeDecl.methods.length] = methodDecl;
1745                                         typeDecl.methods = newMethods;
1746                                 }
1747                                 if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
1748                                         isAbstract = true;
1749                                 } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
1750                                         isAbstract = true;
1751                                 }
1752                         }
1753                 }
1754                 try {
1755                         pushFunctionVariableSet();
1756                         functionDeclarator(methodDecl);
1757                         if (token == TokenNameSEMICOLON) {
1758                                 if (!isAbstract) {
1759                                         methodDecl.sourceEnd = scanner
1760                                                         .getCurrentTokenStartPosition() - 1;
1761                                         throwSyntaxError("Body declaration expected for method: "
1762                                                         + new String(methodDecl.selector));
1763                                 }
1764                                 getNextToken();
1765                                 return;
1766                         }
1767                         functionBody(methodDecl);
1768                 } finally {
1769                         if (!fStackUnassigned.isEmpty()) {
1770                                 fStackUnassigned.remove(fStackUnassigned.size() - 1);
1771                         }
1772                 }
1773         }
1774
1775         private void functionDeclarator(MethodDeclaration methodDecl) {
1776                 // identifier '(' [parameter-list] ')'
1777                 if (token == TokenNameAND) {
1778                         getNextToken();
1779                 }
1780                 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1781                 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1782                 if (Scanner.isIdentifierOrKeyword(token)) {
1783                         methodDecl.selector = scanner.getCurrentIdentifierSource();
1784                         if (token > TokenNameKEYWORD) {
1785                                 problemReporter.phpKeywordWarning(new String[] { scanner
1786                                                 .toStringAction(token) }, scanner
1787                                                 .getCurrentTokenStartPosition(), scanner
1788                                                 .getCurrentTokenEndPosition(), referenceContext,
1789                                                 compilationUnit.compilationResult);
1790                         }
1791                         getNextToken();
1792                         if (token == TokenNameLPAREN) {
1793                                 getNextToken();
1794                         } else {
1795                                 methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
1796                                 throwSyntaxError("'(' expected in function declaration.");
1797                         }
1798                         if (token != TokenNameRPAREN) {
1799                                 parameter_list(methodDecl);
1800                         }
1801                         if (token != TokenNameRPAREN) {
1802                                 methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
1803                                 throwSyntaxError("')' expected in function declaration.");
1804                         } else {
1805                                 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1806                                 getNextToken();
1807                         }
1808                 } else {
1809                         methodDecl.selector = "<undefined>".toCharArray();
1810                         methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
1811                         throwSyntaxError("Function name expected after keyword 'function'.");
1812                 }
1813         }
1814
1815         //
1816         private void parameter_list(MethodDeclaration methodDecl) {
1817                 // non_empty_parameter_list
1818                 // | /* empty */
1819                 non_empty_parameter_list(methodDecl, true);
1820         }
1821
1822         private void non_empty_parameter_list(MethodDeclaration methodDecl,
1823                         boolean empty_allowed) {
1824                 // optional_class_type T_VARIABLE
1825                 // | optional_class_type '&' T_VARIABLE
1826                 // | optional_class_type '&' T_VARIABLE '=' static_scalar
1827                 // | optional_class_type T_VARIABLE '=' static_scalar
1828                 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE
1829                 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
1830                 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
1831                 // static_scalar
1832                 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
1833                 // static_scalar
1834                 char[] typeIdentifier = null;
1835                 if (token == TokenNameIdentifier || token == TokenNamearray
1836                                 || token == TokenNameVariable || token == TokenNameAND) {
1837                         HashSet set = peekVariableSet();
1838                         while (true) {
1839                                 if (token == TokenNameIdentifier || token == TokenNamearray) {// feature
1840                                                                                                                                                                 // req.
1841                                                                                                                                                                 // #1254275
1842                                         typeIdentifier = scanner.getCurrentIdentifierSource();
1843                                         getNextToken();
1844                                 }
1845                                 if (token == TokenNameAND) {
1846                                         getNextToken();
1847                                 }
1848                                 if (token == TokenNameVariable) {
1849                                         if (fMethodVariables != null) {
1850                                                 VariableInfo info;
1851                                                 if (methodDecl.type == MethodDeclaration.FUNCTION_DEFINITION) {
1852                                                         info = new VariableInfo(scanner
1853                                                                         .getCurrentTokenStartPosition(),
1854                                                                         VariableInfo.LEVEL_FUNCTION_DEFINITION);
1855                                                 } else {
1856                                                         info = new VariableInfo(scanner
1857                                                                         .getCurrentTokenStartPosition(),
1858                                                                         VariableInfo.LEVEL_METHOD_DEFINITION);
1859                                                 }
1860                                                 info.typeIdentifier = typeIdentifier;
1861                                                 fMethodVariables.put(new String(scanner
1862                                                                 .getCurrentIdentifierSource()), info);
1863                                         }
1864                                         addVariableSet(set);
1865                                         getNextToken();
1866                                         if (token == TokenNameEQUAL) {
1867                                                 getNextToken();
1868                                                 static_scalar();
1869                                         }
1870                                 } else {
1871                                         throwSyntaxError("Variable expected in parameter list.");
1872                                 }
1873                                 if (token != TokenNameCOMMA) {
1874                                         break;
1875                                 }
1876                                 getNextToken();
1877                         }
1878                         return;
1879                 }
1880                 if (!empty_allowed) {
1881                         throwSyntaxError("Identifier expected in parameter list.");
1882                 }
1883         }
1884
1885         private void optional_class_type() {
1886                 // /* empty */
1887                 // | T_STRING
1888         }
1889
1890         // private void parameterDeclaration() {
1891         // //variable
1892         // //variable-reference
1893         // if (token == TokenNameAND) {
1894         // getNextToken();
1895         // if (isVariable()) {
1896         // getNextToken();
1897         // } else {
1898         // throwSyntaxError("Variable expected after reference operator '&'.");
1899         // }
1900         // }
1901         // //variable '=' constant
1902         // if (token == TokenNameVariable) {
1903         // getNextToken();
1904         // if (token == TokenNameEQUAL) {
1905         // getNextToken();
1906         // static_scalar();
1907         // }
1908         // return;
1909         // }
1910         // // if (token == TokenNamethis) {
1911         // // throwSyntaxError("Reserved word '$this' not allowed in parameter
1912         // // declaration.");
1913         // // }
1914         // }
1915
1916         private void labeledStatementList() {
1917                 if (token != TokenNamecase && token != TokenNamedefault) {
1918                         throwSyntaxError("'case' or 'default' expected.");
1919                 }
1920                 do {
1921                         if (token == TokenNamecase) {
1922                                 getNextToken();
1923                                 expr(); // constant();
1924                                 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1925                                         getNextToken();
1926                                         if (token == TokenNameRBRACE) {
1927                                                 // empty case; assumes that the '}' token belongs to the
1928                                                 // wrapping
1929                                                 // switch statement - #1371992
1930                                                 break;
1931                                         }
1932                                         if (token == TokenNamecase || token == TokenNamedefault) {
1933                                                 // empty case statement ?
1934                                                 continue;
1935                                         }
1936                                         statementList();
1937                                 }
1938                                 // else if (token == TokenNameSEMICOLON) {
1939                                 // setMarker(
1940                                 // "':' expected after 'case' keyword (Found token: " +
1941                                 // scanner.toStringAction(token) + ")",
1942                                 // scanner.getCurrentTokenStartPosition(),
1943                                 // scanner.getCurrentTokenEndPosition(),
1944                                 // INFO);
1945                                 // getNextToken();
1946                                 // if (token == TokenNamecase) { // empty case statement ?
1947                                 // continue;
1948                                 // }
1949                                 // statementList();
1950                                 // }
1951                                 else {
1952                                         throwSyntaxError("':' character expected after 'case' constant (Found token: "
1953                                                         + scanner.toStringAction(token) + ")");
1954                                 }
1955                         } else { // TokenNamedefault
1956                                 getNextToken();
1957                                 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1958                                         getNextToken();
1959                                         if (token == TokenNameRBRACE) {
1960                                                 // empty default case; ; assumes that the '}' token
1961                                                 // belongs to the
1962                                                 // wrapping switch statement - #1371992
1963                                                 break;
1964                                         }
1965                                         if (token != TokenNamecase) {
1966                                                 statementList();
1967                                         }
1968                                 } else {
1969                                         throwSyntaxError("':' character expected after 'default'.");
1970                                 }
1971                         }
1972                 } while (token == TokenNamecase || token == TokenNamedefault);
1973         }
1974
1975         private void ifStatementColon(IfStatement iState) {
1976                 // T_IF '(' expr ')' ':' inner_statement_list new_elseif_list
1977                 // new_else_single T_ENDIF ';'
1978                 HashSet assignedVariableSet = null;
1979                 try {
1980                         Block b = inner_statement_list();
1981                         iState.thenStatement = b;
1982                         checkUnreachable(iState, b);
1983                 } finally {
1984                         assignedVariableSet = removeIfVariableSet();
1985                 }
1986                 if (token == TokenNameelseif) {
1987                         try {
1988                                 pushIfVariableSet();
1989                                 new_elseif_list(iState);
1990                         } finally {
1991                                 HashSet set = removeIfVariableSet();
1992                                 if (assignedVariableSet != null && set != null) {
1993                                         assignedVariableSet.addAll(set);
1994                                 }
1995                         }
1996                 }
1997                 try {
1998                         pushIfVariableSet();
1999                         new_else_single(iState);
2000                 } finally {
2001                         HashSet set = removeIfVariableSet();
2002                         if (assignedVariableSet != null) {
2003                                 HashSet topSet = peekVariableSet();
2004                                 if (topSet != null) {
2005                                         if (set != null) {
2006                                                 topSet.addAll(set);
2007                                         }
2008                                         topSet.addAll(assignedVariableSet);
2009                                 }
2010                         }
2011                 }
2012                 if (token != TokenNameendif) {
2013                         throwSyntaxError("'endif' expected.");
2014                 }
2015                 getNextToken();
2016                 if (token != TokenNameSEMICOLON) {
2017                         reportSyntaxError("';' expected after if-statement.");
2018                         iState.sourceEnd = scanner.getCurrentTokenStartPosition();
2019                 } else {
2020                         iState.sourceEnd = scanner.getCurrentTokenEndPosition();
2021                         getNextToken();
2022                 }
2023         }
2024
2025         private void ifStatement(IfStatement iState) {
2026                 // T_IF '(' expr ')' statement elseif_list else_single
2027                 HashSet assignedVariableSet = null;
2028                 try {
2029                         pushIfVariableSet();
2030                         Statement s = statement();
2031                         iState.thenStatement = s;
2032                         checkUnreachable(iState, s);
2033                 } finally {
2034                         assignedVariableSet = removeIfVariableSet();
2035                 }
2036
2037                 if (token == TokenNameelseif) {
2038                         try {
2039                                 pushIfVariableSet();
2040                                 elseif_list(iState);
2041                         } finally {
2042                                 HashSet set = removeIfVariableSet();
2043                                 if (assignedVariableSet != null && set != null) {
2044                                         assignedVariableSet.addAll(set);
2045                                 }
2046                         }
2047                 }
2048                 try {
2049                         pushIfVariableSet();
2050                         else_single(iState);
2051                 } finally {
2052                         HashSet set = removeIfVariableSet();
2053                         if (assignedVariableSet != null) {
2054                                 HashSet topSet = peekVariableSet();
2055                                 if (topSet != null) {
2056                                         if (set != null) {
2057                                                 topSet.addAll(set);
2058                                         }
2059                                         topSet.addAll(assignedVariableSet);
2060                                 }
2061                         }
2062                 }
2063         }
2064
2065         private void elseif_list(IfStatement iState) {
2066                 // /* empty */
2067                 // | elseif_list T_ELSEIF '(' expr ')' statement
2068                 ArrayList conditionList = new ArrayList();
2069                 ArrayList statementList = new ArrayList();
2070                 Expression e;
2071                 Statement s;
2072                 while (token == TokenNameelseif) {
2073                         getNextToken();
2074                         if (token == TokenNameLPAREN) {
2075                                 getNextToken();
2076                         } else {
2077                                 throwSyntaxError("'(' expected after 'elseif' keyword.");
2078                         }
2079                         e = expr();
2080                         conditionList.add(e);
2081                         if (token == TokenNameRPAREN) {
2082                                 getNextToken();
2083                         } else {
2084                                 throwSyntaxError("')' expected after 'elseif' condition.");
2085                         }
2086                         s = statement();
2087                         statementList.add(s);
2088                         checkUnreachable(iState, s);
2089                 }
2090                 iState.elseifConditions = new Expression[conditionList.size()];
2091                 iState.elseifStatements = new Statement[statementList.size()];
2092                 conditionList.toArray(iState.elseifConditions);
2093                 statementList.toArray(iState.elseifStatements);
2094         }
2095
2096         private void new_elseif_list(IfStatement iState) {
2097                 // /* empty */
2098                 // | new_elseif_list T_ELSEIF '(' expr ')' ':' inner_statement_list
2099                 ArrayList conditionList = new ArrayList();
2100                 ArrayList statementList = new ArrayList();
2101                 Expression e;
2102                 Block b;
2103                 while (token == TokenNameelseif) {
2104                         getNextToken();
2105                         if (token == TokenNameLPAREN) {
2106                                 getNextToken();
2107                         } else {
2108                                 throwSyntaxError("'(' expected after 'elseif' keyword.");
2109                         }
2110                         e = expr();
2111                         conditionList.add(e);
2112                         if (token == TokenNameRPAREN) {
2113                                 getNextToken();
2114                         } else {
2115                                 throwSyntaxError("')' expected after 'elseif' condition.");
2116                         }
2117                         if (token == TokenNameCOLON) {
2118                                 getNextToken();
2119                         } else {
2120                                 throwSyntaxError("':' expected after 'elseif' keyword.");
2121                         }
2122                         b = inner_statement_list();
2123                         statementList.add(b);
2124                         checkUnreachable(iState, b);
2125                 }
2126                 iState.elseifConditions = new Expression[conditionList.size()];
2127                 iState.elseifStatements = new Statement[statementList.size()];
2128                 conditionList.toArray(iState.elseifConditions);
2129                 statementList.toArray(iState.elseifStatements);
2130         }
2131
2132         private void else_single(IfStatement iState) {
2133                 // /* empty */
2134                 // T_ELSE statement
2135                 if (token == TokenNameelse) {
2136                         getNextToken();
2137                         Statement s = statement();
2138                         iState.elseStatement = s;
2139                         checkUnreachable(iState, s);
2140                 } else {
2141                         iState.checkUnreachable = false;
2142                 }
2143                 iState.sourceEnd = scanner.getCurrentTokenStartPosition();
2144         }
2145
2146         private void new_else_single(IfStatement iState) {
2147                 // /* empty */
2148                 // | T_ELSE ':' inner_statement_list
2149                 if (token == TokenNameelse) {
2150                         getNextToken();
2151                         if (token == TokenNameCOLON) {
2152                                 getNextToken();
2153                         } else {
2154                                 throwSyntaxError("':' expected after 'else' keyword.");
2155                         }
2156                         Block b = inner_statement_list();
2157                         iState.elseStatement = b;
2158                         checkUnreachable(iState, b);
2159                 } else {
2160                         iState.checkUnreachable = false;
2161                 }
2162         }
2163
2164         private Block inner_statement_list() {
2165                 // inner_statement_list inner_statement
2166                 // /* empty */
2167                 return statementList();
2168         }
2169
2170         /**
2171          * @param iState
2172          * @param b
2173          */
2174         private void checkUnreachable(IfStatement iState, Statement s) {
2175                 if (s instanceof Block) {
2176                         Block b = (Block) s;
2177                         if (b.statements == null || b.statements.length == 0) {
2178                                 iState.checkUnreachable = false;
2179                         } else {
2180                                 int off = b.statements.length - 1;
2181                                 if (!(b.statements[off] instanceof ReturnStatement)
2182                                                 && !(b.statements[off] instanceof ContinueStatement)
2183                                                 && !(b.statements[off] instanceof BreakStatement)) {
2184                                         if (!(b.statements[off] instanceof IfStatement)
2185                                                         || !((IfStatement) b.statements[off]).checkUnreachable) {
2186                                                 iState.checkUnreachable = false;
2187                                         }
2188                                 }
2189                         }
2190                 } else {
2191                         if (!(s instanceof ReturnStatement)
2192                                         && !(s instanceof ContinueStatement)
2193                                         && !(s instanceof BreakStatement)) {
2194                                 if (!(s instanceof IfStatement)
2195                                                 || !((IfStatement) s).checkUnreachable) {
2196                                         iState.checkUnreachable = false;
2197                                 }
2198                         }
2199                 }
2200         }
2201
2202         // private void elseifStatementList() {
2203         // do {
2204         // elseifStatement();
2205         // switch (token) {
2206         // case TokenNameelse:
2207         // getNextToken();
2208         // if (token == TokenNameCOLON) {
2209         // getNextToken();
2210         // if (token != TokenNameendif) {
2211         // statementList();
2212         // }
2213         // return;
2214         // } else {
2215         // if (token == TokenNameif) { //'else if'
2216         // getNextToken();
2217         // } else {
2218         // throwSyntaxError("':' expected after 'else'.");
2219         // }
2220         // }
2221         // break;
2222         // case TokenNameelseif:
2223         // getNextToken();
2224         // break;
2225         // default:
2226         // return;
2227         // }
2228         // } while (true);
2229         // }
2230
2231         // private void elseifStatement() {
2232         // if (token == TokenNameLPAREN) {
2233         // getNextToken();
2234         // expr();
2235         // if (token != TokenNameRPAREN) {
2236         // throwSyntaxError("')' expected in else-if-statement.");
2237         // }
2238         // getNextToken();
2239         // if (token != TokenNameCOLON) {
2240         // throwSyntaxError("':' expected in else-if-statement.");
2241         // }
2242         // getNextToken();
2243         // if (token != TokenNameendif) {
2244         // statementList();
2245         // }
2246         // }
2247         // }
2248
2249         private void switchStatement() {
2250                 if (token == TokenNameCOLON) {
2251                         // ':' [labeled-statement-list] 'endswitch' ';'
2252                         getNextToken();
2253                         labeledStatementList();
2254                         if (token != TokenNameendswitch) {
2255                                 throwSyntaxError("'endswitch' expected.");
2256                         }
2257                         getNextToken();
2258                         if (token != TokenNameSEMICOLON) {
2259                                 throwSyntaxError("';' expected after switch-statement.");
2260                         }
2261                         getNextToken();
2262                 } else {
2263                         // '{' [labeled-statement-list] '}'
2264                         if (token != TokenNameLBRACE) {
2265                                 throwSyntaxError("'{' expected in switch statement.");
2266                         }
2267                         getNextToken();
2268                         if (token != TokenNameRBRACE) {
2269                                 labeledStatementList();
2270                         }
2271                         if (token != TokenNameRBRACE) {
2272                                 throwSyntaxError("'}' expected in switch statement.");
2273                         }
2274                         getNextToken();
2275                 }
2276         }
2277
2278         private void forStatement() {
2279                 if (token == TokenNameCOLON) {
2280                         getNextToken();
2281                         statementList();
2282                         if (token != TokenNameendfor) {
2283                                 throwSyntaxError("'endfor' expected.");
2284                         }
2285                         getNextToken();
2286                         if (token != TokenNameSEMICOLON) {
2287                                 throwSyntaxError("';' expected after for-statement.");
2288                         }
2289                         getNextToken();
2290                 } else {
2291                         statement();
2292                 }
2293         }
2294
2295         private void whileStatement() {
2296                 // ':' statement-list 'endwhile' ';'
2297                 if (token == TokenNameCOLON) {
2298                         getNextToken();
2299                         statementList();
2300                         if (token != TokenNameendwhile) {
2301                                 throwSyntaxError("'endwhile' expected.");
2302                         }
2303                         getNextToken();
2304                         if (token != TokenNameSEMICOLON) {
2305                                 throwSyntaxError("';' expected after while-statement.");
2306                         }
2307                         getNextToken();
2308                 } else {
2309                         statement();
2310                 }
2311         }
2312
2313         private void foreachStatement() {
2314                 if (token == TokenNameCOLON) {
2315                         getNextToken();
2316                         statementList();
2317                         if (token != TokenNameendforeach) {
2318                                 throwSyntaxError("'endforeach' expected.");
2319                         }
2320                         getNextToken();
2321                         if (token != TokenNameSEMICOLON) {
2322                                 throwSyntaxError("';' expected after foreach-statement.");
2323                         }
2324                         getNextToken();
2325                 } else {
2326                         statement();
2327                 }
2328         }
2329
2330         // private void exitStatus() {
2331         // if (token == TokenNameLPAREN) {
2332         // getNextToken();
2333         // } else {
2334         // throwSyntaxError("'(' expected in 'exit-status'.");
2335         // }
2336         // if (token != TokenNameRPAREN) {
2337         // expression();
2338         // }
2339         // if (token == TokenNameRPAREN) {
2340         // getNextToken();
2341         // } else {
2342         // throwSyntaxError("')' expected after 'exit-status'.");
2343         // }
2344         // }
2345         private void expressionList() {
2346                 do {
2347                         expr();
2348                         if (token == TokenNameCOMMA) {
2349                                 getNextToken();
2350                         } else {
2351                                 break;
2352                         }
2353                 } while (true);
2354         }
2355
2356         private Expression expr() {
2357                 // r_variable
2358                 // | expr_without_variable
2359                 // if (token!=TokenNameEOF) {
2360                 if (Scanner.TRACE) {
2361                         System.out.println("TRACE: expr()");
2362                 }
2363                 return expr_without_variable(true, null);
2364                 // }
2365         }
2366
2367         private Expression expr_without_variable(boolean only_variable,
2368                         UninitializedVariableHandler initHandler) {
2369                 int exprSourceStart = scanner.getCurrentTokenStartPosition();
2370                 int exprSourceEnd = scanner.getCurrentTokenEndPosition();
2371                 Expression expression = new Expression();
2372                 expression.sourceStart = exprSourceStart;
2373                 // default, may be overwritten
2374                 expression.sourceEnd = exprSourceEnd;
2375                 try {
2376                         // internal_functions_in_yacc
2377                         // | T_CLONE expr
2378                         // | T_PRINT expr
2379                         // | '(' expr ')'
2380                         // | '@' expr
2381                         // | '+' expr
2382                         // | '-' expr
2383                         // | '!' expr
2384                         // | '~' expr
2385                         // | T_INC rw_variable
2386                         // | T_DEC rw_variable
2387                         // | T_INT_CAST expr
2388                         // | T_DOUBLE_CAST expr
2389                         // | T_STRING_CAST expr
2390                         // | T_ARRAY_CAST expr
2391                         // | T_OBJECT_CAST expr
2392                         // | T_BOOL_CAST expr
2393                         // | T_UNSET_CAST expr
2394                         // | T_EXIT exit_expr
2395                         // | scalar
2396                         // | T_ARRAY '(' array_pair_list ')'
2397                         // | '`' encaps_list '`'
2398                         // | T_LIST '(' assignment_list ')' '=' expr
2399                         // | T_NEW class_name_reference ctor_arguments
2400                         // | variable '=' expr
2401                         // | variable '=' '&' variable
2402                         // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2403                         // | variable T_PLUS_EQUAL expr
2404                         // | variable T_MINUS_EQUAL expr
2405                         // | variable T_MUL_EQUAL expr
2406                         // | variable T_DIV_EQUAL expr
2407                         // | variable T_CONCAT_EQUAL expr
2408                         // | variable T_MOD_EQUAL expr
2409                         // | variable T_AND_EQUAL expr
2410                         // | variable T_OR_EQUAL expr
2411                         // | variable T_XOR_EQUAL expr
2412                         // | variable T_SL_EQUAL expr
2413                         // | variable T_SR_EQUAL expr
2414                         // | rw_variable T_INC
2415                         // | rw_variable T_DEC
2416                         // | expr T_BOOLEAN_OR expr
2417                         // | expr T_BOOLEAN_AND expr
2418                         // | expr T_LOGICAL_OR expr
2419                         // | expr T_LOGICAL_AND expr
2420                         // | expr T_LOGICAL_XOR expr
2421                         // | expr '|' expr
2422                         // | expr '&' expr
2423                         // | expr '^' expr
2424                         // | expr '.' expr
2425                         // | expr '+' expr
2426                         // | expr '-' expr
2427                         // | expr '*' expr
2428                         // | expr '/' expr
2429                         // | expr '%' expr
2430                         // | expr T_SL expr
2431                         // | expr T_SR expr
2432                         // | expr T_IS_IDENTICAL expr
2433                         // | expr T_IS_NOT_IDENTICAL expr
2434                         // | expr T_IS_EQUAL expr
2435                         // | expr T_IS_NOT_EQUAL expr
2436                         // | expr '<' expr
2437                         // | expr T_IS_SMALLER_OR_EQUAL expr
2438                         // | expr '>' expr
2439                         // | expr T_IS_GREATER_OR_EQUAL expr
2440                         // | expr T_INSTANCEOF class_name_reference
2441                         // | expr '?' expr ':' expr
2442                         if (Scanner.TRACE) {
2443                                 System.out.println("TRACE: expr_without_variable() PART 1");
2444                         }
2445                         switch (token) {
2446                         case TokenNameisset:
2447                                 // T_ISSET '(' isset_variables ')'
2448                                 getNextToken();
2449                                 if (token != TokenNameLPAREN) {
2450                                         throwSyntaxError("'(' expected after keyword 'isset'");
2451                                 }
2452                                 getNextToken();
2453                                 isset_variables();
2454                                 if (token != TokenNameRPAREN) {
2455                                         throwSyntaxError("')' expected after keyword 'isset'");
2456                                 }
2457                                 getNextToken();
2458                                 break;
2459                         case TokenNameempty:
2460                                 getNextToken();
2461                                 if (token != TokenNameLPAREN) {
2462                                         throwSyntaxError("'(' expected after keyword 'empty'");
2463                                 }
2464                                 getNextToken();
2465                                 variable(true, false);
2466                                 if (token != TokenNameRPAREN) {
2467                                         throwSyntaxError("')' expected after keyword 'empty'");
2468                                 }
2469                                 getNextToken();
2470                                 break;
2471                         case TokenNameeval:
2472                         case TokenNameinclude:
2473                         case TokenNameinclude_once:
2474                         case TokenNamerequire:
2475                         case TokenNamerequire_once:
2476                                 internal_functions_in_yacc();
2477                                 break;
2478                         // | '(' expr ')'
2479                         case TokenNameLPAREN:
2480                                 getNextToken();
2481                                 expr();
2482                                 if (token == TokenNameRPAREN) {
2483                                         getNextToken();
2484                                 } else {
2485                                         throwSyntaxError("')' expected in expression.");
2486                                 }
2487                                 break;
2488                         // | T_CLONE expr
2489                         // | T_PRINT expr
2490                         // | '@' expr
2491                         // | '+' expr
2492                         // | '-' expr
2493                         // | '!' expr
2494                         // | '~' expr
2495                         // | T_INT_CAST expr
2496                         // | T_DOUBLE_CAST expr
2497                         // | T_STRING_CAST expr
2498                         // | T_ARRAY_CAST expr
2499                         // | T_OBJECT_CAST expr
2500                         // | T_BOOL_CAST expr
2501                         // | T_UNSET_CAST expr
2502                         case TokenNameclone:
2503                         case TokenNameprint:
2504                         case TokenNameAT:
2505                         case TokenNamePLUS:
2506                         case TokenNameMINUS:
2507                         case TokenNameNOT:
2508                         case TokenNameTWIDDLE:
2509                         case TokenNameintCAST:
2510                         case TokenNamedoubleCAST:
2511                         case TokenNamestringCAST:
2512                         case TokenNamearrayCAST:
2513                         case TokenNameobjectCAST:
2514                         case TokenNameboolCAST:
2515                         case TokenNameunsetCAST:
2516                                 getNextToken();
2517                                 expr();
2518                                 break;
2519                         case TokenNameexit:
2520                                 getNextToken();
2521                                 exit_expr();
2522                                 break;
2523                         // scalar:
2524                         // T_STRING
2525                         // | T_STRING_VARNAME
2526                         // | class_constant
2527                         // | T_START_HEREDOC encaps_list T_END_HEREDOC
2528                         // | '`' encaps_list '`'
2529                         // | common_scalar
2530                         // | '`' encaps_list '`'
2531                         // case TokenNameEncapsedString0:
2532                         // scanner.encapsedStringStack.push(new Character('`'));
2533                         // getNextToken();
2534                         // try {
2535                         // if (token == TokenNameEncapsedString0) {
2536                         // } else {
2537                         // encaps_list();
2538                         // if (token != TokenNameEncapsedString0) {
2539                         // throwSyntaxError("\'`\' expected at end of string" + "(Found
2540                         // token: " +
2541                         // scanner.toStringAction(token) + " )");
2542                         // }
2543                         // }
2544                         // } finally {
2545                         // scanner.encapsedStringStack.pop();
2546                         // getNextToken();
2547                         // }
2548                         // break;
2549                         // // | '\'' encaps_list '\''
2550                         // case TokenNameEncapsedString1:
2551                         // scanner.encapsedStringStack.push(new Character('\''));
2552                         // getNextToken();
2553                         // try {
2554                         // exprSourceStart = scanner.getCurrentTokenStartPosition();
2555                         // if (token == TokenNameEncapsedString1) {
2556                         // expression = new
2557                         // StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
2558                         // exprSourceStart, scanner
2559                         // .getCurrentTokenEndPosition());
2560                         // } else {
2561                         // encaps_list();
2562                         // if (token != TokenNameEncapsedString1) {
2563                         // throwSyntaxError("\'\'\' expected at end of string" + "(Found
2564                         // token: "
2565                         // + scanner.toStringAction(token) + " )");
2566                         // } else {
2567                         // expression = new
2568                         // StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
2569                         // exprSourceStart, scanner
2570                         // .getCurrentTokenEndPosition());
2571                         // }
2572                         // }
2573                         // } finally {
2574                         // scanner.encapsedStringStack.pop();
2575                         // getNextToken();
2576                         // }
2577                         // break;
2578                         // //| '"' encaps_list '"'
2579                         // case TokenNameEncapsedString2:
2580                         // scanner.encapsedStringStack.push(new Character('"'));
2581                         // getNextToken();
2582                         // try {
2583                         // exprSourceStart = scanner.getCurrentTokenStartPosition();
2584                         // if (token == TokenNameEncapsedString2) {
2585                         // expression = new
2586                         // StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
2587                         // exprSourceStart, scanner
2588                         // .getCurrentTokenEndPosition());
2589                         // } else {
2590                         // encaps_list();
2591                         // if (token != TokenNameEncapsedString2) {
2592                         // throwSyntaxError("'\"' expected at end of string" + "(Found
2593                         // token: " +
2594                         // scanner.toStringAction(token) + " )");
2595                         // } else {
2596                         // expression = new
2597                         // StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
2598                         // exprSourceStart, scanner
2599                         // .getCurrentTokenEndPosition());
2600                         // }
2601                         // }
2602                         // } finally {
2603                         // scanner.encapsedStringStack.pop();
2604                         // getNextToken();
2605                         // }
2606                         // break;
2607                         case TokenNameStringDoubleQuote:
2608                                 expression = new StringLiteralDQ(scanner
2609                                                 .getCurrentStringLiteralSource(), scanner
2610                                                 .getCurrentTokenStartPosition(), scanner
2611                                                 .getCurrentTokenEndPosition());
2612                                 common_scalar();
2613                                 break;
2614                         case TokenNameStringSingleQuote:
2615                                 expression = new StringLiteralSQ(scanner
2616                                                 .getCurrentStringLiteralSource(), scanner
2617                                                 .getCurrentTokenStartPosition(), scanner
2618                                                 .getCurrentTokenEndPosition());
2619                                 common_scalar();
2620                                 break;
2621                         case TokenNameIntegerLiteral:
2622                         case TokenNameDoubleLiteral:
2623                         case TokenNameStringInterpolated:
2624                         case TokenNameFILE:
2625                         case TokenNameLINE:
2626                         case TokenNameCLASS_C:
2627                         case TokenNameMETHOD_C:
2628                         case TokenNameFUNC_C:
2629                                 common_scalar();
2630                                 break;
2631                         case TokenNameHEREDOC:
2632                                 getNextToken();
2633                                 break;
2634                         case TokenNamearray:
2635                                 // T_ARRAY '(' array_pair_list ')'
2636                                 getNextToken();
2637                                 if (token == TokenNameLPAREN) {
2638                                         getNextToken();
2639                                         if (token == TokenNameRPAREN) {
2640                                                 getNextToken();
2641                                                 break;
2642                                         }
2643                                         array_pair_list();
2644                                         if (token != TokenNameRPAREN) {
2645                                                 throwSyntaxError("')' or ',' expected after keyword 'array'"
2646                                                                 + "(Found token: "
2647                                                                 + scanner.toStringAction(token) + ")");
2648                                         }
2649                                         getNextToken();
2650                                 } else {
2651                                         throwSyntaxError("'(' expected after keyword 'array'"
2652                                                         + "(Found token: " + scanner.toStringAction(token)
2653                                                         + ")");
2654                                 }
2655                                 break;
2656                         case TokenNamelist:
2657                                 // | T_LIST '(' assignment_list ')' '=' expr
2658                                 getNextToken();
2659                                 if (token == TokenNameLPAREN) {
2660                                         getNextToken();
2661                                         assignment_list();
2662                                         if (token != TokenNameRPAREN) {
2663                                                 throwSyntaxError("')' expected after 'list' keyword.");
2664                                         }
2665                                         getNextToken();
2666                                         if (token != TokenNameEQUAL) {
2667                                                 throwSyntaxError("'=' expected after 'list' keyword.");
2668                                         }
2669                                         getNextToken();
2670                                         expr();
2671                                 } else {
2672                                         throwSyntaxError("'(' expected after 'list' keyword.");
2673                                 }
2674                                 break;
2675                         case TokenNamenew:
2676                                 // | T_NEW class_name_reference ctor_arguments
2677                                 getNextToken();
2678                                 Expression typeRef = class_name_reference();
2679                                 ctor_arguments();
2680                                 if (typeRef != null) {
2681                                         expression = typeRef;
2682                                 }
2683                                 break;
2684                         // | T_INC rw_variable
2685                         // | T_DEC rw_variable
2686                         case TokenNamePLUS_PLUS:
2687                         case TokenNameMINUS_MINUS:
2688                                 getNextToken();
2689                                 rw_variable();
2690                                 break;
2691                         // | variable '=' expr
2692                         // | variable '=' '&' variable
2693                         // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2694                         // | variable T_PLUS_EQUAL expr
2695                         // | variable T_MINUS_EQUAL expr
2696                         // | variable T_MUL_EQUAL expr
2697                         // | variable T_DIV_EQUAL expr
2698                         // | variable T_CONCAT_EQUAL expr
2699                         // | variable T_MOD_EQUAL expr
2700                         // | variable T_AND_EQUAL expr
2701                         // | variable T_OR_EQUAL expr
2702                         // | variable T_XOR_EQUAL expr
2703                         // | variable T_SL_EQUAL expr
2704                         // | variable T_SR_EQUAL expr
2705                         // | rw_variable T_INC
2706                         // | rw_variable T_DEC
2707                         case TokenNameIdentifier:
2708                         case TokenNameVariable:
2709                         case TokenNameDOLLAR:
2710                                 Expression lhs = null;
2711                                 boolean rememberedVar = false;
2712                                 if (token == TokenNameIdentifier) {
2713                                         lhs = identifier(true, true);
2714                                         if (lhs != null) {
2715                                                 expression = lhs;
2716                                         }
2717                                 } else {
2718                                         lhs = variable(true, true);
2719                                         if (lhs != null) {
2720                                                 expression = lhs;
2721                                         }
2722                                         if (lhs != null && lhs instanceof FieldReference
2723                                                         && token != TokenNameEQUAL
2724                                                         && token != TokenNamePLUS_EQUAL
2725                                                         && token != TokenNameMINUS_EQUAL
2726                                                         && token != TokenNameMULTIPLY_EQUAL
2727                                                         && token != TokenNameDIVIDE_EQUAL
2728                                                         && token != TokenNameDOT_EQUAL
2729                                                         && token != TokenNameREMAINDER_EQUAL
2730                                                         && token != TokenNameAND_EQUAL
2731                                                         && token != TokenNameOR_EQUAL
2732                                                         && token != TokenNameXOR_EQUAL
2733                                                         && token != TokenNameRIGHT_SHIFT_EQUAL
2734                                                         && token != TokenNameLEFT_SHIFT_EQUAL) {
2735                                                 FieldReference ref = (FieldReference) lhs;
2736                                                 if (!containsVariableSet(ref.token)) {
2737                                                         if (null == initHandler
2738                                                                         || initHandler.reportError()) {
2739                                                                 problemReporter.uninitializedLocalVariable(
2740                                                                                 new String(ref.token), ref.sourceStart,
2741                                                                                 ref.sourceEnd, referenceContext,
2742                                                                                 compilationUnit.compilationResult);
2743                                                         }
2744                                                         addVariableSet(ref.token);
2745                                                 }
2746                                         }
2747                                 }
2748                                 switch (token) {
2749                                 case TokenNameEQUAL:
2750                                         if (lhs != null && lhs instanceof FieldReference) {
2751                                                 addVariableSet(((FieldReference) lhs).token);
2752                                         }
2753                                         getNextToken();
2754                                         if (token == TokenNameAND) {
2755                                                 getNextToken();
2756                                                 if (token == TokenNamenew) {
2757                                                         // | variable '=' '&' T_NEW class_name_reference
2758                                                         // ctor_arguments
2759                                                         getNextToken();
2760                                                         SingleTypeReference classRef = class_name_reference();
2761                                                         ctor_arguments();
2762                                                         if (classRef != null) {
2763                                                                 if (lhs != null
2764                                                                                 && lhs instanceof FieldReference) {
2765                                                                         // example:
2766                                                                         // $var = & new Object();
2767                                                                         if (fMethodVariables != null) {
2768                                                                                 VariableInfo lhsInfo = new VariableInfo(
2769                                                                                                 ((FieldReference) lhs).sourceStart);
2770                                                                                 lhsInfo.reference = classRef;
2771                                                                                 lhsInfo.typeIdentifier = classRef.token;
2772                                                                                 fMethodVariables.put(new String(
2773                                                                                                 ((FieldReference) lhs).token),
2774                                                                                                 lhsInfo);
2775                                                                                 rememberedVar = true;
2776                                                                         }
2777                                                                 }
2778                                                         }
2779                                                 } else {
2780                                                         Expression rhs = variable(false, false);
2781                                                         if (rhs != null && rhs instanceof FieldReference
2782                                                                         && lhs != null
2783                                                                         && lhs instanceof FieldReference) {
2784                                                                 // example:
2785                                                                 // $var = &$ref;
2786                                                                 if (fMethodVariables != null) {
2787                                                                         VariableInfo rhsInfo = (VariableInfo) fMethodVariables
2788                                                                                         .get(((FieldReference) rhs).token);
2789                                                                         if (rhsInfo != null
2790                                                                                         && rhsInfo.reference != null) {
2791                                                                                 VariableInfo lhsInfo = new VariableInfo(
2792                                                                                                 ((FieldReference) lhs).sourceStart);
2793                                                                                 lhsInfo.reference = rhsInfo.reference;
2794                                                                                 lhsInfo.typeIdentifier = rhsInfo.typeIdentifier;
2795                                                                                 fMethodVariables.put(new String(
2796                                                                                                 ((FieldReference) lhs).token),
2797                                                                                                 lhsInfo);
2798                                                                                 rememberedVar = true;
2799                                                                         }
2800                                                                 }
2801                                                         }
2802                                                 }
2803                                         } else {
2804                                                 Expression rhs = expr();
2805                                                 if (lhs != null && lhs instanceof FieldReference) {
2806                                                         if (rhs != null && rhs instanceof FieldReference) {
2807                                                                 // example:
2808                                                                 // $var = $ref;
2809                                                                 if (fMethodVariables != null) {
2810                                                                         VariableInfo rhsInfo = (VariableInfo) fMethodVariables
2811                                                                                         .get(((FieldReference) rhs).token);
2812                                                                         if (rhsInfo != null
2813                                                                                         && rhsInfo.reference != null) {
2814                                                                                 VariableInfo lhsInfo = new VariableInfo(
2815                                                                                                 ((FieldReference) lhs).sourceStart);
2816                                                                                 lhsInfo.reference = rhsInfo.reference;
2817                                                                                 lhsInfo.typeIdentifier = rhsInfo.typeIdentifier;
2818                                                                                 fMethodVariables.put(new String(
2819                                                                                                 ((FieldReference) lhs).token),
2820                                                                                                 lhsInfo);
2821                                                                                 rememberedVar = true;
2822                                                                         }
2823                                                                 }
2824                                                         } else if (rhs != null
2825                                                                         && rhs instanceof SingleTypeReference) {
2826                                                                 // example:
2827                                                                 // $var = new Object();
2828                                                                 if (fMethodVariables != null) {
2829                                                                         VariableInfo lhsInfo = new VariableInfo(
2830                                                                                         ((FieldReference) lhs).sourceStart);
2831                                                                         lhsInfo.reference = (SingleTypeReference) rhs;
2832                                                                         lhsInfo.typeIdentifier = ((SingleTypeReference) rhs).token;
2833                                                                         fMethodVariables.put(new String(
2834                                                                                         ((FieldReference) lhs).token),
2835                                                                                         lhsInfo);
2836                                                                         rememberedVar = true;
2837                                                                 }
2838                                                         }
2839                                                 }
2840                                         }
2841                                         if (rememberedVar == false && lhs != null
2842                                                         && lhs instanceof FieldReference) {
2843                                                 if (fMethodVariables != null) {
2844                                                         VariableInfo lhsInfo = new VariableInfo(
2845                                                                         ((FieldReference) lhs).sourceStart);
2846                                                         fMethodVariables.put(new String(
2847                                                                         ((FieldReference) lhs).token), lhsInfo);
2848                                                 }
2849                                         }
2850                                         break;
2851                                 case TokenNamePLUS_EQUAL:
2852                                 case TokenNameMINUS_EQUAL:
2853                                 case TokenNameMULTIPLY_EQUAL:
2854                                 case TokenNameDIVIDE_EQUAL:
2855                                 case TokenNameDOT_EQUAL:
2856                                 case TokenNameREMAINDER_EQUAL:
2857                                 case TokenNameAND_EQUAL:
2858                                 case TokenNameOR_EQUAL:
2859                                 case TokenNameXOR_EQUAL:
2860                                 case TokenNameRIGHT_SHIFT_EQUAL:
2861                                 case TokenNameLEFT_SHIFT_EQUAL:
2862                                         if (lhs != null && lhs instanceof FieldReference) {
2863                                                 addVariableSet(((FieldReference) lhs).token);
2864                                         }
2865                                         getNextToken();
2866                                         expr();
2867                                         break;
2868                                 case TokenNamePLUS_PLUS:
2869                                 case TokenNameMINUS_MINUS:
2870                                         getNextToken();
2871                                         break;
2872                                 default:
2873                                         if (!only_variable) {
2874                                                 throwSyntaxError("Variable expression not allowed (found token '"
2875                                                                 + scanner.toStringAction(token) + "').");
2876                                         }
2877                                         if (lhs != null) {
2878                                                 expression = lhs;
2879                                         }
2880                                 }
2881                                 break;
2882                         default:
2883                                 if (token != TokenNameINLINE_HTML) {
2884                                         if (token > TokenNameKEYWORD) {
2885                                                 getNextToken();
2886                                                 break;
2887                                         } else {
2888                                                 // System.out.println(scanner.getCurrentTokenStartPosition());
2889                                                 // System.out.println(scanner.getCurrentTokenEndPosition());
2890
2891                                                 throwSyntaxError("Error in expression (found token '"
2892                                                                 + scanner.toStringAction(token) + "').");
2893                                         }
2894                                 }
2895                                 return expression;
2896                         }
2897                         if (Scanner.TRACE) {
2898                                 System.out.println("TRACE: expr_without_variable() PART 2");
2899                         }
2900                         // | expr T_BOOLEAN_OR expr
2901                         // | expr T_BOOLEAN_AND expr
2902                         // | expr T_LOGICAL_OR expr
2903                         // | expr T_LOGICAL_AND expr
2904                         // | expr T_LOGICAL_XOR expr
2905                         // | expr '|' expr
2906                         // | expr '&' expr
2907                         // | expr '^' expr
2908                         // | expr '.' expr
2909                         // | expr '+' expr
2910                         // | expr '-' expr
2911                         // | expr '*' expr
2912                         // | expr '/' expr
2913                         // | expr '%' expr
2914                         // | expr T_SL expr
2915                         // | expr T_SR expr
2916                         // | expr T_IS_IDENTICAL expr
2917                         // | expr T_IS_NOT_IDENTICAL expr
2918                         // | expr T_IS_EQUAL expr
2919                         // | expr T_IS_NOT_EQUAL expr
2920                         // | expr '<' expr
2921                         // | expr T_IS_SMALLER_OR_EQUAL expr
2922                         // | expr '>' expr
2923                         // | expr T_IS_GREATER_OR_EQUAL expr
2924                         while (true) {
2925                                 switch (token) {
2926                                 case TokenNameOR_OR:
2927                                         getNextToken();
2928                                         expression = new OR_OR_Expression(expression, expr(), token);
2929                                         break;
2930                                 case TokenNameAND_AND:
2931                                         getNextToken();
2932                                         expression = new AND_AND_Expression(expression, expr(),
2933                                                         token);
2934                                         break;
2935                                 case TokenNameEQUAL_EQUAL:
2936                                         getNextToken();
2937                                         expression = new EqualExpression(expression, expr(), token);
2938                                         break;
2939                                 case TokenNameand:
2940                                 case TokenNameor:
2941                                 case TokenNamexor:
2942                                 case TokenNameAND:
2943                                 case TokenNameOR:
2944                                 case TokenNameXOR:
2945                                 case TokenNameDOT:
2946                                 case TokenNamePLUS:
2947                                 case TokenNameMINUS:
2948                                 case TokenNameMULTIPLY:
2949                                 case TokenNameDIVIDE:
2950                                 case TokenNameREMAINDER:
2951                                 case TokenNameLEFT_SHIFT:
2952                                 case TokenNameRIGHT_SHIFT:
2953                                 case TokenNameEQUAL_EQUAL_EQUAL:
2954                                 case TokenNameNOT_EQUAL_EQUAL:
2955                                 case TokenNameNOT_EQUAL:
2956                                 case TokenNameLESS:
2957                                 case TokenNameLESS_EQUAL:
2958                                 case TokenNameGREATER:
2959                                 case TokenNameGREATER_EQUAL:
2960                                         getNextToken();
2961                                         expression = new BinaryExpression(expression, expr(), token);
2962                                         break;
2963                                 // | expr T_INSTANCEOF class_name_reference
2964                                 // | expr '?' expr ':' expr
2965                                 case TokenNameinstanceof:
2966                                         getNextToken();
2967                                         TypeReference classRef = class_name_reference();
2968                                         if (classRef != null) {
2969                                                 expression = new InstanceOfExpression(expression,
2970                                                                 classRef, OperatorIds.INSTANCEOF);
2971                                                 expression.sourceStart = exprSourceStart;
2972                                                 expression.sourceEnd = scanner
2973                                                                 .getCurrentTokenEndPosition();
2974                                         }
2975                                         break;
2976                                 case TokenNameQUESTION:
2977                                         getNextToken();
2978                                         Expression valueIfTrue = expr();
2979                                         if (token != TokenNameCOLON) {
2980                                                 throwSyntaxError("':' expected in conditional expression.");
2981                                         }
2982                                         getNextToken();
2983                                         Expression valueIfFalse = expr();
2984
2985                                         expression = new ConditionalExpression(expression,
2986                                                         valueIfTrue, valueIfFalse);
2987                                         break;
2988                                 default:
2989                                         return expression;
2990                                 }
2991                         }
2992                 } catch (SyntaxError e) {
2993                         // try to find next token after expression with errors:
2994                         if (token == TokenNameSEMICOLON) {
2995                                 getNextToken();
2996                                 return expression;
2997                         }
2998                         if (token == TokenNameRBRACE || token == TokenNameRPAREN
2999                                         || token == TokenNameRBRACKET) {
3000                                 getNextToken();
3001                                 return expression;
3002                         }
3003                         throw e;
3004                 }
3005         }
3006
3007         private SingleTypeReference class_name_reference() {
3008                 // class_name_reference:
3009                 // T_STRING
3010                 // | dynamic_class_name_reference
3011                 SingleTypeReference ref = null;
3012                 if (Scanner.TRACE) {
3013                         System.out.println("TRACE: class_name_reference()");
3014                 }
3015                 if (token == TokenNameIdentifier) {
3016                         ref = new SingleTypeReference(scanner.getCurrentIdentifierSource(),
3017                                         scanner.getCurrentTokenStartPosition());
3018                         getNextToken();
3019                 } else {
3020                         ref = null;
3021                         dynamic_class_name_reference();
3022                 }
3023                 return ref;
3024         }
3025
3026         private void dynamic_class_name_reference() {
3027                 // dynamic_class_name_reference:
3028                 // base_variable T_OBJECT_OPERATOR object_property
3029                 // dynamic_class_name_variable_properties
3030                 // | base_variable
3031                 if (Scanner.TRACE) {
3032                         System.out.println("TRACE: dynamic_class_name_reference()");
3033                 }
3034                 base_variable(true);
3035                 if (token == TokenNameMINUS_GREATER) {
3036                         getNextToken();
3037                         object_property();
3038                         dynamic_class_name_variable_properties();
3039                 }
3040         }
3041
3042         private void dynamic_class_name_variable_properties() {
3043                 // dynamic_class_name_variable_properties:
3044                 // dynamic_class_name_variable_properties
3045                 // dynamic_class_name_variable_property
3046                 // | /* empty */
3047                 if (Scanner.TRACE) {
3048                         System.out
3049                                         .println("TRACE: dynamic_class_name_variable_properties()");
3050                 }
3051                 while (token == TokenNameMINUS_GREATER) {
3052                         dynamic_class_name_variable_property();
3053                 }
3054         }
3055
3056         private void dynamic_class_name_variable_property() {
3057                 // dynamic_class_name_variable_property:
3058                 // T_OBJECT_OPERATOR object_property
3059                 if (Scanner.TRACE) {
3060                         System.out.println("TRACE: dynamic_class_name_variable_property()");
3061                 }
3062                 if (token == TokenNameMINUS_GREATER) {
3063                         getNextToken();
3064                         object_property();
3065                 }
3066         }
3067
3068         private void ctor_arguments() {
3069                 // ctor_arguments:
3070                 // /* empty */
3071                 // | '(' function_call_parameter_list ')'
3072                 if (token == TokenNameLPAREN) {
3073                         getNextToken();
3074                         if (token == TokenNameRPAREN) {
3075                                 getNextToken();
3076                                 return;
3077                         }
3078                         non_empty_function_call_parameter_list();
3079                         if (token != TokenNameRPAREN) {
3080                                 throwSyntaxError("')' expected in ctor_arguments.");
3081                         }
3082                         getNextToken();
3083                 }
3084         }
3085
3086         private void assignment_list() {
3087                 // assignment_list:
3088                 // assignment_list ',' assignment_list_element
3089                 // | assignment_list_element
3090                 while (true) {
3091                         assignment_list_element();
3092                         if (token != TokenNameCOMMA) {
3093                                 break;
3094                         }
3095                         getNextToken();
3096                 }
3097         }
3098
3099         private void assignment_list_element() {
3100                 // assignment_list_element:
3101                 // variable
3102                 // | T_LIST '(' assignment_list ')'
3103                 // | /* empty */
3104                 if (token == TokenNameVariable) {
3105                         variable(true, false);
3106                 } else if (token == TokenNameDOLLAR) {
3107                         variable(false, false);
3108                 } else if (token == TokenNameIdentifier) {
3109                         identifier(true, true);
3110                 } else {
3111                         if (token == TokenNamelist) {
3112                                 getNextToken();
3113                                 if (token == TokenNameLPAREN) {
3114                                         getNextToken();
3115                                         assignment_list();
3116                                         if (token != TokenNameRPAREN) {
3117                                                 throwSyntaxError("')' expected after 'list' keyword.");
3118                                         }
3119                                         getNextToken();
3120                                 } else {
3121                                         throwSyntaxError("'(' expected after 'list' keyword.");
3122                                 }
3123                         }
3124                 }
3125         }
3126
3127         private void array_pair_list() {
3128                 // array_pair_list:
3129                 // /* empty */
3130                 // | non_empty_array_pair_list possible_comma
3131                 non_empty_array_pair_list();
3132                 if (token == TokenNameCOMMA) {
3133                         getNextToken();
3134                 }
3135         }
3136
3137         private void non_empty_array_pair_list() {
3138                 // non_empty_array_pair_list:
3139                 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
3140                 // | non_empty_array_pair_list ',' expr
3141                 // | expr T_DOUBLE_ARROW expr
3142                 // | expr
3143                 // | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
3144                 // | non_empty_array_pair_list ',' '&' w_variable
3145                 // | expr T_DOUBLE_ARROW '&' w_variable
3146                 // | '&' w_variable
3147                 while (true) {
3148                         if (token == TokenNameAND) {
3149                                 getNextToken();
3150                                 variable(true, false);
3151                         } else {
3152                                 expr();
3153                                 if (token == TokenNameAND) {
3154                                         getNextToken();
3155                                         variable(true, false);
3156                                 } else if (token == TokenNameEQUAL_GREATER) {
3157                                         getNextToken();
3158                                         if (token == TokenNameAND) {
3159                                                 getNextToken();
3160                                                 variable(true, false);
3161                                         } else {
3162                                                 expr();
3163                                         }
3164                                 }
3165                         }
3166                         if (token != TokenNameCOMMA) {
3167                                 return;
3168                         }
3169                         getNextToken();
3170                         if (token == TokenNameRPAREN) {
3171                                 return;
3172                         }
3173                 }
3174         }
3175
3176         // private void variableList() {
3177         // do {
3178         // variable();
3179         // if (token == TokenNameCOMMA) {
3180         // getNextToken();
3181         // } else {
3182         // break;
3183         // }
3184         // } while (true);
3185         // }
3186         private Expression variable_without_objects(boolean lefthandside,
3187                         boolean ignoreVar) {
3188                 // variable_without_objects:
3189                 // reference_variable
3190                 // | simple_indirect_reference reference_variable
3191                 if (Scanner.TRACE) {
3192                         System.out.println("TRACE: variable_without_objects()");
3193                 }
3194                 while (token == TokenNameDOLLAR) {
3195                         getNextToken();
3196                 }
3197                 return reference_variable(lefthandside, ignoreVar);
3198         }
3199
3200         private Expression function_call(boolean lefthandside, boolean ignoreVar) {
3201                 // function_call:
3202                 // T_STRING '(' function_call_parameter_list ')'
3203                 // | class_constant '(' function_call_parameter_list ')'
3204                 // | static_member '(' function_call_parameter_list ')'
3205                 // | variable_without_objects '(' function_call_parameter_list ')'
3206                 char[] defineName = null;
3207                 char[] ident = null;
3208                 int startPos = 0;
3209                 int endPos = 0;
3210                 Expression ref = null;
3211                 if (Scanner.TRACE) {
3212                         System.out.println("TRACE: function_call()");
3213                 }
3214                 if (token == TokenNameIdentifier) {
3215                         ident = scanner.getCurrentIdentifierSource();
3216                         defineName = ident;
3217                         startPos = scanner.getCurrentTokenStartPosition();
3218                         endPos = scanner.getCurrentTokenEndPosition();
3219                         getNextToken();
3220                         switch (token) {
3221                         case TokenNamePAAMAYIM_NEKUDOTAYIM:
3222                                 // static member:
3223                                 defineName = null;
3224                                 getNextToken();
3225                                 if (token == TokenNameIdentifier) {
3226                                         // class _constant
3227                                         getNextToken();
3228                                 } else {
3229                                         // static member:
3230                                         variable_without_objects(true, false);
3231                                 }
3232                                 break;
3233                         }
3234                 } else {
3235                         ref = variable_without_objects(lefthandside, ignoreVar);
3236                 }
3237                 if (token != TokenNameLPAREN) {
3238                         if (defineName != null) {
3239                                 // does this identifier contain only uppercase characters?
3240                                 if (defineName.length == 3) {
3241                                         if (defineName[0] == 'd' && defineName[1] == 'i'
3242                                                         && defineName[2] == 'e') {
3243                                                 defineName = null;
3244                                         }
3245                                 } else if (defineName.length == 4) {
3246                                         if (defineName[0] == 't' && defineName[1] == 'r'
3247                                                         && defineName[2] == 'u' && defineName[3] == 'e') {
3248                                                 defineName = null;
3249                                         } else if (defineName[0] == 'n' && defineName[1] == 'u'
3250                                                         && defineName[2] == 'l' && defineName[3] == 'l') {
3251                                                 defineName = null;
3252                                         }
3253                                 } else if (defineName.length == 5) {
3254                                         if (defineName[0] == 'f' && defineName[1] == 'a'
3255                                                         && defineName[2] == 'l' && defineName[3] == 's'
3256                                                         && defineName[4] == 'e') {
3257                                                 defineName = null;
3258                                         }
3259                                 }
3260                                 if (defineName != null) {
3261                                         for (int i = 0; i < defineName.length; i++) {
3262                                                 if (Character.isLowerCase(defineName[i])) {
3263                                                         problemReporter.phpUppercaseIdentifierWarning(
3264                                                                         startPos, endPos, referenceContext,
3265                                                                         compilationUnit.compilationResult);
3266                                                         break;
3267                                                 }
3268                                         }
3269                                 }
3270                         }
3271                 } else {
3272                         getNextToken();
3273                         if (token == TokenNameRPAREN) {
3274                                 getNextToken();
3275                                 return ref;
3276                         }
3277                         non_empty_function_call_parameter_list();
3278                         if (token != TokenNameRPAREN) {
3279                                 String functionName;
3280                                 if (ident == null) {
3281                                         functionName = new String(" ");
3282                                 } else {
3283                                         functionName = new String(ident);
3284                                 }
3285                                 throwSyntaxError("')' expected in function call ("
3286                                                 + functionName + ").");
3287                         }
3288                         getNextToken();
3289                 }
3290                 return ref;
3291         }
3292
3293         private void non_empty_function_call_parameter_list() {
3294                 this.non_empty_function_call_parameter_list(null);
3295         }
3296
3297         // private void function_call_parameter_list() {
3298         // function_call_parameter_list:
3299         // non_empty_function_call_parameter_list { $$ = $1; }
3300         // | /* empty */
3301         // }
3302         private void non_empty_function_call_parameter_list(String functionName) {
3303                 // non_empty_function_call_parameter_list:
3304                 // expr_without_variable
3305                 // | variable
3306                 // | '&' w_variable
3307                 // | non_empty_function_call_parameter_list ',' expr_without_variable
3308                 // | non_empty_function_call_parameter_list ',' variable
3309                 // | non_empty_function_call_parameter_list ',' '&' w_variable
3310                 if (Scanner.TRACE) {
3311                         System.out
3312                                         .println("TRACE: non_empty_function_call_parameter_list()");
3313                 }
3314                 UninitializedVariableHandler initHandler = new UninitializedVariableHandler();
3315                 initHandler.setFunctionName(functionName);
3316                 while (true) {
3317                         initHandler.incrementArgumentCount();
3318                         if (token == TokenNameAND) {
3319                                 getNextToken();
3320                                 w_variable(true);
3321                         } else {
3322                                 // if (token == TokenNameIdentifier || token ==
3323                                 // TokenNameVariable
3324                                 // || token == TokenNameDOLLAR) {
3325                                 // variable();
3326                                 // } else {
3327                                 expr_without_variable(true, initHandler);
3328                                 // }
3329                         }
3330                         if (token != TokenNameCOMMA) {
3331                                 break;
3332                         }
3333                         getNextToken();
3334                 }
3335         }
3336
3337         private void fully_qualified_class_name() {
3338                 if (token == TokenNameIdentifier) {
3339                         getNextToken();
3340                 } else {
3341                         throwSyntaxError("Class name expected.");
3342                 }
3343         }
3344
3345         private void static_member() {
3346                 // static_member:
3347                 // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
3348                 // variable_without_objects
3349                 if (Scanner.TRACE) {
3350                         System.out.println("TRACE: static_member()");
3351                 }
3352                 fully_qualified_class_name();
3353                 if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
3354                         throwSyntaxError("'::' expected after class name (static_member).");
3355                 }
3356                 getNextToken();
3357                 variable_without_objects(false, false);
3358         }
3359
3360         private Expression base_variable_with_function_calls(boolean lefthandside,
3361                         boolean ignoreVar) {
3362                 // base_variable_with_function_calls:
3363                 // base_variable
3364                 // | function_call
3365                 if (Scanner.TRACE) {
3366                         System.out.println("TRACE: base_variable_with_function_calls()");
3367                 }
3368                 return function_call(lefthandside, ignoreVar);
3369         }
3370
3371         private Expression base_variable(boolean lefthandside) {
3372                 // base_variable:
3373                 // reference_variable
3374                 // | simple_indirect_reference reference_variable
3375                 // | static_member
3376                 Expression ref = null;
3377                 if (Scanner.TRACE) {
3378                         System.out.println("TRACE: base_variable()");
3379                 }
3380                 if (token == TokenNameIdentifier) {
3381                         static_member();
3382                 } else {
3383                         while (token == TokenNameDOLLAR) {
3384                                 getNextToken();
3385                         }
3386                         reference_variable(lefthandside, false);
3387                 }
3388                 return ref;
3389         }
3390
3391         // private void simple_indirect_reference() {
3392         // // simple_indirect_reference:
3393         // // '$'
3394         // //| simple_indirect_reference '$'
3395         // }
3396         private Expression reference_variable(boolean lefthandside,
3397                         boolean ignoreVar) {
3398                 // reference_variable:
3399                 // reference_variable '[' dim_offset ']'
3400                 // | reference_variable '{' expr '}'
3401                 // | compound_variable
3402                 Expression ref = null;
3403                 if (Scanner.TRACE) {
3404                         System.out.println("TRACE: reference_variable()");
3405                 }
3406                 ref = compound_variable(lefthandside, ignoreVar);
3407                 while (true) {
3408                         if (token == TokenNameLBRACE) {
3409                                 ref = null;
3410                                 getNextToken();
3411                                 expr();
3412                                 if (token != TokenNameRBRACE) {
3413                                         throwSyntaxError("'}' expected in reference variable.");
3414                                 }
3415                                 getNextToken();
3416                         } else if (token == TokenNameLBRACKET) {
3417                                 // To remove "ref = null;" here, is probably better than the
3418                                 // patch
3419                                 // commented in #1368081 - axelcl
3420                                 getNextToken();
3421                                 if (token != TokenNameRBRACKET) {
3422                                         expr();
3423                                         // dim_offset();
3424                                         if (token != TokenNameRBRACKET) {
3425                                                 throwSyntaxError("']' expected in reference variable.");
3426                                         }
3427                                 }
3428                                 getNextToken();
3429                         } else {
3430                                 break;
3431                         }
3432                 }
3433                 return ref;
3434         }
3435
3436         private Expression compound_variable(boolean lefthandside, boolean ignoreVar) {
3437                 // compound_variable:
3438                 // T_VARIABLE
3439                 // | '$' '{' expr '}'
3440                 if (Scanner.TRACE) {
3441                         System.out.println("TRACE: compound_variable()");
3442                 }
3443                 if (token == TokenNameVariable) {
3444                         if (!lefthandside) {
3445                                 if (!containsVariableSet()) {
3446                                         // reportSyntaxError("The local variable " + new
3447                                         // String(scanner.getCurrentIdentifierSource())
3448                                         // + " may not have been initialized");
3449                                         problemReporter.uninitializedLocalVariable(new String(
3450                                                         scanner.getCurrentIdentifierSource()), scanner
3451                                                         .getCurrentTokenStartPosition(), scanner
3452                                                         .getCurrentTokenEndPosition(), referenceContext,
3453                                                         compilationUnit.compilationResult);
3454                                 }
3455                         } else {
3456                                 if (!ignoreVar) {
3457                                         addVariableSet();
3458                                 }
3459                         }
3460                         FieldReference ref = new FieldReference(scanner
3461                                         .getCurrentIdentifierSource(), scanner
3462                                         .getCurrentTokenStartPosition());
3463                         getNextToken();
3464                         return ref;
3465                 } else {
3466                         // because of simple_indirect_reference
3467                         while (token == TokenNameDOLLAR) {
3468                                 getNextToken();
3469                         }
3470                         if (token != TokenNameLBRACE) {
3471                                 reportSyntaxError("'{' expected after compound variable token '$'.");
3472                                 return null;
3473                         }
3474                         getNextToken();
3475                         expr();
3476                         if (token != TokenNameRBRACE) {
3477                                 throwSyntaxError("'}' expected after compound variable token '$'.");
3478                         }
3479                         getNextToken();
3480                 }
3481                 return null;
3482         } // private void dim_offset() { // // dim_offset: // // /* empty */
3483
3484         // // | expr
3485         // expr();
3486         // }
3487         private void object_property() {
3488                 // object_property:
3489                 // object_dim_list
3490                 // | variable_without_objects
3491                 if (Scanner.TRACE) {
3492                         System.out.println("TRACE: object_property()");
3493                 }
3494                 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
3495                         variable_without_objects(false, false);
3496                 } else {
3497                         object_dim_list();
3498                 }
3499         }
3500
3501         private void object_dim_list() {
3502                 // object_dim_list:
3503                 // object_dim_list '[' dim_offset ']'
3504                 // | object_dim_list '{' expr '}'
3505                 // | variable_name
3506                 if (Scanner.TRACE) {
3507                         System.out.println("TRACE: object_dim_list()");
3508                 }
3509                 variable_name();
3510                 while (true) {
3511                         if (token == TokenNameLBRACE) {
3512                                 getNextToken();
3513                                 expr();
3514                                 if (token != TokenNameRBRACE) {
3515                                         throwSyntaxError("'}' expected in object_dim_list.");
3516                                 }
3517                                 getNextToken();
3518                         } else if (token == TokenNameLBRACKET) {
3519                                 getNextToken();
3520                                 if (token == TokenNameRBRACKET) {
3521                                         getNextToken();
3522                                         continue;
3523                                 }
3524                                 expr();
3525                                 if (token != TokenNameRBRACKET) {
3526                                         throwSyntaxError("']' expected in object_dim_list.");
3527                                 }
3528                                 getNextToken();
3529                         } else {
3530                                 break;
3531                         }
3532                 }
3533         }
3534
3535         private void variable_name() {
3536                 // variable_name:
3537                 // T_STRING
3538                 // | '{' expr '}'
3539                 if (Scanner.TRACE) {
3540                         System.out.println("TRACE: variable_name()");
3541                 }
3542                 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3543                         if (token > TokenNameKEYWORD) {
3544                                 // TODO show a warning "Keyword used as variable" ?
3545                         }
3546                         getNextToken();
3547                 } else {
3548                         if (token != TokenNameLBRACE) {
3549                                 throwSyntaxError("'{' expected in variable name.");
3550                         }
3551                         getNextToken();
3552                         expr();
3553                         if (token != TokenNameRBRACE) {
3554                                 throwSyntaxError("'}' expected in variable name.");
3555                         }
3556                         getNextToken();
3557                 }
3558         }
3559
3560         private void r_variable() {
3561                 variable(false, false);
3562         }
3563
3564         private void w_variable(boolean lefthandside) {
3565                 variable(lefthandside, false);
3566         }
3567
3568         private void rw_variable() {
3569                 variable(false, false);
3570         }
3571
3572         private Expression variable(boolean lefthandside, boolean ignoreVar) {
3573                 // variable:
3574                 // base_variable_with_function_calls T_OBJECT_OPERATOR
3575                 // object_property method_or_not variable_properties
3576                 // | base_variable_with_function_calls
3577                 Expression ref = base_variable_with_function_calls(lefthandside,
3578                                 ignoreVar);
3579                 if (token == TokenNameMINUS_GREATER) {
3580                         ref = null;
3581                         getNextToken();
3582                         object_property();
3583                         method_or_not();
3584                         variable_properties();
3585                 }
3586                 return ref;
3587         }
3588
3589         private void variable_properties() {
3590                 // variable_properties:
3591                 // variable_properties variable_property
3592                 // | /* empty */
3593                 while (token == TokenNameMINUS_GREATER) {
3594                         variable_property();
3595                 }
3596         }
3597
3598         private void variable_property() {
3599                 // variable_property:
3600                 // T_OBJECT_OPERATOR object_property method_or_not
3601                 if (Scanner.TRACE) {
3602                         System.out.println("TRACE: variable_property()");
3603                 }
3604                 if (token == TokenNameMINUS_GREATER) {
3605                         getNextToken();
3606                         object_property();
3607                         method_or_not();
3608                 } else {
3609                         throwSyntaxError("'->' expected in variable_property.");
3610                 }
3611         }
3612
3613         private Expression identifier(boolean lefthandside, boolean ignoreVar) {
3614                 // variable:
3615                 // base_variable_with_function_calls T_OBJECT_OPERATOR
3616                 // object_property method_or_not variable_properties
3617                 // | base_variable_with_function_calls
3618
3619                 // Expression ref = function_call(lefthandside, ignoreVar);
3620
3621                 // function_call:
3622                 // T_STRING '(' function_call_parameter_list ')'
3623                 // | class_constant '(' function_call_parameter_list ')'
3624                 // | static_member '(' function_call_parameter_list ')'
3625                 // | variable_without_objects '(' function_call_parameter_list ')'
3626                 char[] defineName = null;
3627                 char[] ident = null;
3628                 int startPos = 0;
3629                 int endPos = 0;
3630                 Expression ref = null;
3631                 if (Scanner.TRACE) {
3632                         System.out.println("TRACE: function_call()");
3633                 }
3634                 if (token == TokenNameIdentifier) {
3635                         ident = scanner.getCurrentIdentifierSource();
3636                         defineName = ident;
3637                         startPos = scanner.getCurrentTokenStartPosition();
3638                         endPos = scanner.getCurrentTokenEndPosition();
3639                         getNextToken();
3640
3641                         if (token == TokenNameEQUAL || token == TokenNamePLUS_EQUAL
3642                                         || token == TokenNameMINUS_EQUAL
3643                                         || token == TokenNameMULTIPLY_EQUAL
3644                                         || token == TokenNameDIVIDE_EQUAL
3645                                         || token == TokenNameDOT_EQUAL
3646                                         || token == TokenNameREMAINDER_EQUAL
3647                                         || token == TokenNameAND_EQUAL
3648                                         || token == TokenNameOR_EQUAL
3649                                         || token == TokenNameXOR_EQUAL
3650                                         || token == TokenNameRIGHT_SHIFT_EQUAL
3651                                         || token == TokenNameLEFT_SHIFT_EQUAL) {
3652                                 String error = "Assignment operator '"
3653                                                 + scanner.toStringAction(token)
3654                                                 + "' not allowed after identifier '"
3655                                                 + new String(ident)
3656                                                 + "' (use 'define(...)' to define constants).";
3657                                 reportSyntaxError(error);
3658                         }
3659
3660                         switch (token) {
3661                         case TokenNamePAAMAYIM_NEKUDOTAYIM:
3662                                 // static member:
3663                                 defineName = null;
3664                                 getNextToken();
3665                                 if (token == TokenNameIdentifier) {
3666                                         // class _constant
3667                                         getNextToken();
3668                                 } else {
3669                                         // static member:
3670                                         variable_without_objects(true, false);
3671                                 }
3672                                 break;
3673                         }
3674                 } else {
3675                         ref = variable_without_objects(lefthandside, ignoreVar);
3676                 }
3677                 if (token != TokenNameLPAREN) {
3678                         if (defineName != null) {
3679                                 // does this identifier contain only uppercase characters?
3680                                 if (defineName.length == 3) {
3681                                         if (defineName[0] == 'd' && defineName[1] == 'i'
3682                                                         && defineName[2] == 'e') {
3683                                                 defineName = null;
3684                                         }
3685                                 } else if (defineName.length == 4) {
3686                                         if (defineName[0] == 't' && defineName[1] == 'r'
3687                                                         && defineName[2] == 'u' && defineName[3] == 'e') {
3688                                                 defineName = null;
3689                                         } else if (defineName[0] == 'n' && defineName[1] == 'u'
3690                                                         && defineName[2] == 'l' && defineName[3] == 'l') {
3691                                                 defineName = null;
3692                                         }
3693                                 } else if (defineName.length == 5) {
3694                                         if (defineName[0] == 'f' && defineName[1] == 'a'
3695                                                         && defineName[2] == 'l' && defineName[3] == 's'
3696                                                         && defineName[4] == 'e') {
3697                                                 defineName = null;
3698                                         }
3699                                 }
3700                                 if (defineName != null) {
3701                                         for (int i = 0; i < defineName.length; i++) {
3702                                                 if (Character.isLowerCase(defineName[i])) {
3703                                                         problemReporter.phpUppercaseIdentifierWarning(
3704                                                                         startPos, endPos, referenceContext,
3705                                                                         compilationUnit.compilationResult);
3706                                                         break;
3707                                                 }
3708                                         }
3709                                 }
3710                         }
3711                         // TODO is this ok ?
3712                         // return ref;
3713                         // throwSyntaxError("'(' expected in function call.");
3714                 } else {
3715                         getNextToken();
3716
3717                         if (token == TokenNameRPAREN) {
3718                                 getNextToken();
3719                                 ref = null;
3720                         } else {
3721                                 String functionName;
3722                                 if (ident == null) {
3723                                         functionName = new String(" ");
3724                                 } else {
3725                                         functionName = new String(ident);
3726                                 }
3727                                 non_empty_function_call_parameter_list(functionName);
3728                                 if (token != TokenNameRPAREN) {
3729                                         throwSyntaxError("')' expected in function call ("
3730                                                         + functionName + ").");
3731                                 }
3732                                 getNextToken();
3733                         }
3734                 }
3735                 if (token == TokenNameMINUS_GREATER) {
3736                         ref = null;
3737                         getNextToken();
3738                         object_property();
3739                         method_or_not();
3740                         variable_properties();
3741                 }
3742                 return ref;
3743         }
3744
3745         private void method_or_not() {
3746                 // method_or_not:
3747                 // '(' function_call_parameter_list ')'
3748                 // | /* empty */
3749                 if (Scanner.TRACE) {
3750                         System.out.println("TRACE: method_or_not()");
3751                 }
3752                 if (token == TokenNameLPAREN) {
3753                         getNextToken();
3754                         if (token == TokenNameRPAREN) {
3755                                 getNextToken();
3756                                 return;
3757                         }
3758                         non_empty_function_call_parameter_list();
3759                         if (token != TokenNameRPAREN) {
3760                                 throwSyntaxError("')' expected in method_or_not.");
3761                         }
3762                         getNextToken();
3763                 }
3764         }
3765
3766         private void exit_expr() {
3767                 // /* empty */
3768                 // | '(' ')'
3769                 // | '(' expr ')'
3770                 if (token != TokenNameLPAREN) {
3771                         return;
3772                 }
3773                 getNextToken();
3774                 if (token == TokenNameRPAREN) {
3775                         getNextToken();
3776                         return;
3777                 }
3778                 expr();
3779                 if (token != TokenNameRPAREN) {
3780                         throwSyntaxError("')' expected after keyword 'exit'");
3781                 }
3782                 getNextToken();
3783         }
3784
3785         // private void encaps_list() {
3786         // // encaps_list encaps_var
3787         // // | encaps_list T_STRING
3788         // // | encaps_list T_NUM_STRING
3789         // // | encaps_list T_ENCAPSED_AND_WHITESPACE
3790         // // | encaps_list T_CHARACTER
3791         // // | encaps_list T_BAD_CHARACTER
3792         // // | encaps_list '['
3793         // // | encaps_list ']'
3794         // // | encaps_list '{'
3795         // // | encaps_list '}'
3796         // // | encaps_list T_OBJECT_OPERATOR
3797         // // | /* empty */
3798         // while (true) {
3799         // switch (token) {
3800         // case TokenNameSTRING:
3801         // getNextToken();
3802         // break;
3803         // case TokenNameLBRACE:
3804         // // scanner.encapsedStringStack.pop();
3805         // getNextToken();
3806         // break;
3807         // case TokenNameRBRACE:
3808         // // scanner.encapsedStringStack.pop();
3809         // getNextToken();
3810         // break;
3811         // case TokenNameLBRACKET:
3812         // // scanner.encapsedStringStack.pop();
3813         // getNextToken();
3814         // break;
3815         // case TokenNameRBRACKET:
3816         // // scanner.encapsedStringStack.pop();
3817         // getNextToken();
3818         // break;
3819         // case TokenNameMINUS_GREATER:
3820         // // scanner.encapsedStringStack.pop();
3821         // getNextToken();
3822         // break;
3823         // case TokenNameVariable:
3824         // case TokenNameDOLLAR_LBRACE:
3825         // case TokenNameLBRACE_DOLLAR:
3826         // encaps_var();
3827         // break;
3828         // default:
3829         // char encapsedChar = ((Character)
3830         // scanner.encapsedStringStack.peek()).charValue();
3831         // if (encapsedChar == '$') {
3832         // scanner.encapsedStringStack.pop();
3833         // encapsedChar = ((Character)
3834         // scanner.encapsedStringStack.peek()).charValue();
3835         // switch (encapsedChar) {
3836         // case '`':
3837         // if (token == TokenNameEncapsedString0) {
3838         // return;
3839         // }
3840         // token = TokenNameSTRING;
3841         // continue;
3842         // case '\'':
3843         // if (token == TokenNameEncapsedString1) {
3844         // return;
3845         // }
3846         // token = TokenNameSTRING;
3847         // continue;
3848         // case '"':
3849         // if (token == TokenNameEncapsedString2) {
3850         // return;
3851         // }
3852         // token = TokenNameSTRING;
3853         // continue;
3854         // }
3855         // }
3856         // return;
3857         // }
3858         // }
3859         // }
3860
3861         // private void encaps_var() {
3862         // // T_VARIABLE
3863         // // | T_VARIABLE '[' encaps_var_offset ']'
3864         // // | T_VARIABLE T_OBJECT_OPERATOR T_STRING
3865         // // | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
3866         // // | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
3867         // // | T_CURLY_OPEN variable '}'
3868         // switch (token) {
3869         // case TokenNameVariable:
3870         // getNextToken();
3871         // if (token == TokenNameLBRACKET) {
3872         // getNextToken();
3873         // expr(); //encaps_var_offset();
3874         // if (token != TokenNameRBRACKET) {
3875         // throwSyntaxError("']' expected after variable.");
3876         // }
3877         // // scanner.encapsedStringStack.pop();
3878         // getNextToken();
3879         // // }
3880         // } else if (token == TokenNameMINUS_GREATER) {
3881         // getNextToken();
3882         // if (token != TokenNameIdentifier) {
3883         // throwSyntaxError("Identifier expected after '->'.");
3884         // }
3885         // // scanner.encapsedStringStack.pop();
3886         // getNextToken();
3887         // }
3888         // // else {
3889         // // // scanner.encapsedStringStack.pop();
3890         // // int tempToken = TokenNameSTRING;
3891         // // if (!scanner.encapsedStringStack.isEmpty()
3892         // // && (token == TokenNameEncapsedString0
3893         // // || token == TokenNameEncapsedString1
3894         // // || token == TokenNameEncapsedString2 || token ==
3895         // // TokenNameERROR)) {
3896         // // char encapsedChar = ((Character)
3897         // // scanner.encapsedStringStack.peek())
3898         // // .charValue();
3899         // // switch (token) {
3900         // // case TokenNameEncapsedString0 :
3901         // // if (encapsedChar == '`') {
3902         // // tempToken = TokenNameEncapsedString0;
3903         // // }
3904         // // break;
3905         // // case TokenNameEncapsedString1 :
3906         // // if (encapsedChar == '\'') {
3907         // // tempToken = TokenNameEncapsedString1;
3908         // // }
3909         // // break;
3910         // // case TokenNameEncapsedString2 :
3911         // // if (encapsedChar == '"') {
3912         // // tempToken = TokenNameEncapsedString2;
3913         // // }
3914         // // break;
3915         // // case TokenNameERROR :
3916         // // if (scanner.source[scanner.currentPosition - 1] == '\\') {
3917         // // scanner.currentPosition--;
3918         // // getNextToken();
3919         // // }
3920         // // break;
3921         // // }
3922         // // }
3923         // // token = tempToken;
3924         // // }
3925         // break;
3926         // case TokenNameDOLLAR_LBRACE:
3927         // getNextToken();
3928         // if (token == TokenNameDOLLAR_LBRACE) {
3929         // encaps_var();
3930         // } else if (token == TokenNameIdentifier) {
3931         // getNextToken();
3932         // if (token == TokenNameLBRACKET) {
3933         // getNextToken();
3934         // // if (token == TokenNameRBRACKET) {
3935         // // getNextToken();
3936         // // } else {
3937         // expr();
3938         // if (token != TokenNameRBRACKET) {
3939         // throwSyntaxError("']' expected after '${'.");
3940         // }
3941         // getNextToken();
3942         // // }
3943         // }
3944         // } else {
3945         // expr();
3946         // }
3947         // if (token != TokenNameRBRACE) {
3948         // throwSyntaxError("'}' expected.");
3949         // }
3950         // getNextToken();
3951         // break;
3952         // case TokenNameLBRACE_DOLLAR:
3953         // getNextToken();
3954         // if (token == TokenNameLBRACE_DOLLAR) {
3955         // encaps_var();
3956         // } else if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3957         // getNextToken();
3958         // if (token == TokenNameLBRACKET) {
3959         // getNextToken();
3960         // // if (token == TokenNameRBRACKET) {
3961         // // getNextToken();
3962         // // } else {
3963         // expr();
3964         // if (token != TokenNameRBRACKET) {
3965         // throwSyntaxError("']' expected.");
3966         // }
3967         // getNextToken();
3968         // // }
3969         // } else if (token == TokenNameMINUS_GREATER) {
3970         // getNextToken();
3971         // if (token != TokenNameIdentifier && token != TokenNameVariable) {
3972         // throwSyntaxError("String or Variable token expected.");
3973         // }
3974         // getNextToken();
3975         // if (token == TokenNameLBRACKET) {
3976         // getNextToken();
3977         // // if (token == TokenNameRBRACKET) {
3978         // // getNextToken();
3979         // // } else {
3980         // expr();
3981         // if (token != TokenNameRBRACKET) {
3982         // throwSyntaxError("']' expected after '${'.");
3983         // }
3984         // getNextToken();
3985         // // }
3986         // }
3987         // }
3988         // // if (token != TokenNameRBRACE) {
3989         // // throwSyntaxError("'}' expected after '{$'.");
3990         // // }
3991         // // // scanner.encapsedStringStack.pop();
3992         // // getNextToken();
3993         // } else {
3994         // expr();
3995         // if (token != TokenNameRBRACE) {
3996         // throwSyntaxError("'}' expected.");
3997         // }
3998         // // scanner.encapsedStringStack.pop();
3999         // getNextToken();
4000         // }
4001         // break;
4002         // }
4003         // }
4004
4005         // private void encaps_var_offset() {
4006         // // T_STRING
4007         // // | T_NUM_STRING
4008         // // | T_VARIABLE
4009         // switch (token) {
4010         // case TokenNameSTRING:
4011         // getNextToken();
4012         // break;
4013         // case TokenNameIntegerLiteral:
4014         // getNextToken();
4015         // break;
4016         // case TokenNameVariable:
4017         // getNextToken();
4018         // break;
4019         // case TokenNameIdentifier:
4020         // getNextToken();
4021         // break;
4022         // default:
4023         // throwSyntaxError("Variable or String token expected.");
4024         // break;
4025         // }
4026         // }
4027
4028         private void internal_functions_in_yacc() {
4029                 // int start = 0;
4030                 switch (token) {
4031                 // case TokenNameisset:
4032                 // // T_ISSET '(' isset_variables ')'
4033                 // getNextToken();
4034                 // if (token != TokenNameLPAREN) {
4035                 // throwSyntaxError("'(' expected after keyword 'isset'");
4036                 // }
4037                 // getNextToken();
4038                 // isset_variables();
4039                 // if (token != TokenNameRPAREN) {
4040                 // throwSyntaxError("')' expected after keyword 'isset'");
4041                 // }
4042                 // getNextToken();
4043                 // break;
4044                 // case TokenNameempty:
4045                 // // T_EMPTY '(' variable ')'
4046                 // getNextToken();
4047                 // if (token != TokenNameLPAREN) {
4048                 // throwSyntaxError("'(' expected after keyword 'empty'");
4049                 // }
4050                 // getNextToken();
4051                 // variable(false);
4052                 // if (token != TokenNameRPAREN) {
4053                 // throwSyntaxError("')' expected after keyword 'empty'");
4054                 // }
4055                 // getNextToken();
4056                 // break;
4057                 case TokenNameinclude:
4058                         // T_INCLUDE expr
4059                         checkFileName(token);
4060                         break;
4061                 case TokenNameinclude_once:
4062                         // T_INCLUDE_ONCE expr
4063                         checkFileName(token);
4064                         break;
4065                 case TokenNameeval:
4066                         // T_EVAL '(' expr ')'
4067                         getNextToken();
4068                         if (token != TokenNameLPAREN) {
4069                                 throwSyntaxError("'(' expected after keyword 'eval'");
4070                         }
4071                         getNextToken();
4072                         expr();
4073                         if (token != TokenNameRPAREN) {
4074                                 throwSyntaxError("')' expected after keyword 'eval'");
4075                         }
4076                         getNextToken();
4077                         break;
4078                 case TokenNamerequire:
4079                         // T_REQUIRE expr
4080                         checkFileName(token);
4081                         break;
4082                 case TokenNamerequire_once:
4083                         // T_REQUIRE_ONCE expr
4084                         checkFileName(token);
4085                         break;
4086                 }
4087         }
4088
4089         /**
4090          * Parse and check the include file name
4091          * 
4092          * @param includeToken
4093          */
4094         private void checkFileName(int includeToken) {
4095                 // <include-token> expr
4096                 int start = scanner.getCurrentTokenStartPosition();
4097                 boolean hasLPAREN = false;
4098                 getNextToken();
4099                 if (token == TokenNameLPAREN) {
4100                         hasLPAREN = true;
4101                         getNextToken();
4102                 }
4103                 Expression expression = expr();
4104                 if (hasLPAREN) {
4105                         if (token == TokenNameRPAREN) {
4106                                 getNextToken();
4107                         } else {
4108                                 throwSyntaxError("')' expected for keyword '"
4109                                                 + scanner.toStringAction(includeToken) + "'");
4110                         }
4111                 }
4112                 char[] currTokenSource = scanner.getCurrentTokenSource(start);
4113                 IFile file = null;
4114                 if (scanner.compilationUnit != null) {
4115                         IResource resource = scanner.compilationUnit.getResource();
4116                         if (resource != null && resource instanceof IFile) {
4117                                 file = (IFile) resource;
4118                         }
4119                 }
4120                 char[][] tokens;
4121                 tokens = new char[1][];
4122                 tokens[0] = currTokenSource;
4123
4124                 ImportReference impt = new ImportReference(tokens, currTokenSource,
4125                                 start, scanner.getCurrentTokenEndPosition(), false);
4126                 impt.declarationSourceEnd = impt.sourceEnd;
4127                 impt.declarationEnd = impt.declarationSourceEnd;
4128                 // endPosition is just before the ;
4129                 impt.declarationSourceStart = start;
4130                 includesList.add(impt);
4131
4132                 if (expression instanceof StringLiteral) {
4133                         StringLiteral literal = (StringLiteral) expression;
4134                         char[] includeName = literal.source();
4135                         if (includeName.length == 0) {
4136                                 reportSyntaxError("Empty filename after keyword '"
4137                                                 + scanner.toStringAction(includeToken) + "'",
4138                                                 literal.sourceStart, literal.sourceStart + 1);
4139                         }
4140                         String includeNameString = new String(includeName);
4141                         if (literal instanceof StringLiteralDQ) {
4142                                 if (includeNameString.indexOf('$') >= 0) {
4143                                         // assuming that the filename contains a variable => no
4144                                         // filename check
4145                                         return;
4146                                 }
4147                         }
4148                         if (includeNameString.startsWith("http://")) {
4149                                 // assuming external include location
4150                                 return;
4151                         }
4152                         if (file != null) {
4153                                 // check the filename:
4154                                 // System.out.println(new
4155                                 // String(compilationUnit.getFileName())+" - "+
4156                                 // expression.toStringExpression());
4157                                 IProject project = file.getProject();
4158                                 if (project != null) {
4159                                         IPath path = PHPFileUtil.determineFilePath(
4160                                                         includeNameString, file, project);
4161
4162                                         if (path == null) {
4163                                                 // SyntaxError: "File: << >> doesn't exist in project."
4164                                                 String[] args = { expression.toStringExpression(),
4165                                                                 project.getLocation().toString() };
4166                                                 problemReporter.phpIncludeNotExistWarning(args,
4167                                                                 literal.sourceStart, literal.sourceEnd,
4168                                                                 referenceContext,
4169                                                                 compilationUnit.compilationResult);
4170                                         } else {
4171                                                 try {
4172                                                         String filePath = path.toString();
4173                                                         String ext = file.getRawLocation()
4174                                                                         .getFileExtension();
4175                                                         int fileExtensionLength = ext == null ? 0 : ext
4176                                                                         .length() + 1;
4177
4178                                                         IFile f = PHPFileUtil.createFile(path, project);
4179
4180                                                         impt.tokens = CharOperation.splitOn('/', filePath
4181                                                                         .toCharArray(), 0, filePath.length()
4182                                                                         - fileExtensionLength);
4183                                                         impt.setFile(f);
4184                                                 } catch (Exception e) {
4185                                                         // the file is outside of the workspace
4186                                                 }
4187                                         }
4188                                 }
4189                         }
4190                 }
4191         }
4192
4193         private void isset_variables() {
4194                 // variable
4195                 // | isset_variables ','
4196                 if (token == TokenNameRPAREN) {
4197                         throwSyntaxError("Variable expected after keyword 'isset'");
4198                 }
4199                 while (true) {
4200                         variable(true, false);
4201                         if (token == TokenNameCOMMA) {
4202                                 getNextToken();
4203                         } else {
4204                                 break;
4205                         }
4206                 }
4207         }
4208
4209         private boolean common_scalar() {
4210                 // common_scalar:
4211                 // T_LNUMBER
4212                 // | T_DNUMBER
4213                 // | T_CONSTANT_ENCAPSED_STRING
4214                 // | T_LINE
4215                 // | T_FILE
4216                 // | T_CLASS_C
4217                 // | T_METHOD_C
4218                 // | T_FUNC_C
4219                 switch (token) {
4220                 case TokenNameIntegerLiteral:
4221                         getNextToken();
4222                         return true;
4223                 case TokenNameDoubleLiteral:
4224                         getNextToken();
4225                         return true;
4226                 case TokenNameStringDoubleQuote:
4227                         getNextToken();
4228                         return true;
4229                 case TokenNameStringSingleQuote:
4230                         getNextToken();
4231                         return true;
4232                 case TokenNameStringInterpolated:
4233                         getNextToken();
4234                         return true;
4235                 case TokenNameFILE:
4236                         getNextToken();
4237                         return true;
4238                 case TokenNameLINE:
4239                         getNextToken();
4240                         return true;
4241                 case TokenNameCLASS_C:
4242                         getNextToken();
4243                         return true;
4244                 case TokenNameMETHOD_C:
4245                         getNextToken();
4246                         return true;
4247                 case TokenNameFUNC_C:
4248                         getNextToken();
4249                         return true;
4250                 }
4251                 return false;
4252         }
4253
4254         private void scalar() {
4255                 // scalar:
4256                 // T_STRING
4257                 // | T_STRING_VARNAME
4258                 // | class_constant
4259                 // | common_scalar
4260                 // | '"' encaps_list '"'
4261                 // | '\'' encaps_list '\''
4262                 // | T_START_HEREDOC encaps_list T_END_HEREDOC
4263                 throwSyntaxError("Not yet implemented (scalar).");
4264         }
4265
4266         private void static_scalar() {
4267                 // static_scalar: /* compile-time evaluated scalars */
4268                 // common_scalar
4269                 // | T_STRING
4270                 // | '+' static_scalar
4271                 // | '-' static_scalar
4272                 // | T_ARRAY '(' static_array_pair_list ')'
4273                 // | static_class_constant
4274                 if (common_scalar()) {
4275                         return;
4276                 }
4277                 switch (token) {
4278                 case TokenNameIdentifier:
4279                         getNextToken();
4280                         // static_class_constant:
4281                         // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
4282                         if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
4283                                 getNextToken();
4284                                 if (token == TokenNameIdentifier) {
4285                                         getNextToken();
4286                                 } else {
4287                                         throwSyntaxError("Identifier expected after '::' operator.");
4288                                 }
4289                         }
4290                         break;
4291                 case TokenNameEncapsedString0:
4292                         try {
4293                                 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4294                                 while (scanner.currentCharacter != '`') {
4295                                         if (scanner.currentCharacter == '\\') {
4296                                                 scanner.currentPosition++;
4297                                         }
4298                                         scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4299                                 }
4300                                 getNextToken();
4301                         } catch (IndexOutOfBoundsException e) {
4302                                 throwSyntaxError("'`' expected at end of static string.");
4303                         }
4304                         break;
4305                 // case TokenNameEncapsedString1:
4306                 // try {
4307                 // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4308                 // while (scanner.currentCharacter != '\'') {
4309                 // if (scanner.currentCharacter == '\\') {
4310                 // scanner.currentPosition++;
4311                 // }
4312                 // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4313                 // }
4314                 // getNextToken();
4315                 // } catch (IndexOutOfBoundsException e) {
4316                 // throwSyntaxError("'\'' expected at end of static string.");
4317                 // }
4318                 // break;
4319                 // case TokenNameEncapsedString2:
4320                 // try {
4321                 // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4322                 // while (scanner.currentCharacter != '"') {
4323                 // if (scanner.currentCharacter == '\\') {
4324                 // scanner.currentPosition++;
4325                 // }
4326                 // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4327                 // }
4328                 // getNextToken();
4329                 // } catch (IndexOutOfBoundsException e) {
4330                 // throwSyntaxError("'\"' expected at end of static string.");
4331                 // }
4332                 // break;
4333                 case TokenNameStringSingleQuote:
4334                         getNextToken();
4335                         break;
4336                 case TokenNameStringDoubleQuote:
4337                         getNextToken();
4338                         break;
4339                 case TokenNamePLUS:
4340                         getNextToken();
4341                         static_scalar();
4342                         break;
4343                 case TokenNameMINUS:
4344                         getNextToken();
4345                         static_scalar();
4346                         break;
4347                 case TokenNamearray:
4348                         getNextToken();
4349                         if (token != TokenNameLPAREN) {
4350                                 throwSyntaxError("'(' expected after keyword 'array'");
4351                         }
4352                         getNextToken();
4353                         if (token == TokenNameRPAREN) {
4354                                 getNextToken();
4355                                 break;
4356                         }
4357                         non_empty_static_array_pair_list();
4358                         if (token != TokenNameRPAREN) {
4359                                 throwSyntaxError("')' or ',' expected after keyword 'array'");
4360                         }
4361                         getNextToken();
4362                         break;
4363                 // case TokenNamenull :
4364                 // getNextToken();
4365                 // break;
4366                 // case TokenNamefalse :
4367                 // getNextToken();
4368                 // break;
4369                 // case TokenNametrue :
4370                 // getNextToken();
4371                 // break;
4372                 default:
4373                         throwSyntaxError("Static scalar/constant expected.");
4374                 }
4375         }
4376
4377         private void non_empty_static_array_pair_list() {
4378                 // non_empty_static_array_pair_list:
4379                 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
4380                 // static_scalar
4381                 // | non_empty_static_array_pair_list ',' static_scalar
4382                 // | static_scalar T_DOUBLE_ARROW static_scalar
4383                 // | static_scalar
4384                 while (true) {
4385                         static_scalar();
4386                         if (token == TokenNameEQUAL_GREATER) {
4387                                 getNextToken();
4388                                 static_scalar();
4389                         }
4390                         if (token != TokenNameCOMMA) {
4391                                 break;
4392                         }
4393                         getNextToken();
4394                         if (token == TokenNameRPAREN) {
4395                                 break;
4396                         }
4397                 }
4398         }
4399
4400         // public void reportSyntaxError() { //int act, int currentKind, int
4401         // // stateStackTop) {
4402         // /* remember current scanner position */
4403         // int startPos = scanner.startPosition;
4404         // int currentPos = scanner.currentPosition;
4405         //
4406         // this.checkAndReportBracketAnomalies(problemReporter());
4407         // /* reset scanner where it was */
4408         // scanner.startPosition = startPos;
4409         // scanner.currentPosition = currentPos;
4410         // }
4411
4412         public static final int RoundBracket = 0;
4413
4414         public static final int SquareBracket = 1;
4415
4416         public static final int CurlyBracket = 2;
4417
4418         public static final int BracketKinds = 3;
4419
4420         protected int[] nestedMethod; // the ptr is nestedType
4421
4422         protected int nestedType, dimensions;
4423
4424         // variable set stack
4425         final static int VariableStackIncrement = 10;
4426
4427         HashMap fTypeVariables = null;
4428
4429         HashMap fMethodVariables = null;
4430
4431         ArrayList fStackUnassigned = new ArrayList();
4432
4433         // ast stack
4434         final static int AstStackIncrement = 100;
4435
4436         protected int astPtr;
4437
4438         protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
4439
4440         protected int astLengthPtr;
4441
4442         protected int[] astLengthStack;
4443
4444         ASTNode[] noAstNodes = new ASTNode[AstStackIncrement];
4445
4446         public CompilationUnitDeclaration compilationUnit; /*
4447                                                                                                                  * the result from
4448                                                                                                                  * parse()
4449                                                                                                                  */
4450
4451         protected ReferenceContext referenceContext;
4452
4453         protected ProblemReporter problemReporter;
4454
4455         protected CompilerOptions options;
4456
4457         private ArrayList includesList;
4458
4459         // protected CompilationResult compilationResult;
4460         /**
4461          * Returns this parser's problem reporter initialized with its reference
4462          * context. Also it is assumed that a problem is going to be reported, so
4463          * initializes the compilation result's line positions.
4464          */
4465         public ProblemReporter problemReporter() {
4466                 if (scanner.recordLineSeparator) {
4467                         compilationUnit.compilationResult.lineSeparatorPositions = scanner
4468                                         .getLineEnds();
4469                 }
4470                 problemReporter.referenceContext = referenceContext;
4471                 return problemReporter;
4472         }
4473
4474         /*
4475          * Reconsider the entire source looking for inconsistencies in {} () []
4476          */
4477         // public boolean checkAndReportBracketAnomalies(ProblemReporter
4478         // problemReporter) {
4479         // scanner.wasAcr = false;
4480         // boolean anomaliesDetected = false;
4481         // try {
4482         // char[] source = scanner.source;
4483         // int[] leftCount = { 0, 0, 0 };
4484         // int[] rightCount = { 0, 0, 0 };
4485         // int[] depths = { 0, 0, 0 };
4486         // int[][] leftPositions = new int[][] { new int[10], new int[10], new
4487         // int[10]
4488         // };
4489         // int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10]
4490         // };
4491         // int[][] rightPositions = new int[][] { new int[10], new int[10], new
4492         // int[10] };
4493         // int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10]
4494         // };
4495         // scanner.currentPosition = scanner.initialPosition; //starting
4496         // // point
4497         // // (first-zero-based
4498         // // char)
4499         // while (scanner.currentPosition < scanner.eofPosition) { //loop for
4500         // // jumping
4501         // // over
4502         // // comments
4503         // try {
4504         // // ---------Consume white space and handles
4505         // // startPosition---------
4506         // boolean isWhiteSpace;
4507         // do {
4508         // scanner.startPosition = scanner.currentPosition;
4509         // // if (((scanner.currentCharacter =
4510         // // source[scanner.currentPosition++]) == '\\') &&
4511         // // (source[scanner.currentPosition] == 'u')) {
4512         // // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
4513         // // } else {
4514         // if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') ||
4515         // (scanner.currentCharacter == '\n'))) {
4516         // if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
4517         // // only record line positions we have not
4518         // // recorded yet
4519         // scanner.pushLineSeparator();
4520         // }
4521         // }
4522         // isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
4523         // // }
4524         // } while (isWhiteSpace && (scanner.currentPosition <
4525         // scanner.eofPosition));
4526         // // -------consume token until } is found---------
4527         // switch (scanner.currentCharacter) {
4528         // case '{': {
4529         // int index = leftCount[CurlyBracket]++;
4530         // if (index == leftPositions[CurlyBracket].length) {
4531         // System.arraycopy(leftPositions[CurlyBracket], 0,
4532         // (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
4533         // System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] =
4534         // new int[index * 2]), 0, index);
4535         // }
4536         // leftPositions[CurlyBracket][index] = scanner.startPosition;
4537         // leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
4538         // }
4539         // break;
4540         // case '}': {
4541         // int index = rightCount[CurlyBracket]++;
4542         // if (index == rightPositions[CurlyBracket].length) {
4543         // System.arraycopy(rightPositions[CurlyBracket], 0,
4544         // (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
4545         // System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket]
4546         // =
4547         // new int[index * 2]), 0, index);
4548         // }
4549         // rightPositions[CurlyBracket][index] = scanner.startPosition;
4550         // rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
4551         // }
4552         // break;
4553         // case '(': {
4554         // int index = leftCount[RoundBracket]++;
4555         // if (index == leftPositions[RoundBracket].length) {
4556         // System.arraycopy(leftPositions[RoundBracket], 0,
4557         // (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
4558         // System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] =
4559         // new int[index * 2]), 0, index);
4560         // }
4561         // leftPositions[RoundBracket][index] = scanner.startPosition;
4562         // leftDepths[RoundBracket][index] = depths[RoundBracket]++;
4563         // }
4564         // break;
4565         // case ')': {
4566         // int index = rightCount[RoundBracket]++;
4567         // if (index == rightPositions[RoundBracket].length) {
4568         // System.arraycopy(rightPositions[RoundBracket], 0,
4569         // (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
4570         // System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket]
4571         // =
4572         // new int[index * 2]), 0, index);
4573         // }
4574         // rightPositions[RoundBracket][index] = scanner.startPosition;
4575         // rightDepths[RoundBracket][index] = --depths[RoundBracket];
4576         // }
4577         // break;
4578         // case '[': {
4579         // int index = leftCount[SquareBracket]++;
4580         // if (index == leftPositions[SquareBracket].length) {
4581         // System.arraycopy(leftPositions[SquareBracket], 0,
4582         // (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
4583         // System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket]
4584         // =
4585         // new int[index * 2]), 0, index);
4586         // }
4587         // leftPositions[SquareBracket][index] = scanner.startPosition;
4588         // leftDepths[SquareBracket][index] = depths[SquareBracket]++;
4589         // }
4590         // break;
4591         // case ']': {
4592         // int index = rightCount[SquareBracket]++;
4593         // if (index == rightPositions[SquareBracket].length) {
4594         // System.arraycopy(rightPositions[SquareBracket], 0,
4595         // (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
4596         // System.arraycopy(rightDepths[SquareBracket], 0,
4597         // (rightDepths[SquareBracket]
4598         // = new int[index * 2]), 0, index);
4599         // }
4600         // rightPositions[SquareBracket][index] = scanner.startPosition;
4601         // rightDepths[SquareBracket][index] = --depths[SquareBracket];
4602         // }
4603         // break;
4604         // case '\'': {
4605         // if (scanner.getNextChar('\\')) {
4606         // scanner.scanEscapeCharacter();
4607         // } else { // consume next character
4608         // scanner.unicodeAsBackSlash = false;
4609         // // if (((scanner.currentCharacter =
4610         // // source[scanner.currentPosition++]) ==
4611         // // '\\') &&
4612         // // (source[scanner.currentPosition] ==
4613         // // 'u')) {
4614         // // scanner.getNextUnicodeChar();
4615         // // } else {
4616         // if (scanner.withoutUnicodePtr != 0) {
4617         // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
4618         // scanner.currentCharacter;
4619         // }
4620         // // }
4621         // }
4622         // scanner.getNextChar('\'');
4623         // break;
4624         // }
4625         // case '"':
4626         // // consume next character
4627         // scanner.unicodeAsBackSlash = false;
4628         // // if (((scanner.currentCharacter =
4629         // // source[scanner.currentPosition++]) == '\\') &&
4630         // // (source[scanner.currentPosition] == 'u')) {
4631         // // scanner.getNextUnicodeChar();
4632         // // } else {
4633         // if (scanner.withoutUnicodePtr != 0) {
4634         // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
4635         // scanner.currentCharacter;
4636         // }
4637         // // }
4638         // while (scanner.currentCharacter != '"') {
4639         // if (scanner.currentCharacter == '\r') {
4640         // if (source[scanner.currentPosition] == '\n')
4641         // scanner.currentPosition++;
4642         // break; // the string cannot go further that
4643         // // the line
4644         // }
4645         // if (scanner.currentCharacter == '\n') {
4646         // break; // the string cannot go further that
4647         // // the line
4648         // }
4649         // if (scanner.currentCharacter == '\\') {
4650         // scanner.scanEscapeCharacter();
4651         // }
4652         // // consume next character
4653         // scanner.unicodeAsBackSlash = false;
4654         // // if (((scanner.currentCharacter =
4655         // // source[scanner.currentPosition++]) == '\\')
4656         // // && (source[scanner.currentPosition] == 'u'))
4657         // // {
4658         // // scanner.getNextUnicodeChar();
4659         // // } else {
4660         // if (scanner.withoutUnicodePtr != 0) {
4661         // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
4662         // scanner.currentCharacter;
4663         // }
4664         // // }
4665         // }
4666         // break;
4667         // case '/': {
4668         // int test;
4669         // if ((test = scanner.getNextChar('/', '*')) == 0) { //line
4670         // // comment
4671         // //get the next char
4672         // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
4673         // '\\')
4674         // && (source[scanner.currentPosition] == 'u')) {
4675         // //-------------unicode traitement
4676         // // ------------
4677         // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4678         // scanner.currentPosition++;
4679         // while (source[scanner.currentPosition] == 'u') {
4680         // scanner.currentPosition++;
4681         // }
4682         // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
4683         // 15 || c1 < 0
4684         // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
4685         // 15
4686         // || c2 < 0
4687         // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
4688         // 15
4689         // || c3 < 0
4690         // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
4691         // 15
4692         // || c4 < 0) { //error
4693         // // don't
4694         // // care of the
4695         // // value
4696         // scanner.currentCharacter = 'A';
4697         // } //something different from \n and \r
4698         // else {
4699         // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4700         // }
4701         // }
4702         // while (scanner.currentCharacter != '\r' && scanner.currentCharacter !=
4703         // '\n') {
4704         // //get the next char
4705         // scanner.startPosition = scanner.currentPosition;
4706         // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
4707         // '\\')
4708         // && (source[scanner.currentPosition] == 'u')) {
4709         // //-------------unicode traitement
4710         // // ------------
4711         // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4712         // scanner.currentPosition++;
4713         // while (source[scanner.currentPosition] == 'u') {
4714         // scanner.currentPosition++;
4715         // }
4716         // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
4717         // 15 || c1 < 0
4718         // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
4719         // 15
4720         // || c2 < 0
4721         // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
4722         // 15
4723         // || c3 < 0
4724         // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
4725         // 15
4726         // || c4 < 0) { //error
4727         // // don't
4728         // // care of the
4729         // // value
4730         // scanner.currentCharacter = 'A';
4731         // } //something different from \n
4732         // // and \r
4733         // else {
4734         // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4735         // }
4736         // }
4737         // }
4738         // if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') ||
4739         // (scanner.currentCharacter == '\n'))) {
4740         // if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
4741         // // only record line positions we
4742         // // have not recorded yet
4743         // scanner.pushLineSeparator();
4744         // if (this.scanner.taskTags != null) {
4745         // this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(),
4746         // this.scanner
4747         // .getCurrentTokenEndPosition());
4748         // }
4749         // }
4750         // }
4751         // break;
4752         // }
4753         // if (test > 0) { //traditional and annotation
4754         // // comment
4755         // boolean star = false;
4756         // // consume next character
4757         // scanner.unicodeAsBackSlash = false;
4758         // // if (((scanner.currentCharacter =
4759         // // source[scanner.currentPosition++]) ==
4760         // // '\\') &&
4761         // // (source[scanner.currentPosition] ==
4762         // // 'u')) {
4763         // // scanner.getNextUnicodeChar();
4764         // // } else {
4765         // if (scanner.withoutUnicodePtr != 0) {
4766         // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
4767         // scanner.currentCharacter;
4768         // }
4769         // // }
4770         // if (scanner.currentCharacter == '*') {
4771         // star = true;
4772         // }
4773         // //get the next char
4774         // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
4775         // '\\')
4776         // && (source[scanner.currentPosition] == 'u')) {
4777         // //-------------unicode traitement
4778         // // ------------
4779         // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4780         // scanner.currentPosition++;
4781         // while (source[scanner.currentPosition] == 'u') {
4782         // scanner.currentPosition++;
4783         // }
4784         // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
4785         // 15 || c1 < 0
4786         // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
4787         // 15
4788         // || c2 < 0
4789         // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
4790         // 15
4791         // || c3 < 0
4792         // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
4793         // 15
4794         // || c4 < 0) { //error
4795         // // don't
4796         // // care of the
4797         // // value
4798         // scanner.currentCharacter = 'A';
4799         // } //something different from * and /
4800         // else {
4801         // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4802         // }
4803         // }
4804         // //loop until end of comment */
4805         // while ((scanner.currentCharacter != '/') || (!star)) {
4806         // star = scanner.currentCharacter == '*';
4807         // //get next char
4808         // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
4809         // '\\')
4810         // && (source[scanner.currentPosition] == 'u')) {
4811         // //-------------unicode traitement
4812         // // ------------
4813         // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4814         // scanner.currentPosition++;
4815         // while (source[scanner.currentPosition] == 'u') {
4816         // scanner.currentPosition++;
4817         // }
4818         // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
4819         // 15 || c1 < 0
4820         // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
4821         // 15
4822         // || c2 < 0
4823         // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
4824         // 15
4825         // || c3 < 0
4826         // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
4827         // 15
4828         // || c4 < 0) { //error
4829         // // don't
4830         // // care of the
4831         // // value
4832         // scanner.currentCharacter = 'A';
4833         // } //something different from * and
4834         // // /
4835         // else {
4836         // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4837         // }
4838         // }
4839         // }
4840         // if (this.scanner.taskTags != null) {
4841         // this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(),
4842         // this.scanner.getCurrentTokenEndPosition());
4843         // }
4844         // break;
4845         // }
4846         // break;
4847         // }
4848         // default:
4849         // if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
4850         // scanner.scanIdentifierOrKeyword(false);
4851         // break;
4852         // }
4853         // if (Character.isDigit(scanner.currentCharacter)) {
4854         // scanner.scanNumber(false);
4855         // break;
4856         // }
4857         // }
4858         // //-----------------end switch while
4859         // // try--------------------
4860         // } catch (IndexOutOfBoundsException e) {
4861         // break; // read until EOF
4862         // } catch (InvalidInputException e) {
4863         // return false; // no clue
4864         // }
4865         // }
4866         // if (scanner.recordLineSeparator) {
4867         // compilationUnit.compilationResult.lineSeparatorPositions =
4868         // scanner.getLineEnds();
4869         // }
4870         // // check placement anomalies against other kinds of brackets
4871         // for (int kind = 0; kind < BracketKinds; kind++) {
4872         // for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
4873         // int start = leftPositions[kind][leftIndex]; // deepest
4874         // // first
4875         // // find matching closing bracket
4876         // int depth = leftDepths[kind][leftIndex];
4877         // int end = -1;
4878         // for (int i = 0; i < rightCount[kind]; i++) {
4879         // int pos = rightPositions[kind][i];
4880         // // want matching bracket further in source with same
4881         // // depth
4882         // if ((pos > start) && (depth == rightDepths[kind][i])) {
4883         // end = pos;
4884         // break;
4885         // }
4886         // }
4887         // if (end < 0) { // did not find a good closing match
4888         // problemReporter.unmatchedBracket(start, referenceContext,
4889         // compilationUnit.compilationResult);
4890         // return true;
4891         // }
4892         // // check if even number of opening/closing other brackets
4893         // // in between this pair of brackets
4894         // int balance = 0;
4895         // for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds);
4896         // otherKind++) {
4897         // for (int i = 0; i < leftCount[otherKind]; i++) {
4898         // int pos = leftPositions[otherKind][i];
4899         // if ((pos > start) && (pos < end))
4900         // balance++;
4901         // }
4902         // for (int i = 0; i < rightCount[otherKind]; i++) {
4903         // int pos = rightPositions[otherKind][i];
4904         // if ((pos > start) && (pos < end))
4905         // balance--;
4906         // }
4907         // if (balance != 0) {
4908         // problemReporter.unmatchedBracket(start, referenceContext,
4909         // compilationUnit.compilationResult); //bracket
4910         // // anomaly
4911         // return true;
4912         // }
4913         // }
4914         // }
4915         // // too many opening brackets ?
4916         // for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
4917         // anomaliesDetected = true;
4918         // problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i
4919         // -
4920         // 1], referenceContext,
4921         // compilationUnit.compilationResult);
4922         // }
4923         // // too many closing brackets ?
4924         // for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
4925         // anomaliesDetected = true;
4926         // problemReporter.unmatchedBracket(rightPositions[kind][i],
4927         // referenceContext,
4928         // compilationUnit.compilationResult);
4929         // }
4930         // if (anomaliesDetected)
4931         // return true;
4932         // }
4933         // return anomaliesDetected;
4934         // } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
4935         // return anomaliesDetected;
4936         // } catch (NullPointerException e) { // jdk1.2.2 jit bug
4937         // return anomaliesDetected;
4938         // }
4939         // }
4940         protected void pushOnAstLengthStack(int pos) {
4941                 try {
4942                         astLengthStack[++astLengthPtr] = pos;
4943                 } catch (IndexOutOfBoundsException e) {
4944                         int oldStackLength = astLengthStack.length;
4945                         int[] oldPos = astLengthStack;
4946                         astLengthStack = new int[oldStackLength + StackIncrement];
4947                         System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
4948                         astLengthStack[astLengthPtr] = pos;
4949                 }
4950         }
4951
4952         protected void pushOnAstStack(ASTNode node) {
4953                 /*
4954                  * add a new obj on top of the ast stack
4955                  */
4956                 try {
4957                         astStack[++astPtr] = node;
4958                 } catch (IndexOutOfBoundsException e) {
4959                         int oldStackLength = astStack.length;
4960                         ASTNode[] oldStack = astStack;
4961                         astStack = new ASTNode[oldStackLength + AstStackIncrement];
4962                         System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
4963                         astPtr = oldStackLength;
4964                         astStack[astPtr] = node;
4965                 }
4966                 try {
4967                         astLengthStack[++astLengthPtr] = 1;
4968                 } catch (IndexOutOfBoundsException e) {
4969                         int oldStackLength = astLengthStack.length;
4970                         int[] oldPos = astLengthStack;
4971                         astLengthStack = new int[oldStackLength + AstStackIncrement];
4972                         System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
4973                         astLengthStack[astLengthPtr] = 1;
4974                 }
4975         }
4976
4977         protected void resetModifiers() {
4978                 this.modifiers = AccDefault;
4979                 this.modifiersSourceStart = -1; // <-- see comment into
4980                 // modifiersFlag(int)
4981                 this.scanner.commentPtr = -1;
4982         }
4983
4984         protected void consumePackageDeclarationName(IFile file) {
4985                 // create a package name similar to java package names
4986                 String projectPath = ProjectPrefUtil.getDocumentRoot(file.getProject())
4987                                 .toString();
4988                 String filePath = file.getRawLocation().toString();
4989                 String ext = file.getRawLocation().getFileExtension();
4990                 int fileExtensionLength = ext == null ? 0 : ext.length() + 1;
4991                 ImportReference impt;
4992                 char[][] tokens;
4993                 if (filePath.startsWith(projectPath)) {
4994                         tokens = CharOperation.splitOn('/', filePath.toCharArray(),
4995                                         projectPath.length() + 1, filePath.length()
4996                                                         - fileExtensionLength);
4997                 } else {
4998                         String name = file.getName();
4999                         tokens = new char[1][];
5000                         tokens[0] = name.substring(0, name.length() - fileExtensionLength)
5001                                         .toCharArray();
5002                 }
5003
5004                 this.compilationUnit.currentPackage = impt = new ImportReference(
5005                                 tokens, new char[0], 0, 0, true);
5006
5007                 impt.declarationSourceStart = 0;
5008                 impt.declarationSourceEnd = 0;
5009                 impt.declarationEnd = 0;
5010                 // endPosition is just before the ;
5011
5012         }
5013
5014         public final static String[] GLOBALS = { "$this", "$_COOKIE", "$_ENV",
5015                         "$_FILES", "$_GET", "$GLOBALS", "$_POST", "$_REQUEST", "$_SESSION",
5016                         "$_SERVER" };
5017
5018         /**
5019          * 
5020          */
5021         private void pushFunctionVariableSet() {
5022                 HashSet set = new HashSet();
5023                 if (fStackUnassigned.isEmpty()) {
5024                         for (int i = 0; i < GLOBALS.length; i++) {
5025                                 set.add(GLOBALS[i]);
5026                         }
5027                 }
5028                 fStackUnassigned.add(set);
5029         }
5030
5031         private void pushIfVariableSet() {
5032                 if (!fStackUnassigned.isEmpty()) {
5033                         HashSet set = new HashSet();
5034                         fStackUnassigned.add(set);
5035                 }
5036         }
5037
5038         private HashSet removeIfVariableSet() {
5039                 if (!fStackUnassigned.isEmpty()) {
5040                         return (HashSet) fStackUnassigned
5041                                         .remove(fStackUnassigned.size() - 1);
5042                 }
5043                 return null;
5044         }
5045
5046         /**
5047          * Returns the <i>set of assigned variables </i> returns null if no Set is
5048          * defined at the current scanner position
5049          */
5050         private HashSet peekVariableSet() {
5051                 if (!fStackUnassigned.isEmpty()) {
5052                         return (HashSet) fStackUnassigned.get(fStackUnassigned.size() - 1);
5053                 }
5054                 return null;
5055         }
5056
5057         /**
5058          * add the current identifier source to the <i>set of assigned variables
5059          * </i>
5060          * 
5061          * @param set
5062          */
5063         private void addVariableSet(HashSet set) {
5064                 if (set != null) {
5065                         set.add(new String(scanner.getCurrentTokenSource()));
5066                 }
5067         }
5068
5069         /**
5070          * add the current identifier source to the <i>set of assigned variables
5071          * </i>
5072          * 
5073          */
5074         private void addVariableSet() {
5075                 HashSet set = peekVariableSet();
5076                 if (set != null) {
5077                         set.add(new String(scanner.getCurrentTokenSource()));
5078                 }
5079         }
5080
5081         /**
5082          * add the current identifier source to the <i>set of assigned variables
5083          * </i>
5084          * 
5085          */
5086         private void addVariableSet(char[] token) {
5087                 HashSet set = peekVariableSet();
5088                 if (set != null) {
5089                         set.add(new String(token));
5090                 }
5091         }
5092
5093         /**
5094          * check if the current identifier source is in the <i>set of assigned
5095          * variables </i> Returns true, if no set is defined for the current scanner
5096          * position
5097          * 
5098          */
5099         private boolean containsVariableSet() {
5100                 return containsVariableSet(scanner.getCurrentTokenSource());
5101         }
5102
5103         private boolean containsVariableSet(char[] token) {
5104
5105                 if (!fStackUnassigned.isEmpty()) {
5106                         HashSet set;
5107                         String str = new String(token);
5108                         for (int i = 0; i < fStackUnassigned.size(); i++) {
5109                                 set = (HashSet) fStackUnassigned.get(i);
5110                                 if (set.contains(str)) {
5111                                         return true;
5112                                 }
5113                         }
5114                         return false;
5115                 }
5116                 return true;
5117         }
5118 }