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