misc changes in the internal builder
[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
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 != TokenNameINLINE_HTML) {
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 != TokenNameINLINE_HTML) {
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 != TokenNameINLINE_HTML) {
1167           throwSyntaxError("';' expected after 'echo' statement.");
1168         }
1169         getNextToken();
1170       }
1171       return;
1172     } else if (token == TokenNameINLINE_HTML) {
1173       getNextToken();
1174       return;
1175       //    } else if (token == TokenNameprint) {
1176       //      getNextToken();
1177       //      expression();
1178       //      if (token == TokenNameSEMICOLON) {
1179       //        getNextToken();
1180       //      } else {
1181       //        if (token != TokenNameStopPHP) {
1182       //          throwSyntaxError("';' expected after 'print' statement.");
1183       //        }
1184       //        getNextToken();
1185       //      }
1186       //      return;
1187     } else if (token == TokenNameglobal) {
1188       getNextToken();
1189       global_var_list();
1190       if (token == TokenNameSEMICOLON) {
1191         getNextToken();
1192       } else {
1193         if (token != TokenNameINLINE_HTML) {
1194           throwSyntaxError("';' expected after 'global' statement.");
1195         }
1196         getNextToken();
1197       }
1198       return;
1199     } else if (token == TokenNamestatic) {
1200       getNextToken();
1201       static_var_list();
1202       if (token == TokenNameSEMICOLON) {
1203         getNextToken();
1204       } else {
1205         if (token != TokenNameINLINE_HTML) {
1206           throwSyntaxError("';' expected after 'static' statement.");
1207         }
1208         getNextToken();
1209       }
1210       return;
1211     }else if (token == TokenNameunset) {
1212       getNextToken();
1213       if (token == TokenNameLPAREN) {
1214         getNextToken();
1215       } else {
1216         throwSyntaxError("'(' expected after 'unset' statement.");
1217       }
1218       unset_variables();
1219       if (token == TokenNameRPAREN) {
1220         getNextToken();
1221       } else {
1222         throwSyntaxError("')' expected after 'unset' statement.");
1223       }
1224       if (token == TokenNameSEMICOLON) {
1225         getNextToken();
1226       } else {
1227         if (token != TokenNameINLINE_HTML) {
1228           throwSyntaxError("';' expected after 'unset' statement.");
1229         }
1230         getNextToken();
1231       }
1232       return;
1233     } else if (token == TokenNamefunction) {
1234       MethodDeclaration methodDecl = new MethodDeclaration(
1235           this.compilationUnit.compilationResult);
1236       methodDecl.declarationSourceStart = scanner
1237           .getCurrentTokenStartPosition();
1238       getNextToken();
1239       functionDefinition(methodDecl);
1240       return;
1241     } else if (token == TokenNametry) {
1242       getNextToken();
1243 if (token != TokenNameLBRACE) {
1244         throwSyntaxError("'{' expected in 'try' statement.");
1245       }
1246       getNextToken();
1247       statementList();
1248 if (token != TokenNameRBRACE) {
1249         throwSyntaxError("'}' expected in 'try' statement.");
1250       }
1251 getNextToken();
1252       return;
1253     } else if (token == TokenNamecatch) {
1254 getNextToken();
1255 if (token != TokenNameLPAREN) {
1256         throwSyntaxError("'(' expected in 'catch' statement.");
1257       }
1258       getNextToken();
1259       fully_qualified_class_name();
1260       if (token != TokenNameVariable) {
1261         throwSyntaxError("Variable expected in 'catch' statement.");
1262       }
1263       getNextToken();
1264
1265       if (token != TokenNameRBRACE) {
1266         throwSyntaxError("')' expected in 'catch' statement.");
1267       }
1268       getNextToken();
1269 getNextToken();
1270 if (token != TokenNameLBRACE) {
1271         throwSyntaxError("'{' expected in 'catch' statement.");
1272       }
1273       getNextToken();
1274       statementList();
1275 if (token != TokenNameRBRACE) {
1276         throwSyntaxError("'}' expected in 'catch' statement.");
1277       }
1278 getNextToken();
1279       additional_catches();
1280       return;
1281     } else if (token == TokenNamethrow) {
1282       getNextToken();
1283       
1284       expr();
1285       if (token == TokenNameSEMICOLON) {
1286         getNextToken();
1287       } else {
1288         throwSyntaxError("';' expected after 'throw' exxpression.");
1289       }
1290       
1291       return;
1292     } else if (token == TokenNamefinal || token == TokenNameabstract
1293         || token == TokenNameclass || token == TokenNameinterface) {
1294       TypeDeclaration typeDecl = new TypeDeclaration(
1295           this.compilationUnit.compilationResult);
1296       typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1297       // default super class
1298       typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1299       compilationUnit.types.add(typeDecl);
1300       try {
1301         pushOnAstStack(typeDecl);
1302         unticked_class_declaration_statement(typeDecl);
1303         //        classBody(typeDecl);
1304       } finally {
1305         astPtr--;
1306         astLengthPtr--;
1307       }
1308       return;
1309       //      } else {
1310       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
1311     } else if (token == TokenNameLBRACE) {
1312       getNextToken();
1313       if (token != TokenNameRBRACE) {
1314         statementList();
1315       }
1316       if (token == TokenNameRBRACE) {
1317         getNextToken();
1318         return;
1319       } else {
1320         throwSyntaxError("'}' expected.");
1321       }
1322     } else {
1323       if (token != TokenNameSEMICOLON) {
1324         expr();
1325       }
1326       if (token == TokenNameSEMICOLON) {
1327         getNextToken();
1328         return;
1329       } else {
1330         if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
1331           throwSyntaxError("';' expected after expression (Found token: "
1332               + scanner.toStringAction(token) + ")");
1333         }
1334         getNextToken();
1335       }
1336     }
1337   }
1338   private void additional_catches() {
1339     while (token == TokenNamecatch) {
1340       getNextToken();
1341       if (token != TokenNameLPAREN) {
1342         throwSyntaxError("'(' expected in 'catch' statement.");
1343       }
1344       getNextToken();
1345       fully_qualified_class_name();
1346       if (token != TokenNameVariable) {
1347         throwSyntaxError("Variable expected in 'catch' statement.");
1348       }
1349       getNextToken();
1350
1351       if (token != TokenNameRBRACE) {
1352         throwSyntaxError("')' expected in 'catch' statement.");
1353       }
1354       getNextToken();
1355       getNextToken();
1356       if (token != TokenNameLBRACE) {
1357         throwSyntaxError("'{' expected in 'catch' statement.");
1358       }
1359       getNextToken();
1360       statementList();
1361       if (token != TokenNameRBRACE) {
1362         throwSyntaxError("'}' expected in 'catch' statement.");
1363       }
1364       getNextToken();
1365     }
1366   }
1367
1368   private void global_var_list() {
1369     //  global_var_list:
1370     //  global_var_list ',' global_var
1371     //| global_var
1372     while (true) {
1373       global_var();
1374       if (token != TokenNameCOMMA) {
1375         break;
1376       }
1377       getNextToken();
1378     }
1379   }
1380   private void global_var() {
1381     //global_var:
1382     //  T_VARIABLE
1383     //| '$' r_variable
1384     //| '$' '{' expr '}'
1385     if (token == TokenNameVariable) {
1386       getNextToken();
1387     } else if (token == TokenNameDOLLAR) {
1388       getNextToken();
1389       if (token == TokenNameLPAREN) {
1390         getNextToken();
1391         expr();
1392         if (token != TokenNameLPAREN) {
1393           throwSyntaxError("')' expected in global variable.");
1394         }
1395         getNextToken();
1396       } else {
1397         r_variable();
1398       }
1399     }
1400   }
1401   private void static_var_list() {
1402     //static_var_list:
1403     //  static_var_list ',' T_VARIABLE
1404     //| static_var_list ',' T_VARIABLE '=' static_scalar
1405     //| T_VARIABLE
1406     //| T_VARIABLE '=' static_scalar
1407     while (true) {
1408       if (token == TokenNameVariable) {
1409         getNextToken();
1410         if (token == TokenNameEQUAL) {
1411           getNextToken();
1412           static_scalar();
1413         }
1414         if (token != TokenNameCOMMA) {
1415           break;
1416         }
1417         getNextToken();
1418       } else {
1419         break;
1420       }
1421     }
1422   }
1423   private void unset_variables() {
1424     //    unset_variables:
1425     //                  unset_variable
1426     //          | unset_variables ',' unset_variable
1427     //    unset_variable:
1428     //                  variable
1429     while (true) {
1430       variable();
1431       if (token != TokenNameCOMMA) {
1432         break;
1433       }
1434       getNextToken();
1435     }
1436   }
1437   private final void initializeModifiers() {
1438     this.modifiers = 0;
1439     this.modifiersSourceStart = -1;
1440   }
1441   private final void checkAndSetModifiers(int flag) {
1442     this.modifiers |= flag;
1443     if (this.modifiersSourceStart < 0)
1444       this.modifiersSourceStart = this.scanner.startPosition;
1445   }
1446   private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1447     initializeModifiers();
1448     if (token == TokenNameinterface) {
1449       //      interface_entry T_STRING
1450       //                interface_extends_list
1451       //                '{' class_statement_list '}'
1452       checkAndSetModifiers(AccInterface);
1453       getNextToken();
1454       typeDecl.modifiers = this.modifiers;
1455       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1456         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1457         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1458         typeDecl.name = scanner.getCurrentIdentifierSource();
1459         if (token > TokenNameKEYWORD) {
1460           throwSyntaxError("Don't use a keyword for interface declaration ["
1461               + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1462               typeDecl.sourceEnd);
1463         }
1464         getNextToken();
1465         interface_extends_list();
1466       } else {
1467         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1468         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1469         typeDecl.name = new char[]{' '};
1470         throwSyntaxError("Interface name expected after keyword 'interface'.",
1471             typeDecl.sourceStart, typeDecl.sourceEnd);
1472         return;
1473       }
1474     } else {
1475       //      class_entry_type T_STRING extends_from
1476       //                implements_list
1477       //                '{' class_statement_list'}'
1478       class_entry_type();
1479       typeDecl.modifiers = this.modifiers;
1480       //identifier
1481       //identifier 'extends' identifier
1482       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1483         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1484         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1485         typeDecl.name = scanner.getCurrentIdentifierSource();
1486         if (token > TokenNameKEYWORD) {
1487           throwSyntaxError("Don't use a keyword for class declaration ["
1488               + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1489               typeDecl.sourceEnd);
1490         }
1491         getNextToken();
1492         //    extends_from:
1493         //              /* empty */
1494         //      | T_EXTENDS fully_qualified_class_name
1495         if (token == TokenNameextends) {
1496           getNextToken();
1497           if (token == TokenNameIdentifier) {
1498             getNextToken();
1499           } else {
1500             throwSyntaxError("Class name expected after keyword 'extends'.",
1501                 scanner.getCurrentTokenStartPosition(), scanner
1502                     .getCurrentTokenEndPosition());
1503           }
1504         }
1505         implements_list();
1506       } else {
1507         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1508         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1509         typeDecl.name = new char[]{' '};
1510         throwSyntaxError("Class name expected after keyword 'class'.",
1511             typeDecl.sourceStart, typeDecl.sourceEnd);
1512         return;
1513       }
1514     }
1515     //  '{' class_statement_list '}'
1516     if (token == TokenNameLBRACE) {
1517       getNextToken();
1518       if (token != TokenNameRBRACE) {
1519         class_statement_list();
1520       }
1521       if (token == TokenNameRBRACE) {
1522         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1523         getNextToken();
1524       } else {
1525         throwSyntaxError("'}' expected at end of class body.");
1526       }
1527     } else {
1528       throwSyntaxError("'{' expected at start of class body.");
1529     }
1530   }
1531   private void class_entry_type() {
1532     //  T_CLASS
1533     //  | T_ABSTRACT T_CLASS
1534     //  | T_FINAL T_CLASS
1535     if (token == TokenNameclass) {
1536       getNextToken();
1537     } else if (token == TokenNameabstract) {
1538       checkAndSetModifiers(AccAbstract);
1539       getNextToken();
1540       if (token != TokenNameclass) {
1541         throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1542       }
1543       getNextToken();
1544     } else if (token == TokenNamefinal) {
1545       checkAndSetModifiers(AccFinal);
1546       getNextToken();
1547       if (token != TokenNameclass) {
1548         throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1549       }
1550       getNextToken();
1551     } else {
1552       throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1553     }
1554   }
1555   private void interface_extends_list() {
1556     //  /* empty */
1557     //  | T_EXTENDS interface_list
1558     if (token == TokenNameextends) {
1559       getNextToken();
1560       interface_list();
1561     }
1562   }
1563   private void implements_list() {
1564     //  /* empty */
1565     //  | T_IMPLEMENTS interface_list
1566     if (token == TokenNameimplements) {
1567       getNextToken();
1568       interface_list();
1569     }
1570   }
1571   private void interface_list() {
1572     //  interface_list:
1573     //  fully_qualified_class_name
1574     //| interface_list ',' fully_qualified_class_name
1575     do {
1576       if (token == TokenNameIdentifier) {
1577         getNextToken();
1578       } else {
1579         throwSyntaxError("Interface name expected after keyword 'implements'.");
1580       }
1581       if (token != TokenNameCOMMA) {
1582         return;
1583       }
1584       getNextToken();
1585     } while (true);
1586   }
1587   //  private void classBody(TypeDeclaration typeDecl) {
1588   //    //'{' [class-element-list] '}'
1589   //    if (token == TokenNameLBRACE) {
1590   //      getNextToken();
1591   //      if (token != TokenNameRBRACE) {
1592   //        class_statement_list();
1593   //      }
1594   //      if (token == TokenNameRBRACE) {
1595   //        typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1596   //        getNextToken();
1597   //      } else {
1598   //        throwSyntaxError("'}' expected at end of class body.");
1599   //      }
1600   //    } else {
1601   //      throwSyntaxError("'{' expected at start of class body.");
1602   //    }
1603   //  }
1604   private void class_statement_list() {
1605     do {
1606       class_statement();
1607     } while (token == TokenNamepublic || token == TokenNameprotected
1608         || token == TokenNameprivate || token == TokenNamestatic
1609         || token == TokenNameabstract || token == TokenNamefinal
1610         || token == TokenNamefunction || token == TokenNamevar);
1611   }
1612   private void class_statement() {
1613     //    class_statement:
1614     //          variable_modifiers class_variable_declaration ';'
1615     //  | class_constant_declaration ';'
1616     //  | method_modifiers T_FUNCTION is_reference T_STRING
1617     //    '(' parameter_list ')' method_body
1618     initializeModifiers();
1619     if (token == TokenNamevar) {
1620       checkAndSetModifiers(AccPublic);
1621       problemReporter.phpVarDeprecatedWarning(scanner
1622           .getCurrentTokenStartPosition(),
1623           scanner.getCurrentTokenEndPosition(), referenceContext,
1624           compilationUnit.compilationResult);
1625       getNextToken();
1626       class_variable_declaration();
1627     } else {
1628       boolean hasModifiers = member_modifiers();
1629       if (token == TokenNamefunction) {
1630         if (!hasModifiers) {
1631           checkAndSetModifiers(AccPublic);
1632         }
1633         MethodDeclaration methodDecl = new MethodDeclaration(
1634             this.compilationUnit.compilationResult);
1635         methodDecl.declarationSourceStart = scanner
1636             .getCurrentTokenStartPosition();
1637         methodDecl.modifiers = this.modifiers;
1638         getNextToken();
1639         functionDefinition(methodDecl);
1640       } else {
1641         if (!hasModifiers) {
1642           throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1643         }
1644         class_variable_declaration();
1645       }
1646     }
1647     //    if (token == TokenNamefunction) {
1648     //      MethodDeclaration methodDecl = new MethodDeclaration(
1649     //          this.compilationUnit.compilationResult);
1650     //      methodDecl.declarationSourceStart = scanner
1651     //          .getCurrentTokenStartPosition();
1652     //      getNextToken();
1653     //      functionDefinition(methodDecl);
1654     //    } else if (token == TokenNamevar) {
1655     //      getNextToken();
1656     //      classProperty();
1657     //    } else {
1658     //      throwSyntaxError("'function' or 'var' expected.");
1659     //    }
1660   }
1661   //  private void variable_modifiers() {
1662   //    // variable_modifiers:
1663   //    // non_empty_member_modifiers
1664   //    //| T_VAR
1665   //    initializeModifiers();
1666   //    if (token == TokenNamevar) {
1667   //      checkAndSetModifiers(AccPublic);
1668   //      reportSyntaxError(
1669   //          "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
1670   // modifier for field declarations.",
1671   //          scanner.getCurrentTokenStartPosition(), scanner
1672   //              .getCurrentTokenEndPosition());
1673   //      getNextToken();
1674   //    } else {
1675   //      if (!member_modifiers()) {
1676   //        throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1677   // field declarations.");
1678   //      }
1679   //    }
1680   //  }
1681   //  private void method_modifiers() {
1682   //    //method_modifiers:
1683   //    // /* empty */
1684   //    //| non_empty_member_modifiers
1685   //    initializeModifiers();
1686   //    if (!member_modifiers()) {
1687   //      checkAndSetModifiers(AccPublic);
1688   //    }
1689   //  }
1690   private boolean member_modifiers() {
1691     //  T_PUBLIC
1692     //| T_PROTECTED
1693     //| T_PRIVATE
1694     //| T_STATIC
1695     //| T_ABSTRACT
1696     //| T_FINAL
1697     boolean foundToken = false;
1698     while (true) {
1699       if (token == TokenNamepublic) {
1700         checkAndSetModifiers(AccPublic);
1701         getNextToken();
1702         foundToken = true;
1703       } else if (token == TokenNameprotected) {
1704         checkAndSetModifiers(AccProtected);
1705         getNextToken();
1706         foundToken = true;
1707       } else if (token == TokenNameprivate) {
1708         checkAndSetModifiers(AccPrivate);
1709         getNextToken();
1710         foundToken = true;
1711       } else if (token == TokenNamestatic) {
1712         checkAndSetModifiers(AccStatic);
1713         getNextToken();
1714         foundToken = true;
1715       } else if (token == TokenNameabstract) {
1716         checkAndSetModifiers(AccAbstract);
1717         getNextToken();
1718         foundToken = true;
1719       } else if (token == TokenNamefinal) {
1720         checkAndSetModifiers(AccFinal);
1721         getNextToken();
1722         foundToken = true;
1723       } else {
1724         break;
1725       }
1726     }
1727     return foundToken;
1728   }
1729   private void class_variable_declaration() {
1730     //    class_variable_declaration:
1731     //          class_variable_declaration ',' T_VARIABLE
1732     //  | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1733     //  | T_VARIABLE
1734     //  | T_VARIABLE '=' static_scalar
1735     do {
1736       if (token == TokenNameVariable) {
1737         getNextToken();
1738         if (token == TokenNameEQUAL) {
1739           getNextToken();
1740           static_scalar();
1741         }
1742       } else {
1743         //        if (token == TokenNamethis) {
1744         //          throwSyntaxError("'$this' not allowed after keyword 'public'
1745         // 'protected' 'private' 'var'.");
1746         //        }
1747         throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1748       }
1749       if (token != TokenNameCOMMA) {
1750         break;
1751       }
1752       getNextToken();
1753     } while (true);
1754     if (token != TokenNameSEMICOLON) {
1755       throwSyntaxError("';' expected after field declaration.");
1756     }
1757     getNextToken();
1758   }
1759   private void functionDefinition(MethodDeclaration methodDecl) {
1760     if (astPtr == 0) {
1761       compilationUnit.types.add(methodDecl);
1762     } else {
1763       AstNode node = astStack[astPtr];
1764       if (node instanceof TypeDeclaration) {
1765         TypeDeclaration typeDecl = ((TypeDeclaration) node);
1766         if (typeDecl.methods == null) {
1767           typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1768         } else {
1769           AbstractMethodDeclaration[] newMethods;
1770           System
1771               .arraycopy(
1772                   typeDecl.methods,
1773                   0,
1774                   newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1775                   1, typeDecl.methods.length);
1776           newMethods[0] = methodDecl;
1777           typeDecl.methods = newMethods;
1778         }
1779       }
1780     }
1781     functionDeclarator(methodDecl);
1782     functionBody(methodDecl);
1783   }
1784   private void functionDeclarator(MethodDeclaration methodDecl) {
1785     //identifier '(' [parameter-list] ')'
1786     if (token == TokenNameAND) {
1787       getNextToken();
1788     }
1789     if (token == TokenNameIdentifier) {
1790       methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1791       methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1792       methodDecl.selector = scanner.getCurrentIdentifierSource();
1793       getNextToken();
1794       if (token == TokenNameLPAREN) {
1795         getNextToken();
1796       } else {
1797         throwSyntaxError("'(' expected in function declaration.");
1798       }
1799       if (token != TokenNameRPAREN) {
1800         parameterList();
1801       }
1802       if (token != TokenNameRPAREN) {
1803         throwSyntaxError("')' expected in function declaration.");
1804       } else {
1805         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1806         getNextToken();
1807       }
1808     } else {
1809       if (token > TokenNameKEYWORD) {
1810         throwSyntaxError("Don't use keyword for function declaration [" + token
1811             + "].");
1812       }
1813       throwSyntaxError("Function name expected after keyword 'function'.");
1814     }
1815   }
1816   //
1817   private void parameterList() {
1818     //parameter-declaration
1819     //parameter-list ',' parameter-declaration
1820     do {
1821       parameterDeclaration();
1822       if (token != TokenNameCOMMA) {
1823         break;
1824       }
1825       getNextToken();
1826     } while (true);
1827   }
1828   private void parameterDeclaration() {
1829     //variable
1830     //variable-reference
1831     if (token == TokenNameAND) {
1832       getNextToken();
1833       if (isVariable()) {
1834         getNextToken();
1835       } else {
1836         throwSyntaxError("Variable expected after reference operator '&'.");
1837       }
1838     }
1839     //variable '=' constant
1840     if (token == TokenNameVariable) {
1841       getNextToken();
1842       if (token == TokenNameEQUAL) {
1843         getNextToken();
1844         static_scalar();
1845       }
1846       return;
1847     }
1848     //    if (token == TokenNamethis) {
1849     //      throwSyntaxError("Reserved word '$this' not allowed in parameter
1850     // declaration.");
1851     //    }
1852   }
1853   private void labeledStatementList() {
1854     if (token != TokenNamecase && token != TokenNamedefault) {
1855       throwSyntaxError("'case' or 'default' expected.");
1856     }
1857     do {
1858       if (token == TokenNamecase) {
1859         getNextToken();
1860         expr(); //constant();
1861         if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1862           getNextToken();
1863           if (token == TokenNamecase || token == TokenNamedefault) { // empty
1864             // case
1865             // statement
1866             // ?
1867             continue;
1868           }
1869           statementList();
1870         }
1871         //        else if (token == TokenNameSEMICOLON) {
1872         //          setMarker(
1873         //            "':' expected after 'case' keyword (Found token: " +
1874         // scanner.toStringAction(token) + ")",
1875         //            scanner.getCurrentTokenStartPosition(),
1876         //            scanner.getCurrentTokenEndPosition(),
1877         //            INFO);
1878         //          getNextToken();
1879         //          if (token == TokenNamecase) { // empty case statement ?
1880         //            continue;
1881         //          }
1882         //          statementList();
1883         //        }
1884         else {
1885           throwSyntaxError("':' character after 'case' constant expected (Found token: "
1886               + scanner.toStringAction(token) + ")");
1887         }
1888       } else { // TokenNamedefault
1889         getNextToken();
1890         if (token == TokenNameCOLON) {
1891           getNextToken();
1892           statementList();
1893         } else {
1894           throwSyntaxError("':' character after 'default' expected.");
1895         }
1896       }
1897     } while (token == TokenNamecase || token == TokenNamedefault);
1898   }
1899   //  public void labeledStatement() {
1900   //    if (token == TokenNamecase) {
1901   //      getNextToken();
1902   //      constant();
1903   //      if (token == TokenNameDDOT) {
1904   //        getNextToken();
1905   //        statement();
1906   //      } else {
1907   //        throwSyntaxError("':' character after 'case' constant expected.");
1908   //      }
1909   //      return;
1910   //    } else if (token == TokenNamedefault) {
1911   //      getNextToken();
1912   //      if (token == TokenNameDDOT) {
1913   //        getNextToken();
1914   //        statement();
1915   //      } else {
1916   //        throwSyntaxError("':' character after 'default' expected.");
1917   //      }
1918   //      return;
1919   //    }
1920   //  }
1921   //  public void expressionStatement() {
1922   //  }
1923   //  private void inclusionStatement() {
1924   //  }
1925   //  public void compoundStatement() {
1926   //  }
1927   //  public void selectionStatement() {
1928   //  }
1929   //
1930   //  public void iterationStatement() {
1931   //  }
1932   //
1933   //  public void jumpStatement() {
1934   //  }
1935   //
1936   //  public void outputStatement() {
1937   //  }
1938   //
1939   //  public void scopeStatement() {
1940   //  }
1941   //
1942   //  public void flowStatement() {
1943   //  }
1944   //
1945   //  public void definitionStatement() {
1946   //  }
1947   private void ifStatement() {
1948     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1949     if (token == TokenNameCOLON) {
1950       getNextToken();
1951       if (token != TokenNameendif) {
1952         statementList();
1953         switch (token) {
1954           case TokenNameelse :
1955             getNextToken();
1956             if (token == TokenNameCOLON) {
1957               getNextToken();
1958               if (token != TokenNameendif) {
1959                 statementList();
1960               }
1961             } else {
1962               if (token == TokenNameif) { //'else if'
1963                 getNextToken();
1964                 elseifStatementList();
1965               } else {
1966                 throwSyntaxError("':' expected after 'else'.");
1967               }
1968             }
1969             break;
1970           case TokenNameelseif :
1971             getNextToken();
1972             elseifStatementList();
1973             break;
1974         }
1975       }
1976       if (token != TokenNameendif) {
1977         throwSyntaxError("'endif' expected.");
1978       }
1979       getNextToken();
1980       if (token != TokenNameSEMICOLON) {
1981         throwSyntaxError("';' expected after if-statement.");
1982       }
1983       getNextToken();
1984     } else {
1985       // statement [else-statement]
1986       statement(TokenNameEOF);
1987       if (token == TokenNameelseif) {
1988         getNextToken();
1989         if (token == TokenNameLPAREN) {
1990           getNextToken();
1991         } else {
1992           throwSyntaxError("'(' expected after 'elseif' keyword.");
1993         }
1994         expr();
1995         if (token == TokenNameRPAREN) {
1996           getNextToken();
1997         } else {
1998           throwSyntaxError("')' expected after 'elseif' condition.");
1999         }
2000         ifStatement();
2001       } else if (token == TokenNameelse) {
2002         getNextToken();
2003         statement(TokenNameEOF);
2004       }
2005     }
2006   }
2007   private void elseifStatementList() {
2008     do {
2009       elseifStatement();
2010       switch (token) {
2011         case TokenNameelse :
2012           getNextToken();
2013           if (token == TokenNameCOLON) {
2014             getNextToken();
2015             if (token != TokenNameendif) {
2016               statementList();
2017             }
2018             return;
2019           } else {
2020             if (token == TokenNameif) { //'else if'
2021               getNextToken();
2022             } else {
2023               throwSyntaxError("':' expected after 'else'.");
2024             }
2025           }
2026           break;
2027         case TokenNameelseif :
2028           getNextToken();
2029           break;
2030         default :
2031           return;
2032       }
2033     } while (true);
2034   }
2035   private void elseifStatement() {
2036     if (token == TokenNameLPAREN) {
2037       getNextToken();
2038       expr();
2039       if (token != TokenNameRPAREN) {
2040         throwSyntaxError("')' expected in else-if-statement.");
2041       }
2042       getNextToken();
2043       if (token != TokenNameCOLON) {
2044         throwSyntaxError("':' expected in else-if-statement.");
2045       }
2046       getNextToken();
2047       if (token != TokenNameendif) {
2048         statementList();
2049       }
2050     }
2051   }
2052   private void switchStatement() {
2053     if (token == TokenNameCOLON) {
2054       // ':' [labeled-statement-list] 'endswitch' ';'
2055       getNextToken();
2056       labeledStatementList();
2057       if (token != TokenNameendswitch) {
2058         throwSyntaxError("'endswitch' expected.");
2059       }
2060       getNextToken();
2061       if (token != TokenNameSEMICOLON) {
2062         throwSyntaxError("';' expected after switch-statement.");
2063       }
2064       getNextToken();
2065     } else {
2066       // '{' [labeled-statement-list] '}'
2067       if (token != TokenNameLBRACE) {
2068         throwSyntaxError("'{' expected in switch statement.");
2069       }
2070       getNextToken();
2071       if (token != TokenNameRBRACE) {
2072         labeledStatementList();
2073       }
2074       if (token != TokenNameRBRACE) {
2075         throwSyntaxError("'}' expected in switch statement.");
2076       }
2077       getNextToken();
2078     }
2079   }
2080   private void forStatement() {
2081     if (token == TokenNameCOLON) {
2082       getNextToken();
2083       statementList();
2084       if (token != TokenNameendfor) {
2085         throwSyntaxError("'endfor' expected.");
2086       }
2087       getNextToken();
2088       if (token != TokenNameSEMICOLON) {
2089         throwSyntaxError("';' expected after for-statement.");
2090       }
2091       getNextToken();
2092     } else {
2093       statement(TokenNameEOF);
2094     }
2095   }
2096   private void whileStatement() {
2097     // ':' statement-list 'endwhile' ';'
2098     if (token == TokenNameCOLON) {
2099       getNextToken();
2100       statementList();
2101       if (token != TokenNameendwhile) {
2102         throwSyntaxError("'endwhile' expected.");
2103       }
2104       getNextToken();
2105       if (token != TokenNameSEMICOLON) {
2106         throwSyntaxError("';' expected after while-statement.");
2107       }
2108       getNextToken();
2109     } else {
2110       statement(TokenNameEOF);
2111     }
2112   }
2113   private void foreachStatement() {
2114     if (token == TokenNameCOLON) {
2115       getNextToken();
2116       statementList();
2117       if (token != TokenNameendforeach) {
2118         throwSyntaxError("'endforeach' expected.");
2119       }
2120       getNextToken();
2121       if (token != TokenNameSEMICOLON) {
2122         throwSyntaxError("';' expected after foreach-statement.");
2123       }
2124       getNextToken();
2125     } else {
2126       statement(TokenNameEOF);
2127     }
2128   }
2129   //  private void exitStatus() {
2130   //    if (token == TokenNameLPAREN) {
2131   //      getNextToken();
2132   //    } else {
2133   //      throwSyntaxError("'(' expected in 'exit-status'.");
2134   //    }
2135   //    if (token != TokenNameRPAREN) {
2136   //      expression();
2137   //    }
2138   //    if (token == TokenNameRPAREN) {
2139   //      getNextToken();
2140   //    } else {
2141   //      throwSyntaxError("')' expected after 'exit-status'.");
2142   //    }
2143   //  }
2144   private void expressionList() {
2145     do {
2146       expr();
2147       if (token == TokenNameCOMMA) {
2148         getNextToken();
2149       } else {
2150         break;
2151       }
2152     } while (true);
2153   }
2154   private void expr() {
2155     //  r_variable
2156     //  | expr_without_variable
2157     //    if (token!=TokenNameEOF) {
2158     if (Scanner.TRACE) {
2159       System.out.println("TRACE: expr()");
2160     }
2161     expr_without_variable(true);
2162     //    }
2163   }
2164   private void expr_without_variable(boolean only_variable) {
2165     //          internal_functions_in_yacc
2166     //  | T_CLONE expr
2167     //  | T_PRINT expr
2168     //  | '(' expr ')'
2169     //  | '@' expr
2170     //  | '+' expr
2171     //  | '-' expr
2172     //  | '!' expr
2173     //  | '~' expr
2174     //  | T_INC rw_variable
2175     //  | T_DEC rw_variable
2176     //  | T_INT_CAST expr
2177     //  | T_DOUBLE_CAST expr
2178     //  | T_STRING_CAST expr
2179     //  | T_ARRAY_CAST expr
2180     //  | T_OBJECT_CAST expr
2181     //  | T_BOOL_CAST expr
2182     //  | T_UNSET_CAST expr
2183     //  | T_EXIT exit_expr
2184     //  | scalar
2185     //  | T_ARRAY '(' array_pair_list ')'
2186     //  | '`' encaps_list '`'
2187     //  | T_LIST '(' assignment_list ')' '=' expr
2188     //  | T_NEW class_name_reference ctor_arguments
2189     //  | variable '=' expr
2190     //  | variable '=' '&' variable
2191     //  | variable '=' '&' T_NEW class_name_reference ctor_arguments
2192     //  | variable T_PLUS_EQUAL expr
2193     //  | variable T_MINUS_EQUAL expr
2194     //  | variable T_MUL_EQUAL expr
2195     //  | variable T_DIV_EQUAL expr
2196     //  | variable T_CONCAT_EQUAL expr
2197     //  | variable T_MOD_EQUAL expr
2198     //  | variable T_AND_EQUAL expr
2199     //  | variable T_OR_EQUAL expr
2200     //  | variable T_XOR_EQUAL expr
2201     //  | variable T_SL_EQUAL expr
2202     //  | variable T_SR_EQUAL expr
2203     //  | rw_variable T_INC
2204     //  | rw_variable T_DEC
2205     //  | expr T_BOOLEAN_OR expr
2206     //  | expr T_BOOLEAN_AND expr
2207     //  | expr T_LOGICAL_OR expr
2208     //  | expr T_LOGICAL_AND expr
2209     //  | expr T_LOGICAL_XOR expr
2210     //  | expr '|' expr
2211     //  | expr '&' expr
2212     //  | expr '^' expr
2213     //  | expr '.' expr
2214     //  | expr '+' expr
2215     //  | expr '-' expr
2216     //  | expr '*' expr
2217     //  | expr '/' expr
2218     //  | expr '%' expr
2219     //  | expr T_SL expr
2220     //  | expr T_SR expr
2221     //  | expr T_IS_IDENTICAL expr
2222     //  | expr T_IS_NOT_IDENTICAL expr
2223     //  | expr T_IS_EQUAL expr
2224     //  | expr T_IS_NOT_EQUAL expr
2225     //  | expr '<' expr
2226     //  | expr T_IS_SMALLER_OR_EQUAL expr
2227     //  | expr '>' expr
2228     //  | expr T_IS_GREATER_OR_EQUAL expr
2229     //  | expr T_INSTANCEOF class_name_reference
2230     //  | expr '?' expr ':' expr
2231     if (Scanner.TRACE) {
2232       System.out.println("TRACE: expr_without_variable() PART 1");
2233     }
2234     switch (token) {
2235       case TokenNameisset :
2236       case TokenNameempty :
2237       case TokenNameeval :
2238       case TokenNameinclude :
2239       case TokenNameinclude_once :
2240       case TokenNamerequire :
2241       case TokenNamerequire_once :
2242         internal_functions_in_yacc();
2243         break;
2244       //        | '(' expr ')'
2245       case TokenNameLPAREN :
2246         getNextToken();
2247         expr();
2248         if (token == TokenNameRPAREN) {
2249           getNextToken();
2250         } else {
2251           throwSyntaxError("')' expected in expression.");
2252         }
2253         break;
2254       //    | T_CLONE expr
2255       //    | T_PRINT expr
2256       //    | '@' expr
2257       //    | '+' expr
2258       //    | '-' expr
2259       //    | '!' expr
2260       //    | '~' expr
2261       //    | T_INT_CAST expr
2262       //        | T_DOUBLE_CAST expr
2263       //        | T_STRING_CAST expr
2264       //        | T_ARRAY_CAST expr
2265       //        | T_OBJECT_CAST expr
2266       //        | T_BOOL_CAST expr
2267       //        | T_UNSET_CAST expr
2268       case TokenNameclone :
2269       case TokenNameprint :
2270       case TokenNameAT :
2271       case TokenNamePLUS :
2272       case TokenNameMINUS :
2273       case TokenNameNOT :
2274       case TokenNameTWIDDLE :
2275       case TokenNameintCAST :
2276       case TokenNamedoubleCAST :
2277       case TokenNamestringCAST :
2278       case TokenNamearrayCAST :
2279       case TokenNameobjectCAST :
2280       case TokenNameboolCAST :
2281       case TokenNameunsetCAST :
2282         getNextToken();
2283         expr();
2284         break;
2285       case TokenNameexit :
2286         getNextToken();
2287         exit_expr();
2288         break;
2289       //  scalar:
2290       //        T_STRING
2291       //| T_STRING_VARNAME
2292       //| class_constant
2293       //| '"' encaps_list '"'
2294       //| '\'' encaps_list '\''
2295       //| T_START_HEREDOC encaps_list T_END_HEREDOC
2296       //        | '`' encaps_list '`'
2297       //  | common_scalar
2298       case TokenNameIntegerLiteral :
2299       case TokenNameDoubleLiteral :
2300       case TokenNameStringLiteral :
2301       case TokenNameStringConstant :
2302       case TokenNameStringInterpolated :
2303       case TokenNameFILE :
2304       case TokenNameLINE :
2305       case TokenNameCLASS_C :
2306       case TokenNameMETHOD_C :
2307       case TokenNameFUNC_C :
2308         common_scalar();
2309         break;
2310       case TokenNameHEREDOC :
2311         getNextToken();
2312         break;
2313       case TokenNamearray :
2314         //    T_ARRAY '(' array_pair_list ')'
2315         getNextToken();
2316         if (token == TokenNameLPAREN) {
2317           getNextToken();
2318           if (token == TokenNameRPAREN) {
2319             getNextToken();
2320             break;
2321           }
2322           array_pair_list();
2323           if (token != TokenNameRPAREN) {
2324             throwSyntaxError("')' expected after keyword 'array'"
2325                 + "(Found token: " + scanner.toStringAction(token) + ")");
2326           }
2327           getNextToken();
2328         } else {
2329           throwSyntaxError("'(' expected after keyword 'array'"
2330               + "(Found token: " + scanner.toStringAction(token) + ")");
2331         }
2332         break;
2333       case TokenNamelist :
2334         //    | T_LIST '(' assignment_list ')' '=' expr
2335         getNextToken();
2336         if (token == TokenNameLPAREN) {
2337           getNextToken();
2338           assignment_list();
2339           if (token != TokenNameRPAREN) {
2340             throwSyntaxError("')' expected after 'list' keyword.");
2341           }
2342           getNextToken();
2343           if (token != TokenNameEQUAL) {
2344             throwSyntaxError("'=' expected after 'list' keyword.");
2345           }
2346           getNextToken();
2347           expr();
2348         } else {
2349           throwSyntaxError("'(' expected after 'list' keyword.");
2350         }
2351         break;
2352       case TokenNamenew :
2353         //      | T_NEW class_name_reference ctor_arguments
2354         getNextToken();
2355         class_name_reference();
2356         ctor_arguments();
2357         break;
2358       //        | T_INC rw_variable
2359       //        | T_DEC rw_variable
2360       case TokenNamePLUS_PLUS :
2361       case TokenNameMINUS_MINUS :
2362         getNextToken();
2363         rw_variable();
2364         break;
2365       //        | variable '=' expr
2366       //        | variable '=' '&' variable
2367       //        | variable '=' '&' T_NEW class_name_reference ctor_arguments
2368       //        | variable T_PLUS_EQUAL expr
2369       //        | variable T_MINUS_EQUAL expr
2370       //        | variable T_MUL_EQUAL expr
2371       //        | variable T_DIV_EQUAL expr
2372       //        | variable T_CONCAT_EQUAL expr
2373       //        | variable T_MOD_EQUAL expr
2374       //        | variable T_AND_EQUAL expr
2375       //        | variable T_OR_EQUAL expr
2376       //        | variable T_XOR_EQUAL expr
2377       //        | variable T_SL_EQUAL expr
2378       //        | variable T_SR_EQUAL expr
2379       //        | rw_variable T_INC
2380       //        | rw_variable T_DEC
2381       case TokenNameIdentifier :
2382       case TokenNameVariable :
2383       case TokenNameDOLLAR :
2384         variable();
2385         switch (token) {
2386           case TokenNameEQUAL :
2387             getNextToken();
2388             if (token == TokenNameAND) {
2389               getNextToken();
2390               if (token == TokenNamenew) {
2391                 getNextToken();
2392                 throwSyntaxError("not yet implemented (= & new)");
2393                 //                class_name_reference();
2394                 //                ctor_arguments();
2395               } else {
2396                 variable();
2397               }
2398             } else {
2399               expr();
2400             }
2401             break;
2402           case TokenNamePLUS_EQUAL :
2403           case TokenNameMINUS_EQUAL :
2404           case TokenNameMULTIPLY_EQUAL :
2405           case TokenNameDIVIDE_EQUAL :
2406           case TokenNameDOT_EQUAL :
2407           case TokenNameREMAINDER_EQUAL :
2408           case TokenNameAND_EQUAL :
2409           case TokenNameOR_EQUAL :
2410           case TokenNameXOR_EQUAL :
2411           case TokenNameRIGHT_SHIFT_EQUAL :
2412           case TokenNameLEFT_SHIFT_EQUAL :
2413             getNextToken();
2414             expr();
2415             break;
2416           case TokenNamePLUS_PLUS :
2417           case TokenNameMINUS_MINUS :
2418             getNextToken();
2419             break;
2420           default :
2421             if (!only_variable) {
2422               throwSyntaxError("Variable expression not allowed (found token '"
2423                   + scanner.toStringAction(token) + "').");
2424             }
2425         }
2426         break;
2427       default :
2428         if (token != TokenNameINLINE_HTML) {
2429           throwSyntaxError("Error in expression (found token '"
2430               + scanner.toStringAction(token) + "').");
2431         }
2432         return;
2433     }
2434     if (Scanner.TRACE) {
2435       System.out.println("TRACE: expr_without_variable() PART 2");
2436     }
2437     //  | expr T_BOOLEAN_OR expr
2438     //  | expr T_BOOLEAN_AND expr
2439     //  | expr T_LOGICAL_OR expr
2440     //  | expr T_LOGICAL_AND expr
2441     //  | expr T_LOGICAL_XOR expr
2442     //  | expr '|' expr
2443     //  | expr '&' expr
2444     //  | expr '^' expr
2445     //  | expr '.' expr
2446     //  | expr '+' expr
2447     //  | expr '-' expr
2448     //  | expr '*' expr
2449     //  | expr '/' expr
2450     //  | expr '%' expr
2451     //  | expr T_SL expr
2452     //  | expr T_SR expr
2453     //  | expr T_IS_IDENTICAL expr
2454     //  | expr T_IS_NOT_IDENTICAL expr
2455     //  | expr T_IS_EQUAL expr
2456     //  | expr T_IS_NOT_EQUAL expr
2457     //  | expr '<' expr
2458     //  | expr T_IS_SMALLER_OR_EQUAL expr
2459     //  | expr '>' expr
2460     //  | expr T_IS_GREATER_OR_EQUAL expr
2461     while (true) {
2462       switch (token) {
2463         case TokenNameOR_OR :
2464         case TokenNameAND_AND :
2465         case TokenNameand :
2466         case TokenNameor :
2467         case TokenNamexor :
2468         case TokenNameAND :
2469         case TokenNameOR :
2470         case TokenNameXOR :
2471         case TokenNameDOT :
2472         case TokenNamePLUS :
2473         case TokenNameMINUS :
2474         case TokenNameMULTIPLY :
2475         case TokenNameDIVIDE :
2476         case TokenNameREMAINDER :
2477         case TokenNameLEFT_SHIFT :
2478         case TokenNameRIGHT_SHIFT :
2479         case TokenNameEQUAL_EQUAL_EQUAL :
2480         case TokenNameNOT_EQUAL_EQUAL :
2481         case TokenNameEQUAL_EQUAL :
2482         case TokenNameNOT_EQUAL :
2483         case TokenNameLESS :
2484         case TokenNameLESS_EQUAL :
2485         case TokenNameGREATER :
2486         case TokenNameGREATER_EQUAL :
2487           getNextToken();
2488           expr();
2489           break;
2490         //  | expr T_INSTANCEOF class_name_reference
2491         //      | expr '?' expr ':' expr
2492         case TokenNameinstanceof :
2493           getNextToken();
2494           throwSyntaxError("not yet implemented (class_name_reference)");
2495           //            class_name_reference();
2496           break;
2497         case TokenNameQUESTION :
2498           getNextToken();
2499           expr();
2500           if (token == TokenNameCOLON) {
2501             getNextToken();
2502             expr();
2503           }
2504           break;
2505         default :
2506           return;
2507       }
2508     }
2509   }
2510   private void class_name_reference() {
2511     //  class_name_reference:
2512     //  T_STRING
2513     //| dynamic_class_name_reference
2514     if (Scanner.TRACE) {
2515       System.out.println("TRACE: class_name_reference()");
2516     }
2517     if (token == TokenNameIdentifier) {
2518       getNextToken();
2519     } else {
2520       dynamic_class_name_reference();
2521     }
2522   }
2523   private void dynamic_class_name_reference() {
2524     //dynamic_class_name_reference:
2525     //  base_variable T_OBJECT_OPERATOR object_property
2526     // dynamic_class_name_variable_properties
2527     //| base_variable
2528     if (Scanner.TRACE) {
2529       System.out.println("TRACE: dynamic_class_name_reference()");
2530     }
2531     base_variable();
2532     if (token == TokenNameMINUS_GREATER) {
2533       getNextToken();
2534       object_property();
2535       dynamic_class_name_variable_properties();
2536     }
2537   }
2538   private void dynamic_class_name_variable_properties() {
2539     //  dynamic_class_name_variable_properties:
2540     //                  dynamic_class_name_variable_properties
2541     // dynamic_class_name_variable_property
2542     //          | /* empty */
2543     if (Scanner.TRACE) {
2544       System.out.println("TRACE: dynamic_class_name_variable_properties()");
2545     }
2546     while (token == TokenNameMINUS_GREATER) {
2547       dynamic_class_name_variable_property();
2548     }
2549   }
2550   private void dynamic_class_name_variable_property() {
2551     //  dynamic_class_name_variable_property:
2552     //  T_OBJECT_OPERATOR object_property
2553     if (Scanner.TRACE) {
2554       System.out.println("TRACE: dynamic_class_name_variable_property()");
2555     }
2556     if (token == TokenNameMINUS_GREATER) {
2557       getNextToken();
2558       object_property();
2559     }
2560   }
2561   private void ctor_arguments() {
2562     //  ctor_arguments:
2563     //  /* empty */
2564     //| '(' function_call_parameter_list ')'
2565     if (token == TokenNameLPAREN) {
2566       getNextToken();
2567       if (token == TokenNameRPAREN) {
2568         getNextToken();
2569         return;
2570       }
2571       non_empty_function_call_parameter_list();
2572       if (token != TokenNameRPAREN) {
2573         throwSyntaxError("')' expected in ctor_arguments.");
2574       }
2575       getNextToken();
2576     }
2577   }
2578   private void assignment_list() {
2579     //  assignment_list:
2580     //  assignment_list ',' assignment_list_element
2581     //| assignment_list_element
2582     while (true) {
2583       assignment_list_element();
2584       if (token != TokenNameCOMMA) {
2585         break;
2586       }
2587       getNextToken();
2588     }
2589   }
2590   private void assignment_list_element() {
2591     //assignment_list_element:
2592     //  variable
2593     //| T_LIST '(' assignment_list ')'
2594     //| /* empty */
2595     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2596       variable();
2597     } else {
2598       if (token == TokenNamelist) {
2599         getNextToken();
2600         if (token == TokenNameLPAREN) {
2601           getNextToken();
2602           assignment_list();
2603           if (token != TokenNameRPAREN) {
2604             throwSyntaxError("')' expected after 'list' keyword.");
2605           }
2606           getNextToken();
2607         } else {
2608           throwSyntaxError("'(' expected after 'list' keyword.");
2609         }
2610       }
2611     }
2612   }
2613   private void array_pair_list() {
2614     //  array_pair_list:
2615     //  /* empty */
2616     //| non_empty_array_pair_list possible_comma
2617     non_empty_array_pair_list();
2618     if (token == TokenNameCOMMA) {
2619       getNextToken();
2620     }
2621   }
2622   private void non_empty_array_pair_list() {
2623     //non_empty_array_pair_list:
2624     //  non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2625     //| non_empty_array_pair_list ',' expr
2626     //| expr T_DOUBLE_ARROW expr
2627     //| expr
2628     //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2629     //| non_empty_array_pair_list ',' '&' w_variable
2630     //| expr T_DOUBLE_ARROW '&' w_variable
2631     //| '&' w_variable
2632     while (true) {
2633       expr();
2634       if (token == TokenNameAND) {
2635         getNextToken();
2636         variable();
2637         return;
2638       } else if (token == TokenNameEQUAL_GREATER) {
2639         getNextToken();
2640         if (token == TokenNameAND) {
2641           getNextToken();
2642           variable();
2643         } else {
2644           expr();
2645         }
2646       }
2647       if (token != TokenNameCOMMA) {
2648         return;
2649       }
2650       getNextToken();
2651       if (token == TokenNameRPAREN) {
2652         return;
2653       }
2654     }
2655   }
2656 //  private void variableList() {
2657 //    do {
2658 //      variable();
2659 //      if (token == TokenNameCOMMA) {
2660 //        getNextToken();
2661 //      } else {
2662 //        break;
2663 //      }
2664 //    } while (true);
2665 //  }
2666   private void variable_without_objects() {
2667     //  variable_without_objects:
2668     //                  reference_variable
2669     //          | simple_indirect_reference reference_variable
2670     if (Scanner.TRACE) {
2671       System.out.println("TRACE: variable_without_objects()");
2672     }
2673     while (token == TokenNameDOLLAR) {
2674       getNextToken();
2675     }
2676     reference_variable();
2677   }
2678   private void function_call() {
2679     //  function_call:
2680     //  T_STRING '(' function_call_parameter_list ')'
2681     //| class_constant '(' function_call_parameter_list ')'
2682     //| static_member '(' function_call_parameter_list ')'
2683     //| variable_without_objects '(' function_call_parameter_list ')'
2684     if (Scanner.TRACE) {
2685       System.out.println("TRACE: function_call()");
2686     }
2687     if (token == TokenNameIdentifier) {
2688       getNextToken();
2689       switch (token) {
2690         case TokenNamePAAMAYIM_NEKUDOTAYIM :
2691           // static member:
2692           getNextToken();
2693           if (token == TokenNameIdentifier) {
2694             // class _constant
2695             getNextToken();
2696           } else {
2697             //        static member:
2698             variable_without_objects();
2699           }
2700           break;
2701       }
2702     } else {
2703       variable_without_objects();
2704     }
2705     if (token != TokenNameLPAREN) {
2706       // TODO is this ok ?
2707       return;
2708       //      throwSyntaxError("'(' expected in function call.");
2709     }
2710     getNextToken();
2711     if (token == TokenNameRPAREN) {
2712       getNextToken();
2713       return;
2714     }
2715     non_empty_function_call_parameter_list();
2716     if (token != TokenNameRPAREN) {
2717       throwSyntaxError("')' expected in function call.");
2718     }
2719     getNextToken();
2720   }
2721   //  private void function_call_parameter_list() {
2722   //    function_call_parameter_list:
2723   //            non_empty_function_call_parameter_list { $$ = $1; }
2724   //    | /* empty */
2725   //  }
2726   private void non_empty_function_call_parameter_list() {
2727     //non_empty_function_call_parameter_list:
2728     //          expr_without_variable
2729     //  | variable
2730     //  | '&' w_variable
2731     //  | non_empty_function_call_parameter_list ',' expr_without_variable
2732     //  | non_empty_function_call_parameter_list ',' variable
2733     //  | non_empty_function_call_parameter_list ',' '&' w_variable
2734     if (Scanner.TRACE) {
2735       System.out.println("TRACE: non_empty_function_call_parameter_list()");
2736     }
2737     while (true) {
2738       if (token == TokenNameAND) {
2739         getNextToken();
2740         w_variable();
2741       } else {
2742 //        if (token == TokenNameIdentifier || token == TokenNameVariable
2743 //            || token == TokenNameDOLLAR) {
2744 //          variable();
2745 //        } else {
2746           expr_without_variable(true);
2747 //        }
2748       }
2749       if (token != TokenNameCOMMA) {
2750         break;
2751       }
2752       getNextToken();
2753     }
2754   }
2755   private void fully_qualified_class_name() {
2756     if (token == TokenNameIdentifier) {
2757       getNextToken();
2758     } else {
2759       throwSyntaxError("Class name expected.");
2760     }
2761   }
2762   private void static_member() {
2763     //  static_member:
2764     //  fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2765     // variable_without_objects
2766     if (Scanner.TRACE) {
2767       System.out.println("TRACE: static_member()");
2768     }
2769     fully_qualified_class_name();
2770     if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2771       throwSyntaxError("'::' expected after class name (static_member).");
2772     }
2773     getNextToken();
2774     variable_without_objects();
2775   }
2776   private void base_variable_with_function_calls() {
2777     //  base_variable_with_function_calls:
2778     //  base_variable
2779     //| function_call
2780     boolean functionCall = false;
2781     if (Scanner.TRACE) {
2782       System.out.println("TRACE: base_variable_with_function_calls()");
2783     }
2784     if (token == TokenNameIdentifier) {
2785       functionCall = true;
2786     } else if (token == TokenNameVariable) {
2787       int tempToken = token;
2788       int tempPosition = scanner.currentPosition;
2789       getNextToken();
2790       if (token == TokenNameLPAREN) {
2791         functionCall = true;
2792       }
2793       token = tempToken;
2794       scanner.currentPosition = tempPosition;
2795       scanner.phpMode = true;
2796     }
2797     if (functionCall) {
2798       function_call();
2799     } else {
2800       base_variable();
2801     }
2802   }
2803   private void base_variable() {
2804     //  base_variable:
2805     //                  reference_variable
2806     //          | simple_indirect_reference reference_variable
2807     //          | static_member
2808     if (Scanner.TRACE) {
2809       System.out.println("TRACE: base_variable()");
2810     }
2811     if (token == TokenNameIdentifier) {
2812       static_member();
2813     } else {
2814       while (token == TokenNameDOLLAR) {
2815         getNextToken();
2816       }
2817       reference_variable();
2818     }
2819   }
2820   //  private void simple_indirect_reference() {
2821   //    // simple_indirect_reference:
2822   //    // '$'
2823   //    //| simple_indirect_reference '$'
2824   //  }
2825   private void reference_variable() {
2826     //  reference_variable:
2827     //                  reference_variable '[' dim_offset ']'
2828     //          | reference_variable '{' expr '}'
2829     //          | compound_variable
2830     if (Scanner.TRACE) {
2831       System.out.println("TRACE: reference_variable()");
2832     }
2833     compound_variable();
2834     while (true) {
2835       if (token == TokenNameLBRACE) {
2836         getNextToken();
2837         expr();
2838         if (token != TokenNameRBRACE) {
2839           throwSyntaxError("'}' expected in reference variable.");
2840         }
2841         getNextToken();
2842       } else if (token == TokenNameLBRACKET) {
2843         getNextToken();
2844         if (token != TokenNameRBRACKET) {
2845           expr();
2846           //        dim_offset();
2847           if (token != TokenNameRBRACKET) {
2848             throwSyntaxError("']' expected in reference variable.");
2849           }
2850         }
2851         getNextToken();
2852       } else {
2853         break;
2854       }
2855     }
2856   }
2857   private void compound_variable() {
2858     //  compound_variable:
2859     //                  T_VARIABLE
2860     //          | '$' '{' expr '}'
2861     if (Scanner.TRACE) {
2862       System.out.println("TRACE: compound_variable()");
2863     }
2864     if (token == TokenNameVariable) {
2865       getNextToken();
2866     } else {
2867       // because of simple_indirect_reference
2868       while (token == TokenNameDOLLAR) {
2869         getNextToken();
2870       }
2871       if (token != TokenNameLBRACE) {
2872         throwSyntaxError("'{' expected after compound variable token '$'.");
2873       }
2874       getNextToken();
2875       expr();
2876       if (token != TokenNameRBRACE) {
2877         throwSyntaxError("'}' expected after compound variable token '$'.");
2878       }
2879       getNextToken();
2880     }
2881   }
2882   //  private void dim_offset() {
2883   //    // dim_offset:
2884   //    // /* empty */
2885   //    // | expr
2886   //    expr();
2887   //  }
2888   private void object_property() {
2889     //  object_property:
2890     //  object_dim_list
2891     //| variable_without_objects
2892     if (Scanner.TRACE) {
2893       System.out.println("TRACE: object_property()");
2894     }
2895     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2896       variable_without_objects();
2897     } else {
2898       object_dim_list();
2899     }
2900   }
2901   private void object_dim_list() {
2902     //object_dim_list:
2903     //  object_dim_list '[' dim_offset ']'
2904     //| object_dim_list '{' expr '}'
2905     //| variable_name
2906     if (Scanner.TRACE) {
2907       System.out.println("TRACE: object_dim_list()");
2908     }
2909     variable_name();
2910     while (true) {
2911       if (token == TokenNameLBRACE) {
2912         getNextToken();
2913         expr();
2914         if (token != TokenNameRBRACE) {
2915           throwSyntaxError("'}' expected in object_dim_list.");
2916         }
2917         getNextToken();
2918       } else if (token == TokenNameLBRACKET) {
2919         getNextToken();
2920         if (token == TokenNameRBRACKET) {
2921           getNextToken();
2922           continue;
2923         }
2924         expr();
2925         if (token != TokenNameRBRACKET) {
2926           throwSyntaxError("']' expected in object_dim_list.");
2927         }
2928         getNextToken();
2929       } else {
2930         break;
2931       }
2932     }
2933   }
2934   private void variable_name() {
2935     //variable_name:
2936     //  T_STRING
2937     //| '{' expr '}'
2938     if (Scanner.TRACE) {
2939       System.out.println("TRACE: variable_name()");
2940     }
2941     if (token == TokenNameIdentifier) {
2942       getNextToken();
2943     } else {
2944       if (token != TokenNameLBRACE) {
2945         throwSyntaxError("'{' expected in variable name.");
2946       }
2947       getNextToken();
2948       expr();
2949       if (token != TokenNameRBRACE) {
2950         throwSyntaxError("'}' expected in variable name.");
2951       }
2952     }
2953   }
2954   private void r_variable() {
2955     variable();
2956   }
2957   private void w_variable() {
2958     variable();
2959   }
2960   private void rw_variable() {
2961     variable();
2962   }
2963   private void variable() {
2964     //    variable:
2965     //          base_variable_with_function_calls T_OBJECT_OPERATOR
2966     //                  object_property method_or_not variable_properties
2967     //  | base_variable_with_function_calls
2968     base_variable_with_function_calls();
2969     if (token == TokenNameMINUS_GREATER) {
2970       getNextToken();
2971       object_property();
2972       method_or_not();
2973       variable_properties();
2974     }
2975     //    if (token == TokenNameDOLLAR_LBRACE) {
2976     //      getNextToken();
2977     //      expr();
2978     //      ;
2979     //      if (token != TokenNameRBRACE) {
2980     //        throwSyntaxError("'}' expected after indirect variable token '${'.");
2981     //      }
2982     //      getNextToken();
2983     //    } else {
2984     //      if (token == TokenNameVariable) {
2985     //        getNextToken();
2986     //        if (token == TokenNameLBRACKET) {
2987     //          getNextToken();
2988     //          expr();
2989     //          if (token != TokenNameRBRACKET) {
2990     //            throwSyntaxError("']' expected in variable-list.");
2991     //          }
2992     //          getNextToken();
2993     //        } else if (token == TokenNameEQUAL) {
2994     //          getNextToken();
2995     //          static_scalar();
2996     //        }
2997     //      } else {
2998     //        throwSyntaxError("$-variable expected in variable-list.");
2999     //      }
3000     //    }
3001   }
3002   private void variable_properties() {
3003     //  variable_properties:
3004     //                  variable_properties variable_property
3005     //          | /* empty */
3006     while (token == TokenNameMINUS_GREATER) {
3007       variable_property();
3008     }
3009   }
3010   private void variable_property() {
3011     //  variable_property:
3012     //                  T_OBJECT_OPERATOR object_property method_or_not
3013     if (Scanner.TRACE) {
3014       System.out.println("TRACE: variable_property()");
3015     }
3016     if (token == TokenNameMINUS_GREATER) {
3017       getNextToken();
3018       object_property();
3019       method_or_not();
3020     } else {
3021       throwSyntaxError("'->' expected in variable_property.");
3022     }
3023   }
3024   private void method_or_not() {
3025     //  method_or_not:
3026     //                  '(' function_call_parameter_list ')'
3027     //          | /* empty */
3028     if (Scanner.TRACE) {
3029       System.out.println("TRACE: method_or_not()");
3030     }
3031     if (token == TokenNameLPAREN) {
3032       getNextToken();
3033       if (token == TokenNameRPAREN) {
3034         getNextToken();
3035         return;
3036       }
3037       non_empty_function_call_parameter_list();
3038       if (token != TokenNameRPAREN) {
3039         throwSyntaxError("')' expected in method_or_not.");
3040       }
3041       getNextToken();
3042     }
3043   }
3044   private void exit_expr() {
3045     //  /* empty */
3046     //  | '(' ')'
3047     //  | '(' expr ')'
3048     if (token != TokenNameLPAREN) {
3049       return;
3050     }
3051     getNextToken();
3052     if (token == TokenNameRPAREN) {
3053       getNextToken();
3054       return;
3055     }
3056     expr();
3057     if (token != TokenNameRPAREN) {
3058       throwSyntaxError("')' expected after keyword 'exit'");
3059     }
3060     getNextToken();
3061   }
3062   private void internal_functions_in_yacc() {
3063     switch (token) {
3064       case TokenNameisset :
3065         //      T_ISSET '(' isset_variables ')'
3066         getNextToken();
3067         if (token != TokenNameLPAREN) {
3068           throwSyntaxError("'(' expected after keyword 'isset'");
3069         }
3070         getNextToken();
3071         isset_variables();
3072         if (token != TokenNameRPAREN) {
3073           throwSyntaxError("')' expected after keyword 'isset'");
3074         }
3075         getNextToken();
3076         break;
3077       case TokenNameempty :
3078         //      T_EMPTY '(' variable ')'
3079         getNextToken();
3080         if (token != TokenNameLPAREN) {
3081           throwSyntaxError("'(' expected after keyword 'empty'");
3082         }
3083         getNextToken();
3084         variable();
3085         if (token != TokenNameRPAREN) {
3086           throwSyntaxError("')' expected after keyword 'empty'");
3087         }
3088         getNextToken();
3089         break;
3090       case TokenNameinclude :
3091         //T_INCLUDE expr
3092         getNextToken();
3093         expr();
3094         break;
3095       case TokenNameinclude_once :
3096         //      T_INCLUDE_ONCE expr
3097         getNextToken();
3098         expr();
3099         break;
3100       case TokenNameeval :
3101         //      T_EVAL '(' expr ')'
3102         getNextToken();
3103         if (token != TokenNameLPAREN) {
3104           throwSyntaxError("'(' expected after keyword 'eval'");
3105         }
3106         getNextToken();
3107         expr();
3108         if (token != TokenNameRPAREN) {
3109           throwSyntaxError("')' expected after keyword 'eval'");
3110         }
3111         getNextToken();
3112         break;
3113       case TokenNamerequire :
3114         //T_REQUIRE expr
3115         getNextToken();
3116         expr();
3117         break;
3118       case TokenNamerequire_once :
3119         //      T_REQUIRE_ONCE expr
3120         getNextToken();
3121         expr();
3122         break;
3123     }
3124   }
3125   private void isset_variables() {
3126     //  variable
3127     //  | isset_variables ','
3128     if (token == TokenNameRPAREN) {
3129       throwSyntaxError("Variable expected after keyword 'isset'");
3130     }
3131     while (true) {
3132       variable();
3133       if (token == TokenNameCOMMA) {
3134         getNextToken();
3135       } else {
3136         break;
3137       }
3138     }
3139   }
3140   private boolean common_scalar() {
3141     //  common_scalar:
3142     //  T_LNUMBER
3143     //  | T_DNUMBER
3144     //  | T_CONSTANT_ENCAPSED_STRING
3145     //  | T_LINE
3146     //  | T_FILE
3147     //  | T_CLASS_C
3148     //  | T_METHOD_C
3149     //  | T_FUNC_C
3150     switch (token) {
3151       case TokenNameIntegerLiteral :
3152         getNextToken();
3153         return true;
3154       case TokenNameDoubleLiteral :
3155         getNextToken();
3156         return true;
3157       case TokenNameStringLiteral :
3158         getNextToken();
3159         return true;
3160       case TokenNameStringConstant :
3161         getNextToken();
3162         return true;
3163       case TokenNameStringInterpolated :
3164         getNextToken();
3165         return true;
3166       case TokenNameFILE :
3167         getNextToken();
3168         return true;
3169       case TokenNameLINE :
3170         getNextToken();
3171         return true;
3172       case TokenNameCLASS_C :
3173         getNextToken();
3174         return true;
3175       case TokenNameMETHOD_C :
3176         getNextToken();
3177         return true;
3178       case TokenNameFUNC_C :
3179         getNextToken();
3180         return true;
3181     }
3182     return false;
3183   }
3184   private void scalar() {
3185     //  scalar:
3186     //  T_STRING
3187     //| T_STRING_VARNAME
3188     //| class_constant
3189     //| common_scalar
3190     //| '"' encaps_list '"'
3191     //| '\'' encaps_list '\''
3192     //| T_START_HEREDOC encaps_list T_END_HEREDOC
3193     throwSyntaxError("Not yet implemented (scalar).");
3194   }
3195   private void static_scalar() {
3196     //    static_scalar: /* compile-time evaluated scalars */
3197     //          common_scalar
3198     //  | T_STRING
3199     //  | '+' static_scalar
3200     //  | '-' static_scalar
3201     //  | T_ARRAY '(' static_array_pair_list ')'
3202     //  | static_class_constant
3203     if (common_scalar()) {
3204       return;
3205     }
3206     switch (token) {
3207       case TokenNameIdentifier :
3208         getNextToken();
3209         //        static_class_constant:
3210         //              T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3211         if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3212           getNextToken();
3213           if (token == TokenNameIdentifier) {
3214             getNextToken();
3215           } else {
3216             throwSyntaxError("Identifier expected after '::' operator.");
3217           }
3218         }
3219         break;
3220       case TokenNamePLUS :
3221         getNextToken();
3222         static_scalar();
3223         break;
3224       case TokenNameMINUS :
3225         getNextToken();
3226         static_scalar();
3227         break;
3228       case TokenNamearray :
3229         getNextToken();
3230         if (token != TokenNameLPAREN) {
3231           throwSyntaxError("'(' expected after keyword 'array'");
3232         }
3233         getNextToken();
3234         if (token == TokenNameRPAREN) {
3235           getNextToken();
3236           break;
3237         }
3238         non_empty_static_array_pair_list();
3239         if (token != TokenNameRPAREN) {
3240           throwSyntaxError("')' expected after keyword 'array'");
3241         }
3242         getNextToken();
3243         break;
3244       //      case TokenNamenull :
3245       //        getNextToken();
3246       //        break;
3247       //      case TokenNamefalse :
3248       //        getNextToken();
3249       //        break;
3250       //      case TokenNametrue :
3251       //        getNextToken();
3252       //        break;
3253       default :
3254         throwSyntaxError("Static scalar/constant expected.");
3255     }
3256   }
3257   private void non_empty_static_array_pair_list() {
3258     //  non_empty_static_array_pair_list:
3259     //  non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3260     // static_scalar
3261     //| non_empty_static_array_pair_list ',' static_scalar
3262     //| static_scalar T_DOUBLE_ARROW static_scalar
3263     //| static_scalar
3264     while (true) {
3265       static_scalar();
3266       if (token == TokenNameEQUAL_GREATER) {
3267         getNextToken();
3268         static_scalar();
3269       }
3270       if (token != TokenNameCOMMA) {
3271         break;
3272       }
3273       getNextToken();
3274       if (token == TokenNameRPAREN) {
3275         break;
3276       }
3277     }
3278   }
3279   public void reportSyntaxError() { //int act, int currentKind, int
3280     // stateStackTop) {
3281     /* remember current scanner position */
3282     int startPos = scanner.startPosition;
3283     int currentPos = scanner.currentPosition;
3284     //          String[] expectings;
3285     //          String tokenName = name[symbol_index[currentKind]];
3286     //fetch all "accurate" possible terminals that could recover the error
3287     //          int start, end = start = asi(stack[stateStackTop]);
3288     //          while (asr[end] != 0)
3289     //                  end++;
3290     //          int length = end - start;
3291     //          expectings = new String[length];
3292     //          if (length != 0) {
3293     //                  char[] indexes = new char[length];
3294     //                  System.arraycopy(asr, start, indexes, 0, length);
3295     //                  for (int i = 0; i < length; i++) {
3296     //                          expectings[i] = name[symbol_index[indexes[i]]];
3297     //                  }
3298     //          }
3299     //if the pb is an EOF, try to tell the user that they are some
3300     //          if (tokenName.equals(UNEXPECTED_EOF)) {
3301     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3302     //                          char[] tokenSource;
3303     //                          try {
3304     //                                  tokenSource = this.scanner.getCurrentTokenSource();
3305     //                          } catch (Exception e) {
3306     //                                  tokenSource = new char[] {};
3307     //                          }
3308     //                          problemReporter().parseError(
3309     //                                  this.scanner.startPosition,
3310     //                                  this.scanner.currentPosition - 1,
3311     //                                  tokenSource,
3312     //                                  tokenName,
3313     //                                  expectings);
3314     //                  }
3315     //          } else { //the next test is HEAVILY grammar DEPENDENT.
3316     //                  if ((length == 14)
3317     //                          && (expectings[0] == "=") //$NON-NLS-1$
3318     //                          && (expectings[1] == "*=") //$NON-NLS-1$
3319     //                          && (expressionPtr > -1)) {
3320     //                                  switch(currentKind) {
3321     //                                          case TokenNameSEMICOLON:
3322     //                                          case TokenNamePLUS:
3323     //                                          case TokenNameMINUS:
3324     //                                          case TokenNameDIVIDE:
3325     //                                          case TokenNameREMAINDER:
3326     //                                          case TokenNameMULTIPLY:
3327     //                                          case TokenNameLEFT_SHIFT:
3328     //                                          case TokenNameRIGHT_SHIFT:
3329     //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3330     //                                          case TokenNameLESS:
3331     //                                          case TokenNameGREATER:
3332     //                                          case TokenNameLESS_EQUAL:
3333     //                                          case TokenNameGREATER_EQUAL:
3334     //                                          case TokenNameEQUAL_EQUAL:
3335     //                                          case TokenNameNOT_EQUAL:
3336     //                                          case TokenNameXOR:
3337     //                                          case TokenNameAND:
3338     //                                          case TokenNameOR:
3339     //                                          case TokenNameOR_OR:
3340     //                                          case TokenNameAND_AND:
3341     //                                                  // the ; is not the expected token ==> it ends a statement when an
3342     // expression is not ended
3343     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3344     //                                                  break;
3345     //                                          case TokenNameRBRACE :
3346     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3347     //                                                  break;
3348     //                                          default:
3349     //                                                  char[] tokenSource;
3350     //                                                  try {
3351     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
3352     //                                                  } catch (Exception e) {
3353     //                                                          tokenSource = new char[] {};
3354     //                                                  }
3355     //                                                  problemReporter().parseError(
3356     //                                                          this.scanner.startPosition,
3357     //                                                          this.scanner.currentPosition - 1,
3358     //                                                          tokenSource,
3359     //                                                          tokenName,
3360     //                                                          expectings);
3361     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
3362     //                                  }
3363     //                  } else {
3364     char[] tokenSource;
3365     try {
3366       tokenSource = this.scanner.getCurrentTokenSource();
3367     } catch (Exception e) {
3368       tokenSource = new char[]{};
3369     }
3370     //                          problemReporter().parseError(
3371     //                                  this.scanner.startPosition,
3372     //                                  this.scanner.currentPosition - 1,
3373     //                                  tokenSource,
3374     //                                  tokenName,
3375     //                                  expectings);
3376     this.checkAndReportBracketAnomalies(problemReporter());
3377     //                  }
3378     //          }
3379     /* reset scanner where it was */
3380     scanner.startPosition = startPos;
3381     scanner.currentPosition = currentPos;
3382   }
3383   public static final int RoundBracket = 0;
3384   public static final int SquareBracket = 1;
3385   public static final int CurlyBracket = 2;
3386   public static final int BracketKinds = 3;
3387   protected int[] nestedMethod; //the ptr is nestedType
3388   protected int nestedType, dimensions;
3389   //ast stack
3390   final static int AstStackIncrement = 100;
3391   protected int astPtr;
3392   protected AstNode[] astStack = new AstNode[AstStackIncrement];
3393   protected int astLengthPtr;
3394   protected int[] astLengthStack;
3395   AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3396   public CompilationUnitDeclaration compilationUnit; /*
3397                                                       * the result from parse()
3398                                                       */
3399   protected ReferenceContext referenceContext;
3400   protected ProblemReporter problemReporter;
3401   //  protected CompilationResult compilationResult;
3402   /**
3403    * Returns this parser's problem reporter initialized with its reference
3404    * context. Also it is assumed that a problem is going to be reported, so
3405    * initializes the compilation result's line positions.
3406    */
3407   public ProblemReporter problemReporter() {
3408     if (scanner.recordLineSeparator) {
3409       compilationUnit.compilationResult.lineSeparatorPositions = scanner
3410           .getLineEnds();
3411     }
3412     problemReporter.referenceContext = referenceContext;
3413     return problemReporter;
3414   }
3415   /*
3416    * Reconsider the entire source looking for inconsistencies in {} () []
3417    */
3418   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3419     scanner.wasAcr = false;
3420     boolean anomaliesDetected = false;
3421     try {
3422       char[] source = scanner.source;
3423       int[] leftCount = {0, 0, 0};
3424       int[] rightCount = {0, 0, 0};
3425       int[] depths = {0, 0, 0};
3426       int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3427       int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3428       int[][] rightPositions = new int[][]{new int[10], new int[10],
3429           new int[10]};
3430       int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3431       scanner.currentPosition = scanner.initialPosition; //starting
3432       // point
3433       // (first-zero-based
3434       // char)
3435       while (scanner.currentPosition < scanner.eofPosition) { //loop for
3436         // jumping
3437         // over
3438         // comments
3439         try {
3440           // ---------Consume white space and handles
3441           // startPosition---------
3442           boolean isWhiteSpace;
3443           do {
3444             scanner.startPosition = scanner.currentPosition;
3445             //                                          if (((scanner.currentCharacter =
3446             // source[scanner.currentPosition++]) == '\\') &&
3447             // (source[scanner.currentPosition] == 'u')) {
3448             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3449             //                                          } else {
3450             if (scanner.recordLineSeparator
3451                 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3452               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3453                 // only record line positions we have not
3454                 // recorded yet
3455                 scanner.pushLineSeparator();
3456               }
3457             }
3458             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3459             //                                          }
3460           } while (isWhiteSpace
3461               && (scanner.currentPosition < scanner.eofPosition));
3462           // -------consume token until } is found---------
3463           switch (scanner.currentCharacter) {
3464             case '{' :
3465               {
3466                 int index = leftCount[CurlyBracket]++;
3467                 if (index == leftPositions[CurlyBracket].length) {
3468                   System.arraycopy(leftPositions[CurlyBracket], 0,
3469                       (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3470                       index);
3471                   System
3472                       .arraycopy(leftDepths[CurlyBracket], 0,
3473                           (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3474                           index);
3475                 }
3476                 leftPositions[CurlyBracket][index] = scanner.startPosition;
3477                 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3478               }
3479               break;
3480             case '}' :
3481               {
3482                 int index = rightCount[CurlyBracket]++;
3483                 if (index == rightPositions[CurlyBracket].length) {
3484                   System.arraycopy(rightPositions[CurlyBracket], 0,
3485                       (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3486                       index);
3487                   System.arraycopy(rightDepths[CurlyBracket], 0,
3488                       (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3489                       index);
3490                 }
3491                 rightPositions[CurlyBracket][index] = scanner.startPosition;
3492                 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3493               }
3494               break;
3495             case '(' :
3496               {
3497                 int index = leftCount[RoundBracket]++;
3498                 if (index == leftPositions[RoundBracket].length) {
3499                   System.arraycopy(leftPositions[RoundBracket], 0,
3500                       (leftPositions[RoundBracket] = new int[index * 2]), 0,
3501                       index);
3502                   System
3503                       .arraycopy(leftDepths[RoundBracket], 0,
3504                           (leftDepths[RoundBracket] = new int[index * 2]), 0,
3505                           index);
3506                 }
3507                 leftPositions[RoundBracket][index] = scanner.startPosition;
3508                 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3509               }
3510               break;
3511             case ')' :
3512               {
3513                 int index = rightCount[RoundBracket]++;
3514                 if (index == rightPositions[RoundBracket].length) {
3515                   System.arraycopy(rightPositions[RoundBracket], 0,
3516                       (rightPositions[RoundBracket] = new int[index * 2]), 0,
3517                       index);
3518                   System.arraycopy(rightDepths[RoundBracket], 0,
3519                       (rightDepths[RoundBracket] = new int[index * 2]), 0,
3520                       index);
3521                 }
3522                 rightPositions[RoundBracket][index] = scanner.startPosition;
3523                 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3524               }
3525               break;
3526             case '[' :
3527               {
3528                 int index = leftCount[SquareBracket]++;
3529                 if (index == leftPositions[SquareBracket].length) {
3530                   System.arraycopy(leftPositions[SquareBracket], 0,
3531                       (leftPositions[SquareBracket] = new int[index * 2]), 0,
3532                       index);
3533                   System.arraycopy(leftDepths[SquareBracket], 0,
3534                       (leftDepths[SquareBracket] = new int[index * 2]), 0,
3535                       index);
3536                 }
3537                 leftPositions[SquareBracket][index] = scanner.startPosition;
3538                 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3539               }
3540               break;
3541             case ']' :
3542               {
3543                 int index = rightCount[SquareBracket]++;
3544                 if (index == rightPositions[SquareBracket].length) {
3545                   System.arraycopy(rightPositions[SquareBracket], 0,
3546                       (rightPositions[SquareBracket] = new int[index * 2]), 0,
3547                       index);
3548                   System.arraycopy(rightDepths[SquareBracket], 0,
3549                       (rightDepths[SquareBracket] = new int[index * 2]), 0,
3550                       index);
3551                 }
3552                 rightPositions[SquareBracket][index] = scanner.startPosition;
3553                 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3554               }
3555               break;
3556             case '\'' :
3557               {
3558                 if (scanner.getNextChar('\\')) {
3559                   scanner.scanEscapeCharacter();
3560                 } else { // consume next character
3561                   scanner.unicodeAsBackSlash = false;
3562                   //                                                                    if (((scanner.currentCharacter =
3563                   // source[scanner.currentPosition++]) ==
3564                   // '\\') &&
3565                   // (source[scanner.currentPosition] ==
3566                   // 'u')) {
3567                   //                                                                            scanner.getNextUnicodeChar();
3568                   //                                                                    } else {
3569                   if (scanner.withoutUnicodePtr != 0) {
3570                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3571                   }
3572                   //                                                                    }
3573                 }
3574                 scanner.getNextChar('\'');
3575                 break;
3576               }
3577             case '"' :
3578               // consume next character
3579               scanner.unicodeAsBackSlash = false;
3580               //                                                        if (((scanner.currentCharacter =
3581               // source[scanner.currentPosition++]) == '\\') &&
3582               // (source[scanner.currentPosition] == 'u')) {
3583               //                                                                scanner.getNextUnicodeChar();
3584               //                                                        } else {
3585               if (scanner.withoutUnicodePtr != 0) {
3586                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3587               }
3588               //                                                        }
3589               while (scanner.currentCharacter != '"') {
3590                 if (scanner.currentCharacter == '\r') {
3591                   if (source[scanner.currentPosition] == '\n')
3592                     scanner.currentPosition++;
3593                   break; // the string cannot go further that
3594                   // the line
3595                 }
3596                 if (scanner.currentCharacter == '\n') {
3597                   break; // the string cannot go further that
3598                   // the line
3599                 }
3600                 if (scanner.currentCharacter == '\\') {
3601                   scanner.scanEscapeCharacter();
3602                 }
3603                 // consume next character
3604                 scanner.unicodeAsBackSlash = false;
3605                 //                                                              if (((scanner.currentCharacter =
3606                 // source[scanner.currentPosition++]) == '\\')
3607                 // && (source[scanner.currentPosition] == 'u'))
3608                 // {
3609                 //                                                                      scanner.getNextUnicodeChar();
3610                 //                                                              } else {
3611                 if (scanner.withoutUnicodePtr != 0) {
3612                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3613                 }
3614                 //                                                              }
3615               }
3616               break;
3617             case '/' :
3618               {
3619                 int test;
3620                 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3621                   // comment
3622                   //get the next char
3623                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3624                       && (source[scanner.currentPosition] == 'u')) {
3625                     //-------------unicode traitement
3626                     // ------------
3627                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3628                     scanner.currentPosition++;
3629                     while (source[scanner.currentPosition] == 'u') {
3630                       scanner.currentPosition++;
3631                     }
3632                     if ((c1 = Character
3633                         .getNumericValue(source[scanner.currentPosition++])) > 15
3634                         || c1 < 0
3635                         || (c2 = Character
3636                             .getNumericValue(source[scanner.currentPosition++])) > 15
3637                         || c2 < 0
3638                         || (c3 = Character
3639                             .getNumericValue(source[scanner.currentPosition++])) > 15
3640                         || c3 < 0
3641                         || (c4 = Character
3642                             .getNumericValue(source[scanner.currentPosition++])) > 15
3643                         || c4 < 0) { //error don't
3644                       // care of the
3645                       // value
3646                       scanner.currentCharacter = 'A';
3647                     } //something different from \n and \r
3648                     else {
3649                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3650                     }
3651                   }
3652                   while (scanner.currentCharacter != '\r'
3653                       && scanner.currentCharacter != '\n') {
3654                     //get the next char
3655                     scanner.startPosition = scanner.currentPosition;
3656                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3657                         && (source[scanner.currentPosition] == 'u')) {
3658                       //-------------unicode traitement
3659                       // ------------
3660                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3661                       scanner.currentPosition++;
3662                       while (source[scanner.currentPosition] == 'u') {
3663                         scanner.currentPosition++;
3664                       }
3665                       if ((c1 = Character
3666                           .getNumericValue(source[scanner.currentPosition++])) > 15
3667                           || c1 < 0
3668                           || (c2 = Character
3669                               .getNumericValue(source[scanner.currentPosition++])) > 15
3670                           || c2 < 0
3671                           || (c3 = Character
3672                               .getNumericValue(source[scanner.currentPosition++])) > 15
3673                           || c3 < 0
3674                           || (c4 = Character
3675                               .getNumericValue(source[scanner.currentPosition++])) > 15
3676                           || c4 < 0) { //error don't
3677                         // care of the
3678                         // value
3679                         scanner.currentCharacter = 'A';
3680                       } //something different from \n
3681                       // and \r
3682                       else {
3683                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3684                       }
3685                     }
3686                   }
3687                   if (scanner.recordLineSeparator
3688                       && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3689                     if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3690                       // only record line positions we
3691                       // have not recorded yet
3692                       scanner.pushLineSeparator();
3693                       if (this.scanner.taskTags != null) {
3694                         this.scanner.checkTaskTag(this.scanner
3695                             .getCurrentTokenStartPosition(), this.scanner
3696                             .getCurrentTokenEndPosition());
3697                       }
3698                     }
3699                   }
3700                   break;
3701                 }
3702                 if (test > 0) { //traditional and annotation
3703                   // comment
3704                   boolean star = false;
3705                   // consume next character
3706                   scanner.unicodeAsBackSlash = false;
3707                   //                                                                    if (((scanner.currentCharacter =
3708                   // source[scanner.currentPosition++]) ==
3709                   // '\\') &&
3710                   // (source[scanner.currentPosition] ==
3711                   // 'u')) {
3712                   //                                                                            scanner.getNextUnicodeChar();
3713                   //                                                                    } else {
3714                   if (scanner.withoutUnicodePtr != 0) {
3715                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3716                   }
3717                   //                                                                    }
3718                   if (scanner.currentCharacter == '*') {
3719                     star = true;
3720                   }
3721                   //get the next char
3722                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3723                       && (source[scanner.currentPosition] == 'u')) {
3724                     //-------------unicode traitement
3725                     // ------------
3726                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3727                     scanner.currentPosition++;
3728                     while (source[scanner.currentPosition] == 'u') {
3729                       scanner.currentPosition++;
3730                     }
3731                     if ((c1 = Character
3732                         .getNumericValue(source[scanner.currentPosition++])) > 15
3733                         || c1 < 0
3734                         || (c2 = Character
3735                             .getNumericValue(source[scanner.currentPosition++])) > 15
3736                         || c2 < 0
3737                         || (c3 = Character
3738                             .getNumericValue(source[scanner.currentPosition++])) > 15
3739                         || c3 < 0
3740                         || (c4 = Character
3741                             .getNumericValue(source[scanner.currentPosition++])) > 15
3742                         || c4 < 0) { //error don't
3743                       // care of the
3744                       // value
3745                       scanner.currentCharacter = 'A';
3746                     } //something different from * and /
3747                     else {
3748                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3749                     }
3750                   }
3751                   //loop until end of comment */
3752                   while ((scanner.currentCharacter != '/') || (!star)) {
3753                     star = scanner.currentCharacter == '*';
3754                     //get next char
3755                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3756                         && (source[scanner.currentPosition] == 'u')) {
3757                       //-------------unicode traitement
3758                       // ------------
3759                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3760                       scanner.currentPosition++;
3761                       while (source[scanner.currentPosition] == 'u') {
3762                         scanner.currentPosition++;
3763                       }
3764                       if ((c1 = Character
3765                           .getNumericValue(source[scanner.currentPosition++])) > 15
3766                           || c1 < 0
3767                           || (c2 = Character
3768                               .getNumericValue(source[scanner.currentPosition++])) > 15
3769                           || c2 < 0
3770                           || (c3 = Character
3771                               .getNumericValue(source[scanner.currentPosition++])) > 15
3772                           || c3 < 0
3773                           || (c4 = Character
3774                               .getNumericValue(source[scanner.currentPosition++])) > 15
3775                           || c4 < 0) { //error don't
3776                         // care of the
3777                         // value
3778                         scanner.currentCharacter = 'A';
3779                       } //something different from * and
3780                       // /
3781                       else {
3782                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3783                       }
3784                     }
3785                   }
3786                   if (this.scanner.taskTags != null) {
3787                     this.scanner.checkTaskTag(this.scanner
3788                         .getCurrentTokenStartPosition(), this.scanner
3789                         .getCurrentTokenEndPosition());
3790                   }
3791                   break;
3792                 }
3793                 break;
3794               }
3795             default :
3796               if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3797                 scanner.scanIdentifierOrKeyword(false);
3798                 break;
3799               }
3800               if (Character.isDigit(scanner.currentCharacter)) {
3801                 scanner.scanNumber(false);
3802                 break;
3803               }
3804           }
3805           //-----------------end switch while
3806           // try--------------------
3807         } catch (IndexOutOfBoundsException e) {
3808           break; // read until EOF
3809         } catch (InvalidInputException e) {
3810           return false; // no clue
3811         }
3812       }
3813       if (scanner.recordLineSeparator) {
3814         //                              compilationUnit.compilationResult.lineSeparatorPositions =
3815         // scanner.getLineEnds();
3816       }
3817       // check placement anomalies against other kinds of brackets
3818       for (int kind = 0; kind < BracketKinds; kind++) {
3819         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3820           int start = leftPositions[kind][leftIndex]; // deepest
3821           // first
3822           // find matching closing bracket
3823           int depth = leftDepths[kind][leftIndex];
3824           int end = -1;
3825           for (int i = 0; i < rightCount[kind]; i++) {
3826             int pos = rightPositions[kind][i];
3827             // want matching bracket further in source with same
3828             // depth
3829             if ((pos > start) && (depth == rightDepths[kind][i])) {
3830               end = pos;
3831               break;
3832             }
3833           }
3834           if (end < 0) { // did not find a good closing match
3835             problemReporter.unmatchedBracket(start, referenceContext,
3836                 compilationUnit.compilationResult);
3837             return true;
3838           }
3839           // check if even number of opening/closing other brackets
3840           // in between this pair of brackets
3841           int balance = 0;
3842           for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3843             for (int i = 0; i < leftCount[otherKind]; i++) {
3844               int pos = leftPositions[otherKind][i];
3845               if ((pos > start) && (pos < end))
3846                 balance++;
3847             }
3848             for (int i = 0; i < rightCount[otherKind]; i++) {
3849               int pos = rightPositions[otherKind][i];
3850               if ((pos > start) && (pos < end))
3851                 balance--;
3852             }
3853             if (balance != 0) {
3854               problemReporter.unmatchedBracket(start, referenceContext,
3855                   compilationUnit.compilationResult); //bracket
3856               // anomaly
3857               return true;
3858             }
3859           }
3860         }
3861         // too many opening brackets ?
3862         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3863           anomaliesDetected = true;
3864           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3865               - i - 1], referenceContext, compilationUnit.compilationResult);
3866         }
3867         // too many closing brackets ?
3868         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3869           anomaliesDetected = true;
3870           problemReporter.unmatchedBracket(rightPositions[kind][i],
3871               referenceContext, compilationUnit.compilationResult);
3872         }
3873         if (anomaliesDetected)
3874           return true;
3875       }
3876       return anomaliesDetected;
3877     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3878       return anomaliesDetected;
3879     } catch (NullPointerException e) { // jdk1.2.2 jit bug
3880       return anomaliesDetected;
3881     }
3882   }
3883   protected void pushOnAstLengthStack(int pos) {
3884     try {
3885       astLengthStack[++astLengthPtr] = pos;
3886     } catch (IndexOutOfBoundsException e) {
3887       int oldStackLength = astLengthStack.length;
3888       int[] oldPos = astLengthStack;
3889       astLengthStack = new int[oldStackLength + StackIncrement];
3890       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3891       astLengthStack[astLengthPtr] = pos;
3892     }
3893   }
3894   protected void pushOnAstStack(AstNode node) {
3895     /*
3896      * add a new obj on top of the ast stack
3897      */
3898     try {
3899       astStack[++astPtr] = node;
3900     } catch (IndexOutOfBoundsException e) {
3901       int oldStackLength = astStack.length;
3902       AstNode[] oldStack = astStack;
3903       astStack = new AstNode[oldStackLength + AstStackIncrement];
3904       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3905       astPtr = oldStackLength;
3906       astStack[astPtr] = node;
3907     }
3908     try {
3909       astLengthStack[++astLengthPtr] = 1;
3910     } catch (IndexOutOfBoundsException e) {
3911       int oldStackLength = astLengthStack.length;
3912       int[] oldPos = astLengthStack;
3913       astLengthStack = new int[oldStackLength + AstStackIncrement];
3914       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3915       astLengthStack[astLengthPtr] = 1;
3916     }
3917   }
3918 }