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