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
 
   9     Klaus Hartlage - www.eclipseproject.de
 
  10 **********************************************************************/
 
  11 package net.sourceforge.phpdt.internal.compiler.parser;
 
  13 import java.util.ArrayList;
 
  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;
 
  30 import org.eclipse.core.resources.IFile;
 
  31 import org.eclipse.core.runtime.CoreException;
 
  32 import org.eclipse.jface.preference.IPreferenceStore;
 
  34 import test.PHPParserSuperclass;
 
  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;
 
  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
 
  49   public Scanner scanner;
 
  51   private ArrayList phpList;
 
  53   private int currentPHPString;
 
  54   private boolean phpEnd;
 
  56   // private static HashMap keywordMap = null;
 
  64   // row counter for syntax errors:
 
  66   // column counter for syntax errors:
 
  71   //    // current identifier
 
  77   private String stringValue;
 
  79   /** Contains the current expression. */
 
  80   // private StringBuffer expression;
 
  82   private boolean phpMode;
 
  84   //    final static int TokenNameEOF = 0;
 
  85   //    final static int TokenNameERROR = 1;
 
  86   //    final static int TokenNameHTML = 2;
 
  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;
 
 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;
 
 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;
 
 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;
 
 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; // @
 
 161     this.currentPHPString = 0;
 
 162     //          PHPParserSuperclass.fileToParse = fileToParse;
 
 165     this.token = TokenNameEOF;
 
 167     //    this.rowCount = 1;
 
 168     //    this.columnCount = 0;
 
 172     this.initializeScanner();
 
 176   public void setFileToParse(IFile fileToParse) {
 
 177     this.currentPHPString = 0;
 
 178     PHPParserSuperclass.fileToParse = fileToParse;
 
 181     this.token = TokenNameEOF;
 
 183     this.initializeScanner();
 
 186    *  ClassDeclaration Constructor.
 
 189    *@param  sess  Description of Parameter
 
 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]));
 
 199     this.currentPHPString = 0;
 
 200     PHPParserSuperclass.fileToParse = fileToParse;
 
 203     this.token = TokenNameEOF;
 
 205     //    this.rowCount = 1;
 
 206     //    this.columnCount = 0;
 
 210     this.initializeScanner();
 
 213   public void initializeScanner() {
 
 214     this.scanner = new Scanner(false, false, false, false);
 
 217    * Create marker for the parse error
 
 219   private void setMarker(String message, int charStart, int charEnd, int errorLevel) throws CoreException {
 
 220     setMarker(fileToParse, message, charStart, charEnd, errorLevel);
 
 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
 
 229   private void throwSyntaxError(String error) {
 
 231     //    if (str.length() < chIndx) {
 
 234     //    // read until end-of-line
 
 236     //    while (str.length() > eol) {
 
 237     //      ch = str.charAt(eol++);
 
 243     //    throw new SyntaxError(
 
 245     //      chIndx - columnCount + 1,
 
 246     //      str.substring(columnCount, eol),
 
 248     throw new SyntaxError(1, 1, "", error);
 
 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
 
 257   private void throwSyntaxError(String error, int startRow) {
 
 258     throw new SyntaxError(startRow, 0, " ", error);
 
 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);
 
 266    *  Method Declaration.
 
 270   //  private void getChar() {
 
 271   //    if (str.length() > chIndx) {
 
 272   //      ch = str.charAt(chIndx++);
 
 277   //    chIndx = str.length() + 1;
 
 279   //    //  token = TokenNameEOF;
 
 284    * gets the next token from input
 
 286   private void getNextToken() throws CoreException {
 
 288       token = scanner.getNextToken();
 
 290         int currentEndPosition = scanner.getCurrentTokenEndPosition();
 
 291         int currentStartPosition = scanner.getCurrentTokenStartPosition();
 
 293         System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
 
 294         System.out.println(scanner.toStringAction(token));
 
 296     } catch (InvalidInputException e) {
 
 297       token = TokenNameERROR;
 
 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}
 
 310   //  private void getNumber() {
 
 311   //    StringBuffer inum = new StringBuffer();
 
 313   //    int numFormat = 10;
 
 315   //    // save first digit
 
 316   //    char firstCh = ch;
 
 320   //    // determine number conversions:
 
 321   //    if (firstCh == '0') {
 
 350   //    if (numFormat == 16) {
 
 351   //      while ((ch >= '0' && ch <= '9')
 
 352   //        || (ch >= 'a' && ch <= 'f')
 
 353   //        || (ch >= 'A' && ch <= 'F')) {
 
 358   //      while ((ch >= '0' && ch <= '9')
 
 362   //        if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
 
 363   //          if (ch == '.' && dFlag != ' ') {
 
 366   //          if ((dFlag == 'E') || (dFlag == 'e')) {
 
 372   //          if ((ch == '-') || (ch == '+')) {
 
 385   //      if (dFlag != ' ') {
 
 386   //        doubleNumber = new Double(inum.toString());
 
 387   //        token = TokenNameDoubleLiteral;
 
 390   //        longNumber = Long.valueOf(inum.toString(), numFormat);
 
 391   //        token = TokenNameIntegerLiteral;
 
 395   //    } catch (Throwable e) {
 
 396   //      throwSyntaxError("Number format error: " + inum.toString());
 
 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
 
 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++);
 
 416   //        sBuffer.append(ch);
 
 417   //        if (str.length() > chIndx) {
 
 418   //          ch = str.charAt(chIndx++);
 
 419   //          sBuffer.append(ch);
 
 421   //      } else if (ch == openChar) {
 
 422   //        openString = false;
 
 424   //      } else if (ch == '\n') {
 
 426   //        columnCount = chIndx;
 
 428   //        sBuffer.append(ch);
 
 432   //      if (typeString == TokenNameStringConstant) {
 
 433   //        throwSyntaxError(errorMsg, startRow);
 
 435   //        throwSyntaxError(errorMsg);
 
 438   //    token = typeString;
 
 439   //    stringValue = sBuffer.toString();
 
 442   //    public void htmlParserTester(String input) {
 
 443   //            int lineNumber = 1;
 
 444   //            int startLineNumber = 1;
 
 445   //            int startIndex = 0;
 
 448   //            boolean phpMode = false;
 
 449   //            boolean phpFound = false;
 
 451   //            phpList = new ArrayList();
 
 452   //            currentPHPString = 0;
 
 456   //                    while (i < input.length()) {
 
 457   //                            ch = input.charAt(i++);
 
 461   //                            if ((!phpMode) && ch == '<') {
 
 462   //                                    ch2 = input.charAt(i++);
 
 464   //                                            ch2 = input.charAt(i++);
 
 465   //                                            if (Character.isWhitespace(ch2)) {
 
 470   //                                                    startLineNumber = lineNumber;
 
 472   //                                            } else if (ch2 == 'p') {
 
 473   //                                                    ch2 = input.charAt(i++);
 
 475   //                                                            ch2 = input.charAt(i++);
 
 480   //                                                                    startLineNumber = lineNumber;
 
 486   //                                            } else if (ch2 == 'P') {
 
 487   //                                                    ch2 = input.charAt(i++);
 
 489   //                                                            ch2 = input.charAt(i++);
 
 494   //                                                                    startLineNumber = lineNumber;
 
 507   //                                    if (ch == '/' && i < input.length()) {
 
 508   //                                            ch2 = input.charAt(i++);
 
 510   //                                                    while (i < input.length()) {
 
 511   //                                                            ch = input.charAt(i++);
 
 512   //                                                            if (ch == '?' && i < input.length()) {
 
 513   //                                                                    ch2 = input.charAt(i++);
 
 522   //                                                                                            startLineNumber));
 
 526   //                                                            } else if (ch == '\n') {
 
 532   //                                            } else if (ch2 == '*') {
 
 533   //                                                    // multi-line comment
 
 534   //                                                    while (i < input.length()) {
 
 535   //                                                            ch = input.charAt(i++);
 
 538   //                                                            } else if (ch == '*' && i < input.length()) {
 
 539   //                                                                    ch2 = input.charAt(i++);
 
 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++);
 
 560   //                                                                                    input.substring(startIndex, i - 2),
 
 561   //                                                                                    startLineNumber));
 
 565   //                                                    } else if (ch == '\n') {
 
 571   //                                    } else if (ch == '"') {
 
 573   //                                            while (i < input.length()) {
 
 574   //                                                    ch = input.charAt(i++);
 
 578   //                                                            ch == '\\' && i < input.length()) { // escape
 
 580   //                                                    } else if (ch == '"') {
 
 585   //                                    } else if (ch == '\'') {
 
 587   //                                            while (i < input.length()) {
 
 588   //                                                    ch = input.charAt(i++);
 
 592   //                                                            ch == '\\' && i < input.length()) { // escape
 
 594   //                                                    } else if (ch == '\'') {
 
 601   //                                    if (ch == '?' && i < input.length()) {
 
 602   //                                            ch2 = input.charAt(i++);
 
 608   //                                                                    input.substring(startIndex, i - 2),
 
 609   //                                                                    startLineNumber));
 
 619   //                                    "No PHP source code found.",
 
 625   //                                            "Open PHP tag at end of file.",
 
 630   //                                                    input.substring(startIndex, i - 2),
 
 631   //                                                    startLineNumber));
 
 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) {
 
 639   //                            //          System.out.println(temp.substring(startIndx)+"?>");
 
 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());
 
 648   //            } catch (CoreException e) {
 
 652   public void phpParserTester(String s, int rowCount) throws CoreException {
 
 655       if (phpList.size() != 0) {
 
 656         this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
 
 659     this.token = TokenNameEOF;
 
 661     //    this.rowCount = rowCount;
 
 662     //    this.columnCount = 0;
 
 665     scanner.setSource(s.toCharArray());
 
 666     scanner.setPHPMode(true);
 
 670         if (token != TokenNameEOF && token != TokenNameERROR) {
 
 673         if (token != TokenNameEOF) {
 
 674           if (token == TokenNameERROR) {
 
 675             throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
 
 677           if (token == TokenNameRPAREN) {
 
 678             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
 680           if (token == TokenNameRBRACE) {
 
 681             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
 683           if (token == TokenNameRBRACKET) {
 
 684             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
 687           if (token == TokenNameLPAREN) {
 
 688             throwSyntaxError("Read character '('; end-of-file not reached.");
 
 690           if (token == TokenNameLBRACE) {
 
 691             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
 693           if (token == TokenNameLBRACKET) {
 
 694             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
 697           throwSyntaxError("End-of-file not reached.");
 
 700       } catch (SyntaxError err) {
 
 704           //   setMarker(err.getMessage(), err.getLine(), ERROR);
 
 705           setMarker(err.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
 
 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) {
 
 716         if (token == TokenNameEOF || token == TokenNameERROR) {
 
 723   public void init(String s) {
 
 725     this.token = TokenNameEOF;
 
 727     //    this.rowCount = 1;
 
 728     //    this.columnCount = 0;
 
 730     this.phpMode = false;
 
 731     /* scanner initialization */
 
 732     scanner.setSource(s.toCharArray());
 
 733     scanner.setPHPMode(false);
 
 736   protected void initialize(boolean phpMode) {
 
 737     compilationUnit = null;
 
 738     referenceContext = null;
 
 740     this.token = TokenNameEOF;
 
 742     //    this.rowCount = 1;
 
 743     //    this.columnCount = 0;
 
 745     this.phpMode = phpMode;
 
 746     scanner.setPHPMode(phpMode);
 
 749    * Parses a string with php tags
 
 750    * i.e. '<body> <?php phpinfo() ?> </body>'
 
 752   public void parse(String s) throws CoreException {
 
 758          * Parses a string with php tags
 
 759          * i.e. '<body> <?php phpinfo() ?> </body>'
 
 761   protected void parse() throws CoreException {
 
 765         if (token != TokenNameEOF && token != TokenNameERROR) {
 
 768         if (token != TokenNameEOF) {
 
 769           if (token == TokenNameERROR) {
 
 770             throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
 
 772           if (token == TokenNameRPAREN) {
 
 773             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
 775           if (token == TokenNameRBRACE) {
 
 776             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
 778           if (token == TokenNameRBRACKET) {
 
 779             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
 782           if (token == TokenNameLPAREN) {
 
 783             throwSyntaxError("Read character '('; end-of-file not reached.");
 
 785           if (token == TokenNameLBRACE) {
 
 786             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
 788           if (token == TokenNameLBRACKET) {
 
 789             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
 792           throwSyntaxError("End-of-file not reached.");
 
 795       } catch (SyntaxError sytaxErr1) {
 
 796         // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
 
 797         setMarker(sytaxErr1.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
 
 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) {
 
 808           if (token == TokenNameEOF || token == TokenNameERROR) {
 
 811         } catch (SyntaxError sytaxErr2) {
 
 812           //    setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
 
 813           setMarker(sytaxErr2.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
 
 821   public PHPOutlineInfo parseInfo(Object parent, String s) {
 
 822     PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
 
 823     //    Stack stack = new Stack();
 
 824     //    stack.push(outlineInfo.getDeclarations());
 
 827     this.token = TokenNameEOF;
 
 829     //    this.rowCount = 1;
 
 830     //    this.columnCount = 0;
 
 832     this.phpMode = false;
 
 833     scanner.setSource(s.toCharArray());
 
 834     scanner.setPHPMode(false);
 
 838       parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
 
 839     } catch (CoreException e) {
 
 844   private boolean isVariable() {
 
 845     return token == TokenNameVariable || token == TokenNamethis;
 
 848   private void parseDeclarations(PHPOutlineInfo outlineInfo, OutlineableWithChildren current, boolean goBack) {
 
 850     //   PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
 
 851     PHPSegmentWithChildren temp;
 
 854     IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
 
 856       while (token != TokenNameEOF && token != TokenNameERROR) {
 
 857         if (token == TokenNameVariable) {
 
 858           ident = scanner.getCurrentIdentifierSource();
 
 859           outlineInfo.addVariable(new String(ident));
 
 861         } else if (token == TokenNamevar) {
 
 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);
 
 869             if (token != TokenNameSEMICOLON) {
 
 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)));
 
 879                   case TokenNameVariable :
 
 881                     current.add(new PHPVarDeclaration(current, variableName,
 
 882                     //                      chIndx - ident.length,
 
 883                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 885                   case TokenNameIdentifier :
 
 886                     current.add(new PHPVarDeclaration(current, variableName,
 
 887                     //                    chIndx - ident.length,
 
 888                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 890                   case TokenNameDoubleLiteral :
 
 891                     current.add(new PHPVarDeclaration(current, variableName + doubleNumber,
 
 892                     //   chIndx - ident.length,
 
 893                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 895                   case TokenNameIntegerLiteral :
 
 896                     current.add(new PHPVarDeclaration(current, variableName,
 
 897                     //                 chIndx - ident.length,
 
 898                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 900                   case TokenNameStringInterpolated :
 
 901                   case TokenNameStringLiteral :
 
 902                     current.add(new PHPVarDeclaration(current, variableName,
 
 903                     //              chIndx - ident.length,
 
 904                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 906                   case TokenNameStringConstant :
 
 907                     current.add(new PHPVarDeclaration(current, variableName,
 
 908                     //   chIndx - ident.length,
 
 909                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 912                     current.add(new PHPVarDeclaration(current, variableName,
 
 913                     //               chIndx - ident.length
 
 914                     scanner.getCurrentTokenStartPosition()));
 
 920               ident = scanner.getCurrentIdentifierSource();
 
 922               current.add(new PHPVarDeclaration(current, variableName,
 
 923               //          chIndx - ident.length
 
 924               scanner.getCurrentTokenStartPosition()));
 
 927         } else if (token == TokenNamefunction) {
 
 929           if (token == TokenNameAND) {
 
 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());
 
 940             parseDeclarations(outlineInfo, temp, true);
 
 942         } else if (token == TokenNameclass) {
 
 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());
 
 954             //skip tokens for classname, extends and others until we have the opening '{'
 
 955             while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) {
 
 958             parseDeclarations(outlineInfo, temp, true);
 
 961         } else if ((token == TokenNameLBRACE) || (token == TokenNameDOLLAR_LBRACE)) {
 
 964         } else if (token == TokenNameRBRACE) {
 
 967           if (counter == 0 && goBack) {
 
 970         } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) {
 
 971           ident = scanner.getCurrentTokenSource();
 
 974           int startPosition = scanner.getCurrentTokenStartPosition();
 
 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)));
 
 986     } catch (CoreException e) {
 
 987     } catch (SyntaxError sytaxErr) {
 
 989         //  setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
 
 990         setMarker(sytaxErr.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
 
 991       } catch (CoreException e) {
 
 996   private void statementList() throws CoreException {
 
 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)) {
 
1016   private void functionBody(MethodDeclaration methodDecl) throws CoreException {
 
1017     // '{' [statement-list] '}'
 
1018     if (token == TokenNameLBRACE) {
 
1021       throwSyntaxError("'{' expected in compound-statement.");
 
1023     if (token != TokenNameRBRACE) {
 
1026     if (token == TokenNameRBRACE) {
 
1027       methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1030       throwSyntaxError("'}' expected in compound-statement.");
 
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) {
 
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 '@'.");
 
1051     if (token == TokenNameinclude || token == TokenNameinclude_once) {
 
1053       if (token == TokenNameLPAREN) {
 
1055         if (token == TokenNameSEMICOLON) {
 
1058           if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
 
1059             throwSyntaxError("';' expected after 'include' or 'include_once'.");
 
1064         concatenationExpression();
 
1068     } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
 
1071       if (token == TokenNameLPAREN) {
 
1073         if (token == TokenNameSEMICOLON) {
 
1076           if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
 
1077             throwSyntaxError("';' expected after 'require' or 'require_once'.");
 
1082         concatenationExpression();
 
1085     } else if (token == TokenNameif) {
 
1087       if (token == TokenNameLPAREN) {
 
1090         throwSyntaxError("'(' expected after 'if' keyword.");
 
1093       if (token == TokenNameRPAREN) {
 
1096         throwSyntaxError("')' expected after 'if' condition.");
 
1101     } else if (token == TokenNameswitch) {
 
1103       if (token == TokenNameLPAREN) {
 
1106         throwSyntaxError("'(' expected after 'switch' keyword.");
 
1109       if (token == TokenNameRPAREN) {
 
1112         throwSyntaxError("')' expected after 'switch' condition.");
 
1116     } else if (token == TokenNamefor) {
 
1118       if (token == TokenNameLPAREN) {
 
1121         throwSyntaxError("'(' expected after 'for' keyword.");
 
1123       if (token == TokenNameSEMICOLON) {
 
1127         if (token == TokenNameSEMICOLON) {
 
1130           throwSyntaxError("';' expected after 'for'.");
 
1133       if (token == TokenNameSEMICOLON) {
 
1137         if (token == TokenNameSEMICOLON) {
 
1140           throwSyntaxError("';' expected after 'for'.");
 
1143       if (token == TokenNameRPAREN) {
 
1147         if (token == TokenNameRPAREN) {
 
1150           throwSyntaxError("')' expected after 'for'.");
 
1155     } else if (token == TokenNamewhile) {
 
1157       if (token == TokenNameLPAREN) {
 
1160         throwSyntaxError("'(' expected after 'while' keyword.");
 
1163       if (token == TokenNameRPAREN) {
 
1166         throwSyntaxError("')' expected after 'while' condition.");
 
1170     } else if (token == TokenNamedo) {
 
1172       if (token == TokenNameLBRACE) {
 
1175         throwSyntaxError("'{' expected after 'do' keyword.");
 
1177       if (token != TokenNameRBRACE) {
 
1180       if (token == TokenNameRBRACE) {
 
1183         throwSyntaxError("'}' expected after 'do' keyword.");
 
1185       if (token == TokenNamewhile) {
 
1187         if (token == TokenNameLPAREN) {
 
1190           throwSyntaxError("'(' expected after 'while' keyword.");
 
1193         if (token == TokenNameRPAREN) {
 
1196           throwSyntaxError("')' expected after 'while' condition.");
 
1199         throwSyntaxError("'while' expected after 'do' keyword.");
 
1201       if (token == TokenNameSEMICOLON) {
 
1204         if (token != TokenNameStopPHP) {
 
1205           throwSyntaxError("';' expected after do-while statement.");
 
1210     } else if (token == TokenNameforeach) {
 
1212       if (token == TokenNameLPAREN) {
 
1215         throwSyntaxError("'(' expected after 'foreach' keyword.");
 
1218       if (token == TokenNameas) {
 
1221         throwSyntaxError("'as' expected after 'foreach' exxpression.");
 
1224       if (token == TokenNameEQUAL_GREATER) {
 
1228       if (token == TokenNameRPAREN) {
 
1231         throwSyntaxError("')' expected after 'foreach' expression.");
 
1236     } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
 
1238       if (token != TokenNameSEMICOLON) {
 
1241       if (token == TokenNameSEMICOLON) {
 
1244         if (token != TokenNameStopPHP) {
 
1245           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
 
1251     } else if (token == TokenNameecho) {
 
1254       if (token == TokenNameSEMICOLON) {
 
1257         if (token != TokenNameStopPHP) {
 
1258           throwSyntaxError("';' expected after 'echo' statement.");
 
1263       //    } else if (token == TokenNameprint) {
 
1266       //      if (token == TokenNameSEMICOLON) {
 
1269       //        if (token != TokenNameStopPHP) {
 
1270       //          throwSyntaxError("';' expected after 'print' statement.");
 
1276     } else if (token == TokenNameglobal || token == TokenNamestatic) {
 
1279       if (token == TokenNameSEMICOLON) {
 
1282         if (token != TokenNameStopPHP) {
 
1283           throwSyntaxError("';' expected after 'global' or 'static' statement.");
 
1289       //      } else if (token == TokenNameunset) {
 
1291       //        if (token == TokenNameARGOPEN) {
 
1294       //          throwSyntaxError("'(' expected after 'unset' keyword.");
 
1297       //        if (token == TokenNameARGCLOSE) {
 
1300       //          throwSyntaxError("')' expected after 'unset' statement.");
 
1302       //        if (token == TokenNameSEMICOLON) {
 
1305       //          if (token != TokenNameStopPHP) {
 
1306       //            throwSyntaxError("';' expected after 'unset' statement.");
 
1312       //      } else if (token == TokenNameexit || token == TokenNamedie) {
 
1314       //        if (token != TokenNameSEMICOLON) {
 
1317       //        if (token == TokenNameSEMICOLON) {
 
1320       //          if (token != TokenNameStopPHP) {
 
1321       //            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
 
1327     } else if (token == TokenNamedefine) {
 
1329       if (token == TokenNameLPAREN) {
 
1332         throwSyntaxError("'(' expected after 'define' keyword.");
 
1335       if (token == TokenNameCOMMA) {
 
1338         throwSyntaxError("',' expected after first 'define' constant.");
 
1341       if (token == TokenNameCOMMA) {
 
1345       if (token == TokenNameRPAREN) {
 
1348         throwSyntaxError("')' expected after 'define' statement.");
 
1350       if (token == TokenNameSEMICOLON) {
 
1353         if (token != TokenNameStopPHP) {
 
1354           throwSyntaxError("';' expected after 'define' statement.");
 
1359     } else if (token == TokenNamefunction) {
 
1360       MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
 
1361       methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1363       functionDefinition(methodDecl);
 
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);
 
1372         pushOnAstStack(typeDecl);
 
1374         classDeclarator(typeDecl);
 
1375         classBody(typeDecl);
 
1382       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
 
1383     } else if (token == TokenNameLBRACE) {
 
1385       if (token != TokenNameRBRACE) {
 
1388       if (token == TokenNameRBRACE) {
 
1392         throwSyntaxError("'}' expected.");
 
1395       if (token != TokenNameSEMICOLON) {
 
1398       if (token == TokenNameSEMICOLON) {
 
1402         if (token != TokenNameStopPHP && token != TokenNameEOF) {
 
1403           throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
 
1410   private void classDeclarator(TypeDeclaration typeDecl) throws CoreException {
 
1412     //identifier 'extends' identifier
 
1414     if (token == TokenNameIdentifier) {
 
1415       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1416       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1417       typeDecl.name = scanner.getCurrentIdentifierSource();
 
1419       if (token == TokenNameextends) {
 
1422           if (token == TokenNameIdentifier) {
 
1425             reportSyntaxError("Class name expected after keyword 'extends'.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
 
1426             //            throwSyntaxError("ClassDeclaration name expected after keyword 'extends'.");
 
1428         } while (token == TokenNameCOMMA);
 
1431       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1432       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1434       if (token > TokenNameKEYWORD) {
 
1435         typeDecl.name = scanner.getCurrentIdentifierSource();
 
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 + "].");
 
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'.");
 
1448   private void classBody(TypeDeclaration typeDecl) throws CoreException {
 
1449     //'{' [class-element-list] '}'
 
1450     if (token == TokenNameLBRACE) {
 
1452       if (token != TokenNameRBRACE) {
 
1455       if (token == TokenNameRBRACE) {
 
1456         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1459         throwSyntaxError("'}' expected at end of class body.");
 
1462       throwSyntaxError("'{' expected at start of class body.");
 
1466   private void classElementList() throws CoreException {
 
1469     } while (token == TokenNamefunction || token == TokenNamevar);
 
1472   private void classElement() throws CoreException {
 
1474     //function-definition
 
1475     if (token == TokenNamefunction) {
 
1476       MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
 
1477       methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1479       functionDefinition(methodDecl);
 
1480     } else if (token == TokenNamevar) {
 
1484       throwSyntaxError("'function' or 'var' expected.");
 
1488   private void classProperty() throws CoreException {
 
1489     //'var' variable ';'
 
1490     //'var' variable '=' constant ';'
 
1492       if (token == TokenNameVariable) {
 
1494         if (token == TokenNameEQUAL) {
 
1499         if (token == TokenNamethis) {
 
1500           throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
 
1502         throwSyntaxError("Variable expected after keyword 'var'.");
 
1504       if (token != TokenNameCOMMA) {
 
1509     if (token == TokenNameSEMICOLON) {
 
1512       throwSyntaxError("';' expected after variable declaration.");
 
1516   private void functionDefinition(MethodDeclaration methodDecl) throws CoreException {
 
1518       compilationUnit.types.add(methodDecl);
 
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 };
 
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;
 
1533     functionDeclarator(methodDecl);
 
1534     functionBody(methodDecl);
 
1537   private void functionDeclarator(MethodDeclaration methodDecl) throws CoreException {
 
1538     //identifier '(' [parameter-list] ')'
 
1539     if (token == TokenNameAND) {
 
1542     if (token == TokenNameIdentifier) {
 
1543       methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1544       methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1545       methodDecl.selector = scanner.getCurrentIdentifierSource();
 
1547       if (token == TokenNameLPAREN) {
 
1550         throwSyntaxError("'(' expected in function declaration.");
 
1552       if (token != TokenNameRPAREN) {
 
1555       if (token != TokenNameRPAREN) {
 
1556         throwSyntaxError("')' expected in function declaration.");
 
1558         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
 
1562       if (token > TokenNameKEYWORD) {
 
1563         throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
 
1565       throwSyntaxError("Function name expected after keyword 'function'.");
 
1569   private void parameterList() throws CoreException {
 
1570     //parameter-declaration
 
1571     //parameter-list ',' parameter-declaration
 
1573       parameterDeclaration();
 
1574       if (token != TokenNameCOMMA) {
 
1581   private void parameterDeclaration() throws CoreException {
 
1583     //variable-reference
 
1584     if (token == TokenNameAND) {
 
1589         throwSyntaxError("Variable expected after reference operator '&'.");
 
1592     //variable '=' constant
 
1593     if (token == TokenNameVariable) {
 
1595       if (token == TokenNameEQUAL) {
 
1601     if (token == TokenNamethis) {
 
1602       throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
 
1606   private void labeledStatementList() throws CoreException {
 
1607     if (token != TokenNamecase && token != TokenNamedefault) {
 
1608       throwSyntaxError("'case' or 'default' expected.");
 
1611       if (token == TokenNamecase) {
 
1613         expression(); //constant();
 
1614         if (token == TokenNameCOLON) {
 
1616           if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
 
1620         } else if (token == TokenNameSEMICOLON) {
 
1622           //            "':' expected after 'case' keyword (Found token: "
 
1623           //              + scanner.toStringAction(token)
 
1628             "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")",
 
1629             scanner.getCurrentTokenStartPosition(),
 
1630             scanner.getCurrentTokenEndPosition(),
 
1633           if (token == TokenNamecase) { // empty case statement ?
 
1638           throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
 
1640       } else { // TokenNamedefault
 
1642         if (token == TokenNameCOLON) {
 
1646           throwSyntaxError("':' character after 'default' expected.");
 
1649     } while (token == TokenNamecase || token == TokenNamedefault);
 
1652   //  public void labeledStatement() {
 
1653   //    if (token == TokenNamecase) {
 
1656   //      if (token == TokenNameDDOT) {
 
1660   //        throwSyntaxError("':' character after 'case' constant expected.");
 
1663   //    } else if (token == TokenNamedefault) {
 
1665   //      if (token == TokenNameDDOT) {
 
1669   //        throwSyntaxError("':' character after 'default' expected.");
 
1675   //  public void expressionStatement() {
 
1678   //  private void inclusionStatement() {
 
1681   //  public void compoundStatement() {
 
1684   //  public void selectionStatement() {
 
1687   //  public void iterationStatement() {
 
1690   //  public void jumpStatement() {
 
1693   //  public void outputStatement() {
 
1696   //  public void scopeStatement() {
 
1699   //  public void flowStatement() {
 
1702   //  public void definitionStatement() {
 
1705   private void ifStatement() throws CoreException {
 
1706     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
 
1707     if (token == TokenNameCOLON) {
 
1709       if (token != TokenNameendif) {
 
1712           case TokenNameelse :
 
1714             if (token == TokenNameCOLON) {
 
1716               if (token != TokenNameendif) {
 
1720               if (token == TokenNameif) { //'else if'
 
1722                 elseifStatementList();
 
1724                 throwSyntaxError("':' expected after 'else'.");
 
1728           case TokenNameelseif :
 
1730             elseifStatementList();
 
1735       if (token != TokenNameendif) {
 
1736         throwSyntaxError("'endif' expected.");
 
1739       if (token != TokenNameSEMICOLON) {
 
1740         throwSyntaxError("';' expected after if-statement.");
 
1744       // statement [else-statement]
 
1745       statement(TokenNameEOF);
 
1746       if (token == TokenNameelseif) {
 
1748         if (token == TokenNameLPAREN) {
 
1751           throwSyntaxError("'(' expected after 'elseif' keyword.");
 
1754         if (token == TokenNameRPAREN) {
 
1757           throwSyntaxError("')' expected after 'elseif' condition.");
 
1760       } else if (token == TokenNameelse) {
 
1762         statement(TokenNameEOF);
 
1767   private void elseifStatementList() throws CoreException {
 
1771         case TokenNameelse :
 
1773           if (token == TokenNameCOLON) {
 
1775             if (token != TokenNameendif) {
 
1780             if (token == TokenNameif) { //'else if'
 
1783               throwSyntaxError("':' expected after 'else'.");
 
1787         case TokenNameelseif :
 
1796   private void elseifStatement() throws CoreException {
 
1797     if (token == TokenNameLPAREN) {
 
1800       if (token != TokenNameRPAREN) {
 
1801         throwSyntaxError("')' expected in else-if-statement.");
 
1804       if (token != TokenNameCOLON) {
 
1805         throwSyntaxError("':' expected in else-if-statement.");
 
1808       if (token != TokenNameendif) {
 
1814   private void switchStatement() throws CoreException {
 
1815     if (token == TokenNameCOLON) {
 
1816       // ':' [labeled-statement-list] 'endswitch' ';'
 
1818       labeledStatementList();
 
1819       if (token != TokenNameendswitch) {
 
1820         throwSyntaxError("'endswitch' expected.");
 
1823       if (token != TokenNameSEMICOLON) {
 
1824         throwSyntaxError("';' expected after switch-statement.");
 
1828       // '{' [labeled-statement-list] '}'
 
1829       if (token != TokenNameLBRACE) {
 
1830         throwSyntaxError("'{' expected in switch statement.");
 
1833       if (token != TokenNameRBRACE) {
 
1834         labeledStatementList();
 
1836       if (token != TokenNameRBRACE) {
 
1837         throwSyntaxError("'}' expected in switch statement.");
 
1844   private void forStatement() throws CoreException {
 
1845     if (token == TokenNameCOLON) {
 
1848       if (token != TokenNameendfor) {
 
1849         throwSyntaxError("'endfor' expected.");
 
1852       if (token != TokenNameSEMICOLON) {
 
1853         throwSyntaxError("';' expected after for-statement.");
 
1857       statement(TokenNameEOF);
 
1861   private void whileStatement() throws CoreException {
 
1862     // ':' statement-list 'endwhile' ';'
 
1863     if (token == TokenNameCOLON) {
 
1866       if (token != TokenNameendwhile) {
 
1867         throwSyntaxError("'endwhile' expected.");
 
1870       if (token != TokenNameSEMICOLON) {
 
1871         throwSyntaxError("';' expected after while-statement.");
 
1875       statement(TokenNameEOF);
 
1879   private void foreachStatement() throws CoreException {
 
1880     if (token == TokenNameCOLON) {
 
1883       if (token != TokenNameendforeach) {
 
1884         throwSyntaxError("'endforeach' expected.");
 
1887       if (token != TokenNameSEMICOLON) {
 
1888         throwSyntaxError("';' expected after foreach-statement.");
 
1892       statement(TokenNameEOF);
 
1896   private void exitStatus() throws CoreException {
 
1897     if (token == TokenNameLPAREN) {
 
1900       throwSyntaxError("'(' expected in 'exit-status'.");
 
1902     if (token != TokenNameRPAREN) {
 
1905     if (token == TokenNameRPAREN) {
 
1908       throwSyntaxError("')' expected after 'exit-status'.");
 
1912   private void expressionList() throws CoreException {
 
1915       if (token == TokenNameCOMMA) {
 
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) == ';') {
 
1930     //      expression.append(str.charAt(i));
 
1933     //    if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
 
1936     logicalinclusiveorExpression();
 
1937     //      while (token != TokenNameSEMICOLON) {
 
1943   private void postfixExpression() throws CoreException {
 
1946     boolean castFlag = false;
 
1947     boolean arrayFlag = false;
 
1953       case TokenNamenull :
 
1956       case TokenNamefalse :
 
1959       case TokenNametrue :
 
1962       case TokenNameStringConstant :
 
1965       case TokenNameHEREDOC :
 
1966       case TokenNameStringInterpolated :
 
1967       case TokenNameStringLiteral :
 
1970       case TokenNameLPAREN :
 
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)) {
 
1981               if (PHP_TYPES[i].equals("array")) {
 
1991           if (arrayFlag && token == TokenNameLPAREN) {
 
1993             if (token == TokenNameRPAREN) {
 
1997               if (token != TokenNameRPAREN) {
 
1998                 throwSyntaxError(") expected after 'array('.");
 
2002           if (token != TokenNameRPAREN) {
 
2003             throwSyntaxError(") expected after cast-type '" + str + "'.");
 
2011         if (token != TokenNameRPAREN) {
 
2012           throwSyntaxError(") expected in postfix-expression.");
 
2016       case TokenNameDoubleLiteral :
 
2019       case TokenNameIntegerLiteral :
 
2022       case TokenNameDOLLAR_LBRACE :
 
2025         if (token != TokenNameRBRACE) {
 
2026           throwSyntaxError("'}' expected after indirect variable token '${'.");
 
2030       case TokenNameVariable :
 
2031       case TokenNamethis :
 
2032         ident = scanner.getCurrentIdentifierSource();
 
2034         if (token == TokenNameLBRACE) {
 
2037           if (token != TokenNameRBRACE) {
 
2038             throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression.");
 
2041         } else if (token == TokenNameLPAREN) {
 
2043           if (token != TokenNameRPAREN) {
 
2045             if (token != TokenNameRPAREN) {
 
2046               throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression.");
 
2052       case TokenNameIdentifier :
 
2053         ident = scanner.getCurrentIdentifierSource();
 
2055         if (token == TokenNameLPAREN) {
 
2057           if (token != TokenNameRPAREN) {
 
2059             if (token != TokenNameRPAREN) {
 
2061                 "')' expected after identifier '" + new String(ident) + "' in postfix-expression." + "(Found token: " + scanner.toStringAction(token) + ")");
 
2067       case TokenNameprint :
 
2070         //        if (token == TokenNameSEMICOLON) {
 
2073         //          if (token != TokenNameStopPHP) {
 
2074         //            throwSyntaxError("';' expected after 'print' statement.");
 
2079       case TokenNamelist :
 
2081         if (token == TokenNameLPAREN) {
 
2083           if (token == TokenNameCOMMA) {
 
2087           if (token != TokenNameRPAREN) {
 
2088             throwSyntaxError("')' expected after 'list' keyword.");
 
2091           //          if (token == TokenNameSET) {
 
2093           //            logicalinclusiveorExpression();
 
2096           throwSyntaxError("'(' expected after 'list' keyword.");
 
2099         //      case TokenNameexit :
 
2101         //        if (token != TokenNameSEMICOLON) {
 
2104         //        if (token == TokenNameSEMICOLON) {
 
2107         //          if (token != TokenNameStopPHP) {
 
2108         //            throwSyntaxError("';' expected after 'exit' expression.");
 
2113         //      case TokenNamedie :
 
2115         //        if (token != TokenNameSEMICOLON) {
 
2118         //        if (token == TokenNameSEMICOLON) {
 
2121         //          if (token != TokenNameStopPHP) {
 
2122         //            throwSyntaxError("';' expected after 'die' expression.");
 
2127         //      case TokenNamearray :
 
2129         //        if (token == TokenNameARGOPEN) {
 
2131         //          if (token == TokenNameCOMMA) {
 
2134         //          expressionList();
 
2135         //          if (token != TokenNameARGCLOSE) {
 
2136         //            throwSyntaxError("')' expected after 'list' keyword.");
 
2139         //          if (token == TokenNameSET) {
 
2141         //            logicalinclusiveorExpression();
 
2144         //          throwSyntaxError("'(' expected after 'list' keyword.");
 
2148     boolean while_flag = true;
 
2151         case TokenNameLBRACKET :
 
2154           if (token != TokenNameRBRACKET) {
 
2155             throwSyntaxError("] expected in postfix-expression.");
 
2159         case TokenNameCOLON_COLON : // ::
 
2160         case TokenNameMINUS_GREATER : // ->
 
2162           if (token > TokenNameKEYWORD) {
 
2163             ident = scanner.getCurrentIdentifierSource();
 
2165             //              "Avoid using keyword '"
 
2166             //                + new String(ident)
 
2167             //                + "' as variable name.",
 
2171               "Avoid using keyword '" + new String(ident) + "' as variable name.",
 
2172               scanner.getCurrentTokenStartPosition(),
 
2173               scanner.getCurrentTokenEndPosition(),
 
2177             case TokenNameVariable :
 
2178               ident = scanner.getCurrentIdentifierSource();
 
2180               //              if (token == TokenNameARGOPEN) {
 
2182               //                expressionList();
 
2183               //                if (token != TokenNameARGCLOSE) {
 
2184               //                  throwSyntaxError(") expected after variable '" + ident + "'.");
 
2189             case TokenNameIdentifier :
 
2190               //ident = scanner.getCurrentIdentifierSource();
 
2193             case TokenNameLBRACE :
 
2196               if (token != TokenNameRBRACE) {
 
2197                 throwSyntaxError("} expected in postfix-expression.");
 
2202               throwSyntaxError("Syntax error after '->' token.");
 
2203           } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
 
2204               if (token == TokenNameLBRACKET) {
 
2207                 if (token != TokenNameRBRACKET) {
 
2208                   throwSyntaxError("] expected after '->'.");
 
2211               } else if (token == TokenNameLPAREN) {
 
2214                 if (token != TokenNameRPAREN) {
 
2215                   throwSyntaxError(") expected after '->'.");
 
2218               } else if (token == TokenNameLBRACE) {
 
2221                 if (token != TokenNameRBRACE) {
 
2222                   throwSyntaxError("} expected after '->'.");
 
2228         case TokenNamePLUS_PLUS :
 
2231         case TokenNameMINUS_MINUS :
 
2242   private void unaryExpression() throws CoreException {
 
2244       case TokenNamePLUS_PLUS :
 
2248       case TokenNameMINUS_MINUS :
 
2252         // '@' '&' '*' '+' '-' '~' '!'
 
2255         if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) {
 
2256           statement(TokenNameAT);
 
2258           postfixExpression(); //  castExpression();
 
2265       case TokenNameMULTIPLY :
 
2269       case TokenNamePLUS :
 
2273       case TokenNameMINUS :
 
2277       case TokenNameTWIDDLE :
 
2286         postfixExpression();
 
2290   private void castExpression() throws CoreException {
 
2291     //    if (token == TokenNameARGOPEN) {
 
2294     //      if (token != TokenNameARGCLOSE) {
 
2295     //        throwSyntaxError(") expected after cast-expression.");
 
2302   private void assignExpression() throws CoreException {
 
2304     if (token == TokenNameEQUAL) { // =
 
2306       logicalinclusiveorExpression();
 
2307     } else if (token == TokenNameDOT_EQUAL) { // .=
 
2309       logicalinclusiveorExpression();
 
2310     } else if (token == TokenNameEQUAL_GREATER) { // =>
 
2312       logicalinclusiveorExpression();
 
2313     } else if (token == TokenNamePLUS_EQUAL) { // +=
 
2315       logicalinclusiveorExpression();
 
2316     } else if (token == TokenNameMINUS_EQUAL) { // -=
 
2318       logicalinclusiveorExpression();
 
2319     } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
 
2321       logicalinclusiveorExpression();
 
2322     } else if (token == TokenNameDIVIDE_EQUAL) { // *=
 
2324       logicalinclusiveorExpression();
 
2325     } else if (token == TokenNameREMAINDER_EQUAL) { // %=
 
2327       logicalinclusiveorExpression();
 
2328     } else if (token == TokenNameAND_EQUAL) { // &=
 
2330       logicalinclusiveorExpression();
 
2331     } else if (token == TokenNameOR_EQUAL) { // |=
 
2333       logicalinclusiveorExpression();
 
2334     } else if (token == TokenNameXOR_EQUAL) { // ^=
 
2336       logicalinclusiveorExpression();
 
2337     } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
 
2339       logicalinclusiveorExpression();
 
2340     } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
 
2342       logicalinclusiveorExpression();
 
2343     } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
 
2345       logicalinclusiveorExpression();
 
2349   private void multiplicativeExpression() throws CoreException {
 
2352       if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
 
2359   private void concatenationExpression() throws CoreException {
 
2361       multiplicativeExpression();
 
2362       if (token != TokenNameDOT) {
 
2369   private void additiveExpression() throws CoreException {
 
2371       concatenationExpression();
 
2372       if (token != TokenNamePLUS && token != TokenNameMINUS) {
 
2379   private void shiftExpression() throws CoreException {
 
2381       additiveExpression();
 
2382       if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
 
2389   private void relationalExpression() throws CoreException {
 
2392       if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
 
2399   private void identicalExpression() throws CoreException {
 
2401       relationalExpression();
 
2402       if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
 
2409   private void equalityExpression() throws CoreException {
 
2411       identicalExpression();
 
2412       if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
 
2419   private void ternaryExpression() throws CoreException {
 
2420     equalityExpression();
 
2421     if (token == TokenNameQUESTION) {
 
2424       if (token == TokenNameCOLON) {
 
2428         throwSyntaxError("':' expected in ternary operator '? :'.");
 
2433   private void andExpression() throws CoreException {
 
2435       ternaryExpression();
 
2436       if (token != TokenNameAND) {
 
2443   private void exclusiveorExpression() throws CoreException {
 
2446       if (token != TokenNameXOR) {
 
2453   private void inclusiveorExpression() throws CoreException {
 
2455       exclusiveorExpression();
 
2456       if (token != TokenNameOR) {
 
2463   private void booleanandExpression() throws CoreException {
 
2465       inclusiveorExpression();
 
2466       if (token != TokenNameAND_AND) {
 
2473   private void booleanorExpression() throws CoreException {
 
2475       booleanandExpression();
 
2476       if (token != TokenNameOR_OR) {
 
2483   private void logicalandExpression() throws CoreException {
 
2485       booleanorExpression();
 
2486       if (token != TokenNameAND) {
 
2493   private void logicalexclusiveorExpression() throws CoreException {
 
2495       logicalandExpression();
 
2496       if (token != TokenNameXOR) {
 
2503   private void logicalinclusiveorExpression() throws CoreException {
 
2505       logicalexclusiveorExpression();
 
2506       if (token != TokenNameOR) {
 
2513   //  public void assignmentExpression() {
 
2514   //    if (token == TokenNameVARIABLE) {
 
2516   //      if (token == TokenNameSET) {
 
2518   //        logicalinclusiveorExpression();
 
2521   //      logicalinclusiveorExpression();
 
2525   private void variableList() throws CoreException {
 
2528       if (token == TokenNameCOMMA) {
 
2536   private void variable() throws CoreException {
 
2537     if (token == TokenNameDOLLAR_LBRACE) {
 
2541       if (token != TokenNameRBRACE) {
 
2542         throwSyntaxError("'}' expected after indirect variable token '${'.");
 
2546       if (token == TokenNameVariable) {
 
2548         if (token == TokenNameLBRACKET) {
 
2551           if (token != TokenNameRBRACKET) {
 
2552             throwSyntaxError("']' expected in variable-list.");
 
2555         } else if (token == TokenNameEQUAL) {
 
2560         throwSyntaxError("$-variable expected in variable-list.");
 
2566    * It will look for a value (after a '=' for example)
 
2567    * @throws CoreException
 
2569   private void constant() throws CoreException {
 
2572       case TokenNamePLUS :
 
2575           case TokenNameDoubleLiteral :
 
2578           case TokenNameIntegerLiteral :
 
2582             throwSyntaxError("Constant expected after '+' presign.");
 
2585       case TokenNameMINUS :
 
2588           case TokenNameDoubleLiteral :
 
2591           case TokenNameIntegerLiteral :
 
2595             throwSyntaxError("Constant expected after '-' presign.");
 
2598       case TokenNamenull :
 
2601       case TokenNamefalse :
 
2604       case TokenNametrue :
 
2607       case TokenNameIdentifier :
 
2608         //   ident = identifier;
 
2609         char[] ident = scanner.getCurrentIdentifierSource();
 
2611         if (token == TokenNameLPAREN) {
 
2613           if (token != TokenNameRPAREN) {
 
2615             if (token != TokenNameRPAREN) {
 
2616               throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression.");
 
2622       case TokenNameStringLiteral :
 
2625       case TokenNameStringConstant :
 
2628       case TokenNameStringInterpolated :
 
2631       case TokenNameDoubleLiteral :
 
2634       case TokenNameIntegerLiteral :
 
2638         throwSyntaxError("Constant expected.");
 
2642   public void reportSyntaxError() { //int act, int currentKind, int stateStackTop) {
 
2644     /* remember current scanner position */
 
2645     int startPos = scanner.startPosition;
 
2646     int currentPos = scanner.currentPosition;
 
2648     //          String[] expectings;
 
2649     //          String tokenName = name[symbol_index[currentKind]];
 
2651     //fetch all "accurate" possible terminals that could recover the error
 
2652     //          int start, end = start = asi(stack[stateStackTop]);
 
2653     //          while (asr[end] != 0)
 
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]]];
 
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;
 
2670     //                                  tokenSource = this.scanner.getCurrentTokenSource();
 
2671     //                          } catch (Exception e) {
 
2672     //                                  tokenSource = new char[] {};
 
2674     //                          problemReporter().parseError(
 
2675     //                                  this.scanner.startPosition, 
 
2676     //                                  this.scanner.currentPosition - 1, 
 
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]);
 
2710     //                                          case TokenNameRBRACE :
 
2711     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
 
2714     //                                                  char[] tokenSource;
 
2716     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
 
2717     //                                                  } catch (Exception e) {
 
2718     //                                                          tokenSource = new char[] {};
 
2720     //                                                  problemReporter().parseError(
 
2721     //                                                          this.scanner.startPosition, 
 
2722     //                                                          this.scanner.currentPosition - 1, 
 
2726     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
 
2731       tokenSource = this.scanner.getCurrentTokenSource();
 
2732     } catch (Exception e) {
 
2733       tokenSource = new char[] {
 
2736     //                          problemReporter().parseError(
 
2737     //                                  this.scanner.startPosition, 
 
2738     //                                  this.scanner.currentPosition - 1, 
 
2742     this.checkAndReportBracketAnomalies(problemReporter());
 
2745     /* reset scanner where it was */
 
2746     scanner.startPosition = startPos;
 
2747     scanner.currentPosition = currentPos;
 
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;
 
2754   protected int[] nestedMethod; //the ptr is nestedType
 
2755   protected int nestedType, dimensions;
 
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];
 
2764   public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
 
2765   protected ReferenceContext referenceContext;
 
2766   protected ProblemReporter problemReporter;
 
2767   //  protected CompilationResult compilationResult;
 
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.
 
2774   public ProblemReporter problemReporter() {
 
2775     if (scanner.recordLineSeparator) {
 
2776       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
 
2778     problemReporter.referenceContext = referenceContext;
 
2779     return problemReporter;
 
2782    * Reconsider the entire source looking for inconsistencies in {} () []
 
2784   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
 
2786     scanner.wasAcr = false;
 
2787     boolean anomaliesDetected = false;
 
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
 
2800           // ---------Consume white space and handles startPosition---------
 
2801           boolean isWhiteSpace;
 
2803             scanner.startPosition = scanner.currentPosition;
 
2804             //                                          if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
2805             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
 
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();
 
2813             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
 
2815           } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
 
2817           // -------consume token until } is found---------
 
2819           switch (scanner.currentCharacter) {
 
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);
 
2827                 leftPositions[CurlyBracket][index] = scanner.startPosition;
 
2828                 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
 
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);
 
2838                 rightPositions[CurlyBracket][index] = scanner.startPosition;
 
2839                 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
 
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);
 
2849                 leftPositions[RoundBracket][index] = scanner.startPosition;
 
2850                 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
 
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);
 
2860                 rightPositions[RoundBracket][index] = scanner.startPosition;
 
2861                 rightDepths[RoundBracket][index] = --depths[RoundBracket];
 
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);
 
2871                 leftPositions[SquareBracket][index] = scanner.startPosition;
 
2872                 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
 
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);
 
2882                 rightPositions[SquareBracket][index] = scanner.startPosition;
 
2883                 rightDepths[SquareBracket][index] = --depths[SquareBracket];
 
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();
 
2895                   if (scanner.withoutUnicodePtr != 0) {
 
2896                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
2900                 scanner.getNextChar('\'');
 
2903             case '"' : // consume next character
 
2904               scanner.unicodeAsBackSlash = false;
 
2905               //                                                        if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
2906               //                                                                scanner.getNextUnicodeChar();
 
2908               if (scanner.withoutUnicodePtr != 0) {
 
2909                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
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
 
2918                 if (scanner.currentCharacter == '\n') {
 
2919                   break; // the string cannot go further that the line
 
2921                 if (scanner.currentCharacter == '\\') {
 
2922                   scanner.scanEscapeCharacter();
 
2924                 // consume next character
 
2925                 scanner.unicodeAsBackSlash = false;
 
2926                 //                                                              if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
2927                 //                                                                      scanner.getNextUnicodeChar();
 
2929                 if (scanner.withoutUnicodePtr != 0) {
 
2930                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
2938                 if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment 
 
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++;
 
2947                     if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2949                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2951                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
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
 
2958                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
2961                   while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
 
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++;
 
2971                       if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2973                         || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2975                         || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
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
 
2982                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
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());
 
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();
 
3004                   if (scanner.withoutUnicodePtr != 0) {
 
3005                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3008                   if (scanner.currentCharacter == '*') {
 
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++;
 
3019                     if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3021                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3023                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
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 /
 
3030                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3033                   //loop until end of comment */ 
 
3034                   while ((scanner.currentCharacter != '/') || (!star)) {
 
3035                     star = scanner.currentCharacter == '*';
 
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++;
 
3044                       if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3046                         || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3048                         || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
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 /
 
3055                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3059                   if (this.scanner.taskTags != null) {
 
3060                     this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
 
3067               if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
 
3068                 scanner.scanIdentifierOrKeyword(false);
 
3071               if (Character.isDigit(scanner.currentCharacter)) {
 
3072                 scanner.scanNumber(false);
 
3076           //-----------------end switch while try--------------------
 
3077         } catch (IndexOutOfBoundsException e) {
 
3078           break; // read until EOF
 
3079         } catch (InvalidInputException e) {
 
3080           return false; // no clue
 
3083       if (scanner.recordLineSeparator) {
 
3084         //                              compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
 
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];
 
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])) {
 
3102           if (end < 0) { // did not find a good closing match
 
3103             problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
 
3106           // check if even number of opening/closing other brackets in between this pair of brackets
 
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))
 
3114             for (int i = 0; i < rightCount[otherKind]; i++) {
 
3115               int pos = rightPositions[otherKind][i];
 
3116               if ((pos > start) && (pos < end))
 
3120               problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly
 
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);
 
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);
 
3135         if (anomaliesDetected)
 
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;
 
3147   protected void pushOnAstLengthStack(int pos) {
 
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;
 
3159   protected void pushOnAstStack(AstNode node) {
 
3160     /*add a new obj on top of the ast stack
 
3161     astPtr points on the top*/
 
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;
 
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;