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