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.phpeclipse.phpeditor.phpparser;
 
  13 import java.text.MessageFormat;
 
  14 import java.util.ArrayList;
 
  15 import java.util.HashMap;
 
  16 import java.util.Hashtable;
 
  18 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
  19 import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
 
  20 import net.sourceforge.phpeclipse.phpeditor.PHPString;
 
  21 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
 
  23 import org.eclipse.core.resources.IFile;
 
  24 import org.eclipse.core.resources.IMarker;
 
  25 import org.eclipse.core.runtime.CoreException;
 
  26 import org.eclipse.core.runtime.IPath;
 
  27 import org.eclipse.jface.preference.IPreferenceStore;
 
  28 import org.eclipse.ui.texteditor.MarkerUtilities;
 
  30 public class PHPParser extends PHPKeywords {
 
  31   // strings for external parser call
 
  32   private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
 
  33   private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
 
  35   public static final int ERROR = 2;
 
  36   public static final int WARNING = 1;
 
  37   public static final int INFO = 0;
 
  39   private IFile fileToParse;
 
  40   private ArrayList phpList;
 
  42   private int currentPHPString;
 
  43   private boolean phpEnd;
 
  45   private static HashMap keywordMap = null;
 
  53   // row counter for syntax errors:
 
  55   // column counter for syntax errors:
 
  66   private String stringValue;
 
  68   /** Contains the current expression. */
 
  69   private StringBuffer expression;
 
  71   private boolean phpMode;
 
  73   final static int TokenNameEOF = 0;
 
  74   final static int TokenNameERROR = 1;
 
  75   final static int TokenNameHTML = 2;
 
  77   final static int TokenNameREMAINDER = 30;
 
  78   final static int TokenNameNOT = 31;
 
  79   final static int TokenNameDOT = 32;
 
  80   final static int TokenNameXOR = 33;
 
  81   final static int TokenNameDIVIDE = 34;
 
  82   final static int TokenNameMULTIPLY = 35;
 
  83   final static int TokenNameMINUS = 36;
 
  84   final static int TokenNamePLUS = 37;
 
  85   final static int TokenNameEQUAL_EQUAL = 38;
 
  86   final static int TokenNameNOT_EQUAL = 39;
 
  87   final static int TokenNameGREATER = 40;
 
  88   final static int TokenNameGREATER_EQUAL = 41;
 
  89   final static int TokenNameLESS = 42;
 
  90   final static int TokenNameLESS_EQUAL = 43;
 
  91   final static int TokenNameAND_AND = 44;
 
  92   final static int TokenNameOR_OR = 45;
 
  93  // final static int TokenNameHASH = 46; 
 
  94   final static int TokenNameCOLON = 47;
 
  95   final static int TokenNameDOT_EQUAL = 48;
 
  97   final static int TokenNameEQUAL = 49;
 
  98   final static int TokenNameMINUS_GREATER = 50; // ->
 
  99   final static int TokenNameFOREACH = 51;
 
 100   final static int TokenNameAND = 52;
 
 101   //final static int TokenNameDOLLARLISTOPEN = 53;
 
 102   final static int TokenNameTWIDDLE = 54;
 
 103   final static int TokenNameTWIDDLE_EQUAL = 55;
 
 104   final static int TokenNameREMAINDER_EQUAL = 56;
 
 105   final static int TokenNameXOR_EQUAL = 57;
 
 106   final static int TokenNameRIGHT_SHIFT_EQUAL = 58;
 
 107   final static int TokenNameLEFT_SHIFT_EQUAL = 59;
 
 108   final static int TokenNameAND_EQUAL = 60;
 
 109   final static int TokenNameQUESTION = 61;
 
 110   final static int TokenNameCOLON_COLON = 62;
 
 111   final static int TokenNameAT = 63;
 
 112   // final static int TokenNameHEREDOC = 64;
 
 114   final static int TokenNameDOLLAROPEN = 127;
 
 115   final static int TokenNameLPAREN = 128;
 
 116   final static int TokenNameRPAREN = 129;
 
 117   final static int TokenNameLBRACE = 130;
 
 118   final static int TokenNameRBRACE = 131;
 
 119   final static int TokenNameLBRACKET = 132;
 
 120   final static int TokenNameRBRACKET = 133;
 
 121   final static int TokenNameCOMMA = 134;
 
 123   final static int TokenNameStringLiteral = 136;
 
 124   final static int TokenNameIdentifier = 138;
 
 125  // final static int TokenNameDIGIT = 139;
 
 126   final static int TokenNameSEMICOLON = 140;
 
 127  // final static int TokenNameSLOT = 141;
 
 128  // final static int TokenNameSLOTSEQUENCE = 142;
 
 129   final static int TokenNameMINUS_MINUS = 144;
 
 130   final static int TokenNamePLUS_PLUS = 145;
 
 131   final static int TokenNamePLUS_EQUAL = 146;
 
 132   final static int TokenNameDIVIDE_EQUAL = 147;
 
 133   final static int TokenNameMINUS_EQUAL = 148;
 
 134   final static int TokenNameMULTIPLY_EQUAL = 149;
 
 135   final static int TokenNameVariable = 150;
 
 136   final static int TokenNameIntegerLiteral = 151;
 
 137   final static int TokenNameDoubleLiteral = 152;
 
 138   final static int TokenNameStringInterpolated = 153;
 
 139   final static int TokenNameStringConstant = 154;
 
 141   final static int TokenNameLEFT_SHIFT = 155;
 
 142   final static int TokenNameRIGHT_SHIFT = 156;
 
 143   final static int TokenNameEQUAL_EQUAL_EQUAL = 157;
 
 144   final static int TokenNameNOT_EQUAL_EQUAL = 158;
 
 145   final static int TokenNameOR = 159;
 
 146   //  final static int TokenNameAT = 153; // @
 
 151    *@param  sess  Description of Parameter
 
 154   public PHPParser(IFile fileToParse) {
 
 155     if (keywordMap == null) {
 
 156       keywordMap = new HashMap();
 
 157       for (int i = 0; i < PHP_KEYWORS.length; i++) {
 
 158         keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
 
 161     this.currentPHPString = 0;
 
 162     this.fileToParse = fileToParse;
 
 165     this.token = TokenNameEOF;
 
 168     this.columnCount = 0;
 
 175    * Create marker for the parse error
 
 177   private void setMarker(String message, int lineNumber, int errorLevel) throws CoreException {
 
 178     setMarker(fileToParse, message, lineNumber, errorLevel);
 
 181   public static void setMarker(IFile file, String message, int lineNumber, int errorLevel) throws CoreException {
 
 183       Hashtable attributes = new Hashtable();
 
 184       MarkerUtilities.setMessage(attributes, message);
 
 185       switch (errorLevel) {
 
 187           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
 
 190           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
 
 193           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
 
 196       MarkerUtilities.setLineNumber(attributes, lineNumber);
 
 197       MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
 
 202    * This method will throw the SyntaxError.
 
 203    * It will add the good lines and columns to the Error
 
 204    * @param error the error message
 
 205    * @throws SyntaxError the error raised
 
 207   private void throwSyntaxError(String error) {
 
 209     if (str.length() < chIndx) {
 
 212     // read until end-of-line
 
 214     while (str.length() > eol) {
 
 215       ch = str.charAt(eol++);
 
 221     throw new SyntaxError(rowCount, chIndx - columnCount + 1, str.substring(columnCount, eol), error);
 
 225    * This method will throw the SyntaxError.
 
 226    * It will add the good lines and columns to the Error
 
 227    * @param error the error message
 
 228    * @throws SyntaxError the error raised
 
 230   private void throwSyntaxError(String error, int startRow) {
 
 231     throw new SyntaxError(startRow, 0, " ", error);
 
 235    *  Method Declaration.
 
 239   private void getChar() {
 
 240     if (str.length() > chIndx) {
 
 241       ch = str.charAt(chIndx++);
 
 246     chIndx = str.length() + 1;
 
 248     //  token = TokenNameEOF;
 
 252 //  private void getNextToken_OldVersion() throws CoreException {
 
 255 //    while (str.length() > chIndx) {
 
 256 //      ch = str.charAt(chIndx++);
 
 257 //      token = TokenNameERROR;
 
 260 //        columnCount = chIndx;
 
 261 //        continue; // while loop
 
 263 //      if (str.length() == chIndx) {
 
 266 //      if (!Character.isWhitespace(ch)) {
 
 268 //          if (str.length() > chIndx) {
 
 269 //            if (str.charAt(chIndx) == '{') {
 
 271 //              token = TokenNameDOLLAROPEN;
 
 278 //        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) {
 
 282 //        if (ch >= '0' && ch <= '9') {
 
 287 //          if (str.length() > chIndx) {
 
 288 //            if (str.charAt(chIndx) == '/') {
 
 290 //              // read comment until end of line:
 
 291 //              while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
 
 295 //            } else if (str.charAt(chIndx) == '*') {
 
 297 //              // multi line comment:
 
 298 //              while (str.length() > chIndx) {
 
 299 //                if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
 
 303 //                ch = str.charAt(chIndx++);
 
 306 //                  columnCount = chIndx;
 
 312 //        } else if (ch == '#') {
 
 313 //          // read comment until end of line:
 
 314 //          while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
 
 318 //        } else if (ch == '"') {
 
 319 //          // read string until end
 
 320 //          boolean openString = true;
 
 321 //          while (str.length() > chIndx) {
 
 322 //            ch = str.charAt(chIndx++);
 
 324 //              if (str.length() > chIndx) {
 
 325 //                ch = str.charAt(chIndx++);
 
 327 //            } else if (ch == '"') {
 
 328 //              openString = false;
 
 330 //            } else if (ch == '\n') {
 
 332 //              columnCount = chIndx;
 
 336 //            throwSyntaxError("Open string character '\"' at end of file.");
 
 338 //          token = TokenNameINTERPOLATED_STRING;
 
 340 //        } else if (ch == '\'') {
 
 341 //          // read string until end
 
 342 //          boolean openString = true;
 
 343 //          int startRow = rowCount;
 
 344 //          while (str.length() > chIndx) {
 
 345 //            ch = str.charAt(chIndx++);
 
 347 //              if (str.length() > chIndx) {
 
 348 //                ch = str.charAt(chIndx++);
 
 350 //            } else if (ch == '\'') {
 
 351 //              openString = false;
 
 353 //            } else if (ch == '\n') {
 
 355 //              columnCount = chIndx;
 
 359 //            throwSyntaxError("Open string character \"'\" at end of file.", startRow);
 
 361 //          token = TokenNameStringConstant;
 
 363 //        } else if (ch == '`') {
 
 364 //          // read string until end
 
 365 //          boolean openString = true;
 
 366 //          int startRow = rowCount;
 
 367 //          while (str.length() > chIndx) {
 
 368 //            ch = str.charAt(chIndx++);
 
 370 //              if (str.length() > chIndx) {
 
 371 //                ch = str.charAt(chIndx++);
 
 373 //            } else if (ch == '`') {
 
 374 //              openString = false;
 
 376 //            } else if (ch == '\n') {
 
 378 //              columnCount = chIndx;
 
 382 //            throwSyntaxError("Open string character \"`\" at end of file.", startRow);
 
 384 //          token = TokenNameStringConstant;
 
 391 //            token = TokenNameLPAREN;
 
 395 //            token = TokenNameRPAREN;
 
 399 //            token = TokenNameLBRACE;
 
 403 //            token = TokenNameRBRACE;
 
 407 //            token = TokenNameLBRACKET;
 
 411 //            token = TokenNameRBRACKET;
 
 415 //            token = TokenNameCOMMA;
 
 419 //            token = TokenNameQUESTION;
 
 422 //            token = TokenNameAT;
 
 425 //            token = TokenNameTWIDDLE;
 
 426 //            if (str.length() > chIndx) {
 
 427 //              if (str.charAt(chIndx) == '=') {
 
 429 //                token = TokenNameTWIDDLE_EQUAL;
 
 436 //            token = TokenNameDOT;
 
 437 //            if (str.length() > chIndx) {
 
 438 //              if (str.charAt(chIndx) == '=') {
 
 440 //                token = TokenNameDOT_EQUAL;
 
 448 //            token = TokenNameStringLiteral;
 
 452 //            token = TokenNameREMAINDER;
 
 453 //            if (str.length() > chIndx) {
 
 454 //              if (str.charAt(chIndx) == '=') {
 
 456 //                token = TokenNameREMAINDER_EQUAL;
 
 463 //            token = TokenNameSEMICOLON;
 
 467 //            token = TokenNameXOR;
 
 468 //            if (str.length() > chIndx) {
 
 469 //              if (str.charAt(chIndx) == '=') {
 
 471 //                token = TokenNameXOR_EQUAL;
 
 478 //            token = TokenNameDIVIDE;
 
 480 //            if (str.length() > chIndx) {
 
 481 //              if (str.charAt(chIndx) == '=') {
 
 483 //                token = TokenNameDIVIDE_EQUAL;
 
 491 //            token = TokenNameMULTIPLY;
 
 492 //            if (str.length() > chIndx) {
 
 493 //              if (str.charAt(chIndx) == '*') {
 
 495 //                token = TokenNameXOR;
 
 499 //              if (str.charAt(chIndx) == '=') {
 
 501 //                token = TokenNameMULTIPLY_EQUAL;
 
 509 //            token = TokenNamePLUS;
 
 510 //            if (str.length() > chIndx) {
 
 511 //              if (str.charAt(chIndx) == '+') {
 
 513 //                token = TokenNamePLUS_PLUS;
 
 517 //              if (str.charAt(chIndx) == '=') {
 
 519 //                token = TokenNamePLUS_EQUAL;
 
 526 //            token = TokenNameMINUS;
 
 527 //            if (str.length() > chIndx) {
 
 528 //              if (str.charAt(chIndx) == '-') {
 
 530 //                token = TokenNameMINUS_MINUS;
 
 534 //              if (str.charAt(chIndx) == '=') {
 
 536 //                token = TokenNameMINUS_EQUAL;
 
 540 //              if (str.charAt(chIndx) == '>') {
 
 542 //                token = TokenNameMINUS_GREATER;
 
 550 //            token = TokenNameEQUAL;
 
 552 //            if (str.length() > chIndx) {
 
 553 //              ch = str.charAt(chIndx);
 
 557 //                token = TokenNameEQUAL_EQUAL;
 
 558 //                if (str.length() > chIndx) {
 
 559 //                  ch = str.charAt(chIndx);
 
 563 //                    token = TokenNameEQUAL_EQUAL_EQUAL;
 
 570 //                token = TokenNameFOREACH;
 
 578 //            token = TokenNameNOT;
 
 580 //            if (str.length() > chIndx) {
 
 581 //              if (str.charAt(chIndx) == '=') {
 
 583 //                token = TokenNameNOT_EQUAL;
 
 584 //                if (str.length() > chIndx) {
 
 585 //                  ch = str.charAt(chIndx);
 
 589 //                    token = TokenNameNOT_EQUAL_EQUAL;
 
 598 //            token = TokenNameGREATER;
 
 600 //            if (str.length() > chIndx) {
 
 601 //              if (str.charAt(chIndx) == '=') {
 
 603 //                token = TokenNameGREATER_EQUAL;
 
 606 //              if (str.charAt(chIndx) == '>') {
 
 608 //                token = TokenNameRIGHT_SHIFT;
 
 609 //                if (str.length() > chIndx) {
 
 610 //                  if (str.charAt(chIndx) == '=') {
 
 612 //                    token = TokenNameRIGHT_SHIFT_EQUAL;
 
 622 //            token = TokenNameLESS;
 
 624 //            if (str.length() > chIndx) {
 
 625 //              if (str.charAt(chIndx) == '=') {
 
 627 //                token = TokenNameLESS_EQUAL;
 
 631 //              if (str.charAt(chIndx) == '<') {
 
 633 //                token = TokenNameLEFT_SHIFT;
 
 634 //                if (str.charAt(chIndx) == '<') {
 
 636 //                  int startRow = rowCount;
 
 637 //                  if (str.length() > chIndx) {
 
 639 //                    ch = str.charAt(++chIndx);
 
 640 //                    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_')) {
 
 643 //                      token = TokenNameStringConstant;
 
 644 //                      while (str.length() > chIndx) {
 
 645 //                        ch = str.charAt(chIndx++);
 
 647 //                          if (str.length() >= chIndx + identifier.length()) {
 
 648 //                            if (str.substring(chIndx, chIndx + identifier.length()).equals(identifier)) {
 
 649 //                              chIndx += identifier.length();
 
 657 //                  throwSyntaxError("Open heredoc syntax after operator '<<<'.", startRow);
 
 658 //                } else if (str.charAt(chIndx) == '=') {
 
 660 //                  token = TokenNameLEFT_SHIFT_EQUAL;
 
 670 //            token = TokenNameOR;
 
 672 //            if (str.length() > chIndx) {
 
 673 //              if (str.charAt(chIndx) == '|') {
 
 675 //                token = TokenNameOR_OR;
 
 683 //            token = TokenNameAND;
 
 684 //            if (str.length() > chIndx) {
 
 685 //              if (str.charAt(chIndx) == '&') {
 
 687 //                token = TokenNameAND_AND;
 
 690 //              if (str.charAt(chIndx) == '=') {
 
 692 //                token = TokenNameAND_EQUAL;
 
 700 //            token = TokenNameCOLON;
 
 701 //            if (str.length() > chIndx) {
 
 702 //              if (str.charAt(chIndx) == ':') {
 
 704 //                token = TokenNameCOLON_COLON;
 
 709 //            token = TokenNameHASH;
 
 713 //            //            token = TokenNameAT;
 
 717 //            throwSyntaxError("unexpected character: '" + ch + "'");
 
 720 //        if (token == TokenNameERROR) {
 
 721 //          throwSyntaxError("token not found");
 
 728 //    chIndx = str.length() + 1;
 
 730 //    token = TokenNameEOF;
 
 733 //    if (phpList != null) {
 
 734 //      if (currentPHPString < phpList.size()) {
 
 735 //        token = TokenNameERROR;
 
 736 //        temp = (PHPString) phpList.get(currentPHPString++);
 
 737 //        this.str = temp.getPHPString();
 
 738 //        this.token = TokenNameEOF;
 
 740 //        this.rowCount = temp.getLineNumber();
 
 741 //        this.columnCount = 0;
 
 745 //        token = TokenNameERROR;
 
 751    * gets the next token from input
 
 753   private void getNextToken() throws CoreException {
 
 754     boolean phpFound = false;
 
 761         while (str.length() > chIndx) {
 
 762           token = TokenNameERROR;
 
 763           ch = str.charAt(chIndx++);
 
 769             ch2 = str.charAt(chIndx++);
 
 771               ch2 = str.charAt(chIndx++);
 
 772               if (Character.isWhitespace(ch2)) {
 
 777               } else if (ch2 == 'p' || ch2 == 'P') {
 
 778                 ch2 = str.charAt(chIndx++);
 
 779                 if (ch2 == 'h' || ch2 == 'H') {
 
 780                   ch2 = str.charAt(chIndx++);
 
 781                   if (ch2 == 'p' || ch2 == 'P') {
 
 799         while (str.length() > chIndx) {
 
 800           ch = str.charAt(chIndx++);
 
 801           token = TokenNameERROR;
 
 804             columnCount = chIndx;
 
 805             continue; // while loop
 
 807           if (str.length() == chIndx) {
 
 810           if (!Character.isWhitespace(ch)) {
 
 812               if (str.length() > chIndx) {
 
 813                 if (str.charAt(chIndx) == '{') {
 
 815                   token = TokenNameDOLLAROPEN;
 
 822             if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) {
 
 826             if (ch >= '0' && ch <= '9') {
 
 831               if (str.length() > chIndx) {
 
 832                 if (str.charAt(chIndx) == '/') {
 
 835                   // read comment until end of line:
 
 836                   while ((str.length() > chIndx) && (ch != '\n')) {
 
 837                     ch = str.charAt(chIndx++);
 
 839                       ch2 = str.charAt(chIndx);
 
 842                         token = TokenNameHTML;
 
 853                 } else if (str.charAt(chIndx) == '*') {
 
 855                   // multi line comment:
 
 856                   while (str.length() > chIndx) {
 
 857                     if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
 
 861                     ch = str.charAt(chIndx++);
 
 864                       columnCount = chIndx;
 
 870             } else if (ch == '#') {
 
 871               // read comment until end of line:
 
 872               while ((str.length() > chIndx) && (ch != '\n')) {
 
 873                 ch = str.charAt(chIndx++);
 
 875                   ch2 = str.charAt(chIndx);
 
 878                     token = TokenNameHTML;
 
 889             } else if (ch == '"') {
 
 890               getString('"',TokenNameStringInterpolated,"Open string character '\"' at end of file.");
 
 892             } else if (ch == '\'') {
 
 893               getString('\'',TokenNameStringConstant,"Open string character \"'\" at end of file.");
 
 895             } else if (ch == '`') {
 
 896               getString('`',TokenNameStringConstant,"Open string character \"`\" at end of file.");
 
 897               setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO);
 
 904                 token = TokenNameLPAREN;
 
 908                 token = TokenNameRPAREN;
 
 912                 token = TokenNameLBRACE;
 
 916                 token = TokenNameRBRACE;
 
 920                 token = TokenNameLBRACKET;
 
 924                 token = TokenNameRBRACKET;
 
 928                 token = TokenNameCOMMA;
 
 932                 token = TokenNameQUESTION;
 
 933                 if (str.length() > chIndx) {
 
 934                   if (str.charAt(chIndx) == '>') {
 
 936                     token = TokenNameHTML;
 
 949                 token = TokenNameTWIDDLE;
 
 950                 if (str.length() > chIndx) {
 
 951                   if (str.charAt(chIndx) == '=') {
 
 953                     token = TokenNameTWIDDLE_EQUAL;
 
 960                 token = TokenNameDOT;
 
 961                 if (str.length() > chIndx) {
 
 962                   if (str.charAt(chIndx) == '=') {
 
 964                     token = TokenNameDOT_EQUAL;
 
 972                 token = TokenNameStringLiteral;
 
 976                 token = TokenNameREMAINDER;
 
 977                 if (str.length() > chIndx) {
 
 978                   if (str.charAt(chIndx) == '=') {
 
 980                     token = TokenNameREMAINDER_EQUAL;
 
 987                 token = TokenNameSEMICOLON;
 
 991                 token = TokenNameXOR;
 
 992                 if (str.length() > chIndx) {
 
 993                   if (str.charAt(chIndx) == '=') {
 
 995                     token = TokenNameXOR_EQUAL;
 
1002                 token = TokenNameDIVIDE;
 
1004                 if (str.length() > chIndx) {
 
1005                   if (str.charAt(chIndx) == '=') {
 
1007                     token = TokenNameDIVIDE_EQUAL;
 
1015                 token = TokenNameMULTIPLY;
 
1016                 if (str.length() > chIndx) {
 
1017                   if (str.charAt(chIndx) == '*') {
 
1019                     token = TokenNameXOR;
 
1023                   if (str.charAt(chIndx) == '=') {
 
1025                     token = TokenNameMULTIPLY_EQUAL;
 
1033                 token = TokenNamePLUS;
 
1034                 if (str.length() > chIndx) {
 
1035                   if (str.charAt(chIndx) == '+') {
 
1037                     token = TokenNamePLUS_PLUS;
 
1041                   if (str.charAt(chIndx) == '=') {
 
1043                     token = TokenNamePLUS_EQUAL;
 
1050                 token = TokenNameMINUS;
 
1051                 if (str.length() > chIndx) {
 
1052                   if (str.charAt(chIndx) == '-') {
 
1054                     token = TokenNameMINUS_MINUS;
 
1058                   if (str.charAt(chIndx) == '=') {
 
1060                     token = TokenNameMINUS_EQUAL;
 
1064                   if (str.charAt(chIndx) == '>') {
 
1066                     token = TokenNameMINUS_GREATER;
 
1074                 token = TokenNameEQUAL;
 
1076                 if (str.length() > chIndx) {
 
1077                   ch = str.charAt(chIndx);
 
1081                     token = TokenNameEQUAL_EQUAL;
 
1082                     if (str.length() > chIndx) {
 
1083                       ch = str.charAt(chIndx);
 
1087                         token = TokenNameEQUAL_EQUAL_EQUAL;
 
1094                     token = TokenNameFOREACH;
 
1102                 token = TokenNameNOT;
 
1104                 if (str.length() > chIndx) {
 
1105                   if (str.charAt(chIndx) == '=') {
 
1107                     token = TokenNameNOT_EQUAL;
 
1108                     if (str.length() > chIndx) {
 
1109                       ch = str.charAt(chIndx);
 
1113                         token = TokenNameNOT_EQUAL_EQUAL;
 
1122                 token = TokenNameGREATER;
 
1124                 if (str.length() > chIndx) {
 
1125                   if (str.charAt(chIndx) == '=') {
 
1127                     token = TokenNameGREATER_EQUAL;
 
1130                   if (str.charAt(chIndx) == '>') {
 
1132                     token = TokenNameRIGHT_SHIFT;
 
1133                     if (str.length() > chIndx) {
 
1134                       if (str.charAt(chIndx) == '=') {
 
1136                         token = TokenNameRIGHT_SHIFT_EQUAL;
 
1146                 token = TokenNameLESS;
 
1148                 if (str.length() > chIndx) {
 
1149                   if (str.charAt(chIndx) == '=') {
 
1151                     token = TokenNameLESS_EQUAL;
 
1155                   if (str.charAt(chIndx) == '<') {
 
1157                     token = TokenNameLEFT_SHIFT;
 
1158                     if (str.charAt(chIndx) == '<') {
 
1160                       int startRow = rowCount;
 
1161                       if (str.length() > chIndx) {
 
1163                         ch = str.charAt(++chIndx);
 
1164                         if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_')) {
 
1167                           token = TokenNameStringConstant;
 
1168                           while (str.length() > chIndx) {
 
1169                             ch = str.charAt(chIndx++);
 
1171                               if (str.length() >= chIndx + identifier.length()) {
 
1172                                 if (str.substring(chIndx, chIndx + identifier.length()).equals(identifier)) {
 
1173                                   chIndx += identifier.length();
 
1181                       throwSyntaxError("Open heredoc syntax after operator '<<<'.", startRow);
 
1182                     } else if (str.charAt(chIndx) == '=') {
 
1184                       token = TokenNameLEFT_SHIFT_EQUAL;
 
1194                 token = TokenNameOR;
 
1196                 if (str.length() > chIndx) {
 
1197                   if (str.charAt(chIndx) == '|') {
 
1199                     token = TokenNameOR_OR;
 
1207                 token = TokenNameAND;
 
1208                 if (str.length() > chIndx) {
 
1209                   if (str.charAt(chIndx) == '&') {
 
1211                     token = TokenNameAND_AND;
 
1214                   if (str.charAt(chIndx) == '=') {
 
1216                     token = TokenNameAND_EQUAL;
 
1224                 token = TokenNameCOLON;
 
1225                 if (str.length() > chIndx) {
 
1226                   if (str.charAt(chIndx) == ':') {
 
1228                     token = TokenNameCOLON_COLON;
 
1233 //                token = TokenNameHASH;
 
1237                 //            token = TokenNameAT;
 
1241                 throwSyntaxError("unexpected character: '" + ch + "'");
 
1244             if (token == TokenNameERROR) {
 
1245               throwSyntaxError("token not found");
 
1252     } catch (StringIndexOutOfBoundsException e) {
 
1253       // catched from charAt
 
1256     chIndx = str.length() + 1;
 
1258     token = TokenNameEOF;
 
1261     //    if (phpList != null) {
 
1262     //      if (currentPHPString < phpList.size()) {
 
1263     //        token = TokenNameUNDEFINED;
 
1264     //        temp = (PHPString) phpList.get(currentPHPString++);
 
1265     //        this.str = temp.getPHPString();
 
1266     //        this.token = TokenNameEOF;
 
1268     //        this.rowCount = temp.getLineNumber();
 
1269     //        this.columnCount = 0;
 
1273     //        token = TokenNameUNDEFINED;
 
1280    * Get an identifier.
 
1282   private void getIdentifier() {
 
1283   //  StringBuffer ident = new StringBuffer();
 
1284     int startPosition = chIndx - 1;
 
1285 //    ident.append(ch);
 
1288       // attention recursive call:
 
1290       token = TokenNameVariable;
 
1293       token = TokenNameIdentifier;
 
1298     //this will read the buffer until the next character is a forbidden character for identifier
 
1299     while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
 
1300   //    ident.append(ch);
 
1303     int endPosition = chIndx--;
 
1304     int length = (--endPosition) - startPosition;
 
1306     identifier = str.substring(startPosition, endPosition);
 
1307     // System.out.println(identifier);
 
1309     // determine if this identitfer is a keyword
 
1310     // @todo improve this in future version
 
1311     Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
 
1313       token = i.intValue();
 
1319    * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
 
1320    * value {@link PHPParser#TokenNameDOUBLE_NUMBER}<br />
 
1321    * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
 
1322    * value {@link PHPParser#TokenNameINT_NUMBER}
 
1324   private void getNumber() {
 
1325     StringBuffer inum = new StringBuffer();
 
1334     // determine number conversions:
 
1335     if (firstCh == '0') {
 
1364     if (numFormat == 16) {
 
1365       while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
 
1370       while ((ch >= '0' && ch <= '9') || (ch == '.') || (ch == 'E') || (ch == 'e')) {
 
1371         if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
 
1372           if (ch == '.' && dFlag != ' ') {
 
1375           if ((dFlag == 'E') || (dFlag == 'e')) {
 
1381           if ((ch == '-') || (ch == '+')) {
 
1395         doubleNumber = new Double(inum.toString());
 
1396         token = TokenNameDoubleLiteral;
 
1399         longNumber = Long.valueOf(inum.toString(), numFormat);
 
1400         token = TokenNameIntegerLiteral;
 
1404     } catch (Throwable e) {
 
1405       throwSyntaxError("Number format error: " + inum.toString());
 
1411    * @param openChar the opening char ('\'', '"', '`')
 
1412    * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
 
1413    * @param errorMsg the error message in case of parse error in the string
 
1415   private void getString(final char openChar, final int typeString, final String errorMsg) {
 
1416     StringBuffer sBuffer = new StringBuffer();
 
1417     boolean openString = true;
 
1418     int startRow = rowCount;
 
1419     while (str.length() > chIndx) {
 
1420       ch = str.charAt(chIndx++);
 
1423         if (str.length() > chIndx) {
 
1424           ch = str.charAt(chIndx++);
 
1427       } else if (ch == openChar) {
 
1430       } else if (ch == '\n') {
 
1432         columnCount = chIndx;
 
1438       if (typeString == TokenNameStringConstant) {
 
1439         throwSyntaxError(errorMsg, startRow);
 
1441         throwSyntaxError(errorMsg);
 
1445     stringValue = sBuffer.toString();
 
1448   public void htmlParserTester(String input) {
 
1450     int startLineNumber = 1;
 
1454     boolean phpMode = false;
 
1455     boolean phpFound = false;
 
1457     phpList = new ArrayList();
 
1458     currentPHPString = 0;
 
1462       while (i < input.length()) {
 
1463         ch = input.charAt(i++);
 
1467         if ((!phpMode) && ch == '<') {
 
1468           ch2 = input.charAt(i++);
 
1470             ch2 = input.charAt(i++);
 
1471             if (Character.isWhitespace(ch2)) {
 
1476               startLineNumber = lineNumber;
 
1478             } else if (ch2 == 'p') {
 
1479               ch2 = input.charAt(i++);
 
1481                 ch2 = input.charAt(i++);
 
1486                   startLineNumber = lineNumber;
 
1492             } else if (ch2 == 'P') {
 
1493               ch2 = input.charAt(i++);
 
1495                 ch2 = input.charAt(i++);
 
1500                   startLineNumber = lineNumber;
 
1513           if (ch == '/' && i < input.length()) {
 
1514             ch2 = input.charAt(i++);
 
1516               while (i < input.length()) {
 
1517                 ch = input.charAt(i++);
 
1518                 if (ch == '?' && i < input.length()) {
 
1519                   ch2 = input.charAt(i++);
 
1523                     phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
 
1527                 } else if (ch == '\n') {
 
1533             } else if (ch2 == '*') {
 
1534               // multi-line comment
 
1535               while (i < input.length()) {
 
1536                 ch = input.charAt(i++);
 
1539                 } else if (ch == '*' && i < input.length()) {
 
1540                   ch2 = input.charAt(i++);
 
1551           } else if (ch == '#') {
 
1552             while (i < input.length()) {
 
1553               ch = input.charAt(i++);
 
1554               if (ch == '?' && i < input.length()) {
 
1555                 ch2 = input.charAt(i++);
 
1559                   phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
 
1563               } else if (ch == '\n') {
 
1569           } else if (ch == '"') {
 
1571             while (i < input.length()) {
 
1572               ch = input.charAt(i++);
 
1575               } else if (ch == '\\' && i < input.length()) { // escape
 
1577               } else if (ch == '"') {
 
1582           } else if (ch == '\'') {
 
1584             while (i < input.length()) {
 
1585               ch = input.charAt(i++);
 
1588               } else if (ch == '\\' && i < input.length()) { // escape
 
1590               } else if (ch == '\'') {
 
1597           if (ch == '?' && i < input.length()) {
 
1598             ch2 = input.charAt(i++);
 
1602               phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
 
1611         setMarker("No PHP source code found.", lineNumber, PHPParser.INFO);
 
1614           setMarker("Open PHP tag at end of file.", lineNumber, PHPParser.INFO);
 
1615           phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
 
1617         //        for (int j=0;j<phpList.size();j++) {
 
1618         //          String temp = ((PHPString)phpList.get(j)).getPHPString();
 
1619         //          int startIndx = temp.length()-10;
 
1620         //          if (startIndx<0) {
 
1623         //          System.out.println(temp.substring(startIndx)+"?>");
 
1625         phpParserTester(null, 1);
 
1627         //        for(int j=0;j<phpList.size();j++) {
 
1628         //          temp = (PHPString) phpList.get(j);
 
1629         //          parser.start(temp.getPHPString(), temp.getLineNumber());
 
1632     } catch (CoreException e) {
 
1636   public void phpParserTester(String s, int rowCount) throws CoreException {
 
1639       if (phpList.size() != 0) {
 
1640         this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
 
1643     this.token = TokenNameEOF;
 
1645     this.rowCount = rowCount;
 
1646     this.columnCount = 0;
 
1647     this.phpEnd = false;
 
1648     this.phpMode = true;
 
1652         if (token != TokenNameEOF && token != TokenNameERROR) {
 
1655         if (token != TokenNameEOF && token != TokenNameERROR) {
 
1656           if (token == TokenNameRPAREN) {
 
1657             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
1659           if (token == TokenNameRBRACE) {
 
1660             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
1662           if (token == TokenNameRBRACKET) {
 
1663             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
1666           if (token == TokenNameLPAREN) {
 
1667             throwSyntaxError("Read character '('; end-of-file not reached.");
 
1669           if (token == TokenNameLBRACE) {
 
1670             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
1672           if (token == TokenNameLBRACKET) {
 
1673             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
1676           throwSyntaxError("End-of-file not reached.");
 
1679       } catch (SyntaxError err) {
 
1683           setMarker(err.getMessage(), err.getLine(), ERROR);
 
1685         // if an error occured,
 
1686         // try to find keywords 'class' or 'function'
 
1687         // to parse the rest of the string
 
1688         while (token != TokenNameEOF && token != TokenNameERROR) {
 
1689           if (token == TokenNameclass || token == TokenNamefunction) {
 
1694         if (token == TokenNameEOF || token == TokenNameERROR) {
 
1703    * Parses a string with php tags
 
1704    * i.e. '<body> <?php phpinfo() ?> </body>'
 
1706   public void parse(String s) throws CoreException {
 
1708     this.token = TokenNameEOF;
 
1711     this.columnCount = 0;
 
1712     this.phpEnd = false;
 
1713     this.phpMode = false;
 
1717         if (token != TokenNameEOF && token != TokenNameERROR) {
 
1720         if (token != TokenNameEOF && token != TokenNameERROR) {
 
1721           if (token == TokenNameRPAREN) {
 
1722             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
1724           if (token == TokenNameRBRACE) {
 
1725             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
1727           if (token == TokenNameRBRACKET) {
 
1728             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
1731           if (token == TokenNameLPAREN) {
 
1732             throwSyntaxError("Read character '('; end-of-file not reached.");
 
1734           if (token == TokenNameLBRACE) {
 
1735             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
1737           if (token == TokenNameLBRACKET) {
 
1738             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
1741           throwSyntaxError("End-of-file not reached.");
 
1744       } catch (SyntaxError sytaxErr1) {
 
1745         setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
 
1747           // if an error occured,
 
1748           // try to find keywords 'class' or 'function'
 
1749           // to parse the rest of the string
 
1750           while (token != TokenNameEOF && token != TokenNameERROR) {
 
1751             if (token == TokenNameclass || token == TokenNamefunction) {
 
1756           if (token == TokenNameEOF || token == TokenNameERROR) {
 
1759         } catch (SyntaxError sytaxErr2) {
 
1760           setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
 
1768   public PHPOutlineInfo parseInfo(Object parent, String s) {
 
1769     PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
 
1770     //    Stack stack = new Stack();
 
1771     //    stack.push(outlineInfo.getDeclarations());
 
1774     this.token = TokenNameEOF;
 
1777     this.columnCount = 0;
 
1778     this.phpEnd = false;
 
1779     this.phpMode = false;
 
1783       parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
 
1784     } catch (CoreException e) {
 
1789   private void parseDeclarations(PHPOutlineInfo outlineInfo, PHPSegmentWithChildren current, boolean goBack) {
 
1790     //   PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
 
1791     PHPSegmentWithChildren temp;
 
1793     String oldIdentifier;
 
1794     IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
 
1796       while (token != TokenNameEOF && token != TokenNameERROR) {
 
1797         if (token == TokenNameVariable) {
 
1798           outlineInfo.addVariable(identifier);
 
1800         } else if (token == TokenNamevar) {
 
1802           if (token == TokenNameVariable && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
 
1804             outlineInfo.addVariable(identifier);
 
1805             if (token != TokenNameSEMICOLON) {
 
1806               oldIdentifier = identifier;
 
1809                 case TokenNameVariable            : current.add(new PHPVarDeclaration(current, oldIdentifier, chIndx - identifier.length(),identifier));
 
1811                 case TokenNameIdentifier          : current.add(new PHPVarDeclaration(current, oldIdentifier, chIndx - identifier.length(),identifier));
 
1813                 case TokenNameDoubleLiteral       : current.add(new PHPVarDeclaration(current, oldIdentifier + doubleNumber, chIndx - identifier.length(),doubleNumber.toString()));
 
1815                 case TokenNameIntegerLiteral          : current.add(new PHPVarDeclaration(current, oldIdentifier, chIndx - identifier.length(),longNumber.toString()));
 
1817                 case TokenNameStringInterpolated : current.add(new PHPVarDeclaration(current, oldIdentifier, chIndx - identifier.length(),stringValue));
 
1819                 case TokenNameStringConstant     : current.add(new PHPVarDeclaration(current, oldIdentifier, chIndx - identifier.length(),stringValue));
 
1821                 default                     : current.add(new PHPVarDeclaration(current, oldIdentifier, chIndx - identifier.length()));
 
1825               current.add(new PHPVarDeclaration(current, identifier, chIndx - identifier.length()));
 
1828         } else if (token == TokenNamefunction) {
 
1830           if (token == TokenNameAND) {
 
1833           if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
 
1834             outlineInfo.addVariable(identifier);
 
1835             temp = new PHPFunctionDeclaration(current, identifier, chIndx - identifier.length());
 
1838             parseDeclarations(outlineInfo, temp, true);
 
1840         } else if (token == TokenNameclass) {
 
1842           if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
 
1843             outlineInfo.addVariable(identifier);
 
1844             temp = new PHPClassDeclaration(current, identifier, chIndx - identifier.length());
 
1846             //        stack.push(temp);
 
1849             //skip tokens for classname, extends and others until we have the opening '{'
 
1850             while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) {
 
1853             parseDeclarations(outlineInfo, temp, true);
 
1856         } else if (token == TokenNameLBRACE) {
 
1859         } else if (token == TokenNameRBRACE) {
 
1862           if (counter == 0 && goBack) {
 
1865         } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) {
 
1867           outlineInfo.addVariable(identifier);
 
1868           current.add(new PHPReqIncDeclaration(current, identifier, chIndx - identifier.length(),expression.toString()));
 
1874     } catch (CoreException e) {
 
1875     } catch (SyntaxError sytaxErr) {
 
1877         setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
 
1878       } catch (CoreException e) {
 
1883   private void statementList() throws CoreException {
 
1886       if ((token == TokenNameRBRACE)
 
1887         || (token == TokenNamecase)
 
1888         || (token == TokenNamedefault)
 
1889         || (token == TokenNameelseif)
 
1890         || (token == TokenNameendif)
 
1891         || (token == TokenNameendfor)
 
1892         || (token == TokenNameendforeach)
 
1893         || (token == TokenNameendwhile)
 
1894         || (token == TokenNameendswitch)
 
1895         || (token == TokenNameEOF)
 
1896         || (token == TokenNameERROR)) {
 
1902   private void compoundStatement() throws CoreException {
 
1903     // '{' [statement-list] '}'
 
1904     if (token == TokenNameLBRACE) {
 
1907       throwSyntaxError("'{' expected in compound-statement.");
 
1909     if (token != TokenNameRBRACE) {
 
1912     if (token == TokenNameRBRACE) {
 
1915       throwSyntaxError("'}' expected in compound-statement.");
 
1919   private void statement() throws CoreException {
 
1920     //   if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
 
1921     String keyword = identifier;
 
1922     if (token == TokenNameinclude || token == TokenNameinclude_once) {
 
1925       if (token == TokenNameSEMICOLON) {
 
1929           throwSyntaxError("';' character after 'include' or 'include_once' expected.");
 
1934     } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
 
1938       if (token == TokenNameSEMICOLON) {
 
1942           throwSyntaxError("';' character after 'require' or 'require_once' expected.");
 
1947     } else if (token == TokenNameif) {
 
1949       if (token == TokenNameLPAREN) {
 
1952         throwSyntaxError("'(' expected after 'if' keyword.");
 
1955       if (token == TokenNameRPAREN) {
 
1958         throwSyntaxError("')' expected after 'if' condition.");
 
1963     } else if (token == TokenNameswitch) {
 
1965       if (token == TokenNameLPAREN) {
 
1968         throwSyntaxError("'(' expected after 'switch' keyword.");
 
1971       if (token == TokenNameRPAREN) {
 
1974         throwSyntaxError("')' expected after 'switch' condition.");
 
1978     } else if (token == TokenNamefor) {
 
1980       if (token == TokenNameLPAREN) {
 
1983         throwSyntaxError("'(' expected after 'for' keyword.");
 
1985       if (token == TokenNameSEMICOLON) {
 
1989         if (token == TokenNameSEMICOLON) {
 
1992           throwSyntaxError("';' expected after 'for'.");
 
1995       if (token == TokenNameSEMICOLON) {
 
1999         if (token == TokenNameSEMICOLON) {
 
2002           throwSyntaxError("';' expected after 'for'.");
 
2005       if (token == TokenNameRPAREN) {
 
2009         if (token == TokenNameRPAREN) {
 
2012           throwSyntaxError("')' expected after 'for'.");
 
2017     } else if (token == TokenNamewhile) {
 
2019       if (token == TokenNameLPAREN) {
 
2022         throwSyntaxError("'(' expected after 'while' keyword.");
 
2025       if (token == TokenNameRPAREN) {
 
2028         throwSyntaxError("')' expected after 'while' condition.");
 
2032     } else if (token == TokenNamedo) {
 
2034       if (token == TokenNameLBRACE) {
 
2037         throwSyntaxError("'{' expected after 'do' keyword.");
 
2039       if (token != TokenNameRBRACE) {
 
2042       if (token == TokenNameRBRACE) {
 
2045         throwSyntaxError("'}' expected after 'do' keyword.");
 
2047       if (token == TokenNamewhile) {
 
2049         if (token == TokenNameLPAREN) {
 
2052           throwSyntaxError("'(' expected after 'while' keyword.");
 
2055         if (token == TokenNameRPAREN) {
 
2058           throwSyntaxError("')' expected after 'while' condition.");
 
2061         throwSyntaxError("'while' expected after 'do' keyword.");
 
2063       if (token == TokenNameSEMICOLON) {
 
2067           throwSyntaxError("';' expected after do-while statement.");
 
2072     } else if (token == TokenNameforeach) {
 
2074       if (token == TokenNameLPAREN) {
 
2077         throwSyntaxError("'(' expected after 'foreach' keyword.");
 
2080       if (token == TokenNameas) {
 
2083         throwSyntaxError("'as' expected after 'foreach' exxpression.");
 
2086       if (token == TokenNameFOREACH) {
 
2090       if (token == TokenNameRPAREN) {
 
2093         throwSyntaxError("')' expected after 'foreach' expression.");
 
2098     } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
 
2100       if (token != TokenNameSEMICOLON) {
 
2103       if (token == TokenNameSEMICOLON) {
 
2107           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
 
2113     } else if (token == TokenNameecho) {
 
2116       if (token == TokenNameSEMICOLON) {
 
2120           throwSyntaxError("';' expected after 'echo' statement.");
 
2125       //    } else if (token == TokenNameprint) {
 
2128       //      if (token == TokenNameSEMICOLON) {
 
2132       //          throwSyntaxError("';' expected after 'print' statement.");
 
2138     } else if (token == TokenNameglobal || token == TokenNamestatic) {
 
2141       if (token == TokenNameSEMICOLON) {
 
2145           throwSyntaxError("';' expected after 'global' or 'static' statement.");
 
2151       //      } else if (token == TokenNameunset) {
 
2153       //        if (token == TokenNameARGOPEN) {
 
2156       //          throwSyntaxError("'(' expected after 'unset' keyword.");
 
2159       //        if (token == TokenNameARGCLOSE) {
 
2162       //          throwSyntaxError("')' expected after 'unset' statement.");
 
2164       //        if (token == TokenNameSEMICOLON) {
 
2168       //            throwSyntaxError("';' expected after 'unset' statement.");
 
2174       //      } else if (token == TokenNameexit || token == TokenNamedie) {
 
2176       //        if (token != TokenNameSEMICOLON) {
 
2179       //        if (token == TokenNameSEMICOLON) {
 
2183       //            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
 
2189     } else if (token == TokenNamedefine) {
 
2191       if (token == TokenNameLPAREN) {
 
2194         throwSyntaxError("'(' expected after 'define' keyword.");
 
2197       if (token == TokenNameCOMMA) {
 
2200         throwSyntaxError("',' expected after first 'define' constant.");
 
2203       if (token == TokenNameCOMMA) {
 
2207       if (token == TokenNameRPAREN) {
 
2210         throwSyntaxError("')' expected after 'define' statement.");
 
2212       if (token == TokenNameSEMICOLON) {
 
2216           throwSyntaxError("';' expected after 'define' statement.");
 
2221     } else if (token == TokenNamefunction) {
 
2223       functionDefinition();
 
2225     } else if (token == TokenNameclass) {
 
2231       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
 
2232     } else if (token == TokenNameLBRACE) {
 
2233       // compoundStatement
 
2235       if (token != TokenNameRBRACE) {
 
2238       if (token == TokenNameRBRACE) {
 
2242         throwSyntaxError("'}' expected.");
 
2245       if (token != TokenNameSEMICOLON) {
 
2248       if (token == TokenNameSEMICOLON) {
 
2253           throwSyntaxError("';' expected after expression.");
 
2260   private void classDeclarator() throws CoreException {
 
2262     //identifier 'extends' identifier
 
2263     if (token == TokenNameIdentifier) {
 
2265       if (token == TokenNameextends) {
 
2267         if (token == TokenNameIdentifier) {
 
2270           throwSyntaxError("Class name expected after keyword 'extends'.");
 
2274       throwSyntaxError("Class name expected after keyword 'class'.");
 
2278   private void classBody() throws CoreException {
 
2279     //'{' [class-element-list] '}'
 
2280     if (token == TokenNameLBRACE) {
 
2282       if (token != TokenNameRBRACE) {
 
2285       if (token == TokenNameRBRACE) {
 
2288         throwSyntaxError("'}' expected at end of class body.");
 
2291       throwSyntaxError("'{' expected at start of class body.");
 
2295   private void classElementList() throws CoreException {
 
2298     } while (token == TokenNamefunction || token == TokenNamevar);
 
2301   private void classElement() throws CoreException {
 
2303     //function-definition
 
2304     if (token == TokenNamefunction) {
 
2306       functionDefinition();
 
2307     } else if (token == TokenNamevar) {
 
2311       throwSyntaxError("'function' or 'var' expected.");
 
2315   private void classProperty() throws CoreException {
 
2316     //'var' variable ';'
 
2317     //'var' variable '=' constant ';'
 
2319       if (token == TokenNameVariable) {
 
2321         if (token == TokenNameEQUAL) {
 
2326         throwSyntaxError("Variable expected after keyword 'var'.");
 
2328       if (token != TokenNameCOMMA) {
 
2333     if (token == TokenNameSEMICOLON) {
 
2336       throwSyntaxError("';' expected after variable declaration.");
 
2340   private void functionDefinition() throws CoreException {
 
2341     functionDeclarator();
 
2342     compoundStatement();
 
2345   private void functionDeclarator() throws CoreException {
 
2346     //identifier '(' [parameter-list] ')'
 
2347     if (token == TokenNameAND) {
 
2350     if (token == TokenNameIdentifier) {
 
2352       if (token == TokenNameLPAREN) {
 
2355         throwSyntaxError("'(' expected in function declaration.");
 
2357       if (token != TokenNameRPAREN) {
 
2360       if (token != TokenNameRPAREN) {
 
2361         throwSyntaxError("')' expected in function declaration.");
 
2368   private void parameterList() throws CoreException {
 
2369     //parameter-declaration
 
2370     //parameter-list ',' parameter-declaration
 
2372       parameterDeclaration();
 
2373       if (token != TokenNameCOMMA) {
 
2380   private void parameterDeclaration() throws CoreException {
 
2382     //variable-reference
 
2383     if (token == TokenNameAND) {
 
2385       if (token == TokenNameVariable) {
 
2388         throwSyntaxError("Variable expected after reference operator '&'.");
 
2391     //variable '=' constant
 
2392     if (token == TokenNameVariable) {
 
2394       if (token == TokenNameEQUAL) {
 
2402   private void labeledStatementList() throws CoreException {
 
2403     if (token != TokenNamecase && token != TokenNamedefault) {
 
2404       throwSyntaxError("'case' or 'default' expected.");
 
2407       if (token == TokenNamecase) {
 
2410         if (token == TokenNameCOLON) {
 
2412           if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
 
2416         } else if (token == TokenNameSEMICOLON) {
 
2417           setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO);
 
2419           if (token == TokenNamecase) { // empty case statement ?
 
2424           throwSyntaxError("':' character after 'case' constant expected.");
 
2426       } else { // TokenNamedefault
 
2428         if (token == TokenNameCOLON) {
 
2432           throwSyntaxError("':' character after 'default' expected.");
 
2435     } while (token == TokenNamecase || token == TokenNamedefault);
 
2438   //  public void labeledStatement() {
 
2439   //    if (token == TokenNamecase) {
 
2442   //      if (token == TokenNameDDOT) {
 
2446   //        throwSyntaxError("':' character after 'case' constant expected.");
 
2449   //    } else if (token == TokenNamedefault) {
 
2451   //      if (token == TokenNameDDOT) {
 
2455   //        throwSyntaxError("':' character after 'default' expected.");
 
2461   //  public void expressionStatement() {
 
2464   //  private void inclusionStatement() {
 
2467   //  public void compoundStatement() {
 
2470   //  public void selectionStatement() {
 
2473   //  public void iterationStatement() {
 
2476   //  public void jumpStatement() {
 
2479   //  public void outputStatement() {
 
2482   //  public void scopeStatement() {
 
2485   //  public void flowStatement() {
 
2488   //  public void definitionStatement() {
 
2491   private void ifStatement() throws CoreException {
 
2492     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
 
2493     if (token == TokenNameCOLON) {
 
2497         case TokenNameelse :
 
2499           if (token == TokenNameCOLON) {
 
2503             if (token == TokenNameif) { //'else if'
 
2505               elseifStatementList();
 
2507               throwSyntaxError("':' expected after 'else'.");
 
2511         case TokenNameelseif :
 
2513           elseifStatementList();
 
2517       if (token != TokenNameendif) {
 
2518         throwSyntaxError("'endif' expected.");
 
2521       if (token != TokenNameSEMICOLON) {
 
2522         throwSyntaxError("';' expected after if-statement.");
 
2526       // statement [else-statement]
 
2528       if (token == TokenNameelseif) {
 
2530         if (token == TokenNameLPAREN) {
 
2533           throwSyntaxError("'(' expected after 'elseif' keyword.");
 
2536         if (token == TokenNameRPAREN) {
 
2539           throwSyntaxError("')' expected after 'elseif' condition.");
 
2542       } else if (token == TokenNameelse) {
 
2549   private void elseifStatementList() throws CoreException {
 
2553         case TokenNameelse :
 
2555           if (token == TokenNameCOLON) {
 
2560             if (token == TokenNameif) { //'else if'
 
2563               throwSyntaxError("':' expected after 'else'.");
 
2567         case TokenNameelseif :
 
2576   private void elseifStatement() throws CoreException {
 
2577     if (token == TokenNameLPAREN) {
 
2580       if (token != TokenNameLPAREN) {
 
2581         throwSyntaxError("')' expected in else-if-statement.");
 
2584       if (token != TokenNameCOLON) {
 
2585         throwSyntaxError("':' expected in else-if-statement.");
 
2592   private void switchStatement() throws CoreException {
 
2593     if (token == TokenNameCOLON) {
 
2594       // ':' [labeled-statement-list] 'endswitch' ';'
 
2596       labeledStatementList();
 
2597       if (token != TokenNameendswitch) {
 
2598         throwSyntaxError("'endswitch' expected.");
 
2601       if (token != TokenNameSEMICOLON) {
 
2602         throwSyntaxError("';' expected after switch-statement.");
 
2606       // '{' [labeled-statement-list] '}'
 
2607       if (token != TokenNameLBRACE) {
 
2608         throwSyntaxError("'{' expected in switch statement.");
 
2611       if (token != TokenNameRBRACE) {
 
2612         labeledStatementList();
 
2614       if (token != TokenNameRBRACE) {
 
2615         throwSyntaxError("'}' expected in switch statement.");
 
2622   private void forStatement() throws CoreException {
 
2623     if (token == TokenNameCOLON) {
 
2626       if (token != TokenNameendfor) {
 
2627         throwSyntaxError("'endfor' expected.");
 
2630       if (token != TokenNameSEMICOLON) {
 
2631         throwSyntaxError("';' expected after for-statement.");
 
2639   private void whileStatement() throws CoreException {
 
2640     // ':' statement-list 'endwhile' ';'
 
2641     if (token == TokenNameCOLON) {
 
2644       if (token != TokenNameendwhile) {
 
2645         throwSyntaxError("'endwhile' expected.");
 
2648       if (token != TokenNameSEMICOLON) {
 
2649         throwSyntaxError("';' expected after while-statement.");
 
2657   private void foreachStatement() throws CoreException {
 
2658     if (token == TokenNameCOLON) {
 
2661       if (token != TokenNameendforeach) {
 
2662         throwSyntaxError("'endforeach' expected.");
 
2665       if (token != TokenNameSEMICOLON) {
 
2666         throwSyntaxError("';' expected after foreach-statement.");
 
2674   private void exitStatus() throws CoreException {
 
2675     if (token == TokenNameLPAREN) {
 
2678       throwSyntaxError("'(' expected in 'exit-status'.");
 
2680     if (token != TokenNameRPAREN) {
 
2683     if (token == TokenNameRPAREN) {
 
2686       throwSyntaxError("')' expected after 'exit-status'.");
 
2690   private void expressionList() throws CoreException {
 
2693       if (token == TokenNameCOMMA) {
 
2701   private void expression() throws CoreException {
 
2702     //todo: find a better way to get the expression
 
2703     expression = new StringBuffer();
 
2704     for (int i = chIndx;i<str.length();i++) {
 
2705       if (str.charAt(i) == ';') {
 
2708       expression.append(str.charAt(i));
 
2710     //    if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
 
2713     logicalinclusiveorExpression();
 
2714     //      while (token != TokenNameSEMICOLON) {
 
2720   private void postfixExpression() throws CoreException {
 
2722     boolean castFlag = false;
 
2728       case TokenNamenull :
 
2731       case TokenNamefalse :
 
2734       case TokenNametrue :
 
2737       case TokenNameStringConstant :
 
2740       case TokenNameStringInterpolated :
 
2743       case TokenNameLPAREN :
 
2745         if (token == TokenNameIdentifier) {
 
2746           // check if identifier is a type:
 
2748           String str = identifier.toLowerCase();
 
2749           for (int i = 0; i < PHP_TYPES.length; i++) {
 
2750             if (PHP_TYPES[i].equals(str)) {
 
2757             if (token != TokenNameRPAREN) {
 
2758               throwSyntaxError(") expected after cast-type '" + ident + "'.");
 
2768         if (token != TokenNameRPAREN) {
 
2769           throwSyntaxError(") expected in postfix-expression.");
 
2773       case TokenNameDoubleLiteral :
 
2776       case TokenNameIntegerLiteral :
 
2779       case TokenNameDOLLAROPEN :
 
2782         if (token != TokenNameRBRACE) {
 
2783           throwSyntaxError("'}' expected after indirect variable token '${'.");
 
2787       case TokenNameVariable :
 
2790         if (token == TokenNameLBRACE) {
 
2793           if (token != TokenNameRBRACE) {
 
2794             throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression.");
 
2797         } else if (token == TokenNameLPAREN) {
 
2799           if (token != TokenNameRPAREN) {
 
2801             if (token != TokenNameRPAREN) {
 
2802               throwSyntaxError("')' expected after variable '" + ident + "' in postfix-expression.");
 
2808       case TokenNameIdentifier :
 
2811         if (token == TokenNameLPAREN) {
 
2813           if (token != TokenNameRPAREN) {
 
2815             if (token != TokenNameRPAREN) {
 
2816               throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
 
2822       case TokenNameprint :
 
2825         //        if (token == TokenNameSEMICOLON) {
 
2829         //            throwSyntaxError("';' expected after 'print' statement.");
 
2834       case TokenNamelist :
 
2836         if (token == TokenNameLPAREN) {
 
2838           if (token == TokenNameCOMMA) {
 
2842           if (token != TokenNameRPAREN) {
 
2843             throwSyntaxError("')' expected after 'list' keyword.");
 
2846           //          if (token == TokenNameSET) {
 
2848           //            logicalinclusiveorExpression();
 
2851           throwSyntaxError("'(' expected after 'list' keyword.");
 
2854         //      case TokenNameexit :
 
2856         //        if (token != TokenNameSEMICOLON) {
 
2859         //        if (token == TokenNameSEMICOLON) {
 
2863         //            throwSyntaxError("';' expected after 'exit' expression.");
 
2868         //      case TokenNamedie :
 
2870         //        if (token != TokenNameSEMICOLON) {
 
2873         //        if (token == TokenNameSEMICOLON) {
 
2877         //            throwSyntaxError("';' expected after 'die' expression.");
 
2882         //      case TokenNamearray :
 
2884         //        if (token == TokenNameARGOPEN) {
 
2886         //          if (token == TokenNameCOMMA) {
 
2889         //          expressionList();
 
2890         //          if (token != TokenNameARGCLOSE) {
 
2891         //            throwSyntaxError("')' expected after 'list' keyword.");
 
2894         //          if (token == TokenNameSET) {
 
2896         //            logicalinclusiveorExpression();
 
2899         //          throwSyntaxError("'(' expected after 'list' keyword.");
 
2903     boolean while_flag = true;
 
2906         case TokenNameLBRACKET :
 
2909           if (token != TokenNameRBRACKET) {
 
2910             throwSyntaxError("] expected in postfix-expression.");
 
2914         case TokenNameCOLON_COLON : // ::
 
2915         case TokenNameMINUS_GREATER : // ->
 
2917           if (token > TokenNameKEYWORD) {
 
2919             setMarker("Avoid using keyword '" + ident + "' as variable name.", rowCount, PHPParser.INFO);
 
2922             case TokenNameVariable :
 
2925               //              if (token == TokenNameARGOPEN) {
 
2927               //                expressionList();
 
2928               //                if (token != TokenNameARGCLOSE) {
 
2929               //                  throwSyntaxError(") expected after variable '" + ident + "'.");
 
2934             case TokenNameIdentifier :
 
2938             case TokenNameLBRACE :
 
2941               if (token != TokenNameRBRACE) {
 
2942                 throwSyntaxError("} expected in postfix-expression.");
 
2947               throwSyntaxError("Syntax error after '->' token.");
 
2948           } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
 
2949               if (token == TokenNameLBRACKET) {
 
2952                 if (token != TokenNameRBRACKET) {
 
2953                   throwSyntaxError("] expected after '->'.");
 
2957               if (token == TokenNameLPAREN) {
 
2960                 if (token != TokenNameRPAREN) {
 
2961                   throwSyntaxError(") expected after '->'.");
 
2965               if (token == TokenNameLBRACE) {
 
2968                 if (token != TokenNameRBRACE) {
 
2969                   throwSyntaxError("} expected after '->'.");
 
2975         case TokenNamePLUS_PLUS :
 
2978         case TokenNameMINUS_MINUS :
 
2989   private void unaryExpression() throws CoreException {
 
2991       case TokenNamePLUS_PLUS :
 
2995       case TokenNameMINUS_MINUS :
 
2999         // '@' '&' '*' '+' '-' '~' '!'
 
3008       case TokenNameMULTIPLY :
 
3012       case TokenNamePLUS :
 
3016       case TokenNameMINUS :
 
3020       case TokenNameTWIDDLE :
 
3029         postfixExpression();
 
3033   private void castExpression() throws CoreException {
 
3034     //    if (token == TokenNameARGOPEN) {
 
3037     //      if (token != TokenNameARGCLOSE) {
 
3038     //        throwSyntaxError(") expected after cast-expression.");
 
3045   private void typeName() throws CoreException {
 
3046     //'string' 'unset' 'array' 'object'
 
3048     //'real' 'double' 'float'
 
3051     if (token == TokenNameIdentifier) {
 
3053       String str = identifier.toLowerCase();
 
3055       for (int i = 0; i < PHP_TYPES.length; i++) {
 
3056         if (PHP_TYPES[i].equals(str)) {
 
3061     throwSyntaxError("Expected type cast '( <type-name> )'; Got '" + ident + "'.");
 
3064   private void assignExpression() throws CoreException {
 
3066     if (token == TokenNameEQUAL) { // =
 
3068       logicalinclusiveorExpression();
 
3069     } else if (token == TokenNameDOT_EQUAL) { // .=
 
3071       logicalinclusiveorExpression();
 
3072     } else if (token == TokenNameFOREACH) { // =>
 
3074       logicalinclusiveorExpression();
 
3075     } else if (token == TokenNamePLUS_EQUAL) { // +=
 
3077       logicalinclusiveorExpression();
 
3078     } else if (token == TokenNameMINUS_EQUAL) { // -=
 
3080       logicalinclusiveorExpression();
 
3081     } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
 
3083       logicalinclusiveorExpression();
 
3084     } else if (token == TokenNameDIVIDE_EQUAL) { // *=
 
3086       logicalinclusiveorExpression();
 
3087     } else if (token == TokenNameREMAINDER_EQUAL) { // %=
 
3089       logicalinclusiveorExpression();
 
3090     } else if (token == TokenNameAND_EQUAL) { // &=
 
3092       logicalinclusiveorExpression();
 
3093     } else if (token == TokenNameXOR_EQUAL) { // ^=
 
3095       logicalinclusiveorExpression();
 
3096     } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
 
3098       logicalinclusiveorExpression();
 
3099     } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
 
3101       logicalinclusiveorExpression();
 
3102     } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
 
3104       logicalinclusiveorExpression();
 
3108   private void multiplicativeExpression() throws CoreException {
 
3111       if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
 
3118   private void concatenationExpression() throws CoreException {
 
3120       multiplicativeExpression();
 
3121       if (token != TokenNameDOT) {
 
3128   private void additiveExpression() throws CoreException {
 
3130       concatenationExpression();
 
3131       if (token != TokenNamePLUS && token != TokenNameMINUS) {
 
3138   private void shiftExpression() throws CoreException {
 
3140       additiveExpression();
 
3141       if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
 
3148   private void relationalExpression() throws CoreException {
 
3151       if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
 
3158   private void identicalExpression() throws CoreException {
 
3160       relationalExpression();
 
3161       if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
 
3168   private void equalityExpression() throws CoreException {
 
3170       identicalExpression();
 
3171       if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
 
3178   private void ternaryExpression() throws CoreException {
 
3179     equalityExpression();
 
3180     if (token == TokenNameQUESTION) {
 
3183       if (token == TokenNameCOLON) {
 
3187         throwSyntaxError("':' expected in ternary operator '? :'.");
 
3192   private void andExpression() throws CoreException {
 
3194       ternaryExpression();
 
3195       if (token != TokenNameAND) {
 
3202   private void exclusiveorExpression() throws CoreException {
 
3205       if (token != TokenNameXOR) {
 
3212   private void inclusiveorExpression() throws CoreException {
 
3214       exclusiveorExpression();
 
3215       if (token != TokenNameOR) {
 
3222   private void booleanandExpression() throws CoreException {
 
3224       inclusiveorExpression();
 
3225       if (token != TokenNameAND_AND) {
 
3232   private void booleanorExpression() throws CoreException {
 
3234       booleanandExpression();
 
3235       if (token != TokenNameOR_OR) {
 
3242   private void logicalandExpression() throws CoreException {
 
3244       booleanorExpression();
 
3245       if (token != TokenNameAND) {
 
3252   private void logicalexclusiveorExpression() throws CoreException {
 
3254       logicalandExpression();
 
3255       if (token != TokenNameXOR) {
 
3262   private void logicalinclusiveorExpression() throws CoreException {
 
3264       logicalexclusiveorExpression();
 
3265       if (token != TokenNameOR) {
 
3272   //  public void assignmentExpression() {
 
3273   //    if (token == TokenNameVARIABLE) {
 
3275   //      if (token == TokenNameSET) {
 
3277   //        logicalinclusiveorExpression();
 
3280   //      logicalinclusiveorExpression();
 
3284   private void variableList() throws CoreException {
 
3287       if (token == TokenNameCOMMA) {
 
3295   private void variable() throws CoreException {
 
3296     if (token == TokenNameDOLLAROPEN) {
 
3300       if (token != TokenNameRBRACE) {
 
3301         throwSyntaxError("'}' expected after indirect variable token '${'.");
 
3305       if (token == TokenNameVariable) {
 
3307         if (token == TokenNameLBRACKET) {
 
3310           if (token != TokenNameRBRACKET) {
 
3311             throwSyntaxError("']' expected in variable-list.");
 
3314         } else if (token == TokenNameEQUAL) {
 
3319         throwSyntaxError("$-variable expected in variable-list.");
 
3325    * It will look for a value (after a '=' for example)
 
3326    * @throws CoreException
 
3328   private void constant() throws CoreException {
 
3331       case TokenNamePLUS :
 
3334           case TokenNameDoubleLiteral :
 
3337           case TokenNameIntegerLiteral :
 
3341             throwSyntaxError("Constant expected after '+' presign.");
 
3344       case TokenNameMINUS :
 
3347           case TokenNameDoubleLiteral :
 
3350           case TokenNameIntegerLiteral :
 
3354             throwSyntaxError("Constant expected after '-' presign.");
 
3357       case TokenNamenull :
 
3360       case TokenNamefalse :
 
3363       case TokenNametrue :
 
3366       case TokenNameIdentifier :
 
3369         if (token == TokenNameLPAREN) {
 
3371           if (token != TokenNameRPAREN) {
 
3373             if (token != TokenNameRPAREN) {
 
3374               throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
 
3380       case TokenNameStringConstant :
 
3383       case TokenNameStringInterpolated :
 
3386       case TokenNameDoubleLiteral :
 
3389       case TokenNameIntegerLiteral :
 
3393         throwSyntaxError("Constant expected.");
 
3398    * Call the php parse command ( php -l -f <filename> )
 
3399    * and create markers according to the external parser output
 
3401   public static void phpExternalParse(IFile file) {
 
3402     //IFile file = (IFile) resource;
 
3403     IPath path = file.getFullPath();
 
3404     IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
 
3405     String filename = file.getLocation().toString();
 
3407     String[] arguments = { filename };
 
3408     MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
 
3409     String command = form.format(arguments);
 
3411     String parserResult = PHPStartApacheAction.getParserOutput(command, "External parser: ");
 
3414       // parse the buffer to find the errors and warnings
 
3415       createMarkers(parserResult, file);
 
3416     } catch (CoreException e) {
 
3421    * Create markers according to the external parser output
 
3423   private static void createMarkers(String output, IFile file) throws CoreException {
 
3424     // delete all markers
 
3425     file.deleteMarkers(IMarker.PROBLEM, false, 0);
 
3429     boolean flag = true;
 
3430     while ((brIndx = output.indexOf("<br />", indx)) != -1) {
 
3431       // newer php error output (tested with 4.2.3)
 
3432       scanLine(output, file, indx, brIndx);
 
3437       while ((brIndx = output.indexOf("<br>", indx)) != -1) {
 
3438         // older php error output (tested with 4.2.3)
 
3439         scanLine(output, file, indx, brIndx);
 
3445   private static void scanLine(String output, IFile file, int indx, int brIndx) throws CoreException {
 
3447     String outLineNumberString;
 
3448     StringBuffer lineNumberBuffer = new StringBuffer(10);
 
3450     current = output.substring(indx, brIndx);
 
3452     if (current.indexOf(PARSE_WARNING_STRING) != -1 || current.indexOf(PARSE_ERROR_STRING) != -1) {
 
3453       int onLine = current.indexOf("on line <b>");
 
3455         lineNumberBuffer.delete(0, lineNumberBuffer.length());
 
3456         for (int i = onLine; i < current.length(); i++) {
 
3457           ch = current.charAt(i);
 
3458           if ('0' <= ch && '9' >= ch) {
 
3459             lineNumberBuffer.append(ch);
 
3463         int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
 
3465         Hashtable attributes = new Hashtable();
 
3467         current = current.replaceAll("\n", "");
 
3468         current = current.replaceAll("<b>", "");
 
3469         current = current.replaceAll("</b>", "");
 
3470         MarkerUtilities.setMessage(attributes, current);
 
3472         if (current.indexOf(PARSE_ERROR_STRING) != -1)
 
3473           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
 
3474         else if (current.indexOf(PARSE_WARNING_STRING) != -1)
 
3475           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
 
3477           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
 
3478         MarkerUtilities.setLineNumber(attributes, lineNumber);
 
3479         MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);