/**********************************************************************
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 String stringValue;
/** Contains the current expression. */
private StringBuffer expression;
private boolean phpMode;
final static int TokenNameEOF = 0;
final static int TokenNameERROR = 1;
final static int TokenNameHTML = 2;
final static int TokenNameREMAINDER = 30;
final static int TokenNameNOT = 31;
final static int TokenNameDOT = 32;
final static int TokenNameXOR = 33;
final static int TokenNameDIVIDE = 34;
final static int TokenNameMULTIPLY = 35;
final static int TokenNameMINUS = 36;
final static int TokenNamePLUS = 37;
final static int TokenNameEQUAL_EQUAL = 38;
final static int TokenNameNOT_EQUAL = 39;
final static int TokenNameGREATER = 40;
final static int TokenNameGREATER_EQUAL = 41;
final static int TokenNameLESS = 42;
final static int TokenNameLESS_EQUAL = 43;
final static int TokenNameAND_AND = 44;
final static int TokenNameOR_OR = 45;
// final static int TokenNameHASH = 46;
final static int TokenNameCOLON = 47;
final static int TokenNameDOT_EQUAL = 48;
final static int TokenNameEQUAL = 49;
final static int TokenNameMINUS_GREATER = 50; // ->
final static int TokenNameFOREACH = 51;
final static int TokenNameAND = 52;
//final static int TokenNameDOLLARLISTOPEN = 53;
final static int TokenNameTWIDDLE = 54;
final static int TokenNameTWIDDLE_EQUAL = 55;
final static int TokenNameREMAINDER_EQUAL = 56;
final static int TokenNameXOR_EQUAL = 57;
final static int TokenNameRIGHT_SHIFT_EQUAL = 58;
final static int TokenNameLEFT_SHIFT_EQUAL = 59;
final static int TokenNameAND_EQUAL = 60;
final static int TokenNameQUESTION = 61;
final static int TokenNameCOLON_COLON = 62;
final static int TokenNameAT = 63;
// final static int TokenNameHEREDOC = 64;
final static int TokenNameDOLLAROPEN = 127;
final static int TokenNameLPAREN = 128;
final static int TokenNameRPAREN = 129;
final static int TokenNameLBRACE = 130;
final static int TokenNameRBRACE = 131;
final static int TokenNameLBRACKET = 132;
final static int TokenNameRBRACKET = 133;
final static int TokenNameCOMMA = 134;
final static int TokenNameStringLiteral = 136;
final static int TokenNameIdentifier = 138;
// final static int TokenNameDIGIT = 139;
final static int TokenNameSEMICOLON = 140;
// final static int TokenNameSLOT = 141;
// final static int TokenNameSLOTSEQUENCE = 142;
final static int TokenNameMINUS_MINUS = 144;
final static int TokenNamePLUS_PLUS = 145;
final static int TokenNamePLUS_EQUAL = 146;
final static int TokenNameDIVIDE_EQUAL = 147;
final static int TokenNameMINUS_EQUAL = 148;
final static int TokenNameMULTIPLY_EQUAL = 149;
final static int TokenNameVariable = 150;
final static int TokenNameIntegerLiteral = 151;
final static int TokenNameDoubleLiteral = 152;
final static int TokenNameStringInterpolated = 153;
final static int TokenNameStringConstant = 154;
final static int TokenNameLEFT_SHIFT = 155;
final static int TokenNameRIGHT_SHIFT = 156;
final static int TokenNameEQUAL_EQUAL_EQUAL = 157;
final static int TokenNameNOT_EQUAL_EQUAL = 158;
final static int TokenNameOR = 159;
// final static int TokenNameAT = 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 = TokenNameEOF;
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 {
if (file != null) {
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);
}
}
/**
* This method will throw the SyntaxError.
* It will add the good lines and columns to the Error
* @param error the error message
* @throws SyntaxError the error raised
*/
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);
}
/**
* This method will throw the SyntaxError.
* It will add the good lines and columns to the Error
* @param error the error message
* @throws SyntaxError the error raised
*/
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 = TokenNameEOF;
phpEnd = true;
}
// private void getNextToken_OldVersion() throws CoreException {
// phpEnd = false;
//
// while (str.length() > chIndx) {
// ch = str.charAt(chIndx++);
// token = TokenNameERROR;
// 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 = TokenNameDOLLAROPEN;
// 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 = TokenNameINTERPOLATED_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 = TokenNameStringConstant;
// 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 = TokenNameStringConstant;
// return;
// }
//
// switch (ch) {
//
// case '(' :
// token = TokenNameLPAREN;
//
// break;
// case ')' :
// token = TokenNameRPAREN;
//
// break;
// case '{' :
// token = TokenNameLBRACE;
//
// break;
// case '}' :
// token = TokenNameRBRACE;
//
// break;
// case '[' :
// token = TokenNameLBRACKET;
//
// break;
// case ']' :
// token = TokenNameRBRACKET;
//
// break;
// case ',' :
// token = TokenNameCOMMA;
//
// break;
// case '?' :
// token = TokenNameQUESTION;
// break;
// case '@' :
// token = TokenNameAT;
// break;
// case '~' :
// token = TokenNameTWIDDLE;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameTWIDDLE_EQUAL;
//
// break;
// }
// }
// break;
// case '.' :
// token = TokenNameDOT;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameDOT_EQUAL;
//
// break;
// }
// }
//
// break;
// case '"' :
// token = TokenNameStringLiteral;
//
// break;
// case '%' :
// token = TokenNameREMAINDER;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameREMAINDER_EQUAL;
//
// break;
// }
// }
// break;
// case ';' :
// token = TokenNameSEMICOLON;
//
// break;
// case '^' :
// token = TokenNameXOR;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameXOR_EQUAL;
//
// break;
// }
// }
// break;
// case '/' :
// token = TokenNameDIVIDE;
//
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameDIVIDE_EQUAL;
//
// break;
// }
// }
//
// break;
// case '*' :
// token = TokenNameMULTIPLY;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '*') {
// chIndx++;
// token = TokenNameXOR;
//
// break;
// }
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameMULTIPLY_EQUAL;
//
// break;
// }
// }
//
// break;
// case '+' :
// token = TokenNamePLUS;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '+') {
// chIndx++;
// token = TokenNamePLUS_PLUS;
//
// break;
// }
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNamePLUS_EQUAL;
//
// break;
// }
// }
// break;
// case '-' :
// token = TokenNameMINUS;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '-') {
// chIndx++;
// token = TokenNameMINUS_MINUS;
//
// break;
// }
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameMINUS_EQUAL;
//
// break;
// }
// if (str.charAt(chIndx) == '>') {
// chIndx++;
// token = TokenNameMINUS_GREATER;
//
// break;
// }
// }
//
// break;
// case '=' :
// token = TokenNameEQUAL;
//
// if (str.length() > chIndx) {
// ch = str.charAt(chIndx);
//
// if (ch == '=') {
// chIndx++;
// token = TokenNameEQUAL_EQUAL;
// if (str.length() > chIndx) {
// ch = str.charAt(chIndx);
//
// if (ch == '=') {
// chIndx++;
// token = TokenNameEQUAL_EQUAL_EQUAL;
// }
// }
// break;
// }
// if (ch == '>') {
// chIndx++;
// token = TokenNameFOREACH;
//
// break;
// }
// }
//
// break;
// case '!' :
// token = TokenNameNOT;
//
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameNOT_EQUAL;
// if (str.length() > chIndx) {
// ch = str.charAt(chIndx);
//
// if (ch == '=') {
// chIndx++;
// token = TokenNameNOT_EQUAL_EQUAL;
// }
// }
// break;
// }
// }
//
// break;
// case '>' :
// token = TokenNameGREATER;
//
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameGREATER_EQUAL;
// break;
// }
// if (str.charAt(chIndx) == '>') {
// chIndx++;
// token = TokenNameRIGHT_SHIFT;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameRIGHT_SHIFT_EQUAL;
// break;
// }
// }
// break;
// }
// }
//
// break;
// case '<' :
// token = TokenNameLESS;
//
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameLESS_EQUAL;
//
// break;
// }
// if (str.charAt(chIndx) == '<') {
// chIndx++;
// token = TokenNameLEFT_SHIFT;
// 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 = TokenNameStringConstant;
// 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 = TokenNameLEFT_SHIFT_EQUAL;
// break;
// }
// break;
// }
// }
//
// break;
//
// case '|' :
// token = TokenNameOR;
//
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '|') {
// chIndx++;
// token = TokenNameOR_OR;
//
// break;
// }
// }
//
// break;
// case '&' :
// token = TokenNameAND;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == '&') {
// chIndx++;
// token = TokenNameAND_AND;
// break;
// }
// if (str.charAt(chIndx) == '=') {
// chIndx++;
// token = TokenNameAND_EQUAL;
// break;
// }
// break;
// }
//
// break;
// case ':' :
// token = TokenNameCOLON;
// if (str.length() > chIndx) {
// if (str.charAt(chIndx) == ':') {
// chIndx++;
// token = TokenNameCOLON_COLON;
// }
// }
// break;
// case '#' :
// token = TokenNameHASH;
//
// break;
// // case '@' :
// // token = TokenNameAT;
// //
// // break;
// default :
// throwSyntaxError("unexpected character: '" + ch + "'");
// }
//
// if (token == TokenNameERROR) {
// throwSyntaxError("token not found");
// }
//
// return;
// }
// }
//
// chIndx = str.length() + 1;
// ch = ' ';
// token = TokenNameEOF;
// phpEnd = true;
// PHPString temp;
// if (phpList != null) {
// if (currentPHPString < phpList.size()) {
// token = TokenNameERROR;
// temp = (PHPString) phpList.get(currentPHPString++);
// this.str = temp.getPHPString();
// this.token = TokenNameEOF;
// this.chIndx = 0;
// this.rowCount = temp.getLineNumber();
// this.columnCount = 0;
// getNextToken();
// phpEnd = true;
// } else {
// token = TokenNameERROR;
// 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 = TokenNameERROR;
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 == 'P') {
ch2 = str.charAt(chIndx++);
if (ch2 == 'h' || ch2 == 'H') {
ch2 = str.charAt(chIndx++);
if (ch2 == 'p' || ch2 == 'P') {
phpMode = true;
phpFound = true;
break;
}
chIndx--;
}
chIndx--;
}
chIndx--;
}
chIndx--;
}
}
}
if (phpMode) {
while (str.length() > chIndx) {
ch = str.charAt(chIndx++);
token = TokenNameERROR;
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 = TokenNameDOLLAROPEN;
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 = TokenNameHTML;
// 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 = TokenNameHTML;
// php end
phpMode = false;
phpEnd = true;
return;
}
}
}
rowCount++;
continue;
} else if (ch == '"') {
getString('"',TokenNameStringInterpolated,"Open string character '\"' at end of file.");
return;
} else if (ch == '\'') {
getString('\'',TokenNameStringConstant,"Open string character \"'\" at end of file.");
return;
} else if (ch == '`') {
getString('`',TokenNameStringConstant,"Open string character \"`\" at end of file.");
setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO);
return;
}
switch (ch) {
case '(' :
token = TokenNameLPAREN;
break;
case ')' :
token = TokenNameRPAREN;
break;
case '{' :
token = TokenNameLBRACE;
break;
case '}' :
token = TokenNameRBRACE;
break;
case '[' :
token = TokenNameLBRACKET;
break;
case ']' :
token = TokenNameRBRACKET;
break;
case ',' :
token = TokenNameCOMMA;
break;
case '?' :
token = TokenNameQUESTION;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '>') {
chIndx++;
token = TokenNameHTML;
// php end
phpMode = false;
phpEnd = true;
break;
}
}
break;
case '@' :
token = TokenNameAT;
break;
case '~' :
token = TokenNameTWIDDLE;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameTWIDDLE_EQUAL;
break;
}
}
break;
case '.' :
token = TokenNameDOT;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameDOT_EQUAL;
break;
}
}
break;
case '"' :
token = TokenNameStringLiteral;
break;
case '%' :
token = TokenNameREMAINDER;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameREMAINDER_EQUAL;
break;
}
}
break;
case ';' :
token = TokenNameSEMICOLON;
break;
case '^' :
token = TokenNameXOR;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameXOR_EQUAL;
break;
}
}
break;
case '/' :
token = TokenNameDIVIDE;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameDIVIDE_EQUAL;
break;
}
}
break;
case '*' :
token = TokenNameMULTIPLY;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '*') {
chIndx++;
token = TokenNameXOR;
break;
}
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameMULTIPLY_EQUAL;
break;
}
}
break;
case '+' :
token = TokenNamePLUS;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '+') {
chIndx++;
token = TokenNamePLUS_PLUS;
break;
}
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNamePLUS_EQUAL;
break;
}
}
break;
case '-' :
token = TokenNameMINUS;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '-') {
chIndx++;
token = TokenNameMINUS_MINUS;
break;
}
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameMINUS_EQUAL;
break;
}
if (str.charAt(chIndx) == '>') {
chIndx++;
token = TokenNameMINUS_GREATER;
break;
}
}
break;
case '=' :
token = TokenNameEQUAL;
if (str.length() > chIndx) {
ch = str.charAt(chIndx);
if (ch == '=') {
chIndx++;
token = TokenNameEQUAL_EQUAL;
if (str.length() > chIndx) {
ch = str.charAt(chIndx);
if (ch == '=') {
chIndx++;
token = TokenNameEQUAL_EQUAL_EQUAL;
}
}
break;
}
if (ch == '>') {
chIndx++;
token = TokenNameFOREACH;
break;
}
}
break;
case '!' :
token = TokenNameNOT;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameNOT_EQUAL;
if (str.length() > chIndx) {
ch = str.charAt(chIndx);
if (ch == '=') {
chIndx++;
token = TokenNameNOT_EQUAL_EQUAL;
}
}
break;
}
}
break;
case '>' :
token = TokenNameGREATER;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameGREATER_EQUAL;
break;
}
if (str.charAt(chIndx) == '>') {
chIndx++;
token = TokenNameRIGHT_SHIFT;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameRIGHT_SHIFT_EQUAL;
break;
}
}
break;
}
}
break;
case '<' :
token = TokenNameLESS;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameLESS_EQUAL;
break;
}
if (str.charAt(chIndx) == '<') {
chIndx++;
token = TokenNameLEFT_SHIFT;
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 = TokenNameStringConstant;
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 = TokenNameLEFT_SHIFT_EQUAL;
break;
}
break;
}
}
break;
case '|' :
token = TokenNameOR;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '|') {
chIndx++;
token = TokenNameOR_OR;
break;
}
}
break;
case '&' :
token = TokenNameAND;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == '&') {
chIndx++;
token = TokenNameAND_AND;
break;
}
if (str.charAt(chIndx) == '=') {
chIndx++;
token = TokenNameAND_EQUAL;
break;
}
break;
}
break;
case ':' :
token = TokenNameCOLON;
if (str.length() > chIndx) {
if (str.charAt(chIndx) == ':') {
chIndx++;
token = TokenNameCOLON_COLON;
}
}
break;
// case '#' :
// token = TokenNameHASH;
//
// break;
// case '@' :
// token = TokenNameAT;
//
// break;
default :
throwSyntaxError("unexpected character: '" + ch + "'");
}
if (token == TokenNameERROR) {
throwSyntaxError("token not found");
}
return;
}
}
}
} catch (StringIndexOutOfBoundsException e) {
// catched from charAt
}
chIndx = str.length() + 1;
ch = ' ';
token = TokenNameEOF;
phpEnd = true;
//PHPString temp;
// if (phpList != null) {
// if (currentPHPString < phpList.size()) {
// token = TokenNameUNDEFINED;
// temp = (PHPString) phpList.get(currentPHPString++);
// this.str = temp.getPHPString();
// this.token = TokenNameEOF;
// this.chIndx = 0;
// this.rowCount = temp.getLineNumber();
// this.columnCount = 0;
// getNextToken();
// phpEnd = true;
// } else {
// token = TokenNameUNDEFINED;
// return;
// }
// }
}
/**
* Get an identifier.
*/
private void getIdentifier() {
// StringBuffer ident = new StringBuffer();
int startPosition = chIndx - 1;
// ident.append(ch);
if (ch == '$') {
getChar();
// attention recursive call:
getIdentifier();
token = TokenNameVariable;
return;
} else {
token = TokenNameIdentifier;
}
getChar();
//this will read the buffer until the next character is a forbidden character for identifier
while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
// ident.append(ch);
getChar();
}
int endPosition = chIndx--;
int length = (--endPosition) - startPosition;
identifier = str.substring(startPosition, endPosition);
// System.out.println(identifier);
// determine if this identitfer is a keyword
// @todo improve this in future version
Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
if (i != null) {
token = i.intValue();
}
}
/**
* Get a number.
* if it's a double
the number will be stored in doubleNumber
and the token will have the
* value {@link PHPParser#TokenNameDOUBLE_NUMBER}
* if it's a double
the number will be stored in longNumber
and the token will have the
* value {@link PHPParser#TokenNameINT_NUMBER}
*/
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 = TokenNameDoubleLiteral;
return;
} else {
longNumber = Long.valueOf(inum.toString(), numFormat);
token = TokenNameIntegerLiteral;
return;
}
} catch (Throwable e) {
throwSyntaxError("Number format error: " + inum.toString());
}
}
/**
* Get a String.
* @param openChar the opening char ('\'', '"', '`')
* @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
* @param errorMsg the error message in case of parse error in the string
*/
private void getString(final char openChar, final int typeString, final String errorMsg) {
StringBuffer sBuffer = new StringBuffer();
boolean openString = true;
int startRow = rowCount;
while (str.length() > chIndx) {
ch = str.charAt(chIndx++);
if (ch == '\\') {
sBuffer.append(ch);
if (str.length() > chIndx) {
ch = str.charAt(chIndx++);
sBuffer.append(ch);
}
} else if (ch == openChar) {
openString = false;
break;
} else if (ch == '\n') {
rowCount++;
columnCount = chIndx;
} else {
sBuffer.append(ch);
}
}
if (openString) {
if (typeString == TokenNameStringConstant) {
throwSyntaxError(errorMsg, startRow);
} else {
throwSyntaxError(errorMsg);
}
}
token = typeString;
stringValue = sBuffer.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");
// }
phpParserTester(null, 1);
// PHPString temp;
// for(int j=0;j TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
String keyword = identifier;
if (token == TokenNameinclude || token == TokenNameinclude_once) {
getNextToken();
expression();
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
if (!phpEnd) {
throwSyntaxError("';' character after 'include' or 'include_once' expected.");
}
getNextToken();
}
return;
} else if (token == TokenNamerequire || token == TokenNamerequire_once) {
getNextToken();
//constant();
expression();
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
if (!phpEnd) {
throwSyntaxError("';' character after 'require' or 'require_once' expected.");
}
getNextToken();
}
return;
} else if (token == TokenNameif) {
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected after 'if' keyword.");
}
expression();
if (token == TokenNameRPAREN) {
getNextToken();
} else {
throwSyntaxError("')' expected after 'if' condition.");
}
ifStatement();
return;
} else if (token == TokenNameswitch) {
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected after 'switch' keyword.");
}
expression();
if (token == TokenNameRPAREN) {
getNextToken();
} else {
throwSyntaxError("')' expected after 'switch' condition.");
}
switchStatement();
return;
} else if (token == TokenNamefor) {
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected after 'for' keyword.");
}
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
expressionList();
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
throwSyntaxError("';' expected after 'for'.");
}
}
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
expressionList();
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
throwSyntaxError("';' expected after 'for'.");
}
}
if (token == TokenNameRPAREN) {
getNextToken();
} else {
expressionList();
if (token == TokenNameRPAREN) {
getNextToken();
} else {
throwSyntaxError("')' expected after 'for'.");
}
}
forStatement();
return;
} else if (token == TokenNamewhile) {
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected after 'while' keyword.");
}
expression();
if (token == TokenNameRPAREN) {
getNextToken();
} else {
throwSyntaxError("')' expected after 'while' condition.");
}
whileStatement();
return;
} else if (token == TokenNamedo) {
getNextToken();
if (token == TokenNameLBRACE) {
getNextToken();
} else {
throwSyntaxError("'{' expected after 'do' keyword.");
}
if (token != TokenNameRBRACE) {
statementList();
}
if (token == TokenNameRBRACE) {
getNextToken();
} else {
throwSyntaxError("'}' expected after 'do' keyword.");
}
if (token == TokenNamewhile) {
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected after 'while' keyword.");
}
expression();
if (token == TokenNameRPAREN) {
getNextToken();
} else {
throwSyntaxError("')' expected after 'while' condition.");
}
} else {
throwSyntaxError("'while' expected after 'do' keyword.");
}
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
if (!phpEnd) {
throwSyntaxError("';' expected after do-while statement.");
}
getNextToken();
}
return;
} else if (token == TokenNameforeach) {
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected after 'foreach' keyword.");
}
expression();
if (token == TokenNameas) {
getNextToken();
} else {
throwSyntaxError("'as' expected after 'foreach' exxpression.");
}
variable();
if (token == TokenNameFOREACH) {
getNextToken();
variable();
}
if (token == TokenNameRPAREN) {
getNextToken();
} else {
throwSyntaxError("')' expected after 'foreach' expression.");
}
foreachStatement();
return;
} else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
getNextToken();
if (token != TokenNameSEMICOLON) {
expression();
}
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
if (!phpEnd) {
throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
}
getNextToken();
}
return;
} else if (token == TokenNameecho) {
getNextToken();
expressionList();
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
if (!phpEnd) {
throwSyntaxError("';' expected after 'echo' statement.");
}
getNextToken();
}
return;
// } else if (token == TokenNameprint) {
// getNextToken();
// expression();
// if (token == TokenNameSEMICOLON) {
// getNextToken();
// } else {
// if (!phpEnd) {
// throwSyntaxError("';' expected after 'print' statement.");
// }
// getNextToken();
// }
// return;
} else if (token == TokenNameglobal || token == TokenNamestatic) {
getNextToken();
variableList();
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
if (!phpEnd) {
throwSyntaxError("';' expected after 'global' or 'static' statement.");
}
getNextToken();
}
return;
// } else if (token == TokenNameunset) {
// getNextToken();
// if (token == TokenNameARGOPEN) {
// getNextToken();
// } else {
// throwSyntaxError("'(' expected after 'unset' keyword.");
// }
// variableList();
// if (token == TokenNameARGCLOSE) {
// getNextToken();
// } else {
// throwSyntaxError("')' expected after 'unset' statement.");
// }
// if (token == TokenNameSEMICOLON) {
// getNextToken();
// } else {
// if (!phpEnd) {
// throwSyntaxError("';' expected after 'unset' statement.");
// }
// getNextToken();
// }
// return;
// } else if (token == TokenNameexit || token == TokenNamedie) {
// getNextToken();
// if (token != TokenNameSEMICOLON) {
// exitStatus();
// }
// if (token == TokenNameSEMICOLON) {
// getNextToken();
// } else {
// if (!phpEnd) {
// throwSyntaxError("';' expected after 'exit' or 'die' statement.");
// }
// getNextToken();
// }
// return;
} else if (token == TokenNamedefine) {
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected after 'define' keyword.");
}
expression();
if (token == TokenNameCOMMA) {
getNextToken();
} else {
throwSyntaxError("',' expected after first 'define' constant.");
}
expression();
if (token == TokenNameCOMMA) {
getNextToken();
expression();
}
if (token == TokenNameRPAREN) {
getNextToken();
} else {
throwSyntaxError("')' expected after 'define' statement.");
}
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
if (!phpEnd) {
throwSyntaxError("';' expected after 'define' statement.");
}
getNextToken();
}
return;
} else if (token == TokenNamefunction) {
getNextToken();
functionDefinition();
return;
} else if (token == TokenNameclass) {
getNextToken();
classDeclarator();
classBody();
return;
// } else {
// throwSyntaxError("Unexpected keyword '" + keyword + "'");
} else if (token == TokenNameLBRACE) {
// compoundStatement
getNextToken();
if (token != TokenNameRBRACE) {
statementList();
}
if (token == TokenNameRBRACE) {
getNextToken();
return;
} else {
throwSyntaxError("'}' expected.");
}
} else {
if (token != TokenNameSEMICOLON) {
expression();
}
if (token == TokenNameSEMICOLON) {
getNextToken();
return;
} else {
if (!phpEnd) {
throwSyntaxError("';' expected after expression.");
}
getNextToken();
}
}
}
private void classDeclarator() throws CoreException {
//identifier
//identifier 'extends' identifier
if (token == TokenNameIdentifier) {
getNextToken();
if (token == TokenNameextends) {
getNextToken();
if (token == TokenNameIdentifier) {
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 == TokenNameLBRACE) {
getNextToken();
if (token != TokenNameRBRACE) {
classElementList();
}
if (token == TokenNameRBRACE) {
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 == TokenNamefunction || token == TokenNamevar);
}
private void classElement() throws CoreException {
//class-property
//function-definition
if (token == TokenNamefunction) {
getNextToken();
functionDefinition();
} else if (token == TokenNamevar) {
getNextToken();
classProperty();
} else {
throwSyntaxError("'function' or 'var' expected.");
}
}
private void classProperty() throws CoreException {
//'var' variable ';'
//'var' variable '=' constant ';'
do {
if (token == TokenNameVariable) {
getNextToken();
if (token == TokenNameEQUAL) {
getNextToken();
constant();
}
} else {
throwSyntaxError("Variable expected after keyword 'var'.");
}
if (token != TokenNameCOMMA) {
break;
}
getNextToken();
} while (true);
if (token == TokenNameSEMICOLON) {
getNextToken();
} else {
throwSyntaxError("';' expected after variable declaration.");
}
}
private void functionDefinition() throws CoreException {
functionDeclarator();
compoundStatement();
}
private void functionDeclarator() throws CoreException {
//identifier '(' [parameter-list] ')'
if (token == TokenNameAND) {
getNextToken();
}
if (token == TokenNameIdentifier) {
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected in function declaration.");
}
if (token != TokenNameRPAREN) {
parameterList();
}
if (token != TokenNameRPAREN) {
throwSyntaxError("')' expected in function declaration.");
} else {
getNextToken();
}
}
}
//
private void parameterList() throws CoreException {
//parameter-declaration
//parameter-list ',' parameter-declaration
do {
parameterDeclaration();
if (token != TokenNameCOMMA) {
break;
}
getNextToken();
} while (true);
}
private void parameterDeclaration() throws CoreException {
//variable
//variable-reference
if (token == TokenNameAND) {
getNextToken();
if (token == TokenNameVariable) {
getNextToken();
} else {
throwSyntaxError("Variable expected after reference operator '&'.");
}
}
//variable '=' constant
if (token == TokenNameVariable) {
getNextToken();
if (token == TokenNameEQUAL) {
getNextToken();
constant();
}
return;
}
}
private void labeledStatementList() throws CoreException {
if (token != TokenNamecase && token != TokenNamedefault) {
throwSyntaxError("'case' or 'default' expected.");
}
do {
if (token == TokenNamecase) {
getNextToken();
constant();
if (token == TokenNameCOLON) {
getNextToken();
if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
continue;
}
statementList();
} else if (token == TokenNameSEMICOLON) {
setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO);
getNextToken();
if (token == TokenNamecase) { // empty case statement ?
continue;
}
statementList();
} else {
throwSyntaxError("':' character after 'case' constant expected.");
}
} else { // TokenNamedefault
getNextToken();
if (token == TokenNameCOLON) {
getNextToken();
statementList();
} else {
throwSyntaxError("':' character after 'default' expected.");
}
}
} while (token == TokenNamecase || token == TokenNamedefault);
}
// public void labeledStatement() {
// if (token == TokenNamecase) {
// getNextToken();
// constant();
// if (token == TokenNameDDOT) {
// getNextToken();
// statement();
// } else {
// throwSyntaxError("':' character after 'case' constant expected.");
// }
// return;
// } else if (token == TokenNamedefault) {
// getNextToken();
// if (token == TokenNameDDOT) {
// 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 == TokenNameCOLON) {
getNextToken();
statementList();
switch (token) {
case TokenNameelse :
getNextToken();
if (token == TokenNameCOLON) {
getNextToken();
statementList();
} else {
if (token == TokenNameif) { //'else if'
getNextToken();
elseifStatementList();
} else {
throwSyntaxError("':' expected after 'else'.");
}
}
break;
case TokenNameelseif :
getNextToken();
elseifStatementList();
break;
}
if (token != TokenNameendif) {
throwSyntaxError("'endif' expected.");
}
getNextToken();
if (token != TokenNameSEMICOLON) {
throwSyntaxError("';' expected after if-statement.");
}
getNextToken();
} else {
// statement [else-statement]
statement();
if (token == TokenNameelseif) {
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected after 'elseif' keyword.");
}
expression();
if (token == TokenNameRPAREN) {
getNextToken();
} else {
throwSyntaxError("')' expected after 'elseif' condition.");
}
ifStatement();
} else if (token == TokenNameelse) {
getNextToken();
statement();
}
}
}
private void elseifStatementList() throws CoreException {
do {
elseifStatement();
switch (token) {
case TokenNameelse :
getNextToken();
if (token == TokenNameCOLON) {
getNextToken();
statementList();
return;
} else {
if (token == TokenNameif) { //'else if'
getNextToken();
} else {
throwSyntaxError("':' expected after 'else'.");
}
}
break;
case TokenNameelseif :
getNextToken();
break;
default :
return;
}
} while (true);
}
private void elseifStatement() throws CoreException {
if (token == TokenNameLPAREN) {
getNextToken();
expression();
if (token != TokenNameLPAREN) {
throwSyntaxError("')' expected in else-if-statement.");
}
getNextToken();
if (token != TokenNameCOLON) {
throwSyntaxError("':' expected in else-if-statement.");
}
getNextToken();
statementList();
}
}
private void switchStatement() throws CoreException {
if (token == TokenNameCOLON) {
// ':' [labeled-statement-list] 'endswitch' ';'
getNextToken();
labeledStatementList();
if (token != TokenNameendswitch) {
throwSyntaxError("'endswitch' expected.");
}
getNextToken();
if (token != TokenNameSEMICOLON) {
throwSyntaxError("';' expected after switch-statement.");
}
getNextToken();
} else {
// '{' [labeled-statement-list] '}'
if (token != TokenNameLBRACE) {
throwSyntaxError("'{' expected in switch statement.");
}
getNextToken();
if (token != TokenNameRBRACE) {
labeledStatementList();
}
if (token != TokenNameRBRACE) {
throwSyntaxError("'}' expected in switch statement.");
}
getNextToken();
}
}
private void forStatement() throws CoreException {
if (token == TokenNameCOLON) {
getNextToken();
statementList();
if (token != TokenNameendfor) {
throwSyntaxError("'endfor' expected.");
}
getNextToken();
if (token != TokenNameSEMICOLON) {
throwSyntaxError("';' expected after for-statement.");
}
getNextToken();
} else {
statement();
}
}
private void whileStatement() throws CoreException {
// ':' statement-list 'endwhile' ';'
if (token == TokenNameCOLON) {
getNextToken();
statementList();
if (token != TokenNameendwhile) {
throwSyntaxError("'endwhile' expected.");
}
getNextToken();
if (token != TokenNameSEMICOLON) {
throwSyntaxError("';' expected after while-statement.");
}
getNextToken();
} else {
statement();
}
}
private void foreachStatement() throws CoreException {
if (token == TokenNameCOLON) {
getNextToken();
statementList();
if (token != TokenNameendforeach) {
throwSyntaxError("'endforeach' expected.");
}
getNextToken();
if (token != TokenNameSEMICOLON) {
throwSyntaxError("';' expected after foreach-statement.");
}
getNextToken();
} else {
statement();
}
}
private void exitStatus() throws CoreException {
if (token == TokenNameLPAREN) {
getNextToken();
} else {
throwSyntaxError("'(' expected in 'exit-status'.");
}
if (token != TokenNameRPAREN) {
expression();
}
if (token == TokenNameRPAREN) {
getNextToken();
} else {
throwSyntaxError("')' expected after 'exit-status'.");
}
}
private void expressionList() throws CoreException {
do {
expression();
if (token == TokenNameCOMMA) {
getNextToken();
} else {
break;
}
} while (true);
}
private void expression() throws CoreException {
//todo: find a better way to get the expression
expression = new StringBuffer();
for (int i = chIndx;i
getNextToken();
if (token > TokenNameKEYWORD) {
ident = identifier;
setMarker("Avoid using keyword '" + ident + "' as variable name.", rowCount, PHPParser.INFO);
}
switch (token) {
case TokenNameVariable :
ident = identifier;
getNextToken();
// if (token == TokenNameARGOPEN) {
// getNextToken();
// expressionList();
// if (token != TokenNameARGCLOSE) {
// throwSyntaxError(") expected after variable '" + ident + "'.");
// }
// getNextToken();
// }
break;
case TokenNameIdentifier :
ident = identifier;
getNextToken();
break;
case TokenNameLBRACE :
getNextToken();
expression();
if (token != TokenNameRBRACE) {
throwSyntaxError("} expected in postfix-expression.");
}
getNextToken();
break;
default :
throwSyntaxError("Syntax error after '->' token.");
} while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
if (token == TokenNameLBRACKET) {
getNextToken();
expressionList();
if (token != TokenNameRBRACKET) {
throwSyntaxError("] expected after '->'.");
}
getNextToken();
}
if (token == TokenNameLPAREN) {
getNextToken();
expressionList();
if (token != TokenNameRPAREN) {
throwSyntaxError(") expected after '->'.");
}
getNextToken();
}
if (token == TokenNameLBRACE) {
getNextToken();
expression();
if (token != TokenNameRBRACE) {
throwSyntaxError("} expected after '->'.");
}
getNextToken();
}
}
break;
case TokenNamePLUS_PLUS :
getNextToken();
break;
case TokenNameMINUS_MINUS :
getNextToken();
break;
default :
while_flag = false;
}
}
while (while_flag);
}
private void unaryExpression() throws CoreException {
switch (token) {
case TokenNamePLUS_PLUS :
getNextToken();
unaryExpression();
break;
case TokenNameMINUS_MINUS :
getNextToken();
unaryExpression();
break;
// '@' '&' '*' '+' '-' '~' '!'
case TokenNameAT :
getNextToken();
castExpression();
break;
case TokenNameAND :
getNextToken();
castExpression();
break;
case TokenNameMULTIPLY :
getNextToken();
castExpression();
break;
case TokenNamePLUS :
getNextToken();
castExpression();
break;
case TokenNameMINUS :
getNextToken();
castExpression();
break;
case TokenNameTWIDDLE :
getNextToken();
castExpression();
break;
case TokenNameNOT :
getNextToken();
castExpression();
break;
default :
postfixExpression();
}
}
private void castExpression() throws CoreException {
// if (token == TokenNameARGOPEN) {
// getNextToken();
// typeName();
// if (token != TokenNameARGCLOSE) {
// 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 == TokenNameIdentifier) {
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 '( )'; Got '" + ident + "'.");
}
private void assignExpression() throws CoreException {
castExpression();
if (token == TokenNameEQUAL) { // =
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameDOT_EQUAL) { // .=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameFOREACH) { // =>
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNamePLUS_EQUAL) { // +=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameMINUS_EQUAL) { // -=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameMULTIPLY_EQUAL) { // *=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameDIVIDE_EQUAL) { // *=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameREMAINDER_EQUAL) { // %=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameAND_EQUAL) { // &=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameXOR_EQUAL) { // ^=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
getNextToken();
logicalinclusiveorExpression();
} else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
getNextToken();
logicalinclusiveorExpression();
}
}
private void multiplicativeExpression() throws CoreException {
do {
assignExpression();
if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
return;
}
getNextToken();
} while (true);
}
private void concatenationExpression() throws CoreException {
do {
multiplicativeExpression();
if (token != TokenNameDOT) {
return;
}
getNextToken();
} while (true);
}
private void additiveExpression() throws CoreException {
do {
concatenationExpression();
if (token != TokenNamePLUS && token != TokenNameMINUS) {
return;
}
getNextToken();
} while (true);
}
private void shiftExpression() throws CoreException {
do {
additiveExpression();
if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
return;
}
getNextToken();
} while (true);
}
private void relationalExpression() throws CoreException {
do {
shiftExpression();
if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
return;
}
getNextToken();
} while (true);
}
private void identicalExpression() throws CoreException {
do {
relationalExpression();
if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
return;
}
getNextToken();
} while (true);
}
private void equalityExpression() throws CoreException {
do {
identicalExpression();
if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
return;
}
getNextToken();
} while (true);
}
private void ternaryExpression() throws CoreException {
equalityExpression();
if (token == TokenNameQUESTION) {
getNextToken();
expression();
if (token == TokenNameCOLON) {
getNextToken();
expression();
} else {
throwSyntaxError("':' expected in ternary operator '? :'.");
}
}
}
private void andExpression() throws CoreException {
do {
ternaryExpression();
if (token != TokenNameAND) {
return;
}
getNextToken();
} while (true);
}
private void exclusiveorExpression() throws CoreException {
do {
andExpression();
if (token != TokenNameXOR) {
return;
}
getNextToken();
} while (true);
}
private void inclusiveorExpression() throws CoreException {
do {
exclusiveorExpression();
if (token != TokenNameOR) {
return;
}
getNextToken();
} while (true);
}
private void booleanandExpression() throws CoreException {
do {
inclusiveorExpression();
if (token != TokenNameAND_AND) {
return;
}
getNextToken();
} while (true);
}
private void booleanorExpression() throws CoreException {
do {
booleanandExpression();
if (token != TokenNameOR_OR) {
return;
}
getNextToken();
} while (true);
}
private void logicalandExpression() throws CoreException {
do {
booleanorExpression();
if (token != TokenNameAND) {
return;
}
getNextToken();
} while (true);
}
private void logicalexclusiveorExpression() throws CoreException {
do {
logicalandExpression();
if (token != TokenNameXOR) {
return;
}
getNextToken();
} while (true);
}
private void logicalinclusiveorExpression() throws CoreException {
do {
logicalexclusiveorExpression();
if (token != TokenNameOR) {
return;
}
getNextToken();
} while (true);
}
// public void assignmentExpression() {
// if (token == TokenNameVARIABLE) {
// getNextToken();
// if (token == TokenNameSET) {
// getNextToken();
// logicalinclusiveorExpression();
// }
// } else {
// logicalinclusiveorExpression();
// }
// }
private void variableList() throws CoreException {
do {
variable();
if (token == TokenNameCOMMA) {
getNextToken();
} else {
break;
}
} while (true);
}
private void variable() throws CoreException {
if (token == TokenNameDOLLAROPEN) {
getNextToken();
expression();
;
if (token != TokenNameRBRACE) {
throwSyntaxError("'}' expected after indirect variable token '${'.");
}
getNextToken();
} else {
if (token == TokenNameVariable) {
getNextToken();
if (token == TokenNameLBRACKET) {
getNextToken();
expression();
if (token != TokenNameRBRACKET) {
throwSyntaxError("']' expected in variable-list.");
}
getNextToken();
} else if (token == TokenNameEQUAL) {
getNextToken();
constant();
}
} else {
throwSyntaxError("$-variable expected in variable-list.");
}
}
}
/**
* It will look for a value (after a '=' for example)
* @throws CoreException
*/
private void constant() throws CoreException {
String ident;
switch (token) {
case TokenNamePLUS :
getNextToken();
switch (token) {
case TokenNameDoubleLiteral :
getNextToken();
break;
case TokenNameIntegerLiteral :
getNextToken();
break;
default :
throwSyntaxError("Constant expected after '+' presign.");
}
break;
case TokenNameMINUS :
getNextToken();
switch (token) {
case TokenNameDoubleLiteral :
getNextToken();
break;
case TokenNameIntegerLiteral :
getNextToken();
break;
default :
throwSyntaxError("Constant expected after '-' presign.");
}
break;
case TokenNamenull :
getNextToken();
break;
case TokenNamefalse :
getNextToken();
break;
case TokenNametrue :
getNextToken();
break;
case TokenNameIdentifier :
ident = identifier;
getNextToken();
if (token == TokenNameLPAREN) {
getNextToken();
if (token != TokenNameRPAREN) {
expressionList();
if (token != TokenNameRPAREN) {
throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
}
}
getNextToken();
}
break;
case TokenNameStringConstant :
getNextToken();
break;
case TokenNameStringInterpolated :
getNextToken();
break;
case TokenNameDoubleLiteral :
getNextToken();
break;
case TokenNameIntegerLiteral :
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.getParserOutput(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("
", 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("
", 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 ");
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("", "");
current = current.replaceAll("", "");
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);
}
}
}
}