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