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