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