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