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