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