--- /dev/null
+/**********************************************************************
+Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ Klaus Hartlage - www.eclipseproject.de
+**********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.phpparser;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
+import net.sourceforge.phpeclipse.phpeditor.PHPString;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.ui.texteditor.MarkerUtilities;
+
+public class PHPParser extends PHPKeywords {
+ // strings for external parser call
+ private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
+ private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
+
+ public static final int ERROR = 2;
+ public static final int WARNING = 1;
+ public static final int INFO = 0;
+ private IFile fileToParse;
+ private ArrayList phpList;
+
+ private int currentPHPString;
+ private boolean phpEnd;
+
+ private static HashMap keywordMap = null;
+ private String str;
+
+ // current character
+ char ch;
+ // current token
+ int token;
+
+ // row counter for syntax errors:
+ int rowCount;
+ // column counter for syntax errors:
+ int columnCount;
+
+ int chIndx;
+
+ // current identifier
+ String identifier;
+
+ Long longNumber;
+ Double doubleNumber;
+ private boolean phpMode;
+
+ final static int TT_EOF = 0;
+ final static int TT_UNDEFINED = 1;
+ final static int TT_HTML = 2;
+
+ final static int TT_MOD = 30;
+ final static int TT_NOT = 31;
+ final static int TT_DOT = 32;
+ final static int TT_POW = 33;
+ final static int TT_DIV = 34;
+ final static int TT_MULTIPLY = 35;
+ final static int TT_SUBTRACT = 36;
+ final static int TT_ADD = 37;
+ final static int TT_EQUAL = 38;
+ final static int TT_UNEQUAL = 39;
+ final static int TT_GREATER = 40;
+ final static int TT_GREATEREQUAL = 41;
+ final static int TT_LESS = 42;
+ final static int TT_LESSEQUAL = 43;
+ final static int TT_AND = 44;
+ final static int TT_OR = 45;
+ final static int TT_HASH = 46;
+ final static int TT_DDOT = 47;
+ final static int TT_DOTASSIGN = 48;
+
+ final static int TT_ASSIGN = 49;
+ final static int TT_REF = 50;
+ final static int TT_FOREACH = 51;
+ final static int TT_AMPERSAND = 52;
+ final static int TT_DOLLARLISTOPEN = 53;
+ final static int TT_TILDE = 54;
+ final static int TT_TILDEASSIGN = 55;
+ final static int TT_MODASSIGN = 56;
+ final static int TT_POWASSIGN = 57;
+ final static int TT_RSHIFTASSIGN = 58;
+ final static int TT_LSHIFTASSIGN = 59;
+ final static int TT_ANDASSIGN = 60;
+ final static int TT_QUESTIONMARK = 61;
+ final static int TT_DDOT2 = 62;
+ final static int TT_AT = 63;
+ // final static int TT_HEREDOC = 64;
+
+ final static int TT_DOLLAROPEN = 127;
+ final static int TT_ARGOPEN = 128;
+ final static int TT_ARGCLOSE = 129;
+ final static int TT_LISTOPEN = 130;
+ final static int TT_LISTCLOSE = 131;
+ final static int TT_PARTOPEN = 132;
+ final static int TT_PARTCLOSE = 133;
+ final static int TT_COMMA = 134;
+
+ final static int TT_STRING = 136;
+ final static int TT_IDENTIFIER = 138;
+ final static int TT_DIGIT = 139;
+ final static int TT_SEMICOLON = 140;
+ final static int TT_SLOT = 141;
+ final static int TT_SLOTSEQUENCE = 142;
+ final static int TT_DECREMENT = 144;
+ final static int TT_INCREMENT = 145;
+ final static int TT_ADDTO = 146;
+ final static int TT_DIVIDEBY = 147;
+ final static int TT_SUBTRACTFROM = 148;
+ final static int TT_TIMESBY = 149;
+ final static int TT_VARIABLE = 150;
+ final static int TT_INT_NUMBER = 151;
+ final static int TT_DOUBLE_NUMBER = 152;
+ final static int TT_INTERPOLATED_STRING = 153;
+ final static int TT_STRING_CONSTANT = 154;
+
+ final static int TT_LSHIFT = 155;
+ final static int TT_RSHIFT = 156;
+ final static int TT_EX_EQUAL = 157;
+ final static int TT_EX_UNEQUAL = 158;
+ final static int TT_LINE = 159;
+ // final static int TT_AT = 153; // @
+ /**
+ * Class Constructor.
+ *
+ *@param s
+ *@param sess Description of Parameter
+ *@see
+ */
+ public PHPParser(IFile fileToParse) {
+ if (keywordMap == null) {
+ keywordMap = new HashMap();
+ for (int i = 0; i < PHP_KEYWORS.length; i++) {
+ keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
+ }
+ }
+ this.currentPHPString = 0;
+ this.fileToParse = fileToParse;
+ this.phpList = null;
+ this.str = "";
+ this.token = TT_EOF;
+ this.chIndx = 0;
+ this.rowCount = 1;
+ this.columnCount = 0;
+ this.phpEnd = false;
+
+ // getNextToken();
+ }
+
+ /**
+ * Create marker for the parse error
+ */
+ private void setMarker(String message, int lineNumber, int errorLevel) throws CoreException {
+ setMarker(fileToParse, message, lineNumber, errorLevel);
+ }
+
+ public static void setMarker(IFile file, String message, int lineNumber, int errorLevel) throws CoreException {
+
+ Hashtable attributes = new Hashtable();
+ MarkerUtilities.setMessage(attributes, message);
+ switch (errorLevel) {
+ case ERROR :
+ attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
+ break;
+ case WARNING :
+ attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
+ break;
+ case INFO :
+ attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
+ break;
+ }
+ MarkerUtilities.setLineNumber(attributes, lineNumber);
+ MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
+ }
+
+ private void throwSyntaxError(String error) {
+
+ if (str.length() < chIndx) {
+ chIndx--;
+ }
+ // read until end-of-line
+ int eol = chIndx;
+ while (str.length() > eol) {
+ ch = str.charAt(eol++);
+ if (ch == '\n') {
+ eol--;
+ break;
+ }
+ }
+ throw new SyntaxError(rowCount, chIndx - columnCount + 1, str.substring(columnCount, eol), error);
+ }
+
+ private void throwSyntaxError(String error, int startRow) {
+
+ throw new SyntaxError(startRow, 0, " ", error);
+ }
+
+ /**
+ * Method Declaration.
+ *
+ *@see
+ */
+ private void getChar() {
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+
+ return;
+ }
+
+ chIndx = str.length() + 1;
+ ch = ' ';
+ // token = TT_EOF;
+ phpEnd = true;
+ }
+
+ private void getNextToken_OldVersion() throws CoreException {
+ phpEnd = false;
+
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ token = TT_UNDEFINED;
+ if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ continue; // while loop
+ }
+ if (str.length() == chIndx) {
+ phpEnd = true;
+ }
+ if (!Character.isWhitespace(ch)) {
+ if (ch == '$') {
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '{') {
+ chIndx++;
+ token = TT_DOLLAROPEN;
+ return;
+ }
+ }
+ getIdentifier();
+ return;
+ }
+ if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) {
+ getIdentifier();
+ return;
+ }
+ if (ch >= '0' && ch <= '9') {
+ getNumber();
+ return;
+ }
+ if (ch == '/') {
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '/') {
+ chIndx++;
+ // read comment until end of line:
+ while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
+ chIndx++;
+ }
+ continue;
+ } else if (str.charAt(chIndx) == '*') {
+ chIndx++;
+ // multi line comment:
+ while (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
+ chIndx += 2;
+ break;
+ }
+ ch = str.charAt(chIndx++);
+ if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ }
+ }
+ continue;
+ }
+ }
+ } else if (ch == '#') {
+ // read comment until end of line:
+ while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
+ chIndx++;
+ }
+ continue;
+ } else if (ch == '"') {
+ // read string until end
+ boolean openString = true;
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ if (ch == '\\') {
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ }
+ } else if (ch == '"') {
+ openString = false;
+ break;
+ } else if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ }
+ }
+ if (openString) {
+ throwSyntaxError("Open string character '\"' at end of file.");
+ }
+ token = TT_INTERPOLATED_STRING;
+ return;
+ } else if (ch == '\'') {
+ // read string until end
+ boolean openString = true;
+ int startRow = rowCount;
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ if (ch == '\\') {
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ }
+ } else if (ch == '\'') {
+ openString = false;
+ break;
+ } else if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ }
+ }
+ if (openString) {
+ throwSyntaxError("Open string character \"'\" at end of file.", startRow);
+ }
+ token = TT_STRING_CONSTANT;
+ return;
+ } else if (ch == '`') {
+ // read string until end
+ boolean openString = true;
+ int startRow = rowCount;
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ if (ch == '\\') {
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ }
+ } else if (ch == '`') {
+ openString = false;
+ break;
+ } else if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ }
+ }
+ if (openString) {
+ throwSyntaxError("Open string character \"`\" at end of file.", startRow);
+ }
+ setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO);
+ token = TT_STRING_CONSTANT;
+ return;
+ }
+
+ switch (ch) {
+
+ case '(' :
+ token = TT_ARGOPEN;
+
+ break;
+ case ')' :
+ token = TT_ARGCLOSE;
+
+ break;
+ case '{' :
+ token = TT_LISTOPEN;
+
+ break;
+ case '}' :
+ token = TT_LISTCLOSE;
+
+ break;
+ case '[' :
+ token = TT_PARTOPEN;
+
+ break;
+ case ']' :
+ token = TT_PARTCLOSE;
+
+ break;
+ case ',' :
+ token = TT_COMMA;
+
+ break;
+ case '?' :
+ token = TT_QUESTIONMARK;
+ break;
+ case '@' :
+ token = TT_AT;
+ break;
+ case '~' :
+ token = TT_TILDE;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_TILDEASSIGN;
+
+ break;
+ }
+ }
+ break;
+ case '.' :
+ token = TT_DOT;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_DOTASSIGN;
+
+ break;
+ }
+ }
+
+ break;
+ case '"' :
+ token = TT_STRING;
+
+ break;
+ case '%' :
+ token = TT_MOD;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_MODASSIGN;
+
+ break;
+ }
+ }
+ break;
+ case ';' :
+ token = TT_SEMICOLON;
+
+ break;
+ case '^' :
+ token = TT_POW;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_POWASSIGN;
+
+ break;
+ }
+ }
+ break;
+ case '/' :
+ token = TT_DIV;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_DIVIDEBY;
+
+ break;
+ }
+ }
+
+ break;
+ case '*' :
+ token = TT_MULTIPLY;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '*') {
+ chIndx++;
+ token = TT_POW;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_TIMESBY;
+
+ break;
+ }
+ }
+
+ break;
+ case '+' :
+ token = TT_ADD;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '+') {
+ chIndx++;
+ token = TT_INCREMENT;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_ADDTO;
+
+ break;
+ }
+ }
+ break;
+ case '-' :
+ token = TT_SUBTRACT;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '-') {
+ chIndx++;
+ token = TT_DECREMENT;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_SUBTRACTFROM;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '>') {
+ chIndx++;
+ token = TT_REF;
+
+ break;
+ }
+ }
+
+ break;
+ case '=' :
+ token = TT_ASSIGN;
+
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx);
+
+ if (ch == '=') {
+ chIndx++;
+ token = TT_EQUAL;
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx);
+
+ if (ch == '=') {
+ chIndx++;
+ token = TT_EX_EQUAL;
+ }
+ }
+ break;
+ }
+ if (ch == '>') {
+ chIndx++;
+ token = TT_FOREACH;
+
+ break;
+ }
+ }
+
+ break;
+ case '!' :
+ token = TT_NOT;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_UNEQUAL;
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx);
+
+ if (ch == '=') {
+ chIndx++;
+ token = TT_EX_UNEQUAL;
+ }
+ }
+ break;
+ }
+ }
+
+ break;
+ case '>' :
+ token = TT_GREATER;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_GREATEREQUAL;
+ break;
+ }
+ if (str.charAt(chIndx) == '>') {
+ chIndx++;
+ token = TT_RSHIFT;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_RSHIFTASSIGN;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ break;
+ case '<' :
+ token = TT_LESS;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_LESSEQUAL;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '<') {
+ chIndx++;
+ token = TT_LSHIFT;
+ if (str.charAt(chIndx) == '<') {
+ // heredoc
+ int startRow = rowCount;
+ if (str.length() > chIndx) {
+
+ ch = str.charAt(++chIndx);
+ if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_')) {
+ chIndx++;
+ getIdentifier();
+ token = TT_STRING_CONSTANT;
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ if (ch == '\n') {
+ if (str.length() >= chIndx + identifier.length()) {
+ if (str.substring(chIndx, chIndx + identifier.length()).equals(identifier)) {
+ chIndx += identifier.length();
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ throwSyntaxError("Open heredoc syntax after operator '<<<'.", startRow);
+ } else if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_LSHIFTASSIGN;
+ break;
+ }
+ break;
+ }
+ }
+
+ break;
+
+ case '|' :
+ token = TT_LINE;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '|') {
+ chIndx++;
+ token = TT_OR;
+
+ break;
+ }
+ }
+
+ break;
+ case '&' :
+ token = TT_AMPERSAND;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '&') {
+ chIndx++;
+ token = TT_AND;
+ break;
+ }
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_ANDASSIGN;
+ break;
+ }
+ break;
+ }
+
+ break;
+ case ':' :
+ token = TT_DDOT;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == ':') {
+ chIndx++;
+ token = TT_DDOT2;
+ }
+ }
+ break;
+ case '#' :
+ token = TT_HASH;
+
+ break;
+ // case '@' :
+ // token = TT_AT;
+ //
+ // break;
+ default :
+ throwSyntaxError("unexpected character: '" + ch + "'");
+ }
+
+ if (token == TT_UNDEFINED) {
+ throwSyntaxError("token not found");
+ }
+
+ return;
+ }
+ }
+
+ chIndx = str.length() + 1;
+ ch = ' ';
+ token = TT_EOF;
+ phpEnd = true;
+ PHPString temp;
+ if (phpList != null) {
+ if (currentPHPString < phpList.size()) {
+ token = TT_UNDEFINED;
+ temp = (PHPString) phpList.get(currentPHPString++);
+ this.str = temp.getPHPString();
+ this.token = TT_EOF;
+ this.chIndx = 0;
+ this.rowCount = temp.getLineNumber();
+ this.columnCount = 0;
+ getNextToken();
+ phpEnd = true;
+ } else {
+ token = TT_UNDEFINED;
+ return;
+ }
+ }
+ }
+ /**
+ * gets the next token from input
+ */
+ private void getNextToken() throws CoreException {
+ boolean phpFound = false;
+ char ch2;
+
+ phpEnd = false;
+ try {
+ if (!phpMode) {
+
+ while (str.length() > chIndx) {
+ token = TT_UNDEFINED;
+ ch = str.charAt(chIndx++);
+
+ if (ch == '\n') {
+ rowCount++;
+ }
+ if (ch == '<') {
+ ch2 = str.charAt(chIndx++);
+ if (ch2 == '?') {
+ ch2 = str.charAt(chIndx++);
+ if (Character.isWhitespace(ch2)) {
+ // php start
+ phpMode = true;
+ phpFound = true;
+ break;
+ } else if (ch2 == 'p') {
+ ch2 = str.charAt(chIndx++);
+ if (ch2 == 'h') {
+ ch2 = str.charAt(chIndx++);
+ if (ch2 == 'p') {
+ phpMode = true;
+ phpFound = true;
+ break;
+ }
+ chIndx--;
+ }
+ chIndx--;
+ } else if (ch2 == 'P') {
+ ch2 = str.charAt(chIndx++);
+ if (ch2 == 'H') {
+ ch2 = str.charAt(chIndx++);
+ if (ch2 == 'P') {
+ phpMode = true;
+ phpFound = true;
+ break;
+ }
+ chIndx--;
+ }
+ chIndx--;
+ }
+ chIndx--;
+ }
+ chIndx--;
+ }
+ }
+
+ }
+
+ if (phpMode) {
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ token = TT_UNDEFINED;
+ if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ continue; // while loop
+ }
+ if (str.length() == chIndx) {
+ phpEnd = true;
+ }
+ if (!Character.isWhitespace(ch)) {
+ if (ch == '$') {
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '{') {
+ chIndx++;
+ token = TT_DOLLAROPEN;
+ return;
+ }
+ }
+ getIdentifier();
+ return;
+ }
+ if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) {
+ getIdentifier();
+ return;
+ }
+ if (ch >= '0' && ch <= '9') {
+ getNumber();
+ return;
+ }
+ if (ch == '/') {
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '/') {
+ ch = '/';
+ chIndx++;
+ // read comment until end of line:
+ while ((str.length() > chIndx) && (ch != '\n')) {
+ ch = str.charAt(chIndx++);
+ if (ch == '?') {
+ ch2 = str.charAt(chIndx);
+ if (ch2 == '>') {
+ chIndx++;
+ token = TT_HTML;
+ // php end
+ phpMode = false;
+ phpEnd = true;
+ return;
+ }
+ }
+ }
+ rowCount++;
+ continue;
+
+ } else if (str.charAt(chIndx) == '*') {
+ chIndx++;
+ // multi line comment:
+ while (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
+ chIndx += 2;
+ break;
+ }
+ ch = str.charAt(chIndx++);
+ if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ }
+ }
+ continue;
+ }
+ }
+ } else if (ch == '#') {
+ // read comment until end of line:
+ while ((str.length() > chIndx) && (ch != '\n')) {
+ ch = str.charAt(chIndx++);
+ if (ch == '?') {
+ ch2 = str.charAt(chIndx);
+ if (ch2 == '>') {
+ chIndx++;
+ token = TT_HTML;
+ // php end
+ phpMode = false;
+ phpEnd = true;
+ return;
+ }
+ }
+ }
+ rowCount++;
+ continue;
+
+ } else if (ch == '"') {
+ // read string until end
+ boolean openString = true;
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ if (ch == '\\') {
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ }
+ } else if (ch == '"') {
+ openString = false;
+ break;
+ } else if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ }
+ }
+ if (openString) {
+ throwSyntaxError("Open string character '\"' at end of file.");
+ }
+ token = TT_INTERPOLATED_STRING;
+ return;
+ } else if (ch == '\'') {
+ // read string until end
+ boolean openString = true;
+ int startRow = rowCount;
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ if (ch == '\\') {
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ }
+ } else if (ch == '\'') {
+ openString = false;
+ break;
+ } else if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ }
+ }
+ if (openString) {
+ throwSyntaxError("Open string character \"'\" at end of file.", startRow);
+ }
+ token = TT_STRING_CONSTANT;
+ return;
+ } else if (ch == '`') {
+ // read string until end
+ boolean openString = true;
+ int startRow = rowCount;
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ if (ch == '\\') {
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ }
+ } else if (ch == '`') {
+ openString = false;
+ break;
+ } else if (ch == '\n') {
+ rowCount++;
+ columnCount = chIndx;
+ }
+ }
+ if (openString) {
+ throwSyntaxError("Open string character \"`\" at end of file.", startRow);
+ }
+ setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO);
+ token = TT_STRING_CONSTANT;
+ return;
+ }
+
+ switch (ch) {
+
+ case '(' :
+ token = TT_ARGOPEN;
+
+ break;
+ case ')' :
+ token = TT_ARGCLOSE;
+
+ break;
+ case '{' :
+ token = TT_LISTOPEN;
+
+ break;
+ case '}' :
+ token = TT_LISTCLOSE;
+
+ break;
+ case '[' :
+ token = TT_PARTOPEN;
+
+ break;
+ case ']' :
+ token = TT_PARTCLOSE;
+
+ break;
+ case ',' :
+ token = TT_COMMA;
+
+ break;
+ case '?' :
+ token = TT_QUESTIONMARK;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '>') {
+ chIndx++;
+ token = TT_HTML;
+ // php end
+ phpMode = false;
+ phpEnd = true;
+ break;
+ }
+ }
+
+ break;
+ case '@' :
+ token = TT_AT;
+ break;
+ case '~' :
+ token = TT_TILDE;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_TILDEASSIGN;
+
+ break;
+ }
+ }
+ break;
+ case '.' :
+ token = TT_DOT;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_DOTASSIGN;
+
+ break;
+ }
+ }
+
+ break;
+ case '"' :
+ token = TT_STRING;
+
+ break;
+ case '%' :
+ token = TT_MOD;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_MODASSIGN;
+
+ break;
+ }
+ }
+ break;
+ case ';' :
+ token = TT_SEMICOLON;
+
+ break;
+ case '^' :
+ token = TT_POW;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_POWASSIGN;
+
+ break;
+ }
+ }
+ break;
+ case '/' :
+ token = TT_DIV;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_DIVIDEBY;
+
+ break;
+ }
+ }
+
+ break;
+ case '*' :
+ token = TT_MULTIPLY;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '*') {
+ chIndx++;
+ token = TT_POW;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_TIMESBY;
+
+ break;
+ }
+ }
+
+ break;
+ case '+' :
+ token = TT_ADD;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '+') {
+ chIndx++;
+ token = TT_INCREMENT;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_ADDTO;
+
+ break;
+ }
+ }
+ break;
+ case '-' :
+ token = TT_SUBTRACT;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '-') {
+ chIndx++;
+ token = TT_DECREMENT;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_SUBTRACTFROM;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '>') {
+ chIndx++;
+ token = TT_REF;
+
+ break;
+ }
+ }
+
+ break;
+ case '=' :
+ token = TT_ASSIGN;
+
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx);
+
+ if (ch == '=') {
+ chIndx++;
+ token = TT_EQUAL;
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx);
+
+ if (ch == '=') {
+ chIndx++;
+ token = TT_EX_EQUAL;
+ }
+ }
+ break;
+ }
+ if (ch == '>') {
+ chIndx++;
+ token = TT_FOREACH;
+
+ break;
+ }
+ }
+
+ break;
+ case '!' :
+ token = TT_NOT;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_UNEQUAL;
+ if (str.length() > chIndx) {
+ ch = str.charAt(chIndx);
+
+ if (ch == '=') {
+ chIndx++;
+ token = TT_EX_UNEQUAL;
+ }
+ }
+ break;
+ }
+ }
+
+ break;
+ case '>' :
+ token = TT_GREATER;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_GREATEREQUAL;
+ break;
+ }
+ if (str.charAt(chIndx) == '>') {
+ chIndx++;
+ token = TT_RSHIFT;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_RSHIFTASSIGN;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ break;
+ case '<' :
+ token = TT_LESS;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_LESSEQUAL;
+
+ break;
+ }
+ if (str.charAt(chIndx) == '<') {
+ chIndx++;
+ token = TT_LSHIFT;
+ if (str.charAt(chIndx) == '<') {
+ // heredoc
+ int startRow = rowCount;
+ if (str.length() > chIndx) {
+
+ ch = str.charAt(++chIndx);
+ if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_')) {
+ chIndx++;
+ getIdentifier();
+ token = TT_STRING_CONSTANT;
+ while (str.length() > chIndx) {
+ ch = str.charAt(chIndx++);
+ if (ch == '\n') {
+ if (str.length() >= chIndx + identifier.length()) {
+ if (str.substring(chIndx, chIndx + identifier.length()).equals(identifier)) {
+ chIndx += identifier.length();
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ throwSyntaxError("Open heredoc syntax after operator '<<<'.", startRow);
+ } else if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_LSHIFTASSIGN;
+ break;
+ }
+ break;
+ }
+ }
+
+ break;
+
+ case '|' :
+ token = TT_LINE;
+
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '|') {
+ chIndx++;
+ token = TT_OR;
+
+ break;
+ }
+ }
+
+ break;
+ case '&' :
+ token = TT_AMPERSAND;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == '&') {
+ chIndx++;
+ token = TT_AND;
+ break;
+ }
+ if (str.charAt(chIndx) == '=') {
+ chIndx++;
+ token = TT_ANDASSIGN;
+ break;
+ }
+ break;
+ }
+
+ break;
+ case ':' :
+ token = TT_DDOT;
+ if (str.length() > chIndx) {
+ if (str.charAt(chIndx) == ':') {
+ chIndx++;
+ token = TT_DDOT2;
+ }
+ }
+ break;
+ case '#' :
+ token = TT_HASH;
+
+ break;
+ // case '@' :
+ // token = TT_AT;
+ //
+ // break;
+ default :
+ throwSyntaxError("unexpected character: '" + ch + "'");
+ }
+
+ if (token == TT_UNDEFINED) {
+ throwSyntaxError("token not found");
+ }
+
+ return;
+ }
+ }
+ }
+ } catch (StringIndexOutOfBoundsException e) {
+ // catched from charAt
+ }
+
+ chIndx = str.length() + 1;
+ ch = ' ';
+ token = TT_EOF;
+ phpEnd = true;
+ //PHPString temp;
+ // if (phpList != null) {
+ // if (currentPHPString < phpList.size()) {
+ // token = TT_UNDEFINED;
+ // temp = (PHPString) phpList.get(currentPHPString++);
+ // this.str = temp.getPHPString();
+ // this.token = TT_EOF;
+ // this.chIndx = 0;
+ // this.rowCount = temp.getLineNumber();
+ // this.columnCount = 0;
+ // getNextToken();
+ // phpEnd = true;
+ // } else {
+ // token = TT_UNDEFINED;
+ // return;
+ // }
+ // }
+ }
+
+ private void getIdentifier() {
+ StringBuffer ident = new StringBuffer();
+
+ ident.append(ch);
+ if (ch == '$') {
+ token = TT_VARIABLE;
+ } else {
+ token = TT_IDENTIFIER;
+ }
+ getChar();
+ while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
+ ident.append(ch);
+ getChar();
+ }
+ identifier = ident.toString();
+ chIndx--;
+
+ Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
+ if (i != null) {
+ token = i.intValue();
+ }
+ }
+
+ private void getNumber() {
+ StringBuffer inum = new StringBuffer();
+ char dFlag = ' ';
+ int numFormat = 10;
+
+ // save first digit
+ char firstCh = ch;
+ inum.append(ch);
+
+ getChar();
+ // determine number conversions:
+ if (firstCh == '0') {
+ switch (ch) {
+ case 'b' :
+ numFormat = 2;
+ getChar();
+ break;
+ case 'B' :
+ numFormat = 2;
+ getChar();
+ break;
+ case 'o' :
+ numFormat = 8;
+ getChar();
+ break;
+ case 'O' :
+ numFormat = 8;
+ getChar();
+ break;
+ case 'x' :
+ numFormat = 16;
+ getChar();
+ break;
+ case 'X' :
+ numFormat = 16;
+ getChar();
+ break;
+ }
+ }
+
+ if (numFormat == 16) {
+ while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
+ inum.append(ch);
+ getChar();
+ }
+ } else {
+ while ((ch >= '0' && ch <= '9') || (ch == '.') || (ch == 'E') || (ch == 'e')) {
+ if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
+ if (ch == '.' && dFlag != ' ') {
+ break;
+ }
+ if ((dFlag == 'E') || (dFlag == 'e')) {
+ break;
+ }
+ dFlag = ch;
+ inum.append(ch);
+ getChar();
+ if ((ch == '-') || (ch == '+')) {
+ inum.append(ch);
+ getChar();
+ }
+ } else {
+ inum.append(ch);
+ getChar();
+ }
+ }
+ }
+ chIndx--;
+
+ try {
+ if (dFlag != ' ') {
+ doubleNumber = new Double(inum.toString());
+ token = TT_DOUBLE_NUMBER;
+ return;
+ } else {
+ longNumber = Long.valueOf(inum.toString(), numFormat);
+ token = TT_INT_NUMBER;
+ return;
+ }
+
+ } catch (Throwable e) {
+ throwSyntaxError("Number format error: " + inum.toString());
+ }
+ }
+
+ public void htmlParserTester(String input) {
+ int lineNumber = 1;
+ int startLineNumber = 1;
+ int startIndex = 0;
+ char ch;
+ char ch2;
+ boolean phpMode = false;
+ boolean phpFound = false;
+
+ phpList = new ArrayList();
+ currentPHPString = 0;
+
+ try {
+ int i = 0;
+ while (i < input.length()) {
+ ch = input.charAt(i++);
+ if (ch == '\n') {
+ lineNumber++;
+ }
+ if ((!phpMode) && ch == '<') {
+ ch2 = input.charAt(i++);
+ if (ch2 == '?') {
+ ch2 = input.charAt(i++);
+ if (Character.isWhitespace(ch2)) {
+ // php start
+ phpMode = true;
+ phpFound = true;
+ startIndex = i;
+ startLineNumber = lineNumber;
+ continue;
+ } else if (ch2 == 'p') {
+ ch2 = input.charAt(i++);
+ if (ch2 == 'h') {
+ ch2 = input.charAt(i++);
+ if (ch2 == 'p') {
+ phpMode = true;
+ phpFound = true;
+ startIndex = i;
+ startLineNumber = lineNumber;
+ continue;
+ }
+ i--;
+ }
+ i--;
+ } else if (ch2 == 'P') {
+ ch2 = input.charAt(i++);
+ if (ch2 == 'H') {
+ ch2 = input.charAt(i++);
+ if (ch2 == 'P') {
+ phpMode = true;
+ phpFound = true;
+ startIndex = i;
+ startLineNumber = lineNumber;
+ continue;
+ }
+ i--;
+ }
+ i--;
+ }
+ i--;
+ }
+ i--;
+ }
+
+ if (phpMode) {
+ if (ch == '/' && i < input.length()) {
+ ch2 = input.charAt(i++);
+ if (ch2 == '/') {
+ while (i < input.length()) {
+ ch = input.charAt(i++);
+ if (ch == '?' && i < input.length()) {
+ ch2 = input.charAt(i++);
+ if (ch2 == '>') {
+ // php end
+ phpMode = false;
+ phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
+ continue;
+ }
+ i--;
+ } else if (ch == '\n') {
+ lineNumber++;
+ break;
+ }
+ }
+ continue;
+ } else if (ch2 == '*') {
+ // multi-line comment
+ while (i < input.length()) {
+ ch = input.charAt(i++);
+ if (ch == '\n') {
+ lineNumber++;
+ } else if (ch == '*' && i < input.length()) {
+ ch2 = input.charAt(i++);
+ if (ch2 == '/') {
+ break;
+ }
+ i--;
+ }
+ }
+ continue;
+ } else {
+ i--;
+ }
+ } else if (ch == '#') {
+ while (i < input.length()) {
+ ch = input.charAt(i++);
+ if (ch == '?' && i < input.length()) {
+ ch2 = input.charAt(i++);
+ if (ch2 == '>') {
+ // php end
+ phpMode = false;
+ phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
+ continue;
+ }
+ i--;
+ } else if (ch == '\n') {
+ lineNumber++;
+ break;
+ }
+ }
+ continue;
+ } else if (ch == '"') {
+ ch = ' ';
+ while (i < input.length()) {
+ ch = input.charAt(i++);
+ if (ch == '\n') {
+ lineNumber++;
+ } else if (ch == '\\' && i < input.length()) { // escape
+ i++;
+ } else if (ch == '"') {
+ break;
+ }
+ }
+ continue;
+ } else if (ch == '\'') {
+ ch = ' ';
+ while (i < input.length()) {
+ ch = input.charAt(i++);
+ if (ch == '\n') {
+ lineNumber++;
+ } else if (ch == '\\' && i < input.length()) { // escape
+ i++;
+ } else if (ch == '\'') {
+ break;
+ }
+ }
+ continue;
+ }
+
+ if (ch == '?' && i < input.length()) {
+ ch2 = input.charAt(i++);
+ if (ch2 == '>') {
+ // php end
+ phpMode = false;
+ phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
+ continue;
+ }
+ i--;
+ }
+ }
+ }
+
+ if (!phpFound) {
+ setMarker("No PHP source code found.", lineNumber, PHPParser.INFO);
+ } else {
+ if (phpMode) {
+ setMarker("Open PHP tag at end of file.", lineNumber, PHPParser.INFO);
+ phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
+ }
+ // for (int j=0;j<phpList.size();j++) {
+ // String temp = ((PHPString)phpList.get(j)).getPHPString();
+ // int startIndx = temp.length()-10;
+ // if (startIndx<0) {
+ // startIndx = 0;
+ // }
+ // System.out.println(temp.substring(startIndx)+"?>");
+ // }
+ phpParserTester(null, 1);
+ // PHPString temp;
+ // for(int j=0;j<phpList.size();j++) {
+ // temp = (PHPString) phpList.get(j);
+ // parser.start(temp.getPHPString(), temp.getLineNumber());
+ // }
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ public void phpParserTester(String s, int rowCount) throws CoreException {
+ this.str = s;
+ if (s == null) {
+ if (phpList.size() != 0) {
+ this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
+ }
+ }
+ this.token = TT_EOF;
+ this.chIndx = 0;
+ this.rowCount = rowCount;
+ this.columnCount = 0;
+ this.phpEnd = false;
+ this.phpMode = true;
+ getNextToken();
+ do {
+ try {
+ if (token != TT_EOF && token != TT_UNDEFINED) {
+ statementList();
+ }
+ if (token != TT_EOF && token != TT_UNDEFINED) {
+ if (token == TT_ARGCLOSE) {
+ throwSyntaxError("Too many closing ')'; end-of-file not reached.");
+ }
+ if (token == TT_LISTCLOSE) {
+ throwSyntaxError("Too many closing '}'; end-of-file not reached.");
+ }
+ if (token == TT_PARTCLOSE) {
+ throwSyntaxError("Too many closing ']'; end-of-file not reached.");
+ }
+
+ if (token == TT_ARGOPEN) {
+ throwSyntaxError("Read character '('; end-of-file not reached.");
+ }
+ if (token == TT_LISTOPEN) {
+ throwSyntaxError("Read character '{'; end-of-file not reached.");
+ }
+ if (token == TT_PARTOPEN) {
+ throwSyntaxError("Read character '['; end-of-file not reached.");
+ }
+
+ throwSyntaxError("End-of-file not reached.");
+ }
+ return;
+ } catch (SyntaxError err) {
+ if (s != null) {
+ throw err;
+ } else {
+ setMarker(err.getMessage(), err.getLine(), ERROR);
+ }
+ // if an error occured,
+ // try to find keywords 'class' or 'function'
+ // to parse the rest of the string
+ while (token != TT_EOF && token != TT_UNDEFINED) {
+ if (token == TT_class || token == TT_function) {
+ break;
+ }
+ getNextToken();
+ }
+ if (token == TT_EOF || token == TT_UNDEFINED) {
+ return;
+ }
+ }
+ }
+ while (true);
+ }
+
+ /**
+ * Parses a string with php tAGS
+ * i.e. '<body> <?php phpinfo() ?> </body>'
+ */
+ public void parse(String s) throws CoreException {
+ this.str = s;
+ this.token = TT_EOF;
+ this.chIndx = 0;
+ this.rowCount = 1;
+ this.columnCount = 0;
+ this.phpEnd = false;
+ this.phpMode = false;
+ getNextToken();
+ do {
+ try {
+ if (token != TT_EOF && token != TT_UNDEFINED) {
+ statementList();
+ }
+ if (token != TT_EOF && token != TT_UNDEFINED) {
+ if (token == TT_ARGCLOSE) {
+ throwSyntaxError("Too many closing ')'; end-of-file not reached.");
+ }
+ if (token == TT_LISTCLOSE) {
+ throwSyntaxError("Too many closing '}'; end-of-file not reached.");
+ }
+ if (token == TT_PARTCLOSE) {
+ throwSyntaxError("Too many closing ']'; end-of-file not reached.");
+ }
+
+ if (token == TT_ARGOPEN) {
+ throwSyntaxError("Read character '('; end-of-file not reached.");
+ }
+ if (token == TT_LISTOPEN) {
+ throwSyntaxError("Read character '{'; end-of-file not reached.");
+ }
+ if (token == TT_PARTOPEN) {
+ throwSyntaxError("Read character '['; end-of-file not reached.");
+ }
+
+ throwSyntaxError("End-of-file not reached.");
+ }
+ return;
+ } catch (SyntaxError sytaxErr1) {
+ setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
+ try {
+ // if an error occured,
+ // try to find keywords 'class' or 'function'
+ // to parse the rest of the string
+ while (token != TT_EOF && token != TT_UNDEFINED) {
+ if (token == TT_class || token == TT_function) {
+ break;
+ }
+ getNextToken();
+ }
+ if (token == TT_EOF || token == TT_UNDEFINED) {
+ return;
+ }
+ } catch (SyntaxError sytaxErr2) {
+ setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
+ return;
+ }
+ }
+ }
+ while (true);
+ }
+
+ private void statementList() throws CoreException {
+ do {
+ statement();
+ if ((token == TT_LISTCLOSE)
+ || (token == TT_case)
+ || (token == TT_default)
+ || (token == TT_elseif)
+ || (token == TT_endif)
+ || (token == TT_endfor)
+ || (token == TT_endforeach)
+ || (token == TT_endwhile)
+ || (token == TT_endswitch)
+ || (token == TT_EOF)
+ || (token == TT_UNDEFINED)) {
+ return;
+ }
+ } while (true);
+ }
+
+ private void compoundStatement() throws CoreException {
+ // '{' [statement-list] '}'
+ if (token == TT_LISTOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'{' expected in compound-statement.");
+ }
+ if (token != TT_LISTCLOSE) {
+ statementList();
+ }
+ if (token == TT_LISTCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'}' expected in compound-statement.");
+ }
+ }
+
+ private void statement() throws CoreException {
+ // if (token > TT_KEYWORD && token != TT_list && token != TT_new) {
+ String keyword = identifier;
+ if (token == TT_include || token == TT_include_once) {
+ getNextToken();
+ expression();
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ if (!phpEnd) {
+ throwSyntaxError("';' character after 'include' or 'include_once' expected.");
+ }
+ getNextToken();
+ }
+ return;
+ } else if (token == TT_require || token == TT_require_once) {
+ getNextToken();
+ //constant();
+ expression();
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ if (!phpEnd) {
+ throwSyntaxError("';' character after 'require' or 'require_once' expected.");
+ }
+ getNextToken();
+ }
+ return;
+ } else if (token == TT_if) {
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected after 'if' keyword.");
+ }
+ expression();
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("')' expected after 'if' condition.");
+ }
+ ifStatement();
+ return;
+
+ } else if (token == TT_switch) {
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected after 'switch' keyword.");
+ }
+ expression();
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("')' expected after 'switch' condition.");
+ }
+ switchStatement();
+ return;
+ } else if (token == TT_for) {
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected after 'for' keyword.");
+ }
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ expressionList();
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ throwSyntaxError("';' expected after 'for'.");
+ }
+ }
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ expressionList();
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ throwSyntaxError("';' expected after 'for'.");
+ }
+ }
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ expressionList();
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("')' expected after 'for'.");
+ }
+ }
+ forStatement();
+ return;
+ } else if (token == TT_while) {
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected after 'while' keyword.");
+ }
+ expression();
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("')' expected after 'while' condition.");
+ }
+ whileStatement();
+ return;
+ } else if (token == TT_do) {
+ getNextToken();
+ if (token == TT_LISTOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'{' expected after 'do' keyword.");
+ }
+ if (token != TT_LISTCLOSE) {
+ statementList();
+ }
+ if (token == TT_LISTCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'}' expected after 'do' keyword.");
+ }
+ if (token == TT_while) {
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected after 'while' keyword.");
+ }
+ expression();
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("')' expected after 'while' condition.");
+ }
+ } else {
+ throwSyntaxError("'while' expected after 'do' keyword.");
+ }
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ if (!phpEnd) {
+ throwSyntaxError("';' expected after do-while statement.");
+ }
+ getNextToken();
+ }
+ return;
+ } else if (token == TT_foreach) {
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected after 'foreach' keyword.");
+ }
+ expression();
+ if (token == TT_as) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'as' expected after 'foreach' exxpression.");
+ }
+ variable();
+ if (token == TT_FOREACH) {
+ getNextToken();
+ variable();
+ }
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("')' expected after 'foreach' expression.");
+ }
+ foreachStatement();
+ return;
+
+ } else if (token == TT_continue || token == TT_break || token == TT_return) {
+ getNextToken();
+ if (token != TT_SEMICOLON) {
+ expression();
+ }
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ if (!phpEnd) {
+ throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
+ }
+ getNextToken();
+ }
+ return;
+
+ } else if (token == TT_echo) {
+ getNextToken();
+ expressionList();
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ if (!phpEnd) {
+ throwSyntaxError("';' expected after 'echo' statement.");
+ }
+ getNextToken();
+ }
+ return;
+ // } else if (token == TT_print) {
+ // getNextToken();
+ // expression();
+ // if (token == TT_SEMICOLON) {
+ // getNextToken();
+ // } else {
+ // if (!phpEnd) {
+ // throwSyntaxError("';' expected after 'print' statement.");
+ // }
+ // getNextToken();
+ // }
+ // return;
+
+ } else if (token == TT_global || token == TT_static) {
+ getNextToken();
+ variableList();
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ if (!phpEnd) {
+ throwSyntaxError("';' expected after 'global' or 'static' statement.");
+ }
+ getNextToken();
+ }
+ return;
+
+ // } else if (token == TT_unset) {
+ // getNextToken();
+ // if (token == TT_ARGOPEN) {
+ // getNextToken();
+ // } else {
+ // throwSyntaxError("'(' expected after 'unset' keyword.");
+ // }
+ // variableList();
+ // if (token == TT_ARGCLOSE) {
+ // getNextToken();
+ // } else {
+ // throwSyntaxError("')' expected after 'unset' statement.");
+ // }
+ // if (token == TT_SEMICOLON) {
+ // getNextToken();
+ // } else {
+ // if (!phpEnd) {
+ // throwSyntaxError("';' expected after 'unset' statement.");
+ // }
+ // getNextToken();
+ // }
+ // return;
+
+ // } else if (token == TT_exit || token == TT_die) {
+ // getNextToken();
+ // if (token != TT_SEMICOLON) {
+ // exitStatus();
+ // }
+ // if (token == TT_SEMICOLON) {
+ // getNextToken();
+ // } else {
+ // if (!phpEnd) {
+ // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
+ // }
+ // getNextToken();
+ // }
+ // return;
+
+ } else if (token == TT_define) {
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected after 'define' keyword.");
+ }
+ expression();
+ if (token == TT_COMMA) {
+ getNextToken();
+ } else {
+ throwSyntaxError("',' expected after first 'define' constant.");
+ }
+ expression();
+ if (token == TT_COMMA) {
+ getNextToken();
+ expression();
+ }
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("')' expected after 'define' statement.");
+ }
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ if (!phpEnd) {
+ throwSyntaxError("';' expected after 'define' statement.");
+ }
+ getNextToken();
+ }
+ return;
+ } else if (token == TT_function) {
+ getNextToken();
+ functionDefinition();
+ return;
+ } else if (token == TT_class) {
+ getNextToken();
+ classDeclarator();
+ classBody();
+ return;
+ // } else {
+ // throwSyntaxError("Unexpected keyword '" + keyword + "'");
+ } else if (token == TT_LISTOPEN) {
+ // compoundStatement
+ getNextToken();
+ if (token != TT_LISTCLOSE) {
+ statementList();
+ }
+ if (token == TT_LISTCLOSE) {
+ getNextToken();
+ return;
+ } else {
+ throwSyntaxError("'}' expected.");
+ }
+ } else {
+ if (token != TT_SEMICOLON) {
+ expression();
+ }
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ return;
+ } else {
+ if (!phpEnd) {
+ throwSyntaxError("';' expected after expression.");
+ }
+ getNextToken();
+ }
+ }
+ }
+
+ private void classDeclarator() throws CoreException {
+ //identifier
+ //identifier 'extends' identifier
+ if (token == TT_IDENTIFIER) {
+ getNextToken();
+ if (token == TT_extends) {
+ getNextToken();
+ if (token == TT_IDENTIFIER) {
+ getNextToken();
+ } else {
+ throwSyntaxError("Class name expected after keyword 'extends'.");
+ }
+ }
+ } else {
+ throwSyntaxError("Class name expected after keyword 'class'.");
+ }
+ }
+
+ private void classBody() throws CoreException {
+ //'{' [class-element-list] '}'
+ if (token == TT_LISTOPEN) {
+ getNextToken();
+ if (token != TT_LISTCLOSE) {
+ classElementList();
+ }
+ if (token == TT_LISTCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'}' expected at end of class body.");
+ }
+ } else {
+ throwSyntaxError("'{' expected at start of class body.");
+ }
+ }
+
+ private void classElementList() throws CoreException {
+ do {
+ classElement();
+ } while (token == TT_function || token == TT_var);
+ }
+
+ private void classElement() throws CoreException {
+ //class-property
+ //function-definition
+ if (token == TT_function) {
+ getNextToken();
+ functionDefinition();
+ } else if (token == TT_var) {
+ getNextToken();
+ classProperty();
+ } else {
+ throwSyntaxError("'function' or 'var' expected.");
+ }
+ }
+
+ private void classProperty() throws CoreException {
+ //'var' variable ';'
+ //'var' variable '=' constant ';'
+ do {
+ if (token == TT_VARIABLE) {
+ getNextToken();
+ if (token == TT_ASSIGN) {
+ getNextToken();
+ constant();
+ }
+ } else {
+ throwSyntaxError("Variable expected after keyword 'var'.");
+ }
+ if (token != TT_COMMA) {
+ break;
+ }
+ getNextToken();
+ } while (true);
+ if (token == TT_SEMICOLON) {
+ getNextToken();
+ } else {
+ throwSyntaxError("';' expected after variable declaration.");
+ }
+ }
+
+ private void functionDefinition() throws CoreException {
+ functionDeclarator();
+ compoundStatement();
+ }
+
+ private void functionDeclarator() throws CoreException {
+ //identifier '(' [parameter-list] ')'
+ if (token == TT_AMPERSAND) {
+ getNextToken();
+ }
+ if (token == TT_IDENTIFIER) {
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected in function declaration.");
+ }
+ if (token != TT_ARGCLOSE) {
+ parameterList();
+ }
+ if (token != TT_ARGCLOSE) {
+ throwSyntaxError("')' expected in function declaration.");
+ } else {
+ getNextToken();
+ }
+ }
+ }
+ //
+ private void parameterList() throws CoreException {
+ //parameter-declaration
+ //parameter-list ',' parameter-declaration
+ do {
+ parameterDeclaration();
+ if (token != TT_COMMA) {
+ break;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void parameterDeclaration() throws CoreException {
+ //variable
+ //variable-reference
+ if (token == TT_AMPERSAND) {
+ getNextToken();
+ if (token == TT_VARIABLE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("Variable expected after reference operator '&'.");
+ }
+ }
+ //variable '=' constant
+ if (token == TT_VARIABLE) {
+ getNextToken();
+ if (token == TT_ASSIGN) {
+ getNextToken();
+ constant();
+ }
+ return;
+ }
+ }
+
+ private void labeledStatementList() throws CoreException {
+ if (token != TT_case && token != TT_default) {
+ throwSyntaxError("'case' or 'default' expected.");
+ }
+ do {
+ if (token == TT_case) {
+ getNextToken();
+ constant();
+ if (token == TT_DDOT) {
+ getNextToken();
+ if (token == TT_case || token == TT_default) { // empty case statement ?
+ continue;
+ }
+ statementList();
+ } else if (token == TT_SEMICOLON) {
+ setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO);
+ getNextToken();
+ if (token == TT_case) { // empty case statement ?
+ continue;
+ }
+ statementList();
+ } else {
+ throwSyntaxError("':' character after 'case' constant expected.");
+ }
+ } else { // TT_default
+ getNextToken();
+ if (token == TT_DDOT) {
+ getNextToken();
+ statementList();
+ } else {
+ throwSyntaxError("':' character after 'default' expected.");
+ }
+ }
+ } while (token == TT_case || token == TT_default);
+ }
+
+ // public void labeledStatement() {
+ // if (token == TT_case) {
+ // getNextToken();
+ // constant();
+ // if (token == TT_DDOT) {
+ // getNextToken();
+ // statement();
+ // } else {
+ // throwSyntaxError("':' character after 'case' constant expected.");
+ // }
+ // return;
+ // } else if (token == TT_default) {
+ // getNextToken();
+ // if (token == TT_DDOT) {
+ // getNextToken();
+ // statement();
+ // } else {
+ // throwSyntaxError("':' character after 'default' expected.");
+ // }
+ // return;
+ // }
+ // }
+
+ // public void expressionStatement() {
+ // }
+
+ // private void inclusionStatement() {
+ // }
+
+ // public void compoundStatement() {
+ // }
+
+ // public void selectionStatement() {
+ // }
+ //
+ // public void iterationStatement() {
+ // }
+ //
+ // public void jumpStatement() {
+ // }
+ //
+ // public void outputStatement() {
+ // }
+ //
+ // public void scopeStatement() {
+ // }
+ //
+ // public void flowStatement() {
+ // }
+ //
+ // public void definitionStatement() {
+ // }
+
+ private void ifStatement() throws CoreException {
+ // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
+ if (token == TT_DDOT) {
+ getNextToken();
+ statementList();
+ switch (token) {
+ case TT_else :
+ getNextToken();
+ if (token == TT_DDOT) {
+ getNextToken();
+ statementList();
+ } else {
+ if (token == TT_if) { //'else if'
+ getNextToken();
+ elseifStatementList();
+ } else {
+ throwSyntaxError("':' expected after 'else'.");
+ }
+ }
+ break;
+ case TT_elseif :
+ getNextToken();
+ elseifStatementList();
+ break;
+ }
+
+ if (token != TT_endif) {
+ throwSyntaxError("'endif' expected.");
+ }
+ getNextToken();
+ if (token != TT_SEMICOLON) {
+ throwSyntaxError("';' expected after if-statement.");
+ }
+ getNextToken();
+ } else {
+ // statement [else-statement]
+ statement();
+ if (token == TT_elseif) {
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected after 'elseif' keyword.");
+ }
+ expression();
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("')' expected after 'elseif' condition.");
+ }
+ ifStatement();
+ } else if (token == TT_else) {
+ getNextToken();
+ statement();
+ }
+ }
+ }
+
+ private void elseifStatementList() throws CoreException {
+ do {
+ elseifStatement();
+ switch (token) {
+ case TT_else :
+ getNextToken();
+ if (token == TT_DDOT) {
+ getNextToken();
+ statementList();
+ return;
+ } else {
+ if (token == TT_if) { //'else if'
+ getNextToken();
+ } else {
+ throwSyntaxError("':' expected after 'else'.");
+ }
+ }
+ break;
+ case TT_elseif :
+ getNextToken();
+ break;
+ default :
+ return;
+ }
+ } while (true);
+ }
+
+ private void elseifStatement() throws CoreException {
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ expression();
+ if (token != TT_ARGOPEN) {
+ throwSyntaxError("')' expected in else-if-statement.");
+ }
+ getNextToken();
+ if (token != TT_DDOT) {
+ throwSyntaxError("':' expected in else-if-statement.");
+ }
+ getNextToken();
+ statementList();
+ }
+ }
+
+ private void switchStatement() throws CoreException {
+ if (token == TT_DDOT) {
+ // ':' [labeled-statement-list] 'endswitch' ';'
+ getNextToken();
+ labeledStatementList();
+ if (token != TT_endswitch) {
+ throwSyntaxError("'endswitch' expected.");
+ }
+ getNextToken();
+ if (token != TT_SEMICOLON) {
+ throwSyntaxError("';' expected after switch-statement.");
+ }
+ getNextToken();
+ } else {
+ // '{' [labeled-statement-list] '}'
+ if (token != TT_LISTOPEN) {
+ throwSyntaxError("'{' expected in switch statement.");
+ }
+ getNextToken();
+ if (token != TT_LISTCLOSE) {
+ labeledStatementList();
+ }
+ if (token != TT_LISTCLOSE) {
+ throwSyntaxError("'}' expected in switch statement.");
+ }
+ getNextToken();
+
+ }
+ }
+
+ private void forStatement() throws CoreException {
+ if (token == TT_DDOT) {
+ getNextToken();
+ statementList();
+ if (token != TT_endfor) {
+ throwSyntaxError("'endfor' expected.");
+ }
+ getNextToken();
+ if (token != TT_SEMICOLON) {
+ throwSyntaxError("';' expected after for-statement.");
+ }
+ getNextToken();
+ } else {
+ statement();
+ }
+ }
+
+ private void whileStatement() throws CoreException {
+ // ':' statement-list 'endwhile' ';'
+ if (token == TT_DDOT) {
+ getNextToken();
+ statementList();
+ if (token != TT_endwhile) {
+ throwSyntaxError("'endwhile' expected.");
+ }
+ getNextToken();
+ if (token != TT_SEMICOLON) {
+ throwSyntaxError("';' expected after while-statement.");
+ }
+ getNextToken();
+ } else {
+ statement();
+ }
+ }
+
+ private void foreachStatement() throws CoreException {
+ if (token == TT_DDOT) {
+ getNextToken();
+ statementList();
+ if (token != TT_endforeach) {
+ throwSyntaxError("'endforeach' expected.");
+ }
+ getNextToken();
+ if (token != TT_SEMICOLON) {
+ throwSyntaxError("';' expected after foreach-statement.");
+ }
+ getNextToken();
+ } else {
+ statement();
+ }
+ }
+
+ private void exitStatus() throws CoreException {
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ } else {
+ throwSyntaxError("'(' expected in 'exit-status'.");
+ }
+ if (token != TT_ARGCLOSE) {
+ expression();
+ }
+ if (token == TT_ARGCLOSE) {
+ getNextToken();
+ } else {
+ throwSyntaxError("')' expected after 'exit-status'.");
+ }
+ }
+
+ private void expressionList() throws CoreException {
+ do {
+ expression();
+ if (token == TT_COMMA) {
+ getNextToken();
+ } else {
+ break;
+ }
+ } while (true);
+ }
+
+ private void expression() throws CoreException {
+ // if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) {
+ // getNextToken();
+ // } else {
+ logicalinclusiveorExpression();
+ // while (token != TT_SEMICOLON) {
+ // getNextToken();
+ // // }
+ // }
+ }
+
+ private void postfixExpression() throws CoreException {
+ String ident;
+ boolean castFlag = false;
+ switch (token) {
+ case TT_new :
+ getNextToken();
+ expression();
+ break;
+ case TT_null :
+ getNextToken();
+ break;
+ case TT_false :
+ getNextToken();
+ break;
+ case TT_true :
+ getNextToken();
+ break;
+ case TT_STRING_CONSTANT :
+ getNextToken();
+ break;
+ case TT_INTERPOLATED_STRING :
+ getNextToken();
+ break;
+ case TT_ARGOPEN :
+ getNextToken();
+ if (token == TT_IDENTIFIER) {
+ // check if identifier is a type:
+ ident = identifier;
+ String str = identifier.toLowerCase();
+ for (int i = 0; i < PHP_TYPES.length; i++) {
+ if (PHP_TYPES[i].equals(str)) {
+ castFlag = true;
+ break;
+ }
+ }
+ if (castFlag) {
+ getNextToken();
+ if (token != TT_ARGCLOSE) {
+ throwSyntaxError(") expected after cast-type '" + ident + "'.");
+ }
+ getNextToken();
+ expression();
+ break;
+ }
+ }
+ if (!castFlag) {
+ expression();
+ }
+ if (token != TT_ARGCLOSE) {
+ throwSyntaxError(") expected in postfix-expression.");
+ }
+ getNextToken();
+ break;
+ case TT_DOUBLE_NUMBER :
+ getNextToken();
+ break;
+ case TT_INT_NUMBER :
+ getNextToken();
+ break;
+ case TT_DOLLAROPEN :
+ getNextToken();
+ expression();
+ if (token != TT_LISTCLOSE) {
+ throwSyntaxError("'}' expected after indirect variable token '${'.");
+ }
+ getNextToken();
+ break;
+ case TT_VARIABLE :
+ ident = identifier;
+ getNextToken();
+ if (token == TT_LISTOPEN) {
+ getNextToken();
+ expression();
+ if (token != TT_LISTCLOSE) {
+ throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression.");
+ }
+ getNextToken();
+ } else if (token == TT_ARGOPEN) {
+ getNextToken();
+ if (token != TT_ARGCLOSE) {
+ expressionList();
+ if (token != TT_ARGCLOSE) {
+ throwSyntaxError("')' expected after variable '" + ident + "' in postfix-expression.");
+ }
+ }
+ getNextToken();
+ }
+ break;
+ case TT_IDENTIFIER :
+ ident = identifier;
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ if (token != TT_ARGCLOSE) {
+ expressionList();
+ if (token != TT_ARGCLOSE) {
+ throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
+ }
+ }
+ getNextToken();
+ }
+ break;
+ case TT_print :
+ getNextToken();
+ expression();
+ // if (token == TT_SEMICOLON) {
+ // getNextToken();
+ // } else {
+ // if (!phpEnd) {
+ // throwSyntaxError("';' expected after 'print' statement.");
+ // }
+ // getNextToken();
+ // }
+ break;
+ case TT_list :
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ if (token == TT_COMMA) {
+ getNextToken();
+ }
+ expressionList();
+ if (token != TT_ARGCLOSE) {
+ throwSyntaxError("')' expected after 'list' keyword.");
+ }
+ getNextToken();
+ // if (token == TT_SET) {
+ // getNextToken();
+ // logicalinclusiveorExpression();
+ // }
+ } else {
+ throwSyntaxError("'(' expected after 'list' keyword.");
+ }
+ break;
+ // case TT_exit :
+ // getNextToken();
+ // if (token != TT_SEMICOLON) {
+ // exitStatus();
+ // }
+ // if (token == TT_SEMICOLON) {
+ // getNextToken();
+ // } else {
+ // if (!phpEnd) {
+ // throwSyntaxError("';' expected after 'exit' expression.");
+ // }
+ // getNextToken();
+ // }
+ // break;
+ // case TT_die :
+ // getNextToken();
+ // if (token != TT_SEMICOLON) {
+ // exitStatus();
+ // }
+ // if (token == TT_SEMICOLON) {
+ // getNextToken();
+ // } else {
+ // if (!phpEnd) {
+ // throwSyntaxError("';' expected after 'die' expression.");
+ // }
+ // }
+ // break;
+
+ // case TT_array :
+ // getNextToken();
+ // if (token == TT_ARGOPEN) {
+ // getNextToken();
+ // if (token == TT_COMMA) {
+ // getNextToken();
+ // }
+ // expressionList();
+ // if (token != TT_ARGCLOSE) {
+ // throwSyntaxError("')' expected after 'list' keyword.");
+ // }
+ // getNextToken();
+ // if (token == TT_SET) {
+ // getNextToken();
+ // logicalinclusiveorExpression();
+ // }
+ // } else {
+ // throwSyntaxError("'(' expected after 'list' keyword.");
+ // }
+ // break;
+ }
+ boolean while_flag = true;
+ do {
+ switch (token) {
+ case TT_PARTOPEN :
+ getNextToken();
+ expression();
+ if (token != TT_PARTCLOSE) {
+ throwSyntaxError("] expected in postfix-expression.");
+ }
+ getNextToken();
+ break;
+ case TT_DDOT2 : // ::
+ case TT_REF : // ->
+ getNextToken();
+ if (token > TT_KEYWORD) {
+ ident = identifier;
+ setMarker("Avoid using keyword '" + ident + "' as variable name.", rowCount, PHPParser.INFO);
+ }
+ switch (token) {
+ case TT_VARIABLE :
+ ident = identifier;
+ getNextToken();
+ // if (token == TT_ARGOPEN) {
+ // getNextToken();
+ // expressionList();
+ // if (token != TT_ARGCLOSE) {
+ // throwSyntaxError(") expected after variable '" + ident + "'.");
+ // }
+ // getNextToken();
+ // }
+ break;
+ case TT_IDENTIFIER :
+ ident = identifier;
+ getNextToken();
+ break;
+ case TT_LISTOPEN :
+ getNextToken();
+ expression();
+ if (token != TT_LISTCLOSE) {
+ throwSyntaxError("} expected in postfix-expression.");
+ }
+ getNextToken();
+ break;
+ default :
+ throwSyntaxError("Syntax error after '->' token.");
+ } while (token == TT_PARTOPEN || token == TT_ARGOPEN || token == TT_LISTOPEN) {
+ if (token == TT_PARTOPEN) {
+ getNextToken();
+ expressionList();
+ if (token != TT_PARTCLOSE) {
+ throwSyntaxError("] expected after '->'.");
+ }
+ getNextToken();
+ }
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ expressionList();
+ if (token != TT_ARGCLOSE) {
+ throwSyntaxError(") expected after '->'.");
+ }
+ getNextToken();
+ }
+ if (token == TT_LISTOPEN) {
+ getNextToken();
+ expression();
+ if (token != TT_LISTCLOSE) {
+ throwSyntaxError("} expected after '->'.");
+ }
+ getNextToken();
+ }
+ }
+ break;
+ case TT_INCREMENT :
+ getNextToken();
+ break;
+ case TT_DECREMENT :
+ getNextToken();
+ break;
+ default :
+ while_flag = false;
+ }
+
+ }
+ while (while_flag);
+ }
+
+ private void unaryExpression() throws CoreException {
+ switch (token) {
+ case TT_INCREMENT :
+ getNextToken();
+ unaryExpression();
+ break;
+ case TT_DECREMENT :
+ getNextToken();
+ unaryExpression();
+ break;
+ // '@' '&' '*' '+' '-' '~' '!'
+ case TT_AT :
+ getNextToken();
+ castExpression();
+ break;
+ case TT_AMPERSAND :
+ getNextToken();
+ castExpression();
+ break;
+ case TT_MULTIPLY :
+ getNextToken();
+ castExpression();
+ break;
+ case TT_ADD :
+ getNextToken();
+ castExpression();
+ break;
+ case TT_SUBTRACT :
+ getNextToken();
+ castExpression();
+ break;
+ case TT_TILDE :
+ getNextToken();
+ castExpression();
+ break;
+ case TT_NOT :
+ getNextToken();
+ castExpression();
+ break;
+ default :
+ postfixExpression();
+ }
+ }
+
+ private void castExpression() throws CoreException {
+ // if (token == TT_ARGOPEN) {
+ // getNextToken();
+ // typeName();
+ // if (token != TT_ARGCLOSE) {
+ // throwSyntaxError(") expected after cast-expression.");
+ // }
+ // getNextToken();
+ // }
+ unaryExpression();
+ }
+
+ private void typeName() throws CoreException {
+ //'string' 'unset' 'array' 'object'
+ //'bool' 'boolean'
+ //'real' 'double' 'float'
+ //'int' 'integer'
+ String ident = "";
+ if (token == TT_IDENTIFIER) {
+ ident = identifier;
+ String str = identifier.toLowerCase();
+ getNextToken();
+ for (int i = 0; i < PHP_TYPES.length; i++) {
+ if (PHP_TYPES[i].equals(str)) {
+ return;
+ }
+ }
+ }
+ throwSyntaxError("Expected type cast '( <type-name> )'; Got '" + ident + "'.");
+ }
+
+ private void assignExpression() throws CoreException {
+ castExpression();
+ if (token == TT_ASSIGN) { // =
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_DOTASSIGN) { // .=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_FOREACH) { // =>
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_ADDTO) { // +=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_SUBTRACTFROM) { // -=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_TIMESBY) { // *=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_DIVIDEBY) { // *=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_MODASSIGN) { // %=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_ANDASSIGN) { // &=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_POWASSIGN) { // ^=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_LSHIFTASSIGN) { // <<=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_RSHIFTASSIGN) { // >>=
+ getNextToken();
+ logicalinclusiveorExpression();
+ } else if (token == TT_TILDEASSIGN) { // ~=
+ getNextToken();
+ logicalinclusiveorExpression();
+ }
+ }
+
+ private void multiplicativeExpression() throws CoreException {
+ do {
+ assignExpression();
+ if (token != TT_MULTIPLY && token != TT_DIV && token != TT_MOD) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void concatenationExpression() throws CoreException {
+ do {
+ multiplicativeExpression();
+ if (token != TT_DOT) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void additiveExpression() throws CoreException {
+ do {
+ concatenationExpression();
+ if (token != TT_ADD && token != TT_SUBTRACT) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void shiftExpression() throws CoreException {
+ do {
+ additiveExpression();
+ if (token != TT_LSHIFT && token != TT_RSHIFT) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void relationalExpression() throws CoreException {
+ do {
+ shiftExpression();
+ if (token != TT_LESS && token != TT_GREATER && token != TT_LESSEQUAL && token != TT_GREATEREQUAL) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void identicalExpression() throws CoreException {
+ do {
+ relationalExpression();
+ if (token != TT_EX_EQUAL && token != TT_EX_UNEQUAL) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void equalityExpression() throws CoreException {
+ do {
+ identicalExpression();
+ if (token != TT_EQUAL && token != TT_UNEQUAL) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void ternaryExpression() throws CoreException {
+ equalityExpression();
+ if (token == TT_QUESTIONMARK) {
+ getNextToken();
+ expression();
+ if (token == TT_DDOT) {
+ getNextToken();
+ expression();
+ } else {
+ throwSyntaxError("':' expected in ternary operator '? :'.");
+ }
+ }
+ }
+
+ private void andExpression() throws CoreException {
+ do {
+ ternaryExpression();
+ if (token != TT_AMPERSAND) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void exclusiveorExpression() throws CoreException {
+ do {
+ andExpression();
+ if (token != TT_POW) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void inclusiveorExpression() throws CoreException {
+ do {
+ exclusiveorExpression();
+ if (token != TT_LINE) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void booleanandExpression() throws CoreException {
+ do {
+ inclusiveorExpression();
+ if (token != TT_AND) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void booleanorExpression() throws CoreException {
+ do {
+ booleanandExpression();
+ if (token != TT_OR) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void logicalandExpression() throws CoreException {
+ do {
+ booleanorExpression();
+ if (token != TT_and) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void logicalexclusiveorExpression() throws CoreException {
+ do {
+ logicalandExpression();
+ if (token != TT_xor) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ private void logicalinclusiveorExpression() throws CoreException {
+ do {
+ logicalexclusiveorExpression();
+ if (token != TT_or) {
+ return;
+ }
+ getNextToken();
+ } while (true);
+ }
+
+ // public void assignmentExpression() {
+ // if (token == TT_VARIABLE) {
+ // getNextToken();
+ // if (token == TT_SET) {
+ // getNextToken();
+ // logicalinclusiveorExpression();
+ // }
+ // } else {
+ // logicalinclusiveorExpression();
+ // }
+ // }
+
+ private void variableList() throws CoreException {
+ do {
+ variable();
+ if (token == TT_COMMA) {
+ getNextToken();
+ } else {
+ break;
+ }
+ } while (true);
+ }
+
+ private void variable() throws CoreException {
+ if (token == TT_DOLLAROPEN) {
+ getNextToken();
+ expression();
+ ;
+ if (token != TT_LISTCLOSE) {
+ throwSyntaxError("'}' expected after indirect variable token '${'.");
+ }
+ getNextToken();
+ } else {
+ if (token == TT_VARIABLE) {
+ getNextToken();
+ if (token == TT_PARTOPEN) {
+ getNextToken();
+ expression();
+ if (token != TT_PARTCLOSE) {
+ throwSyntaxError("']' expected in variable-list.");
+ }
+ getNextToken();
+ } else if (token == TT_ASSIGN) {
+ getNextToken();
+ constant();
+ }
+ } else {
+ throwSyntaxError("$-variable expected in variable-list.");
+ }
+ }
+ }
+
+ private void constant() throws CoreException {
+ String ident;
+ switch (token) {
+ case TT_ADD :
+ getNextToken();
+ switch (token) {
+ case TT_DOUBLE_NUMBER :
+ getNextToken();
+ break;
+ case TT_INT_NUMBER :
+ getNextToken();
+ break;
+ default :
+ throwSyntaxError("Constant expected after '+' presign.");
+ }
+ break;
+ case TT_SUBTRACT :
+ getNextToken();
+ switch (token) {
+ case TT_DOUBLE_NUMBER :
+ getNextToken();
+ break;
+ case TT_INT_NUMBER :
+ getNextToken();
+ break;
+ default :
+ throwSyntaxError("Constant expected after '-' presign.");
+ }
+ break;
+ case TT_null :
+ getNextToken();
+ break;
+ case TT_false :
+ getNextToken();
+ break;
+ case TT_true :
+ getNextToken();
+ break;
+ case TT_IDENTIFIER :
+ ident = identifier;
+ getNextToken();
+ if (token == TT_ARGOPEN) {
+ getNextToken();
+ if (token != TT_ARGCLOSE) {
+ expressionList();
+ if (token != TT_ARGCLOSE) {
+ throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
+ }
+ }
+ getNextToken();
+ }
+ break;
+ case TT_STRING_CONSTANT :
+ getNextToken();
+ break;
+ case TT_INTERPOLATED_STRING :
+ getNextToken();
+ break;
+ case TT_DOUBLE_NUMBER :
+ getNextToken();
+ break;
+ case TT_INT_NUMBER :
+ getNextToken();
+ break;
+ default :
+ throwSyntaxError("Constant expected.");
+ }
+ }
+
+ /**
+ * Call the php parse command ( php -l -f <filename> )
+ * and create markers according to the external parser output
+ */
+ public static void phpExternalParse(IFile file) {
+ //IFile file = (IFile) resource;
+ IPath path = file.getFullPath();
+ IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
+ String filename = file.getLocation().toString();
+
+ String[] arguments = { filename };
+ MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
+ String command = form.format(arguments);
+
+ String parserResult = PHPStartApacheAction.execute(command, "External parser: ");
+
+ try {
+ // parse the buffer to find the errors and warnings
+ createMarkers(parserResult, file);
+ } catch (CoreException e) {
+ }
+ }
+
+ /**
+ * Create markers according to the external parser output
+ */
+ private static void createMarkers(String output, IFile file) throws CoreException {
+ // delete all markers
+ file.deleteMarkers(IMarker.PROBLEM, false, 0);
+
+ int indx = 0;
+ int brIndx = 0;
+ boolean flag = true;
+ while ((brIndx = output.indexOf("<br />", indx)) != -1) {
+ // newer php error output (tested with 4.2.3)
+ scanLine(output, file, indx, brIndx);
+ indx = brIndx + 6;
+ flag = false;
+ }
+ if (flag) {
+ while ((brIndx = output.indexOf("<br>", indx)) != -1) {
+ // older php error output (tested with 4.2.3)
+ scanLine(output, file, indx, brIndx);
+ indx = brIndx + 4;
+ }
+ }
+ }
+
+ private static void scanLine(String output, IFile file, int indx, int brIndx) throws CoreException {
+ String current;
+ String outLineNumberString;
+ StringBuffer lineNumberBuffer = new StringBuffer(10);
+ char ch;
+ current = output.substring(indx, brIndx);
+
+ if (current.indexOf(PARSE_WARNING_STRING) != -1 || current.indexOf(PARSE_ERROR_STRING) != -1) {
+ int onLine = current.indexOf("on line <b>");
+ if (onLine != -1) {
+ lineNumberBuffer.delete(0, lineNumberBuffer.length());
+ for (int i = onLine; i < current.length(); i++) {
+ ch = current.charAt(i);
+ if ('0' <= ch && '9' >= ch) {
+ lineNumberBuffer.append(ch);
+ }
+ }
+
+ int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
+
+ Hashtable attributes = new Hashtable();
+
+ current = current.replaceAll("\n", "");
+ current = current.replaceAll("<b>", "");
+ current = current.replaceAll("</b>", "");
+ MarkerUtilities.setMessage(attributes, current);
+
+ if (current.indexOf(PARSE_ERROR_STRING) != -1)
+ attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
+ else if (current.indexOf(PARSE_WARNING_STRING) != -1)
+ attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
+ else
+ attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
+ MarkerUtilities.setLineNumber(attributes, lineNumber);
+ MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
+ }
+ }
+ }
+}
\ No newline at end of file