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