1 /**********************************************************************
2 Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Common Public License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/legal/cpl-v10.html
9 Klaus Hartlage - www.eclipseproject.de
10 **********************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.parser;
13 import java.text.MessageFormat;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Hashtable;
18 import net.sourceforge.phpdt.core.compiler.*;
19 import net.sourceforge.phpdt.internal.compiler.parser.*;
20 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
21 import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
22 import net.sourceforge.phpeclipse.phpeditor.PHPString;
23 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
25 import org.eclipse.core.resources.IFile;
26 import org.eclipse.core.resources.IMarker;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IPath;
29 import org.eclipse.jface.preference.IPreferenceStore;
30 import org.eclipse.ui.texteditor.MarkerUtilities;
32 public class Parser extends PHPKeywords implements ITerminalSymbols {
33 // strings for external parser call
34 private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
35 private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
37 public static final int ERROR = 2;
38 public static final int WARNING = 1;
39 public static final int INFO = 0;
41 public static final boolean DEBUG = false;
43 public Scanner scanner;
45 private IFile fileToParse;
46 private ArrayList phpList;
48 private int currentPHPString;
49 private boolean phpEnd;
51 private static HashMap keywordMap = null;
59 // row counter for syntax errors:
61 // column counter for syntax errors:
66 // // current identifier
72 private String stringValue;
74 /** Contains the current expression. */
75 // private StringBuffer expression;
77 private boolean phpMode;
79 // final static int TokenNameEOF = 0;
80 // final static int TokenNameERROR = 1;
81 // final static int TokenNameHTML = 2;
83 // final static int TokenNameREMAINDER = 30;
84 // final static int TokenNameNOT = 31;
85 // final static int TokenNameDOT = 32;
86 // final static int TokenNameXOR = 33;
87 // final static int TokenNameDIVIDE = 34;
88 // final static int TokenNameMULTIPLY = 35;
89 // final static int TokenNameMINUS = 36;
90 // final static int TokenNamePLUS = 37;
91 // final static int TokenNameEQUAL_EQUAL = 38;
92 // final static int TokenNameNOT_EQUAL = 39;
93 // final static int TokenNameGREATER = 40;
94 // final static int TokenNameGREATER_EQUAL = 41;
95 // final static int TokenNameLESS = 42;
96 // final static int TokenNameLESS_EQUAL = 43;
97 // final static int TokenNameAND_AND = 44;
98 // final static int TokenNameOR_OR = 45;
99 // // final static int TokenNameHASH = 46;
100 // final static int TokenNameCOLON = 47;
101 // final static int TokenNameDOT_EQUAL = 48;
103 // final static int TokenNameEQUAL = 49;
104 // final static int TokenNameMINUS_GREATER = 50; // ->
105 // final static int TokenNameFOREACH = 51;
106 // final static int TokenNameAND = 52;
107 // //final static int TokenNameDOLLARLISTOPEN = 53;
108 // final static int TokenNameTWIDDLE = 54;
109 // final static int TokenNameTWIDDLE_EQUAL = 55;
110 // final static int TokenNameREMAINDER_EQUAL = 56;
111 // final static int TokenNameXOR_EQUAL = 57;
112 // final static int TokenNameRIGHT_SHIFT_EQUAL = 58;
113 // final static int TokenNameLEFT_SHIFT_EQUAL = 59;
114 // final static int TokenNameAND_EQUAL = 60;
115 // final static int TokenNameOR_EQUAL = 61;
116 // final static int TokenNameQUESTION = 62;
117 // final static int TokenNameCOLON_COLON = 63;
118 // final static int TokenNameAT = 63;
119 // // final static int TokenNameHEREDOC = 64;
121 // final static int TokenNameDOLLAROPEN = 127;
122 // final static int TokenNameLPAREN = 128;
123 // final static int TokenNameRPAREN = 129;
124 // final static int TokenNameLBRACE = 130;
125 // final static int TokenNameRBRACE = 131;
126 // final static int TokenNameLBRACKET = 132;
127 // final static int TokenNameRBRACKET = 133;
128 // final static int TokenNameCOMMA = 134;
130 // final static int TokenNameStringLiteral = 136;
131 // final static int TokenNameIdentifier = 138;
132 // // final static int TokenNameDIGIT = 139;
133 // final static int TokenNameSEMICOLON = 140;
134 // // final static int TokenNameSLOT = 141;
135 // // final static int TokenNameSLOTSEQUENCE = 142;
136 // final static int TokenNameMINUS_MINUS = 144;
137 // final static int TokenNamePLUS_PLUS = 145;
138 // final static int TokenNamePLUS_EQUAL = 146;
139 // final static int TokenNameDIVIDE_EQUAL = 147;
140 // final static int TokenNameMINUS_EQUAL = 148;
141 // final static int TokenNameMULTIPLY_EQUAL = 149;
142 // final static int TokenNameVariable = 150;
143 // final static int TokenNameIntegerLiteral = 151;
144 // final static int TokenNameDoubleLiteral = 152;
145 // final static int TokenNameStringInterpolated = 153;
146 // final static int TokenNameStringConstant = 154;
148 // final static int TokenNameLEFT_SHIFT = 155;
149 // final static int TokenNameRIGHT_SHIFT = 156;
150 // final static int TokenNameEQUAL_EQUAL_EQUAL = 157;
151 // final static int TokenNameNOT_EQUAL_EQUAL = 158;
152 // final static int TokenNameOR = 159;
153 // final static int TokenNameAT = 153; // @
158 *@param sess Description of Parameter
161 public Parser(IFile fileToParse) {
162 if (keywordMap == null) {
163 keywordMap = new HashMap();
164 for (int i = 0; i < PHP_KEYWORS.length; i++) {
165 keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
168 this.currentPHPString = 0;
169 this.fileToParse = fileToParse;
172 this.token = TokenNameEOF;
174 // this.rowCount = 1;
175 // this.columnCount = 0;
179 this.initializeScanner();
182 public void initializeScanner() {
183 this.scanner = new Scanner(false, false, false, false);
186 * Create marker for the parse error
188 private void setMarker(
193 throws CoreException {
194 setMarker(fileToParse, message, charStart, charEnd, errorLevel);
197 public static void setMarker(
203 throws CoreException {
205 Hashtable attributes = new Hashtable();
206 MarkerUtilities.setMessage(attributes, message);
207 switch (errorLevel) {
209 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
214 new Integer(IMarker.SEVERITY_WARNING));
217 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
220 MarkerUtilities.setCharStart(attributes, charStart);
221 MarkerUtilities.setCharEnd(attributes, charEnd);
222 // setLineNumber(attributes, lineNumber);
223 MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
228 * This method will throw the SyntaxError.
229 * It will add the good lines and columns to the Error
230 * @param error the error message
231 * @throws SyntaxError the error raised
233 private void throwSyntaxError(String error) {
235 // if (str.length() < chIndx) {
238 // // read until end-of-line
240 // while (str.length() > eol) {
241 // ch = str.charAt(eol++);
247 // throw new SyntaxError(
249 // chIndx - columnCount + 1,
250 // str.substring(columnCount, eol),
252 throw new SyntaxError(
260 * This method will throw the SyntaxError.
261 * It will add the good lines and columns to the Error
262 * @param error the error message
263 * @throws SyntaxError the error raised
265 private void throwSyntaxError(String error, int startRow) {
266 throw new SyntaxError(startRow, 0, " ", error);
270 * Method Declaration.
274 // private void getChar() {
275 // if (str.length() > chIndx) {
276 // ch = str.charAt(chIndx++);
281 // chIndx = str.length() + 1;
283 // // token = TokenNameEOF;
288 * gets the next token from input
290 private void getNextToken() throws CoreException {
292 token = scanner.getNextToken();
294 int currentEndPosition = scanner.getCurrentTokenEndPosition();
295 int currentStartPosition = scanner.getCurrentTokenStartPosition();
298 currentStartPosition + "," + currentEndPosition + ": ");
299 System.out.println(scanner.toStringAction(token));
301 } catch (InvalidInputException e) {
302 token = TokenNameERROR;
306 // boolean phpFound = false;
313 // while (str.length() > chIndx) {
314 // token = TokenNameERROR;
315 // ch = str.charAt(chIndx++);
321 // ch2 = str.charAt(chIndx++);
323 // ch2 = str.charAt(chIndx++);
324 // if (Character.isWhitespace(ch2)) {
329 // } else if (ch2 == 'p' || ch2 == 'P') {
330 // ch2 = str.charAt(chIndx++);
331 // if (ch2 == 'h' || ch2 == 'H') {
332 // ch2 = str.charAt(chIndx++);
333 // if (ch2 == 'p' || ch2 == 'P') {
351 // while (str.length() > chIndx) {
352 // ch = str.charAt(chIndx++);
353 // token = TokenNameERROR;
356 // columnCount = chIndx;
357 // continue; // while loop
359 // if (str.length() == chIndx) {
362 // if (!Character.isWhitespace(ch)) {
364 // if (str.length() > chIndx) {
365 // if (str.charAt(chIndx) == '{') {
367 // token = TokenNameDOLLAROPEN;
374 // if ((ch >= 'a' && ch <= 'z')
375 // || (ch >= 'A' && ch <= 'Z')
381 // if (ch >= '0' && ch <= '9') {
386 // if (str.length() > chIndx) {
387 // if (str.charAt(chIndx) == '/') {
390 // // read comment until end of line:
391 // while ((str.length() > chIndx)
392 // && (ch != '\n')) {
393 // ch = str.charAt(chIndx++);
395 // ch2 = str.charAt(chIndx);
398 // token = TokenNameHTML;
409 // } else if (str.charAt(chIndx) == '*') {
411 // // multi line comment:
412 // while (str.length() > chIndx) {
413 // if (str.charAt(chIndx) == '*'
414 // && (str.length() > (chIndx + 1))
415 // && str.charAt(chIndx + 1) == '/') {
419 // ch = str.charAt(chIndx++);
422 // columnCount = chIndx;
428 // } else if (ch == '#') {
429 // // read comment until end of line:
430 // while ((str.length() > chIndx) && (ch != '\n')) {
431 // ch = str.charAt(chIndx++);
433 // ch2 = str.charAt(chIndx);
436 // token = TokenNameHTML;
447 // } else if (ch == '"') {
450 // TokenNameStringInterpolated,
451 // "Open string character '\"' at end of file.");
453 // } else if (ch == '\'') {
456 // TokenNameStringConstant,
457 // "Open string character \"'\" at end of file.");
459 // } else if (ch == '`') {
462 // TokenNameStringConstant,
463 // "Open string character \"`\" at end of file.");
465 // "Other string delimiters prefered (found \"`\").",
474 // token = TokenNameLPAREN;
478 // token = TokenNameRPAREN;
482 // token = TokenNameLBRACE;
486 // token = TokenNameRBRACE;
490 // token = TokenNameLBRACKET;
494 // token = TokenNameRBRACKET;
498 // token = TokenNameCOMMA;
502 // token = TokenNameQUESTION;
503 // if (str.length() > chIndx) {
504 // if (str.charAt(chIndx) == '>') {
506 // token = TokenNameHTML;
516 // token = TokenNameAT;
519 // token = TokenNameTWIDDLE;
520 // if (str.length() > chIndx) {
521 // if (str.charAt(chIndx) == '=') {
523 // token = TokenNameTWIDDLE_EQUAL;
530 // token = TokenNameDOT;
531 // if (str.length() > chIndx) {
532 // if (str.charAt(chIndx) == '=') {
534 // token = TokenNameDOT_EQUAL;
542 // token = TokenNameStringLiteral;
546 // token = TokenNameREMAINDER;
547 // if (str.length() > chIndx) {
548 // if (str.charAt(chIndx) == '=') {
550 // token = TokenNameREMAINDER_EQUAL;
557 // token = TokenNameSEMICOLON;
561 // token = TokenNameXOR;
562 // if (str.length() > chIndx) {
563 // if (str.charAt(chIndx) == '=') {
565 // token = TokenNameXOR_EQUAL;
572 // token = TokenNameDIVIDE;
574 // if (str.length() > chIndx) {
575 // if (str.charAt(chIndx) == '=') {
577 // token = TokenNameDIVIDE_EQUAL;
585 // token = TokenNameMULTIPLY;
586 // if (str.length() > chIndx) {
587 // if (str.charAt(chIndx) == '*') {
589 // token = TokenNameXOR;
593 // if (str.charAt(chIndx) == '=') {
595 // token = TokenNameMULTIPLY_EQUAL;
603 // token = TokenNamePLUS;
604 // if (str.length() > chIndx) {
605 // if (str.charAt(chIndx) == '+') {
607 // token = TokenNamePLUS_PLUS;
611 // if (str.charAt(chIndx) == '=') {
613 // token = TokenNamePLUS_EQUAL;
620 // token = TokenNameMINUS;
621 // if (str.length() > chIndx) {
622 // if (str.charAt(chIndx) == '-') {
624 // token = TokenNameMINUS_MINUS;
628 // if (str.charAt(chIndx) == '=') {
630 // token = TokenNameMINUS_EQUAL;
634 // if (str.charAt(chIndx) == '>') {
636 // token = TokenNameMINUS_GREATER;
644 // token = TokenNameEQUAL;
646 // if (str.length() > chIndx) {
647 // ch = str.charAt(chIndx);
651 // token = TokenNameEQUAL_EQUAL;
652 // if (str.length() > chIndx) {
653 // ch = str.charAt(chIndx);
658 // TokenNameEQUAL_EQUAL_EQUAL;
665 // token = TokenNameEQUAL_GREATER;
673 // token = TokenNameNOT;
675 // if (str.length() > chIndx) {
676 // if (str.charAt(chIndx) == '=') {
678 // token = TokenNameNOT_EQUAL;
679 // if (str.length() > chIndx) {
680 // ch = str.charAt(chIndx);
685 // TokenNameNOT_EQUAL_EQUAL;
694 // token = TokenNameGREATER;
696 // if (str.length() > chIndx) {
697 // if (str.charAt(chIndx) == '=') {
699 // token = TokenNameGREATER_EQUAL;
702 // if (str.charAt(chIndx) == '>') {
704 // token = TokenNameRIGHT_SHIFT;
705 // if (str.length() > chIndx) {
706 // if (str.charAt(chIndx) == '=') {
709 // TokenNameRIGHT_SHIFT_EQUAL;
719 // token = TokenNameLESS;
721 // if (str.length() > chIndx) {
722 // if (str.charAt(chIndx) == '=') {
724 // token = TokenNameLESS_EQUAL;
728 // if (str.charAt(chIndx) == '<') {
730 // token = TokenNameLEFT_SHIFT;
731 // if (str.charAt(chIndx) == '<') {
733 // int startRow = rowCount;
734 // if (str.length() > chIndx) {
736 // ch = str.charAt(++chIndx);
737 // if ((ch >= 'a' && ch <= 'z')
738 // || (ch >= 'A' && ch <= 'Z')
743 // TokenNameStringConstant;
744 // while (str.length()
760 // .equals(identifier)) {
772 // "Open heredoc syntax after operator '<<<'.",
774 // } else if (str.charAt(chIndx) == '=') {
776 // token = TokenNameLEFT_SHIFT_EQUAL;
786 // token = TokenNameOR;
788 // if (str.length() > chIndx) {
789 // if (str.charAt(chIndx) == '|') {
791 // token = TokenNameOR_OR;
794 // if (str.charAt(chIndx) == '=') {
796 // token = TokenNameOR_EQUAL;
803 // token = TokenNameAND;
804 // if (str.length() > chIndx) {
805 // if (str.charAt(chIndx) == '&') {
807 // token = TokenNameAND_AND;
810 // if (str.charAt(chIndx) == '=') {
812 // token = TokenNameAND_EQUAL;
820 // token = TokenNameCOLON;
821 // if (str.length() > chIndx) {
822 // if (str.charAt(chIndx) == ':') {
824 // token = TokenNameCOLON_COLON;
829 // // token = TokenNameHASH;
833 // // token = TokenNameAT;
838 // "unexpected character: '" + ch + "'");
841 // if (token == TokenNameERROR) {
842 // throwSyntaxError("token not found");
849 // } catch (StringIndexOutOfBoundsException e) {
850 // // catched from charAt
853 // chIndx = str.length() + 1;
855 // token = TokenNameEOF;
858 // // if (phpList != null) {
859 // // if (currentPHPString < phpList.size()) {
860 // // token = TokenNameUNDEFINED;
861 // // temp = (PHPString) phpList.get(currentPHPString++);
862 // // this.str = temp.getPHPString();
863 // // this.token = TokenNameEOF;
864 // // this.chIndx = 0;
865 // // this.rowCount = temp.getLineNumber();
866 // // this.columnCount = 0;
867 // // getNextToken();
870 // // token = TokenNameUNDEFINED;
877 // * Get an identifier.
879 // private void getIdentifier() {
880 // // StringBuffer ident = new StringBuffer();
881 // int startPosition = chIndx - 1;
882 // // ident.append(ch);
885 // // attention recursive call:
887 // token = TokenNameVariable;
890 // token = TokenNameIdentifier;
895 // //this will read the buffer until the next character is a forbidden character for identifier
896 // while ((ch >= 'a' && ch <= 'z')
897 // || (ch >= 'A' && ch <= 'Z')
898 // || (ch >= '0' && ch <= '9')
900 // // ident.append(ch);
903 // int endPosition = chIndx--;
904 // int length = (--endPosition) - startPosition;
906 // identifier = str.substring(startPosition, endPosition);
907 // // System.out.println(identifier);
909 // // determine if this identitfer is a keyword
910 // // @todo improve this in future version
911 // Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
913 // token = i.intValue();
919 * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
920 * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
921 * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
922 * value {@link Parser#TokenNameINT_NUMBER}
924 // private void getNumber() {
925 // StringBuffer inum = new StringBuffer();
927 // int numFormat = 10;
929 // // save first digit
930 // char firstCh = ch;
934 // // determine number conversions:
935 // if (firstCh == '0') {
964 // if (numFormat == 16) {
965 // while ((ch >= '0' && ch <= '9')
966 // || (ch >= 'a' && ch <= 'f')
967 // || (ch >= 'A' && ch <= 'F')) {
972 // while ((ch >= '0' && ch <= '9')
976 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
977 // if (ch == '.' && dFlag != ' ') {
980 // if ((dFlag == 'E') || (dFlag == 'e')) {
986 // if ((ch == '-') || (ch == '+')) {
999 // if (dFlag != ' ') {
1000 // doubleNumber = new Double(inum.toString());
1001 // token = TokenNameDoubleLiteral;
1004 // longNumber = Long.valueOf(inum.toString(), numFormat);
1005 // token = TokenNameIntegerLiteral;
1009 // } catch (Throwable e) {
1010 // throwSyntaxError("Number format error: " + inum.toString());
1016 // * @param openChar the opening char ('\'', '"', '`')
1017 // * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
1018 // * @param errorMsg the error message in case of parse error in the string
1020 // private void getString(
1021 // final char openChar,
1022 // final int typeString,
1023 // final String errorMsg) {
1024 // StringBuffer sBuffer = new StringBuffer();
1025 // boolean openString = true;
1026 // int startRow = rowCount;
1027 // while (str.length() > chIndx) {
1028 // ch = str.charAt(chIndx++);
1029 // if (ch == '\\') {
1030 // sBuffer.append(ch);
1031 // if (str.length() > chIndx) {
1032 // ch = str.charAt(chIndx++);
1033 // sBuffer.append(ch);
1035 // } else if (ch == openChar) {
1036 // openString = false;
1038 // } else if (ch == '\n') {
1040 // columnCount = chIndx;
1042 // sBuffer.append(ch);
1045 // if (openString) {
1046 // if (typeString == TokenNameStringConstant) {
1047 // throwSyntaxError(errorMsg, startRow);
1049 // throwSyntaxError(errorMsg);
1052 // token = typeString;
1053 // stringValue = sBuffer.toString();
1056 // public void htmlParserTester(String input) {
1057 // int lineNumber = 1;
1058 // int startLineNumber = 1;
1059 // int startIndex = 0;
1062 // boolean phpMode = false;
1063 // boolean phpFound = false;
1065 // phpList = new ArrayList();
1066 // currentPHPString = 0;
1070 // while (i < input.length()) {
1071 // ch = input.charAt(i++);
1072 // if (ch == '\n') {
1075 // if ((!phpMode) && ch == '<') {
1076 // ch2 = input.charAt(i++);
1077 // if (ch2 == '?') {
1078 // ch2 = input.charAt(i++);
1079 // if (Character.isWhitespace(ch2)) {
1084 // startLineNumber = lineNumber;
1086 // } else if (ch2 == 'p') {
1087 // ch2 = input.charAt(i++);
1088 // if (ch2 == 'h') {
1089 // ch2 = input.charAt(i++);
1090 // if (ch2 == 'p') {
1094 // startLineNumber = lineNumber;
1100 // } else if (ch2 == 'P') {
1101 // ch2 = input.charAt(i++);
1102 // if (ch2 == 'H') {
1103 // ch2 = input.charAt(i++);
1104 // if (ch2 == 'P') {
1108 // startLineNumber = lineNumber;
1121 // if (ch == '/' && i < input.length()) {
1122 // ch2 = input.charAt(i++);
1123 // if (ch2 == '/') {
1124 // while (i < input.length()) {
1125 // ch = input.charAt(i++);
1126 // if (ch == '?' && i < input.length()) {
1127 // ch2 = input.charAt(i++);
1128 // if (ch2 == '>') {
1136 // startLineNumber));
1140 // } else if (ch == '\n') {
1146 // } else if (ch2 == '*') {
1147 // // multi-line comment
1148 // while (i < input.length()) {
1149 // ch = input.charAt(i++);
1150 // if (ch == '\n') {
1152 // } else if (ch == '*' && i < input.length()) {
1153 // ch2 = input.charAt(i++);
1154 // if (ch2 == '/') {
1164 // } else if (ch == '#') {
1165 // while (i < input.length()) {
1166 // ch = input.charAt(i++);
1167 // if (ch == '?' && i < input.length()) {
1168 // ch2 = input.charAt(i++);
1169 // if (ch2 == '>') {
1174 // input.substring(startIndex, i - 2),
1175 // startLineNumber));
1179 // } else if (ch == '\n') {
1185 // } else if (ch == '"') {
1187 // while (i < input.length()) {
1188 // ch = input.charAt(i++);
1189 // if (ch == '\n') {
1192 // ch == '\\' && i < input.length()) { // escape
1194 // } else if (ch == '"') {
1199 // } else if (ch == '\'') {
1201 // while (i < input.length()) {
1202 // ch = input.charAt(i++);
1203 // if (ch == '\n') {
1206 // ch == '\\' && i < input.length()) { // escape
1208 // } else if (ch == '\'') {
1215 // if (ch == '?' && i < input.length()) {
1216 // ch2 = input.charAt(i++);
1217 // if (ch2 == '>') {
1222 // input.substring(startIndex, i - 2),
1223 // startLineNumber));
1233 // "No PHP source code found.",
1239 // "Open PHP tag at end of file.",
1244 // input.substring(startIndex, i - 2),
1245 // startLineNumber));
1247 // // for (int j=0;j<phpList.size();j++) {
1248 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
1249 // // int startIndx = temp.length()-10;
1250 // // if (startIndx<0) {
1251 // // startIndx = 0;
1253 // // System.out.println(temp.substring(startIndx)+"?>");
1255 // phpParserTester(null, 1);
1256 // // PHPString temp;
1257 // // for(int j=0;j<phpList.size();j++) {
1258 // // temp = (PHPString) phpList.get(j);
1259 // // parser.start(temp.getPHPString(), temp.getLineNumber());
1262 // } catch (CoreException e) {
1266 public void phpParserTester(String s, int rowCount) throws CoreException {
1269 if (phpList.size() != 0) {
1270 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
1273 this.token = TokenNameEOF;
1275 // this.rowCount = rowCount;
1276 // this.columnCount = 0;
1277 this.phpEnd = false;
1278 this.phpMode = true;
1279 scanner.setSource(s.toCharArray());
1280 scanner.setPHPMode(true);
1284 if (token != TokenNameEOF && token != TokenNameERROR) {
1287 if (token != TokenNameEOF && token != TokenNameERROR) {
1288 if (token == TokenNameRPAREN) {
1289 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1291 if (token == TokenNameRBRACE) {
1292 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1294 if (token == TokenNameRBRACKET) {
1295 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1298 if (token == TokenNameLPAREN) {
1299 throwSyntaxError("Read character '('; end-of-file not reached.");
1301 if (token == TokenNameLBRACE) {
1302 throwSyntaxError("Read character '{'; end-of-file not reached.");
1304 if (token == TokenNameLBRACKET) {
1305 throwSyntaxError("Read character '['; end-of-file not reached.");
1308 throwSyntaxError("End-of-file not reached.");
1311 } catch (SyntaxError err) {
1315 // setMarker(err.getMessage(), err.getLine(), ERROR);
1318 scanner.getCurrentTokenStartPosition(),
1319 scanner.getCurrentTokenEndPosition(),
1322 // if an error occured,
1323 // try to find keywords 'class' or 'function'
1324 // to parse the rest of the string
1325 while (token != TokenNameEOF && token != TokenNameERROR) {
1326 if (token == TokenNameclass || token == TokenNamefunction) {
1331 if (token == TokenNameEOF || token == TokenNameERROR) {
1340 * Parses a string with php tags
1341 * i.e. '<body> <?php phpinfo() ?> </body>'
1343 public void parse(String s) throws CoreException {
1345 this.token = TokenNameEOF;
1347 // this.rowCount = 1;
1348 // this.columnCount = 0;
1349 this.phpEnd = false;
1350 this.phpMode = false;
1351 /* scanner initialization */
1352 scanner.setSource(s.toCharArray());
1353 scanner.setPHPMode(false);
1357 if (token != TokenNameEOF && token != TokenNameERROR) {
1360 if (token != TokenNameEOF && token != TokenNameERROR) {
1361 if (token == TokenNameRPAREN) {
1362 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1364 if (token == TokenNameRBRACE) {
1365 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1367 if (token == TokenNameRBRACKET) {
1368 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1371 if (token == TokenNameLPAREN) {
1372 throwSyntaxError("Read character '('; end-of-file not reached.");
1374 if (token == TokenNameLBRACE) {
1375 throwSyntaxError("Read character '{'; end-of-file not reached.");
1377 if (token == TokenNameLBRACKET) {
1378 throwSyntaxError("Read character '['; end-of-file not reached.");
1381 throwSyntaxError("End-of-file not reached.");
1384 } catch (SyntaxError sytaxErr1) {
1385 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
1387 sytaxErr1.getMessage(),
1388 scanner.getCurrentTokenStartPosition(),
1389 scanner.getCurrentTokenEndPosition(),
1392 // if an error occured,
1393 // try to find keywords 'class' or 'function'
1394 // to parse the rest of the string
1395 while (token != TokenNameEOF && token != TokenNameERROR) {
1396 if (token == TokenNameclass || token == TokenNamefunction) {
1401 if (token == TokenNameEOF || token == TokenNameERROR) {
1404 } catch (SyntaxError sytaxErr2) {
1405 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
1407 sytaxErr2.getMessage(),
1408 scanner.getCurrentTokenStartPosition(),
1409 scanner.getCurrentTokenEndPosition(),
1418 public PHPOutlineInfo parseInfo(Object parent, String s) {
1419 PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
1420 // Stack stack = new Stack();
1421 // stack.push(outlineInfo.getDeclarations());
1424 this.token = TokenNameEOF;
1426 // this.rowCount = 1;
1427 // this.columnCount = 0;
1428 this.phpEnd = false;
1429 this.phpMode = false;
1430 scanner.setSource(s.toCharArray());
1431 scanner.setPHPMode(false);
1435 parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
1436 } catch (CoreException e) {
1441 private void parseDeclarations(
1442 PHPOutlineInfo outlineInfo,
1443 PHPSegmentWithChildren current,
1446 // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
1447 PHPSegmentWithChildren temp;
1450 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
1452 while (token != TokenNameEOF && token != TokenNameERROR) {
1453 if (token == TokenNameVariable) {
1454 ident = scanner.getCurrentIdentifierSource();
1455 outlineInfo.addVariable(new String(ident));
1457 } else if (token == TokenNamevar) {
1459 if (token == TokenNameVariable
1460 && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
1461 ident = scanner.getCurrentIdentifierSource();
1462 String variableName = new String(ident);
1463 outlineInfo.addVariable(variableName);
1465 if (token != TokenNameSEMICOLON) {
1468 ident = scanner.getCurrentTokenSource();
1469 if (token > TokenNameKEYWORD) {
1470 current.add(new PHPVarDeclaration(current, variableName,
1471 // chIndx - ident.length,
1472 scanner.getCurrentTokenStartPosition(), new String(ident)));
1475 case TokenNameVariable :
1476 current.add(new PHPVarDeclaration(current, variableName,
1477 // chIndx - ident.length,
1478 scanner.getCurrentTokenStartPosition(), new String(ident)));
1480 case TokenNameIdentifier :
1481 current.add(new PHPVarDeclaration(current, variableName,
1482 // chIndx - ident.length,
1483 scanner.getCurrentTokenStartPosition(), new String(ident)));
1485 case TokenNameDoubleLiteral :
1487 .add(new PHPVarDeclaration(
1489 variableName + doubleNumber,
1490 // chIndx - ident.length,
1491 scanner.getCurrentTokenStartPosition(), new String(ident)));
1493 case TokenNameIntegerLiteral :
1494 current.add(new PHPVarDeclaration(current, variableName,
1495 // chIndx - ident.length,
1496 scanner.getCurrentTokenStartPosition(), new String(ident)));
1498 case TokenNameStringInterpolated :
1499 case TokenNameStringLiteral :
1500 current.add(new PHPVarDeclaration(current, variableName,
1501 // chIndx - ident.length,
1502 scanner.getCurrentTokenStartPosition(), new String(ident)));
1504 case TokenNameStringConstant :
1505 current.add(new PHPVarDeclaration(current, variableName,
1506 // chIndx - ident.length,
1507 scanner.getCurrentTokenStartPosition(), new String(ident)));
1510 current.add(new PHPVarDeclaration(current, variableName,
1511 // chIndx - ident.length
1512 scanner.getCurrentTokenStartPosition()));
1518 ident = scanner.getCurrentIdentifierSource();
1520 current.add(new PHPVarDeclaration(current, variableName,
1521 // chIndx - ident.length
1522 scanner.getCurrentTokenStartPosition()));
1525 } else if (token == TokenNamefunction) {
1527 if (token == TokenNameAND) {
1530 if (token == TokenNameIdentifier
1531 && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
1532 ident = scanner.getCurrentIdentifierSource();
1533 outlineInfo.addVariable(new String(ident));
1534 temp = new PHPFunctionDeclaration(current, new String(ident),
1535 // chIndx - ident.length
1536 scanner.getCurrentTokenStartPosition());
1539 parseDeclarations(outlineInfo, temp, true);
1541 } else if (token == TokenNameclass) {
1543 if (token == TokenNameIdentifier
1544 && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
1545 ident = scanner.getCurrentIdentifierSource();
1546 outlineInfo.addVariable(new String(ident));
1547 temp = new PHPClassDeclaration(current, new String(ident),
1548 // chIndx - ident.len
1549 scanner.getCurrentTokenStartPosition());
1551 // stack.push(temp);
1554 //skip tokens for classname, extends and others until we have the opening '{'
1555 while (token != TokenNameLBRACE
1556 && token != TokenNameEOF
1557 && token != TokenNameERROR) {
1560 parseDeclarations(outlineInfo, temp, true);
1563 } else if (token == TokenNameLBRACE) {
1566 } else if (token == TokenNameRBRACE) {
1569 if (counter == 0 && goBack) {
1573 token == TokenNamerequire
1574 || token == TokenNamerequire_once
1575 || token == TokenNameinclude
1576 || token == TokenNameinclude_once) {
1577 ident = scanner.getCurrentTokenSource();
1580 int startPosition = scanner.getCurrentTokenStartPosition();
1582 char[] expr = scanner.getCurrentTokenSource(startPosition);
1583 outlineInfo.addVariable(new String(ident));
1584 current.add(new PHPReqIncDeclaration(current, new String(ident),
1585 // chIndx - ident.length,
1586 startPosition, new String(expr)));
1592 } catch (CoreException e) {
1593 } catch (SyntaxError sytaxErr) {
1595 // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
1597 sytaxErr.getMessage(),
1598 scanner.getCurrentTokenStartPosition(),
1599 scanner.getCurrentTokenEndPosition(),
1601 } catch (CoreException e) {
1606 private void statementList() throws CoreException {
1609 if ((token == TokenNameRBRACE)
1610 || (token == TokenNamecase)
1611 || (token == TokenNamedefault)
1612 || (token == TokenNameelseif)
1613 || (token == TokenNameendif)
1614 || (token == TokenNameendfor)
1615 || (token == TokenNameendforeach)
1616 || (token == TokenNameendwhile)
1617 || (token == TokenNameendswitch)
1618 || (token == TokenNameEOF)
1619 || (token == TokenNameERROR)) {
1625 private void compoundStatement() throws CoreException {
1626 // '{' [statement-list] '}'
1627 if (token == TokenNameLBRACE) {
1630 throwSyntaxError("'{' expected in compound-statement.");
1632 if (token != TokenNameRBRACE) {
1635 if (token == TokenNameRBRACE) {
1638 throwSyntaxError("'}' expected in compound-statement.");
1642 private void statement() throws CoreException {
1643 // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
1644 // char[] ident = scanner.getCurrentIdentifierSource();
1645 // String keyword = new String(ident);
1646 if (token == TokenNameinclude || token == TokenNameinclude_once) {
1649 if (token == TokenNameSEMICOLON) {
1652 if (token != TokenNameStopPHP) {
1653 throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1658 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1662 if (token == TokenNameSEMICOLON) {
1665 if (token != TokenNameStopPHP) {
1666 throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1671 } else if (token == TokenNameif) {
1673 if (token == TokenNameLPAREN) {
1676 throwSyntaxError("'(' expected after 'if' keyword.");
1679 if (token == TokenNameRPAREN) {
1682 throwSyntaxError("')' expected after 'if' condition.");
1687 } else if (token == TokenNameswitch) {
1689 if (token == TokenNameLPAREN) {
1692 throwSyntaxError("'(' expected after 'switch' keyword.");
1695 if (token == TokenNameRPAREN) {
1698 throwSyntaxError("')' expected after 'switch' condition.");
1702 } else if (token == TokenNamefor) {
1704 if (token == TokenNameLPAREN) {
1707 throwSyntaxError("'(' expected after 'for' keyword.");
1709 if (token == TokenNameSEMICOLON) {
1713 if (token == TokenNameSEMICOLON) {
1716 throwSyntaxError("';' expected after 'for'.");
1719 if (token == TokenNameSEMICOLON) {
1723 if (token == TokenNameSEMICOLON) {
1726 throwSyntaxError("';' expected after 'for'.");
1729 if (token == TokenNameRPAREN) {
1733 if (token == TokenNameRPAREN) {
1736 throwSyntaxError("')' expected after 'for'.");
1741 } else if (token == TokenNamewhile) {
1743 if (token == TokenNameLPAREN) {
1746 throwSyntaxError("'(' expected after 'while' keyword.");
1749 if (token == TokenNameRPAREN) {
1752 throwSyntaxError("')' expected after 'while' condition.");
1756 } else if (token == TokenNamedo) {
1758 if (token == TokenNameLBRACE) {
1761 throwSyntaxError("'{' expected after 'do' keyword.");
1763 if (token != TokenNameRBRACE) {
1766 if (token == TokenNameRBRACE) {
1769 throwSyntaxError("'}' expected after 'do' keyword.");
1771 if (token == TokenNamewhile) {
1773 if (token == TokenNameLPAREN) {
1776 throwSyntaxError("'(' expected after 'while' keyword.");
1779 if (token == TokenNameRPAREN) {
1782 throwSyntaxError("')' expected after 'while' condition.");
1785 throwSyntaxError("'while' expected after 'do' keyword.");
1787 if (token == TokenNameSEMICOLON) {
1790 if (token != TokenNameStopPHP) {
1791 throwSyntaxError("';' expected after do-while statement.");
1796 } else if (token == TokenNameforeach) {
1798 if (token == TokenNameLPAREN) {
1801 throwSyntaxError("'(' expected after 'foreach' keyword.");
1804 if (token == TokenNameas) {
1807 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1810 if (token == TokenNameEQUAL_GREATER) {
1814 if (token == TokenNameRPAREN) {
1817 throwSyntaxError("')' expected after 'foreach' expression.");
1823 token == TokenNamecontinue
1824 || token == TokenNamebreak
1825 || token == TokenNamereturn) {
1827 if (token != TokenNameSEMICOLON) {
1830 if (token == TokenNameSEMICOLON) {
1833 if (token != TokenNameStopPHP) {
1834 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1840 } else if (token == TokenNameecho) {
1843 if (token == TokenNameSEMICOLON) {
1846 if (token != TokenNameStopPHP) {
1847 throwSyntaxError("';' expected after 'echo' statement.");
1852 // } else if (token == TokenNameprint) {
1855 // if (token == TokenNameSEMICOLON) {
1858 // if (token != TokenNameStopPHP) {
1859 // throwSyntaxError("';' expected after 'print' statement.");
1865 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1868 if (token == TokenNameSEMICOLON) {
1871 if (token != TokenNameStopPHP) {
1872 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1878 // } else if (token == TokenNameunset) {
1880 // if (token == TokenNameARGOPEN) {
1883 // throwSyntaxError("'(' expected after 'unset' keyword.");
1886 // if (token == TokenNameARGCLOSE) {
1889 // throwSyntaxError("')' expected after 'unset' statement.");
1891 // if (token == TokenNameSEMICOLON) {
1894 // if (token != TokenNameStopPHP) {
1895 // throwSyntaxError("';' expected after 'unset' statement.");
1901 // } else if (token == TokenNameexit || token == TokenNamedie) {
1903 // if (token != TokenNameSEMICOLON) {
1906 // if (token == TokenNameSEMICOLON) {
1909 // if (token != TokenNameStopPHP) {
1910 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1916 } else if (token == TokenNamedefine) {
1918 if (token == TokenNameLPAREN) {
1921 throwSyntaxError("'(' expected after 'define' keyword.");
1924 if (token == TokenNameCOMMA) {
1927 throwSyntaxError("',' expected after first 'define' constant.");
1930 if (token == TokenNameCOMMA) {
1934 if (token == TokenNameRPAREN) {
1937 throwSyntaxError("')' expected after 'define' statement.");
1939 if (token == TokenNameSEMICOLON) {
1942 if (token != TokenNameStopPHP) {
1943 throwSyntaxError("';' expected after 'define' statement.");
1948 } else if (token == TokenNamefunction) {
1950 functionDefinition();
1952 } else if (token == TokenNameclass) {
1958 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1959 } else if (token == TokenNameLBRACE) {
1960 // compoundStatement
1962 if (token != TokenNameRBRACE) {
1965 if (token == TokenNameRBRACE) {
1969 throwSyntaxError("'}' expected.");
1972 if (token != TokenNameSEMICOLON) {
1975 if (token == TokenNameSEMICOLON) {
1979 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1981 "';' expected after expression (Found token: "
1982 + scanner.toStringAction(token)
1990 private void classDeclarator() throws CoreException {
1992 //identifier 'extends' identifier
1993 if (token == TokenNameIdentifier) {
1995 if (token == TokenNameextends) {
1997 if (token == TokenNameIdentifier) {
2000 throwSyntaxError("Class name expected after keyword 'extends'.");
2004 throwSyntaxError("Class name expected after keyword 'class'.");
2008 private void classBody() throws CoreException {
2009 //'{' [class-element-list] '}'
2010 if (token == TokenNameLBRACE) {
2012 if (token != TokenNameRBRACE) {
2015 if (token == TokenNameRBRACE) {
2018 throwSyntaxError("'}' expected at end of class body.");
2021 throwSyntaxError("'{' expected at start of class body.");
2025 private void classElementList() throws CoreException {
2028 } while (token == TokenNamefunction || token == TokenNamevar);
2031 private void classElement() throws CoreException {
2033 //function-definition
2034 if (token == TokenNamefunction) {
2036 functionDefinition();
2037 } else if (token == TokenNamevar) {
2041 throwSyntaxError("'function' or 'var' expected.");
2045 private void classProperty() throws CoreException {
2046 //'var' variable ';'
2047 //'var' variable '=' constant ';'
2049 if (token == TokenNameVariable) {
2051 if (token == TokenNameEQUAL) {
2056 throwSyntaxError("Variable expected after keyword 'var'.");
2058 if (token != TokenNameCOMMA) {
2063 if (token == TokenNameSEMICOLON) {
2066 throwSyntaxError("';' expected after variable declaration.");
2070 private void functionDefinition() throws CoreException {
2071 functionDeclarator();
2072 compoundStatement();
2075 private void functionDeclarator() throws CoreException {
2076 //identifier '(' [parameter-list] ')'
2077 if (token == TokenNameAND) {
2080 if (token == TokenNameIdentifier) {
2082 if (token == TokenNameLPAREN) {
2085 throwSyntaxError("'(' expected in function declaration.");
2087 if (token != TokenNameRPAREN) {
2090 if (token != TokenNameRPAREN) {
2091 throwSyntaxError("')' expected in function declaration.");
2098 private void parameterList() throws CoreException {
2099 //parameter-declaration
2100 //parameter-list ',' parameter-declaration
2102 parameterDeclaration();
2103 if (token != TokenNameCOMMA) {
2110 private void parameterDeclaration() throws CoreException {
2112 //variable-reference
2113 if (token == TokenNameAND) {
2115 if (token == TokenNameVariable) {
2118 throwSyntaxError("Variable expected after reference operator '&'.");
2121 //variable '=' constant
2122 if (token == TokenNameVariable) {
2124 if (token == TokenNameEQUAL) {
2132 private void labeledStatementList() throws CoreException {
2133 if (token != TokenNamecase && token != TokenNamedefault) {
2134 throwSyntaxError("'case' or 'default' expected.");
2137 if (token == TokenNamecase) {
2140 if (token == TokenNameCOLON) {
2142 if (token == TokenNamecase
2143 || token == TokenNamedefault) { // empty case statement ?
2147 } else if (token == TokenNameSEMICOLON) {
2149 // "':' expected after 'case' keyword (Found token: "
2150 // + scanner.toStringAction(token)
2155 "':' expected after 'case' keyword (Found token: "
2156 + scanner.toStringAction(token)
2158 scanner.getCurrentTokenStartPosition(),
2159 scanner.getCurrentTokenEndPosition(),
2162 if (token == TokenNamecase) { // empty case statement ?
2168 "':' character after 'case' constant expected (Found token: "
2169 + scanner.toStringAction(token)
2172 } else { // TokenNamedefault
2174 if (token == TokenNameCOLON) {
2178 throwSyntaxError("':' character after 'default' expected.");
2181 } while (token == TokenNamecase || token == TokenNamedefault);
2184 // public void labeledStatement() {
2185 // if (token == TokenNamecase) {
2188 // if (token == TokenNameDDOT) {
2192 // throwSyntaxError("':' character after 'case' constant expected.");
2195 // } else if (token == TokenNamedefault) {
2197 // if (token == TokenNameDDOT) {
2201 // throwSyntaxError("':' character after 'default' expected.");
2207 // public void expressionStatement() {
2210 // private void inclusionStatement() {
2213 // public void compoundStatement() {
2216 // public void selectionStatement() {
2219 // public void iterationStatement() {
2222 // public void jumpStatement() {
2225 // public void outputStatement() {
2228 // public void scopeStatement() {
2231 // public void flowStatement() {
2234 // public void definitionStatement() {
2237 private void ifStatement() throws CoreException {
2238 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
2239 if (token == TokenNameCOLON) {
2243 case TokenNameelse :
2245 if (token == TokenNameCOLON) {
2249 if (token == TokenNameif) { //'else if'
2251 elseifStatementList();
2253 throwSyntaxError("':' expected after 'else'.");
2257 case TokenNameelseif :
2259 elseifStatementList();
2263 if (token != TokenNameendif) {
2264 throwSyntaxError("'endif' expected.");
2267 if (token != TokenNameSEMICOLON) {
2268 throwSyntaxError("';' expected after if-statement.");
2272 // statement [else-statement]
2274 if (token == TokenNameelseif) {
2276 if (token == TokenNameLPAREN) {
2279 throwSyntaxError("'(' expected after 'elseif' keyword.");
2282 if (token == TokenNameRPAREN) {
2285 throwSyntaxError("')' expected after 'elseif' condition.");
2288 } else if (token == TokenNameelse) {
2295 private void elseifStatementList() throws CoreException {
2299 case TokenNameelse :
2301 if (token == TokenNameCOLON) {
2306 if (token == TokenNameif) { //'else if'
2309 throwSyntaxError("':' expected after 'else'.");
2313 case TokenNameelseif :
2322 private void elseifStatement() throws CoreException {
2323 if (token == TokenNameLPAREN) {
2326 if (token != TokenNameLPAREN) {
2327 throwSyntaxError("')' expected in else-if-statement.");
2330 if (token != TokenNameCOLON) {
2331 throwSyntaxError("':' expected in else-if-statement.");
2338 private void switchStatement() throws CoreException {
2339 if (token == TokenNameCOLON) {
2340 // ':' [labeled-statement-list] 'endswitch' ';'
2342 labeledStatementList();
2343 if (token != TokenNameendswitch) {
2344 throwSyntaxError("'endswitch' expected.");
2347 if (token != TokenNameSEMICOLON) {
2348 throwSyntaxError("';' expected after switch-statement.");
2352 // '{' [labeled-statement-list] '}'
2353 if (token != TokenNameLBRACE) {
2354 throwSyntaxError("'{' expected in switch statement.");
2357 if (token != TokenNameRBRACE) {
2358 labeledStatementList();
2360 if (token != TokenNameRBRACE) {
2361 throwSyntaxError("'}' expected in switch statement.");
2368 private void forStatement() throws CoreException {
2369 if (token == TokenNameCOLON) {
2372 if (token != TokenNameendfor) {
2373 throwSyntaxError("'endfor' expected.");
2376 if (token != TokenNameSEMICOLON) {
2377 throwSyntaxError("';' expected after for-statement.");
2385 private void whileStatement() throws CoreException {
2386 // ':' statement-list 'endwhile' ';'
2387 if (token == TokenNameCOLON) {
2390 if (token != TokenNameendwhile) {
2391 throwSyntaxError("'endwhile' expected.");
2394 if (token != TokenNameSEMICOLON) {
2395 throwSyntaxError("';' expected after while-statement.");
2403 private void foreachStatement() throws CoreException {
2404 if (token == TokenNameCOLON) {
2407 if (token != TokenNameendforeach) {
2408 throwSyntaxError("'endforeach' expected.");
2411 if (token != TokenNameSEMICOLON) {
2412 throwSyntaxError("';' expected after foreach-statement.");
2420 private void exitStatus() throws CoreException {
2421 if (token == TokenNameLPAREN) {
2424 throwSyntaxError("'(' expected in 'exit-status'.");
2426 if (token != TokenNameRPAREN) {
2429 if (token == TokenNameRPAREN) {
2432 throwSyntaxError("')' expected after 'exit-status'.");
2436 private void expressionList() throws CoreException {
2439 if (token == TokenNameCOMMA) {
2447 private void expression() throws CoreException {
2448 //todo: find a better way to get the expression
2449 // expression = new StringBuffer();
2450 // for (int i = chIndx; i < str.length(); i++) {
2451 // if (str.charAt(i) == ';') {
2454 // expression.append(str.charAt(i));
2457 // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
2460 logicalinclusiveorExpression();
2461 // while (token != TokenNameSEMICOLON) {
2467 private void postfixExpression() throws CoreException {
2470 boolean castFlag = false;
2476 case TokenNamenull :
2479 case TokenNamefalse :
2482 case TokenNametrue :
2485 case TokenNameStringConstant :
2488 case TokenNameHEREDOC :
2489 case TokenNameStringInterpolated :
2490 case TokenNameStringLiteral :
2493 case TokenNameLPAREN :
2495 if (token == TokenNameIdentifier) {
2496 // check if identifier is a type:
2497 // ident = identifier;
2498 ident = scanner.getCurrentIdentifierSource();
2499 String str = new String(ident).toLowerCase();
2500 for (int i = 0; i < PHP_TYPES.length; i++) {
2501 if (PHP_TYPES[i].equals(str)) {
2508 if (token != TokenNameRPAREN) {
2509 throwSyntaxError(") expected after cast-type '" + str + "'.");
2519 if (token != TokenNameRPAREN) {
2520 throwSyntaxError(") expected in postfix-expression.");
2524 case TokenNameDoubleLiteral :
2527 case TokenNameIntegerLiteral :
2530 case TokenNameDOLLAR_LBRACE :
2533 if (token != TokenNameRBRACE) {
2534 throwSyntaxError("'}' expected after indirect variable token '${'.");
2538 case TokenNameVariable :
2539 ident = scanner.getCurrentIdentifierSource();
2541 if (token == TokenNameLBRACE) {
2544 if (token != TokenNameRBRACE) {
2546 "'}' expected after variable '"
2548 + "' in variable-expression.");
2551 } else if (token == TokenNameLPAREN) {
2553 if (token != TokenNameRPAREN) {
2555 if (token != TokenNameRPAREN) {
2557 "')' expected after variable '"
2559 + "' in postfix-expression.");
2565 case TokenNameIdentifier :
2566 ident = scanner.getCurrentIdentifierSource();
2568 if (token == TokenNameLPAREN) {
2570 if (token != TokenNameRPAREN) {
2572 if (token != TokenNameRPAREN) {
2574 "')' expected after identifier '"
2576 + "' in postfix-expression."
2578 + scanner.toStringAction(token)
2585 case TokenNameprint :
2588 // if (token == TokenNameSEMICOLON) {
2591 // if (token != TokenNameStopPHP) {
2592 // throwSyntaxError("';' expected after 'print' statement.");
2597 case TokenNamelist :
2599 if (token == TokenNameLPAREN) {
2601 if (token == TokenNameCOMMA) {
2605 if (token != TokenNameRPAREN) {
2606 throwSyntaxError("')' expected after 'list' keyword.");
2609 // if (token == TokenNameSET) {
2611 // logicalinclusiveorExpression();
2614 throwSyntaxError("'(' expected after 'list' keyword.");
2617 // case TokenNameexit :
2619 // if (token != TokenNameSEMICOLON) {
2622 // if (token == TokenNameSEMICOLON) {
2625 // if (token != TokenNameStopPHP) {
2626 // throwSyntaxError("';' expected after 'exit' expression.");
2631 // case TokenNamedie :
2633 // if (token != TokenNameSEMICOLON) {
2636 // if (token == TokenNameSEMICOLON) {
2639 // if (token != TokenNameStopPHP) {
2640 // throwSyntaxError("';' expected after 'die' expression.");
2645 // case TokenNamearray :
2647 // if (token == TokenNameARGOPEN) {
2649 // if (token == TokenNameCOMMA) {
2652 // expressionList();
2653 // if (token != TokenNameARGCLOSE) {
2654 // throwSyntaxError("')' expected after 'list' keyword.");
2657 // if (token == TokenNameSET) {
2659 // logicalinclusiveorExpression();
2662 // throwSyntaxError("'(' expected after 'list' keyword.");
2666 boolean while_flag = true;
2669 case TokenNameLBRACKET :
2672 if (token != TokenNameRBRACKET) {
2673 throwSyntaxError("] expected in postfix-expression.");
2677 case TokenNameCOLON_COLON : // ::
2678 case TokenNameMINUS_GREATER : // ->
2680 if (token > TokenNameKEYWORD) {
2681 ident = scanner.getCurrentIdentifierSource();
2683 // "Avoid using keyword '"
2684 // + new String(ident)
2685 // + "' as variable name.",
2689 "Avoid using keyword '"
2691 + "' as variable name.",
2692 scanner.getCurrentTokenStartPosition(),
2693 scanner.getCurrentTokenEndPosition(),
2697 case TokenNameVariable :
2698 ident = scanner.getCurrentIdentifierSource();
2700 // if (token == TokenNameARGOPEN) {
2702 // expressionList();
2703 // if (token != TokenNameARGCLOSE) {
2704 // throwSyntaxError(") expected after variable '" + ident + "'.");
2709 case TokenNameIdentifier :
2710 //ident = scanner.getCurrentIdentifierSource();
2713 case TokenNameLBRACE :
2716 if (token != TokenNameRBRACE) {
2717 throwSyntaxError("} expected in postfix-expression.");
2722 throwSyntaxError("Syntax error after '->' token.");
2724 token == TokenNameLBRACKET
2725 || token == TokenNameLPAREN
2726 || token == TokenNameLBRACE) {
2727 if (token == TokenNameLBRACKET) {
2730 if (token != TokenNameRBRACKET) {
2731 throwSyntaxError("] expected after '->'.");
2735 if (token == TokenNameLPAREN) {
2738 if (token != TokenNameRPAREN) {
2739 throwSyntaxError(") expected after '->'.");
2743 if (token == TokenNameLBRACE) {
2746 if (token != TokenNameRBRACE) {
2747 throwSyntaxError("} expected after '->'.");
2753 case TokenNamePLUS_PLUS :
2756 case TokenNameMINUS_MINUS :
2767 private void unaryExpression() throws CoreException {
2769 case TokenNamePLUS_PLUS :
2773 case TokenNameMINUS_MINUS :
2777 // '@' '&' '*' '+' '-' '~' '!'
2786 case TokenNameMULTIPLY :
2790 case TokenNamePLUS :
2794 case TokenNameMINUS :
2798 case TokenNameTWIDDLE :
2807 postfixExpression();
2811 private void castExpression() throws CoreException {
2812 // if (token == TokenNameARGOPEN) {
2815 // if (token != TokenNameARGCLOSE) {
2816 // throwSyntaxError(") expected after cast-expression.");
2823 private void typeName() throws CoreException {
2824 //'string' 'unset' 'array' 'object'
2826 //'real' 'double' 'float'
2828 String identifier = "";
2829 if (token == TokenNameIdentifier) {
2830 char[] ident = scanner.getCurrentIdentifierSource();
2831 identifier = new String(ident);
2832 String str = identifier.toLowerCase();
2834 for (int i = 0; i < PHP_TYPES.length; i++) {
2835 if (PHP_TYPES[i].equals(str)) {
2841 "Expected type cast '( <type-name> )'; Got '" + identifier + "'.");
2844 private void assignExpression() throws CoreException {
2846 if (token == TokenNameEQUAL) { // =
2848 logicalinclusiveorExpression();
2849 } else if (token == TokenNameDOT_EQUAL) { // .=
2851 logicalinclusiveorExpression();
2852 } else if (token == TokenNameEQUAL_GREATER) { // =>
2854 logicalinclusiveorExpression();
2855 } else if (token == TokenNamePLUS_EQUAL) { // +=
2857 logicalinclusiveorExpression();
2858 } else if (token == TokenNameMINUS_EQUAL) { // -=
2860 logicalinclusiveorExpression();
2861 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2863 logicalinclusiveorExpression();
2864 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2866 logicalinclusiveorExpression();
2867 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2869 logicalinclusiveorExpression();
2870 } else if (token == TokenNameAND_EQUAL) { // &=
2872 logicalinclusiveorExpression();
2873 } else if (token == TokenNameOR_EQUAL) { // |=
2875 logicalinclusiveorExpression();
2876 } else if (token == TokenNameXOR_EQUAL) { // ^=
2878 logicalinclusiveorExpression();
2879 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2881 logicalinclusiveorExpression();
2882 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2884 logicalinclusiveorExpression();
2885 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2887 logicalinclusiveorExpression();
2891 private void multiplicativeExpression() throws CoreException {
2894 if (token != TokenNameMULTIPLY
2895 && token != TokenNameDIVIDE
2896 && token != TokenNameREMAINDER) {
2903 private void concatenationExpression() throws CoreException {
2905 multiplicativeExpression();
2906 if (token != TokenNameDOT) {
2913 private void additiveExpression() throws CoreException {
2915 concatenationExpression();
2916 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2923 private void shiftExpression() throws CoreException {
2925 additiveExpression();
2926 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2933 private void relationalExpression() throws CoreException {
2936 if (token != TokenNameLESS
2937 && token != TokenNameGREATER
2938 && token != TokenNameLESS_EQUAL
2939 && token != TokenNameGREATER_EQUAL) {
2946 private void identicalExpression() throws CoreException {
2948 relationalExpression();
2949 if (token != TokenNameEQUAL_EQUAL_EQUAL
2950 && token != TokenNameNOT_EQUAL_EQUAL) {
2957 private void equalityExpression() throws CoreException {
2959 identicalExpression();
2960 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2967 private void ternaryExpression() throws CoreException {
2968 equalityExpression();
2969 if (token == TokenNameQUESTION) {
2972 if (token == TokenNameCOLON) {
2976 throwSyntaxError("':' expected in ternary operator '? :'.");
2981 private void andExpression() throws CoreException {
2983 ternaryExpression();
2984 if (token != TokenNameAND) {
2991 private void exclusiveorExpression() throws CoreException {
2994 if (token != TokenNameXOR) {
3001 private void inclusiveorExpression() throws CoreException {
3003 exclusiveorExpression();
3004 if (token != TokenNameOR) {
3011 private void booleanandExpression() throws CoreException {
3013 inclusiveorExpression();
3014 if (token != TokenNameAND_AND) {
3021 private void booleanorExpression() throws CoreException {
3023 booleanandExpression();
3024 if (token != TokenNameOR_OR) {
3031 private void logicalandExpression() throws CoreException {
3033 booleanorExpression();
3034 if (token != TokenNameAND) {
3041 private void logicalexclusiveorExpression() throws CoreException {
3043 logicalandExpression();
3044 if (token != TokenNameXOR) {
3051 private void logicalinclusiveorExpression() throws CoreException {
3053 logicalexclusiveorExpression();
3054 if (token != TokenNameOR) {
3061 // public void assignmentExpression() {
3062 // if (token == TokenNameVARIABLE) {
3064 // if (token == TokenNameSET) {
3066 // logicalinclusiveorExpression();
3069 // logicalinclusiveorExpression();
3073 private void variableList() throws CoreException {
3076 if (token == TokenNameCOMMA) {
3084 private void variable() throws CoreException {
3085 if (token == TokenNameDOLLAR_LBRACE) {
3089 if (token != TokenNameRBRACE) {
3090 throwSyntaxError("'}' expected after indirect variable token '${'.");
3094 if (token == TokenNameVariable) {
3096 if (token == TokenNameLBRACKET) {
3099 if (token != TokenNameRBRACKET) {
3100 throwSyntaxError("']' expected in variable-list.");
3103 } else if (token == TokenNameEQUAL) {
3108 throwSyntaxError("$-variable expected in variable-list.");
3114 * It will look for a value (after a '=' for example)
3115 * @throws CoreException
3117 private void constant() throws CoreException {
3120 case TokenNamePLUS :
3123 case TokenNameDoubleLiteral :
3126 case TokenNameIntegerLiteral :
3130 throwSyntaxError("Constant expected after '+' presign.");
3133 case TokenNameMINUS :
3136 case TokenNameDoubleLiteral :
3139 case TokenNameIntegerLiteral :
3143 throwSyntaxError("Constant expected after '-' presign.");
3146 case TokenNamenull :
3149 case TokenNamefalse :
3152 case TokenNametrue :
3155 case TokenNameIdentifier :
3156 // ident = identifier;
3157 char[] ident = scanner.getCurrentIdentifierSource();
3159 if (token == TokenNameLPAREN) {
3161 if (token != TokenNameRPAREN) {
3163 if (token != TokenNameRPAREN) {
3165 "')' expected after identifier '"
3167 + "' in postfix-expression.");
3173 case TokenNameStringLiteral :
3176 case TokenNameStringConstant :
3179 case TokenNameStringInterpolated :
3182 case TokenNameDoubleLiteral :
3185 case TokenNameIntegerLiteral :
3189 throwSyntaxError("Constant expected.");
3194 * Call the php parse command ( php -l -f <filename> )
3195 * and create markers according to the external parser output
3197 public static void phpExternalParse(IFile file) {
3198 //IFile file = (IFile) resource;
3199 IPath path = file.getFullPath();
3200 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
3201 String filename = file.getLocation().toString();
3203 String[] arguments = { filename };
3204 MessageFormat form =
3205 new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
3206 String command = form.format(arguments);
3208 String parserResult =
3209 PHPStartApacheAction.getParserOutput(command, "External parser: ");
3212 // parse the buffer to find the errors and warnings
3213 createMarkers(parserResult, file);
3214 } catch (CoreException e) {
3219 * Create markers according to the external parser output
3221 private static void createMarkers(String output, IFile file)
3222 throws CoreException {
3223 // delete all markers
3224 file.deleteMarkers(IMarker.PROBLEM, false, 0);
3228 boolean flag = true;
3229 while ((brIndx = output.indexOf("<br />", indx)) != -1) {
3230 // newer php error output (tested with 4.2.3)
3231 scanLine(output, file, indx, brIndx);
3236 while ((brIndx = output.indexOf("<br>", indx)) != -1) {
3237 // older php error output (tested with 4.2.3)
3238 scanLine(output, file, indx, brIndx);
3244 private static void scanLine(String output, IFile file, int indx, int brIndx)
3245 throws CoreException {
3247 String outLineNumberString;
3248 StringBuffer lineNumberBuffer = new StringBuffer(10);
3250 current = output.substring(indx, brIndx);
3252 if (current.indexOf(PARSE_WARNING_STRING) != -1
3253 || current.indexOf(PARSE_ERROR_STRING) != -1) {
3254 int onLine = current.indexOf("on line <b>");
3256 lineNumberBuffer.delete(0, lineNumberBuffer.length());
3257 for (int i = onLine; i < current.length(); i++) {
3258 ch = current.charAt(i);
3259 if ('0' <= ch && '9' >= ch) {
3260 lineNumberBuffer.append(ch);
3264 int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
3266 Hashtable attributes = new Hashtable();
3268 current = current.replaceAll("\n", "");
3269 current = current.replaceAll("<b>", "");
3270 current = current.replaceAll("</b>", "");
3271 MarkerUtilities.setMessage(attributes, current);
3273 if (current.indexOf(PARSE_ERROR_STRING) != -1)
3274 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
3275 else if (current.indexOf(PARSE_WARNING_STRING) != -1)
3278 new Integer(IMarker.SEVERITY_WARNING));
3280 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
3281 MarkerUtilities.setLineNumber(attributes, lineNumber);
3282 MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);