e7491b1c62964ddfd3d5d379160ba7dcf4eb9cde
[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       // default super class
927       typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
928       compilationUnit.types.add(typeDecl);
929       try {
930         pushOnAstStack(typeDecl);
931         unticked_class_declaration_statement(typeDecl);
932         //        classBody(typeDecl);
933       } finally {
934         astPtr--;
935         astLengthPtr--;
936       }
937       return;
938       //      } else {
939       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
940     } else if (token == TokenNameLBRACE) {
941       getNextToken();
942       if (token != TokenNameRBRACE) {
943         statementList();
944       }
945       if (token == TokenNameRBRACE) {
946         getNextToken();
947         return;
948       } else {
949         throwSyntaxError("'}' expected.");
950       }
951     } else {
952       if (token != TokenNameSEMICOLON) {
953         expr();
954       }
955       if (token == TokenNameSEMICOLON) {
956         getNextToken();
957         return;
958       } else {
959         if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
960           throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
961         }
962         getNextToken();
963       }
964     }
965   }
966   private void additional_catches() {
967     while (token == TokenNamecatch) {
968       getNextToken();
969       if (token != TokenNameLPAREN) {
970         throwSyntaxError("'(' expected in 'catch' statement.");
971       }
972       getNextToken();
973       fully_qualified_class_name();
974       if (token != TokenNameVariable) {
975         throwSyntaxError("Variable expected in 'catch' statement.");
976       }
977       getNextToken();
978       if (token != TokenNameRPAREN) {
979         throwSyntaxError("')' expected in 'catch' statement.");
980       }
981       getNextToken();
982       if (token != TokenNameLBRACE) {
983         throwSyntaxError("'{' expected in 'catch' statement.");
984       }
985       getNextToken();
986       statementList();
987       if (token != TokenNameRBRACE) {
988         throwSyntaxError("'}' expected in 'catch' statement.");
989       }
990       getNextToken();
991     }
992   }
993   private void foreach_variable() {
994     //  w_variable
995     //| '&' w_variable
996     if (token == TokenNameAND) {
997       getNextToken();
998     }
999     w_variable();
1000   }
1001   private void foreach_optional_arg() {
1002     //  /* empty */
1003     //| T_DOUBLE_ARROW foreach_variable
1004     if (token == TokenNameEQUAL_GREATER) {
1005       getNextToken();
1006       foreach_variable();
1007     }
1008   }
1009   private void global_var_list() {
1010     //  global_var_list:
1011     //  global_var_list ',' global_var
1012     //| global_var
1013     while (true) {
1014       global_var();
1015       if (token != TokenNameCOMMA) {
1016         break;
1017       }
1018       getNextToken();
1019     }
1020   }
1021   private void global_var() {
1022     //global_var:
1023     //  T_VARIABLE
1024     //| '$' r_variable
1025     //| '$' '{' expr '}'
1026     if (token == TokenNameVariable) {
1027       getNextToken();
1028     } else if (token == TokenNameDOLLAR) {
1029       getNextToken();
1030       if (token == TokenNameLPAREN) {
1031         getNextToken();
1032         expr();
1033         if (token != TokenNameLPAREN) {
1034           throwSyntaxError("')' expected in global variable.");
1035         }
1036         getNextToken();
1037       } else {
1038         r_variable();
1039       }
1040     }
1041   }
1042   private void static_var_list() {
1043     //static_var_list:
1044     //  static_var_list ',' T_VARIABLE
1045     //| static_var_list ',' T_VARIABLE '=' static_scalar
1046     //| T_VARIABLE
1047     //| T_VARIABLE '=' static_scalar
1048     while (true) {
1049       if (token == TokenNameVariable) {
1050         getNextToken();
1051         if (token == TokenNameEQUAL) {
1052           getNextToken();
1053           static_scalar();
1054         }
1055         if (token != TokenNameCOMMA) {
1056           break;
1057         }
1058         getNextToken();
1059       } else {
1060         break;
1061       }
1062     }
1063   }
1064   private void unset_variables() {
1065     //    unset_variables:
1066     //                  unset_variable
1067     //          | unset_variables ',' unset_variable
1068     //    unset_variable:
1069     //                  variable
1070     while (true) {
1071       variable();
1072       if (token != TokenNameCOMMA) {
1073         break;
1074       }
1075       getNextToken();
1076     }
1077   }
1078   private final void initializeModifiers() {
1079     this.modifiers = 0;
1080     this.modifiersSourceStart = -1;
1081   }
1082   private final void checkAndSetModifiers(int flag) {
1083     this.modifiers |= flag;
1084     if (this.modifiersSourceStart < 0)
1085       this.modifiersSourceStart = this.scanner.startPosition;
1086   }
1087   private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1088     initializeModifiers();
1089     if (token == TokenNameinterface) {
1090       //      interface_entry T_STRING
1091       //                interface_extends_list
1092       //                '{' class_statement_list '}'
1093       checkAndSetModifiers(AccInterface);
1094       getNextToken();
1095       typeDecl.modifiers = this.modifiers;
1096       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1097         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1098         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1099         typeDecl.name = scanner.getCurrentIdentifierSource();
1100         if (token > TokenNameKEYWORD) {
1101           throwSyntaxError("Don't use a keyword for interface declaration [" + scanner.toStringAction(token) + "].",
1102               typeDecl.sourceStart, typeDecl.sourceEnd);
1103         }
1104         getNextToken();
1105         interface_extends_list();
1106       } else {
1107         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1108         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1109         typeDecl.name = new char[]{' '};
1110         throwSyntaxError("Interface name expected after keyword 'interface'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1111         return;
1112       }
1113     } else {
1114       //      class_entry_type T_STRING extends_from
1115       //                implements_list
1116       //                '{' class_statement_list'}'
1117       class_entry_type();
1118       typeDecl.modifiers = this.modifiers;
1119       //identifier
1120       //identifier 'extends' identifier
1121       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1122         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1123         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1124         typeDecl.name = scanner.getCurrentIdentifierSource();
1125         if (token > TokenNameKEYWORD) {
1126           throwSyntaxError("Don't use a keyword for class declaration [" + scanner.toStringAction(token) + "].",
1127               typeDecl.sourceStart, typeDecl.sourceEnd);
1128         }
1129         getNextToken();
1130         //    extends_from:
1131         //              /* empty */
1132         //      | T_EXTENDS fully_qualified_class_name
1133         if (token == TokenNameextends) {
1134           interface_extends_list();
1135           //          getNextToken();
1136           //          if (token != TokenNameIdentifier) {
1137           //            throwSyntaxError("Class name expected after keyword
1138           // 'extends'.",
1139           //                scanner.getCurrentTokenStartPosition(), scanner
1140           //                    .getCurrentTokenEndPosition());
1141           //          }
1142         }
1143         implements_list();
1144       } else {
1145         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1146         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1147         typeDecl.name = new char[]{' '};
1148         throwSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1149         return;
1150       }
1151     }
1152     //  '{' class_statement_list '}'
1153     if (token == TokenNameLBRACE) {
1154       getNextToken();
1155       if (token != TokenNameRBRACE) {
1156         ArrayList list = new ArrayList();
1157         class_statement_list(list);
1158         typeDecl.fields = new FieldDeclaration[list.size()];
1159         for (int i = 0; i < list.size(); i++) {
1160           typeDecl.fields[i] = (FieldDeclaration) list.get(i);
1161         }
1162       }
1163       if (token == TokenNameRBRACE) {
1164         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1165         getNextToken();
1166       } else {
1167         throwSyntaxError("'}' expected at end of class body.");
1168       }
1169     } else {
1170       throwSyntaxError("'{' expected at start of class body.");
1171     }
1172   }
1173   private void class_entry_type() {
1174     //  T_CLASS
1175     //  | T_ABSTRACT T_CLASS
1176     //  | T_FINAL T_CLASS
1177     if (token == TokenNameclass) {
1178       getNextToken();
1179     } else if (token == TokenNameabstract) {
1180       checkAndSetModifiers(AccAbstract);
1181       getNextToken();
1182       if (token != TokenNameclass) {
1183         throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1184       }
1185       getNextToken();
1186     } else if (token == TokenNamefinal) {
1187       checkAndSetModifiers(AccFinal);
1188       getNextToken();
1189       if (token != TokenNameclass) {
1190         throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1191       }
1192       getNextToken();
1193     } else {
1194       throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1195     }
1196   }
1197   private void interface_extends_list() {
1198     //  /* empty */
1199     //  | T_EXTENDS interface_list
1200     if (token == TokenNameextends) {
1201       getNextToken();
1202       interface_list();
1203     }
1204   }
1205   private void implements_list() {
1206     //  /* empty */
1207     //  | T_IMPLEMENTS interface_list
1208     if (token == TokenNameimplements) {
1209       getNextToken();
1210       interface_list();
1211     }
1212   }
1213   private void interface_list() {
1214     //  interface_list:
1215     //  fully_qualified_class_name
1216     //| interface_list ',' fully_qualified_class_name
1217     do {
1218       if (token == TokenNameIdentifier) {
1219         getNextToken();
1220       } else {
1221         throwSyntaxError("Interface name expected after keyword 'implements'.");
1222       }
1223       if (token != TokenNameCOMMA) {
1224         return;
1225       }
1226       getNextToken();
1227     } while (true);
1228   }
1229   //  private void classBody(TypeDeclaration typeDecl) {
1230   //    //'{' [class-element-list] '}'
1231   //    if (token == TokenNameLBRACE) {
1232   //      getNextToken();
1233   //      if (token != TokenNameRBRACE) {
1234   //        class_statement_list();
1235   //      }
1236   //      if (token == TokenNameRBRACE) {
1237   //        typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1238   //        getNextToken();
1239   //      } else {
1240   //        throwSyntaxError("'}' expected at end of class body.");
1241   //      }
1242   //    } else {
1243   //      throwSyntaxError("'{' expected at start of class body.");
1244   //    }
1245   //  }
1246   private void class_statement_list(ArrayList list) {
1247     do {
1248       class_statement(list);
1249     } while (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic
1250         || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar
1251         || token == TokenNameconst);
1252   }
1253   private void class_statement(ArrayList list) {
1254     //    class_statement:
1255     //          variable_modifiers class_variable_declaration ';'
1256     //  | class_constant_declaration ';'
1257     //  | method_modifiers T_FUNCTION is_reference T_STRING
1258     //    '(' parameter_list ')' method_body
1259     initializeModifiers();
1260     int declarationSourceStart = scanner.getCurrentTokenStartPosition();
1261     
1262     if (token == TokenNamevar) {
1263       checkAndSetModifiers(AccPublic);
1264       problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
1265           referenceContext, compilationUnit.compilationResult);
1266       getNextToken();
1267       class_variable_declaration(declarationSourceStart, list);
1268     } else if (token == TokenNameconst) {
1269       checkAndSetModifiers(AccFinal|AccPublic);
1270       class_constant_declaration(declarationSourceStart, list);
1271       if (token != TokenNameSEMICOLON) {
1272         throwSyntaxError("';' expected after class const declaration.");
1273       }
1274       getNextToken();
1275     } else {
1276       boolean hasModifiers = member_modifiers();
1277       if (token == TokenNamefunction) {
1278         if (!hasModifiers) {
1279           checkAndSetModifiers(AccPublic);
1280         }
1281         MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1282         methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1283         methodDecl.modifiers = this.modifiers;
1284         getNextToken();
1285         functionDefinition(methodDecl);
1286       } else {
1287         if (!hasModifiers) {
1288           throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1289         }
1290         class_variable_declaration(declarationSourceStart, list);
1291       }
1292     }
1293   }
1294   private void class_constant_declaration(int declarationSourceStart, ArrayList list) {
1295     //  class_constant_declaration ',' T_STRING '=' static_scalar
1296     //  | T_CONST T_STRING '=' static_scalar
1297     if (token != TokenNameconst) {
1298       throwSyntaxError("'const' keyword expected in class declaration.");
1299     } else {
1300       getNextToken();
1301     }
1302     while (true) {
1303       if (token != TokenNameIdentifier) {
1304         throwSyntaxError("Identifier expected in class const declaration.");
1305       }
1306       FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner.getCurrentIdentifierSource(), scanner
1307           .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1308       fieldDeclaration.modifiers = this.modifiers;
1309       fieldDeclaration.declarationSourceStart = declarationSourceStart;
1310       fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1311       fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1312       //        fieldDeclaration.type
1313       list.add(fieldDeclaration);
1314       getNextToken();
1315       if (token != TokenNameEQUAL) {
1316         throwSyntaxError("'=' expected in class const declaration.");
1317       }
1318       getNextToken();
1319       static_scalar();
1320       if (token != TokenNameCOMMA) {
1321         break; // while(true)-loop
1322       }
1323       getNextToken();
1324     }
1325   }
1326   //  private void variable_modifiers() {
1327   //    // variable_modifiers:
1328   //    // non_empty_member_modifiers
1329   //    //| T_VAR
1330   //    initializeModifiers();
1331   //    if (token == TokenNamevar) {
1332   //      checkAndSetModifiers(AccPublic);
1333   //      reportSyntaxError(
1334   //          "Keyword 'var' is deprecated. Please use 'public' 'private' or
1335   // 'protected'
1336   // modifier for field declarations.",
1337   //          scanner.getCurrentTokenStartPosition(), scanner
1338   //              .getCurrentTokenEndPosition());
1339   //      getNextToken();
1340   //    } else {
1341   //      if (!member_modifiers()) {
1342   //        throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1343   // field declarations.");
1344   //      }
1345   //    }
1346   //  }
1347   //  private void method_modifiers() {
1348   //    //method_modifiers:
1349   //    // /* empty */
1350   //    //| non_empty_member_modifiers
1351   //    initializeModifiers();
1352   //    if (!member_modifiers()) {
1353   //      checkAndSetModifiers(AccPublic);
1354   //    }
1355   //  }
1356   private boolean member_modifiers() {
1357     //  T_PUBLIC
1358     //| T_PROTECTED
1359     //| T_PRIVATE
1360     //| T_STATIC
1361     //| T_ABSTRACT
1362     //| T_FINAL
1363     boolean foundToken = false;
1364     while (true) {
1365       if (token == TokenNamepublic) {
1366         checkAndSetModifiers(AccPublic);
1367         getNextToken();
1368         foundToken = true;
1369       } else if (token == TokenNameprotected) {
1370         checkAndSetModifiers(AccProtected);
1371         getNextToken();
1372         foundToken = true;
1373       } else if (token == TokenNameprivate) {
1374         checkAndSetModifiers(AccPrivate);
1375         getNextToken();
1376         foundToken = true;
1377       } else if (token == TokenNamestatic) {
1378         checkAndSetModifiers(AccStatic);
1379         getNextToken();
1380         foundToken = true;
1381       } else if (token == TokenNameabstract) {
1382         checkAndSetModifiers(AccAbstract);
1383         getNextToken();
1384         foundToken = true;
1385       } else if (token == TokenNamefinal) {
1386         checkAndSetModifiers(AccFinal);
1387         getNextToken();
1388         foundToken = true;
1389       } else {
1390         break;
1391       }
1392     }
1393     return foundToken;
1394   }
1395   private void class_variable_declaration(int declarationSourceStart, ArrayList list) {
1396     //    class_variable_declaration:
1397     //          class_variable_declaration ',' T_VARIABLE
1398     //  | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1399     //  | T_VARIABLE
1400     //  | T_VARIABLE '=' static_scalar
1401     char[] classVariable;
1402     do {
1403       if (token == TokenNameVariable) {
1404         classVariable = scanner.getCurrentIdentifierSource();
1405       //  indexManager.addIdentifierInformation('v', classVariable, buf, -1, -1);
1406         FieldDeclaration fieldDeclaration = new FieldDeclaration(classVariable, scanner
1407             .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1408         fieldDeclaration.modifiers = this.modifiers;
1409         fieldDeclaration.declarationSourceStart = declarationSourceStart;
1410         fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1411         fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1412         //        fieldDeclaration.type
1413         list.add(fieldDeclaration);
1414         getNextToken();
1415         if (token == TokenNameEQUAL) {
1416           getNextToken();
1417           static_scalar();
1418         }
1419       } else {
1420         //        if (token == TokenNamethis) {
1421         //          throwSyntaxError("'$this' not allowed after keyword 'public'
1422         // 'protected' 'private' 'var'.");
1423         //        }
1424         throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1425       }
1426       if (token != TokenNameCOMMA) {
1427         break;
1428       }
1429       getNextToken();
1430     } while (true);
1431     if (token != TokenNameSEMICOLON) {
1432       throwSyntaxError("';' expected after field declaration.");
1433     }
1434     getNextToken();
1435   }
1436   private void functionDefinition(MethodDeclaration methodDecl) {
1437     boolean isAbstract = false;
1438     if (astPtr == 0) {
1439       compilationUnit.types.add(methodDecl);
1440     } else {
1441       AstNode node = astStack[astPtr];
1442       if (node instanceof TypeDeclaration) {
1443         TypeDeclaration typeDecl = ((TypeDeclaration) node);
1444         if (typeDecl.methods == null) {
1445           typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1446         } else {
1447           AbstractMethodDeclaration[] newMethods;
1448           System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1,
1449               typeDecl.methods.length);
1450           newMethods[0] = methodDecl;
1451           typeDecl.methods = newMethods;
1452         }
1453         if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
1454           isAbstract = true;
1455         } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
1456           isAbstract = true;
1457         }
1458       }
1459     }
1460     functionDeclarator(methodDecl);
1461     if (token == TokenNameSEMICOLON) {
1462       if (!isAbstract) {
1463         throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector));
1464       }
1465       getNextToken();
1466       return;
1467     }
1468     functionBody(methodDecl);
1469   }
1470   private void functionDeclarator(MethodDeclaration methodDecl) {
1471     //identifier '(' [parameter-list] ')'
1472     if (token == TokenNameAND) {
1473       getNextToken();
1474     }
1475     methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1476     methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1477     if (Scanner.isIdentifierOrKeyword(token)) {
1478       methodDecl.selector = scanner.getCurrentIdentifierSource();
1479       if (token > TokenNameKEYWORD) {
1480         problemReporter.phpKeywordWarning(new String[]{scanner.toStringAction(token)}, scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
1481             referenceContext, compilationUnit.compilationResult);
1482 //        reportSyntaxWarning("Don't use keyword for function declaration [" + scanner.toStringAction(token) + "].",
1483 //          scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1484       }
1485       getNextToken();
1486       if (token == TokenNameLPAREN) {
1487         getNextToken();
1488       } else {
1489         throwSyntaxError("'(' expected in function declaration.");
1490       }
1491       if (token != TokenNameRPAREN) {
1492         parameter_list(); 
1493       }
1494       if (token != TokenNameRPAREN) {
1495         throwSyntaxError("')' expected in function declaration.");
1496       } else {
1497         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1498         getNextToken();
1499       }
1500     } else {
1501       methodDecl.selector = "<undefined>".toCharArray();
1502       throwSyntaxError("Function name expected after keyword 'function'.");
1503     }
1504   }
1505   //
1506   private void parameter_list() {
1507     //  non_empty_parameter_list
1508     //  | /* empty */
1509     non_empty_parameter_list(true);
1510   }
1511   private void non_empty_parameter_list(boolean empty_allowed) {
1512     //  optional_class_type T_VARIABLE
1513     //  | optional_class_type '&' T_VARIABLE
1514     //  | optional_class_type '&' T_VARIABLE '=' static_scalar
1515     //  | optional_class_type T_VARIABLE '=' static_scalar
1516     //  | non_empty_parameter_list ',' optional_class_type T_VARIABLE
1517     //  | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
1518     //  | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
1519     // static_scalar
1520     //  | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
1521     // static_scalar
1522     if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) {
1523       while (true) {
1524         if (token == TokenNameIdentifier) {
1525           getNextToken();
1526         }
1527         if (token == TokenNameAND) {
1528           getNextToken();
1529         }
1530         if (token == TokenNameVariable) {
1531           getNextToken();
1532           if (token == TokenNameEQUAL) {
1533             getNextToken();
1534             static_scalar();
1535           }
1536         } else {
1537           throwSyntaxError("Variable expected in parameter list.");
1538         }
1539         if (token != TokenNameCOMMA) {
1540           break;
1541         }
1542         getNextToken();
1543       }
1544       return;
1545     }
1546     if (!empty_allowed) {
1547       throwSyntaxError("Identifier expected in parameter list.");
1548     }
1549   }
1550   private void optional_class_type() {
1551     //  /* empty */
1552     //| T_STRING
1553   }
1554   private void parameterDeclaration() {
1555     //variable
1556     //variable-reference
1557     if (token == TokenNameAND) {
1558       getNextToken();
1559       if (isVariable()) {
1560         getNextToken();
1561       } else {
1562         throwSyntaxError("Variable expected after reference operator '&'.");
1563       }
1564     }
1565     //variable '=' constant
1566     if (token == TokenNameVariable) {
1567       getNextToken();
1568       if (token == TokenNameEQUAL) {
1569         getNextToken();
1570         static_scalar();
1571       }
1572       return;
1573     }
1574     //    if (token == TokenNamethis) {
1575     //      throwSyntaxError("Reserved word '$this' not allowed in parameter
1576     // declaration.");
1577     //    }
1578   }
1579   private void labeledStatementList() {
1580     if (token != TokenNamecase && token != TokenNamedefault) {
1581       throwSyntaxError("'case' or 'default' expected.");
1582     }
1583     do {
1584       if (token == TokenNamecase) {
1585         getNextToken();
1586         expr(); //constant();
1587         if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1588           getNextToken();
1589           if (token == TokenNamecase || token == TokenNamedefault) {
1590             // empty case statement ?
1591             continue;
1592           }
1593           statementList();
1594         }
1595         //        else if (token == TokenNameSEMICOLON) {
1596         //          setMarker(
1597         //            "':' expected after 'case' keyword (Found token: " +
1598         // scanner.toStringAction(token) + ")",
1599         //            scanner.getCurrentTokenStartPosition(),
1600         //            scanner.getCurrentTokenEndPosition(),
1601         //            INFO);
1602         //          getNextToken();
1603         //          if (token == TokenNamecase) { // empty case statement ?
1604         //            continue;
1605         //          }
1606         //          statementList();
1607         //        }
1608         else {
1609           throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
1610         }
1611       } else { // TokenNamedefault
1612         getNextToken();
1613         if (token == TokenNameCOLON) {
1614           getNextToken();
1615           if (token == TokenNameRBRACE) {
1616             // empty default case
1617             break;
1618           }
1619           statementList();
1620         } else {
1621           throwSyntaxError("':' character after 'default' expected.");
1622         }
1623       }
1624     } while (token == TokenNamecase || token == TokenNamedefault);
1625   }
1626   //  public void labeledStatement() {
1627   //    if (token == TokenNamecase) {
1628   //      getNextToken();
1629   //      constant();
1630   //      if (token == TokenNameDDOT) {
1631   //        getNextToken();
1632   //        statement();
1633   //      } else {
1634   //        throwSyntaxError("':' character after 'case' constant expected.");
1635   //      }
1636   //      return;
1637   //    } else if (token == TokenNamedefault) {
1638   //      getNextToken();
1639   //      if (token == TokenNameDDOT) {
1640   //        getNextToken();
1641   //        statement();
1642   //      } else {
1643   //        throwSyntaxError("':' character after 'default' expected.");
1644   //      }
1645   //      return;
1646   //    }
1647   //  }
1648   //  public void expressionStatement() {
1649   //  }
1650   //  private void inclusionStatement() {
1651   //  }
1652   //  public void compoundStatement() {
1653   //  }
1654   //  public void selectionStatement() {
1655   //  }
1656   //
1657   //  public void iterationStatement() {
1658   //  }
1659   //
1660   //  public void jumpStatement() {
1661   //  }
1662   //
1663   //  public void outputStatement() {
1664   //  }
1665   //
1666   //  public void scopeStatement() {
1667   //  }
1668   //
1669   //  public void flowStatement() {
1670   //  }
1671   //
1672   //  public void definitionStatement() {
1673   //  }
1674   private void ifStatement() {
1675     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1676     if (token == TokenNameCOLON) {
1677       getNextToken();
1678       if (token != TokenNameendif) {
1679         statementList();
1680         switch (token) {
1681           case TokenNameelse :
1682             getNextToken();
1683             if (token == TokenNameCOLON) {
1684               getNextToken();
1685               if (token != TokenNameendif) {
1686                 statementList();
1687               }
1688             } else {
1689               if (token == TokenNameif) { //'else if'
1690                 getNextToken();
1691                 elseifStatementList();
1692               } else {
1693                 throwSyntaxError("':' expected after 'else'.");
1694               }
1695             }
1696             break;
1697           case TokenNameelseif :
1698             getNextToken();
1699             elseifStatementList();
1700             break;
1701         }
1702       }
1703       if (token != TokenNameendif) {
1704         throwSyntaxError("'endif' expected.");
1705       }
1706       getNextToken();
1707       if (token != TokenNameSEMICOLON) {
1708         throwSyntaxError("';' expected after if-statement.");
1709       }
1710       getNextToken();
1711     } else {
1712       // statement [else-statement]
1713       statement(TokenNameEOF);
1714       if (token == TokenNameelseif) {
1715         getNextToken();
1716         if (token == TokenNameLPAREN) {
1717           getNextToken();
1718         } else {
1719           throwSyntaxError("'(' expected after 'elseif' keyword.");
1720         }
1721         expr();
1722         if (token == TokenNameRPAREN) {
1723           getNextToken();
1724         } else {
1725           throwSyntaxError("')' expected after 'elseif' condition.");
1726         }
1727         ifStatement();
1728       } else if (token == TokenNameelse) {
1729         getNextToken();
1730         statement(TokenNameEOF);
1731       }
1732     }
1733   }
1734   private void elseifStatementList() {
1735     do {
1736       elseifStatement();
1737       switch (token) {
1738         case TokenNameelse :
1739           getNextToken();
1740           if (token == TokenNameCOLON) {
1741             getNextToken();
1742             if (token != TokenNameendif) {
1743               statementList();
1744             }
1745             return;
1746           } else {
1747             if (token == TokenNameif) { //'else if'
1748               getNextToken();
1749             } else {
1750               throwSyntaxError("':' expected after 'else'.");
1751             }
1752           }
1753           break;
1754         case TokenNameelseif :
1755           getNextToken();
1756           break;
1757         default :
1758           return;
1759       }
1760     } while (true);
1761   }
1762   private void elseifStatement() {
1763     if (token == TokenNameLPAREN) {
1764       getNextToken();
1765       expr();
1766       if (token != TokenNameRPAREN) {
1767         throwSyntaxError("')' expected in else-if-statement.");
1768       }
1769       getNextToken();
1770       if (token != TokenNameCOLON) {
1771         throwSyntaxError("':' expected in else-if-statement.");
1772       }
1773       getNextToken();
1774       if (token != TokenNameendif) {
1775         statementList();
1776       }
1777     }
1778   }
1779   private void switchStatement() {
1780     if (token == TokenNameCOLON) {
1781       // ':' [labeled-statement-list] 'endswitch' ';'
1782       getNextToken();
1783       labeledStatementList();
1784       if (token != TokenNameendswitch) {
1785         throwSyntaxError("'endswitch' expected.");
1786       }
1787       getNextToken();
1788       if (token != TokenNameSEMICOLON) {
1789         throwSyntaxError("';' expected after switch-statement.");
1790       }
1791       getNextToken();
1792     } else {
1793       // '{' [labeled-statement-list] '}'
1794       if (token != TokenNameLBRACE) {
1795         throwSyntaxError("'{' expected in switch statement.");
1796       }
1797       getNextToken();
1798       if (token != TokenNameRBRACE) {
1799         labeledStatementList();
1800       }
1801       if (token != TokenNameRBRACE) {
1802         throwSyntaxError("'}' expected in switch statement.");
1803       }
1804       getNextToken();
1805     }
1806   }
1807   private void forStatement() {
1808     if (token == TokenNameCOLON) {
1809       getNextToken();
1810       statementList();
1811       if (token != TokenNameendfor) {
1812         throwSyntaxError("'endfor' expected.");
1813       }
1814       getNextToken();
1815       if (token != TokenNameSEMICOLON) {
1816         throwSyntaxError("';' expected after for-statement.");
1817       }
1818       getNextToken();
1819     } else {
1820       statement(TokenNameEOF);
1821     }
1822   }
1823   private void whileStatement() {
1824     // ':' statement-list 'endwhile' ';'
1825     if (token == TokenNameCOLON) {
1826       getNextToken();
1827       statementList();
1828       if (token != TokenNameendwhile) {
1829         throwSyntaxError("'endwhile' expected.");
1830       }
1831       getNextToken();
1832       if (token != TokenNameSEMICOLON) {
1833         throwSyntaxError("';' expected after while-statement.");
1834       }
1835       getNextToken();
1836     } else {
1837       statement(TokenNameEOF);
1838     }
1839   }
1840   private void foreachStatement() {
1841     if (token == TokenNameCOLON) {
1842       getNextToken();
1843       statementList();
1844       if (token != TokenNameendforeach) {
1845         throwSyntaxError("'endforeach' expected.");
1846       }
1847       getNextToken();
1848       if (token != TokenNameSEMICOLON) {
1849         throwSyntaxError("';' expected after foreach-statement.");
1850       }
1851       getNextToken();
1852     } else {
1853       statement(TokenNameEOF);
1854     }
1855   }
1856   //  private void exitStatus() {
1857   //    if (token == TokenNameLPAREN) {
1858   //      getNextToken();
1859   //    } else {
1860   //      throwSyntaxError("'(' expected in 'exit-status'.");
1861   //    }
1862   //    if (token != TokenNameRPAREN) {
1863   //      expression();
1864   //    }
1865   //    if (token == TokenNameRPAREN) {
1866   //      getNextToken();
1867   //    } else {
1868   //      throwSyntaxError("')' expected after 'exit-status'.");
1869   //    }
1870   //  }
1871   private void expressionList() {
1872     do {
1873       expr();
1874       if (token == TokenNameCOMMA) {
1875         getNextToken();
1876       } else {
1877         break;
1878       }
1879     } while (true);
1880   }
1881   private void expr() {
1882     //  r_variable
1883     //  | expr_without_variable
1884     //    if (token!=TokenNameEOF) {
1885     if (Scanner.TRACE) {
1886       System.out.println("TRACE: expr()");
1887     }
1888     expr_without_variable(true);
1889     //    }
1890   }
1891   private void expr_without_variable(boolean only_variable) {
1892     //          internal_functions_in_yacc
1893     //  | T_CLONE expr
1894     //  | T_PRINT expr
1895     //  | '(' expr ')'
1896     //  | '@' expr
1897     //  | '+' expr
1898     //  | '-' expr
1899     //  | '!' expr
1900     //  | '~' expr
1901     //  | T_INC rw_variable
1902     //  | T_DEC rw_variable
1903     //  | T_INT_CAST expr
1904     //  | T_DOUBLE_CAST expr
1905     //  | T_STRING_CAST expr
1906     //  | T_ARRAY_CAST expr
1907     //  | T_OBJECT_CAST expr
1908     //  | T_BOOL_CAST expr
1909     //  | T_UNSET_CAST expr
1910     //  | T_EXIT exit_expr
1911     //  | scalar
1912     //  | T_ARRAY '(' array_pair_list ')'
1913     //  | '`' encaps_list '`'
1914     //  | T_LIST '(' assignment_list ')' '=' expr
1915     //  | T_NEW class_name_reference ctor_arguments
1916     //  | variable '=' expr
1917     //  | variable '=' '&' variable
1918     //  | variable '=' '&' T_NEW class_name_reference ctor_arguments
1919     //  | variable T_PLUS_EQUAL expr
1920     //  | variable T_MINUS_EQUAL expr
1921     //  | variable T_MUL_EQUAL expr
1922     //  | variable T_DIV_EQUAL expr
1923     //  | variable T_CONCAT_EQUAL expr
1924     //  | variable T_MOD_EQUAL expr
1925     //  | variable T_AND_EQUAL expr
1926     //  | variable T_OR_EQUAL expr
1927     //  | variable T_XOR_EQUAL expr
1928     //  | variable T_SL_EQUAL expr
1929     //  | variable T_SR_EQUAL expr
1930     //  | rw_variable T_INC
1931     //  | rw_variable T_DEC
1932     //  | expr T_BOOLEAN_OR expr
1933     //  | expr T_BOOLEAN_AND expr
1934     //  | expr T_LOGICAL_OR expr
1935     //  | expr T_LOGICAL_AND expr
1936     //  | expr T_LOGICAL_XOR expr
1937     //  | expr '|' expr
1938     //  | expr '&' expr
1939     //  | expr '^' expr
1940     //  | expr '.' expr
1941     //  | expr '+' expr
1942     //  | expr '-' expr
1943     //  | expr '*' expr
1944     //  | expr '/' expr
1945     //  | expr '%' expr
1946     //  | expr T_SL expr
1947     //  | expr T_SR expr
1948     //  | expr T_IS_IDENTICAL expr
1949     //  | expr T_IS_NOT_IDENTICAL expr
1950     //  | expr T_IS_EQUAL expr
1951     //  | expr T_IS_NOT_EQUAL expr
1952     //  | expr '<' expr
1953     //  | expr T_IS_SMALLER_OR_EQUAL expr
1954     //  | expr '>' expr
1955     //  | expr T_IS_GREATER_OR_EQUAL expr
1956     //  | expr T_INSTANCEOF class_name_reference
1957     //  | expr '?' expr ':' expr
1958     if (Scanner.TRACE) {
1959       System.out.println("TRACE: expr_without_variable() PART 1");
1960     }
1961     switch (token) {
1962       case TokenNameisset :
1963       case TokenNameempty :
1964       case TokenNameeval :
1965       case TokenNameinclude :
1966       case TokenNameinclude_once :
1967       case TokenNamerequire :
1968       case TokenNamerequire_once :
1969         internal_functions_in_yacc();
1970         break;
1971       //        | '(' expr ')'
1972       case TokenNameLPAREN :
1973         getNextToken();
1974         expr();
1975         if (token == TokenNameRPAREN) {
1976           getNextToken();
1977         } else {
1978           throwSyntaxError("')' expected in expression.");
1979         }
1980         break;
1981       //    | T_CLONE expr
1982       //    | T_PRINT expr
1983       //    | '@' expr
1984       //    | '+' expr
1985       //    | '-' expr
1986       //    | '!' expr
1987       //    | '~' expr
1988       //    | T_INT_CAST expr
1989       //        | T_DOUBLE_CAST expr
1990       //        | T_STRING_CAST expr
1991       //        | T_ARRAY_CAST expr
1992       //        | T_OBJECT_CAST expr
1993       //        | T_BOOL_CAST expr
1994       //        | T_UNSET_CAST expr
1995       case TokenNameclone :
1996       case TokenNameprint :
1997       case TokenNameAT :
1998       case TokenNamePLUS :
1999       case TokenNameMINUS :
2000       case TokenNameNOT :
2001       case TokenNameTWIDDLE :
2002       case TokenNameintCAST :
2003       case TokenNamedoubleCAST :
2004       case TokenNamestringCAST :
2005       case TokenNamearrayCAST :
2006       case TokenNameobjectCAST :
2007       case TokenNameboolCAST :
2008       case TokenNameunsetCAST :
2009         getNextToken();
2010         expr();
2011         break;
2012       case TokenNameexit :
2013         getNextToken();
2014         exit_expr();
2015         break;
2016       //  scalar:
2017       //        T_STRING
2018       //| T_STRING_VARNAME
2019       //| class_constant
2020       //| T_START_HEREDOC encaps_list T_END_HEREDOC
2021       //        | '`' encaps_list '`'
2022       //  | common_scalar
2023       //        | '`' encaps_list '`'
2024       case TokenNameEncapsedString0 :
2025         scanner.encapsedStringStack.push(new Character('`'));
2026         getNextToken();
2027         try {
2028           if (token == TokenNameEncapsedString0) {
2029           } else {
2030             encaps_list();
2031             if (token != TokenNameEncapsedString0) {
2032               throwSyntaxError("\'`\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2033             }
2034           }
2035         } finally {
2036           scanner.encapsedStringStack.pop();
2037           getNextToken();
2038         }
2039         break;
2040       //      | '\'' encaps_list '\''
2041       case TokenNameEncapsedString1 :
2042         scanner.encapsedStringStack.push(new Character('\''));
2043         getNextToken();
2044         try {
2045           if (token == TokenNameEncapsedString1) {
2046           } else {
2047             encaps_list();
2048             if (token != TokenNameEncapsedString1) {
2049               throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2050             }
2051           }
2052         } finally {
2053           scanner.encapsedStringStack.pop();
2054           getNextToken();
2055         }
2056         break;
2057       //| '"' encaps_list '"'
2058       case TokenNameEncapsedString2 :
2059         scanner.encapsedStringStack.push(new Character('"'));
2060         getNextToken();
2061         try {
2062           if (token == TokenNameEncapsedString2) {
2063           } else {
2064             encaps_list();
2065             if (token != TokenNameEncapsedString2) {
2066               throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2067             }
2068           }
2069         } finally {
2070           scanner.encapsedStringStack.pop();
2071           getNextToken();
2072         }
2073         break;
2074       case TokenNameIntegerLiteral :
2075       case TokenNameDoubleLiteral :
2076       case TokenNameStringDoubleQuote :
2077       case TokenNameStringSingleQuote :
2078       case TokenNameStringInterpolated :
2079       case TokenNameFILE :
2080       case TokenNameLINE :
2081       case TokenNameCLASS_C :
2082       case TokenNameMETHOD_C :
2083       case TokenNameFUNC_C :
2084         common_scalar();
2085         break;
2086       case TokenNameHEREDOC :
2087         getNextToken();
2088         break;
2089       case TokenNamearray :
2090         //    T_ARRAY '(' array_pair_list ')'
2091         getNextToken();
2092         if (token == TokenNameLPAREN) {
2093           getNextToken();
2094           if (token == TokenNameRPAREN) {
2095             getNextToken();
2096             break;
2097           }
2098           array_pair_list();
2099           if (token != TokenNameRPAREN) {
2100             throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2101           }
2102           getNextToken();
2103         } else {
2104           throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2105         }
2106         break;
2107       case TokenNamelist :
2108         //    | T_LIST '(' assignment_list ')' '=' expr
2109         getNextToken();
2110         if (token == TokenNameLPAREN) {
2111           getNextToken();
2112           assignment_list();
2113           if (token != TokenNameRPAREN) {
2114             throwSyntaxError("')' expected after 'list' keyword.");
2115           }
2116           getNextToken();
2117           if (token != TokenNameEQUAL) {
2118             throwSyntaxError("'=' expected after 'list' keyword.");
2119           }
2120           getNextToken();
2121           expr();
2122         } else {
2123           throwSyntaxError("'(' expected after 'list' keyword.");
2124         }
2125         break;
2126       case TokenNamenew :
2127         //      | T_NEW class_name_reference ctor_arguments
2128         getNextToken();
2129         class_name_reference();
2130         ctor_arguments();
2131         break;
2132       //        | T_INC rw_variable
2133       //        | T_DEC rw_variable
2134       case TokenNamePLUS_PLUS :
2135       case TokenNameMINUS_MINUS :
2136         getNextToken();
2137         rw_variable();
2138         break;
2139       //        | variable '=' expr
2140       //        | variable '=' '&' variable
2141       //        | variable '=' '&' T_NEW class_name_reference ctor_arguments
2142       //        | variable T_PLUS_EQUAL expr
2143       //        | variable T_MINUS_EQUAL expr
2144       //        | variable T_MUL_EQUAL expr
2145       //        | variable T_DIV_EQUAL expr
2146       //        | variable T_CONCAT_EQUAL expr
2147       //        | variable T_MOD_EQUAL expr
2148       //        | variable T_AND_EQUAL expr
2149       //        | variable T_OR_EQUAL expr
2150       //        | variable T_XOR_EQUAL expr
2151       //        | variable T_SL_EQUAL expr
2152       //        | variable T_SR_EQUAL expr
2153       //        | rw_variable T_INC
2154       //        | rw_variable T_DEC
2155       case TokenNameIdentifier :
2156       case TokenNameVariable :
2157       case TokenNameDOLLAR :
2158         variable();
2159         switch (token) {
2160           case TokenNameEQUAL :
2161             getNextToken();
2162             if (token == TokenNameAND) {
2163               getNextToken();
2164               if (token == TokenNamenew) {
2165                 // | variable '=' '&' T_NEW class_name_reference
2166                 // ctor_arguments
2167                 getNextToken();
2168                 class_name_reference();
2169                 ctor_arguments();
2170               } else {
2171                 variable();
2172               }
2173             } else {
2174               expr();
2175             }
2176             break;
2177           case TokenNamePLUS_EQUAL :
2178           case TokenNameMINUS_EQUAL :
2179           case TokenNameMULTIPLY_EQUAL :
2180           case TokenNameDIVIDE_EQUAL :
2181           case TokenNameDOT_EQUAL :
2182           case TokenNameREMAINDER_EQUAL :
2183           case TokenNameAND_EQUAL :
2184           case TokenNameOR_EQUAL :
2185           case TokenNameXOR_EQUAL :
2186           case TokenNameRIGHT_SHIFT_EQUAL :
2187           case TokenNameLEFT_SHIFT_EQUAL :
2188             getNextToken();
2189             expr();
2190             break;
2191           case TokenNamePLUS_PLUS :
2192           case TokenNameMINUS_MINUS :
2193             getNextToken();
2194             break;
2195           default :
2196             if (!only_variable) {
2197               throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "').");
2198             }
2199         }
2200         break;
2201       default :
2202         if (token != TokenNameINLINE_HTML) {
2203           if (token > TokenNameKEYWORD) {
2204             getNextToken();
2205             break;
2206           } else {
2207             throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "').");
2208           }
2209         }
2210         return;
2211     }
2212     if (Scanner.TRACE) {
2213       System.out.println("TRACE: expr_without_variable() PART 2");
2214     }
2215     //  | expr T_BOOLEAN_OR expr
2216     //  | expr T_BOOLEAN_AND expr
2217     //  | expr T_LOGICAL_OR expr
2218     //  | expr T_LOGICAL_AND expr
2219     //  | expr T_LOGICAL_XOR expr
2220     //  | expr '|' expr
2221     //  | expr '&' expr
2222     //  | expr '^' expr
2223     //  | expr '.' expr
2224     //  | expr '+' expr
2225     //  | expr '-' expr
2226     //  | expr '*' expr
2227     //  | expr '/' expr
2228     //  | expr '%' expr
2229     //  | expr T_SL expr
2230     //  | expr T_SR expr
2231     //  | expr T_IS_IDENTICAL expr
2232     //  | expr T_IS_NOT_IDENTICAL expr
2233     //  | expr T_IS_EQUAL expr
2234     //  | expr T_IS_NOT_EQUAL expr
2235     //  | expr '<' expr
2236     //  | expr T_IS_SMALLER_OR_EQUAL expr
2237     //  | expr '>' expr
2238     //  | expr T_IS_GREATER_OR_EQUAL expr
2239     while (true) {
2240       switch (token) {
2241         case TokenNameOR_OR :
2242         case TokenNameAND_AND :
2243         case TokenNameand :
2244         case TokenNameor :
2245         case TokenNamexor :
2246         case TokenNameAND :
2247         case TokenNameOR :
2248         case TokenNameXOR :
2249         case TokenNameDOT :
2250         case TokenNamePLUS :
2251         case TokenNameMINUS :
2252         case TokenNameMULTIPLY :
2253         case TokenNameDIVIDE :
2254         case TokenNameREMAINDER :
2255         case TokenNameLEFT_SHIFT :
2256         case TokenNameRIGHT_SHIFT :
2257         case TokenNameEQUAL_EQUAL_EQUAL :
2258         case TokenNameNOT_EQUAL_EQUAL :
2259         case TokenNameEQUAL_EQUAL :
2260         case TokenNameNOT_EQUAL :
2261         case TokenNameLESS :
2262         case TokenNameLESS_EQUAL :
2263         case TokenNameGREATER :
2264         case TokenNameGREATER_EQUAL :
2265           getNextToken();
2266           expr();
2267           break;
2268         //  | expr T_INSTANCEOF class_name_reference
2269         //      | expr '?' expr ':' expr
2270         case TokenNameinstanceof :
2271           getNextToken();
2272           class_name_reference();
2273           break;
2274         case TokenNameQUESTION :
2275           getNextToken();
2276           expr();
2277           if (token == TokenNameCOLON) {
2278             getNextToken();
2279             expr();
2280           }
2281           break;
2282         default :
2283           return;
2284       }
2285     }
2286   }
2287   private void class_name_reference() {
2288     //  class_name_reference:
2289     //  T_STRING
2290     //| dynamic_class_name_reference
2291     if (Scanner.TRACE) {
2292       System.out.println("TRACE: class_name_reference()");
2293     }
2294     if (token == TokenNameIdentifier) {
2295       getNextToken();
2296     } else {
2297       dynamic_class_name_reference();
2298     }
2299   }
2300   private void dynamic_class_name_reference() {
2301     //dynamic_class_name_reference:
2302     //  base_variable T_OBJECT_OPERATOR object_property
2303     // dynamic_class_name_variable_properties
2304     //| base_variable
2305     if (Scanner.TRACE) {
2306       System.out.println("TRACE: dynamic_class_name_reference()");
2307     }
2308     base_variable();
2309     if (token == TokenNameMINUS_GREATER) {
2310       getNextToken();
2311       object_property();
2312       dynamic_class_name_variable_properties();
2313     }
2314   }
2315   private void dynamic_class_name_variable_properties() {
2316     //  dynamic_class_name_variable_properties:
2317     //                  dynamic_class_name_variable_properties
2318     // dynamic_class_name_variable_property
2319     //          | /* empty */
2320     if (Scanner.TRACE) {
2321       System.out.println("TRACE: dynamic_class_name_variable_properties()");
2322     }
2323     while (token == TokenNameMINUS_GREATER) {
2324       dynamic_class_name_variable_property();
2325     }
2326   }
2327   private void dynamic_class_name_variable_property() {
2328     //  dynamic_class_name_variable_property:
2329     //  T_OBJECT_OPERATOR object_property
2330     if (Scanner.TRACE) {
2331       System.out.println("TRACE: dynamic_class_name_variable_property()");
2332     }
2333     if (token == TokenNameMINUS_GREATER) {
2334       getNextToken();
2335       object_property();
2336     }
2337   }
2338   private void ctor_arguments() {
2339     //  ctor_arguments:
2340     //  /* empty */
2341     //| '(' function_call_parameter_list ')'
2342     if (token == TokenNameLPAREN) {
2343       getNextToken();
2344       if (token == TokenNameRPAREN) {
2345         getNextToken();
2346         return;
2347       }
2348       non_empty_function_call_parameter_list();
2349       if (token != TokenNameRPAREN) {
2350         throwSyntaxError("')' expected in ctor_arguments.");
2351       }
2352       getNextToken();
2353     }
2354   }
2355   private void assignment_list() {
2356     //  assignment_list:
2357     //  assignment_list ',' assignment_list_element
2358     //| assignment_list_element
2359     while (true) {
2360       assignment_list_element();
2361       if (token != TokenNameCOMMA) {
2362         break;
2363       }
2364       getNextToken();
2365     }
2366   }
2367   private void assignment_list_element() {
2368     //assignment_list_element:
2369     //  variable
2370     //| T_LIST '(' assignment_list ')'
2371     //| /* empty */
2372     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2373       variable();
2374     } else {
2375       if (token == TokenNamelist) {
2376         getNextToken();
2377         if (token == TokenNameLPAREN) {
2378           getNextToken();
2379           assignment_list();
2380           if (token != TokenNameRPAREN) {
2381             throwSyntaxError("')' expected after 'list' keyword.");
2382           }
2383           getNextToken();
2384         } else {
2385           throwSyntaxError("'(' expected after 'list' keyword.");
2386         }
2387       }
2388     }
2389   }
2390   private void array_pair_list() {
2391     //  array_pair_list:
2392     //  /* empty */
2393     //| non_empty_array_pair_list possible_comma
2394     non_empty_array_pair_list();
2395     if (token == TokenNameCOMMA) {
2396       getNextToken();
2397     }
2398   }
2399   private void non_empty_array_pair_list() {
2400     //non_empty_array_pair_list:
2401     //  non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2402     //| non_empty_array_pair_list ',' expr
2403     //| expr T_DOUBLE_ARROW expr
2404     //| expr
2405     //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2406     //| non_empty_array_pair_list ',' '&' w_variable
2407     //| expr T_DOUBLE_ARROW '&' w_variable
2408     //| '&' w_variable
2409     while (true) {
2410       if (token == TokenNameAND) {
2411         getNextToken();
2412         variable();
2413       } else {
2414         expr();
2415         if (token == TokenNameAND) {
2416           getNextToken();
2417           variable();
2418         } else if (token == TokenNameEQUAL_GREATER) {
2419           getNextToken();
2420           if (token == TokenNameAND) {
2421             getNextToken();
2422             variable();
2423           } else {
2424             expr();
2425           }
2426         }
2427       }
2428       if (token != TokenNameCOMMA) {
2429         return;
2430       }
2431       getNextToken();
2432       if (token == TokenNameRPAREN) {
2433         return;
2434       }
2435     }
2436   }
2437   //  private void variableList() {
2438   //    do {
2439   //      variable();
2440   //      if (token == TokenNameCOMMA) {
2441   //        getNextToken();
2442   //      } else {
2443   //        break;
2444   //      }
2445   //    } while (true);
2446   //  }
2447   private void variable_without_objects() {
2448     //  variable_without_objects:
2449     //                  reference_variable
2450     //          | simple_indirect_reference reference_variable
2451     if (Scanner.TRACE) {
2452       System.out.println("TRACE: variable_without_objects()");
2453     }
2454     while (token == TokenNameDOLLAR) {
2455       getNextToken();
2456     }
2457     reference_variable();
2458   }
2459   private void function_call() {
2460     //  function_call:
2461     //  T_STRING '(' function_call_parameter_list ')'
2462     //| class_constant '(' function_call_parameter_list ')'
2463     //| static_member '(' function_call_parameter_list ')'
2464     //| variable_without_objects '(' function_call_parameter_list ')'
2465     char[] defineName = null;
2466     int startPos=0;
2467     int endPos=0;
2468     if (Scanner.TRACE) {
2469       System.out.println("TRACE: function_call()");
2470     }
2471     if (token == TokenNameIdentifier) {
2472       defineName = scanner.getCurrentIdentifierSource();
2473       startPos = scanner.getCurrentTokenStartPosition();
2474       endPos = scanner.getCurrentTokenEndPosition();
2475       getNextToken();
2476       switch (token) {
2477         case TokenNamePAAMAYIM_NEKUDOTAYIM :
2478           // static member:
2479           defineName = null;
2480           getNextToken();
2481           if (token == TokenNameIdentifier) {
2482             // class _constant
2483             getNextToken();
2484           } else {
2485             //        static member:
2486             variable_without_objects();
2487           }
2488           break;
2489       }
2490     } else {
2491       variable_without_objects();
2492     }
2493     if (token != TokenNameLPAREN) {
2494       if (defineName!=null) {
2495         // does this identifier contain only uppercase characters?
2496         if (defineName.length==3) {
2497           if (defineName[0]=='d' &&
2498               defineName[1]=='i' &&
2499               defineName[2]=='e' ) {
2500             defineName=null;
2501           } 
2502         } else if (defineName.length==4) {
2503           if (defineName[0]=='t' &&
2504               defineName[1]=='r' &&
2505               defineName[2]=='u' &&
2506               defineName[3]=='e' ) {
2507             defineName=null;
2508           } else if (defineName[0]=='n' &&
2509               defineName[1]=='u' &&
2510               defineName[2]=='l' &&
2511               defineName[3]=='l' ) {
2512             defineName=null;
2513           }
2514         } else if (defineName.length==5) {
2515           if (defineName[0]=='f' &&
2516               defineName[1]=='a' &&
2517               defineName[2]=='l' &&
2518               defineName[3]=='s' &&
2519               defineName[4]=='e' ) {
2520             defineName=null;
2521           }
2522         }
2523         if (defineName!=null) {
2524           for (int i=0; i<defineName.length;i++) {
2525             if (Character.isLowerCase(defineName[i])) {  
2526               problemReporter.phpUppercaseIdentifierWarning(startPos, endPos,
2527                 referenceContext, compilationUnit.compilationResult);
2528               break;
2529             }
2530           }
2531         }
2532       }
2533       // TODO is this ok ?
2534       return;
2535       //      throwSyntaxError("'(' expected in function call.");
2536     }
2537     getNextToken();
2538     if (token == TokenNameRPAREN) {
2539       getNextToken();
2540       return;
2541     }
2542     non_empty_function_call_parameter_list();
2543     if (token != TokenNameRPAREN) {
2544       throwSyntaxError("')' expected in function call.");
2545     }
2546     getNextToken();
2547   }
2548   //  private void function_call_parameter_list() {
2549   //    function_call_parameter_list:
2550   //            non_empty_function_call_parameter_list { $$ = $1; }
2551   //    | /* empty */
2552   //  }
2553   private void non_empty_function_call_parameter_list() {
2554     //non_empty_function_call_parameter_list:
2555     //          expr_without_variable
2556     //  | variable
2557     //  | '&' w_variable
2558     //  | non_empty_function_call_parameter_list ',' expr_without_variable
2559     //  | non_empty_function_call_parameter_list ',' variable
2560     //  | non_empty_function_call_parameter_list ',' '&' w_variable
2561     if (Scanner.TRACE) {
2562       System.out.println("TRACE: non_empty_function_call_parameter_list()");
2563     }
2564     while (true) {
2565       if (token == TokenNameAND) {
2566         getNextToken();
2567         w_variable();
2568       } else {
2569         //        if (token == TokenNameIdentifier || token ==
2570         // TokenNameVariable
2571         //            || token == TokenNameDOLLAR) {
2572         //          variable();
2573         //        } else {
2574         expr_without_variable(true);
2575         //        }
2576       }
2577       if (token != TokenNameCOMMA) {
2578         break;
2579       }
2580       getNextToken();
2581     }
2582   }
2583   private void fully_qualified_class_name() {
2584     if (token == TokenNameIdentifier) {
2585       getNextToken();
2586     } else {
2587       throwSyntaxError("Class name expected.");
2588     }
2589   }
2590   private void static_member() {
2591     //  static_member:
2592     //  fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2593     // variable_without_objects
2594     if (Scanner.TRACE) {
2595       System.out.println("TRACE: static_member()");
2596     }
2597     fully_qualified_class_name();
2598     if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2599       throwSyntaxError("'::' expected after class name (static_member).");
2600     }
2601     getNextToken();
2602     variable_without_objects();
2603   }
2604   private void base_variable_with_function_calls() {
2605     //  base_variable_with_function_calls:
2606     //  base_variable
2607     //| function_call
2608     boolean functionCall = false;
2609     if (Scanner.TRACE) {
2610       System.out.println("TRACE: base_variable_with_function_calls()");
2611     }
2612     //    if (token == TokenNameIdentifier) {
2613     //      functionCall = true;
2614     //    } else if (token == TokenNameVariable) {
2615     //      int tempToken = token;
2616     //      int tempPosition = scanner.currentPosition;
2617     //      getNextToken();
2618     //      if (token == TokenNameLPAREN) {
2619     //        functionCall = true;
2620     //      }
2621     //      token = tempToken;
2622     //      scanner.currentPosition = tempPosition;
2623     //      scanner.phpMode = true;
2624     //    }
2625     //    if (functionCall) {
2626     function_call();
2627     //    } else {
2628     //      base_variable();
2629     //    }
2630   }
2631   private void base_variable() {
2632     //  base_variable:
2633     //                  reference_variable
2634     //          | simple_indirect_reference reference_variable
2635     //          | static_member
2636     if (Scanner.TRACE) {
2637       System.out.println("TRACE: base_variable()");
2638     }
2639     if (token == TokenNameIdentifier) {
2640       static_member();
2641     } else {
2642       while (token == TokenNameDOLLAR) {
2643         getNextToken();
2644       }
2645       reference_variable();
2646     }
2647   }
2648   //  private void simple_indirect_reference() {
2649   //    // simple_indirect_reference:
2650   //    // '$'
2651   //    //| simple_indirect_reference '$'
2652   //  }
2653   private void reference_variable() {
2654     //  reference_variable:
2655     //                  reference_variable '[' dim_offset ']'
2656     //          | reference_variable '{' expr '}'
2657     //          | compound_variable
2658     if (Scanner.TRACE) {
2659       System.out.println("TRACE: reference_variable()");
2660     }
2661     compound_variable();
2662     while (true) {
2663       if (token == TokenNameLBRACE) {
2664         getNextToken();
2665         expr();
2666         if (token != TokenNameRBRACE) {
2667           throwSyntaxError("'}' expected in reference variable.");
2668         }
2669         getNextToken();
2670       } else if (token == TokenNameLBRACKET) {
2671         getNextToken();
2672         if (token != TokenNameRBRACKET) {
2673           expr();
2674           //        dim_offset();
2675           if (token != TokenNameRBRACKET) {
2676             throwSyntaxError("']' expected in reference variable.");
2677           }
2678         }
2679         getNextToken();
2680       } else {
2681         break;
2682       }
2683     }
2684   }
2685   private void compound_variable() {
2686     //  compound_variable:
2687     //                  T_VARIABLE
2688     //          | '$' '{' expr '}'
2689     if (Scanner.TRACE) {
2690       System.out.println("TRACE: compound_variable()");
2691     }
2692     if (token == TokenNameVariable) {
2693       getNextToken();
2694     } else {
2695       // because of simple_indirect_reference
2696       while (token == TokenNameDOLLAR) {
2697         getNextToken();
2698       }
2699       if (token != TokenNameLBRACE) {
2700         throwSyntaxError("'{' expected after compound variable token '$'.");
2701       }
2702       getNextToken();
2703       expr();
2704       if (token != TokenNameRBRACE) {
2705         throwSyntaxError("'}' expected after compound variable token '$'.");
2706       }
2707       getNextToken();
2708     }
2709   }
2710   //  private void dim_offset() {
2711   //    // dim_offset:
2712   //    // /* empty */
2713   //    // | expr
2714   //    expr();
2715   //  }
2716   private void object_property() {
2717     //  object_property:
2718     //  object_dim_list
2719     //| variable_without_objects
2720     if (Scanner.TRACE) {
2721       System.out.println("TRACE: object_property()");
2722     }
2723     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2724       variable_without_objects();
2725     } else {
2726       object_dim_list();
2727     }
2728   }
2729   private void object_dim_list() {
2730     //object_dim_list:
2731     //  object_dim_list '[' dim_offset ']'
2732     //| object_dim_list '{' expr '}'
2733     //| variable_name
2734     if (Scanner.TRACE) {
2735       System.out.println("TRACE: object_dim_list()");
2736     }
2737     variable_name();
2738     while (true) {
2739       if (token == TokenNameLBRACE) {
2740         getNextToken();
2741         expr();
2742         if (token != TokenNameRBRACE) {
2743           throwSyntaxError("'}' expected in object_dim_list.");
2744         }
2745         getNextToken();
2746       } else if (token == TokenNameLBRACKET) {
2747         getNextToken();
2748         if (token == TokenNameRBRACKET) {
2749           getNextToken();
2750           continue;
2751         }
2752         expr();
2753         if (token != TokenNameRBRACKET) {
2754           throwSyntaxError("']' expected in object_dim_list.");
2755         }
2756         getNextToken();
2757       } else {
2758         break;
2759       }
2760     }
2761   }
2762   private void variable_name() {
2763     //variable_name:
2764     //  T_STRING
2765     //| '{' expr '}'
2766     if (Scanner.TRACE) {
2767       System.out.println("TRACE: variable_name()");
2768     }
2769     if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
2770       if (token > TokenNameKEYWORD) {
2771         // TODO show a warning "Keyword used as variable" ?
2772       }
2773       getNextToken();
2774     } else {
2775       if (token != TokenNameLBRACE) {
2776         throwSyntaxError("'{' expected in variable name.");
2777       }
2778       getNextToken();
2779       expr();
2780       if (token != TokenNameRBRACE) {
2781         throwSyntaxError("'}' expected in variable name.");
2782       }
2783       getNextToken();
2784     }
2785   }
2786   private void r_variable() {
2787     variable();
2788   }
2789   private void w_variable() {
2790     variable();
2791   }
2792   private void rw_variable() {
2793     variable();
2794   }
2795   private void variable() {
2796     //    variable:
2797     //          base_variable_with_function_calls T_OBJECT_OPERATOR
2798     //                  object_property method_or_not variable_properties
2799     //  | base_variable_with_function_calls
2800     base_variable_with_function_calls();
2801     if (token == TokenNameMINUS_GREATER) {
2802       getNextToken();
2803       object_property();
2804       method_or_not();
2805       variable_properties();
2806     }
2807     //    if (token == TokenNameDOLLAR_LBRACE) {
2808     //      getNextToken();
2809     //      expr();
2810     //      ;
2811     //      if (token != TokenNameRBRACE) {
2812     //        throwSyntaxError("'}' expected after indirect variable token '${'.");
2813     //      }
2814     //      getNextToken();
2815     //    } else {
2816     //      if (token == TokenNameVariable) {
2817     //        getNextToken();
2818     //        if (token == TokenNameLBRACKET) {
2819     //          getNextToken();
2820     //          expr();
2821     //          if (token != TokenNameRBRACKET) {
2822     //            throwSyntaxError("']' expected in variable-list.");
2823     //          }
2824     //          getNextToken();
2825     //        } else if (token == TokenNameEQUAL) {
2826     //          getNextToken();
2827     //          static_scalar();
2828     //        }
2829     //      } else {
2830     //        throwSyntaxError("$-variable expected in variable-list.");
2831     //      }
2832     //    }
2833   }
2834   private void variable_properties() {
2835     //  variable_properties:
2836     //                  variable_properties variable_property
2837     //          | /* empty */
2838     while (token == TokenNameMINUS_GREATER) {
2839       variable_property();
2840     }
2841   }
2842   private void variable_property() {
2843     //  variable_property:
2844     //                  T_OBJECT_OPERATOR object_property method_or_not
2845     if (Scanner.TRACE) {
2846       System.out.println("TRACE: variable_property()");
2847     }
2848     if (token == TokenNameMINUS_GREATER) {
2849       getNextToken();
2850       object_property();
2851       method_or_not();
2852     } else {
2853       throwSyntaxError("'->' expected in variable_property.");
2854     }
2855   }
2856   private void method_or_not() {
2857     //  method_or_not:
2858     //                  '(' function_call_parameter_list ')'
2859     //          | /* empty */
2860     if (Scanner.TRACE) {
2861       System.out.println("TRACE: method_or_not()");
2862     }
2863     if (token == TokenNameLPAREN) {
2864       getNextToken();
2865       if (token == TokenNameRPAREN) {
2866         getNextToken();
2867         return;
2868       }
2869       non_empty_function_call_parameter_list();
2870       if (token != TokenNameRPAREN) {
2871         throwSyntaxError("')' expected in method_or_not.");
2872       }
2873       getNextToken();
2874     }
2875   }
2876   private void exit_expr() {
2877     //  /* empty */
2878     //  | '(' ')'
2879     //  | '(' expr ')'
2880     if (token != TokenNameLPAREN) {
2881       return;
2882     }
2883     getNextToken();
2884     if (token == TokenNameRPAREN) {
2885       getNextToken();
2886       return;
2887     }
2888     expr();
2889     if (token != TokenNameRPAREN) {
2890       throwSyntaxError("')' expected after keyword 'exit'");
2891     }
2892     getNextToken();
2893   }
2894   private void encaps_list() {
2895     //                  encaps_list encaps_var
2896     //          | encaps_list T_STRING
2897     //          | encaps_list T_NUM_STRING
2898     //          | encaps_list T_ENCAPSED_AND_WHITESPACE
2899     //          | encaps_list T_CHARACTER
2900     //          | encaps_list T_BAD_CHARACTER
2901     //          | encaps_list '['
2902     //          | encaps_list ']'
2903     //          | encaps_list '{'
2904     //          | encaps_list '}'
2905     //          | encaps_list T_OBJECT_OPERATOR
2906     //          | /* empty */
2907     while (true) {
2908       switch (token) {
2909         case TokenNameSTRING :
2910           getNextToken();
2911           break;
2912         case TokenNameLBRACE :
2913           //          scanner.encapsedStringStack.pop();
2914           getNextToken();
2915           break;
2916         case TokenNameRBRACE :
2917           //          scanner.encapsedStringStack.pop();
2918           getNextToken();
2919           break;
2920         case TokenNameLBRACKET :
2921           //          scanner.encapsedStringStack.pop();
2922           getNextToken();
2923           break;
2924         case TokenNameRBRACKET :
2925           //          scanner.encapsedStringStack.pop();
2926           getNextToken();
2927           break;
2928         case TokenNameMINUS_GREATER :
2929           //          scanner.encapsedStringStack.pop();
2930           getNextToken();
2931           break;
2932         case TokenNameVariable :
2933         case TokenNameDOLLAR_LBRACE :
2934         case TokenNameCURLY_OPEN :
2935           encaps_var();
2936           break;
2937         //        case TokenNameDOLLAR :
2938         //          getNextToken();
2939         //          if (token == TokenNameLBRACE) {
2940         //            token = TokenNameDOLLAR_LBRACE;
2941         //            encaps_var();
2942         //          }
2943         //          break;
2944         default :
2945           char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
2946           if (encapsedChar == '$') {
2947             scanner.encapsedStringStack.pop();
2948             encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
2949             switch (encapsedChar) {
2950               case '`' :
2951                 if (token == TokenNameEncapsedString0) {
2952                   return;
2953                 }
2954                 token = TokenNameSTRING;
2955                 continue;
2956               case '\'' :
2957                 if (token == TokenNameEncapsedString1) {
2958                   return;
2959                 }
2960                 token = TokenNameSTRING;
2961                 continue;
2962               case '"' :
2963                 if (token == TokenNameEncapsedString2) {
2964                   return;
2965                 }
2966                 token = TokenNameSTRING;
2967                 continue;
2968             }
2969           }
2970           return;
2971       }
2972     }
2973   }
2974   private void encaps_var() {
2975     //                  T_VARIABLE
2976     //          | T_VARIABLE '[' encaps_var_offset ']'
2977     //          | T_VARIABLE T_OBJECT_OPERATOR T_STRING
2978     //          | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
2979     //          | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
2980     //          | T_CURLY_OPEN variable '}'
2981     switch (token) {
2982       case TokenNameVariable :
2983         getNextToken();
2984         if (token == TokenNameLBRACKET) {
2985           getNextToken();
2986           //          if (token == TokenNameRBRACKET) {
2987           //            getNextToken();
2988           //          } else {
2989           expr(); //encaps_var_offset();
2990           if (token != TokenNameRBRACKET) {
2991             throwSyntaxError("']' expected after variable.");
2992           }
2993           //          scanner.encapsedStringStack.pop();
2994           getNextToken();
2995           //          }
2996         } else if (token == TokenNameMINUS_GREATER) {
2997           getNextToken();
2998           if (token != TokenNameIdentifier) {
2999             throwSyntaxError("Identifier expected after '->'.");
3000           }
3001           //          scanner.encapsedStringStack.pop();
3002           getNextToken();
3003         }
3004         //        else {
3005         //          // scanner.encapsedStringStack.pop();
3006         //          int tempToken = TokenNameSTRING;
3007         //          if (!scanner.encapsedStringStack.isEmpty()
3008         //              && (token == TokenNameEncapsedString0
3009         //                  || token == TokenNameEncapsedString1
3010         //                  || token == TokenNameEncapsedString2 || token ==
3011         // TokenNameERROR)) {
3012         //            char encapsedChar = ((Character)
3013         // scanner.encapsedStringStack.peek())
3014         //                .charValue();
3015         //            switch (token) {
3016         //              case TokenNameEncapsedString0 :
3017         //                if (encapsedChar == '`') {
3018         //                  tempToken = TokenNameEncapsedString0;
3019         //                }
3020         //                break;
3021         //              case TokenNameEncapsedString1 :
3022         //                if (encapsedChar == '\'') {
3023         //                  tempToken = TokenNameEncapsedString1;
3024         //                }
3025         //                break;
3026         //              case TokenNameEncapsedString2 :
3027         //                if (encapsedChar == '"') {
3028         //                  tempToken = TokenNameEncapsedString2;
3029         //                }
3030         //                break;
3031         //              case TokenNameERROR :
3032         //                if (scanner.source[scanner.currentPosition - 1] == '\\') {
3033         //                  scanner.currentPosition--;
3034         //                  getNextToken();
3035         //                }
3036         //                break;
3037         //            }
3038         //          }
3039         //          token = tempToken;
3040         //        }
3041         break;
3042       case TokenNameDOLLAR_LBRACE :
3043         getNextToken();
3044         if (token == TokenNameIdentifier) {
3045           getNextToken();
3046           if (token == TokenNameLBRACKET) {
3047             getNextToken();
3048             //            if (token == TokenNameRBRACKET) {
3049             //              getNextToken();
3050             //            } else {
3051             expr();
3052             if (token != TokenNameRBRACKET) {
3053               throwSyntaxError("']' expected after '${'.");
3054             }
3055             getNextToken();
3056             //            }
3057           }
3058           if (token != TokenNameRBRACE) {
3059             throwSyntaxError("'}' expected after '${'.");
3060           }
3061           //          scanner.encapsedStringStack.pop();
3062           getNextToken();
3063         } else {
3064           expr();
3065           if (token != TokenNameRBRACE) {
3066             throwSyntaxError("'}' expected.");
3067           }
3068           //          scanner.encapsedStringStack.pop();
3069           getNextToken();
3070         }
3071         break;
3072       case TokenNameCURLY_OPEN :
3073         getNextToken();
3074         if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3075           getNextToken();
3076           if (token == TokenNameLBRACKET) {
3077             getNextToken();
3078             //            if (token == TokenNameRBRACKET) {
3079             //              getNextToken();
3080             //            } else {
3081             expr();
3082             if (token != TokenNameRBRACKET) {
3083               throwSyntaxError("']' expected after '{$'.");
3084             }
3085             getNextToken();
3086             //            }
3087           } else if (token == TokenNameMINUS_GREATER) {
3088             getNextToken();
3089             if (token != TokenNameIdentifier) {
3090               throwSyntaxError("String token expected.");
3091             }
3092             getNextToken();
3093           }
3094           //          if (token != TokenNameRBRACE) {
3095           //            throwSyntaxError("'}' expected after '{$'.");
3096           //          }
3097           //          // scanner.encapsedStringStack.pop();
3098           //          getNextToken();
3099         } else {
3100           expr();
3101           if (token != TokenNameRBRACE) {
3102             throwSyntaxError("'}' expected.");
3103           }
3104           //          scanner.encapsedStringStack.pop();
3105           getNextToken();
3106         }
3107         break;
3108     }
3109   }
3110   private void encaps_var_offset() {
3111     //                  T_STRING
3112     //          | T_NUM_STRING
3113     //          | T_VARIABLE
3114     switch (token) {
3115       case TokenNameSTRING :
3116         getNextToken();
3117         break;
3118       case TokenNameIntegerLiteral :
3119         getNextToken();
3120         break;
3121       case TokenNameVariable :
3122         getNextToken();
3123         break;
3124       case TokenNameIdentifier :
3125         getNextToken();
3126         break;
3127       default :
3128         throwSyntaxError("Variable or String token expected.");
3129         break;
3130     }
3131   }
3132   private void internal_functions_in_yacc() {
3133     int start = 0;
3134     ImportReference impt = null;
3135     switch (token) {
3136       case TokenNameisset :
3137         //      T_ISSET '(' isset_variables ')'
3138         getNextToken();
3139         if (token != TokenNameLPAREN) {
3140           throwSyntaxError("'(' expected after keyword 'isset'");
3141         }
3142         getNextToken();
3143         isset_variables();
3144         if (token != TokenNameRPAREN) {
3145           throwSyntaxError("')' expected after keyword 'isset'");
3146         }
3147         getNextToken();
3148         break;
3149       case TokenNameempty :
3150         //      T_EMPTY '(' variable ')'
3151         getNextToken();
3152         if (token != TokenNameLPAREN) {
3153           throwSyntaxError("'(' expected after keyword 'empty'");
3154         }
3155         getNextToken();
3156         variable();
3157         if (token != TokenNameRPAREN) {
3158           throwSyntaxError("')' expected after keyword 'empty'");
3159         }
3160         getNextToken();
3161         break;
3162       case TokenNameinclude :
3163         //T_INCLUDE expr
3164         start = scanner.getCurrentTokenStartPosition();
3165         getNextToken();
3166         expr();
3167
3168         impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3169         impt.declarationSourceEnd = impt.sourceEnd;
3170         impt.declarationEnd = impt.declarationSourceEnd;
3171         //endPosition is just before the ;
3172         impt.declarationSourceStart = start;
3173         includesList.add(impt);
3174         break;
3175       case TokenNameinclude_once :
3176         //      T_INCLUDE_ONCE expr
3177         start = scanner.getCurrentTokenStartPosition();
3178         getNextToken();
3179         expr();
3180         impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3181         impt.declarationSourceEnd = impt.sourceEnd;
3182         impt.declarationEnd = impt.declarationSourceEnd;
3183         //endPosition is just before the ;
3184         impt.declarationSourceStart = start;
3185         includesList.add(impt);
3186         break;
3187       case TokenNameeval :
3188         //      T_EVAL '(' expr ')'
3189         getNextToken();
3190         if (token != TokenNameLPAREN) {
3191           throwSyntaxError("'(' expected after keyword 'eval'");
3192         }
3193         getNextToken();
3194         expr();
3195         if (token != TokenNameRPAREN) {
3196           throwSyntaxError("')' expected after keyword 'eval'");
3197         }
3198         getNextToken();
3199         break;
3200       case TokenNamerequire :
3201         //T_REQUIRE expr
3202         start = scanner.getCurrentTokenStartPosition();
3203         getNextToken();
3204         expr();
3205         impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3206         impt.declarationSourceEnd = impt.sourceEnd;
3207         impt.declarationEnd = impt.declarationSourceEnd;
3208         //endPosition is just before the ;
3209         impt.declarationSourceStart = start;
3210         includesList.add(impt);
3211         break;
3212       case TokenNamerequire_once :
3213         //      T_REQUIRE_ONCE expr
3214         start = scanner.getCurrentTokenStartPosition();
3215         getNextToken();
3216         expr();
3217         impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3218         impt.declarationSourceEnd = impt.sourceEnd;
3219         impt.declarationEnd = impt.declarationSourceEnd;
3220         //endPosition is just before the ;
3221         impt.declarationSourceStart = start;
3222         includesList.add(impt);
3223         break;
3224     }
3225   }
3226   private void isset_variables() {
3227     //  variable
3228     //  | isset_variables ','
3229     if (token == TokenNameRPAREN) {
3230       throwSyntaxError("Variable expected after keyword 'isset'");
3231     }
3232     while (true) {
3233       variable();
3234       if (token == TokenNameCOMMA) {
3235         getNextToken();
3236       } else {
3237         break;
3238       }
3239     }
3240   }
3241   private boolean common_scalar() {
3242     //  common_scalar:
3243     //  T_LNUMBER
3244     //  | T_DNUMBER
3245     //  | T_CONSTANT_ENCAPSED_STRING
3246     //  | T_LINE
3247     //  | T_FILE
3248     //  | T_CLASS_C
3249     //  | T_METHOD_C
3250     //  | T_FUNC_C
3251     switch (token) {
3252       case TokenNameIntegerLiteral :
3253         getNextToken();
3254         return true;
3255       case TokenNameDoubleLiteral :
3256         getNextToken();
3257         return true;
3258       case TokenNameStringDoubleQuote :
3259         getNextToken();
3260         return true;
3261       case TokenNameStringSingleQuote :
3262         getNextToken();
3263         return true;
3264       case TokenNameStringInterpolated :
3265         getNextToken();
3266         return true;
3267       case TokenNameFILE :
3268         getNextToken();
3269         return true;
3270       case TokenNameLINE :
3271         getNextToken();
3272         return true;
3273       case TokenNameCLASS_C :
3274         getNextToken();
3275         return true;
3276       case TokenNameMETHOD_C :
3277         getNextToken();
3278         return true;
3279       case TokenNameFUNC_C :
3280         getNextToken();
3281         return true;
3282     }
3283     return false;
3284   }
3285   private void scalar() {
3286     //  scalar:
3287     //  T_STRING
3288     //| T_STRING_VARNAME
3289     //| class_constant
3290     //| common_scalar
3291     //| '"' encaps_list '"'
3292     //| '\'' encaps_list '\''
3293     //| T_START_HEREDOC encaps_list T_END_HEREDOC
3294     throwSyntaxError("Not yet implemented (scalar).");
3295   }
3296   private void static_scalar() {
3297     //    static_scalar: /* compile-time evaluated scalars */
3298     //          common_scalar
3299     //  | T_STRING
3300     //  | '+' static_scalar
3301     //  | '-' static_scalar
3302     //  | T_ARRAY '(' static_array_pair_list ')'
3303     //  | static_class_constant
3304     if (common_scalar()) {
3305       return;
3306     }
3307     switch (token) {
3308       case TokenNameIdentifier :
3309         getNextToken();
3310         //        static_class_constant:
3311         //              T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3312         if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3313           getNextToken();
3314           if (token == TokenNameIdentifier) {
3315             getNextToken();
3316           } else {
3317             throwSyntaxError("Identifier expected after '::' operator.");
3318           }
3319         }
3320         break;
3321       case TokenNameEncapsedString0 :
3322         try {
3323           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3324           while (scanner.currentCharacter != '`') {
3325             if (scanner.currentCharacter == '\\') {
3326               scanner.currentPosition++;
3327             }
3328             scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3329           }
3330           getNextToken();
3331         } catch (IndexOutOfBoundsException e) {
3332           throwSyntaxError("'`' expected at end of static string.");
3333         }
3334         break;
3335       case TokenNameEncapsedString1 :
3336         try {
3337           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3338           while (scanner.currentCharacter != '\'') {
3339             if (scanner.currentCharacter == '\\') {
3340               scanner.currentPosition++;
3341             }
3342             scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3343           }
3344           getNextToken();
3345         } catch (IndexOutOfBoundsException e) {
3346           throwSyntaxError("'\'' expected at end of static string.");
3347         }
3348         break;
3349       case TokenNameEncapsedString2 :
3350         try {
3351           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3352           while (scanner.currentCharacter != '"') {
3353             if (scanner.currentCharacter == '\\') {
3354               scanner.currentPosition++;
3355             }
3356             scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3357           }
3358           getNextToken();
3359         } catch (IndexOutOfBoundsException e) {
3360           throwSyntaxError("'\"' expected at end of static string.");
3361         }
3362         break;
3363       case TokenNamePLUS :
3364         getNextToken();
3365         static_scalar();
3366         break;
3367       case TokenNameMINUS :
3368         getNextToken();
3369         static_scalar();
3370         break;
3371       case TokenNamearray :
3372         getNextToken();
3373         if (token != TokenNameLPAREN) {
3374           throwSyntaxError("'(' expected after keyword 'array'");
3375         }
3376         getNextToken();
3377         if (token == TokenNameRPAREN) {
3378           getNextToken();
3379           break;
3380         }
3381         non_empty_static_array_pair_list();
3382         if (token != TokenNameRPAREN) {
3383           throwSyntaxError("')' expected after keyword 'array'");
3384         }
3385         getNextToken();
3386         break;
3387       //      case TokenNamenull :
3388       //        getNextToken();
3389       //        break;
3390       //      case TokenNamefalse :
3391       //        getNextToken();
3392       //        break;
3393       //      case TokenNametrue :
3394       //        getNextToken();
3395       //        break;
3396       default :
3397         throwSyntaxError("Static scalar/constant expected.");
3398     }
3399   }
3400   private void non_empty_static_array_pair_list() {
3401     //  non_empty_static_array_pair_list:
3402     //  non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3403     // static_scalar
3404     //| non_empty_static_array_pair_list ',' static_scalar
3405     //| static_scalar T_DOUBLE_ARROW static_scalar
3406     //| static_scalar
3407     while (true) {
3408       static_scalar();
3409       if (token == TokenNameEQUAL_GREATER) {
3410         getNextToken();
3411         static_scalar();
3412       }
3413       if (token != TokenNameCOMMA) {
3414         break;
3415       }
3416       getNextToken();
3417       if (token == TokenNameRPAREN) {
3418         break;
3419       }
3420     }
3421   }
3422   public void reportSyntaxError() { //int act, int currentKind, int
3423     // stateStackTop) {
3424     /* remember current scanner position */
3425     int startPos = scanner.startPosition;
3426     int currentPos = scanner.currentPosition;
3427     //          String[] expectings;
3428     //          String tokenName = name[symbol_index[currentKind]];
3429     //fetch all "accurate" possible terminals that could recover the error
3430     //          int start, end = start = asi(stack[stateStackTop]);
3431     //          while (asr[end] != 0)
3432     //                  end++;
3433     //          int length = end - start;
3434     //          expectings = new String[length];
3435     //          if (length != 0) {
3436     //                  char[] indexes = new char[length];
3437     //                  System.arraycopy(asr, start, indexes, 0, length);
3438     //                  for (int i = 0; i < length; i++) {
3439     //                          expectings[i] = name[symbol_index[indexes[i]]];
3440     //                  }
3441     //          }
3442     //if the pb is an EOF, try to tell the user that they are some
3443     //          if (tokenName.equals(UNEXPECTED_EOF)) {
3444     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3445     //                          char[] tokenSource;
3446     //                          try {
3447     //                                  tokenSource = this.scanner.getCurrentTokenSource();
3448     //                          } catch (Exception e) {
3449     //                                  tokenSource = new char[] {};
3450     //                          }
3451     //                          problemReporter().parseError(
3452     //                                  this.scanner.startPosition,
3453     //                                  this.scanner.currentPosition - 1,
3454     //                                  tokenSource,
3455     //                                  tokenName,
3456     //                                  expectings);
3457     //                  }
3458     //          } else { //the next test is HEAVILY grammar DEPENDENT.
3459     //                  if ((length == 14)
3460     //                          && (expectings[0] == "=") //$NON-NLS-1$
3461     //                          && (expectings[1] == "*=") //$NON-NLS-1$
3462     //                          && (expressionPtr > -1)) {
3463     //                                  switch(currentKind) {
3464     //                                          case TokenNameSEMICOLON:
3465     //                                          case TokenNamePLUS:
3466     //                                          case TokenNameMINUS:
3467     //                                          case TokenNameDIVIDE:
3468     //                                          case TokenNameREMAINDER:
3469     //                                          case TokenNameMULTIPLY:
3470     //                                          case TokenNameLEFT_SHIFT:
3471     //                                          case TokenNameRIGHT_SHIFT:
3472     //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3473     //                                          case TokenNameLESS:
3474     //                                          case TokenNameGREATER:
3475     //                                          case TokenNameLESS_EQUAL:
3476     //                                          case TokenNameGREATER_EQUAL:
3477     //                                          case TokenNameEQUAL_EQUAL:
3478     //                                          case TokenNameNOT_EQUAL:
3479     //                                          case TokenNameXOR:
3480     //                                          case TokenNameAND:
3481     //                                          case TokenNameOR:
3482     //                                          case TokenNameOR_OR:
3483     //                                          case TokenNameAND_AND:
3484     //                                                  // the ; is not the expected token ==> it ends a statement when an
3485     // expression is not ended
3486     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3487     //                                                  break;
3488     //                                          case TokenNameRBRACE :
3489     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3490     //                                                  break;
3491     //                                          default:
3492     //                                                  char[] tokenSource;
3493     //                                                  try {
3494     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
3495     //                                                  } catch (Exception e) {
3496     //                                                          tokenSource = new char[] {};
3497     //                                                  }
3498     //                                                  problemReporter().parseError(
3499     //                                                          this.scanner.startPosition,
3500     //                                                          this.scanner.currentPosition - 1,
3501     //                                                          tokenSource,
3502     //                                                          tokenName,
3503     //                                                          expectings);
3504     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
3505     //                                  }
3506     //                  } else {
3507     char[] tokenSource;
3508     try {
3509       tokenSource = this.scanner.getCurrentTokenSource();
3510     } catch (Exception e) {
3511       tokenSource = new char[]{};
3512     }
3513     //                          problemReporter().parseError(
3514     //                                  this.scanner.startPosition,
3515     //                                  this.scanner.currentPosition - 1,
3516     //                                  tokenSource,
3517     //                                  tokenName,
3518     //                                  expectings);
3519     this.checkAndReportBracketAnomalies(problemReporter());
3520     //                  }
3521     //          }
3522     /* reset scanner where it was */
3523     scanner.startPosition = startPos;
3524     scanner.currentPosition = currentPos;
3525   }
3526   public static final int RoundBracket = 0;
3527   public static final int SquareBracket = 1;
3528   public static final int CurlyBracket = 2;
3529   public static final int BracketKinds = 3;
3530   protected int[] nestedMethod; //the ptr is nestedType
3531   protected int nestedType, dimensions;
3532   //ast stack
3533   final static int AstStackIncrement = 100;
3534   protected int astPtr;
3535   protected AstNode[] astStack = new AstNode[AstStackIncrement];
3536   protected int astLengthPtr;
3537   protected int[] astLengthStack;
3538   AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3539   public CompilationUnitDeclaration compilationUnit; /*
3540                                                       * the result from parse()
3541                                                       */
3542   protected ReferenceContext referenceContext;
3543   protected ProblemReporter problemReporter;
3544   protected CompilerOptions options;
3545   private ArrayList includesList;
3546   //  protected CompilationResult compilationResult;
3547   /**
3548    * Returns this parser's problem reporter initialized with its reference
3549    * context. Also it is assumed that a problem is going to be reported, so
3550    * initializes the compilation result's line positions.
3551    */
3552   public ProblemReporter problemReporter() {
3553     if (scanner.recordLineSeparator) {
3554       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3555     }
3556     problemReporter.referenceContext = referenceContext;
3557     return problemReporter;
3558   }
3559   /*
3560    * Reconsider the entire source looking for inconsistencies in {} () []
3561    */
3562   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3563     scanner.wasAcr = false;
3564     boolean anomaliesDetected = false;
3565     try {
3566       char[] source = scanner.source;
3567       int[] leftCount = {0, 0, 0};
3568       int[] rightCount = {0, 0, 0};
3569       int[] depths = {0, 0, 0};
3570       int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3571       int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3572       int[][] rightPositions = new int[][]{new int[10], new int[10], new int[10]};
3573       int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3574       scanner.currentPosition = scanner.initialPosition; //starting
3575       // point
3576       // (first-zero-based
3577       // char)
3578       while (scanner.currentPosition < scanner.eofPosition) { //loop for
3579         // jumping
3580         // over
3581         // comments
3582         try {
3583           // ---------Consume white space and handles
3584           // startPosition---------
3585           boolean isWhiteSpace;
3586           do {
3587             scanner.startPosition = scanner.currentPosition;
3588             //                                          if (((scanner.currentCharacter =
3589             // source[scanner.currentPosition++]) == '\\') &&
3590             // (source[scanner.currentPosition] == 'u')) {
3591             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3592             //                                          } else {
3593             if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3594               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3595                 // only record line positions we have not
3596                 // recorded yet
3597                 scanner.pushLineSeparator();
3598               }
3599             }
3600             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3601             //                                          }
3602           } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
3603           // -------consume token until } is found---------
3604           switch (scanner.currentCharacter) {
3605             case '{' : {
3606               int index = leftCount[CurlyBracket]++;
3607               if (index == leftPositions[CurlyBracket].length) {
3608                 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
3609                 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
3610               }
3611               leftPositions[CurlyBracket][index] = scanner.startPosition;
3612               leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3613             }
3614               break;
3615             case '}' : {
3616               int index = rightCount[CurlyBracket]++;
3617               if (index == rightPositions[CurlyBracket].length) {
3618                 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
3619                 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
3620               }
3621               rightPositions[CurlyBracket][index] = scanner.startPosition;
3622               rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3623             }
3624               break;
3625             case '(' : {
3626               int index = leftCount[RoundBracket]++;
3627               if (index == leftPositions[RoundBracket].length) {
3628                 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
3629                 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
3630               }
3631               leftPositions[RoundBracket][index] = scanner.startPosition;
3632               leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3633             }
3634               break;
3635             case ')' : {
3636               int index = rightCount[RoundBracket]++;
3637               if (index == rightPositions[RoundBracket].length) {
3638                 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
3639                 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
3640               }
3641               rightPositions[RoundBracket][index] = scanner.startPosition;
3642               rightDepths[RoundBracket][index] = --depths[RoundBracket];
3643             }
3644               break;
3645             case '[' : {
3646               int index = leftCount[SquareBracket]++;
3647               if (index == leftPositions[SquareBracket].length) {
3648                 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
3649                 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
3650               }
3651               leftPositions[SquareBracket][index] = scanner.startPosition;
3652               leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3653             }
3654               break;
3655             case ']' : {
3656               int index = rightCount[SquareBracket]++;
3657               if (index == rightPositions[SquareBracket].length) {
3658                 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
3659                 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
3660               }
3661               rightPositions[SquareBracket][index] = scanner.startPosition;
3662               rightDepths[SquareBracket][index] = --depths[SquareBracket];
3663             }
3664               break;
3665             case '\'' : {
3666               if (scanner.getNextChar('\\')) {
3667                 scanner.scanEscapeCharacter();
3668               } else { // consume next character
3669                 scanner.unicodeAsBackSlash = false;
3670                 //                                                                      if (((scanner.currentCharacter =
3671                 // source[scanner.currentPosition++]) ==
3672                 // '\\') &&
3673                 // (source[scanner.currentPosition] ==
3674                 // 'u')) {
3675                 //                                                                              scanner.getNextUnicodeChar();
3676                 //                                                                      } else {
3677                 if (scanner.withoutUnicodePtr != 0) {
3678                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3679                 }
3680                 //                                                                      }
3681               }
3682               scanner.getNextChar('\'');
3683               break;
3684             }
3685             case '"' :
3686               // consume next character
3687               scanner.unicodeAsBackSlash = false;
3688               //                                                        if (((scanner.currentCharacter =
3689               // source[scanner.currentPosition++]) == '\\') &&
3690               // (source[scanner.currentPosition] == 'u')) {
3691               //                                                                scanner.getNextUnicodeChar();
3692               //                                                        } else {
3693               if (scanner.withoutUnicodePtr != 0) {
3694                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3695               }
3696               //                                                        }
3697               while (scanner.currentCharacter != '"') {
3698                 if (scanner.currentCharacter == '\r') {
3699                   if (source[scanner.currentPosition] == '\n')
3700                     scanner.currentPosition++;
3701                   break; // the string cannot go further that
3702                   // the line
3703                 }
3704                 if (scanner.currentCharacter == '\n') {
3705                   break; // the string cannot go further that
3706                   // the line
3707                 }
3708                 if (scanner.currentCharacter == '\\') {
3709                   scanner.scanEscapeCharacter();
3710                 }
3711                 // consume next character
3712                 scanner.unicodeAsBackSlash = false;
3713                 //                                                              if (((scanner.currentCharacter =
3714                 // source[scanner.currentPosition++]) == '\\')
3715                 // && (source[scanner.currentPosition] == 'u'))
3716                 // {
3717                 //                                                                      scanner.getNextUnicodeChar();
3718                 //                                                              } else {
3719                 if (scanner.withoutUnicodePtr != 0) {
3720                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3721                 }
3722                 //                                                              }
3723               }
3724               break;
3725             case '/' : {
3726               int test;
3727               if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3728                 // comment
3729                 //get the next char
3730                 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3731                     && (source[scanner.currentPosition] == 'u')) {
3732                   //-------------unicode traitement
3733                   // ------------
3734                   int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3735                   scanner.currentPosition++;
3736                   while (source[scanner.currentPosition] == 'u') {
3737                     scanner.currentPosition++;
3738                   }
3739                   if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3740                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3741                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3742                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3743                                                                                                                // don't
3744                     // care of the
3745                     // value
3746                     scanner.currentCharacter = 'A';
3747                   } //something different from \n and \r
3748                   else {
3749                     scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3750                   }
3751                 }
3752                 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
3753                   //get the next char
3754                   scanner.startPosition = scanner.currentPosition;
3755                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3756                       && (source[scanner.currentPosition] == 'u')) {
3757                     //-------------unicode traitement
3758                     // ------------
3759                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3760                     scanner.currentPosition++;
3761                     while (source[scanner.currentPosition] == 'u') {
3762                       scanner.currentPosition++;
3763                     }
3764                     if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3765                         || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3766                         || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3767                         || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3768                                                                                                                  // don't
3769                       // care of the
3770                       // value
3771                       scanner.currentCharacter = 'A';
3772                     } //something different from \n
3773                     // and \r
3774                     else {
3775                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3776                     }
3777                   }
3778                 }
3779                 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3780                   if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3781                     // only record line positions we
3782                     // have not recorded yet
3783                     scanner.pushLineSeparator();
3784                     if (this.scanner.taskTags != null) {
3785                       this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner
3786                           .getCurrentTokenEndPosition());
3787                     }
3788                   }
3789                 }
3790                 break;
3791               }
3792               if (test > 0) { //traditional and annotation
3793                 // comment
3794                 boolean star = false;
3795                 // consume next character
3796                 scanner.unicodeAsBackSlash = false;
3797                 //                                                                      if (((scanner.currentCharacter =
3798                 // source[scanner.currentPosition++]) ==
3799                 // '\\') &&
3800                 // (source[scanner.currentPosition] ==
3801                 // 'u')) {
3802                 //                                                                              scanner.getNextUnicodeChar();
3803                 //                                                                      } else {
3804                 if (scanner.withoutUnicodePtr != 0) {
3805                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3806                 }
3807                 //                                                                      }
3808                 if (scanner.currentCharacter == '*') {
3809                   star = true;
3810                 }
3811                 //get the next char
3812                 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3813                     && (source[scanner.currentPosition] == 'u')) {
3814                   //-------------unicode traitement
3815                   // ------------
3816                   int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3817                   scanner.currentPosition++;
3818                   while (source[scanner.currentPosition] == 'u') {
3819                     scanner.currentPosition++;
3820                   }
3821                   if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3822                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3823                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3824                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3825                                                                                                                // don't
3826                     // care of the
3827                     // value
3828                     scanner.currentCharacter = 'A';
3829                   } //something different from * and /
3830                   else {
3831                     scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3832                   }
3833                 }
3834                 //loop until end of comment */
3835                 while ((scanner.currentCharacter != '/') || (!star)) {
3836                   star = scanner.currentCharacter == '*';
3837                   //get next char
3838                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3839                       && (source[scanner.currentPosition] == 'u')) {
3840                     //-------------unicode traitement
3841                     // ------------
3842                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3843                     scanner.currentPosition++;
3844                     while (source[scanner.currentPosition] == 'u') {
3845                       scanner.currentPosition++;
3846                     }
3847                     if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3848                         || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3849                         || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3850                         || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3851                                                                                                                  // don't
3852                       // care of the
3853                       // value
3854                       scanner.currentCharacter = 'A';
3855                     } //something different from * and
3856                     // /
3857                     else {
3858                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3859                     }
3860                   }
3861                 }
3862                 if (this.scanner.taskTags != null) {
3863                   this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
3864                 }
3865                 break;
3866               }
3867               break;
3868             }
3869             default :
3870               if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3871                 scanner.scanIdentifierOrKeyword(false);
3872                 break;
3873               }
3874               if (Character.isDigit(scanner.currentCharacter)) {
3875                 scanner.scanNumber(false);
3876                 break;
3877               }
3878           }
3879           //-----------------end switch while
3880           // try--------------------
3881         } catch (IndexOutOfBoundsException e) {
3882           break; // read until EOF
3883         } catch (InvalidInputException e) {
3884           return false; // no clue
3885         }
3886       }
3887       if (scanner.recordLineSeparator) {
3888         //                              compilationUnit.compilationResult.lineSeparatorPositions =
3889         // scanner.getLineEnds();
3890       }
3891       // check placement anomalies against other kinds of brackets
3892       for (int kind = 0; kind < BracketKinds; kind++) {
3893         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3894           int start = leftPositions[kind][leftIndex]; // deepest
3895           // first
3896           // find matching closing bracket
3897           int depth = leftDepths[kind][leftIndex];
3898           int end = -1;
3899           for (int i = 0; i < rightCount[kind]; i++) {
3900             int pos = rightPositions[kind][i];
3901             // want matching bracket further in source with same
3902             // depth
3903             if ((pos > start) && (depth == rightDepths[kind][i])) {
3904               end = pos;
3905               break;
3906             }
3907           }
3908           if (end < 0) { // did not find a good closing match
3909             problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
3910             return true;
3911           }
3912           // check if even number of opening/closing other brackets
3913           // in between this pair of brackets
3914           int balance = 0;
3915           for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3916             for (int i = 0; i < leftCount[otherKind]; i++) {
3917               int pos = leftPositions[otherKind][i];
3918               if ((pos > start) && (pos < end))
3919                 balance++;
3920             }
3921             for (int i = 0; i < rightCount[otherKind]; i++) {
3922               int pos = rightPositions[otherKind][i];
3923               if ((pos > start) && (pos < end))
3924                 balance--;
3925             }
3926             if (balance != 0) {
3927               problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket
3928               // anomaly
3929               return true;
3930             }
3931           }
3932         }
3933         // too many opening brackets ?
3934         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3935           anomaliesDetected = true;
3936           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext,
3937               compilationUnit.compilationResult);
3938         }
3939         // too many closing brackets ?
3940         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3941           anomaliesDetected = true;
3942           problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
3943         }
3944         if (anomaliesDetected)
3945           return true;
3946       }
3947       return anomaliesDetected;
3948     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3949       return anomaliesDetected;
3950     } catch (NullPointerException e) { // jdk1.2.2 jit bug
3951       return anomaliesDetected;
3952     }
3953   }
3954   protected void pushOnAstLengthStack(int pos) {
3955     try {
3956       astLengthStack[++astLengthPtr] = pos;
3957     } catch (IndexOutOfBoundsException e) {
3958       int oldStackLength = astLengthStack.length;
3959       int[] oldPos = astLengthStack;
3960       astLengthStack = new int[oldStackLength + StackIncrement];
3961       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3962       astLengthStack[astLengthPtr] = pos;
3963     }
3964   }
3965   protected void pushOnAstStack(AstNode node) {
3966     /*
3967      * add a new obj on top of the ast stack
3968      */
3969     try {
3970       astStack[++astPtr] = node;
3971     } catch (IndexOutOfBoundsException e) {
3972       int oldStackLength = astStack.length;
3973       AstNode[] oldStack = astStack;
3974       astStack = new AstNode[oldStackLength + AstStackIncrement];
3975       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3976       astPtr = oldStackLength;
3977       astStack[astPtr] = node;
3978     }
3979     try {
3980       astLengthStack[++astLengthPtr] = 1;
3981     } catch (IndexOutOfBoundsException e) {
3982       int oldStackLength = astLengthStack.length;
3983       int[] oldPos = astLengthStack;
3984       astLengthStack = new int[oldStackLength + AstStackIncrement];
3985       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3986       astLengthStack[astLengthPtr] = 1;
3987     }
3988   }
3989
3990   protected void resetModifiers() {
3991     this.modifiers = AccDefault;
3992     this.modifiersSourceStart = -1; // <-- see comment into
3993     // modifiersFlag(int)
3994     this.scanner.commentPtr = -1;
3995   }
3996 }