improved parser string handling
[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           if (token > TokenNameKEYWORD) {
2215             getNextToken();
2216             break;
2217           } else {
2218             throwSyntaxError("Error in expression (found token '"
2219                 + scanner.toStringAction(token) + "').");
2220           }
2221         }
2222         return;
2223     }
2224     if (Scanner.TRACE) {
2225       System.out.println("TRACE: expr_without_variable() PART 2");
2226     }
2227     //  | expr T_BOOLEAN_OR expr
2228     //  | expr T_BOOLEAN_AND expr
2229     //  | expr T_LOGICAL_OR expr
2230     //  | expr T_LOGICAL_AND expr
2231     //  | expr T_LOGICAL_XOR expr
2232     //  | expr '|' expr
2233     //  | expr '&' expr
2234     //  | expr '^' expr
2235     //  | expr '.' expr
2236     //  | expr '+' expr
2237     //  | expr '-' expr
2238     //  | expr '*' expr
2239     //  | expr '/' expr
2240     //  | expr '%' expr
2241     //  | expr T_SL expr
2242     //  | expr T_SR expr
2243     //  | expr T_IS_IDENTICAL expr
2244     //  | expr T_IS_NOT_IDENTICAL expr
2245     //  | expr T_IS_EQUAL expr
2246     //  | expr T_IS_NOT_EQUAL expr
2247     //  | expr '<' expr
2248     //  | expr T_IS_SMALLER_OR_EQUAL expr
2249     //  | expr '>' expr
2250     //  | expr T_IS_GREATER_OR_EQUAL expr
2251     while (true) {
2252       switch (token) {
2253         case TokenNameOR_OR :
2254         case TokenNameAND_AND :
2255         case TokenNameand :
2256         case TokenNameor :
2257         case TokenNamexor :
2258         case TokenNameAND :
2259         case TokenNameOR :
2260         case TokenNameXOR :
2261         case TokenNameDOT :
2262         case TokenNamePLUS :
2263         case TokenNameMINUS :
2264         case TokenNameMULTIPLY :
2265         case TokenNameDIVIDE :
2266         case TokenNameREMAINDER :
2267         case TokenNameLEFT_SHIFT :
2268         case TokenNameRIGHT_SHIFT :
2269         case TokenNameEQUAL_EQUAL_EQUAL :
2270         case TokenNameNOT_EQUAL_EQUAL :
2271         case TokenNameEQUAL_EQUAL :
2272         case TokenNameNOT_EQUAL :
2273         case TokenNameLESS :
2274         case TokenNameLESS_EQUAL :
2275         case TokenNameGREATER :
2276         case TokenNameGREATER_EQUAL :
2277           getNextToken();
2278           expr();
2279           break;
2280         //  | expr T_INSTANCEOF class_name_reference
2281         //      | expr '?' expr ':' expr
2282         case TokenNameinstanceof :
2283           getNextToken();
2284           class_name_reference();
2285           break;
2286         case TokenNameQUESTION :
2287           getNextToken();
2288           expr();
2289           if (token == TokenNameCOLON) {
2290             getNextToken();
2291             expr();
2292           }
2293           break;
2294         default :
2295           return;
2296       }
2297     }
2298   }
2299   private void class_name_reference() {
2300     //  class_name_reference:
2301     //  T_STRING
2302     //| dynamic_class_name_reference
2303     if (Scanner.TRACE) {
2304       System.out.println("TRACE: class_name_reference()");
2305     }
2306     if (token == TokenNameIdentifier) {
2307       getNextToken();
2308     } else {
2309       dynamic_class_name_reference();
2310     }
2311   }
2312   private void dynamic_class_name_reference() {
2313     //dynamic_class_name_reference:
2314     //  base_variable T_OBJECT_OPERATOR object_property
2315     // dynamic_class_name_variable_properties
2316     //| base_variable
2317     if (Scanner.TRACE) {
2318       System.out.println("TRACE: dynamic_class_name_reference()");
2319     }
2320     base_variable();
2321     if (token == TokenNameMINUS_GREATER) {
2322       getNextToken();
2323       object_property();
2324       dynamic_class_name_variable_properties();
2325     }
2326   }
2327   private void dynamic_class_name_variable_properties() {
2328     //  dynamic_class_name_variable_properties:
2329     //                  dynamic_class_name_variable_properties
2330     // dynamic_class_name_variable_property
2331     //          | /* empty */
2332     if (Scanner.TRACE) {
2333       System.out.println("TRACE: dynamic_class_name_variable_properties()");
2334     }
2335     while (token == TokenNameMINUS_GREATER) {
2336       dynamic_class_name_variable_property();
2337     }
2338   }
2339   private void dynamic_class_name_variable_property() {
2340     //  dynamic_class_name_variable_property:
2341     //  T_OBJECT_OPERATOR object_property
2342     if (Scanner.TRACE) {
2343       System.out.println("TRACE: dynamic_class_name_variable_property()");
2344     }
2345     if (token == TokenNameMINUS_GREATER) {
2346       getNextToken();
2347       object_property();
2348     }
2349   }
2350   private void ctor_arguments() {
2351     //  ctor_arguments:
2352     //  /* empty */
2353     //| '(' function_call_parameter_list ')'
2354     if (token == TokenNameLPAREN) {
2355       getNextToken();
2356       if (token == TokenNameRPAREN) {
2357         getNextToken();
2358         return;
2359       }
2360       non_empty_function_call_parameter_list();
2361       if (token != TokenNameRPAREN) {
2362         throwSyntaxError("')' expected in ctor_arguments.");
2363       }
2364       getNextToken();
2365     }
2366   }
2367   private void assignment_list() {
2368     //  assignment_list:
2369     //  assignment_list ',' assignment_list_element
2370     //| assignment_list_element
2371     while (true) {
2372       assignment_list_element();
2373       if (token != TokenNameCOMMA) {
2374         break;
2375       }
2376       getNextToken();
2377     }
2378   }
2379   private void assignment_list_element() {
2380     //assignment_list_element:
2381     //  variable
2382     //| T_LIST '(' assignment_list ')'
2383     //| /* empty */
2384     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2385       variable();
2386     } else {
2387       if (token == TokenNamelist) {
2388         getNextToken();
2389         if (token == TokenNameLPAREN) {
2390           getNextToken();
2391           assignment_list();
2392           if (token != TokenNameRPAREN) {
2393             throwSyntaxError("')' expected after 'list' keyword.");
2394           }
2395           getNextToken();
2396         } else {
2397           throwSyntaxError("'(' expected after 'list' keyword.");
2398         }
2399       }
2400     }
2401   }
2402   private void array_pair_list() {
2403     //  array_pair_list:
2404     //  /* empty */
2405     //| non_empty_array_pair_list possible_comma
2406     non_empty_array_pair_list();
2407     if (token == TokenNameCOMMA) {
2408       getNextToken();
2409     }
2410   }
2411   private void non_empty_array_pair_list() {
2412     //non_empty_array_pair_list:
2413     //  non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2414     //| non_empty_array_pair_list ',' expr
2415     //| expr T_DOUBLE_ARROW expr
2416     //| expr
2417     //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2418     //| non_empty_array_pair_list ',' '&' w_variable
2419     //| expr T_DOUBLE_ARROW '&' w_variable
2420     //| '&' w_variable
2421     while (true) {
2422       if (token == TokenNameAND) {
2423         getNextToken();
2424         variable();
2425       } else {
2426         expr();
2427         if (token == TokenNameAND) {
2428           getNextToken();
2429           variable();
2430         } else if (token == TokenNameEQUAL_GREATER) {
2431           getNextToken();
2432           if (token == TokenNameAND) {
2433             getNextToken();
2434             variable();
2435           } else {
2436             expr();
2437           }
2438         }
2439       }
2440       if (token != TokenNameCOMMA) {
2441         return;
2442       }
2443       getNextToken();
2444       if (token == TokenNameRPAREN) {
2445         return;
2446       }
2447     }
2448   }
2449   //  private void variableList() {
2450   //    do {
2451   //      variable();
2452   //      if (token == TokenNameCOMMA) {
2453   //        getNextToken();
2454   //      } else {
2455   //        break;
2456   //      }
2457   //    } while (true);
2458   //  }
2459   private void variable_without_objects() {
2460     //  variable_without_objects:
2461     //                  reference_variable
2462     //          | simple_indirect_reference reference_variable
2463     if (Scanner.TRACE) {
2464       System.out.println("TRACE: variable_without_objects()");
2465     }
2466     while (token == TokenNameDOLLAR) {
2467       getNextToken();
2468     }
2469     reference_variable();
2470   }
2471   private void function_call() {
2472     //  function_call:
2473     //  T_STRING '(' function_call_parameter_list ')'
2474     //| class_constant '(' function_call_parameter_list ')'
2475     //| static_member '(' function_call_parameter_list ')'
2476     //| variable_without_objects '(' function_call_parameter_list ')'
2477     if (Scanner.TRACE) {
2478       System.out.println("TRACE: function_call()");
2479     }
2480     if (token == TokenNameIdentifier) {
2481       getNextToken();
2482       switch (token) {
2483         case TokenNamePAAMAYIM_NEKUDOTAYIM :
2484           // static member:
2485           getNextToken();
2486           if (token == TokenNameIdentifier) {
2487             // class _constant
2488             getNextToken();
2489           } else {
2490             //        static member:
2491             variable_without_objects();
2492           }
2493           break;
2494       }
2495     } else {
2496       variable_without_objects();
2497     }
2498     if (token != TokenNameLPAREN) {
2499       // TODO is this ok ?
2500       return;
2501       //      throwSyntaxError("'(' expected in function call.");
2502     }
2503     getNextToken();
2504     if (token == TokenNameRPAREN) {
2505       getNextToken();
2506       return;
2507     }
2508     non_empty_function_call_parameter_list();
2509     if (token != TokenNameRPAREN) {
2510       throwSyntaxError("')' expected in function call.");
2511     }
2512     getNextToken();
2513   }
2514   //  private void function_call_parameter_list() {
2515   //    function_call_parameter_list:
2516   //            non_empty_function_call_parameter_list { $$ = $1; }
2517   //    | /* empty */
2518   //  }
2519   private void non_empty_function_call_parameter_list() {
2520     //non_empty_function_call_parameter_list:
2521     //          expr_without_variable
2522     //  | variable
2523     //  | '&' w_variable
2524     //  | non_empty_function_call_parameter_list ',' expr_without_variable
2525     //  | non_empty_function_call_parameter_list ',' variable
2526     //  | non_empty_function_call_parameter_list ',' '&' w_variable
2527     if (Scanner.TRACE) {
2528       System.out.println("TRACE: non_empty_function_call_parameter_list()");
2529     }
2530     while (true) {
2531       if (token == TokenNameAND) {
2532         getNextToken();
2533         w_variable();
2534       } else {
2535         //        if (token == TokenNameIdentifier || token == TokenNameVariable
2536         //            || token == TokenNameDOLLAR) {
2537         //          variable();
2538         //        } else {
2539         expr_without_variable(true);
2540         //        }
2541       }
2542       if (token != TokenNameCOMMA) {
2543         break;
2544       }
2545       getNextToken();
2546     }
2547   }
2548   private void fully_qualified_class_name() {
2549     if (token == TokenNameIdentifier) {
2550       getNextToken();
2551     } else {
2552       throwSyntaxError("Class name expected.");
2553     }
2554   }
2555   private void static_member() {
2556     //  static_member:
2557     //  fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2558     // variable_without_objects
2559     if (Scanner.TRACE) {
2560       System.out.println("TRACE: static_member()");
2561     }
2562     fully_qualified_class_name();
2563     if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2564       throwSyntaxError("'::' expected after class name (static_member).");
2565     }
2566     getNextToken();
2567     variable_without_objects();
2568   }
2569   private void base_variable_with_function_calls() {
2570     //  base_variable_with_function_calls:
2571     //  base_variable
2572     //| function_call
2573     boolean functionCall = false;
2574     if (Scanner.TRACE) {
2575       System.out.println("TRACE: base_variable_with_function_calls()");
2576     }
2577     //    if (token == TokenNameIdentifier) {
2578     //      functionCall = true;
2579     //    } else if (token == TokenNameVariable) {
2580     //      int tempToken = token;
2581     //      int tempPosition = scanner.currentPosition;
2582     //      getNextToken();
2583     //      if (token == TokenNameLPAREN) {
2584     //        functionCall = true;
2585     //      }
2586     //      token = tempToken;
2587     //      scanner.currentPosition = tempPosition;
2588     //      scanner.phpMode = true;
2589     //    }
2590     //    if (functionCall) {
2591     function_call();
2592     //    } else {
2593     //      base_variable();
2594     //    }
2595   }
2596   private void base_variable() {
2597     //  base_variable:
2598     //                  reference_variable
2599     //          | simple_indirect_reference reference_variable
2600     //          | static_member
2601     if (Scanner.TRACE) {
2602       System.out.println("TRACE: base_variable()");
2603     }
2604     if (token == TokenNameIdentifier) {
2605       static_member();
2606     } else {
2607       while (token == TokenNameDOLLAR) {
2608         getNextToken();
2609       }
2610       reference_variable();
2611     }
2612   }
2613   //  private void simple_indirect_reference() {
2614   //    // simple_indirect_reference:
2615   //    // '$'
2616   //    //| simple_indirect_reference '$'
2617   //  }
2618   private void reference_variable() {
2619     //  reference_variable:
2620     //                  reference_variable '[' dim_offset ']'
2621     //          | reference_variable '{' expr '}'
2622     //          | compound_variable
2623     if (Scanner.TRACE) {
2624       System.out.println("TRACE: reference_variable()");
2625     }
2626     compound_variable();
2627     while (true) {
2628       if (token == TokenNameLBRACE) {
2629         getNextToken();
2630         expr();
2631         if (token != TokenNameRBRACE) {
2632           throwSyntaxError("'}' expected in reference variable.");
2633         }
2634         getNextToken();
2635       } else if (token == TokenNameLBRACKET) {
2636         getNextToken();
2637         if (token != TokenNameRBRACKET) {
2638           expr();
2639           //        dim_offset();
2640           if (token != TokenNameRBRACKET) {
2641             throwSyntaxError("']' expected in reference variable.");
2642           }
2643         }
2644         getNextToken();
2645       } else {
2646         break;
2647       }
2648     }
2649   }
2650   private void compound_variable() {
2651     //  compound_variable:
2652     //                  T_VARIABLE
2653     //          | '$' '{' expr '}'
2654     if (Scanner.TRACE) {
2655       System.out.println("TRACE: compound_variable()");
2656     }
2657     if (token == TokenNameVariable) {
2658       getNextToken();
2659     } else {
2660       // because of simple_indirect_reference
2661       while (token == TokenNameDOLLAR) {
2662         getNextToken();
2663       }
2664       if (token != TokenNameLBRACE) {
2665         throwSyntaxError("'{' expected after compound variable token '$'.");
2666       }
2667       getNextToken();
2668       expr();
2669       if (token != TokenNameRBRACE) {
2670         throwSyntaxError("'}' expected after compound variable token '$'.");
2671       }
2672       getNextToken();
2673     }
2674   }
2675   //  private void dim_offset() {
2676   //    // dim_offset:
2677   //    // /* empty */
2678   //    // | expr
2679   //    expr();
2680   //  }
2681   private void object_property() {
2682     //  object_property:
2683     //  object_dim_list
2684     //| variable_without_objects
2685     if (Scanner.TRACE) {
2686       System.out.println("TRACE: object_property()");
2687     }
2688     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2689       variable_without_objects();
2690     } else {
2691       object_dim_list();
2692     }
2693   }
2694   private void object_dim_list() {
2695     //object_dim_list:
2696     //  object_dim_list '[' dim_offset ']'
2697     //| object_dim_list '{' expr '}'
2698     //| variable_name
2699     if (Scanner.TRACE) {
2700       System.out.println("TRACE: object_dim_list()");
2701     }
2702     variable_name();
2703     while (true) {
2704       if (token == TokenNameLBRACE) {
2705         getNextToken();
2706         expr();
2707         if (token != TokenNameRBRACE) {
2708           throwSyntaxError("'}' expected in object_dim_list.");
2709         }
2710         getNextToken();
2711       } else if (token == TokenNameLBRACKET) {
2712         getNextToken();
2713         if (token == TokenNameRBRACKET) {
2714           getNextToken();
2715           continue;
2716         }
2717         expr();
2718         if (token != TokenNameRBRACKET) {
2719           throwSyntaxError("']' expected in object_dim_list.");
2720         }
2721         getNextToken();
2722       } else {
2723         break;
2724       }
2725     }
2726   }
2727   private void variable_name() {
2728     //variable_name:
2729     //  T_STRING
2730     //| '{' expr '}'
2731     if (Scanner.TRACE) {
2732       System.out.println("TRACE: variable_name()");
2733     }
2734     if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
2735       if (token > TokenNameKEYWORD) {
2736         // TODO show a warning "Keyword used as variable" ?
2737       }
2738       getNextToken();
2739     } else {
2740       if (token != TokenNameLBRACE) {
2741         throwSyntaxError("'{' expected in variable name.");
2742       }
2743       getNextToken();
2744       expr();
2745       if (token != TokenNameRBRACE) {
2746         throwSyntaxError("'}' expected in variable name.");
2747       }
2748       getNextToken();
2749     }
2750   }
2751   private void r_variable() {
2752     variable();
2753   }
2754   private void w_variable() {
2755     variable();
2756   }
2757   private void rw_variable() {
2758     variable();
2759   }
2760   private void variable() {
2761     //    variable:
2762     //          base_variable_with_function_calls T_OBJECT_OPERATOR
2763     //                  object_property method_or_not variable_properties
2764     //  | base_variable_with_function_calls
2765     base_variable_with_function_calls();
2766     if (token == TokenNameMINUS_GREATER) {
2767       getNextToken();
2768       object_property();
2769       method_or_not();
2770       variable_properties();
2771     }
2772     //    if (token == TokenNameDOLLAR_LBRACE) {
2773     //      getNextToken();
2774     //      expr();
2775     //      ;
2776     //      if (token != TokenNameRBRACE) {
2777     //        throwSyntaxError("'}' expected after indirect variable token '${'.");
2778     //      }
2779     //      getNextToken();
2780     //    } else {
2781     //      if (token == TokenNameVariable) {
2782     //        getNextToken();
2783     //        if (token == TokenNameLBRACKET) {
2784     //          getNextToken();
2785     //          expr();
2786     //          if (token != TokenNameRBRACKET) {
2787     //            throwSyntaxError("']' expected in variable-list.");
2788     //          }
2789     //          getNextToken();
2790     //        } else if (token == TokenNameEQUAL) {
2791     //          getNextToken();
2792     //          static_scalar();
2793     //        }
2794     //      } else {
2795     //        throwSyntaxError("$-variable expected in variable-list.");
2796     //      }
2797     //    }
2798   }
2799   private void variable_properties() {
2800     //  variable_properties:
2801     //                  variable_properties variable_property
2802     //          | /* empty */
2803     while (token == TokenNameMINUS_GREATER) {
2804       variable_property();
2805     }
2806   }
2807   private void variable_property() {
2808     //  variable_property:
2809     //                  T_OBJECT_OPERATOR object_property method_or_not
2810     if (Scanner.TRACE) {
2811       System.out.println("TRACE: variable_property()");
2812     }
2813     if (token == TokenNameMINUS_GREATER) {
2814       getNextToken();
2815       object_property();
2816       method_or_not();
2817     } else {
2818       throwSyntaxError("'->' expected in variable_property.");
2819     }
2820   }
2821   private void method_or_not() {
2822     //  method_or_not:
2823     //                  '(' function_call_parameter_list ')'
2824     //          | /* empty */
2825     if (Scanner.TRACE) {
2826       System.out.println("TRACE: method_or_not()");
2827     }
2828     if (token == TokenNameLPAREN) {
2829       getNextToken();
2830       if (token == TokenNameRPAREN) {
2831         getNextToken();
2832         return;
2833       }
2834       non_empty_function_call_parameter_list();
2835       if (token != TokenNameRPAREN) {
2836         throwSyntaxError("')' expected in method_or_not.");
2837       }
2838       getNextToken();
2839     }
2840   }
2841   private void exit_expr() {
2842     //  /* empty */
2843     //  | '(' ')'
2844     //  | '(' expr ')'
2845     if (token != TokenNameLPAREN) {
2846       return;
2847     }
2848     getNextToken();
2849     if (token == TokenNameRPAREN) {
2850       getNextToken();
2851       return;
2852     }
2853     expr();
2854     if (token != TokenNameRPAREN) {
2855       throwSyntaxError("')' expected after keyword 'exit'");
2856     }
2857     getNextToken();
2858   }
2859   private void encaps_list() {
2860     //                  encaps_list encaps_var
2861     //          | encaps_list T_STRING
2862     //          | encaps_list T_NUM_STRING
2863     //          | encaps_list T_ENCAPSED_AND_WHITESPACE
2864     //          | encaps_list T_CHARACTER
2865     //          | encaps_list T_BAD_CHARACTER
2866     //          | encaps_list '['
2867     //          | encaps_list ']'
2868     //          | encaps_list '{'
2869     //          | encaps_list '}'
2870     //          | encaps_list T_OBJECT_OPERATOR
2871     //          | /* empty */
2872     while (true) {
2873       switch (token) {
2874         case TokenNameSTRING :
2875           getNextToken();
2876           break;
2877         case TokenNameLBRACE :
2878           //          scanner.encapsedStringStack.pop();
2879           getNextToken();
2880           break;
2881         case TokenNameRBRACE :
2882           //          scanner.encapsedStringStack.pop();
2883           getNextToken();
2884           break;
2885         case TokenNameLBRACKET :
2886           //          scanner.encapsedStringStack.pop();
2887           getNextToken();
2888           break;
2889         case TokenNameRBRACKET :
2890           //          scanner.encapsedStringStack.pop();
2891           getNextToken();
2892           break;
2893         case TokenNameMINUS_GREATER :
2894           //          scanner.encapsedStringStack.pop();
2895           getNextToken();
2896           break;
2897         case TokenNameVariable :
2898         case TokenNameDOLLAR_LBRACE :
2899         case TokenNameCURLY_OPEN :
2900           encaps_var();
2901           break;
2902         //        case TokenNameDOLLAR :
2903         //          getNextToken();
2904         //          if (token == TokenNameLBRACE) {
2905         //            token = TokenNameDOLLAR_LBRACE;
2906         //            encaps_var();
2907         //          }
2908         //          break;
2909         default :
2910           char encapsedChar = ((Character) scanner.encapsedStringStack.peek())
2911               .charValue();
2912           if (encapsedChar == '$') {
2913             scanner.encapsedStringStack.pop();
2914             encapsedChar = ((Character) scanner.encapsedStringStack.peek())
2915                 .charValue();
2916             switch (encapsedChar) {
2917               case '`' :
2918                 if (token == TokenNameEncapsedString0) {
2919                   return;
2920                 }
2921                 token = TokenNameSTRING;
2922                 continue;
2923               case '\'' :
2924                 if (token == TokenNameEncapsedString1) {
2925                   return;
2926                 }
2927                 token = TokenNameSTRING;
2928                 continue;
2929               case '"' :
2930                 if (token == TokenNameEncapsedString2) {
2931                   return;
2932                 }
2933                 token = TokenNameSTRING;
2934                 continue;
2935             }
2936           }
2937           return;
2938       }
2939     }
2940   }
2941   private void encaps_var() {
2942     //                  T_VARIABLE
2943     //          | T_VARIABLE '[' encaps_var_offset ']'
2944     //          | T_VARIABLE T_OBJECT_OPERATOR T_STRING
2945     //          | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
2946     //          | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
2947     //          | T_CURLY_OPEN variable '}'
2948     switch (token) {
2949       case TokenNameVariable :
2950         getNextToken();
2951         if (token == TokenNameLBRACKET) {
2952           getNextToken();
2953           //          if (token == TokenNameRBRACKET) {
2954           //            getNextToken();
2955           //          } else {
2956           expr(); //encaps_var_offset();
2957           if (token != TokenNameRBRACKET) {
2958             throwSyntaxError("']' expected after variable.");
2959           }
2960           //          scanner.encapsedStringStack.pop();
2961           getNextToken();
2962           //          }
2963         } else if (token == TokenNameMINUS_GREATER) {
2964           getNextToken();
2965           if (token != TokenNameIdentifier) {
2966             throwSyntaxError("Identifier expected after '->'.");
2967           }
2968           //          scanner.encapsedStringStack.pop();
2969           getNextToken();
2970         }
2971         //        else {
2972         //          // scanner.encapsedStringStack.pop();
2973         //          int tempToken = TokenNameSTRING;
2974         //          if (!scanner.encapsedStringStack.isEmpty()
2975         //              && (token == TokenNameEncapsedString0
2976         //                  || token == TokenNameEncapsedString1
2977         //                  || token == TokenNameEncapsedString2 || token == TokenNameERROR)) {
2978         //            char encapsedChar = ((Character) scanner.encapsedStringStack.peek())
2979         //                .charValue();
2980         //            switch (token) {
2981         //              case TokenNameEncapsedString0 :
2982         //                if (encapsedChar == '`') {
2983         //                  tempToken = TokenNameEncapsedString0;
2984         //                }
2985         //                break;
2986         //              case TokenNameEncapsedString1 :
2987         //                if (encapsedChar == '\'') {
2988         //                  tempToken = TokenNameEncapsedString1;
2989         //                }
2990         //                break;
2991         //              case TokenNameEncapsedString2 :
2992         //                if (encapsedChar == '"') {
2993         //                  tempToken = TokenNameEncapsedString2;
2994         //                }
2995         //                break;
2996         //              case TokenNameERROR :
2997         //                if (scanner.source[scanner.currentPosition - 1] == '\\') {
2998         //                  scanner.currentPosition--;
2999         //                  getNextToken();
3000         //                }
3001         //                break;
3002         //            }
3003         //          }
3004         //          token = tempToken;
3005         //        }
3006         break;
3007       case TokenNameDOLLAR_LBRACE :
3008         getNextToken();
3009         if (token == TokenNameIdentifier) {
3010           getNextToken();
3011           if (token == TokenNameLBRACKET) {
3012             getNextToken();
3013             //            if (token == TokenNameRBRACKET) {
3014             //              getNextToken();
3015             //            } else {
3016             expr();
3017             if (token != TokenNameRBRACKET) {
3018               throwSyntaxError("']' expected after '${'.");
3019             }
3020             getNextToken();
3021             //            }
3022           }
3023           if (token != TokenNameRBRACE) {
3024             throwSyntaxError("'}' expected after '${'.");
3025           }
3026           //          scanner.encapsedStringStack.pop();
3027           getNextToken();
3028         } else {
3029           expr();
3030           if (token != TokenNameRBRACE) {
3031             throwSyntaxError("'}' expected.");
3032           }
3033           //          scanner.encapsedStringStack.pop();
3034           getNextToken();
3035         }
3036         break;
3037       case TokenNameCURLY_OPEN :
3038         getNextToken();
3039         if (token == TokenNameIdentifier||token>TokenNameKEYWORD) {
3040           getNextToken();
3041           if (token == TokenNameLBRACKET) {
3042             getNextToken();
3043             //            if (token == TokenNameRBRACKET) {
3044             //              getNextToken();
3045             //            } else {
3046             expr();
3047             if (token != TokenNameRBRACKET) {
3048               throwSyntaxError("']' expected after '{$'.");
3049             }
3050             getNextToken();
3051             //            }
3052           } else if (token == TokenNameMINUS_GREATER) {
3053             getNextToken();
3054             if (token != TokenNameIdentifier) {
3055               throwSyntaxError("String token expected.");
3056             }
3057             getNextToken();
3058           }
3059           //          if (token != TokenNameRBRACE) {
3060           //            throwSyntaxError("'}' expected after '{$'.");
3061           //          }
3062           //          // scanner.encapsedStringStack.pop();
3063           //          getNextToken();
3064         } else {
3065           expr();
3066           if (token != TokenNameRBRACE) {
3067             throwSyntaxError("'}' expected.");
3068           }
3069           //          scanner.encapsedStringStack.pop();
3070           getNextToken();
3071         }
3072         break;
3073     }
3074   }
3075   private void encaps_var_offset() {
3076     //                  T_STRING
3077     //          | T_NUM_STRING
3078     //          | T_VARIABLE
3079     switch (token) {
3080       case TokenNameSTRING :
3081         getNextToken();
3082         break;
3083       case TokenNameIntegerLiteral :
3084         getNextToken();
3085         break;
3086       case TokenNameVariable :
3087         getNextToken();
3088         break;
3089       case TokenNameIdentifier :
3090         getNextToken();
3091         break;
3092       default :
3093         throwSyntaxError("Variable or String token expected.");
3094         break;
3095     }
3096   }
3097   private void internal_functions_in_yacc() {
3098     switch (token) {
3099       case TokenNameisset :
3100         //      T_ISSET '(' isset_variables ')'
3101         getNextToken();
3102         if (token != TokenNameLPAREN) {
3103           throwSyntaxError("'(' expected after keyword 'isset'");
3104         }
3105         getNextToken();
3106         isset_variables();
3107         if (token != TokenNameRPAREN) {
3108           throwSyntaxError("')' expected after keyword 'isset'");
3109         }
3110         getNextToken();
3111         break;
3112       case TokenNameempty :
3113         //      T_EMPTY '(' variable ')'
3114         getNextToken();
3115         if (token != TokenNameLPAREN) {
3116           throwSyntaxError("'(' expected after keyword 'empty'");
3117         }
3118         getNextToken();
3119         variable();
3120         if (token != TokenNameRPAREN) {
3121           throwSyntaxError("')' expected after keyword 'empty'");
3122         }
3123         getNextToken();
3124         break;
3125       case TokenNameinclude :
3126         //T_INCLUDE expr
3127         getNextToken();
3128         expr();
3129         break;
3130       case TokenNameinclude_once :
3131         //      T_INCLUDE_ONCE expr
3132         getNextToken();
3133         expr();
3134         break;
3135       case TokenNameeval :
3136         //      T_EVAL '(' expr ')'
3137         getNextToken();
3138         if (token != TokenNameLPAREN) {
3139           throwSyntaxError("'(' expected after keyword 'eval'");
3140         }
3141         getNextToken();
3142         expr();
3143         if (token != TokenNameRPAREN) {
3144           throwSyntaxError("')' expected after keyword 'eval'");
3145         }
3146         getNextToken();
3147         break;
3148       case TokenNamerequire :
3149         //T_REQUIRE expr
3150         getNextToken();
3151         expr();
3152         break;
3153       case TokenNamerequire_once :
3154         //      T_REQUIRE_ONCE expr
3155         getNextToken();
3156         expr();
3157         break;
3158     }
3159   }
3160   private void isset_variables() {
3161     //  variable
3162     //  | isset_variables ','
3163     if (token == TokenNameRPAREN) {
3164       throwSyntaxError("Variable expected after keyword 'isset'");
3165     }
3166     while (true) {
3167       variable();
3168       if (token == TokenNameCOMMA) {
3169         getNextToken();
3170       } else {
3171         break;
3172       }
3173     }
3174   }
3175   private boolean common_scalar() {
3176     //  common_scalar:
3177     //  T_LNUMBER
3178     //  | T_DNUMBER
3179     //  | T_CONSTANT_ENCAPSED_STRING
3180     //  | T_LINE
3181     //  | T_FILE
3182     //  | T_CLASS_C
3183     //  | T_METHOD_C
3184     //  | T_FUNC_C
3185     switch (token) {
3186       case TokenNameIntegerLiteral :
3187         getNextToken();
3188         return true;
3189       case TokenNameDoubleLiteral :
3190         getNextToken();
3191         return true;
3192       case TokenNameStringLiteral :
3193         getNextToken();
3194         return true;
3195       case TokenNameStringConstant :
3196         getNextToken();
3197         return true;
3198       case TokenNameStringInterpolated :
3199         getNextToken();
3200         return true;
3201       case TokenNameFILE :
3202         getNextToken();
3203         return true;
3204       case TokenNameLINE :
3205         getNextToken();
3206         return true;
3207       case TokenNameCLASS_C :
3208         getNextToken();
3209         return true;
3210       case TokenNameMETHOD_C :
3211         getNextToken();
3212         return true;
3213       case TokenNameFUNC_C :
3214         getNextToken();
3215         return true;
3216     }
3217     return false;
3218   }
3219   private void scalar() {
3220     //  scalar:
3221     //  T_STRING
3222     //| T_STRING_VARNAME
3223     //| class_constant
3224     //| common_scalar
3225     //| '"' encaps_list '"'
3226     //| '\'' encaps_list '\''
3227     //| T_START_HEREDOC encaps_list T_END_HEREDOC
3228     throwSyntaxError("Not yet implemented (scalar).");
3229   }
3230   private void static_scalar() {
3231     //    static_scalar: /* compile-time evaluated scalars */
3232     //          common_scalar
3233     //  | T_STRING
3234     //  | '+' static_scalar
3235     //  | '-' static_scalar
3236     //  | T_ARRAY '(' static_array_pair_list ')'
3237     //  | static_class_constant
3238     if (common_scalar()) {
3239       return;
3240     }
3241     switch (token) {
3242       case TokenNameIdentifier :
3243         getNextToken();
3244         //        static_class_constant:
3245         //              T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3246         if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3247           getNextToken();
3248           if (token == TokenNameIdentifier) {
3249             getNextToken();
3250           } else {
3251             throwSyntaxError("Identifier expected after '::' operator.");
3252           }
3253         }
3254         break;
3255       case TokenNameEncapsedString0 :
3256         try {
3257           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3258           while (scanner.currentCharacter != '`') {
3259             if (scanner.currentCharacter == '\\') {
3260               scanner.currentPosition++;
3261             }
3262             scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3263           }
3264           getNextToken();
3265         } catch (IndexOutOfBoundsException e) {
3266           throwSyntaxError("'`' expected at end of static string.");
3267         }
3268         break;
3269       case TokenNameEncapsedString1 :
3270         try {
3271           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3272           while (scanner.currentCharacter != '\'') {
3273             if (scanner.currentCharacter == '\\') {
3274               scanner.currentPosition++;
3275             }
3276             scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3277           }
3278           getNextToken();
3279         } catch (IndexOutOfBoundsException e) {
3280           throwSyntaxError("'\'' expected at end of static string.");
3281         }
3282         break;
3283       case TokenNameEncapsedString2 :
3284         try {
3285           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3286           while (scanner.currentCharacter != '"') {
3287             if (scanner.currentCharacter == '\\') {
3288               scanner.currentPosition++;
3289             }
3290             scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3291           }
3292           getNextToken();
3293         } catch (IndexOutOfBoundsException e) {
3294           throwSyntaxError("'\"' expected at end of static string.");
3295         }
3296         break;
3297       case TokenNamePLUS :
3298         getNextToken();
3299         static_scalar();
3300         break;
3301       case TokenNameMINUS :
3302         getNextToken();
3303         static_scalar();
3304         break;
3305       case TokenNamearray :
3306         getNextToken();
3307         if (token != TokenNameLPAREN) {
3308           throwSyntaxError("'(' expected after keyword 'array'");
3309         }
3310         getNextToken();
3311         if (token == TokenNameRPAREN) {
3312           getNextToken();
3313           break;
3314         }
3315         non_empty_static_array_pair_list();
3316         if (token != TokenNameRPAREN) {
3317           throwSyntaxError("')' expected after keyword 'array'");
3318         }
3319         getNextToken();
3320         break;
3321       //      case TokenNamenull :
3322       //        getNextToken();
3323       //        break;
3324       //      case TokenNamefalse :
3325       //        getNextToken();
3326       //        break;
3327       //      case TokenNametrue :
3328       //        getNextToken();
3329       //        break;
3330       default :
3331         throwSyntaxError("Static scalar/constant expected.");
3332     }
3333   }
3334   private void non_empty_static_array_pair_list() {
3335     //  non_empty_static_array_pair_list:
3336     //  non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3337     // static_scalar
3338     //| non_empty_static_array_pair_list ',' static_scalar
3339     //| static_scalar T_DOUBLE_ARROW static_scalar
3340     //| static_scalar
3341     while (true) {
3342       static_scalar();
3343       if (token == TokenNameEQUAL_GREATER) {
3344         getNextToken();
3345         static_scalar();
3346       }
3347       if (token != TokenNameCOMMA) {
3348         break;
3349       }
3350       getNextToken();
3351       if (token == TokenNameRPAREN) {
3352         break;
3353       }
3354     }
3355   }
3356   public void reportSyntaxError() { //int act, int currentKind, int
3357     // stateStackTop) {
3358     /* remember current scanner position */
3359     int startPos = scanner.startPosition;
3360     int currentPos = scanner.currentPosition;
3361     //          String[] expectings;
3362     //          String tokenName = name[symbol_index[currentKind]];
3363     //fetch all "accurate" possible terminals that could recover the error
3364     //          int start, end = start = asi(stack[stateStackTop]);
3365     //          while (asr[end] != 0)
3366     //                  end++;
3367     //          int length = end - start;
3368     //          expectings = new String[length];
3369     //          if (length != 0) {
3370     //                  char[] indexes = new char[length];
3371     //                  System.arraycopy(asr, start, indexes, 0, length);
3372     //                  for (int i = 0; i < length; i++) {
3373     //                          expectings[i] = name[symbol_index[indexes[i]]];
3374     //                  }
3375     //          }
3376     //if the pb is an EOF, try to tell the user that they are some
3377     //          if (tokenName.equals(UNEXPECTED_EOF)) {
3378     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3379     //                          char[] tokenSource;
3380     //                          try {
3381     //                                  tokenSource = this.scanner.getCurrentTokenSource();
3382     //                          } catch (Exception e) {
3383     //                                  tokenSource = new char[] {};
3384     //                          }
3385     //                          problemReporter().parseError(
3386     //                                  this.scanner.startPosition,
3387     //                                  this.scanner.currentPosition - 1,
3388     //                                  tokenSource,
3389     //                                  tokenName,
3390     //                                  expectings);
3391     //                  }
3392     //          } else { //the next test is HEAVILY grammar DEPENDENT.
3393     //                  if ((length == 14)
3394     //                          && (expectings[0] == "=") //$NON-NLS-1$
3395     //                          && (expectings[1] == "*=") //$NON-NLS-1$
3396     //                          && (expressionPtr > -1)) {
3397     //                                  switch(currentKind) {
3398     //                                          case TokenNameSEMICOLON:
3399     //                                          case TokenNamePLUS:
3400     //                                          case TokenNameMINUS:
3401     //                                          case TokenNameDIVIDE:
3402     //                                          case TokenNameREMAINDER:
3403     //                                          case TokenNameMULTIPLY:
3404     //                                          case TokenNameLEFT_SHIFT:
3405     //                                          case TokenNameRIGHT_SHIFT:
3406     //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3407     //                                          case TokenNameLESS:
3408     //                                          case TokenNameGREATER:
3409     //                                          case TokenNameLESS_EQUAL:
3410     //                                          case TokenNameGREATER_EQUAL:
3411     //                                          case TokenNameEQUAL_EQUAL:
3412     //                                          case TokenNameNOT_EQUAL:
3413     //                                          case TokenNameXOR:
3414     //                                          case TokenNameAND:
3415     //                                          case TokenNameOR:
3416     //                                          case TokenNameOR_OR:
3417     //                                          case TokenNameAND_AND:
3418     //                                                  // the ; is not the expected token ==> it ends a statement when an
3419     // expression is not ended
3420     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3421     //                                                  break;
3422     //                                          case TokenNameRBRACE :
3423     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3424     //                                                  break;
3425     //                                          default:
3426     //                                                  char[] tokenSource;
3427     //                                                  try {
3428     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
3429     //                                                  } catch (Exception e) {
3430     //                                                          tokenSource = new char[] {};
3431     //                                                  }
3432     //                                                  problemReporter().parseError(
3433     //                                                          this.scanner.startPosition,
3434     //                                                          this.scanner.currentPosition - 1,
3435     //                                                          tokenSource,
3436     //                                                          tokenName,
3437     //                                                          expectings);
3438     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
3439     //                                  }
3440     //                  } else {
3441     char[] tokenSource;
3442     try {
3443       tokenSource = this.scanner.getCurrentTokenSource();
3444     } catch (Exception e) {
3445       tokenSource = new char[]{};
3446     }
3447     //                          problemReporter().parseError(
3448     //                                  this.scanner.startPosition,
3449     //                                  this.scanner.currentPosition - 1,
3450     //                                  tokenSource,
3451     //                                  tokenName,
3452     //                                  expectings);
3453     this.checkAndReportBracketAnomalies(problemReporter());
3454     //                  }
3455     //          }
3456     /* reset scanner where it was */
3457     scanner.startPosition = startPos;
3458     scanner.currentPosition = currentPos;
3459   }
3460   public static final int RoundBracket = 0;
3461   public static final int SquareBracket = 1;
3462   public static final int CurlyBracket = 2;
3463   public static final int BracketKinds = 3;
3464   protected int[] nestedMethod; //the ptr is nestedType
3465   protected int nestedType, dimensions;
3466   //ast stack
3467   final static int AstStackIncrement = 100;
3468   protected int astPtr;
3469   protected AstNode[] astStack = new AstNode[AstStackIncrement];
3470   protected int astLengthPtr;
3471   protected int[] astLengthStack;
3472   AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3473   public CompilationUnitDeclaration compilationUnit; /*
3474                                                       * the result from parse()
3475                                                       */
3476   protected ReferenceContext referenceContext;
3477   protected ProblemReporter problemReporter;
3478   protected CompilerOptions options;
3479   //  protected CompilationResult compilationResult;
3480   /**
3481    * Returns this parser's problem reporter initialized with its reference
3482    * context. Also it is assumed that a problem is going to be reported, so
3483    * initializes the compilation result's line positions.
3484    */
3485   public ProblemReporter problemReporter() {
3486     if (scanner.recordLineSeparator) {
3487       compilationUnit.compilationResult.lineSeparatorPositions = scanner
3488           .getLineEnds();
3489     }
3490     problemReporter.referenceContext = referenceContext;
3491     return problemReporter;
3492   }
3493   /*
3494    * Reconsider the entire source looking for inconsistencies in {} () []
3495    */
3496   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3497     scanner.wasAcr = false;
3498     boolean anomaliesDetected = false;
3499     try {
3500       char[] source = scanner.source;
3501       int[] leftCount = {0, 0, 0};
3502       int[] rightCount = {0, 0, 0};
3503       int[] depths = {0, 0, 0};
3504       int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3505       int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3506       int[][] rightPositions = new int[][]{new int[10], new int[10],
3507           new int[10]};
3508       int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3509       scanner.currentPosition = scanner.initialPosition; //starting
3510       // point
3511       // (first-zero-based
3512       // char)
3513       while (scanner.currentPosition < scanner.eofPosition) { //loop for
3514         // jumping
3515         // over
3516         // comments
3517         try {
3518           // ---------Consume white space and handles
3519           // startPosition---------
3520           boolean isWhiteSpace;
3521           do {
3522             scanner.startPosition = scanner.currentPosition;
3523             //                                          if (((scanner.currentCharacter =
3524             // source[scanner.currentPosition++]) == '\\') &&
3525             // (source[scanner.currentPosition] == 'u')) {
3526             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3527             //                                          } else {
3528             if (scanner.recordLineSeparator
3529                 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3530               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3531                 // only record line positions we have not
3532                 // recorded yet
3533                 scanner.pushLineSeparator();
3534               }
3535             }
3536             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3537             //                                          }
3538           } while (isWhiteSpace
3539               && (scanner.currentPosition < scanner.eofPosition));
3540           // -------consume token until } is found---------
3541           switch (scanner.currentCharacter) {
3542             case '{' :
3543               {
3544                 int index = leftCount[CurlyBracket]++;
3545                 if (index == leftPositions[CurlyBracket].length) {
3546                   System.arraycopy(leftPositions[CurlyBracket], 0,
3547                       (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3548                       index);
3549                   System
3550                       .arraycopy(leftDepths[CurlyBracket], 0,
3551                           (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3552                           index);
3553                 }
3554                 leftPositions[CurlyBracket][index] = scanner.startPosition;
3555                 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3556               }
3557               break;
3558             case '}' :
3559               {
3560                 int index = rightCount[CurlyBracket]++;
3561                 if (index == rightPositions[CurlyBracket].length) {
3562                   System.arraycopy(rightPositions[CurlyBracket], 0,
3563                       (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3564                       index);
3565                   System.arraycopy(rightDepths[CurlyBracket], 0,
3566                       (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3567                       index);
3568                 }
3569                 rightPositions[CurlyBracket][index] = scanner.startPosition;
3570                 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3571               }
3572               break;
3573             case '(' :
3574               {
3575                 int index = leftCount[RoundBracket]++;
3576                 if (index == leftPositions[RoundBracket].length) {
3577                   System.arraycopy(leftPositions[RoundBracket], 0,
3578                       (leftPositions[RoundBracket] = new int[index * 2]), 0,
3579                       index);
3580                   System
3581                       .arraycopy(leftDepths[RoundBracket], 0,
3582                           (leftDepths[RoundBracket] = new int[index * 2]), 0,
3583                           index);
3584                 }
3585                 leftPositions[RoundBracket][index] = scanner.startPosition;
3586                 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3587               }
3588               break;
3589             case ')' :
3590               {
3591                 int index = rightCount[RoundBracket]++;
3592                 if (index == rightPositions[RoundBracket].length) {
3593                   System.arraycopy(rightPositions[RoundBracket], 0,
3594                       (rightPositions[RoundBracket] = new int[index * 2]), 0,
3595                       index);
3596                   System.arraycopy(rightDepths[RoundBracket], 0,
3597                       (rightDepths[RoundBracket] = new int[index * 2]), 0,
3598                       index);
3599                 }
3600                 rightPositions[RoundBracket][index] = scanner.startPosition;
3601                 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3602               }
3603               break;
3604             case '[' :
3605               {
3606                 int index = leftCount[SquareBracket]++;
3607                 if (index == leftPositions[SquareBracket].length) {
3608                   System.arraycopy(leftPositions[SquareBracket], 0,
3609                       (leftPositions[SquareBracket] = new int[index * 2]), 0,
3610                       index);
3611                   System.arraycopy(leftDepths[SquareBracket], 0,
3612                       (leftDepths[SquareBracket] = new int[index * 2]), 0,
3613                       index);
3614                 }
3615                 leftPositions[SquareBracket][index] = scanner.startPosition;
3616                 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3617               }
3618               break;
3619             case ']' :
3620               {
3621                 int index = rightCount[SquareBracket]++;
3622                 if (index == rightPositions[SquareBracket].length) {
3623                   System.arraycopy(rightPositions[SquareBracket], 0,
3624                       (rightPositions[SquareBracket] = new int[index * 2]), 0,
3625                       index);
3626                   System.arraycopy(rightDepths[SquareBracket], 0,
3627                       (rightDepths[SquareBracket] = new int[index * 2]), 0,
3628                       index);
3629                 }
3630                 rightPositions[SquareBracket][index] = scanner.startPosition;
3631                 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3632               }
3633               break;
3634             case '\'' :
3635               {
3636                 if (scanner.getNextChar('\\')) {
3637                   scanner.scanEscapeCharacter();
3638                 } else { // consume next character
3639                   scanner.unicodeAsBackSlash = false;
3640                   //                                                                    if (((scanner.currentCharacter =
3641                   // source[scanner.currentPosition++]) ==
3642                   // '\\') &&
3643                   // (source[scanner.currentPosition] ==
3644                   // 'u')) {
3645                   //                                                                            scanner.getNextUnicodeChar();
3646                   //                                                                    } else {
3647                   if (scanner.withoutUnicodePtr != 0) {
3648                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3649                   }
3650                   //                                                                    }
3651                 }
3652                 scanner.getNextChar('\'');
3653                 break;
3654               }
3655             case '"' :
3656               // consume next character
3657               scanner.unicodeAsBackSlash = false;
3658               //                                                        if (((scanner.currentCharacter =
3659               // source[scanner.currentPosition++]) == '\\') &&
3660               // (source[scanner.currentPosition] == 'u')) {
3661               //                                                                scanner.getNextUnicodeChar();
3662               //                                                        } else {
3663               if (scanner.withoutUnicodePtr != 0) {
3664                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3665               }
3666               //                                                        }
3667               while (scanner.currentCharacter != '"') {
3668                 if (scanner.currentCharacter == '\r') {
3669                   if (source[scanner.currentPosition] == '\n')
3670                     scanner.currentPosition++;
3671                   break; // the string cannot go further that
3672                   // the line
3673                 }
3674                 if (scanner.currentCharacter == '\n') {
3675                   break; // the string cannot go further that
3676                   // the line
3677                 }
3678                 if (scanner.currentCharacter == '\\') {
3679                   scanner.scanEscapeCharacter();
3680                 }
3681                 // consume next character
3682                 scanner.unicodeAsBackSlash = false;
3683                 //                                                              if (((scanner.currentCharacter =
3684                 // source[scanner.currentPosition++]) == '\\')
3685                 // && (source[scanner.currentPosition] == 'u'))
3686                 // {
3687                 //                                                                      scanner.getNextUnicodeChar();
3688                 //                                                              } else {
3689                 if (scanner.withoutUnicodePtr != 0) {
3690                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3691                 }
3692                 //                                                              }
3693               }
3694               break;
3695             case '/' :
3696               {
3697                 int test;
3698                 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3699                   // comment
3700                   //get the next char
3701                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3702                       && (source[scanner.currentPosition] == 'u')) {
3703                     //-------------unicode traitement
3704                     // ------------
3705                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3706                     scanner.currentPosition++;
3707                     while (source[scanner.currentPosition] == 'u') {
3708                       scanner.currentPosition++;
3709                     }
3710                     if ((c1 = Character
3711                         .getNumericValue(source[scanner.currentPosition++])) > 15
3712                         || c1 < 0
3713                         || (c2 = Character
3714                             .getNumericValue(source[scanner.currentPosition++])) > 15
3715                         || c2 < 0
3716                         || (c3 = Character
3717                             .getNumericValue(source[scanner.currentPosition++])) > 15
3718                         || c3 < 0
3719                         || (c4 = Character
3720                             .getNumericValue(source[scanner.currentPosition++])) > 15
3721                         || c4 < 0) { //error don't
3722                       // care of the
3723                       // value
3724                       scanner.currentCharacter = 'A';
3725                     } //something different from \n and \r
3726                     else {
3727                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3728                     }
3729                   }
3730                   while (scanner.currentCharacter != '\r'
3731                       && scanner.currentCharacter != '\n') {
3732                     //get the next char
3733                     scanner.startPosition = scanner.currentPosition;
3734                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3735                         && (source[scanner.currentPosition] == 'u')) {
3736                       //-------------unicode traitement
3737                       // ------------
3738                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3739                       scanner.currentPosition++;
3740                       while (source[scanner.currentPosition] == 'u') {
3741                         scanner.currentPosition++;
3742                       }
3743                       if ((c1 = Character
3744                           .getNumericValue(source[scanner.currentPosition++])) > 15
3745                           || c1 < 0
3746                           || (c2 = Character
3747                               .getNumericValue(source[scanner.currentPosition++])) > 15
3748                           || c2 < 0
3749                           || (c3 = Character
3750                               .getNumericValue(source[scanner.currentPosition++])) > 15
3751                           || c3 < 0
3752                           || (c4 = Character
3753                               .getNumericValue(source[scanner.currentPosition++])) > 15
3754                           || c4 < 0) { //error don't
3755                         // care of the
3756                         // value
3757                         scanner.currentCharacter = 'A';
3758                       } //something different from \n
3759                       // and \r
3760                       else {
3761                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3762                       }
3763                     }
3764                   }
3765                   if (scanner.recordLineSeparator
3766                       && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3767                     if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3768                       // only record line positions we
3769                       // have not recorded yet
3770                       scanner.pushLineSeparator();
3771                       if (this.scanner.taskTags != null) {
3772                         this.scanner.checkTaskTag(this.scanner
3773                             .getCurrentTokenStartPosition(), this.scanner
3774                             .getCurrentTokenEndPosition());
3775                       }
3776                     }
3777                   }
3778                   break;
3779                 }
3780                 if (test > 0) { //traditional and annotation
3781                   // comment
3782                   boolean star = false;
3783                   // consume next character
3784                   scanner.unicodeAsBackSlash = false;
3785                   //                                                                    if (((scanner.currentCharacter =
3786                   // source[scanner.currentPosition++]) ==
3787                   // '\\') &&
3788                   // (source[scanner.currentPosition] ==
3789                   // 'u')) {
3790                   //                                                                            scanner.getNextUnicodeChar();
3791                   //                                                                    } else {
3792                   if (scanner.withoutUnicodePtr != 0) {
3793                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3794                   }
3795                   //                                                                    }
3796                   if (scanner.currentCharacter == '*') {
3797                     star = true;
3798                   }
3799                   //get the next char
3800                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3801                       && (source[scanner.currentPosition] == 'u')) {
3802                     //-------------unicode traitement
3803                     // ------------
3804                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3805                     scanner.currentPosition++;
3806                     while (source[scanner.currentPosition] == 'u') {
3807                       scanner.currentPosition++;
3808                     }
3809                     if ((c1 = Character
3810                         .getNumericValue(source[scanner.currentPosition++])) > 15
3811                         || c1 < 0
3812                         || (c2 = Character
3813                             .getNumericValue(source[scanner.currentPosition++])) > 15
3814                         || c2 < 0
3815                         || (c3 = Character
3816                             .getNumericValue(source[scanner.currentPosition++])) > 15
3817                         || c3 < 0
3818                         || (c4 = Character
3819                             .getNumericValue(source[scanner.currentPosition++])) > 15
3820                         || c4 < 0) { //error don't
3821                       // care of the
3822                       // value
3823                       scanner.currentCharacter = 'A';
3824                     } //something different from * and /
3825                     else {
3826                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3827                     }
3828                   }
3829                   //loop until end of comment */
3830                   while ((scanner.currentCharacter != '/') || (!star)) {
3831                     star = scanner.currentCharacter == '*';
3832                     //get next char
3833                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3834                         && (source[scanner.currentPosition] == 'u')) {
3835                       //-------------unicode traitement
3836                       // ------------
3837                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3838                       scanner.currentPosition++;
3839                       while (source[scanner.currentPosition] == 'u') {
3840                         scanner.currentPosition++;
3841                       }
3842                       if ((c1 = Character
3843                           .getNumericValue(source[scanner.currentPosition++])) > 15
3844                           || c1 < 0
3845                           || (c2 = Character
3846                               .getNumericValue(source[scanner.currentPosition++])) > 15
3847                           || c2 < 0
3848                           || (c3 = Character
3849                               .getNumericValue(source[scanner.currentPosition++])) > 15
3850                           || c3 < 0
3851                           || (c4 = Character
3852                               .getNumericValue(source[scanner.currentPosition++])) > 15
3853                           || c4 < 0) { //error don't
3854                         // care of the
3855                         // value
3856                         scanner.currentCharacter = 'A';
3857                       } //something different from * and
3858                       // /
3859                       else {
3860                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3861                       }
3862                     }
3863                   }
3864                   if (this.scanner.taskTags != null) {
3865                     this.scanner.checkTaskTag(this.scanner
3866                         .getCurrentTokenStartPosition(), this.scanner
3867                         .getCurrentTokenEndPosition());
3868                   }
3869                   break;
3870                 }
3871                 break;
3872               }
3873             default :
3874               if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3875                 scanner.scanIdentifierOrKeyword(false);
3876                 break;
3877               }
3878               if (Character.isDigit(scanner.currentCharacter)) {
3879                 scanner.scanNumber(false);
3880                 break;
3881               }
3882           }
3883           //-----------------end switch while
3884           // try--------------------
3885         } catch (IndexOutOfBoundsException e) {
3886           break; // read until EOF
3887         } catch (InvalidInputException e) {
3888           return false; // no clue
3889         }
3890       }
3891       if (scanner.recordLineSeparator) {
3892         //                              compilationUnit.compilationResult.lineSeparatorPositions =
3893         // scanner.getLineEnds();
3894       }
3895       // check placement anomalies against other kinds of brackets
3896       for (int kind = 0; kind < BracketKinds; kind++) {
3897         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3898           int start = leftPositions[kind][leftIndex]; // deepest
3899           // first
3900           // find matching closing bracket
3901           int depth = leftDepths[kind][leftIndex];
3902           int end = -1;
3903           for (int i = 0; i < rightCount[kind]; i++) {
3904             int pos = rightPositions[kind][i];
3905             // want matching bracket further in source with same
3906             // depth
3907             if ((pos > start) && (depth == rightDepths[kind][i])) {
3908               end = pos;
3909               break;
3910             }
3911           }
3912           if (end < 0) { // did not find a good closing match
3913             problemReporter.unmatchedBracket(start, referenceContext,
3914                 compilationUnit.compilationResult);
3915             return true;
3916           }
3917           // check if even number of opening/closing other brackets
3918           // in between this pair of brackets
3919           int balance = 0;
3920           for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3921             for (int i = 0; i < leftCount[otherKind]; i++) {
3922               int pos = leftPositions[otherKind][i];
3923               if ((pos > start) && (pos < end))
3924                 balance++;
3925             }
3926             for (int i = 0; i < rightCount[otherKind]; i++) {
3927               int pos = rightPositions[otherKind][i];
3928               if ((pos > start) && (pos < end))
3929                 balance--;
3930             }
3931             if (balance != 0) {
3932               problemReporter.unmatchedBracket(start, referenceContext,
3933                   compilationUnit.compilationResult); //bracket
3934               // anomaly
3935               return true;
3936             }
3937           }
3938         }
3939         // too many opening brackets ?
3940         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3941           anomaliesDetected = true;
3942           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3943               - i - 1], referenceContext, compilationUnit.compilationResult);
3944         }
3945         // too many closing brackets ?
3946         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3947           anomaliesDetected = true;
3948           problemReporter.unmatchedBracket(rightPositions[kind][i],
3949               referenceContext, compilationUnit.compilationResult);
3950         }
3951         if (anomaliesDetected)
3952           return true;
3953       }
3954       return anomaliesDetected;
3955     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3956       return anomaliesDetected;
3957     } catch (NullPointerException e) { // jdk1.2.2 jit bug
3958       return anomaliesDetected;
3959     }
3960   }
3961   protected void pushOnAstLengthStack(int pos) {
3962     try {
3963       astLengthStack[++astLengthPtr] = pos;
3964     } catch (IndexOutOfBoundsException e) {
3965       int oldStackLength = astLengthStack.length;
3966       int[] oldPos = astLengthStack;
3967       astLengthStack = new int[oldStackLength + StackIncrement];
3968       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3969       astLengthStack[astLengthPtr] = pos;
3970     }
3971   }
3972   protected void pushOnAstStack(AstNode node) {
3973     /*
3974      * add a new obj on top of the ast stack
3975      */
3976     try {
3977       astStack[++astPtr] = node;
3978     } catch (IndexOutOfBoundsException e) {
3979       int oldStackLength = astStack.length;
3980       AstNode[] oldStack = astStack;
3981       astStack = new AstNode[oldStackLength + AstStackIncrement];
3982       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3983       astPtr = oldStackLength;
3984       astStack[astPtr] = node;
3985     }
3986     try {
3987       astLengthStack[++astLengthPtr] = 1;
3988     } catch (IndexOutOfBoundsException e) {
3989       int oldStackLength = astLengthStack.length;
3990       int[] oldPos = astLengthStack;
3991       astLengthStack = new int[oldStackLength + AstStackIncrement];
3992       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3993       astLengthStack[astLengthPtr] = 1;
3994     }
3995   }
3996 }