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;
 
  12 import java.util.ArrayList;
 
  13 import net.sourceforge.phpdt.core.compiler.CharOperation;
 
  14 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
 
  15 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
 
  16 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
 
  17 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
 
  18 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
 
  19 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
 
  20 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
 
  21 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
 
  22 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
 
  23 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
 
  24 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
 
  25 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
 
  26 import net.sourceforge.phpeclipse.phpeditor.PHPString;
 
  27 import org.eclipse.core.resources.IFile;
 
  28 public class Parser //extends PHPParserSuperclass
 
  29     implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
 
  30   //internal data for the automat
 
  31   protected final static int StackIncrement = 255;
 
  32   protected int stateStackTop;
 
  33   protected int[] stack = new int[StackIncrement];
 
  34   public int firstToken; // handle for multiple parsing goals
 
  35   public int lastAct; //handle for multiple parsing goals
 
  36   protected RecoveredElement currentElement;
 
  37   public static boolean VERBOSE_RECOVERY = false;
 
  38   protected boolean diet = false; //tells the scanner to jump over some
 
  39   // parts of the code/expressions like
 
  42   public Scanner scanner;
 
  43   private ArrayList phpList;
 
  44   private int currentPHPString;
 
  45   private boolean phpEnd;
 
  46   // private static HashMap keywordMap = null;
 
  52   // row counter for syntax errors:
 
  54   // column counter for syntax errors:
 
  58   //    // current identifier
 
  62   private String stringValue;
 
  63   /** Contains the current expression. */
 
  64   // private StringBuffer expression;
 
  65   private boolean phpMode;
 
  66   protected int modifiers;
 
  67   protected int modifiersSourceStart;
 
  69     this.currentPHPString = 0;
 
  70     //          PHPParserSuperclass.fileToParse = fileToParse;
 
  73     this.token = TokenNameEOF;
 
  76     //    this.columnCount = 0;
 
  79     this.initializeScanner();
 
  81   public void setFileToParse(IFile fileToParse) {
 
  82     this.currentPHPString = 0;
 
  83     //    PHPParserSuperclass.fileToParse = fileToParse;
 
  86     this.token = TokenNameEOF;
 
  88     this.initializeScanner();
 
  91    * ClassDeclaration Constructor.
 
  95    *            Description of Parameter
 
  98   public Parser(IFile fileToParse) {
 
  99     //    if (keywordMap == null) {
 
 100     //      keywordMap = new HashMap();
 
 101     //      for (int i = 0; i < PHP_KEYWORS.length; i++) {
 
 102     //        keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
 
 105     this.currentPHPString = 0;
 
 106     //    PHPParserSuperclass.fileToParse = fileToParse;
 
 109     this.token = TokenNameEOF;
 
 111     //    this.rowCount = 1;
 
 112     //    this.columnCount = 0;
 
 115     this.initializeScanner();
 
 117   public void initializeScanner() {
 
 118     this.scanner = new Scanner(false, false, false, false);
 
 121    * Create marker for the parse error
 
 123   //  private void setMarker(String message, int charStart, int charEnd, int
 
 125   //    setMarker(fileToParse, message, charStart, charEnd, errorLevel);
 
 128    * This method will throw the SyntaxError. It will add the good lines and
 
 129    * columns to the Error
 
 133    * @throws SyntaxError
 
 136   private void throwSyntaxError(String error) {
 
 137     int problemStartPosition = scanner.getCurrentTokenStartPosition();
 
 138     int problemEndPosition = scanner.getCurrentTokenEndPosition();
 
 139     throwSyntaxError(error, problemStartPosition, problemEndPosition);
 
 142    * This method will throw the SyntaxError. It will add the good lines and
 
 143    * columns to the Error
 
 147    * @throws SyntaxError
 
 150   //  private void throwSyntaxError(String error, int startRow) {
 
 151   //    throw new SyntaxError(startRow, 0, " ", error);
 
 153   private void throwSyntaxError(String error, int problemStartPosition,
 
 154       int problemEndPosition) {
 
 156         .phpParsingError(new String[]{error}, problemStartPosition,
 
 157             problemEndPosition, referenceContext,
 
 158             compilationUnit.compilationResult);
 
 159     throw new SyntaxError(1, 0, " ", error);
 
 161   private void reportSyntaxError(String error, int problemStartPosition,
 
 162       int problemEndPosition) {
 
 164         .phpParsingError(new String[]{error}, problemStartPosition,
 
 165             problemEndPosition, referenceContext,
 
 166             compilationUnit.compilationResult);
 
 169    * Method Declaration.
 
 173   //  private void getChar() {
 
 174   //    if (str.length() > chIndx) {
 
 175   //      ch = str.charAt(chIndx++);
 
 180   //    chIndx = str.length() + 1;
 
 182   //    // token = TokenNameEOF;
 
 186    * gets the next token from input
 
 188   private void getNextToken() {
 
 190       token = scanner.getNextToken();
 
 192         int currentEndPosition = scanner.getCurrentTokenEndPosition();
 
 193         int currentStartPosition = scanner.getCurrentTokenStartPosition();
 
 195             .print(currentStartPosition + "," + currentEndPosition + ": ");
 
 196         System.out.println(scanner.toStringAction(token));
 
 198     } catch (InvalidInputException e) {
 
 199       token = TokenNameERROR;
 
 204    * Get a number. if it's a <code>double</code> the number will be stored in
 
 205    * <code>doubleNumber</code> and the token will have the value
 
 206    * {@link Parser#TokenNameDOUBLE_NUMBER}<br />
 
 207    * if it's a <code>double</code> the number will be stored in <code>longNumber</code>
 
 208    * and the token will have the value {@link Parser#TokenNameINT_NUMBER}
 
 210   //  private void getNumber() {
 
 211   //    StringBuffer inum = new StringBuffer();
 
 213   //    int numFormat = 10;
 
 215   //    // save first digit
 
 216   //    char firstCh = ch;
 
 220   //    // determine number conversions:
 
 221   //    if (firstCh == '0') {
 
 250   //    if (numFormat == 16) {
 
 251   //      while ((ch >= '0' && ch <= '9')
 
 252   //        || (ch >= 'a' && ch <= 'f')
 
 253   //        || (ch >= 'A' && ch <= 'F')) {
 
 258   //      while ((ch >= '0' && ch <= '9')
 
 262   //        if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
 
 263   //          if (ch == '.' && dFlag != ' ') {
 
 266   //          if ((dFlag == 'E') || (dFlag == 'e')) {
 
 272   //          if ((ch == '-') || (ch == '+')) {
 
 285   //      if (dFlag != ' ') {
 
 286   //        doubleNumber = new Double(inum.toString());
 
 287   //        token = TokenNameDoubleLiteral;
 
 290   //        longNumber = Long.valueOf(inum.toString(), numFormat);
 
 291   //        token = TokenNameIntegerLiteral;
 
 295   //    } catch (Throwable e) {
 
 296   //      throwSyntaxError("Number format error: " + inum.toString());
 
 302   //   * @param openChar the opening char ('\'', '"', '`')
 
 303   //   * @param typeString the type of string {@link
 
 304   // #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
 
 305   //   * @param errorMsg the error message in case of parse error in the string
 
 307   //  private void getString(
 
 308   //    final char openChar,
 
 309   //    final int typeString,
 
 310   //    final String errorMsg) {
 
 311   //    StringBuffer sBuffer = new StringBuffer();
 
 312   //    boolean openString = true;
 
 313   //    int startRow = rowCount;
 
 314   //    while (str.length() > chIndx) {
 
 315   //      ch = str.charAt(chIndx++);
 
 317   //        sBuffer.append(ch);
 
 318   //        if (str.length() > chIndx) {
 
 319   //          ch = str.charAt(chIndx++);
 
 320   //          sBuffer.append(ch);
 
 322   //      } else if (ch == openChar) {
 
 323   //        openString = false;
 
 325   //      } else if (ch == '\n') {
 
 327   //        columnCount = chIndx;
 
 329   //        sBuffer.append(ch);
 
 333   //      if (typeString == TokenNameStringConstant) {
 
 334   //        throwSyntaxError(errorMsg, startRow);
 
 336   //        throwSyntaxError(errorMsg);
 
 339   //    token = typeString;
 
 340   //    stringValue = sBuffer.toString();
 
 342   //    public void htmlParserTester(String input) {
 
 343   //            int lineNumber = 1;
 
 344   //            int startLineNumber = 1;
 
 345   //            int startIndex = 0;
 
 348   //            boolean phpMode = false;
 
 349   //            boolean phpFound = false;
 
 351   //            phpList = new ArrayList();
 
 352   //            currentPHPString = 0;
 
 356   //                    while (i < input.length()) {
 
 357   //                            ch = input.charAt(i++);
 
 361   //                            if ((!phpMode) && ch == '<') {
 
 362   //                                    ch2 = input.charAt(i++);
 
 364   //                                            ch2 = input.charAt(i++);
 
 365   //                                            if (Character.isWhitespace(ch2)) {
 
 370   //                                                    startLineNumber = lineNumber;
 
 372   //                                            } else if (ch2 == 'p') {
 
 373   //                                                    ch2 = input.charAt(i++);
 
 375   //                                                            ch2 = input.charAt(i++);
 
 380   //                                                                    startLineNumber = lineNumber;
 
 386   //                                            } else if (ch2 == 'P') {
 
 387   //                                                    ch2 = input.charAt(i++);
 
 389   //                                                            ch2 = input.charAt(i++);
 
 394   //                                                                    startLineNumber = lineNumber;
 
 407   //                                    if (ch == '/' && i < input.length()) {
 
 408   //                                            ch2 = input.charAt(i++);
 
 410   //                                                    while (i < input.length()) {
 
 411   //                                                            ch = input.charAt(i++);
 
 412   //                                                            if (ch == '?' && i < input.length()) {
 
 413   //                                                                    ch2 = input.charAt(i++);
 
 422   //                                                                                            startLineNumber));
 
 426   //                                                            } else if (ch == '\n') {
 
 432   //                                            } else if (ch2 == '*') {
 
 433   //                                                    // multi-line comment
 
 434   //                                                    while (i < input.length()) {
 
 435   //                                                            ch = input.charAt(i++);
 
 438   //                                                            } else if (ch == '*' && i < input.length()) {
 
 439   //                                                                    ch2 = input.charAt(i++);
 
 450   //                                    } else if (ch == '#') {
 
 451   //                                            while (i < input.length()) {
 
 452   //                                                    ch = input.charAt(i++);
 
 453   //                                                    if (ch == '?' && i < input.length()) {
 
 454   //                                                            ch2 = input.charAt(i++);
 
 460   //                                                                                    input.substring(startIndex, i - 2),
 
 461   //                                                                                    startLineNumber));
 
 465   //                                                    } else if (ch == '\n') {
 
 471   //                                    } else if (ch == '"') {
 
 473   //                                            while (i < input.length()) {
 
 474   //                                                    ch = input.charAt(i++);
 
 478   //                                                            ch == '\\' && i < input.length()) { // escape
 
 480   //                                                    } else if (ch == '"') {
 
 485   //                                    } else if (ch == '\'') {
 
 487   //                                            while (i < input.length()) {
 
 488   //                                                    ch = input.charAt(i++);
 
 492   //                                                            ch == '\\' && i < input.length()) { // escape
 
 494   //                                                    } else if (ch == '\'') {
 
 501   //                                    if (ch == '?' && i < input.length()) {
 
 502   //                                            ch2 = input.charAt(i++);
 
 508   //                                                                    input.substring(startIndex, i - 2),
 
 509   //                                                                    startLineNumber));
 
 519   //                                    "No PHP source code found.",
 
 525   //                                            "Open PHP tag at end of file.",
 
 530   //                                                    input.substring(startIndex, i - 2),
 
 531   //                                                    startLineNumber));
 
 533   //                            // for (int j=0;j<phpList.size();j++) {
 
 534   //                            // String temp = ((PHPString)phpList.get(j)).getPHPString();
 
 535   //                            // int startIndx = temp.length()-10;
 
 536   //                            // if (startIndx<0) {
 
 539   //                            // System.out.println(temp.substring(startIndx)+"?>");
 
 541   //                            phpParserTester(null, 1);
 
 542   //                            // PHPString temp;
 
 543   //                            // for(int j=0;j<phpList.size();j++) {
 
 544   //                            // temp = (PHPString) phpList.get(j);
 
 545   //                            // parser.start(temp.getPHPString(), temp.getLineNumber());
 
 548   //            } catch (CoreException e) {
 
 551   public void phpParserTester(String s, int rowCount) {
 
 554       if (phpList.size() != 0) {
 
 555         this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
 
 558     this.token = TokenNameEOF;
 
 560     //    this.rowCount = rowCount;
 
 561     //    this.columnCount = 0;
 
 564     scanner.setSource(s.toCharArray());
 
 565     scanner.setPHPMode(true);
 
 569         if (token != TokenNameEOF && token != TokenNameERROR) {
 
 572         if (token != TokenNameEOF) {
 
 573           if (token == TokenNameERROR) {
 
 574             throwSyntaxError("Scanner error (Found unknown token: "
 
 575                 + scanner.toStringAction(token) + ")");
 
 577           if (token == TokenNameRPAREN) {
 
 578             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
 580           if (token == TokenNameRBRACE) {
 
 581             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
 583           if (token == TokenNameRBRACKET) {
 
 584             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
 586           if (token == TokenNameLPAREN) {
 
 587             throwSyntaxError("Read character '('; end-of-file not reached.");
 
 589           if (token == TokenNameLBRACE) {
 
 590             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
 592           if (token == TokenNameLBRACKET) {
 
 593             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
 595           throwSyntaxError("End-of-file not reached.");
 
 598       } catch (SyntaxError err) {
 
 602           //   setMarker(err.getMessage(), err.getLine(), ERROR);
 
 603           //          setMarker(err.getMessage(),
 
 604           // scanner.getCurrentTokenStartPosition(),
 
 605           // scanner.getCurrentTokenEndPosition(), ERROR);
 
 607         // if an error occured,
 
 608         // try to find keywords 'class' or 'function'
 
 609         // to parse the rest of the string
 
 610         while (token != TokenNameEOF && token != TokenNameERROR) {
 
 611           if (token == TokenNameabstract || token == TokenNamefinal
 
 612               || token == TokenNameclass || token == TokenNamefunction) {
 
 617         if (token == TokenNameEOF || token == TokenNameERROR) {
 
 623   public void init(String s) {
 
 625     this.token = TokenNameEOF;
 
 627     //    this.rowCount = 1;
 
 628     //    this.columnCount = 0;
 
 630     this.phpMode = false;
 
 631     /* scanner initialization */
 
 632     scanner.setSource(s.toCharArray());
 
 633     scanner.setPHPMode(false);
 
 635   protected void initialize(boolean phpMode) {
 
 636     compilationUnit = null;
 
 637     referenceContext = null;
 
 639     this.token = TokenNameEOF;
 
 641     //    this.rowCount = 1;
 
 642     //    this.columnCount = 0;
 
 644     this.phpMode = phpMode;
 
 645     scanner.setPHPMode(phpMode);
 
 648    * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
 
 651   public void parse(String s) {
 
 656    * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
 
 659   protected void parse() {
 
 663         if (token != TokenNameEOF && token != TokenNameERROR) {
 
 666         if (token != TokenNameEOF) {
 
 667           if (token == TokenNameERROR) {
 
 668             throwSyntaxError("Scanner error (Found unknown token: "
 
 669                 + scanner.toStringAction(token) + ")");
 
 671           if (token == TokenNameRPAREN) {
 
 672             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
 674           if (token == TokenNameRBRACE) {
 
 675             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
 677           if (token == TokenNameRBRACKET) {
 
 678             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
 680           if (token == TokenNameLPAREN) {
 
 681             throwSyntaxError("Read character '('; end-of-file not reached.");
 
 683           if (token == TokenNameLBRACE) {
 
 684             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
 686           if (token == TokenNameLBRACKET) {
 
 687             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
 689           throwSyntaxError("End-of-file not reached.");
 
 692       } catch (SyntaxError sytaxErr1) {
 
 693         // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
 
 695         //        setMarker(sytaxErr1.getMessage(),
 
 696         // scanner.getCurrentTokenStartPosition(),
 
 697         // scanner.getCurrentTokenEndPosition(), ERROR);
 
 699           // if an error occured,
 
 700           // try to find keywords 'class' or 'function'
 
 701           // to parse the rest of the string
 
 702           while (token != TokenNameEOF && token != TokenNameERROR) {
 
 703             if (token == TokenNameabstract || token == TokenNamefinal
 
 704                 || token == TokenNameclass || token == TokenNamefunction) {
 
 709           if (token == TokenNameEOF || token == TokenNameERROR) {
 
 712         } catch (SyntaxError sytaxErr2) {
 
 713           //    setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
 
 715           //          setMarker(sytaxErr2.getMessage(),
 
 716           // scanner.getCurrentTokenStartPosition(),
 
 717           // scanner.getCurrentTokenEndPosition(), ERROR);
 
 723   //  public PHPOutlineInfo parseInfo(Object parent, String s) {
 
 724   //    PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
 
 725   //    // Stack stack = new Stack();
 
 726   //    // stack.push(outlineInfo.getDeclarations());
 
 728   //    this.token = TokenNameEOF;
 
 729   //    // this.chIndx = 0;
 
 730   //    // this.rowCount = 1;
 
 731   //    // this.columnCount = 0;
 
 732   //    this.phpEnd = false;
 
 733   //    this.phpMode = false;
 
 734   //    scanner.setSource(s.toCharArray());
 
 735   //    scanner.setPHPMode(false);
 
 738   //    parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
 
 740   //    return outlineInfo;
 
 742   private boolean isVariable() {
 
 743     return token == TokenNameVariable || token == TokenNamethis;
 
 745   //  private void parseDeclarations(PHPOutlineInfo outlineInfo,
 
 746   //      OutlineableWithChildren current, boolean goBack) {
 
 748   //    // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
 
 749   //    PHPSegmentWithChildren temp;
 
 751   //    IPreferenceStore store =
 
 752   // PHPeclipsePlugin.getDefault().getPreferenceStore();
 
 754   //      while (token != TokenNameEOF && token != TokenNameERROR) {
 
 755   //        if (token == TokenNameVariable) {
 
 756   //          ident = scanner.getCurrentIdentifierSource();
 
 757   //          outlineInfo.addVariable(new String(ident));
 
 759   //        } else if (token == TokenNamevar) {
 
 761   //          if (token == TokenNameVariable
 
 762   //              && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
 
 763   //            ident = scanner.getCurrentIdentifierSource();
 
 764   //            //substring(1) added because PHPVarDeclaration doesn't
 
 765   //            // need the $ anymore
 
 766   //            String variableName = new String(ident).substring(1);
 
 767   //            outlineInfo.addVariable(variableName);
 
 769   //            if (token != TokenNameSEMICOLON) {
 
 771   //              ident = scanner.getCurrentTokenSource();
 
 772   //              if (token > TokenNameKEYWORD) {
 
 773   //                current.add(new PHPVarDeclaration(current, variableName,
 
 774   //                // chIndx - ident.length,
 
 775   //                    scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 778   //                  case TokenNameVariable :
 
 779   //                  case TokenNamethis :
 
 780   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 783   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 786   //                  case TokenNameIdentifier :
 
 787   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 790   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 793   //                  case TokenNameDoubleLiteral :
 
 794   //                    current.add(new PHPVarDeclaration(current, variableName
 
 798   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 801   //                  case TokenNameIntegerLiteral :
 
 802   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 805   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 808   //                  case TokenNameStringInterpolated :
 
 809   //                  case TokenNameStringLiteral :
 
 810   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 813   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 816   //                  case TokenNameStringConstant :
 
 817   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 820   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 824   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 827   //                        scanner.getCurrentTokenStartPosition()));
 
 832   //              ident = scanner.getCurrentIdentifierSource();
 
 833   //              current.add(new PHPVarDeclaration(current, variableName,
 
 834   //              // chIndx - ident.length
 
 835   //                  scanner.getCurrentTokenStartPosition()));
 
 838   //        } else if (token == TokenNamefunction) {
 
 840   //          if (token == TokenNameAND) {
 
 843   //          if (token == TokenNameIdentifier
 
 844   //              && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
 
 845   //            ident = scanner.getCurrentIdentifierSource();
 
 846   //            outlineInfo.addVariable(new String(ident));
 
 847   //            temp = new PHPFunctionDeclaration(current, new String(ident),
 
 848   //            // chIndx - ident.length
 
 849   //                scanner.getCurrentTokenStartPosition());
 
 850   //            current.add(temp);
 
 852   //            parseDeclarations(outlineInfo, temp, true);
 
 854   //        } else if (token == TokenNameclass) {
 
 856   //          if (token == TokenNameIdentifier
 
 857   //              && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
 
 858   //            ident = scanner.getCurrentIdentifierSource();
 
 859   //            outlineInfo.addVariable(new String(ident));
 
 860   //            temp = new PHPClassDeclaration(current, new String(ident),
 
 861   //            // chIndx - ident.len
 
 862   //                scanner.getCurrentTokenStartPosition());
 
 863   //            current.add(temp);
 
 864   //            // stack.push(temp);
 
 866   //            //skip tokens for classname, extends and others until
 
 867   //            // we have the opening '{'
 
 868   //            while (token != TokenNameLBRACE && token != TokenNameEOF
 
 869   //                && token != TokenNameERROR) {
 
 872   //            parseDeclarations(outlineInfo, temp, true);
 
 875   //        } else if ((token == TokenNameLBRACE)
 
 876   //            || (token == TokenNameDOLLAR_LBRACE)) {
 
 879   //        } else if (token == TokenNameRBRACE) {
 
 882   //          if (counter == 0 && goBack) {
 
 885   //        } else if (token == TokenNamerequire || token == TokenNamerequire_once
 
 886   //            || token == TokenNameinclude || token == TokenNameinclude_once) {
 
 887   //          ident = scanner.getCurrentTokenSource();
 
 889   //          int startPosition = scanner.getCurrentTokenStartPosition();
 
 891   //          char[] expr = scanner.getCurrentTokenSource(startPosition);
 
 892   //          outlineInfo.addVariable(new String(ident));
 
 893   //          current.add(new PHPReqIncDeclaration(current, new String(ident),
 
 894   //          // chIndx - ident.length,
 
 895   //              startPosition, new String(expr)));
 
 901   //    } catch (SyntaxError sytaxErr) {
 
 903   //      // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
 
 904   //      // setMarker(sytaxErr.getMessage(),
 
 905   //      // scanner.getCurrentTokenStartPosition(),
 
 906   //      // scanner.getCurrentTokenEndPosition(), ERROR);
 
 907   //      // } catch (CoreException e) {
 
 911   private void statementList() {
 
 913       statement(TokenNameEOF);
 
 914       if ((token == TokenNameRBRACE) || (token == TokenNamecase)
 
 915           || (token == TokenNamedefault) || (token == TokenNameelse)
 
 916           || (token == TokenNameelseif) || (token == TokenNameendif)
 
 917           || (token == TokenNameendfor) || (token == TokenNameendforeach)
 
 918           || (token == TokenNameendwhile) || (token == TokenNameendswitch)
 
 919           || (token == TokenNameEOF) || (token == TokenNameERROR)) {
 
 924   private void functionBody(MethodDeclaration methodDecl) {
 
 925     // '{' [statement-list] '}'
 
 926     if (token == TokenNameLBRACE) {
 
 929       throwSyntaxError("'{' expected in compound-statement.");
 
 931     if (token != TokenNameRBRACE) {
 
 934     if (token == TokenNameRBRACE) {
 
 935       methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
 938       throwSyntaxError("'}' expected in compound-statement.");
 
 941   private void statement(int previousToken) {
 
 942     //   if (token > TokenNameKEYWORD && token != TokenNamelist && token !=
 
 944     //  char[] ident = scanner.getCurrentIdentifierSource();
 
 945     //  String keyword = new String(ident);
 
 946     if (token == TokenNameAT) {
 
 948       if (token != TokenNamerequire && token != TokenNamerequire_once
 
 949           && token != TokenNameinclude && token != TokenNameinclude_once
 
 950           && token != TokenNameIdentifier && token != TokenNameVariable
 
 951           && token != TokenNamethis && token != TokenNameStringInterpolated) {
 
 952         throwSyntaxError("identifier expected after '@'.");
 
 955     if (token == TokenNameinclude || token == TokenNameinclude_once) {
 
 957       if (token == TokenNameLPAREN) {
 
 959         if (token == TokenNameSEMICOLON) {
 
 962           if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
 
 963             throwSyntaxError("';' expected after 'include' or 'include_once'.");
 
 968         concatenationExpression();
 
 971     } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
 
 974       if (token == TokenNameLPAREN) {
 
 976         if (token == TokenNameSEMICOLON) {
 
 979           if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
 
 980             throwSyntaxError("';' expected after 'require' or 'require_once'.");
 
 985         concatenationExpression();
 
 988     } else if (token == TokenNameif) {
 
 990       if (token == TokenNameLPAREN) {
 
 993         throwSyntaxError("'(' expected after 'if' keyword.");
 
 996       if (token == TokenNameRPAREN) {
 
 999         throwSyntaxError("')' expected after 'if' condition.");
 
1003     } else if (token == TokenNameswitch) {
 
1005       if (token == TokenNameLPAREN) {
 
1008         throwSyntaxError("'(' expected after 'switch' keyword.");
 
1011       if (token == TokenNameRPAREN) {
 
1014         throwSyntaxError("')' expected after 'switch' condition.");
 
1018     } else if (token == TokenNamefor) {
 
1020       if (token == TokenNameLPAREN) {
 
1023         throwSyntaxError("'(' expected after 'for' keyword.");
 
1025       if (token == TokenNameSEMICOLON) {
 
1029         if (token == TokenNameSEMICOLON) {
 
1032           throwSyntaxError("';' expected after 'for'.");
 
1035       if (token == TokenNameSEMICOLON) {
 
1039         if (token == TokenNameSEMICOLON) {
 
1042           throwSyntaxError("';' expected after 'for'.");
 
1045       if (token == TokenNameRPAREN) {
 
1049         if (token == TokenNameRPAREN) {
 
1052           throwSyntaxError("')' expected after 'for'.");
 
1057     } else if (token == TokenNamewhile) {
 
1059       if (token == TokenNameLPAREN) {
 
1062         throwSyntaxError("'(' expected after 'while' keyword.");
 
1065       if (token == TokenNameRPAREN) {
 
1068         throwSyntaxError("')' expected after 'while' condition.");
 
1072     } else if (token == TokenNamedo) {
 
1074       if (token == TokenNameLBRACE) {
 
1077         throwSyntaxError("'{' expected after 'do' keyword.");
 
1079       if (token != TokenNameRBRACE) {
 
1082       if (token == TokenNameRBRACE) {
 
1085         throwSyntaxError("'}' expected after 'do' keyword.");
 
1087       if (token == TokenNamewhile) {
 
1089         if (token == TokenNameLPAREN) {
 
1092           throwSyntaxError("'(' expected after 'while' keyword.");
 
1095         if (token == TokenNameRPAREN) {
 
1098           throwSyntaxError("')' expected after 'while' condition.");
 
1101         throwSyntaxError("'while' expected after 'do' keyword.");
 
1103       if (token == TokenNameSEMICOLON) {
 
1106         if (token != TokenNameStopPHP) {
 
1107           throwSyntaxError("';' expected after do-while statement.");
 
1112     } else if (token == TokenNameforeach) {
 
1114       if (token == TokenNameLPAREN) {
 
1117         throwSyntaxError("'(' expected after 'foreach' keyword.");
 
1120       if (token == TokenNameas) {
 
1123         throwSyntaxError("'as' expected after 'foreach' exxpression.");
 
1126       if (token == TokenNameEQUAL_GREATER) {
 
1130       if (token == TokenNameRPAREN) {
 
1133         throwSyntaxError("')' expected after 'foreach' expression.");
 
1137     } else if (token == TokenNamecontinue || token == TokenNamebreak
 
1138         || token == TokenNamereturn) {
 
1140       if (token != TokenNameSEMICOLON) {
 
1143       if (token == TokenNameSEMICOLON) {
 
1146         if (token != TokenNameStopPHP) {
 
1147           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
 
1152     } else if (token == TokenNameecho) {
 
1155       if (token == TokenNameSEMICOLON) {
 
1158         if (token != TokenNameStopPHP) {
 
1159           throwSyntaxError("';' expected after 'echo' statement.");
 
1164       //    } else if (token == TokenNameprint) {
 
1167       //      if (token == TokenNameSEMICOLON) {
 
1170       //        if (token != TokenNameStopPHP) {
 
1171       //          throwSyntaxError("';' expected after 'print' statement.");
 
1176     } else if (token == TokenNameglobal || token == TokenNamestatic) {
 
1179       if (token == TokenNameSEMICOLON) {
 
1182         if (token != TokenNameStopPHP) {
 
1183           throwSyntaxError("';' expected after 'global' or 'static' statement.");
 
1188     } else if (token == TokenNameunset) {
 
1190       if (token == TokenNameLPAREN) {
 
1193         throwSyntaxError("'(' expected after 'unset' statement.");
 
1196       if (token == TokenNameRPAREN) {
 
1199         throwSyntaxError("')' expected after 'unset' statement.");
 
1201       if (token == TokenNameSEMICOLON) {
 
1204         if (token != TokenNameStopPHP) {
 
1205           throwSyntaxError("';' expected after 'unset' statement.");
 
1210       //      } else if (token == TokenNameexit || token == TokenNamedie) {
 
1212       //        if (token != TokenNameSEMICOLON) {
 
1215       //        if (token == TokenNameSEMICOLON) {
 
1218       //          if (token != TokenNameStopPHP) {
 
1219       //            throwSyntaxError("';' expected after 'exit' or 'die'
 
1225 //    } else if (token == TokenNamedefine) {
 
1227 //      if (token == TokenNameLPAREN) {
 
1230 //        throwSyntaxError("'(' expected after 'define' keyword.");
 
1233 //      if (token == TokenNameCOMMA) {
 
1236 //        throwSyntaxError("',' expected after first 'define' constant.");
 
1239 //      if (token == TokenNameCOMMA) {
 
1243 //      if (token == TokenNameRPAREN) {
 
1246 //        throwSyntaxError("')' expected after 'define' statement.");
 
1248 //      if (token == TokenNameSEMICOLON) {
 
1251 //        if (token != TokenNameStopPHP) {
 
1252 //          throwSyntaxError("';' expected after 'define' statement.");
 
1257     } else if (token == TokenNamefunction) {
 
1258       MethodDeclaration methodDecl = new MethodDeclaration(
 
1259           this.compilationUnit.compilationResult);
 
1260       methodDecl.declarationSourceStart = scanner
 
1261           .getCurrentTokenStartPosition();
 
1263       functionDefinition(methodDecl);
 
1265     } else if (token == TokenNamefinal || token == TokenNameabstract
 
1266         || token == TokenNameclass || token == TokenNameinterface) {
 
1267       TypeDeclaration typeDecl = new TypeDeclaration(
 
1268           this.compilationUnit.compilationResult);
 
1269       typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1270       // default super class
 
1271       typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
 
1272       compilationUnit.types.add(typeDecl);
 
1274         pushOnAstStack(typeDecl);
 
1275         unticked_class_declaration_statement(typeDecl);
 
1276         //        classBody(typeDecl);
 
1283       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
 
1284     } else if (token == TokenNameLBRACE) {
 
1286       if (token != TokenNameRBRACE) {
 
1289       if (token == TokenNameRBRACE) {
 
1293         throwSyntaxError("'}' expected.");
 
1296       if (token != TokenNameSEMICOLON) {
 
1299       if (token == TokenNameSEMICOLON) {
 
1303         if (token != TokenNameStopPHP && token != TokenNameEOF) {
 
1304           throwSyntaxError("';' expected after expression (Found token: "
 
1305               + scanner.toStringAction(token) + ")");
 
1311   private void unset_variables() {
 
1314     //          | unset_variables ',' unset_variable
 
1319       if (token != TokenNameCOMMA) {
 
1325   private final void initializeModifiers() {
 
1327     this.modifiersSourceStart = -1;
 
1329   private final void checkAndSetModifiers(int flag) {
 
1330     this.modifiers |= flag;
 
1331     if (this.modifiersSourceStart < 0)
 
1332       this.modifiersSourceStart = this.scanner.startPosition;
 
1334   private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
 
1335     initializeModifiers();
 
1336     if (token == TokenNameinterface) {
 
1337       //      interface_entry T_STRING
 
1338       //                interface_extends_list
 
1339       //                '{' class_statement_list '}'
 
1340       checkAndSetModifiers(AccInterface);
 
1342       typeDecl.modifiers = this.modifiers;
 
1343       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
1344         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1345         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1346         typeDecl.name = scanner.getCurrentIdentifierSource();
 
1347         if (token > TokenNameKEYWORD) {
 
1348           throwSyntaxError("Don't use a keyword for interface declaration ["
 
1349               + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
 
1350               typeDecl.sourceEnd);
 
1353         interface_extends_list();
 
1355         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1356         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1357         typeDecl.name = new char[]{' '};
 
1358         throwSyntaxError("Interface name expected after keyword 'interface'.",
 
1359             typeDecl.sourceStart, typeDecl.sourceEnd);
 
1363       //      class_entry_type T_STRING extends_from
 
1365       //                '{' class_statement_list'}'
 
1367       typeDecl.modifiers = this.modifiers;
 
1369       //identifier 'extends' identifier
 
1370       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
1371         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1372         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1373         typeDecl.name = scanner.getCurrentIdentifierSource();
 
1374         if (token > TokenNameKEYWORD) {
 
1375           throwSyntaxError("Don't use a keyword for class declaration ["
 
1376               + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
 
1377               typeDecl.sourceEnd);
 
1382         //      | T_EXTENDS fully_qualified_class_name
 
1383         if (token == TokenNameextends) {
 
1385           if (token == TokenNameIdentifier) {
 
1388             throwSyntaxError("Class name expected after keyword 'extends'.",
 
1389                 scanner.getCurrentTokenStartPosition(), scanner
 
1390                     .getCurrentTokenEndPosition());
 
1395         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1396         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1397         typeDecl.name = new char[]{' '};
 
1398         throwSyntaxError("Class name expected after keyword 'class'.",
 
1399             typeDecl.sourceStart, typeDecl.sourceEnd);
 
1403     //  '{' class_statement_list '}'
 
1404     if (token == TokenNameLBRACE) {
 
1406       if (token != TokenNameRBRACE) {
 
1407         class_statement_list();
 
1409       if (token == TokenNameRBRACE) {
 
1410         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1413         throwSyntaxError("'}' expected at end of class body.");
 
1416       throwSyntaxError("'{' expected at start of class body.");
 
1419   private void class_entry_type() {
 
1421     //  | T_ABSTRACT T_CLASS
 
1422     //  | T_FINAL T_CLASS
 
1423     if (token == TokenNameclass) {
 
1425     } else if (token == TokenNameabstract) {
 
1426       checkAndSetModifiers(AccAbstract);
 
1428       if (token != TokenNameclass) {
 
1429         throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
 
1432     } else if (token == TokenNamefinal) {
 
1433       checkAndSetModifiers(AccFinal);
 
1435       if (token != TokenNameclass) {
 
1436         throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
 
1440         throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
 
1443   private void interface_extends_list() {
 
1445     //  | T_EXTENDS interface_list
 
1446     if (token == TokenNameextends) {
 
1451   private void implements_list() {
 
1453     //  | T_IMPLEMENTS interface_list
 
1454     if (token == TokenNameimplements) {
 
1459   private void interface_list() {
 
1461     //  fully_qualified_class_name
 
1462     //| interface_list ',' fully_qualified_class_name
 
1464       if (token == TokenNameIdentifier) {
 
1467         throwSyntaxError("Interface name expected after keyword 'implements'.");
 
1469       if (token != TokenNameCOMMA) {
 
1475   //  private void classBody(TypeDeclaration typeDecl) {
 
1476   //    //'{' [class-element-list] '}'
 
1477   //    if (token == TokenNameLBRACE) {
 
1479   //      if (token != TokenNameRBRACE) {
 
1480   //        class_statement_list();
 
1482   //      if (token == TokenNameRBRACE) {
 
1483   //        typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1486   //        throwSyntaxError("'}' expected at end of class body.");
 
1489   //      throwSyntaxError("'{' expected at start of class body.");
 
1492   private void class_statement_list() {
 
1495     } while (token == TokenNamepublic || 
 
1496         token == TokenNameprotected || 
 
1497         token == TokenNameprivate || 
 
1498         token == TokenNamestatic || 
 
1499         token == TokenNameabstract || 
 
1500         token == TokenNamefinal || 
 
1501         token == TokenNamefunction || 
 
1502         token == TokenNamevar);
 
1504   private void class_statement() {
 
1506     //          variable_modifiers class_variable_declaration ';'
 
1507     //  | class_constant_declaration ';'
 
1508     //  | method_modifiers T_FUNCTION is_reference T_STRING
 
1509     //    '(' parameter_list ')' method_body
 
1510     initializeModifiers();
 
1511     if (token == TokenNamevar) {
 
1512       checkAndSetModifiers(AccPublic);
 
1514           "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected' modifier for field declarations.",
 
1515           scanner.getCurrentTokenStartPosition(), scanner
 
1516               .getCurrentTokenEndPosition());
 
1520       boolean hasModifiers = member_modifiers();
 
1521       if (token == TokenNamefunction) {
 
1522         if (!hasModifiers) {
 
1523           checkAndSetModifiers(AccPublic);
 
1525         MethodDeclaration methodDecl = new MethodDeclaration(
 
1526             this.compilationUnit.compilationResult);
 
1527         methodDecl.declarationSourceStart = scanner
 
1528             .getCurrentTokenStartPosition();
 
1529         methodDecl.modifiers = this.modifiers;
 
1531         functionDefinition(methodDecl);
 
1533         if (!hasModifiers) {
 
1534           throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
 
1539     //    if (token == TokenNamefunction) {
 
1540     //      MethodDeclaration methodDecl = new MethodDeclaration(
 
1541     //          this.compilationUnit.compilationResult);
 
1542     //      methodDecl.declarationSourceStart = scanner
 
1543     //          .getCurrentTokenStartPosition();
 
1545     //      functionDefinition(methodDecl);
 
1546     //    } else if (token == TokenNamevar) {
 
1550     //      throwSyntaxError("'function' or 'var' expected.");
 
1553   //  private void variable_modifiers() {
 
1554   //    // variable_modifiers:
 
1555   //    // non_empty_member_modifiers
 
1557   //    initializeModifiers();
 
1558   //    if (token == TokenNamevar) {
 
1559   //      checkAndSetModifiers(AccPublic);
 
1560   //      reportSyntaxError(
 
1561   //          "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
 
1562   // modifier for field declarations.",
 
1563   //          scanner.getCurrentTokenStartPosition(), scanner
 
1564   //              .getCurrentTokenEndPosition());
 
1567   //      if (!member_modifiers()) {
 
1568   //        throwSyntaxError("'public' 'private' or 'protected' modifier expected for
 
1569   // field declarations.");
 
1573   //  private void method_modifiers() {
 
1574   //    //method_modifiers:
 
1576   //    //| non_empty_member_modifiers
 
1577   //    initializeModifiers();
 
1578   //    if (!member_modifiers()) {
 
1579   //      checkAndSetModifiers(AccPublic);
 
1582   private boolean member_modifiers() {
 
1589     boolean foundToken = false;
 
1591       if (token == TokenNamepublic) {
 
1592         checkAndSetModifiers(AccPublic);
 
1595       } else if (token == TokenNameprotected) {
 
1596         checkAndSetModifiers(AccProtected);
 
1599       } else if (token == TokenNameprivate) {
 
1600         checkAndSetModifiers(AccPrivate);
 
1603       } else if (token == TokenNamestatic) {
 
1604         checkAndSetModifiers(AccStatic);
 
1607       } else if (token == TokenNameabstract) {
 
1608         checkAndSetModifiers(AccAbstract);
 
1611       } else if (token == TokenNamefinal) {
 
1612         checkAndSetModifiers(AccFinal);
 
1621   private void classProperty() {
 
1622     //'var' variable ';'
 
1623     //'var' variable '=' constant ';'
 
1625       if (token == TokenNameVariable) {
 
1627         if (token == TokenNameEQUAL) {
 
1632         if (token == TokenNamethis) {
 
1633           throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
 
1635         throwSyntaxError("Variable expected after keyword 'var'.");
 
1637       if (token != TokenNameCOMMA) {
 
1642     if (token == TokenNameSEMICOLON) {
 
1645       throwSyntaxError("';' expected after variable declaration.");
 
1648   private void functionDefinition(MethodDeclaration methodDecl) {
 
1650       compilationUnit.types.add(methodDecl);
 
1652       AstNode node = astStack[astPtr];
 
1653       if (node instanceof TypeDeclaration) {
 
1654         TypeDeclaration typeDecl = ((TypeDeclaration) node);
 
1655         if (typeDecl.methods == null) {
 
1656           typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
 
1658           AbstractMethodDeclaration[] newMethods;
 
1663                   newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
 
1664                   1, typeDecl.methods.length);
 
1665           newMethods[0] = methodDecl;
 
1666           typeDecl.methods = newMethods;
 
1670     functionDeclarator(methodDecl);
 
1671     functionBody(methodDecl);
 
1673   private void functionDeclarator(MethodDeclaration methodDecl) {
 
1674     //identifier '(' [parameter-list] ')'
 
1675     if (token == TokenNameAND) {
 
1678     if (token == TokenNameIdentifier) {
 
1679       methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1680       methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1681       methodDecl.selector = scanner.getCurrentIdentifierSource();
 
1683       if (token == TokenNameLPAREN) {
 
1686         throwSyntaxError("'(' expected in function declaration.");
 
1688       if (token != TokenNameRPAREN) {
 
1691       if (token != TokenNameRPAREN) {
 
1692         throwSyntaxError("')' expected in function declaration.");
 
1694         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
 
1698       if (token > TokenNameKEYWORD) {
 
1699         throwSyntaxError("Don't use keyword for function declaration [" + token
 
1702       throwSyntaxError("Function name expected after keyword 'function'.");
 
1706   private void parameterList() {
 
1707     //parameter-declaration
 
1708     //parameter-list ',' parameter-declaration
 
1710       parameterDeclaration();
 
1711       if (token != TokenNameCOMMA) {
 
1717   private void parameterDeclaration() {
 
1719     //variable-reference
 
1720     if (token == TokenNameAND) {
 
1725         throwSyntaxError("Variable expected after reference operator '&'.");
 
1728     //variable '=' constant
 
1729     if (token == TokenNameVariable) {
 
1731       if (token == TokenNameEQUAL) {
 
1737     if (token == TokenNamethis) {
 
1738       throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
 
1741   private void labeledStatementList() {
 
1742     if (token != TokenNamecase && token != TokenNamedefault) {
 
1743       throwSyntaxError("'case' or 'default' expected.");
 
1746       if (token == TokenNamecase) {
 
1748         expr(); //constant();
 
1749         if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
 
1751           if (token == TokenNamecase || token == TokenNamedefault) { // empty
 
1759         //        else if (token == TokenNameSEMICOLON) {
 
1761         //            "':' expected after 'case' keyword (Found token: " +
 
1762         // scanner.toStringAction(token) + ")",
 
1763         //            scanner.getCurrentTokenStartPosition(),
 
1764         //            scanner.getCurrentTokenEndPosition(),
 
1767         //          if (token == TokenNamecase) { // empty case statement ?
 
1773           throwSyntaxError("':' character after 'case' constant expected (Found token: "
 
1774               + scanner.toStringAction(token) + ")");
 
1776       } else { // TokenNamedefault
 
1778         if (token == TokenNameCOLON) {
 
1782           throwSyntaxError("':' character after 'default' expected.");
 
1785     } while (token == TokenNamecase || token == TokenNamedefault);
 
1787   //  public void labeledStatement() {
 
1788   //    if (token == TokenNamecase) {
 
1791   //      if (token == TokenNameDDOT) {
 
1795   //        throwSyntaxError("':' character after 'case' constant expected.");
 
1798   //    } else if (token == TokenNamedefault) {
 
1800   //      if (token == TokenNameDDOT) {
 
1804   //        throwSyntaxError("':' character after 'default' expected.");
 
1809   //  public void expressionStatement() {
 
1811   //  private void inclusionStatement() {
 
1813   //  public void compoundStatement() {
 
1815   //  public void selectionStatement() {
 
1818   //  public void iterationStatement() {
 
1821   //  public void jumpStatement() {
 
1824   //  public void outputStatement() {
 
1827   //  public void scopeStatement() {
 
1830   //  public void flowStatement() {
 
1833   //  public void definitionStatement() {
 
1835   private void ifStatement() {
 
1836     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
 
1837     if (token == TokenNameCOLON) {
 
1839       if (token != TokenNameendif) {
 
1842           case TokenNameelse :
 
1844             if (token == TokenNameCOLON) {
 
1846               if (token != TokenNameendif) {
 
1850               if (token == TokenNameif) { //'else if'
 
1852                 elseifStatementList();
 
1854                 throwSyntaxError("':' expected after 'else'.");
 
1858           case TokenNameelseif :
 
1860             elseifStatementList();
 
1864       if (token != TokenNameendif) {
 
1865         throwSyntaxError("'endif' expected.");
 
1868       if (token != TokenNameSEMICOLON) {
 
1869         throwSyntaxError("';' expected after if-statement.");
 
1873       // statement [else-statement]
 
1874       statement(TokenNameEOF);
 
1875       if (token == TokenNameelseif) {
 
1877         if (token == TokenNameLPAREN) {
 
1880           throwSyntaxError("'(' expected after 'elseif' keyword.");
 
1883         if (token == TokenNameRPAREN) {
 
1886           throwSyntaxError("')' expected after 'elseif' condition.");
 
1889       } else if (token == TokenNameelse) {
 
1891         statement(TokenNameEOF);
 
1895   private void elseifStatementList() {
 
1899         case TokenNameelse :
 
1901           if (token == TokenNameCOLON) {
 
1903             if (token != TokenNameendif) {
 
1908             if (token == TokenNameif) { //'else if'
 
1911               throwSyntaxError("':' expected after 'else'.");
 
1915         case TokenNameelseif :
 
1923   private void elseifStatement() {
 
1924     if (token == TokenNameLPAREN) {
 
1927       if (token != TokenNameRPAREN) {
 
1928         throwSyntaxError("')' expected in else-if-statement.");
 
1931       if (token != TokenNameCOLON) {
 
1932         throwSyntaxError("':' expected in else-if-statement.");
 
1935       if (token != TokenNameendif) {
 
1940   private void switchStatement() {
 
1941     if (token == TokenNameCOLON) {
 
1942       // ':' [labeled-statement-list] 'endswitch' ';'
 
1944       labeledStatementList();
 
1945       if (token != TokenNameendswitch) {
 
1946         throwSyntaxError("'endswitch' expected.");
 
1949       if (token != TokenNameSEMICOLON) {
 
1950         throwSyntaxError("';' expected after switch-statement.");
 
1954       // '{' [labeled-statement-list] '}'
 
1955       if (token != TokenNameLBRACE) {
 
1956         throwSyntaxError("'{' expected in switch statement.");
 
1959       if (token != TokenNameRBRACE) {
 
1960         labeledStatementList();
 
1962       if (token != TokenNameRBRACE) {
 
1963         throwSyntaxError("'}' expected in switch statement.");
 
1968   private void forStatement() {
 
1969     if (token == TokenNameCOLON) {
 
1972       if (token != TokenNameendfor) {
 
1973         throwSyntaxError("'endfor' expected.");
 
1976       if (token != TokenNameSEMICOLON) {
 
1977         throwSyntaxError("';' expected after for-statement.");
 
1981       statement(TokenNameEOF);
 
1984   private void whileStatement() {
 
1985     // ':' statement-list 'endwhile' ';'
 
1986     if (token == TokenNameCOLON) {
 
1989       if (token != TokenNameendwhile) {
 
1990         throwSyntaxError("'endwhile' expected.");
 
1993       if (token != TokenNameSEMICOLON) {
 
1994         throwSyntaxError("';' expected after while-statement.");
 
1998       statement(TokenNameEOF);
 
2001   private void foreachStatement() {
 
2002     if (token == TokenNameCOLON) {
 
2005       if (token != TokenNameendforeach) {
 
2006         throwSyntaxError("'endforeach' expected.");
 
2009       if (token != TokenNameSEMICOLON) {
 
2010         throwSyntaxError("';' expected after foreach-statement.");
 
2014       statement(TokenNameEOF);
 
2017   //  private void exitStatus() {
 
2018   //    if (token == TokenNameLPAREN) {
 
2021   //      throwSyntaxError("'(' expected in 'exit-status'.");
 
2023   //    if (token != TokenNameRPAREN) {
 
2026   //    if (token == TokenNameRPAREN) {
 
2029   //      throwSyntaxError("')' expected after 'exit-status'.");
 
2032   private void expressionList() {
 
2035       if (token == TokenNameCOMMA) {
 
2042   private void expr() {
 
2043     //todo: find a better way to get the expression
 
2044     //    expression = new StringBuffer();
 
2045     //    for (int i = chIndx; i < str.length(); i++) {
 
2046     //      if (str.charAt(i) == ';') {
 
2049     //      expression.append(str.charAt(i));
 
2051     //    if (token == TokenNameSTRING_CONSTANT || token ==
 
2052     // TokenNameINTERPOLATED_STRING) {
 
2055     logicalinclusiveorExpression();
 
2056     //      while (token != TokenNameSEMICOLON) {
 
2061   private void expr_without_variable() {
 
2064     boolean castFlag = false;
 
2065     boolean arrayFlag = false;
 
2067       case TokenNameisset :
 
2068       case TokenNameempty :
 
2069       case TokenNameeval :
 
2070       case TokenNameinclude :
 
2071       case TokenNameinclude_once :
 
2072       case TokenNamerequire :
 
2073       case TokenNamerequire_once :
 
2074         internal_functions_in_yacc();
 
2080       case TokenNamenull :
 
2083       case TokenNamefalse :
 
2086       case TokenNametrue :
 
2089       case TokenNameStringConstant :
 
2092       case TokenNameHEREDOC :
 
2093       case TokenNameStringInterpolated :
 
2094       case TokenNameStringLiteral :
 
2097       case TokenNameLPAREN :
 
2099         if (token == TokenNameIdentifier) {
 
2100           // check if identifier is a type:
 
2101           //    ident = identifier;
 
2102           ident = scanner.getCurrentIdentifierSource();
 
2103           String str = new String(ident).toLowerCase();
 
2104           for (int i = 0; i < PHP_TYPES.length; i++) {
 
2105             if (PHP_TYPES[i].equals(str)) {
 
2107               if (PHP_TYPES[i].equals("array")) {
 
2116           if (arrayFlag && token == TokenNameLPAREN) {
 
2118             if (token == TokenNameRPAREN) {
 
2122               if (token != TokenNameRPAREN) {
 
2123                 throwSyntaxError(") expected after 'array('.");
 
2127           if (token != TokenNameRPAREN) {
 
2128             throwSyntaxError(") expected after cast-type '" + str + "'.");
 
2136         if (token != TokenNameRPAREN) {
 
2137           throwSyntaxError(") expected in postfix-expression.");
 
2141       case TokenNameDoubleLiteral :
 
2144       case TokenNameIntegerLiteral :
 
2147       case TokenNameDOLLAR_LBRACE :
 
2150         if (token != TokenNameRBRACE) {
 
2151           throwSyntaxError("'}' expected after indirect variable token '${'.");
 
2155       case TokenNameVariable :
 
2156       case TokenNamethis :
 
2157         ident = scanner.getCurrentIdentifierSource();
 
2159         if (token == TokenNameLBRACE) {
 
2162           if (token != TokenNameRBRACE) {
 
2163             throwSyntaxError("'}' expected after variable '"
 
2164                 + new String(ident) + "' in variable-expression.");
 
2167         } else if (token == TokenNameLPAREN) {
 
2169           if (token != TokenNameRPAREN) {
 
2171             if (token != TokenNameRPAREN) {
 
2172               throwSyntaxError("')' expected after variable '"
 
2173                   + new String(ident) + "' in postfix-expression.");
 
2179       case TokenNameIdentifier :
 
2180         ident = scanner.getCurrentIdentifierSource();
 
2182         if (token == TokenNameLPAREN) {
 
2184           if (token != TokenNameRPAREN) {
 
2186             if (token != TokenNameRPAREN) {
 
2187               throwSyntaxError("')' expected after identifier '"
 
2188                   + new String(ident) + "' in postfix-expression."
 
2189                   + "(Found token: " + scanner.toStringAction(token) + ")");
 
2195       case TokenNamearray :
 
2196     //    T_ARRAY '(' array_pair_list ')'
 
2198         if (token == TokenNameLPAREN) {
 
2200           if (token == TokenNameRPAREN) {
 
2205           if (token != TokenNameRPAREN) {
 
2206             throwSyntaxError("')' expected after keyword 'array'"
 
2207                 + "(Found token: " + scanner.toStringAction(token) + ")");
 
2211           throwSyntaxError("'(' expected after keyword 'array'"
 
2212               + "(Found token: " + scanner.toStringAction(token) + ")");
 
2215       case TokenNameprint :
 
2219       case TokenNameexit :
 
2223       case TokenNamelist :
 
2225         if (token == TokenNameLPAREN) {
 
2227           if (token == TokenNameCOMMA) {
 
2231           if (token != TokenNameRPAREN) {
 
2232             throwSyntaxError("')' expected after 'list' keyword.");
 
2235           //          if (token == TokenNameSET) {
 
2237           //            logicalinclusiveorExpression();
 
2240           throwSyntaxError("'(' expected after 'list' keyword.");
 
2243     //      case TokenNameexit :
 
2245     //        if (token != TokenNameSEMICOLON) {
 
2248     //        if (token == TokenNameSEMICOLON) {
 
2251     //          if (token != TokenNameStopPHP) {
 
2252     //            throwSyntaxError("';' expected after 'exit' expression.");
 
2257     //      case TokenNamedie :
 
2259     //        if (token != TokenNameSEMICOLON) {
 
2262     //        if (token == TokenNameSEMICOLON) {
 
2265     //          if (token != TokenNameStopPHP) {
 
2266     //            throwSyntaxError("';' expected after 'die' expression.");
 
2270     //      case TokenNamearray :
 
2272     //        if (token == TokenNameARGOPEN) {
 
2274     //          if (token == TokenNameCOMMA) {
 
2277     //          expressionList();
 
2278     //          if (token != TokenNameARGCLOSE) {
 
2279     //            throwSyntaxError("')' expected after 'list' keyword.");
 
2282     //          if (token == TokenNameSET) {
 
2284     //            logicalinclusiveorExpression();
 
2287     //          throwSyntaxError("'(' expected after 'list' keyword.");
 
2291     boolean while_flag = true;
 
2294         case TokenNameLBRACKET :
 
2297           if (token != TokenNameRBRACKET) {
 
2298             throwSyntaxError("] expected in postfix-expression.");
 
2302         case TokenNameCOLON_COLON :
 
2304         case TokenNameMINUS_GREATER :
 
2307           if (token > TokenNameKEYWORD) {
 
2308             ident = scanner.getCurrentIdentifierSource();
 
2310             //              "Avoid using keyword '"
 
2311             //                + new String(ident)
 
2312             //                + "' as variable name.",
 
2316             //              "Avoid using keyword '" + new String(ident) + "' as
 
2318             //              scanner.getCurrentTokenStartPosition(),
 
2319             //              scanner.getCurrentTokenEndPosition(),
 
2323             case TokenNameVariable :
 
2324               ident = scanner.getCurrentIdentifierSource();
 
2326               //              if (token == TokenNameARGOPEN) {
 
2328               //                expressionList();
 
2329               //                if (token != TokenNameARGCLOSE) {
 
2330               //                  throwSyntaxError(") expected after variable '" +
 
2336             case TokenNameIdentifier :
 
2337               //ident = scanner.getCurrentIdentifierSource();
 
2340             case TokenNameLBRACE :
 
2343               if (token != TokenNameRBRACE) {
 
2344                 throwSyntaxError("} expected in postfix-expression.");
 
2349               throwSyntaxError("Syntax error after '->' token.");
 
2351           while (token == TokenNameLBRACKET || token == TokenNameLPAREN
 
2352               || token == TokenNameLBRACE) {
 
2353             if (token == TokenNameLBRACKET) {
 
2356               if (token != TokenNameRBRACKET) {
 
2357                 throwSyntaxError("] expected after '->'.");
 
2360             } else if (token == TokenNameLPAREN) {
 
2363               if (token != TokenNameRPAREN) {
 
2364                 throwSyntaxError(") expected after '->'.");
 
2367             } else if (token == TokenNameLBRACE) {
 
2370               if (token != TokenNameRBRACE) {
 
2371                 throwSyntaxError("} expected after '->'.");
 
2377         case TokenNamePLUS_PLUS :
 
2380         case TokenNameMINUS_MINUS :
 
2386     } while (while_flag);
 
2388   private void array_pair_list() {
 
2391 //|     non_empty_array_pair_list possible_comma        
 
2392     non_empty_array_pair_list();
 
2393     if (token == TokenNameCOMMA) {
 
2399   private void non_empty_array_pair_list() {
 
2400 //non_empty_array_pair_list:
 
2401 //      non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr   
 
2402 //|     non_empty_array_pair_list ',' expr                       
 
2403 //|     expr T_DOUBLE_ARROW expr 
 
2405 //|     non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable 
 
2406 //|     non_empty_array_pair_list ',' '&' w_variable  
 
2407 //|     expr T_DOUBLE_ARROW '&' w_variable 
 
2411   private void unaryExpression() {
 
2413       case TokenNamePLUS_PLUS :
 
2417       case TokenNameMINUS_MINUS :
 
2421       // '@' '&' '*' '+' '-' '~' '!'
 
2424         if (token == TokenNameinclude || token == TokenNameinclude_once
 
2425             || token == TokenNamerequire || token == TokenNamerequire_once) {
 
2426           statement(TokenNameAT);
 
2428           expr_without_variable(); //  castExpression();
 
2435       case TokenNameMULTIPLY :
 
2439       case TokenNamePLUS :
 
2443       case TokenNameMINUS :
 
2447       case TokenNameTWIDDLE :
 
2456         expr_without_variable();
 
2459   private void castExpression() {
 
2460     //    if (token == TokenNameARGOPEN) {
 
2463     //      if (token != TokenNameARGCLOSE) {
 
2464     //        throwSyntaxError(") expected after cast-expression.");
 
2470   private void assignExpression() {
 
2472     if (token == TokenNameEQUAL) { // =
 
2474       logicalinclusiveorExpression();
 
2475     } else if (token == TokenNameDOT_EQUAL) { // .=
 
2477       logicalinclusiveorExpression();
 
2478     } else if (token == TokenNameEQUAL_GREATER) { // =>
 
2480       logicalinclusiveorExpression();
 
2481     } else if (token == TokenNamePLUS_EQUAL) { // +=
 
2483       logicalinclusiveorExpression();
 
2484     } else if (token == TokenNameMINUS_EQUAL) { // -=
 
2486       logicalinclusiveorExpression();
 
2487     } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
 
2489       logicalinclusiveorExpression();
 
2490     } else if (token == TokenNameDIVIDE_EQUAL) { // *=
 
2492       logicalinclusiveorExpression();
 
2493     } else if (token == TokenNameREMAINDER_EQUAL) { // %=
 
2495       logicalinclusiveorExpression();
 
2496     } else if (token == TokenNameAND_EQUAL) { // &=
 
2498       logicalinclusiveorExpression();
 
2499     } else if (token == TokenNameOR_EQUAL) { // |=
 
2501       logicalinclusiveorExpression();
 
2502     } else if (token == TokenNameXOR_EQUAL) { // ^=
 
2504       logicalinclusiveorExpression();
 
2505     } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
 
2507       logicalinclusiveorExpression();
 
2508     } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
 
2510       logicalinclusiveorExpression();
 
2511     } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
 
2513       logicalinclusiveorExpression();
 
2516   private void multiplicativeExpression() {
 
2519       if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE
 
2520           && token != TokenNameREMAINDER) {
 
2526   private void concatenationExpression() {
 
2528       multiplicativeExpression();
 
2529       if (token != TokenNameDOT) {
 
2535   private void additiveExpression() {
 
2537       concatenationExpression();
 
2538       if (token != TokenNamePLUS && token != TokenNameMINUS) {
 
2544   private void shiftExpression() {
 
2546       additiveExpression();
 
2547       if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
 
2553   private void relationalExpression() {
 
2556       if (token != TokenNameLESS && token != TokenNameGREATER
 
2557           && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
 
2563   private void identicalExpression() {
 
2565       relationalExpression();
 
2566       if (token != TokenNameEQUAL_EQUAL_EQUAL
 
2567           && token != TokenNameNOT_EQUAL_EQUAL) {
 
2573   private void equalityExpression() {
 
2575       identicalExpression();
 
2576       if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
 
2582   private void ternaryExpression() {
 
2583     equalityExpression();
 
2584     if (token == TokenNameQUESTION) {
 
2587       if (token == TokenNameCOLON) {
 
2591         throwSyntaxError("':' expected in ternary operator '? :'.");
 
2595   private void andExpression() {
 
2597       ternaryExpression();
 
2598       if (token != TokenNameAND) {
 
2604   private void exclusiveorExpression() {
 
2607       if (token != TokenNameXOR) {
 
2613   private void inclusiveorExpression() {
 
2615       exclusiveorExpression();
 
2616       if (token != TokenNameOR) {
 
2622   private void booleanandExpression() {
 
2624       inclusiveorExpression();
 
2625       if (token != TokenNameAND_AND) {
 
2631   private void booleanorExpression() {
 
2633       booleanandExpression();
 
2634       if (token != TokenNameOR_OR) {
 
2640   private void logicalandExpression() {
 
2642       booleanorExpression();
 
2643       if (token != TokenNameAND) {
 
2649   private void logicalexclusiveorExpression() {
 
2651       logicalandExpression();
 
2652       if (token != TokenNameXOR) {
 
2658   private void logicalinclusiveorExpression() {
 
2660       logicalexclusiveorExpression();
 
2661       if (token != TokenNameOR) {
 
2667   //  public void assignmentExpression() {
 
2668   //    if (token == TokenNameVARIABLE) {
 
2670   //      if (token == TokenNameSET) {
 
2672   //        logicalinclusiveorExpression();
 
2675   //      logicalinclusiveorExpression();
 
2678   private void variableList() {
 
2681       if (token == TokenNameCOMMA) {
 
2688   private void variable() {
 
2689     if (token == TokenNameDOLLAR_LBRACE) {
 
2693       if (token != TokenNameRBRACE) {
 
2694         throwSyntaxError("'}' expected after indirect variable token '${'.");
 
2698       if (token == TokenNameVariable) {
 
2700         if (token == TokenNameLBRACKET) {
 
2703           if (token != TokenNameRBRACKET) {
 
2704             throwSyntaxError("']' expected in variable-list.");
 
2707         } else if (token == TokenNameEQUAL) {
 
2712         throwSyntaxError("$-variable expected in variable-list.");
 
2716   private void exit_expr() {
 
2720     if (token != TokenNameLPAREN) {
 
2724     if (token == TokenNameRPAREN) {
 
2729     if (token != TokenNameRPAREN) {
 
2730       throwSyntaxError("')' expected after keyword 'exit'");
 
2734   private void internal_functions_in_yacc() {
 
2736       case TokenNameisset :
 
2737         //      T_ISSET '(' isset_variables ')'
 
2739         if (token != TokenNameLPAREN) {
 
2740           throwSyntaxError("'(' expected after keyword 'isset'");
 
2744         if (token != TokenNameRPAREN) {
 
2745           throwSyntaxError("')' expected after keyword 'isset'");
 
2749       case TokenNameempty :
 
2750         //      T_EMPTY '(' variable ')'
 
2752         if (token != TokenNameLPAREN) {
 
2753           throwSyntaxError("'(' expected after keyword 'empty'");
 
2757         if (token != TokenNameRPAREN) {
 
2758           throwSyntaxError("')' expected after keyword 'empty'");
 
2762       case TokenNameinclude :
 
2767       case TokenNameinclude_once :
 
2768         //      T_INCLUDE_ONCE expr
 
2772       case TokenNameeval :
 
2773         //      T_EVAL '(' expr ')'
 
2775         if (token != TokenNameLPAREN) {
 
2776           throwSyntaxError("'(' expected after keyword 'eval'");
 
2780         if (token != TokenNameRPAREN) {
 
2781           throwSyntaxError("')' expected after keyword 'eval'");
 
2785       case TokenNamerequire :
 
2790       case TokenNamerequire_once :
 
2791         //      T_REQUIRE_ONCE expr
 
2797   private void isset_variables() {
 
2799     //  | isset_variables ','
 
2800     if (token == TokenNameRPAREN) {
 
2801       throwSyntaxError("Variable expected after keyword 'isset'");
 
2805       if (token == TokenNameCOMMA) {
 
2813    * It will look for a value (after a '=' for example) @
 
2815   private void constant() {
 
2818       case TokenNamePLUS :
 
2821           case TokenNameDoubleLiteral :
 
2824           case TokenNameIntegerLiteral :
 
2828             throwSyntaxError("Constant expected after '+' presign.");
 
2831       case TokenNameMINUS :
 
2834           case TokenNameDoubleLiteral :
 
2837           case TokenNameIntegerLiteral :
 
2841             throwSyntaxError("Constant expected after '-' presign.");
 
2844       case TokenNamenull :
 
2847       case TokenNamefalse :
 
2850       case TokenNametrue :
 
2853       case TokenNameIdentifier :
 
2854         //   ident = identifier;
 
2855         char[] ident = scanner.getCurrentIdentifierSource();
 
2857         if (token == TokenNameLPAREN) {
 
2859           if (token != TokenNameRPAREN) {
 
2861             if (token != TokenNameRPAREN) {
 
2862               throwSyntaxError("')' expected after identifier '"
 
2863                   + new String(ident) + "' in postfix-expression.");
 
2869       case TokenNameStringLiteral :
 
2872       case TokenNameStringConstant :
 
2875       case TokenNameStringInterpolated :
 
2878       case TokenNameDoubleLiteral :
 
2881       case TokenNameIntegerLiteral :
 
2885         throwSyntaxError("Constant expected.");
 
2888   public void reportSyntaxError() { //int act, int currentKind, int
 
2890     /* remember current scanner position */
 
2891     int startPos = scanner.startPosition;
 
2892     int currentPos = scanner.currentPosition;
 
2893     //          String[] expectings;
 
2894     //          String tokenName = name[symbol_index[currentKind]];
 
2895     //fetch all "accurate" possible terminals that could recover the error
 
2896     //          int start, end = start = asi(stack[stateStackTop]);
 
2897     //          while (asr[end] != 0)
 
2899     //          int length = end - start;
 
2900     //          expectings = new String[length];
 
2901     //          if (length != 0) {
 
2902     //                  char[] indexes = new char[length];
 
2903     //                  System.arraycopy(asr, start, indexes, 0, length);
 
2904     //                  for (int i = 0; i < length; i++) {
 
2905     //                          expectings[i] = name[symbol_index[indexes[i]]];
 
2908     //if the pb is an EOF, try to tell the user that they are some
 
2909     //          if (tokenName.equals(UNEXPECTED_EOF)) {
 
2910     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
 
2911     //                          char[] tokenSource;
 
2913     //                                  tokenSource = this.scanner.getCurrentTokenSource();
 
2914     //                          } catch (Exception e) {
 
2915     //                                  tokenSource = new char[] {};
 
2917     //                          problemReporter().parseError(
 
2918     //                                  this.scanner.startPosition,
 
2919     //                                  this.scanner.currentPosition - 1,
 
2924     //          } else { //the next test is HEAVILY grammar DEPENDENT.
 
2925     //                  if ((length == 14)
 
2926     //                          && (expectings[0] == "=") //$NON-NLS-1$
 
2927     //                          && (expectings[1] == "*=") //$NON-NLS-1$
 
2928     //                          && (expressionPtr > -1)) {
 
2929     //                                  switch(currentKind) {
 
2930     //                                          case TokenNameSEMICOLON:
 
2931     //                                          case TokenNamePLUS:
 
2932     //                                          case TokenNameMINUS:
 
2933     //                                          case TokenNameDIVIDE:
 
2934     //                                          case TokenNameREMAINDER:
 
2935     //                                          case TokenNameMULTIPLY:
 
2936     //                                          case TokenNameLEFT_SHIFT:
 
2937     //                                          case TokenNameRIGHT_SHIFT:
 
2938     //// case TokenNameUNSIGNED_RIGHT_SHIFT:
 
2939     //                                          case TokenNameLESS:
 
2940     //                                          case TokenNameGREATER:
 
2941     //                                          case TokenNameLESS_EQUAL:
 
2942     //                                          case TokenNameGREATER_EQUAL:
 
2943     //                                          case TokenNameEQUAL_EQUAL:
 
2944     //                                          case TokenNameNOT_EQUAL:
 
2945     //                                          case TokenNameXOR:
 
2946     //                                          case TokenNameAND:
 
2947     //                                          case TokenNameOR:
 
2948     //                                          case TokenNameOR_OR:
 
2949     //                                          case TokenNameAND_AND:
 
2950     //                                                  // the ; is not the expected token ==> it ends a statement when an
 
2951     // expression is not ended
 
2952     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
 
2954     //                                          case TokenNameRBRACE :
 
2955     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
 
2958     //                                                  char[] tokenSource;
 
2960     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
 
2961     //                                                  } catch (Exception e) {
 
2962     //                                                          tokenSource = new char[] {};
 
2964     //                                                  problemReporter().parseError(
 
2965     //                                                          this.scanner.startPosition,
 
2966     //                                                          this.scanner.currentPosition - 1,
 
2970     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
 
2975       tokenSource = this.scanner.getCurrentTokenSource();
 
2976     } catch (Exception e) {
 
2977       tokenSource = new char[]{};
 
2979     //                          problemReporter().parseError(
 
2980     //                                  this.scanner.startPosition,
 
2981     //                                  this.scanner.currentPosition - 1,
 
2985     this.checkAndReportBracketAnomalies(problemReporter());
 
2988     /* reset scanner where it was */
 
2989     scanner.startPosition = startPos;
 
2990     scanner.currentPosition = currentPos;
 
2992   public static final int RoundBracket = 0;
 
2993   public static final int SquareBracket = 1;
 
2994   public static final int CurlyBracket = 2;
 
2995   public static final int BracketKinds = 3;
 
2996   protected int[] nestedMethod; //the ptr is nestedType
 
2997   protected int nestedType, dimensions;
 
2999   final static int AstStackIncrement = 100;
 
3000   protected int astPtr;
 
3001   protected AstNode[] astStack = new AstNode[AstStackIncrement];
 
3002   protected int astLengthPtr;
 
3003   protected int[] astLengthStack;
 
3004   AstNode[] noAstNodes = new AstNode[AstStackIncrement];
 
3005   public CompilationUnitDeclaration compilationUnit; /*
 
3006                                                       * the result from parse()
 
3008   protected ReferenceContext referenceContext;
 
3009   protected ProblemReporter problemReporter;
 
3010   //  protected CompilationResult compilationResult;
 
3012    * Returns this parser's problem reporter initialized with its reference
 
3013    * context. Also it is assumed that a problem is going to be reported, so
 
3014    * initializes the compilation result's line positions.
 
3016   public ProblemReporter problemReporter() {
 
3017     if (scanner.recordLineSeparator) {
 
3018       compilationUnit.compilationResult.lineSeparatorPositions = scanner
 
3021     problemReporter.referenceContext = referenceContext;
 
3022     return problemReporter;
 
3025    * Reconsider the entire source looking for inconsistencies in {} () []
 
3027   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
 
3028     scanner.wasAcr = false;
 
3029     boolean anomaliesDetected = false;
 
3031       char[] source = scanner.source;
 
3032       int[] leftCount = {0, 0, 0};
 
3033       int[] rightCount = {0, 0, 0};
 
3034       int[] depths = {0, 0, 0};
 
3035       int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
 
3036       int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
 
3037       int[][] rightPositions = new int[][]{new int[10], new int[10],
 
3039       int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
 
3040       scanner.currentPosition = scanner.initialPosition; //starting
 
3042       // (first-zero-based
 
3044       while (scanner.currentPosition < scanner.eofPosition) { //loop for
 
3049           // ---------Consume white space and handles
 
3050           // startPosition---------
 
3051           boolean isWhiteSpace;
 
3053             scanner.startPosition = scanner.currentPosition;
 
3054             //                                          if (((scanner.currentCharacter =
 
3055             // source[scanner.currentPosition++]) == '\\') &&
 
3056             // (source[scanner.currentPosition] == 'u')) {
 
3057             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
 
3059             if (scanner.recordLineSeparator
 
3060                 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
 
3061               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
 
3062                 // only record line positions we have not
 
3064                 scanner.pushLineSeparator();
 
3067             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
 
3069           } while (isWhiteSpace
 
3070               && (scanner.currentPosition < scanner.eofPosition));
 
3071           // -------consume token until } is found---------
 
3072           switch (scanner.currentCharacter) {
 
3075                 int index = leftCount[CurlyBracket]++;
 
3076                 if (index == leftPositions[CurlyBracket].length) {
 
3077                   System.arraycopy(leftPositions[CurlyBracket], 0,
 
3078                       (leftPositions[CurlyBracket] = new int[index * 2]), 0,
 
3081                       .arraycopy(leftDepths[CurlyBracket], 0,
 
3082                           (leftDepths[CurlyBracket] = new int[index * 2]), 0,
 
3085                 leftPositions[CurlyBracket][index] = scanner.startPosition;
 
3086                 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
 
3091                 int index = rightCount[CurlyBracket]++;
 
3092                 if (index == rightPositions[CurlyBracket].length) {
 
3093                   System.arraycopy(rightPositions[CurlyBracket], 0,
 
3094                       (rightPositions[CurlyBracket] = new int[index * 2]), 0,
 
3096                   System.arraycopy(rightDepths[CurlyBracket], 0,
 
3097                       (rightDepths[CurlyBracket] = new int[index * 2]), 0,
 
3100                 rightPositions[CurlyBracket][index] = scanner.startPosition;
 
3101                 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
 
3106                 int index = leftCount[RoundBracket]++;
 
3107                 if (index == leftPositions[RoundBracket].length) {
 
3108                   System.arraycopy(leftPositions[RoundBracket], 0,
 
3109                       (leftPositions[RoundBracket] = new int[index * 2]), 0,
 
3112                       .arraycopy(leftDepths[RoundBracket], 0,
 
3113                           (leftDepths[RoundBracket] = new int[index * 2]), 0,
 
3116                 leftPositions[RoundBracket][index] = scanner.startPosition;
 
3117                 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
 
3122                 int index = rightCount[RoundBracket]++;
 
3123                 if (index == rightPositions[RoundBracket].length) {
 
3124                   System.arraycopy(rightPositions[RoundBracket], 0,
 
3125                       (rightPositions[RoundBracket] = new int[index * 2]), 0,
 
3127                   System.arraycopy(rightDepths[RoundBracket], 0,
 
3128                       (rightDepths[RoundBracket] = new int[index * 2]), 0,
 
3131                 rightPositions[RoundBracket][index] = scanner.startPosition;
 
3132                 rightDepths[RoundBracket][index] = --depths[RoundBracket];
 
3137                 int index = leftCount[SquareBracket]++;
 
3138                 if (index == leftPositions[SquareBracket].length) {
 
3139                   System.arraycopy(leftPositions[SquareBracket], 0,
 
3140                       (leftPositions[SquareBracket] = new int[index * 2]), 0,
 
3142                   System.arraycopy(leftDepths[SquareBracket], 0,
 
3143                       (leftDepths[SquareBracket] = new int[index * 2]), 0,
 
3146                 leftPositions[SquareBracket][index] = scanner.startPosition;
 
3147                 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
 
3152                 int index = rightCount[SquareBracket]++;
 
3153                 if (index == rightPositions[SquareBracket].length) {
 
3154                   System.arraycopy(rightPositions[SquareBracket], 0,
 
3155                       (rightPositions[SquareBracket] = new int[index * 2]), 0,
 
3157                   System.arraycopy(rightDepths[SquareBracket], 0,
 
3158                       (rightDepths[SquareBracket] = new int[index * 2]), 0,
 
3161                 rightPositions[SquareBracket][index] = scanner.startPosition;
 
3162                 rightDepths[SquareBracket][index] = --depths[SquareBracket];
 
3167                 if (scanner.getNextChar('\\')) {
 
3168                   scanner.scanEscapeCharacter();
 
3169                 } else { // consume next character
 
3170                   scanner.unicodeAsBackSlash = false;
 
3171                   //                                                                    if (((scanner.currentCharacter =
 
3172                   // source[scanner.currentPosition++]) ==
 
3174                   // (source[scanner.currentPosition] ==
 
3176                   //                                                                            scanner.getNextUnicodeChar();
 
3178                   if (scanner.withoutUnicodePtr != 0) {
 
3179                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3183                 scanner.getNextChar('\'');
 
3187               // consume next character
 
3188               scanner.unicodeAsBackSlash = false;
 
3189               //                                                        if (((scanner.currentCharacter =
 
3190               // source[scanner.currentPosition++]) == '\\') &&
 
3191               // (source[scanner.currentPosition] == 'u')) {
 
3192               //                                                                scanner.getNextUnicodeChar();
 
3194               if (scanner.withoutUnicodePtr != 0) {
 
3195                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3198               while (scanner.currentCharacter != '"') {
 
3199                 if (scanner.currentCharacter == '\r') {
 
3200                   if (source[scanner.currentPosition] == '\n')
 
3201                     scanner.currentPosition++;
 
3202                   break; // the string cannot go further that
 
3205                 if (scanner.currentCharacter == '\n') {
 
3206                   break; // the string cannot go further that
 
3209                 if (scanner.currentCharacter == '\\') {
 
3210                   scanner.scanEscapeCharacter();
 
3212                 // consume next character
 
3213                 scanner.unicodeAsBackSlash = false;
 
3214                 //                                                              if (((scanner.currentCharacter =
 
3215                 // source[scanner.currentPosition++]) == '\\')
 
3216                 // && (source[scanner.currentPosition] == 'u'))
 
3218                 //                                                                      scanner.getNextUnicodeChar();
 
3220                 if (scanner.withoutUnicodePtr != 0) {
 
3221                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3229                 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
 
3232                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
3233                       && (source[scanner.currentPosition] == 'u')) {
 
3234                     //-------------unicode traitement
 
3236                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3237                     scanner.currentPosition++;
 
3238                     while (source[scanner.currentPosition] == 'u') {
 
3239                       scanner.currentPosition++;
 
3242                         .getNumericValue(source[scanner.currentPosition++])) > 15
 
3245                             .getNumericValue(source[scanner.currentPosition++])) > 15
 
3248                             .getNumericValue(source[scanner.currentPosition++])) > 15
 
3251                             .getNumericValue(source[scanner.currentPosition++])) > 15
 
3252                         || c4 < 0) { //error don't
 
3255                       scanner.currentCharacter = 'A';
 
3256                     } //something different from \n and \r
 
3258                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3261                   while (scanner.currentCharacter != '\r'
 
3262                       && scanner.currentCharacter != '\n') {
 
3264                     scanner.startPosition = scanner.currentPosition;
 
3265                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
3266                         && (source[scanner.currentPosition] == 'u')) {
 
3267                       //-------------unicode traitement
 
3269                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3270                       scanner.currentPosition++;
 
3271                       while (source[scanner.currentPosition] == 'u') {
 
3272                         scanner.currentPosition++;
 
3275                           .getNumericValue(source[scanner.currentPosition++])) > 15
 
3278                               .getNumericValue(source[scanner.currentPosition++])) > 15
 
3281                               .getNumericValue(source[scanner.currentPosition++])) > 15
 
3284                               .getNumericValue(source[scanner.currentPosition++])) > 15
 
3285                           || c4 < 0) { //error don't
 
3288                         scanner.currentCharacter = 'A';
 
3289                       } //something different from \n
 
3292                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3296                   if (scanner.recordLineSeparator
 
3297                       && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
 
3298                     if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
 
3299                       // only record line positions we
 
3300                       // have not recorded yet
 
3301                       scanner.pushLineSeparator();
 
3302                       if (this.scanner.taskTags != null) {
 
3303                         this.scanner.checkTaskTag(this.scanner
 
3304                             .getCurrentTokenStartPosition(), this.scanner
 
3305                             .getCurrentTokenEndPosition());
 
3311                 if (test > 0) { //traditional and annotation
 
3313                   boolean star = false;
 
3314                   // consume next character
 
3315                   scanner.unicodeAsBackSlash = false;
 
3316                   //                                                                    if (((scanner.currentCharacter =
 
3317                   // source[scanner.currentPosition++]) ==
 
3319                   // (source[scanner.currentPosition] ==
 
3321                   //                                                                            scanner.getNextUnicodeChar();
 
3323                   if (scanner.withoutUnicodePtr != 0) {
 
3324                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3327                   if (scanner.currentCharacter == '*') {
 
3331                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
3332                       && (source[scanner.currentPosition] == 'u')) {
 
3333                     //-------------unicode traitement
 
3335                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3336                     scanner.currentPosition++;
 
3337                     while (source[scanner.currentPosition] == 'u') {
 
3338                       scanner.currentPosition++;
 
3341                         .getNumericValue(source[scanner.currentPosition++])) > 15
 
3344                             .getNumericValue(source[scanner.currentPosition++])) > 15
 
3347                             .getNumericValue(source[scanner.currentPosition++])) > 15
 
3350                             .getNumericValue(source[scanner.currentPosition++])) > 15
 
3351                         || c4 < 0) { //error don't
 
3354                       scanner.currentCharacter = 'A';
 
3355                     } //something different from * and /
 
3357                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3360                   //loop until end of comment */
 
3361                   while ((scanner.currentCharacter != '/') || (!star)) {
 
3362                     star = scanner.currentCharacter == '*';
 
3364                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
3365                         && (source[scanner.currentPosition] == 'u')) {
 
3366                       //-------------unicode traitement
 
3368                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3369                       scanner.currentPosition++;
 
3370                       while (source[scanner.currentPosition] == 'u') {
 
3371                         scanner.currentPosition++;
 
3374                           .getNumericValue(source[scanner.currentPosition++])) > 15
 
3377                               .getNumericValue(source[scanner.currentPosition++])) > 15
 
3380                               .getNumericValue(source[scanner.currentPosition++])) > 15
 
3383                               .getNumericValue(source[scanner.currentPosition++])) > 15
 
3384                           || c4 < 0) { //error don't
 
3387                         scanner.currentCharacter = 'A';
 
3388                       } //something different from * and
 
3391                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3395                   if (this.scanner.taskTags != null) {
 
3396                     this.scanner.checkTaskTag(this.scanner
 
3397                         .getCurrentTokenStartPosition(), this.scanner
 
3398                         .getCurrentTokenEndPosition());
 
3405               if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
 
3406                 scanner.scanIdentifierOrKeyword(false);
 
3409               if (Character.isDigit(scanner.currentCharacter)) {
 
3410                 scanner.scanNumber(false);
 
3414           //-----------------end switch while
 
3415           // try--------------------
 
3416         } catch (IndexOutOfBoundsException e) {
 
3417           break; // read until EOF
 
3418         } catch (InvalidInputException e) {
 
3419           return false; // no clue
 
3422       if (scanner.recordLineSeparator) {
 
3423         //                              compilationUnit.compilationResult.lineSeparatorPositions =
 
3424         // scanner.getLineEnds();
 
3426       // check placement anomalies against other kinds of brackets
 
3427       for (int kind = 0; kind < BracketKinds; kind++) {
 
3428         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
 
3429           int start = leftPositions[kind][leftIndex]; // deepest
 
3431           // find matching closing bracket
 
3432           int depth = leftDepths[kind][leftIndex];
 
3434           for (int i = 0; i < rightCount[kind]; i++) {
 
3435             int pos = rightPositions[kind][i];
 
3436             // want matching bracket further in source with same
 
3438             if ((pos > start) && (depth == rightDepths[kind][i])) {
 
3443           if (end < 0) { // did not find a good closing match
 
3444             problemReporter.unmatchedBracket(start, referenceContext,
 
3445                 compilationUnit.compilationResult);
 
3448           // check if even number of opening/closing other brackets
 
3449           // in between this pair of brackets
 
3451           for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
 
3452             for (int i = 0; i < leftCount[otherKind]; i++) {
 
3453               int pos = leftPositions[otherKind][i];
 
3454               if ((pos > start) && (pos < end))
 
3457             for (int i = 0; i < rightCount[otherKind]; i++) {
 
3458               int pos = rightPositions[otherKind][i];
 
3459               if ((pos > start) && (pos < end))
 
3463               problemReporter.unmatchedBracket(start, referenceContext,
 
3464                   compilationUnit.compilationResult); //bracket
 
3470         // too many opening brackets ?
 
3471         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
 
3472           anomaliesDetected = true;
 
3473           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
 
3474               - i - 1], referenceContext, compilationUnit.compilationResult);
 
3476         // too many closing brackets ?
 
3477         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
 
3478           anomaliesDetected = true;
 
3479           problemReporter.unmatchedBracket(rightPositions[kind][i],
 
3480               referenceContext, compilationUnit.compilationResult);
 
3482         if (anomaliesDetected)
 
3485       return anomaliesDetected;
 
3486     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
 
3487       return anomaliesDetected;
 
3488     } catch (NullPointerException e) { // jdk1.2.2 jit bug
 
3489       return anomaliesDetected;
 
3492   protected void pushOnAstLengthStack(int pos) {
 
3494       astLengthStack[++astLengthPtr] = pos;
 
3495     } catch (IndexOutOfBoundsException e) {
 
3496       int oldStackLength = astLengthStack.length;
 
3497       int[] oldPos = astLengthStack;
 
3498       astLengthStack = new int[oldStackLength + StackIncrement];
 
3499       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
 
3500       astLengthStack[astLengthPtr] = pos;
 
3503   protected void pushOnAstStack(AstNode node) {
 
3505      * add a new obj on top of the ast stack
 
3508       astStack[++astPtr] = node;
 
3509     } catch (IndexOutOfBoundsException e) {
 
3510       int oldStackLength = astStack.length;
 
3511       AstNode[] oldStack = astStack;
 
3512       astStack = new AstNode[oldStackLength + AstStackIncrement];
 
3513       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
 
3514       astPtr = oldStackLength;
 
3515       astStack[astPtr] = node;
 
3518       astLengthStack[++astLengthPtr] = 1;
 
3519     } catch (IndexOutOfBoundsException e) {
 
3520       int oldStackLength = astLengthStack.length;
 
3521       int[] oldPos = astLengthStack;
 
3522       astLengthStack = new int[oldStackLength + AstStackIncrement];
 
3523       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
 
3524       astLengthStack[astLengthPtr] = 1;