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