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();
 
 175   public void setFileToParse(IFile fileToParse) {
 
 176     this.currentPHPString = 0;
 
 177     PHPParserSuperclass.fileToParse = fileToParse;
 
 180     this.token = TokenNameEOF;
 
 182     this.initializeScanner();
 
 185    *  ClassDeclaration Constructor.
 
 188    *@param  sess  Description of Parameter
 
 191   public Parser(IFile fileToParse) {
 
 192     //    if (keywordMap == null) {
 
 193     //      keywordMap = new HashMap();
 
 194     //      for (int i = 0; i < PHP_KEYWORS.length; i++) {
 
 195     //        keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
 
 198     this.currentPHPString = 0;
 
 199     PHPParserSuperclass.fileToParse = fileToParse;
 
 202     this.token = TokenNameEOF;
 
 204     //    this.rowCount = 1;
 
 205     //    this.columnCount = 0;
 
 209     this.initializeScanner();
 
 212   public void initializeScanner() {
 
 213     this.scanner = new Scanner(false, false, false, false);
 
 216    * Create marker for the parse error
 
 218   private void setMarker(String message, int charStart, int charEnd, int errorLevel) throws CoreException {
 
 219     setMarker(fileToParse, message, charStart, charEnd, errorLevel);
 
 223    * This method will throw the SyntaxError.
 
 224    * It will add the good lines and columns to the Error
 
 225    * @param error the error message
 
 226    * @throws SyntaxError the error raised
 
 228   private void throwSyntaxError(String error) {
 
 230     //    if (str.length() < chIndx) {
 
 233     //    // read until end-of-line
 
 235     //    while (str.length() > eol) {
 
 236     //      ch = str.charAt(eol++);
 
 242     //    throw new SyntaxError(
 
 244     //      chIndx - columnCount + 1,
 
 245     //      str.substring(columnCount, eol),
 
 247     throw new SyntaxError(1, 1, "", error);
 
 251    * This method will throw the SyntaxError.
 
 252    * It will add the good lines and columns to the Error
 
 253    * @param error the error message
 
 254    * @throws SyntaxError the error raised
 
 256   private void throwSyntaxError(String error, int startRow) {
 
 257     throw new SyntaxError(startRow, 0, " ", error);
 
 260   private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
 
 261     problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, compilationUnit.compilationResult);
 
 262     throw new SyntaxError(1, 0, " ", error);
 
 265    *  Method Declaration.
 
 269   //  private void getChar() {
 
 270   //    if (str.length() > chIndx) {
 
 271   //      ch = str.charAt(chIndx++);
 
 276   //    chIndx = str.length() + 1;
 
 278   //    //  token = TokenNameEOF;
 
 283    * gets the next token from input
 
 285   private void getNextToken() throws CoreException {
 
 287       token = scanner.getNextToken();
 
 289         int currentEndPosition = scanner.getCurrentTokenEndPosition();
 
 290         int currentStartPosition = scanner.getCurrentTokenStartPosition();
 
 292         System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
 
 293         System.out.println(scanner.toStringAction(token));
 
 295     } catch (InvalidInputException e) {
 
 296       token = TokenNameERROR;
 
 304    * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
 
 305    * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
 
 306    * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
 
 307    * value {@link Parser#TokenNameINT_NUMBER}
 
 309   //  private void getNumber() {
 
 310   //    StringBuffer inum = new StringBuffer();
 
 312   //    int numFormat = 10;
 
 314   //    // save first digit
 
 315   //    char firstCh = ch;
 
 319   //    // determine number conversions:
 
 320   //    if (firstCh == '0') {
 
 349   //    if (numFormat == 16) {
 
 350   //      while ((ch >= '0' && ch <= '9')
 
 351   //        || (ch >= 'a' && ch <= 'f')
 
 352   //        || (ch >= 'A' && ch <= 'F')) {
 
 357   //      while ((ch >= '0' && ch <= '9')
 
 361   //        if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
 
 362   //          if (ch == '.' && dFlag != ' ') {
 
 365   //          if ((dFlag == 'E') || (dFlag == 'e')) {
 
 371   //          if ((ch == '-') || (ch == '+')) {
 
 384   //      if (dFlag != ' ') {
 
 385   //        doubleNumber = new Double(inum.toString());
 
 386   //        token = TokenNameDoubleLiteral;
 
 389   //        longNumber = Long.valueOf(inum.toString(), numFormat);
 
 390   //        token = TokenNameIntegerLiteral;
 
 394   //    } catch (Throwable e) {
 
 395   //      throwSyntaxError("Number format error: " + inum.toString());
 
 401   //   * @param openChar the opening char ('\'', '"', '`')
 
 402   //   * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
 
 403   //   * @param errorMsg the error message in case of parse error in the string
 
 405   //  private void getString(
 
 406   //    final char openChar,
 
 407   //    final int typeString,
 
 408   //    final String errorMsg) {
 
 409   //    StringBuffer sBuffer = new StringBuffer();
 
 410   //    boolean openString = true;
 
 411   //    int startRow = rowCount;
 
 412   //    while (str.length() > chIndx) {
 
 413   //      ch = str.charAt(chIndx++);
 
 415   //        sBuffer.append(ch);
 
 416   //        if (str.length() > chIndx) {
 
 417   //          ch = str.charAt(chIndx++);
 
 418   //          sBuffer.append(ch);
 
 420   //      } else if (ch == openChar) {
 
 421   //        openString = false;
 
 423   //      } else if (ch == '\n') {
 
 425   //        columnCount = chIndx;
 
 427   //        sBuffer.append(ch);
 
 431   //      if (typeString == TokenNameStringConstant) {
 
 432   //        throwSyntaxError(errorMsg, startRow);
 
 434   //        throwSyntaxError(errorMsg);
 
 437   //    token = typeString;
 
 438   //    stringValue = sBuffer.toString();
 
 441   //    public void htmlParserTester(String input) {
 
 442   //            int lineNumber = 1;
 
 443   //            int startLineNumber = 1;
 
 444   //            int startIndex = 0;
 
 447   //            boolean phpMode = false;
 
 448   //            boolean phpFound = false;
 
 450   //            phpList = new ArrayList();
 
 451   //            currentPHPString = 0;
 
 455   //                    while (i < input.length()) {
 
 456   //                            ch = input.charAt(i++);
 
 460   //                            if ((!phpMode) && ch == '<') {
 
 461   //                                    ch2 = input.charAt(i++);
 
 463   //                                            ch2 = input.charAt(i++);
 
 464   //                                            if (Character.isWhitespace(ch2)) {
 
 469   //                                                    startLineNumber = lineNumber;
 
 471   //                                            } else if (ch2 == 'p') {
 
 472   //                                                    ch2 = input.charAt(i++);
 
 474   //                                                            ch2 = input.charAt(i++);
 
 479   //                                                                    startLineNumber = lineNumber;
 
 485   //                                            } else if (ch2 == 'P') {
 
 486   //                                                    ch2 = input.charAt(i++);
 
 488   //                                                            ch2 = input.charAt(i++);
 
 493   //                                                                    startLineNumber = lineNumber;
 
 506   //                                    if (ch == '/' && i < input.length()) {
 
 507   //                                            ch2 = input.charAt(i++);
 
 509   //                                                    while (i < input.length()) {
 
 510   //                                                            ch = input.charAt(i++);
 
 511   //                                                            if (ch == '?' && i < input.length()) {
 
 512   //                                                                    ch2 = input.charAt(i++);
 
 521   //                                                                                            startLineNumber));
 
 525   //                                                            } else if (ch == '\n') {
 
 531   //                                            } else if (ch2 == '*') {
 
 532   //                                                    // multi-line comment
 
 533   //                                                    while (i < input.length()) {
 
 534   //                                                            ch = input.charAt(i++);
 
 537   //                                                            } else if (ch == '*' && i < input.length()) {
 
 538   //                                                                    ch2 = input.charAt(i++);
 
 549   //                                    } else if (ch == '#') {
 
 550   //                                            while (i < input.length()) {
 
 551   //                                                    ch = input.charAt(i++);
 
 552   //                                                    if (ch == '?' && i < input.length()) {
 
 553   //                                                            ch2 = input.charAt(i++);
 
 559   //                                                                                    input.substring(startIndex, i - 2),
 
 560   //                                                                                    startLineNumber));
 
 564   //                                                    } else if (ch == '\n') {
 
 570   //                                    } else if (ch == '"') {
 
 572   //                                            while (i < input.length()) {
 
 573   //                                                    ch = input.charAt(i++);
 
 577   //                                                            ch == '\\' && i < input.length()) { // escape
 
 579   //                                                    } else if (ch == '"') {
 
 584   //                                    } else if (ch == '\'') {
 
 586   //                                            while (i < input.length()) {
 
 587   //                                                    ch = input.charAt(i++);
 
 591   //                                                            ch == '\\' && i < input.length()) { // escape
 
 593   //                                                    } else if (ch == '\'') {
 
 600   //                                    if (ch == '?' && i < input.length()) {
 
 601   //                                            ch2 = input.charAt(i++);
 
 607   //                                                                    input.substring(startIndex, i - 2),
 
 608   //                                                                    startLineNumber));
 
 618   //                                    "No PHP source code found.",
 
 624   //                                            "Open PHP tag at end of file.",
 
 629   //                                                    input.substring(startIndex, i - 2),
 
 630   //                                                    startLineNumber));
 
 632   //                            //        for (int j=0;j<phpList.size();j++) {
 
 633   //                            //          String temp = ((PHPString)phpList.get(j)).getPHPString();
 
 634   //                            //          int startIndx = temp.length()-10;
 
 635   //                            //          if (startIndx<0) {
 
 638   //                            //          System.out.println(temp.substring(startIndx)+"?>");
 
 640   //                            phpParserTester(null, 1);
 
 641   //                            //        PHPString temp;
 
 642   //                            //        for(int j=0;j<phpList.size();j++) {
 
 643   //                            //          temp = (PHPString) phpList.get(j);
 
 644   //                            //          parser.start(temp.getPHPString(), temp.getLineNumber());
 
 647   //            } catch (CoreException e) {
 
 651   public void phpParserTester(String s, int rowCount) throws CoreException {
 
 654       if (phpList.size() != 0) {
 
 655         this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
 
 658     this.token = TokenNameEOF;
 
 660     //    this.rowCount = rowCount;
 
 661     //    this.columnCount = 0;
 
 664     scanner.setSource(s.toCharArray());
 
 665     scanner.setPHPMode(true);
 
 669         if (token != TokenNameEOF && token != TokenNameERROR) {
 
 672         if (token != TokenNameEOF) {
 
 673           if (token == TokenNameERROR) {
 
 674             throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
 
 676           if (token == TokenNameRPAREN) {
 
 677             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
 679           if (token == TokenNameRBRACE) {
 
 680             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
 682           if (token == TokenNameRBRACKET) {
 
 683             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
 686           if (token == TokenNameLPAREN) {
 
 687             throwSyntaxError("Read character '('; end-of-file not reached.");
 
 689           if (token == TokenNameLBRACE) {
 
 690             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
 692           if (token == TokenNameLBRACKET) {
 
 693             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
 696           throwSyntaxError("End-of-file not reached.");
 
 699       } catch (SyntaxError err) {
 
 703           //   setMarker(err.getMessage(), err.getLine(), ERROR);
 
 704           setMarker(err.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
 
 706         // if an error occured,
 
 707         // try to find keywords 'class' or 'function'
 
 708         // to parse the rest of the string
 
 709         while (token != TokenNameEOF && token != TokenNameERROR) {
 
 710           if (token == TokenNameclass || token == TokenNamefunction) {
 
 715         if (token == TokenNameEOF || token == TokenNameERROR) {
 
 722   public void init(String s) {
 
 724     this.token = TokenNameEOF;
 
 726     //    this.rowCount = 1;
 
 727     //    this.columnCount = 0;
 
 729     this.phpMode = false;
 
 730     /* scanner initialization */
 
 731     scanner.setSource(s.toCharArray());
 
 732     scanner.setPHPMode(false);
 
 735   protected void initialize() {
 
 736     compilationUnit = null;
 
 737     referenceContext = null;
 
 739     this.token = TokenNameEOF;
 
 741     //    this.rowCount = 1;
 
 742     //    this.columnCount = 0;
 
 744     this.phpMode = false;
 
 745     scanner.setPHPMode(false);
 
 748    * Parses a string with php tags
 
 749    * i.e. '<body> <?php phpinfo() ?> </body>'
 
 751   public void parse(String s) throws CoreException {
 
 757          * Parses a string with php tags
 
 758          * i.e. '<body> <?php phpinfo() ?> </body>'
 
 760   protected void parse() throws CoreException {
 
 764         if (token != TokenNameEOF && token != TokenNameERROR) {
 
 767         if (token != TokenNameEOF) {
 
 768           if (token == TokenNameERROR) {
 
 769             throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
 
 771           if (token == TokenNameRPAREN) {
 
 772             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
 774           if (token == TokenNameRBRACE) {
 
 775             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
 777           if (token == TokenNameRBRACKET) {
 
 778             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
 781           if (token == TokenNameLPAREN) {
 
 782             throwSyntaxError("Read character '('; end-of-file not reached.");
 
 784           if (token == TokenNameLBRACE) {
 
 785             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
 787           if (token == TokenNameLBRACKET) {
 
 788             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
 791           throwSyntaxError("End-of-file not reached.");
 
 794       } catch (SyntaxError sytaxErr1) {
 
 795         // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
 
 796         setMarker(sytaxErr1.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
 
 798           // if an error occured,
 
 799           // try to find keywords 'class' or 'function'
 
 800           // to parse the rest of the string
 
 801           while (token != TokenNameEOF && token != TokenNameERROR) {
 
 802             if (token == TokenNameclass || token == TokenNamefunction) {
 
 807           if (token == TokenNameEOF || token == TokenNameERROR) {
 
 810         } catch (SyntaxError sytaxErr2) {
 
 811           //    setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
 
 812           setMarker(sytaxErr2.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
 
 820   public PHPOutlineInfo parseInfo(Object parent, String s) {
 
 821     PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
 
 822     //    Stack stack = new Stack();
 
 823     //    stack.push(outlineInfo.getDeclarations());
 
 826     this.token = TokenNameEOF;
 
 828     //    this.rowCount = 1;
 
 829     //    this.columnCount = 0;
 
 831     this.phpMode = false;
 
 832     scanner.setSource(s.toCharArray());
 
 833     scanner.setPHPMode(false);
 
 837       parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
 
 838     } catch (CoreException e) {
 
 843   private boolean isVariable() {
 
 844     return token == TokenNameVariable || token == TokenNamethis;
 
 847   private void parseDeclarations(PHPOutlineInfo outlineInfo, OutlineableWithChildren current, boolean goBack) {
 
 849     //   PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
 
 850     PHPSegmentWithChildren temp;
 
 853     IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
 
 855       while (token != TokenNameEOF && token != TokenNameERROR) {
 
 856         if (token == TokenNameVariable) {
 
 857           ident = scanner.getCurrentIdentifierSource();
 
 858           outlineInfo.addVariable(new String(ident));
 
 860         } else if (token == TokenNamevar) {
 
 862           if (token == TokenNameVariable && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
 
 863             ident = scanner.getCurrentIdentifierSource();
 
 864             //substring(1) added because PHPVarDeclaration doesn't need the $ anymore
 
 865             String variableName = new String(ident).substring(1);
 
 866             outlineInfo.addVariable(variableName);
 
 868             if (token != TokenNameSEMICOLON) {
 
 871               ident = scanner.getCurrentTokenSource();
 
 872               if (token > TokenNameKEYWORD) {
 
 873                 current.add(new PHPVarDeclaration(current, variableName,
 
 874                 //                      chIndx - ident.length,
 
 875                 scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 878                   case TokenNameVariable :
 
 880                     current.add(new PHPVarDeclaration(current, variableName,
 
 881                     //                      chIndx - ident.length,
 
 882                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 884                   case TokenNameIdentifier :
 
 885                     current.add(new PHPVarDeclaration(current, variableName,
 
 886                     //                    chIndx - ident.length,
 
 887                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 889                   case TokenNameDoubleLiteral :
 
 890                     current.add(new PHPVarDeclaration(current, variableName + doubleNumber,
 
 891                     //   chIndx - ident.length,
 
 892                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 894                   case TokenNameIntegerLiteral :
 
 895                     current.add(new PHPVarDeclaration(current, variableName,
 
 896                     //                 chIndx - ident.length,
 
 897                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 899                   case TokenNameStringInterpolated :
 
 900                   case TokenNameStringLiteral :
 
 901                     current.add(new PHPVarDeclaration(current, variableName,
 
 902                     //              chIndx - ident.length,
 
 903                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 905                   case TokenNameStringConstant :
 
 906                     current.add(new PHPVarDeclaration(current, variableName,
 
 907                     //   chIndx - ident.length,
 
 908                     scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 911                     current.add(new PHPVarDeclaration(current, variableName,
 
 912                     //               chIndx - ident.length
 
 913                     scanner.getCurrentTokenStartPosition()));
 
 919               ident = scanner.getCurrentIdentifierSource();
 
 921               current.add(new PHPVarDeclaration(current, variableName,
 
 922               //          chIndx - ident.length
 
 923               scanner.getCurrentTokenStartPosition()));
 
 926         } else if (token == TokenNamefunction) {
 
 928           if (token == TokenNameAND) {
 
 931           if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
 
 932             ident = scanner.getCurrentIdentifierSource();
 
 933             outlineInfo.addVariable(new String(ident));
 
 934             temp = new PHPFunctionDeclaration(current, new String(ident),
 
 935               // chIndx - ident.length
 
 936   scanner.getCurrentTokenStartPosition());
 
 939             parseDeclarations(outlineInfo, temp, true);
 
 941         } else if (token == TokenNameclass) {
 
 943           if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
 
 944             ident = scanner.getCurrentIdentifierSource();
 
 945             outlineInfo.addVariable(new String(ident));
 
 946             temp = new PHPClassDeclaration(current, new String(ident),
 
 947               //      chIndx - ident.len
 
 948   scanner.getCurrentTokenStartPosition());
 
 953             //skip tokens for classname, extends and others until we have the opening '{'
 
 954             while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) {
 
 957             parseDeclarations(outlineInfo, temp, true);
 
 960         } else if ((token == TokenNameLBRACE) || (token == TokenNameDOLLAR_LBRACE)) {
 
 963         } else if (token == TokenNameRBRACE) {
 
 966           if (counter == 0 && goBack) {
 
 969         } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) {
 
 970           ident = scanner.getCurrentTokenSource();
 
 973           int startPosition = scanner.getCurrentTokenStartPosition();
 
 975           char[] expr = scanner.getCurrentTokenSource(startPosition);
 
 976           outlineInfo.addVariable(new String(ident));
 
 977           current.add(new PHPReqIncDeclaration(current, new String(ident),
 
 978           //    chIndx - ident.length,
 
 979           startPosition, new String(expr)));
 
 985     } catch (CoreException e) {
 
 986     } catch (SyntaxError sytaxErr) {
 
 988         //  setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
 
 989         setMarker(sytaxErr.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
 
 990       } catch (CoreException e) {
 
 995   private void statementList() throws CoreException {
 
 997       statement(TokenNameEOF);
 
 998       if ((token == TokenNameRBRACE)
 
 999         || (token == TokenNamecase)
 
1000         || (token == TokenNamedefault)
 
1001         || (token == TokenNameelse)
 
1002         || (token == TokenNameelseif)
 
1003         || (token == TokenNameendif)
 
1004         || (token == TokenNameendfor)
 
1005         || (token == TokenNameendforeach)
 
1006         || (token == TokenNameendwhile)
 
1007         || (token == TokenNameendswitch)
 
1008         || (token == TokenNameEOF)
 
1009         || (token == TokenNameERROR)) {
 
1015   private void functionBody(MethodDeclaration methodDecl) throws CoreException {
 
1016     // '{' [statement-list] '}'
 
1017     if (token == TokenNameLBRACE) {
 
1020       throwSyntaxError("'{' expected in compound-statement.");
 
1022     if (token != TokenNameRBRACE) {
 
1025     if (token == TokenNameRBRACE) {
 
1026       methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1029       throwSyntaxError("'}' expected in compound-statement.");
 
1033   private void statement(int previousToken) throws CoreException {
 
1034     //   if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
 
1035     //  char[] ident = scanner.getCurrentIdentifierSource();
 
1036     //  String keyword = new String(ident);
 
1037         if (token == TokenNameAT) {
 
1039                 if (token != TokenNamerequire
 
1040                                 && token != TokenNamerequire_once
 
1041                                 && token != TokenNameinclude
 
1042                                 && token != TokenNameinclude_once
 
1043                                 && token != TokenNameIdentifier
 
1044                                 && token != TokenNameVariable
 
1045                                 && token != TokenNamethis
 
1046                                 && token != TokenNameStringInterpolated) {
 
1047                         throwSyntaxError("identifier expected after '@'.");
 
1050     if (token == TokenNameinclude || token == TokenNameinclude_once) {
 
1052       if (token == TokenNameLPAREN) {
 
1054         if (token == TokenNameSEMICOLON) {
 
1057           if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
 
1058             throwSyntaxError("';' expected after 'include' or 'include_once'.");
 
1063         concatenationExpression();
 
1067     } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
 
1070       if (token == TokenNameLPAREN) {
 
1072         if (token == TokenNameSEMICOLON) {
 
1075           if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
 
1076             throwSyntaxError("';' expected after 'require' or 'require_once'.");
 
1081         concatenationExpression();
 
1084     } else if (token == TokenNameif) {
 
1086       if (token == TokenNameLPAREN) {
 
1089         throwSyntaxError("'(' expected after 'if' keyword.");
 
1092       if (token == TokenNameRPAREN) {
 
1095         throwSyntaxError("')' expected after 'if' condition.");
 
1100     } else if (token == TokenNameswitch) {
 
1102       if (token == TokenNameLPAREN) {
 
1105         throwSyntaxError("'(' expected after 'switch' keyword.");
 
1108       if (token == TokenNameRPAREN) {
 
1111         throwSyntaxError("')' expected after 'switch' condition.");
 
1115     } else if (token == TokenNamefor) {
 
1117       if (token == TokenNameLPAREN) {
 
1120         throwSyntaxError("'(' expected after 'for' keyword.");
 
1122       if (token == TokenNameSEMICOLON) {
 
1126         if (token == TokenNameSEMICOLON) {
 
1129           throwSyntaxError("';' expected after 'for'.");
 
1132       if (token == TokenNameSEMICOLON) {
 
1136         if (token == TokenNameSEMICOLON) {
 
1139           throwSyntaxError("';' expected after 'for'.");
 
1142       if (token == TokenNameRPAREN) {
 
1146         if (token == TokenNameRPAREN) {
 
1149           throwSyntaxError("')' expected after 'for'.");
 
1154     } else if (token == TokenNamewhile) {
 
1156       if (token == TokenNameLPAREN) {
 
1159         throwSyntaxError("'(' expected after 'while' keyword.");
 
1162       if (token == TokenNameRPAREN) {
 
1165         throwSyntaxError("')' expected after 'while' condition.");
 
1169     } else if (token == TokenNamedo) {
 
1171       if (token == TokenNameLBRACE) {
 
1174         throwSyntaxError("'{' expected after 'do' keyword.");
 
1176       if (token != TokenNameRBRACE) {
 
1179       if (token == TokenNameRBRACE) {
 
1182         throwSyntaxError("'}' expected after 'do' keyword.");
 
1184       if (token == TokenNamewhile) {
 
1186         if (token == TokenNameLPAREN) {
 
1189           throwSyntaxError("'(' expected after 'while' keyword.");
 
1192         if (token == TokenNameRPAREN) {
 
1195           throwSyntaxError("')' expected after 'while' condition.");
 
1198         throwSyntaxError("'while' expected after 'do' keyword.");
 
1200       if (token == TokenNameSEMICOLON) {
 
1203         if (token != TokenNameStopPHP) {
 
1204           throwSyntaxError("';' expected after do-while statement.");
 
1209     } else if (token == TokenNameforeach) {
 
1211       if (token == TokenNameLPAREN) {
 
1214         throwSyntaxError("'(' expected after 'foreach' keyword.");
 
1217       if (token == TokenNameas) {
 
1220         throwSyntaxError("'as' expected after 'foreach' exxpression.");
 
1223       if (token == TokenNameEQUAL_GREATER) {
 
1227       if (token == TokenNameRPAREN) {
 
1230         throwSyntaxError("')' expected after 'foreach' expression.");
 
1235     } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
 
1237       if (token != TokenNameSEMICOLON) {
 
1240       if (token == TokenNameSEMICOLON) {
 
1243         if (token != TokenNameStopPHP) {
 
1244           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
 
1250     } else if (token == TokenNameecho) {
 
1253       if (token == TokenNameSEMICOLON) {
 
1256         if (token != TokenNameStopPHP) {
 
1257           throwSyntaxError("';' expected after 'echo' statement.");
 
1262       //    } else if (token == TokenNameprint) {
 
1265       //      if (token == TokenNameSEMICOLON) {
 
1268       //        if (token != TokenNameStopPHP) {
 
1269       //          throwSyntaxError("';' expected after 'print' statement.");
 
1275     } else if (token == TokenNameglobal || token == TokenNamestatic) {
 
1278       if (token == TokenNameSEMICOLON) {
 
1281         if (token != TokenNameStopPHP) {
 
1282           throwSyntaxError("';' expected after 'global' or 'static' statement.");
 
1288       //      } else if (token == TokenNameunset) {
 
1290       //        if (token == TokenNameARGOPEN) {
 
1293       //          throwSyntaxError("'(' expected after 'unset' keyword.");
 
1296       //        if (token == TokenNameARGCLOSE) {
 
1299       //          throwSyntaxError("')' expected after 'unset' statement.");
 
1301       //        if (token == TokenNameSEMICOLON) {
 
1304       //          if (token != TokenNameStopPHP) {
 
1305       //            throwSyntaxError("';' expected after 'unset' statement.");
 
1311       //      } else if (token == TokenNameexit || token == TokenNamedie) {
 
1313       //        if (token != TokenNameSEMICOLON) {
 
1316       //        if (token == TokenNameSEMICOLON) {
 
1319       //          if (token != TokenNameStopPHP) {
 
1320       //            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
 
1326     } else if (token == TokenNamedefine) {
 
1328       if (token == TokenNameLPAREN) {
 
1331         throwSyntaxError("'(' expected after 'define' keyword.");
 
1334       if (token == TokenNameCOMMA) {
 
1337         throwSyntaxError("',' expected after first 'define' constant.");
 
1340       if (token == TokenNameCOMMA) {
 
1344       if (token == TokenNameRPAREN) {
 
1347         throwSyntaxError("')' expected after 'define' statement.");
 
1349       if (token == TokenNameSEMICOLON) {
 
1352         if (token != TokenNameStopPHP) {
 
1353           throwSyntaxError("';' expected after 'define' statement.");
 
1358     } else if (token == TokenNamefunction) {
 
1359       MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
 
1360       methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1362       functionDefinition(methodDecl);
 
1364     } else if (token == TokenNameclass) {
 
1365       TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 
1366       typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1367       // default super class
 
1368       typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
 
1369       compilationUnit.types.add(typeDecl);
 
1371         pushOnAstStack(typeDecl);
 
1373         classDeclarator(typeDecl);
 
1374         classBody(typeDecl);
 
1381       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
 
1382     } else if (token == TokenNameLBRACE) {
 
1384       if (token != TokenNameRBRACE) {
 
1387       if (token == TokenNameRBRACE) {
 
1391         throwSyntaxError("'}' expected.");
 
1394       if (token != TokenNameSEMICOLON) {
 
1397       if (token == TokenNameSEMICOLON) {
 
1401         if (token != TokenNameStopPHP && token != TokenNameEOF) {
 
1402           throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
 
1409   private void classDeclarator(TypeDeclaration typeDecl) throws CoreException {
 
1411     //identifier 'extends' identifier
 
1413     if (token == TokenNameIdentifier) {
 
1414       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1415       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1416       typeDecl.name = scanner.getCurrentIdentifierSource();
 
1418       if (token == TokenNameextends) {
 
1421           if (token == TokenNameIdentifier) {
 
1424             reportSyntaxError("Class name expected after keyword 'extends'.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
 
1425             //            throwSyntaxError("ClassDeclaration name expected after keyword 'extends'.");
 
1427         } while (token == TokenNameCOMMA);
 
1430       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1431       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1433       if (token > TokenNameKEYWORD) {
 
1434         typeDecl.name = scanner.getCurrentIdentifierSource();
 
1436           "Don't use keyword for class declaration [" + scanner.toStringAction(token) + "].",
 
1437                                   typeDecl.sourceStart,
 
1438                                   typeDecl.sourceEnd);
 
1439         //        throwSyntaxError("Don't use keyword for class declaration [" + token + "].");
 
1441       typeDecl.name = new char[] { ' ' };
 
1442       reportSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
 
1443       //      throwSyntaxError("ClassDeclaration name expected after keyword 'class'.");
 
1447   private void classBody(TypeDeclaration typeDecl) throws CoreException {
 
1448     //'{' [class-element-list] '}'
 
1449     if (token == TokenNameLBRACE) {
 
1451       if (token != TokenNameRBRACE) {
 
1454       if (token == TokenNameRBRACE) {
 
1455         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1458         throwSyntaxError("'}' expected at end of class body.");
 
1461       throwSyntaxError("'{' expected at start of class body.");
 
1465   private void classElementList() throws CoreException {
 
1468     } while (token == TokenNamefunction || token == TokenNamevar);
 
1471   private void classElement() throws CoreException {
 
1473     //function-definition
 
1474     if (token == TokenNamefunction) {
 
1475       MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
 
1476       methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1478       functionDefinition(methodDecl);
 
1479     } else if (token == TokenNamevar) {
 
1483       throwSyntaxError("'function' or 'var' expected.");
 
1487   private void classProperty() throws CoreException {
 
1488     //'var' variable ';'
 
1489     //'var' variable '=' constant ';'
 
1491       if (token == TokenNameVariable) {
 
1493         if (token == TokenNameEQUAL) {
 
1498         if (token == TokenNamethis) {
 
1499           throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
 
1501         throwSyntaxError("Variable expected after keyword 'var'.");
 
1503       if (token != TokenNameCOMMA) {
 
1508     if (token == TokenNameSEMICOLON) {
 
1511       throwSyntaxError("';' expected after variable declaration.");
 
1515   private void functionDefinition(MethodDeclaration methodDecl) throws CoreException {
 
1517       compilationUnit.types.add(methodDecl);
 
1519       AstNode node = astStack[astPtr];
 
1520       if (node instanceof TypeDeclaration) {
 
1521         TypeDeclaration typeDecl = ((TypeDeclaration) node);
 
1522         if (typeDecl.methods == null) {
 
1523           typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
 
1525           AbstractMethodDeclaration[] newMethods;
 
1526           System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, typeDecl.methods.length);
 
1527           newMethods[0] = methodDecl;
 
1528           typeDecl.methods = newMethods;
 
1532     functionDeclarator(methodDecl);
 
1533     functionBody(methodDecl);
 
1536   private void functionDeclarator(MethodDeclaration methodDecl) throws CoreException {
 
1537     //identifier '(' [parameter-list] ')'
 
1538     if (token == TokenNameAND) {
 
1541     if (token == TokenNameIdentifier) {
 
1542       methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1543       methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1544       methodDecl.selector = scanner.getCurrentIdentifierSource();
 
1546       if (token == TokenNameLPAREN) {
 
1549         throwSyntaxError("'(' expected in function declaration.");
 
1551       if (token != TokenNameRPAREN) {
 
1554       if (token != TokenNameRPAREN) {
 
1555         throwSyntaxError("')' expected in function declaration.");
 
1557         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
 
1561       if (token > TokenNameKEYWORD) {
 
1562         throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
 
1564       throwSyntaxError("Function name expected after keyword 'function'.");
 
1568   private void parameterList() throws CoreException {
 
1569     //parameter-declaration
 
1570     //parameter-list ',' parameter-declaration
 
1572       parameterDeclaration();
 
1573       if (token != TokenNameCOMMA) {
 
1580   private void parameterDeclaration() throws CoreException {
 
1582     //variable-reference
 
1583     if (token == TokenNameAND) {
 
1588         throwSyntaxError("Variable expected after reference operator '&'.");
 
1591     //variable '=' constant
 
1592     if (token == TokenNameVariable) {
 
1594       if (token == TokenNameEQUAL) {
 
1600     if (token == TokenNamethis) {
 
1601       throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
 
1605   private void labeledStatementList() throws CoreException {
 
1606     if (token != TokenNamecase && token != TokenNamedefault) {
 
1607       throwSyntaxError("'case' or 'default' expected.");
 
1610       if (token == TokenNamecase) {
 
1612         expression(); //constant();
 
1613         if (token == TokenNameCOLON) {
 
1615           if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
 
1619         } else if (token == TokenNameSEMICOLON) {
 
1621           //            "':' expected after 'case' keyword (Found token: "
 
1622           //              + scanner.toStringAction(token)
 
1627             "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")",
 
1628             scanner.getCurrentTokenStartPosition(),
 
1629             scanner.getCurrentTokenEndPosition(),
 
1632           if (token == TokenNamecase) { // empty case statement ?
 
1637           throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
 
1639       } else { // TokenNamedefault
 
1641         if (token == TokenNameCOLON) {
 
1645           throwSyntaxError("':' character after 'default' expected.");
 
1648     } while (token == TokenNamecase || token == TokenNamedefault);
 
1651   //  public void labeledStatement() {
 
1652   //    if (token == TokenNamecase) {
 
1655   //      if (token == TokenNameDDOT) {
 
1659   //        throwSyntaxError("':' character after 'case' constant expected.");
 
1662   //    } else if (token == TokenNamedefault) {
 
1664   //      if (token == TokenNameDDOT) {
 
1668   //        throwSyntaxError("':' character after 'default' expected.");
 
1674   //  public void expressionStatement() {
 
1677   //  private void inclusionStatement() {
 
1680   //  public void compoundStatement() {
 
1683   //  public void selectionStatement() {
 
1686   //  public void iterationStatement() {
 
1689   //  public void jumpStatement() {
 
1692   //  public void outputStatement() {
 
1695   //  public void scopeStatement() {
 
1698   //  public void flowStatement() {
 
1701   //  public void definitionStatement() {
 
1704   private void ifStatement() throws CoreException {
 
1705     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
 
1706     if (token == TokenNameCOLON) {
 
1708       if (token != TokenNameendif) {
 
1711           case TokenNameelse :
 
1713             if (token == TokenNameCOLON) {
 
1715               if (token != TokenNameendif) {
 
1719               if (token == TokenNameif) { //'else if'
 
1721                 elseifStatementList();
 
1723                 throwSyntaxError("':' expected after 'else'.");
 
1727           case TokenNameelseif :
 
1729             elseifStatementList();
 
1734       if (token != TokenNameendif) {
 
1735         throwSyntaxError("'endif' expected.");
 
1738       if (token != TokenNameSEMICOLON) {
 
1739         throwSyntaxError("';' expected after if-statement.");
 
1743       // statement [else-statement]
 
1744       statement(TokenNameEOF);
 
1745       if (token == TokenNameelseif) {
 
1747         if (token == TokenNameLPAREN) {
 
1750           throwSyntaxError("'(' expected after 'elseif' keyword.");
 
1753         if (token == TokenNameRPAREN) {
 
1756           throwSyntaxError("')' expected after 'elseif' condition.");
 
1759       } else if (token == TokenNameelse) {
 
1761         statement(TokenNameEOF);
 
1766   private void elseifStatementList() throws CoreException {
 
1770         case TokenNameelse :
 
1772           if (token == TokenNameCOLON) {
 
1774             if (token != TokenNameendif) {
 
1779             if (token == TokenNameif) { //'else if'
 
1782               throwSyntaxError("':' expected after 'else'.");
 
1786         case TokenNameelseif :
 
1795   private void elseifStatement() throws CoreException {
 
1796     if (token == TokenNameLPAREN) {
 
1799       if (token != TokenNameRPAREN) {
 
1800         throwSyntaxError("')' expected in else-if-statement.");
 
1803       if (token != TokenNameCOLON) {
 
1804         throwSyntaxError("':' expected in else-if-statement.");
 
1807       if (token != TokenNameendif) {
 
1813   private void switchStatement() throws CoreException {
 
1814     if (token == TokenNameCOLON) {
 
1815       // ':' [labeled-statement-list] 'endswitch' ';'
 
1817       labeledStatementList();
 
1818       if (token != TokenNameendswitch) {
 
1819         throwSyntaxError("'endswitch' expected.");
 
1822       if (token != TokenNameSEMICOLON) {
 
1823         throwSyntaxError("';' expected after switch-statement.");
 
1827       // '{' [labeled-statement-list] '}'
 
1828       if (token != TokenNameLBRACE) {
 
1829         throwSyntaxError("'{' expected in switch statement.");
 
1832       if (token != TokenNameRBRACE) {
 
1833         labeledStatementList();
 
1835       if (token != TokenNameRBRACE) {
 
1836         throwSyntaxError("'}' expected in switch statement.");
 
1843   private void forStatement() throws CoreException {
 
1844     if (token == TokenNameCOLON) {
 
1847       if (token != TokenNameendfor) {
 
1848         throwSyntaxError("'endfor' expected.");
 
1851       if (token != TokenNameSEMICOLON) {
 
1852         throwSyntaxError("';' expected after for-statement.");
 
1856       statement(TokenNameEOF);
 
1860   private void whileStatement() throws CoreException {
 
1861     // ':' statement-list 'endwhile' ';'
 
1862     if (token == TokenNameCOLON) {
 
1865       if (token != TokenNameendwhile) {
 
1866         throwSyntaxError("'endwhile' expected.");
 
1869       if (token != TokenNameSEMICOLON) {
 
1870         throwSyntaxError("';' expected after while-statement.");
 
1874       statement(TokenNameEOF);
 
1878   private void foreachStatement() throws CoreException {
 
1879     if (token == TokenNameCOLON) {
 
1882       if (token != TokenNameendforeach) {
 
1883         throwSyntaxError("'endforeach' expected.");
 
1886       if (token != TokenNameSEMICOLON) {
 
1887         throwSyntaxError("';' expected after foreach-statement.");
 
1891       statement(TokenNameEOF);
 
1895   private void exitStatus() throws CoreException {
 
1896     if (token == TokenNameLPAREN) {
 
1899       throwSyntaxError("'(' expected in 'exit-status'.");
 
1901     if (token != TokenNameRPAREN) {
 
1904     if (token == TokenNameRPAREN) {
 
1907       throwSyntaxError("')' expected after 'exit-status'.");
 
1911   private void expressionList() throws CoreException {
 
1914       if (token == TokenNameCOMMA) {
 
1922   private void expression() throws CoreException {
 
1923     //todo: find a better way to get the expression
 
1924     //    expression = new StringBuffer();
 
1925     //    for (int i = chIndx; i < str.length(); i++) {
 
1926     //      if (str.charAt(i) == ';') {
 
1929     //      expression.append(str.charAt(i));
 
1932     //    if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
 
1935     logicalinclusiveorExpression();
 
1936     //      while (token != TokenNameSEMICOLON) {
 
1942   private void postfixExpression() throws CoreException {
 
1945     boolean castFlag = false;
 
1946     boolean arrayFlag = false;
 
1952       case TokenNamenull :
 
1955       case TokenNamefalse :
 
1958       case TokenNametrue :
 
1961       case TokenNameStringConstant :
 
1964       case TokenNameHEREDOC :
 
1965       case TokenNameStringInterpolated :
 
1966       case TokenNameStringLiteral :
 
1969       case TokenNameLPAREN :
 
1972         if (token == TokenNameIdentifier) {
 
1973           // check if identifier is a type:
 
1974           //    ident = identifier;
 
1975           ident = scanner.getCurrentIdentifierSource();
 
1976           String str = new String(ident).toLowerCase();
 
1977           for (int i = 0; i < PHP_TYPES.length; i++) {
 
1978             if (PHP_TYPES[i].equals(str)) {
 
1980               if (PHP_TYPES[i].equals("array")) {
 
1990           if (arrayFlag && token == TokenNameLPAREN) {
 
1992             if (token == TokenNameRPAREN) {
 
1996               if (token != TokenNameRPAREN) {
 
1997                 throwSyntaxError(") expected after 'array('.");
 
2001           if (token != TokenNameRPAREN) {
 
2002             throwSyntaxError(") expected after cast-type '" + str + "'.");
 
2010         if (token != TokenNameRPAREN) {
 
2011           throwSyntaxError(") expected in postfix-expression.");
 
2015       case TokenNameDoubleLiteral :
 
2018       case TokenNameIntegerLiteral :
 
2021       case TokenNameDOLLAR_LBRACE :
 
2024         if (token != TokenNameRBRACE) {
 
2025           throwSyntaxError("'}' expected after indirect variable token '${'.");
 
2029       case TokenNameVariable :
 
2030       case TokenNamethis :
 
2031         ident = scanner.getCurrentIdentifierSource();
 
2033         if (token == TokenNameLBRACE) {
 
2036           if (token != TokenNameRBRACE) {
 
2037             throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression.");
 
2040         } else if (token == TokenNameLPAREN) {
 
2042           if (token != TokenNameRPAREN) {
 
2044             if (token != TokenNameRPAREN) {
 
2045               throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression.");
 
2051       case TokenNameIdentifier :
 
2052         ident = scanner.getCurrentIdentifierSource();
 
2054         if (token == TokenNameLPAREN) {
 
2056           if (token != TokenNameRPAREN) {
 
2058             if (token != TokenNameRPAREN) {
 
2060                 "')' expected after identifier '" + new String(ident) + "' in postfix-expression." + "(Found token: " + scanner.toStringAction(token) + ")");
 
2066       case TokenNameprint :
 
2069         //        if (token == TokenNameSEMICOLON) {
 
2072         //          if (token != TokenNameStopPHP) {
 
2073         //            throwSyntaxError("';' expected after 'print' statement.");
 
2078       case TokenNamelist :
 
2080         if (token == TokenNameLPAREN) {
 
2082           if (token == TokenNameCOMMA) {
 
2086           if (token != TokenNameRPAREN) {
 
2087             throwSyntaxError("')' expected after 'list' keyword.");
 
2090           //          if (token == TokenNameSET) {
 
2092           //            logicalinclusiveorExpression();
 
2095           throwSyntaxError("'(' expected after 'list' keyword.");
 
2098         //      case TokenNameexit :
 
2100         //        if (token != TokenNameSEMICOLON) {
 
2103         //        if (token == TokenNameSEMICOLON) {
 
2106         //          if (token != TokenNameStopPHP) {
 
2107         //            throwSyntaxError("';' expected after 'exit' expression.");
 
2112         //      case TokenNamedie :
 
2114         //        if (token != TokenNameSEMICOLON) {
 
2117         //        if (token == TokenNameSEMICOLON) {
 
2120         //          if (token != TokenNameStopPHP) {
 
2121         //            throwSyntaxError("';' expected after 'die' expression.");
 
2126         //      case TokenNamearray :
 
2128         //        if (token == TokenNameARGOPEN) {
 
2130         //          if (token == TokenNameCOMMA) {
 
2133         //          expressionList();
 
2134         //          if (token != TokenNameARGCLOSE) {
 
2135         //            throwSyntaxError("')' expected after 'list' keyword.");
 
2138         //          if (token == TokenNameSET) {
 
2140         //            logicalinclusiveorExpression();
 
2143         //          throwSyntaxError("'(' expected after 'list' keyword.");
 
2147     boolean while_flag = true;
 
2150         case TokenNameLBRACKET :
 
2153           if (token != TokenNameRBRACKET) {
 
2154             throwSyntaxError("] expected in postfix-expression.");
 
2158         case TokenNameCOLON_COLON : // ::
 
2159         case TokenNameMINUS_GREATER : // ->
 
2161           if (token > TokenNameKEYWORD) {
 
2162             ident = scanner.getCurrentIdentifierSource();
 
2164             //              "Avoid using keyword '"
 
2165             //                + new String(ident)
 
2166             //                + "' as variable name.",
 
2170               "Avoid using keyword '" + new String(ident) + "' as variable name.",
 
2171               scanner.getCurrentTokenStartPosition(),
 
2172               scanner.getCurrentTokenEndPosition(),
 
2176             case TokenNameVariable :
 
2177               ident = scanner.getCurrentIdentifierSource();
 
2179               //              if (token == TokenNameARGOPEN) {
 
2181               //                expressionList();
 
2182               //                if (token != TokenNameARGCLOSE) {
 
2183               //                  throwSyntaxError(") expected after variable '" + ident + "'.");
 
2188             case TokenNameIdentifier :
 
2189               //ident = scanner.getCurrentIdentifierSource();
 
2192             case TokenNameLBRACE :
 
2195               if (token != TokenNameRBRACE) {
 
2196                 throwSyntaxError("} expected in postfix-expression.");
 
2201               throwSyntaxError("Syntax error after '->' token.");
 
2202           } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
 
2203               if (token == TokenNameLBRACKET) {
 
2206                 if (token != TokenNameRBRACKET) {
 
2207                   throwSyntaxError("] expected after '->'.");
 
2210               } else if (token == TokenNameLPAREN) {
 
2213                 if (token != TokenNameRPAREN) {
 
2214                   throwSyntaxError(") expected after '->'.");
 
2217               } else if (token == TokenNameLBRACE) {
 
2220                 if (token != TokenNameRBRACE) {
 
2221                   throwSyntaxError("} expected after '->'.");
 
2227         case TokenNamePLUS_PLUS :
 
2230         case TokenNameMINUS_MINUS :
 
2241   private void unaryExpression() throws CoreException {
 
2243       case TokenNamePLUS_PLUS :
 
2247       case TokenNameMINUS_MINUS :
 
2251         // '@' '&' '*' '+' '-' '~' '!'
 
2254         if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) {
 
2255           statement(TokenNameAT);
 
2257           postfixExpression(); //  castExpression();
 
2264       case TokenNameMULTIPLY :
 
2268       case TokenNamePLUS :
 
2272       case TokenNameMINUS :
 
2276       case TokenNameTWIDDLE :
 
2285         postfixExpression();
 
2289   private void castExpression() throws CoreException {
 
2290     //    if (token == TokenNameARGOPEN) {
 
2293     //      if (token != TokenNameARGCLOSE) {
 
2294     //        throwSyntaxError(") expected after cast-expression.");
 
2301   private void assignExpression() throws CoreException {
 
2303     if (token == TokenNameEQUAL) { // =
 
2305       logicalinclusiveorExpression();
 
2306     } else if (token == TokenNameDOT_EQUAL) { // .=
 
2308       logicalinclusiveorExpression();
 
2309     } else if (token == TokenNameEQUAL_GREATER) { // =>
 
2311       logicalinclusiveorExpression();
 
2312     } else if (token == TokenNamePLUS_EQUAL) { // +=
 
2314       logicalinclusiveorExpression();
 
2315     } else if (token == TokenNameMINUS_EQUAL) { // -=
 
2317       logicalinclusiveorExpression();
 
2318     } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
 
2320       logicalinclusiveorExpression();
 
2321     } else if (token == TokenNameDIVIDE_EQUAL) { // *=
 
2323       logicalinclusiveorExpression();
 
2324     } else if (token == TokenNameREMAINDER_EQUAL) { // %=
 
2326       logicalinclusiveorExpression();
 
2327     } else if (token == TokenNameAND_EQUAL) { // &=
 
2329       logicalinclusiveorExpression();
 
2330     } else if (token == TokenNameOR_EQUAL) { // |=
 
2332       logicalinclusiveorExpression();
 
2333     } else if (token == TokenNameXOR_EQUAL) { // ^=
 
2335       logicalinclusiveorExpression();
 
2336     } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
 
2338       logicalinclusiveorExpression();
 
2339     } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
 
2341       logicalinclusiveorExpression();
 
2342     } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
 
2344       logicalinclusiveorExpression();
 
2348   private void multiplicativeExpression() throws CoreException {
 
2351       if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
 
2358   private void concatenationExpression() throws CoreException {
 
2360       multiplicativeExpression();
 
2361       if (token != TokenNameDOT) {
 
2368   private void additiveExpression() throws CoreException {
 
2370       concatenationExpression();
 
2371       if (token != TokenNamePLUS && token != TokenNameMINUS) {
 
2378   private void shiftExpression() throws CoreException {
 
2380       additiveExpression();
 
2381       if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
 
2388   private void relationalExpression() throws CoreException {
 
2391       if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
 
2398   private void identicalExpression() throws CoreException {
 
2400       relationalExpression();
 
2401       if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
 
2408   private void equalityExpression() throws CoreException {
 
2410       identicalExpression();
 
2411       if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
 
2418   private void ternaryExpression() throws CoreException {
 
2419     equalityExpression();
 
2420     if (token == TokenNameQUESTION) {
 
2423       if (token == TokenNameCOLON) {
 
2427         throwSyntaxError("':' expected in ternary operator '? :'.");
 
2432   private void andExpression() throws CoreException {
 
2434       ternaryExpression();
 
2435       if (token != TokenNameAND) {
 
2442   private void exclusiveorExpression() throws CoreException {
 
2445       if (token != TokenNameXOR) {
 
2452   private void inclusiveorExpression() throws CoreException {
 
2454       exclusiveorExpression();
 
2455       if (token != TokenNameOR) {
 
2462   private void booleanandExpression() throws CoreException {
 
2464       inclusiveorExpression();
 
2465       if (token != TokenNameAND_AND) {
 
2472   private void booleanorExpression() throws CoreException {
 
2474       booleanandExpression();
 
2475       if (token != TokenNameOR_OR) {
 
2482   private void logicalandExpression() throws CoreException {
 
2484       booleanorExpression();
 
2485       if (token != TokenNameAND) {
 
2492   private void logicalexclusiveorExpression() throws CoreException {
 
2494       logicalandExpression();
 
2495       if (token != TokenNameXOR) {
 
2502   private void logicalinclusiveorExpression() throws CoreException {
 
2504       logicalexclusiveorExpression();
 
2505       if (token != TokenNameOR) {
 
2512   //  public void assignmentExpression() {
 
2513   //    if (token == TokenNameVARIABLE) {
 
2515   //      if (token == TokenNameSET) {
 
2517   //        logicalinclusiveorExpression();
 
2520   //      logicalinclusiveorExpression();
 
2524   private void variableList() throws CoreException {
 
2527       if (token == TokenNameCOMMA) {
 
2535   private void variable() throws CoreException {
 
2536     if (token == TokenNameDOLLAR_LBRACE) {
 
2540       if (token != TokenNameRBRACE) {
 
2541         throwSyntaxError("'}' expected after indirect variable token '${'.");
 
2545       if (token == TokenNameVariable) {
 
2547         if (token == TokenNameLBRACKET) {
 
2550           if (token != TokenNameRBRACKET) {
 
2551             throwSyntaxError("']' expected in variable-list.");
 
2554         } else if (token == TokenNameEQUAL) {
 
2559         throwSyntaxError("$-variable expected in variable-list.");
 
2565    * It will look for a value (after a '=' for example)
 
2566    * @throws CoreException
 
2568   private void constant() throws CoreException {
 
2571       case TokenNamePLUS :
 
2574           case TokenNameDoubleLiteral :
 
2577           case TokenNameIntegerLiteral :
 
2581             throwSyntaxError("Constant expected after '+' presign.");
 
2584       case TokenNameMINUS :
 
2587           case TokenNameDoubleLiteral :
 
2590           case TokenNameIntegerLiteral :
 
2594             throwSyntaxError("Constant expected after '-' presign.");
 
2597       case TokenNamenull :
 
2600       case TokenNamefalse :
 
2603       case TokenNametrue :
 
2606       case TokenNameIdentifier :
 
2607         //   ident = identifier;
 
2608         char[] ident = scanner.getCurrentIdentifierSource();
 
2610         if (token == TokenNameLPAREN) {
 
2612           if (token != TokenNameRPAREN) {
 
2614             if (token != TokenNameRPAREN) {
 
2615               throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression.");
 
2621       case TokenNameStringLiteral :
 
2624       case TokenNameStringConstant :
 
2627       case TokenNameStringInterpolated :
 
2630       case TokenNameDoubleLiteral :
 
2633       case TokenNameIntegerLiteral :
 
2637         throwSyntaxError("Constant expected.");
 
2641   public void reportSyntaxError() { //int act, int currentKind, int stateStackTop) {
 
2643     /* remember current scanner position */
 
2644     int startPos = scanner.startPosition;
 
2645     int currentPos = scanner.currentPosition;
 
2647     //          String[] expectings;
 
2648     //          String tokenName = name[symbol_index[currentKind]];
 
2650     //fetch all "accurate" possible terminals that could recover the error
 
2651     //          int start, end = start = asi(stack[stateStackTop]);
 
2652     //          while (asr[end] != 0)
 
2654     //          int length = end - start;
 
2655     //          expectings = new String[length];
 
2656     //          if (length != 0) {
 
2657     //                  char[] indexes = new char[length];
 
2658     //                  System.arraycopy(asr, start, indexes, 0, length);
 
2659     //                  for (int i = 0; i < length; i++) {
 
2660     //                          expectings[i] = name[symbol_index[indexes[i]]];
 
2664     //if the pb is an EOF, try to tell the user that they are some 
 
2665     //          if (tokenName.equals(UNEXPECTED_EOF)) {
 
2666     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
 
2667     //                          char[] tokenSource;
 
2669     //                                  tokenSource = this.scanner.getCurrentTokenSource();
 
2670     //                          } catch (Exception e) {
 
2671     //                                  tokenSource = new char[] {};
 
2673     //                          problemReporter().parseError(
 
2674     //                                  this.scanner.startPosition, 
 
2675     //                                  this.scanner.currentPosition - 1, 
 
2680     //          } else { //the next test is HEAVILY grammar DEPENDENT.
 
2681     //                  if ((length == 14)
 
2682     //                          && (expectings[0] == "=") //$NON-NLS-1$
 
2683     //                          && (expectings[1] == "*=") //$NON-NLS-1$
 
2684     //                          && (expressionPtr > -1)) {
 
2685     //                                  switch(currentKind) {
 
2686     //                                          case TokenNameSEMICOLON:
 
2687     //                                          case TokenNamePLUS:
 
2688     //                                          case TokenNameMINUS:
 
2689     //                                          case TokenNameDIVIDE:
 
2690     //                                          case TokenNameREMAINDER:
 
2691     //                                          case TokenNameMULTIPLY:
 
2692     //                                          case TokenNameLEFT_SHIFT:
 
2693     //                                          case TokenNameRIGHT_SHIFT:
 
2694     ////                                                case TokenNameUNSIGNED_RIGHT_SHIFT:
 
2695     //                                          case TokenNameLESS:
 
2696     //                                          case TokenNameGREATER:
 
2697     //                                          case TokenNameLESS_EQUAL:
 
2698     //                                          case TokenNameGREATER_EQUAL:
 
2699     //                                          case TokenNameEQUAL_EQUAL:
 
2700     //                                          case TokenNameNOT_EQUAL:
 
2701     //                                          case TokenNameXOR:
 
2702     //                                          case TokenNameAND:
 
2703     //                                          case TokenNameOR:
 
2704     //                                          case TokenNameOR_OR:
 
2705     //                                          case TokenNameAND_AND:
 
2706     //                                                  // the ; is not the expected token ==> it ends a statement when an expression is not ended
 
2707     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
 
2709     //                                          case TokenNameRBRACE :
 
2710     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
 
2713     //                                                  char[] tokenSource;
 
2715     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
 
2716     //                                                  } catch (Exception e) {
 
2717     //                                                          tokenSource = new char[] {};
 
2719     //                                                  problemReporter().parseError(
 
2720     //                                                          this.scanner.startPosition, 
 
2721     //                                                          this.scanner.currentPosition - 1, 
 
2725     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
 
2730       tokenSource = this.scanner.getCurrentTokenSource();
 
2731     } catch (Exception e) {
 
2732       tokenSource = new char[] {
 
2735     //                          problemReporter().parseError(
 
2736     //                                  this.scanner.startPosition, 
 
2737     //                                  this.scanner.currentPosition - 1, 
 
2741     this.checkAndReportBracketAnomalies(problemReporter());
 
2744     /* reset scanner where it was */
 
2745     scanner.startPosition = startPos;
 
2746     scanner.currentPosition = currentPos;
 
2748   public static final int RoundBracket = 0;
 
2749   public static final int SquareBracket = 1;
 
2750   public static final int CurlyBracket = 2;
 
2751   public static final int BracketKinds = 3;
 
2753   protected int[] nestedMethod; //the ptr is nestedType
 
2754   protected int nestedType, dimensions;
 
2756   final static int AstStackIncrement = 100;
 
2757   protected int astPtr;
 
2758   protected AstNode[] astStack = new AstNode[AstStackIncrement];
 
2759   protected int astLengthPtr;
 
2760   protected int[] astLengthStack;
 
2761   AstNode[] noAstNodes = new AstNode[AstStackIncrement];
 
2763   public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
 
2764   protected ReferenceContext referenceContext;
 
2765   protected ProblemReporter problemReporter;
 
2766   //  protected CompilationResult compilationResult;
 
2769    * Returns this parser's problem reporter initialized with its reference context.
 
2770    * Also it is assumed that a problem is going to be reported, so initializes
 
2771    * the compilation result's line positions.
 
2773   public ProblemReporter problemReporter() {
 
2774     if (scanner.recordLineSeparator) {
 
2775       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
 
2777     problemReporter.referenceContext = referenceContext;
 
2778     return problemReporter;
 
2781    * Reconsider the entire source looking for inconsistencies in {} () []
 
2783   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
 
2785     scanner.wasAcr = false;
 
2786     boolean anomaliesDetected = false;
 
2788       char[] source = scanner.source;
 
2789       int[] leftCount = { 0, 0, 0 };
 
2790       int[] rightCount = { 0, 0, 0 };
 
2791       int[] depths = { 0, 0, 0 };
 
2792       int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] };
 
2793       int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] };
 
2794       int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] };
 
2795       int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] };
 
2796       scanner.currentPosition = scanner.initialPosition; //starting point (first-zero-based char)
 
2797       while (scanner.currentPosition < scanner.eofPosition) { //loop for jumping over comments
 
2799           // ---------Consume white space and handles startPosition---------
 
2800           boolean isWhiteSpace;
 
2802             scanner.startPosition = scanner.currentPosition;
 
2803             //                                          if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
2804             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
 
2806             if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
 
2807               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
 
2808                 // only record line positions we have not recorded yet
 
2809                 scanner.pushLineSeparator();
 
2812             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
 
2814           } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
 
2816           // -------consume token until } is found---------
 
2818           switch (scanner.currentCharacter) {
 
2821                 int index = leftCount[CurlyBracket]++;
 
2822                 if (index == leftPositions[CurlyBracket].length) {
 
2823                   System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
 
2824                   System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
 
2826                 leftPositions[CurlyBracket][index] = scanner.startPosition;
 
2827                 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
 
2832                 int index = rightCount[CurlyBracket]++;
 
2833                 if (index == rightPositions[CurlyBracket].length) {
 
2834                   System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
 
2835                   System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
 
2837                 rightPositions[CurlyBracket][index] = scanner.startPosition;
 
2838                 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
 
2843                 int index = leftCount[RoundBracket]++;
 
2844                 if (index == leftPositions[RoundBracket].length) {
 
2845                   System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
 
2846                   System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
 
2848                 leftPositions[RoundBracket][index] = scanner.startPosition;
 
2849                 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
 
2854                 int index = rightCount[RoundBracket]++;
 
2855                 if (index == rightPositions[RoundBracket].length) {
 
2856                   System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
 
2857                   System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
 
2859                 rightPositions[RoundBracket][index] = scanner.startPosition;
 
2860                 rightDepths[RoundBracket][index] = --depths[RoundBracket];
 
2865                 int index = leftCount[SquareBracket]++;
 
2866                 if (index == leftPositions[SquareBracket].length) {
 
2867                   System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
 
2868                   System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
 
2870                 leftPositions[SquareBracket][index] = scanner.startPosition;
 
2871                 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
 
2876                 int index = rightCount[SquareBracket]++;
 
2877                 if (index == rightPositions[SquareBracket].length) {
 
2878                   System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
 
2879                   System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
 
2881                 rightPositions[SquareBracket][index] = scanner.startPosition;
 
2882                 rightDepths[SquareBracket][index] = --depths[SquareBracket];
 
2887                 if (scanner.getNextChar('\\')) {
 
2888                   scanner.scanEscapeCharacter();
 
2889                 } else { // consume next character
 
2890                   scanner.unicodeAsBackSlash = false;
 
2891                   //                                                                    if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
2892                   //                                                                            scanner.getNextUnicodeChar();
 
2894                   if (scanner.withoutUnicodePtr != 0) {
 
2895                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
2899                 scanner.getNextChar('\'');
 
2902             case '"' : // consume next character
 
2903               scanner.unicodeAsBackSlash = false;
 
2904               //                                                        if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
2905               //                                                                scanner.getNextUnicodeChar();
 
2907               if (scanner.withoutUnicodePtr != 0) {
 
2908                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
2911               while (scanner.currentCharacter != '"') {
 
2912                 if (scanner.currentCharacter == '\r') {
 
2913                   if (source[scanner.currentPosition] == '\n')
 
2914                     scanner.currentPosition++;
 
2915                   break; // the string cannot go further that the line
 
2917                 if (scanner.currentCharacter == '\n') {
 
2918                   break; // the string cannot go further that the line
 
2920                 if (scanner.currentCharacter == '\\') {
 
2921                   scanner.scanEscapeCharacter();
 
2923                 // consume next character
 
2924                 scanner.unicodeAsBackSlash = false;
 
2925                 //                                                              if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
2926                 //                                                                      scanner.getNextUnicodeChar();
 
2928                 if (scanner.withoutUnicodePtr != 0) {
 
2929                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
2937                 if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment 
 
2939                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
2940                     //-------------unicode traitement ------------
 
2941                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
2942                     scanner.currentPosition++;
 
2943                     while (source[scanner.currentPosition] == 'u') {
 
2944                       scanner.currentPosition++;
 
2946                     if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2948                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2950                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2952                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2953                       || c4 < 0) { //error don't care of the value
 
2954                       scanner.currentCharacter = 'A';
 
2955                     } //something different from \n and \r
 
2957                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
2960                   while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
 
2962                     scanner.startPosition = scanner.currentPosition;
 
2963                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
2964                       //-------------unicode traitement ------------
 
2965                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
2966                       scanner.currentPosition++;
 
2967                       while (source[scanner.currentPosition] == 'u') {
 
2968                         scanner.currentPosition++;
 
2970                       if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2972                         || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2974                         || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2976                         || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
2977                         || c4 < 0) { //error don't care of the value
 
2978                         scanner.currentCharacter = 'A';
 
2979                       } //something different from \n and \r
 
2981                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
2985                   if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
 
2986                     if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
 
2987                       // only record line positions we have not recorded yet
 
2988                       scanner.pushLineSeparator();
 
2989                       if (this.scanner.taskTags != null) {
 
2990                         this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
 
2996                 if (test > 0) { //traditional and annotation comment
 
2997                   boolean star = false;
 
2998                   // consume next character
 
2999                   scanner.unicodeAsBackSlash = false;
 
3000                   //                                                                    if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
3001                   //                                                                            scanner.getNextUnicodeChar();
 
3003                   if (scanner.withoutUnicodePtr != 0) {
 
3004                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3007                   if (scanner.currentCharacter == '*') {
 
3011                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
3012                     //-------------unicode traitement ------------
 
3013                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3014                     scanner.currentPosition++;
 
3015                     while (source[scanner.currentPosition] == 'u') {
 
3016                       scanner.currentPosition++;
 
3018                     if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3020                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3022                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3024                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3025                       || c4 < 0) { //error don't care of the value
 
3026                       scanner.currentCharacter = 'A';
 
3027                     } //something different from * and /
 
3029                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3032                   //loop until end of comment */ 
 
3033                   while ((scanner.currentCharacter != '/') || (!star)) {
 
3034                     star = scanner.currentCharacter == '*';
 
3036                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
 
3037                       //-------------unicode traitement ------------
 
3038                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3039                       scanner.currentPosition++;
 
3040                       while (source[scanner.currentPosition] == 'u') {
 
3041                         scanner.currentPosition++;
 
3043                       if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3045                         || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3047                         || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3049                         || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
 
3050                         || c4 < 0) { //error don't care of the value
 
3051                         scanner.currentCharacter = 'A';
 
3052                       } //something different from * and /
 
3054                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3058                   if (this.scanner.taskTags != null) {
 
3059                     this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
 
3066               if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
 
3067                 scanner.scanIdentifierOrKeyword(false);
 
3070               if (Character.isDigit(scanner.currentCharacter)) {
 
3071                 scanner.scanNumber(false);
 
3075           //-----------------end switch while try--------------------
 
3076         } catch (IndexOutOfBoundsException e) {
 
3077           break; // read until EOF
 
3078         } catch (InvalidInputException e) {
 
3079           return false; // no clue
 
3082       if (scanner.recordLineSeparator) {
 
3083         //                              compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
 
3086       // check placement anomalies against other kinds of brackets
 
3087       for (int kind = 0; kind < BracketKinds; kind++) {
 
3088         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
 
3089           int start = leftPositions[kind][leftIndex]; // deepest first
 
3090           // find matching closing bracket
 
3091           int depth = leftDepths[kind][leftIndex];
 
3093           for (int i = 0; i < rightCount[kind]; i++) {
 
3094             int pos = rightPositions[kind][i];
 
3095             // want matching bracket further in source with same depth
 
3096             if ((pos > start) && (depth == rightDepths[kind][i])) {
 
3101           if (end < 0) { // did not find a good closing match
 
3102             problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
 
3105           // check if even number of opening/closing other brackets in between this pair of brackets
 
3107           for (int otherKind = 0;(balance == 0) && (otherKind < BracketKinds); otherKind++) {
 
3108             for (int i = 0; i < leftCount[otherKind]; i++) {
 
3109               int pos = leftPositions[otherKind][i];
 
3110               if ((pos > start) && (pos < end))
 
3113             for (int i = 0; i < rightCount[otherKind]; i++) {
 
3114               int pos = rightPositions[otherKind][i];
 
3115               if ((pos > start) && (pos < end))
 
3119               problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly
 
3124         // too many opening brackets ?
 
3125         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
 
3126           anomaliesDetected = true;
 
3127           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, compilationUnit.compilationResult);
 
3129         // too many closing brackets ?
 
3130         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
 
3131           anomaliesDetected = true;
 
3132           problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
 
3134         if (anomaliesDetected)
 
3138       return anomaliesDetected;
 
3139     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
 
3140       return anomaliesDetected;
 
3141     } catch (NullPointerException e) { // jdk1.2.2 jit bug
 
3142       return anomaliesDetected;
 
3146   protected void pushOnAstLengthStack(int pos) {
 
3148       astLengthStack[++astLengthPtr] = pos;
 
3149     } catch (IndexOutOfBoundsException e) {
 
3150       int oldStackLength = astLengthStack.length;
 
3151       int[] oldPos = astLengthStack;
 
3152       astLengthStack = new int[oldStackLength + StackIncrement];
 
3153       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
 
3154       astLengthStack[astLengthPtr] = pos;
 
3158   protected void pushOnAstStack(AstNode node) {
 
3159     /*add a new obj on top of the ast stack
 
3160     astPtr points on the top*/
 
3163       astStack[++astPtr] = node;
 
3164     } catch (IndexOutOfBoundsException e) {
 
3165       int oldStackLength = astStack.length;
 
3166       AstNode[] oldStack = astStack;
 
3167       astStack = new AstNode[oldStackLength + AstStackIncrement];
 
3168       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
 
3169       astPtr = oldStackLength;
 
3170       astStack[astPtr] = node;
 
3174       astLengthStack[++astLengthPtr] = 1;
 
3175     } catch (IndexOutOfBoundsException e) {
 
3176       int oldStackLength = astLengthStack.length;
 
3177       int[] oldPos = astLengthStack;
 
3178       astLengthStack = new int[oldStackLength + AstStackIncrement];
 
3179       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
 
3180       astLengthStack[astLengthPtr] = 1;