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