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