X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java index 91620bc..7da9027 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java @@ -10,17 +10,25 @@ Contributors: **********************************************************************/ package net.sourceforge.phpeclipse.phpeditor; +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.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; @@ -90,6 +98,7 @@ public class PHPParser extends PHPKeywords { 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; @@ -194,6 +203,11 @@ public class PHPParser extends PHPKeywords { 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. * @@ -306,6 +320,7 @@ public class PHPParser extends PHPKeywords { } else if (ch == '\'') { // read string until end boolean openString = true; + int startRow = rowCount; while (str.length() > chIndx) { ch = str.charAt(chIndx++); if (ch == '\\') { @@ -321,13 +336,14 @@ public class PHPParser extends PHPKeywords { } } if (openString) { - throwSyntaxError("Open string character \"'\" at end of file."); + 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 == '\\') { @@ -343,7 +359,7 @@ public class PHPParser extends PHPKeywords { } } if (openString) { - throwSyntaxError("Open string character \"`\" at end of file."); + throwSyntaxError("Open string character \"`\" at end of file.", startRow); } setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO); token = TT_STRING_CONSTANT; @@ -596,12 +612,34 @@ public class PHPParser extends PHPKeywords { if (str.charAt(chIndx) == '<') { chIndx++; token = TT_LSHIFT; - if (str.length() > chIndx) { - if (str.charAt(chIndx) == '=') { - chIndx++; - token = TT_LSHIFTASSIGN; - break; + 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; } @@ -1274,17 +1312,17 @@ public class PHPParser extends PHPKeywords { } } return; - } else if (token == TT_print) { - getNextToken(); - expression(); - if (token == TT_SEMICOLON) { - getNextToken(); - } else { - if (!phpEnd) { - throwSyntaxError("';' expected after 'print' statement."); - } - } - return; + // } else if (token == TT_print) { + // getNextToken(); + // expression(); + // if (token == TT_SEMICOLON) { + // getNextToken(); + // } else { + // if (!phpEnd) { + // throwSyntaxError("';' expected after 'print' statement."); + // } + // } + // return; } else if (token == TT_global || token == TT_static) { getNextToken(); @@ -1957,6 +1995,17 @@ public class PHPParser extends PHPKeywords { getNextToken(); } break; + case TT_print : + getNextToken(); + expression(); + // if (token == TT_SEMICOLON) { + // getNextToken(); + // } else { + // if (!phpEnd) { + // throwSyntaxError("';' expected after 'print' statement."); + // } + // } + break; case TT_list : getNextToken(); if (token == TT_ARGOPEN) { @@ -2507,5 +2556,91 @@ public class PHPParser extends PHPKeywords { 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); + } + } + } } \ No newline at end of file