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