misc parser changes
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Parser.java
1 /**********************************************************************
2  Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de
3  All rights reserved. This program and the accompanying material
4  are made available under the terms of the Common Public License v1.0
5  which accompanies this distribution, and is available at
6  http://www.eclipse.org/legal/cpl-v10.html
7
8  Contributors:
9  Klaus Hartlage - www.eclipseproject.de
10  **********************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.parser;
12 import java.util.ArrayList;
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
15 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
16 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
17 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
18 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
19 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
20 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
21 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
22 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
23 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
26
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 || token > TokenNameKEYWORD) {
2942       if (token > TokenNameKEYWORD) {
2943         // TODO show a warning "Keyword used as variable" ?
2944       }
2945       getNextToken();
2946     } else {
2947       
2948       if (token != TokenNameLBRACE) {
2949         throwSyntaxError("'{' expected in variable name.");
2950       }
2951       getNextToken();
2952       expr();
2953       if (token != TokenNameRBRACE) {
2954         throwSyntaxError("'}' expected in variable name.");
2955       }
2956     }
2957   }
2958   private void r_variable() {
2959     variable();
2960   }
2961   private void w_variable() {
2962     variable();
2963   }
2964   private void rw_variable() {
2965     variable();
2966   }
2967   private void variable() {
2968     //    variable:
2969     //          base_variable_with_function_calls T_OBJECT_OPERATOR
2970     //                  object_property method_or_not variable_properties
2971     //  | base_variable_with_function_calls
2972     base_variable_with_function_calls();
2973     if (token == TokenNameMINUS_GREATER) {
2974       getNextToken();
2975       object_property();
2976       method_or_not();
2977       variable_properties();
2978     }
2979     //    if (token == TokenNameDOLLAR_LBRACE) {
2980     //      getNextToken();
2981     //      expr();
2982     //      ;
2983     //      if (token != TokenNameRBRACE) {
2984     //        throwSyntaxError("'}' expected after indirect variable token '${'.");
2985     //      }
2986     //      getNextToken();
2987     //    } else {
2988     //      if (token == TokenNameVariable) {
2989     //        getNextToken();
2990     //        if (token == TokenNameLBRACKET) {
2991     //          getNextToken();
2992     //          expr();
2993     //          if (token != TokenNameRBRACKET) {
2994     //            throwSyntaxError("']' expected in variable-list.");
2995     //          }
2996     //          getNextToken();
2997     //        } else if (token == TokenNameEQUAL) {
2998     //          getNextToken();
2999     //          static_scalar();
3000     //        }
3001     //      } else {
3002     //        throwSyntaxError("$-variable expected in variable-list.");
3003     //      }
3004     //    }
3005   }
3006   private void variable_properties() {
3007     //  variable_properties:
3008     //                  variable_properties variable_property
3009     //          | /* empty */
3010     while (token == TokenNameMINUS_GREATER) {
3011       variable_property();
3012     }
3013   }
3014   private void variable_property() {
3015     //  variable_property:
3016     //                  T_OBJECT_OPERATOR object_property method_or_not
3017     if (Scanner.TRACE) {
3018       System.out.println("TRACE: variable_property()");
3019     }
3020     if (token == TokenNameMINUS_GREATER) {
3021       getNextToken();
3022       object_property();
3023       method_or_not();
3024     } else {
3025       throwSyntaxError("'->' expected in variable_property.");
3026     }
3027   }
3028   private void method_or_not() {
3029     //  method_or_not:
3030     //                  '(' function_call_parameter_list ')'
3031     //          | /* empty */
3032     if (Scanner.TRACE) {
3033       System.out.println("TRACE: method_or_not()");
3034     }
3035     if (token == TokenNameLPAREN) {
3036       getNextToken();
3037       if (token == TokenNameRPAREN) {
3038         getNextToken();
3039         return;
3040       }
3041       non_empty_function_call_parameter_list();
3042       if (token != TokenNameRPAREN) {
3043         throwSyntaxError("')' expected in method_or_not.");
3044       }
3045       getNextToken();
3046     }
3047   }
3048   private void exit_expr() {
3049     //  /* empty */
3050     //  | '(' ')'
3051     //  | '(' expr ')'
3052     if (token != TokenNameLPAREN) {
3053       return;
3054     }
3055     getNextToken();
3056     if (token == TokenNameRPAREN) {
3057       getNextToken();
3058       return;
3059     }
3060     expr();
3061     if (token != TokenNameRPAREN) {
3062       throwSyntaxError("')' expected after keyword 'exit'");
3063     }
3064     getNextToken();
3065   }
3066   private void internal_functions_in_yacc() {
3067     switch (token) {
3068       case TokenNameisset :
3069         //      T_ISSET '(' isset_variables ')'
3070         getNextToken();
3071         if (token != TokenNameLPAREN) {
3072           throwSyntaxError("'(' expected after keyword 'isset'");
3073         }
3074         getNextToken();
3075         isset_variables();
3076         if (token != TokenNameRPAREN) {
3077           throwSyntaxError("')' expected after keyword 'isset'");
3078         }
3079         getNextToken();
3080         break;
3081       case TokenNameempty :
3082         //      T_EMPTY '(' variable ')'
3083         getNextToken();
3084         if (token != TokenNameLPAREN) {
3085           throwSyntaxError("'(' expected after keyword 'empty'");
3086         }
3087         getNextToken();
3088         variable();
3089         if (token != TokenNameRPAREN) {
3090           throwSyntaxError("')' expected after keyword 'empty'");
3091         }
3092         getNextToken();
3093         break;
3094       case TokenNameinclude :
3095         //T_INCLUDE expr
3096         getNextToken();
3097         expr();
3098         break;
3099       case TokenNameinclude_once :
3100         //      T_INCLUDE_ONCE expr
3101         getNextToken();
3102         expr();
3103         break;
3104       case TokenNameeval :
3105         //      T_EVAL '(' expr ')'
3106         getNextToken();
3107         if (token != TokenNameLPAREN) {
3108           throwSyntaxError("'(' expected after keyword 'eval'");
3109         }
3110         getNextToken();
3111         expr();
3112         if (token != TokenNameRPAREN) {
3113           throwSyntaxError("')' expected after keyword 'eval'");
3114         }
3115         getNextToken();
3116         break;
3117       case TokenNamerequire :
3118         //T_REQUIRE expr
3119         getNextToken();
3120         expr();
3121         break;
3122       case TokenNamerequire_once :
3123         //      T_REQUIRE_ONCE expr
3124         getNextToken();
3125         expr();
3126         break;
3127     }
3128   }
3129   private void isset_variables() {
3130     //  variable
3131     //  | isset_variables ','
3132     if (token == TokenNameRPAREN) {
3133       throwSyntaxError("Variable expected after keyword 'isset'");
3134     }
3135     while (true) {
3136       variable();
3137       if (token == TokenNameCOMMA) {
3138         getNextToken();
3139       } else {
3140         break;
3141       }
3142     }
3143   }
3144   private boolean common_scalar() {
3145     //  common_scalar:
3146     //  T_LNUMBER
3147     //  | T_DNUMBER
3148     //  | T_CONSTANT_ENCAPSED_STRING
3149     //  | T_LINE
3150     //  | T_FILE
3151     //  | T_CLASS_C
3152     //  | T_METHOD_C
3153     //  | T_FUNC_C
3154     switch (token) {
3155       case TokenNameIntegerLiteral :
3156         getNextToken();
3157         return true;
3158       case TokenNameDoubleLiteral :
3159         getNextToken();
3160         return true;
3161       case TokenNameStringLiteral :
3162         getNextToken();
3163         return true;
3164       case TokenNameStringConstant :
3165         getNextToken();
3166         return true;
3167       case TokenNameStringInterpolated :
3168         getNextToken();
3169         return true;
3170       case TokenNameFILE :
3171         getNextToken();
3172         return true;
3173       case TokenNameLINE :
3174         getNextToken();
3175         return true;
3176       case TokenNameCLASS_C :
3177         getNextToken();
3178         return true;
3179       case TokenNameMETHOD_C :
3180         getNextToken();
3181         return true;
3182       case TokenNameFUNC_C :
3183         getNextToken();
3184         return true;
3185     }
3186     return false;
3187   }
3188   private void scalar() {
3189     //  scalar:
3190     //  T_STRING
3191     //| T_STRING_VARNAME
3192     //| class_constant
3193     //| common_scalar
3194     //| '"' encaps_list '"'
3195     //| '\'' encaps_list '\''
3196     //| T_START_HEREDOC encaps_list T_END_HEREDOC
3197     throwSyntaxError("Not yet implemented (scalar).");
3198   }
3199   private void static_scalar() {
3200     //    static_scalar: /* compile-time evaluated scalars */
3201     //          common_scalar
3202     //  | T_STRING
3203     //  | '+' static_scalar
3204     //  | '-' static_scalar
3205     //  | T_ARRAY '(' static_array_pair_list ')'
3206     //  | static_class_constant
3207     if (common_scalar()) {
3208       return;
3209     }
3210     switch (token) {
3211       case TokenNameIdentifier :
3212         getNextToken();
3213         //        static_class_constant:
3214         //              T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3215         if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3216           getNextToken();
3217           if (token == TokenNameIdentifier) {
3218             getNextToken();
3219           } else {
3220             throwSyntaxError("Identifier expected after '::' operator.");
3221           }
3222         }
3223         break;
3224       case TokenNamePLUS :
3225         getNextToken();
3226         static_scalar();
3227         break;
3228       case TokenNameMINUS :
3229         getNextToken();
3230         static_scalar();
3231         break;
3232       case TokenNamearray :
3233         getNextToken();
3234         if (token != TokenNameLPAREN) {
3235           throwSyntaxError("'(' expected after keyword 'array'");
3236         }
3237         getNextToken();
3238         if (token == TokenNameRPAREN) {
3239           getNextToken();
3240           break;
3241         }
3242         non_empty_static_array_pair_list();
3243         if (token != TokenNameRPAREN) {
3244           throwSyntaxError("')' expected after keyword 'array'");
3245         }
3246         getNextToken();
3247         break;
3248       //      case TokenNamenull :
3249       //        getNextToken();
3250       //        break;
3251       //      case TokenNamefalse :
3252       //        getNextToken();
3253       //        break;
3254       //      case TokenNametrue :
3255       //        getNextToken();
3256       //        break;
3257       default :
3258         throwSyntaxError("Static scalar/constant expected.");
3259     }
3260   }
3261   private void non_empty_static_array_pair_list() {
3262     //  non_empty_static_array_pair_list:
3263     //  non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3264     // static_scalar
3265     //| non_empty_static_array_pair_list ',' static_scalar
3266     //| static_scalar T_DOUBLE_ARROW static_scalar
3267     //| static_scalar
3268     while (true) {
3269       static_scalar();
3270       if (token == TokenNameEQUAL_GREATER) {
3271         getNextToken();
3272         static_scalar();
3273       }
3274       if (token != TokenNameCOMMA) {
3275         break;
3276       }
3277       getNextToken();
3278       if (token == TokenNameRPAREN) {
3279         break;
3280       }
3281     }
3282   }
3283   public void reportSyntaxError() { //int act, int currentKind, int
3284     // stateStackTop) {
3285     /* remember current scanner position */
3286     int startPos = scanner.startPosition;
3287     int currentPos = scanner.currentPosition;
3288     //          String[] expectings;
3289     //          String tokenName = name[symbol_index[currentKind]];
3290     //fetch all "accurate" possible terminals that could recover the error
3291     //          int start, end = start = asi(stack[stateStackTop]);
3292     //          while (asr[end] != 0)
3293     //                  end++;
3294     //          int length = end - start;
3295     //          expectings = new String[length];
3296     //          if (length != 0) {
3297     //                  char[] indexes = new char[length];
3298     //                  System.arraycopy(asr, start, indexes, 0, length);
3299     //                  for (int i = 0; i < length; i++) {
3300     //                          expectings[i] = name[symbol_index[indexes[i]]];
3301     //                  }
3302     //          }
3303     //if the pb is an EOF, try to tell the user that they are some
3304     //          if (tokenName.equals(UNEXPECTED_EOF)) {
3305     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3306     //                          char[] tokenSource;
3307     //                          try {
3308     //                                  tokenSource = this.scanner.getCurrentTokenSource();
3309     //                          } catch (Exception e) {
3310     //                                  tokenSource = new char[] {};
3311     //                          }
3312     //                          problemReporter().parseError(
3313     //                                  this.scanner.startPosition,
3314     //                                  this.scanner.currentPosition - 1,
3315     //                                  tokenSource,
3316     //                                  tokenName,
3317     //                                  expectings);
3318     //                  }
3319     //          } else { //the next test is HEAVILY grammar DEPENDENT.
3320     //                  if ((length == 14)
3321     //                          && (expectings[0] == "=") //$NON-NLS-1$
3322     //                          && (expectings[1] == "*=") //$NON-NLS-1$
3323     //                          && (expressionPtr > -1)) {
3324     //                                  switch(currentKind) {
3325     //                                          case TokenNameSEMICOLON:
3326     //                                          case TokenNamePLUS:
3327     //                                          case TokenNameMINUS:
3328     //                                          case TokenNameDIVIDE:
3329     //                                          case TokenNameREMAINDER:
3330     //                                          case TokenNameMULTIPLY:
3331     //                                          case TokenNameLEFT_SHIFT:
3332     //                                          case TokenNameRIGHT_SHIFT:
3333     //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3334     //                                          case TokenNameLESS:
3335     //                                          case TokenNameGREATER:
3336     //                                          case TokenNameLESS_EQUAL:
3337     //                                          case TokenNameGREATER_EQUAL:
3338     //                                          case TokenNameEQUAL_EQUAL:
3339     //                                          case TokenNameNOT_EQUAL:
3340     //                                          case TokenNameXOR:
3341     //                                          case TokenNameAND:
3342     //                                          case TokenNameOR:
3343     //                                          case TokenNameOR_OR:
3344     //                                          case TokenNameAND_AND:
3345     //                                                  // the ; is not the expected token ==> it ends a statement when an
3346     // expression is not ended
3347     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3348     //                                                  break;
3349     //                                          case TokenNameRBRACE :
3350     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3351     //                                                  break;
3352     //                                          default:
3353     //                                                  char[] tokenSource;
3354     //                                                  try {
3355     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
3356     //                                                  } catch (Exception e) {
3357     //                                                          tokenSource = new char[] {};
3358     //                                                  }
3359     //                                                  problemReporter().parseError(
3360     //                                                          this.scanner.startPosition,
3361     //                                                          this.scanner.currentPosition - 1,
3362     //                                                          tokenSource,
3363     //                                                          tokenName,
3364     //                                                          expectings);
3365     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
3366     //                                  }
3367     //                  } else {
3368     char[] tokenSource;
3369     try {
3370       tokenSource = this.scanner.getCurrentTokenSource();
3371     } catch (Exception e) {
3372       tokenSource = new char[]{};
3373     }
3374     //                          problemReporter().parseError(
3375     //                                  this.scanner.startPosition,
3376     //                                  this.scanner.currentPosition - 1,
3377     //                                  tokenSource,
3378     //                                  tokenName,
3379     //                                  expectings);
3380     this.checkAndReportBracketAnomalies(problemReporter());
3381     //                  }
3382     //          }
3383     /* reset scanner where it was */
3384     scanner.startPosition = startPos;
3385     scanner.currentPosition = currentPos;
3386   }
3387   public static final int RoundBracket = 0;
3388   public static final int SquareBracket = 1;
3389   public static final int CurlyBracket = 2;
3390   public static final int BracketKinds = 3;
3391   protected int[] nestedMethod; //the ptr is nestedType
3392   protected int nestedType, dimensions;
3393   //ast stack
3394   final static int AstStackIncrement = 100;
3395   protected int astPtr;
3396   protected AstNode[] astStack = new AstNode[AstStackIncrement];
3397   protected int astLengthPtr;
3398   protected int[] astLengthStack;
3399   AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3400   public CompilationUnitDeclaration compilationUnit; /*
3401                                                       * the result from parse()
3402                                                       */
3403   protected ReferenceContext referenceContext;
3404   protected ProblemReporter problemReporter;
3405   //  protected CompilationResult compilationResult;
3406   /**
3407    * Returns this parser's problem reporter initialized with its reference
3408    * context. Also it is assumed that a problem is going to be reported, so
3409    * initializes the compilation result's line positions.
3410    */
3411   public ProblemReporter problemReporter() {
3412     if (scanner.recordLineSeparator) {
3413       compilationUnit.compilationResult.lineSeparatorPositions = scanner
3414           .getLineEnds();
3415     }
3416     problemReporter.referenceContext = referenceContext;
3417     return problemReporter;
3418   }
3419   /*
3420    * Reconsider the entire source looking for inconsistencies in {} () []
3421    */
3422   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3423     scanner.wasAcr = false;
3424     boolean anomaliesDetected = false;
3425     try {
3426       char[] source = scanner.source;
3427       int[] leftCount = {0, 0, 0};
3428       int[] rightCount = {0, 0, 0};
3429       int[] depths = {0, 0, 0};
3430       int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3431       int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3432       int[][] rightPositions = new int[][]{new int[10], new int[10],
3433           new int[10]};
3434       int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3435       scanner.currentPosition = scanner.initialPosition; //starting
3436       // point
3437       // (first-zero-based
3438       // char)
3439       while (scanner.currentPosition < scanner.eofPosition) { //loop for
3440         // jumping
3441         // over
3442         // comments
3443         try {
3444           // ---------Consume white space and handles
3445           // startPosition---------
3446           boolean isWhiteSpace;
3447           do {
3448             scanner.startPosition = scanner.currentPosition;
3449             //                                          if (((scanner.currentCharacter =
3450             // source[scanner.currentPosition++]) == '\\') &&
3451             // (source[scanner.currentPosition] == 'u')) {
3452             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3453             //                                          } else {
3454             if (scanner.recordLineSeparator
3455                 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3456               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3457                 // only record line positions we have not
3458                 // recorded yet
3459                 scanner.pushLineSeparator();
3460               }
3461             }
3462             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3463             //                                          }
3464           } while (isWhiteSpace
3465               && (scanner.currentPosition < scanner.eofPosition));
3466           // -------consume token until } is found---------
3467           switch (scanner.currentCharacter) {
3468             case '{' :
3469               {
3470                 int index = leftCount[CurlyBracket]++;
3471                 if (index == leftPositions[CurlyBracket].length) {
3472                   System.arraycopy(leftPositions[CurlyBracket], 0,
3473                       (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3474                       index);
3475                   System
3476                       .arraycopy(leftDepths[CurlyBracket], 0,
3477                           (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3478                           index);
3479                 }
3480                 leftPositions[CurlyBracket][index] = scanner.startPosition;
3481                 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3482               }
3483               break;
3484             case '}' :
3485               {
3486                 int index = rightCount[CurlyBracket]++;
3487                 if (index == rightPositions[CurlyBracket].length) {
3488                   System.arraycopy(rightPositions[CurlyBracket], 0,
3489                       (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3490                       index);
3491                   System.arraycopy(rightDepths[CurlyBracket], 0,
3492                       (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3493                       index);
3494                 }
3495                 rightPositions[CurlyBracket][index] = scanner.startPosition;
3496                 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3497               }
3498               break;
3499             case '(' :
3500               {
3501                 int index = leftCount[RoundBracket]++;
3502                 if (index == leftPositions[RoundBracket].length) {
3503                   System.arraycopy(leftPositions[RoundBracket], 0,
3504                       (leftPositions[RoundBracket] = new int[index * 2]), 0,
3505                       index);
3506                   System
3507                       .arraycopy(leftDepths[RoundBracket], 0,
3508                           (leftDepths[RoundBracket] = new int[index * 2]), 0,
3509                           index);
3510                 }
3511                 leftPositions[RoundBracket][index] = scanner.startPosition;
3512                 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3513               }
3514               break;
3515             case ')' :
3516               {
3517                 int index = rightCount[RoundBracket]++;
3518                 if (index == rightPositions[RoundBracket].length) {
3519                   System.arraycopy(rightPositions[RoundBracket], 0,
3520                       (rightPositions[RoundBracket] = new int[index * 2]), 0,
3521                       index);
3522                   System.arraycopy(rightDepths[RoundBracket], 0,
3523                       (rightDepths[RoundBracket] = new int[index * 2]), 0,
3524                       index);
3525                 }
3526                 rightPositions[RoundBracket][index] = scanner.startPosition;
3527                 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3528               }
3529               break;
3530             case '[' :
3531               {
3532                 int index = leftCount[SquareBracket]++;
3533                 if (index == leftPositions[SquareBracket].length) {
3534                   System.arraycopy(leftPositions[SquareBracket], 0,
3535                       (leftPositions[SquareBracket] = new int[index * 2]), 0,
3536                       index);
3537                   System.arraycopy(leftDepths[SquareBracket], 0,
3538                       (leftDepths[SquareBracket] = new int[index * 2]), 0,
3539                       index);
3540                 }
3541                 leftPositions[SquareBracket][index] = scanner.startPosition;
3542                 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3543               }
3544               break;
3545             case ']' :
3546               {
3547                 int index = rightCount[SquareBracket]++;
3548                 if (index == rightPositions[SquareBracket].length) {
3549                   System.arraycopy(rightPositions[SquareBracket], 0,
3550                       (rightPositions[SquareBracket] = new int[index * 2]), 0,
3551                       index);
3552                   System.arraycopy(rightDepths[SquareBracket], 0,
3553                       (rightDepths[SquareBracket] = new int[index * 2]), 0,
3554                       index);
3555                 }
3556                 rightPositions[SquareBracket][index] = scanner.startPosition;
3557                 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3558               }
3559               break;
3560             case '\'' :
3561               {
3562                 if (scanner.getNextChar('\\')) {
3563                   scanner.scanEscapeCharacter();
3564                 } else { // consume next character
3565                   scanner.unicodeAsBackSlash = false;
3566                   //                                                                    if (((scanner.currentCharacter =
3567                   // source[scanner.currentPosition++]) ==
3568                   // '\\') &&
3569                   // (source[scanner.currentPosition] ==
3570                   // 'u')) {
3571                   //                                                                            scanner.getNextUnicodeChar();
3572                   //                                                                    } else {
3573                   if (scanner.withoutUnicodePtr != 0) {
3574                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3575                   }
3576                   //                                                                    }
3577                 }
3578                 scanner.getNextChar('\'');
3579                 break;
3580               }
3581             case '"' :
3582               // consume next character
3583               scanner.unicodeAsBackSlash = false;
3584               //                                                        if (((scanner.currentCharacter =
3585               // source[scanner.currentPosition++]) == '\\') &&
3586               // (source[scanner.currentPosition] == 'u')) {
3587               //                                                                scanner.getNextUnicodeChar();
3588               //                                                        } else {
3589               if (scanner.withoutUnicodePtr != 0) {
3590                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3591               }
3592               //                                                        }
3593               while (scanner.currentCharacter != '"') {
3594                 if (scanner.currentCharacter == '\r') {
3595                   if (source[scanner.currentPosition] == '\n')
3596                     scanner.currentPosition++;
3597                   break; // the string cannot go further that
3598                   // the line
3599                 }
3600                 if (scanner.currentCharacter == '\n') {
3601                   break; // the string cannot go further that
3602                   // the line
3603                 }
3604                 if (scanner.currentCharacter == '\\') {
3605                   scanner.scanEscapeCharacter();
3606                 }
3607                 // consume next character
3608                 scanner.unicodeAsBackSlash = false;
3609                 //                                                              if (((scanner.currentCharacter =
3610                 // source[scanner.currentPosition++]) == '\\')
3611                 // && (source[scanner.currentPosition] == 'u'))
3612                 // {
3613                 //                                                                      scanner.getNextUnicodeChar();
3614                 //                                                              } else {
3615                 if (scanner.withoutUnicodePtr != 0) {
3616                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3617                 }
3618                 //                                                              }
3619               }
3620               break;
3621             case '/' :
3622               {
3623                 int test;
3624                 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3625                   // comment
3626                   //get the next char
3627                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3628                       && (source[scanner.currentPosition] == 'u')) {
3629                     //-------------unicode traitement
3630                     // ------------
3631                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3632                     scanner.currentPosition++;
3633                     while (source[scanner.currentPosition] == 'u') {
3634                       scanner.currentPosition++;
3635                     }
3636                     if ((c1 = Character
3637                         .getNumericValue(source[scanner.currentPosition++])) > 15
3638                         || c1 < 0
3639                         || (c2 = Character
3640                             .getNumericValue(source[scanner.currentPosition++])) > 15
3641                         || c2 < 0
3642                         || (c3 = Character
3643                             .getNumericValue(source[scanner.currentPosition++])) > 15
3644                         || c3 < 0
3645                         || (c4 = Character
3646                             .getNumericValue(source[scanner.currentPosition++])) > 15
3647                         || c4 < 0) { //error don't
3648                       // care of the
3649                       // value
3650                       scanner.currentCharacter = 'A';
3651                     } //something different from \n and \r
3652                     else {
3653                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3654                     }
3655                   }
3656                   while (scanner.currentCharacter != '\r'
3657                       && scanner.currentCharacter != '\n') {
3658                     //get the next char
3659                     scanner.startPosition = scanner.currentPosition;
3660                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3661                         && (source[scanner.currentPosition] == 'u')) {
3662                       //-------------unicode traitement
3663                       // ------------
3664                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3665                       scanner.currentPosition++;
3666                       while (source[scanner.currentPosition] == 'u') {
3667                         scanner.currentPosition++;
3668                       }
3669                       if ((c1 = Character
3670                           .getNumericValue(source[scanner.currentPosition++])) > 15
3671                           || c1 < 0
3672                           || (c2 = Character
3673                               .getNumericValue(source[scanner.currentPosition++])) > 15
3674                           || c2 < 0
3675                           || (c3 = Character
3676                               .getNumericValue(source[scanner.currentPosition++])) > 15
3677                           || c3 < 0
3678                           || (c4 = Character
3679                               .getNumericValue(source[scanner.currentPosition++])) > 15
3680                           || c4 < 0) { //error don't
3681                         // care of the
3682                         // value
3683                         scanner.currentCharacter = 'A';
3684                       } //something different from \n
3685                       // and \r
3686                       else {
3687                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3688                       }
3689                     }
3690                   }
3691                   if (scanner.recordLineSeparator
3692                       && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3693                     if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3694                       // only record line positions we
3695                       // have not recorded yet
3696                       scanner.pushLineSeparator();
3697                       if (this.scanner.taskTags != null) {
3698                         this.scanner.checkTaskTag(this.scanner
3699                             .getCurrentTokenStartPosition(), this.scanner
3700                             .getCurrentTokenEndPosition());
3701                       }
3702                     }
3703                   }
3704                   break;
3705                 }
3706                 if (test > 0) { //traditional and annotation
3707                   // comment
3708                   boolean star = false;
3709                   // consume next character
3710                   scanner.unicodeAsBackSlash = false;
3711                   //                                                                    if (((scanner.currentCharacter =
3712                   // source[scanner.currentPosition++]) ==
3713                   // '\\') &&
3714                   // (source[scanner.currentPosition] ==
3715                   // 'u')) {
3716                   //                                                                            scanner.getNextUnicodeChar();
3717                   //                                                                    } else {
3718                   if (scanner.withoutUnicodePtr != 0) {
3719                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3720                   }
3721                   //                                                                    }
3722                   if (scanner.currentCharacter == '*') {
3723                     star = true;
3724                   }
3725                   //get the next char
3726                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3727                       && (source[scanner.currentPosition] == 'u')) {
3728                     //-------------unicode traitement
3729                     // ------------
3730                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3731                     scanner.currentPosition++;
3732                     while (source[scanner.currentPosition] == 'u') {
3733                       scanner.currentPosition++;
3734                     }
3735                     if ((c1 = Character
3736                         .getNumericValue(source[scanner.currentPosition++])) > 15
3737                         || c1 < 0
3738                         || (c2 = Character
3739                             .getNumericValue(source[scanner.currentPosition++])) > 15
3740                         || c2 < 0
3741                         || (c3 = Character
3742                             .getNumericValue(source[scanner.currentPosition++])) > 15
3743                         || c3 < 0
3744                         || (c4 = Character
3745                             .getNumericValue(source[scanner.currentPosition++])) > 15
3746                         || c4 < 0) { //error don't
3747                       // care of the
3748                       // value
3749                       scanner.currentCharacter = 'A';
3750                     } //something different from * and /
3751                     else {
3752                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3753                     }
3754                   }
3755                   //loop until end of comment */
3756                   while ((scanner.currentCharacter != '/') || (!star)) {
3757                     star = scanner.currentCharacter == '*';
3758                     //get next char
3759                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3760                         && (source[scanner.currentPosition] == 'u')) {
3761                       //-------------unicode traitement
3762                       // ------------
3763                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3764                       scanner.currentPosition++;
3765                       while (source[scanner.currentPosition] == 'u') {
3766                         scanner.currentPosition++;
3767                       }
3768                       if ((c1 = Character
3769                           .getNumericValue(source[scanner.currentPosition++])) > 15
3770                           || c1 < 0
3771                           || (c2 = Character
3772                               .getNumericValue(source[scanner.currentPosition++])) > 15
3773                           || c2 < 0
3774                           || (c3 = Character
3775                               .getNumericValue(source[scanner.currentPosition++])) > 15
3776                           || c3 < 0
3777                           || (c4 = Character
3778                               .getNumericValue(source[scanner.currentPosition++])) > 15
3779                           || c4 < 0) { //error don't
3780                         // care of the
3781                         // value
3782                         scanner.currentCharacter = 'A';
3783                       } //something different from * and
3784                       // /
3785                       else {
3786                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3787                       }
3788                     }
3789                   }
3790                   if (this.scanner.taskTags != null) {
3791                     this.scanner.checkTaskTag(this.scanner
3792                         .getCurrentTokenStartPosition(), this.scanner
3793                         .getCurrentTokenEndPosition());
3794                   }
3795                   break;
3796                 }
3797                 break;
3798               }
3799             default :
3800               if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3801                 scanner.scanIdentifierOrKeyword(false);
3802                 break;
3803               }
3804               if (Character.isDigit(scanner.currentCharacter)) {
3805                 scanner.scanNumber(false);
3806                 break;
3807               }
3808           }
3809           //-----------------end switch while
3810           // try--------------------
3811         } catch (IndexOutOfBoundsException e) {
3812           break; // read until EOF
3813         } catch (InvalidInputException e) {
3814           return false; // no clue
3815         }
3816       }
3817       if (scanner.recordLineSeparator) {
3818         //                              compilationUnit.compilationResult.lineSeparatorPositions =
3819         // scanner.getLineEnds();
3820       }
3821       // check placement anomalies against other kinds of brackets
3822       for (int kind = 0; kind < BracketKinds; kind++) {
3823         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3824           int start = leftPositions[kind][leftIndex]; // deepest
3825           // first
3826           // find matching closing bracket
3827           int depth = leftDepths[kind][leftIndex];
3828           int end = -1;
3829           for (int i = 0; i < rightCount[kind]; i++) {
3830             int pos = rightPositions[kind][i];
3831             // want matching bracket further in source with same
3832             // depth
3833             if ((pos > start) && (depth == rightDepths[kind][i])) {
3834               end = pos;
3835               break;
3836             }
3837           }
3838           if (end < 0) { // did not find a good closing match
3839             problemReporter.unmatchedBracket(start, referenceContext,
3840                 compilationUnit.compilationResult);
3841             return true;
3842           }
3843           // check if even number of opening/closing other brackets
3844           // in between this pair of brackets
3845           int balance = 0;
3846           for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3847             for (int i = 0; i < leftCount[otherKind]; i++) {
3848               int pos = leftPositions[otherKind][i];
3849               if ((pos > start) && (pos < end))
3850                 balance++;
3851             }
3852             for (int i = 0; i < rightCount[otherKind]; i++) {
3853               int pos = rightPositions[otherKind][i];
3854               if ((pos > start) && (pos < end))
3855                 balance--;
3856             }
3857             if (balance != 0) {
3858               problemReporter.unmatchedBracket(start, referenceContext,
3859                   compilationUnit.compilationResult); //bracket
3860               // anomaly
3861               return true;
3862             }
3863           }
3864         }
3865         // too many opening brackets ?
3866         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3867           anomaliesDetected = true;
3868           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3869               - i - 1], referenceContext, compilationUnit.compilationResult);
3870         }
3871         // too many closing brackets ?
3872         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3873           anomaliesDetected = true;
3874           problemReporter.unmatchedBracket(rightPositions[kind][i],
3875               referenceContext, compilationUnit.compilationResult);
3876         }
3877         if (anomaliesDetected)
3878           return true;
3879       }
3880       return anomaliesDetected;
3881     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3882       return anomaliesDetected;
3883     } catch (NullPointerException e) { // jdk1.2.2 jit bug
3884       return anomaliesDetected;
3885     }
3886   }
3887   protected void pushOnAstLengthStack(int pos) {
3888     try {
3889       astLengthStack[++astLengthPtr] = pos;
3890     } catch (IndexOutOfBoundsException e) {
3891       int oldStackLength = astLengthStack.length;
3892       int[] oldPos = astLengthStack;
3893       astLengthStack = new int[oldStackLength + StackIncrement];
3894       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3895       astLengthStack[astLengthPtr] = pos;
3896     }
3897   }
3898   protected void pushOnAstStack(AstNode node) {
3899     /*
3900      * add a new obj on top of the ast stack
3901      */
3902     try {
3903       astStack[++astPtr] = node;
3904     } catch (IndexOutOfBoundsException e) {
3905       int oldStackLength = astStack.length;
3906       AstNode[] oldStack = astStack;
3907       astStack = new AstNode[oldStackLength + AstStackIncrement];
3908       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3909       astPtr = oldStackLength;
3910       astStack[astPtr] = node;
3911     }
3912     try {
3913       astLengthStack[++astLengthPtr] = 1;
3914     } catch (IndexOutOfBoundsException e) {
3915       int oldStackLength = astLengthStack.length;
3916       int[] oldPos = astLengthStack;
3917       astLengthStack = new int[oldStackLength + AstStackIncrement];
3918       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3919       astLengthStack[astLengthPtr] = 1;
3920     }
3921   }
3922 }