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