/********************************************************************** 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 TokenNameUNDEFINED = 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 TokenNameSUBTRACT = 36; final static int TokenNameADD = 37; final static int TokenNameEQUAL = 38; final static int TokenNameUNEQUAL = 39; final static int TokenNameGREATER = 40; final static int TokenNameGREATEREQUAL = 41; final static int TokenNameLESS = 42; final static int TokenNameLESSEQUAL = 43; final static int TokenNameAND = 44; final static int TokenNameOR = 45; final static int TokenNameHASH = 46; final static int TokenNameDDOT = 47; final static int TokenNameDOTASSIGN = 48; final static int TokenNameASSIGN = 49; final static int TokenNameREF = 50; final static int TokenNameFOREACH = 51; final static int TokenNameAMPERSAND = 52; final static int TokenNameDOLLARLISTOPEN = 53; final static int TokenNameTILDE = 54; final static int TokenNameTILDEASSIGN = 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 TokenNameANDASSIGN = 60; final static int TokenNameQUESTIONMARK = 61; final static int TokenNameDDOT2 = 62; final static int TokenNameAT = 63; // final static int TokenNameHEREDOC = 64; final static int TokenNameDOLLAROPEN = 127; final static int TokenNameARGOPEN = 128; final static int TokenNameARGCLOSE = 129; final static int TokenNameLISTOPEN = 130; final static int TokenNameLISTCLOSE = 131; final static int TokenNamePARTOPEN = 132; final static int TokenNamePARTCLOSE = 133; final static int TokenNameCOMMA = 134; final static int TokenNameSTRING = 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 TokenNameDECREMENT = 144; final static int TokenNameINCREMENT = 145; final static int TokenNameADDTO = 146; final static int TokenNameDIVIDE_EQUAL = 147; final static int TokenNameSUBTRACTFROM = 148; final static int TokenNameTIMESBY = 149; final static int TokenNameVARIABLE = 150; final static int TokenNameINT_NUMBER = 151; final static int TokenNameDOUBLE_NUMBER = 152; final static int TokenNameINTERPOLATED_STRING = 153; final static int TokenNameSTRING_CONSTANT = 154; final static int TokenNameLEFT_SHIFT = 155; final static int TokenNameRSHIFT = 156; final static int TokenNameEX_EQUAL = 157; final static int TokenNameEX_UNEQUAL = 158; final static int TokenNameLINE = 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 = TokenNameUNDEFINED; 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 = TokenNameSTRING_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); } token = TokenNameSTRING_CONSTANT; return; } switch (ch) { case '(' : token = TokenNameARGOPEN; break; case ')' : token = TokenNameARGCLOSE; break; case '{' : token = TokenNameLISTOPEN; break; case '}' : token = TokenNameLISTCLOSE; break; case '[' : token = TokenNamePARTOPEN; break; case ']' : token = TokenNamePARTCLOSE; break; case ',' : token = TokenNameCOMMA; break; case '?' : token = TokenNameQUESTIONMARK; break; case '@' : token = TokenNameAT; break; case '~' : token = TokenNameTILDE; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameTILDEASSIGN; break; } } break; case '.' : token = TokenNameDOT; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameDOTASSIGN; break; } } break; case '"' : token = TokenNameSTRING; 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 = TokenNameTIMESBY; break; } } break; case '+' : token = TokenNameADD; if (str.length() > chIndx) { if (str.charAt(chIndx) == '+') { chIndx++; token = TokenNameINCREMENT; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameADDTO; break; } } break; case '-' : token = TokenNameSUBTRACT; if (str.length() > chIndx) { if (str.charAt(chIndx) == '-') { chIndx++; token = TokenNameDECREMENT; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameSUBTRACTFROM; break; } if (str.charAt(chIndx) == '>') { chIndx++; token = TokenNameREF; break; } } break; case '=' : token = TokenNameASSIGN; if (str.length() > chIndx) { ch = str.charAt(chIndx); if (ch == '=') { chIndx++; token = TokenNameEQUAL; if (str.length() > chIndx) { ch = str.charAt(chIndx); if (ch == '=') { chIndx++; token = TokenNameEX_EQUAL; } } break; } if (ch == '>') { chIndx++; token = TokenNameFOREACH; break; } } break; case '!' : token = TokenNameNOT; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameUNEQUAL; if (str.length() > chIndx) { ch = str.charAt(chIndx); if (ch == '=') { chIndx++; token = TokenNameEX_UNEQUAL; } } break; } } break; case '>' : token = TokenNameGREATER; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameGREATEREQUAL; break; } if (str.charAt(chIndx) == '>') { chIndx++; token = TokenNameRSHIFT; 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 = TokenNameLESSEQUAL; 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 = TokenNameSTRING_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 = TokenNameLEFT_SHIFT_EQUAL; break; } break; } } break; case '|' : token = TokenNameLINE; if (str.length() > chIndx) { if (str.charAt(chIndx) == '|') { chIndx++; token = TokenNameOR; break; } } break; case '&' : token = TokenNameAMPERSAND; if (str.length() > chIndx) { if (str.charAt(chIndx) == '&') { chIndx++; token = TokenNameAND; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameANDASSIGN; break; } break; } break; case ':' : token = TokenNameDDOT; if (str.length() > chIndx) { if (str.charAt(chIndx) == ':') { chIndx++; token = TokenNameDDOT2; } } break; case '#' : token = TokenNameHASH; break; // case '@' : // token = TokenNameAT; // // break; default : throwSyntaxError("unexpected character: '" + ch + "'"); } if (token == TokenNameUNDEFINED) { throwSyntaxError("token not found"); } return; } } 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; } } } /** * 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 = TokenNameUNDEFINED; 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 = TokenNameUNDEFINED; 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('"',TokenNameINTERPOLATED_STRING,"Open string character '\"' at end of file."); return; } else if (ch == '\'') { getString('\'',TokenNameSTRING_CONSTANT,"Open string character \"'\" at end of file."); return; } else if (ch == '`') { getString('`',TokenNameSTRING_CONSTANT,"Open string character \"`\" at end of file."); setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO); return; } switch (ch) { case '(' : token = TokenNameARGOPEN; break; case ')' : token = TokenNameARGCLOSE; break; case '{' : token = TokenNameLISTOPEN; break; case '}' : token = TokenNameLISTCLOSE; break; case '[' : token = TokenNamePARTOPEN; break; case ']' : token = TokenNamePARTCLOSE; break; case ',' : token = TokenNameCOMMA; break; case '?' : token = TokenNameQUESTIONMARK; 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 = TokenNameTILDE; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameTILDEASSIGN; break; } } break; case '.' : token = TokenNameDOT; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameDOTASSIGN; break; } } break; case '"' : token = TokenNameSTRING; 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 = TokenNameTIMESBY; break; } } break; case '+' : token = TokenNameADD; if (str.length() > chIndx) { if (str.charAt(chIndx) == '+') { chIndx++; token = TokenNameINCREMENT; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameADDTO; break; } } break; case '-' : token = TokenNameSUBTRACT; if (str.length() > chIndx) { if (str.charAt(chIndx) == '-') { chIndx++; token = TokenNameDECREMENT; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameSUBTRACTFROM; break; } if (str.charAt(chIndx) == '>') { chIndx++; token = TokenNameREF; break; } } break; case '=' : token = TokenNameASSIGN; if (str.length() > chIndx) { ch = str.charAt(chIndx); if (ch == '=') { chIndx++; token = TokenNameEQUAL; if (str.length() > chIndx) { ch = str.charAt(chIndx); if (ch == '=') { chIndx++; token = TokenNameEX_EQUAL; } } break; } if (ch == '>') { chIndx++; token = TokenNameFOREACH; break; } } break; case '!' : token = TokenNameNOT; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameUNEQUAL; if (str.length() > chIndx) { ch = str.charAt(chIndx); if (ch == '=') { chIndx++; token = TokenNameEX_UNEQUAL; } } break; } } break; case '>' : token = TokenNameGREATER; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameGREATEREQUAL; break; } if (str.charAt(chIndx) == '>') { chIndx++; token = TokenNameRSHIFT; 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 = TokenNameLESSEQUAL; 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 = TokenNameSTRING_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 = TokenNameLEFT_SHIFT_EQUAL; break; } break; } } break; case '|' : token = TokenNameLINE; if (str.length() > chIndx) { if (str.charAt(chIndx) == '|') { chIndx++; token = TokenNameOR; break; } } break; case '&' : token = TokenNameAMPERSAND; if (str.length() > chIndx) { if (str.charAt(chIndx) == '&') { chIndx++; token = TokenNameAND; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TokenNameANDASSIGN; break; } break; } break; case ':' : token = TokenNameDDOT; if (str.length() > chIndx) { if (str.charAt(chIndx) == ':') { chIndx++; token = TokenNameDDOT2; } } break; case '#' : token = TokenNameHASH; break; // case '@' : // token = TokenNameAT; // // break; default : throwSyntaxError("unexpected character: '" + ch + "'"); } if (token == TokenNameUNDEFINED) { 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 = TokenNameDOUBLE_NUMBER; return; } else { longNumber = Long.valueOf(inum.toString(), numFormat); token = TokenNameINT_NUMBER; 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 == TokenNameSTRING_CONSTANT) { 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 == TokenNameARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'if' keyword."); } expression(); if (token == TokenNameARGCLOSE) { getNextToken(); } else { throwSyntaxError("')' expected after 'if' condition."); } ifStatement(); return; } else if (token == TokenNameswitch) { getNextToken(); if (token == TokenNameARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'switch' keyword."); } expression(); if (token == TokenNameARGCLOSE) { getNextToken(); } else { throwSyntaxError("')' expected after 'switch' condition."); } switchStatement(); return; } else if (token == TokenNamefor) { getNextToken(); if (token == TokenNameARGOPEN) { 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 == TokenNameARGCLOSE) { getNextToken(); } else { expressionList(); if (token == TokenNameARGCLOSE) { getNextToken(); } else { throwSyntaxError("')' expected after 'for'."); } } forStatement(); return; } else if (token == TokenNamewhile) { getNextToken(); if (token == TokenNameARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'while' keyword."); } expression(); if (token == TokenNameARGCLOSE) { getNextToken(); } else { throwSyntaxError("')' expected after 'while' condition."); } whileStatement(); return; } else if (token == TokenNamedo) { getNextToken(); if (token == TokenNameLISTOPEN) { getNextToken(); } else { throwSyntaxError("'{' expected after 'do' keyword."); } if (token != TokenNameLISTCLOSE) { statementList(); } if (token == TokenNameLISTCLOSE) { getNextToken(); } else { throwSyntaxError("'}' expected after 'do' keyword."); } if (token == TokenNamewhile) { getNextToken(); if (token == TokenNameARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'while' keyword."); } expression(); if (token == TokenNameARGCLOSE) { 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 == TokenNameARGOPEN) { 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 == TokenNameARGCLOSE) { 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 == TokenNameARGOPEN) { 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 == TokenNameARGCLOSE) { 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 == TokenNameLISTOPEN) { // compoundStatement getNextToken(); if (token != TokenNameLISTCLOSE) { statementList(); } if (token == TokenNameLISTCLOSE) { 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 == TokenNameLISTOPEN) { getNextToken(); if (token != TokenNameLISTCLOSE) { classElementList(); } if (token == TokenNameLISTCLOSE) { 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 == TokenNameASSIGN) { 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 == TokenNameAMPERSAND) { getNextToken(); } if (token == TokenNameIDENTIFIER) { getNextToken(); if (token == TokenNameARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected in function declaration."); } if (token != TokenNameARGCLOSE) { parameterList(); } if (token != TokenNameARGCLOSE) { 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 == TokenNameAMPERSAND) { getNextToken(); if (token == TokenNameVARIABLE) { getNextToken(); } else { throwSyntaxError("Variable expected after reference operator '&'."); } } //variable '=' constant if (token == TokenNameVARIABLE) { getNextToken(); if (token == TokenNameASSIGN) { 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 == TokenNameDDOT) { 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 == TokenNameDDOT) { 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 == TokenNameDDOT) { getNextToken(); statementList(); switch (token) { case TokenNameelse : getNextToken(); if (token == TokenNameDDOT) { 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 == TokenNameARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'elseif' keyword."); } expression(); if (token == TokenNameARGCLOSE) { 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 == TokenNameDDOT) { 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 == TokenNameARGOPEN) { getNextToken(); expression(); if (token != TokenNameARGOPEN) { throwSyntaxError("')' expected in else-if-statement."); } getNextToken(); if (token != TokenNameDDOT) { throwSyntaxError("':' expected in else-if-statement."); } getNextToken(); statementList(); } } private void switchStatement() throws CoreException { if (token == TokenNameDDOT) { // ':' [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 != TokenNameLISTOPEN) { throwSyntaxError("'{' expected in switch statement."); } getNextToken(); if (token != TokenNameLISTCLOSE) { labeledStatementList(); } if (token != TokenNameLISTCLOSE) { throwSyntaxError("'}' expected in switch statement."); } getNextToken(); } } private void forStatement() throws CoreException { if (token == TokenNameDDOT) { 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 == TokenNameDDOT) { 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 == TokenNameDDOT) { 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 == TokenNameARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected in 'exit-status'."); } if (token != TokenNameARGCLOSE) { expression(); } if (token == TokenNameARGCLOSE) { 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 TokenNameLISTOPEN : getNextToken(); expression(); if (token != TokenNameLISTCLOSE) { throwSyntaxError("} expected in postfix-expression."); } getNextToken(); break; default : throwSyntaxError("Syntax error after '->' token."); } while (token == TokenNamePARTOPEN || token == TokenNameARGOPEN || token == TokenNameLISTOPEN) { if (token == TokenNamePARTOPEN) { getNextToken(); expressionList(); if (token != TokenNamePARTCLOSE) { throwSyntaxError("] expected after '->'."); } getNextToken(); } if (token == TokenNameARGOPEN) { getNextToken(); expressionList(); if (token != TokenNameARGCLOSE) { throwSyntaxError(") expected after '->'."); } getNextToken(); } if (token == TokenNameLISTOPEN) { getNextToken(); expression(); if (token != TokenNameLISTCLOSE) { throwSyntaxError("} expected after '->'."); } getNextToken(); } } break; case TokenNameINCREMENT : getNextToken(); break; case TokenNameDECREMENT : getNextToken(); break; default : while_flag = false; } } while (while_flag); } private void unaryExpression() throws CoreException { switch (token) { case TokenNameINCREMENT : getNextToken(); unaryExpression(); break; case TokenNameDECREMENT : getNextToken(); unaryExpression(); break; // '@' '&' '*' '+' '-' '~' '!' case TokenNameAT : getNextToken(); castExpression(); break; case TokenNameAMPERSAND : getNextToken(); castExpression(); break; case TokenNameMULTIPLY : getNextToken(); castExpression(); break; case TokenNameADD : getNextToken(); castExpression(); break; case TokenNameSUBTRACT : getNextToken(); castExpression(); break; case TokenNameTILDE : 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 == TokenNameASSIGN) { // = getNextToken(); logicalinclusiveorExpression(); } else if (token == TokenNameDOTASSIGN) { // .= getNextToken(); logicalinclusiveorExpression(); } else if (token == TokenNameFOREACH) { // => getNextToken(); logicalinclusiveorExpression(); } else if (token == TokenNameADDTO) { // += getNextToken(); logicalinclusiveorExpression(); } else if (token == TokenNameSUBTRACTFROM) { // -= getNextToken(); logicalinclusiveorExpression(); } else if (token == TokenNameTIMESBY) { // *= getNextToken(); logicalinclusiveorExpression(); } else if (token == TokenNameDIVIDE_EQUAL) { // *= getNextToken(); logicalinclusiveorExpression(); } else if (token == TokenNameREMAINDER_EQUAL) { // %= getNextToken(); logicalinclusiveorExpression(); } else if (token == TokenNameANDASSIGN) { // &= 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 == TokenNameTILDEASSIGN) { // ~= 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 != TokenNameADD && token != TokenNameSUBTRACT) { return; } getNextToken(); } while (true); } private void shiftExpression() throws CoreException { do { additiveExpression(); if (token != TokenNameLEFT_SHIFT && token != TokenNameRSHIFT) { return; } getNextToken(); } while (true); } private void relationalExpression() throws CoreException { do { shiftExpression(); if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESSEQUAL && token != TokenNameGREATEREQUAL) { return; } getNextToken(); } while (true); } private void identicalExpression() throws CoreException { do { relationalExpression(); if (token != TokenNameEX_EQUAL && token != TokenNameEX_UNEQUAL) { return; } getNextToken(); } while (true); } private void equalityExpression() throws CoreException { do { identicalExpression(); if (token != TokenNameEQUAL && token != TokenNameUNEQUAL) { return; } getNextToken(); } while (true); } private void ternaryExpression() throws CoreException { equalityExpression(); if (token == TokenNameQUESTIONMARK) { getNextToken(); expression(); if (token == TokenNameDDOT) { getNextToken(); expression(); } else { throwSyntaxError("':' expected in ternary operator '? :'."); } } } private void andExpression() throws CoreException { do { ternaryExpression(); if (token != TokenNameAMPERSAND) { 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 != TokenNameLINE) { return; } getNextToken(); } while (true); } private void booleanandExpression() throws CoreException { do { inclusiveorExpression(); if (token != TokenNameAND) { return; } getNextToken(); } while (true); } private void booleanorExpression() throws CoreException { do { booleanandExpression(); if (token != TokenNameOR) { 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 != TokenNameLISTCLOSE) { throwSyntaxError("'}' expected after indirect variable token '${'."); } getNextToken(); } else { if (token == TokenNameVARIABLE) { getNextToken(); if (token == TokenNamePARTOPEN) { getNextToken(); expression(); if (token != TokenNamePARTCLOSE) { throwSyntaxError("']' expected in variable-list."); } getNextToken(); } else if (token == TokenNameASSIGN) { 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 TokenNameADD : getNextToken(); switch (token) { case TokenNameDOUBLE_NUMBER : getNextToken(); break; case TokenNameINT_NUMBER : getNextToken(); break; default : throwSyntaxError("Constant expected after '+' presign."); } break; case TokenNameSUBTRACT : getNextToken(); switch (token) { case TokenNameDOUBLE_NUMBER : getNextToken(); break; case TokenNameINT_NUMBER : 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 == TokenNameARGOPEN) { getNextToken(); if (token != TokenNameARGCLOSE) { expressionList(); if (token != TokenNameARGCLOSE) { throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression."); } } getNextToken(); } break; case TokenNameSTRING_CONSTANT : getNextToken(); break; case TokenNameINTERPOLATED_STRING : getNextToken(); break; case TokenNameDOUBLE_NUMBER : getNextToken(); break; case TokenNameINT_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.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); } } } }