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