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