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.phpeclipse.phpeditor.phpparser;
13 import java.text.MessageFormat;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Hashtable;
18 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
19 import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
20 import net.sourceforge.phpeclipse.phpeditor.PHPString;
21 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
22 import org.eclipse.core.resources.IFile;
23 import org.eclipse.core.resources.IMarker;
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.core.runtime.IPath;
26 import org.eclipse.jface.preference.IPreferenceStore;
27 import org.eclipse.ui.texteditor.MarkerUtilities;
29 public class PHPParser extends PHPKeywords {
30 // strings for external parser call
31 private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
32 private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
34 public static final int ERROR = 2;
35 public static final int WARNING = 1;
36 public static final int INFO = 0;
37 private IFile fileToParse;
38 private ArrayList phpList;
40 private int currentPHPString;
41 private boolean phpEnd;
43 private static HashMap keywordMap = null;
51 // row counter for syntax errors:
53 // column counter for syntax errors:
63 private boolean phpMode;
65 final static int TT_EOF = 0;
66 final static int TT_UNDEFINED = 1;
67 final static int TT_HTML = 2;
69 final static int TT_MOD = 30;
70 final static int TT_NOT = 31;
71 final static int TT_DOT = 32;
72 final static int TT_POW = 33;
73 final static int TT_DIV = 34;
74 final static int TT_MULTIPLY = 35;
75 final static int TT_SUBTRACT = 36;
76 final static int TT_ADD = 37;
77 final static int TT_EQUAL = 38;
78 final static int TT_UNEQUAL = 39;
79 final static int TT_GREATER = 40;
80 final static int TT_GREATEREQUAL = 41;
81 final static int TT_LESS = 42;
82 final static int TT_LESSEQUAL = 43;
83 final static int TT_AND = 44;
84 final static int TT_OR = 45;
85 final static int TT_HASH = 46;
86 final static int TT_DDOT = 47;
87 final static int TT_DOTASSIGN = 48;
89 final static int TT_ASSIGN = 49;
90 final static int TT_REF = 50;
91 final static int TT_FOREACH = 51;
92 final static int TT_AMPERSAND = 52;
93 final static int TT_DOLLARLISTOPEN = 53;
94 final static int TT_TILDE = 54;
95 final static int TT_TILDEASSIGN = 55;
96 final static int TT_MODASSIGN = 56;
97 final static int TT_POWASSIGN = 57;
98 final static int TT_RSHIFTASSIGN = 58;
99 final static int TT_LSHIFTASSIGN = 59;
100 final static int TT_ANDASSIGN = 60;
101 final static int TT_QUESTIONMARK = 61;
102 final static int TT_DDOT2 = 62;
103 final static int TT_AT = 63;
104 // final static int TT_HEREDOC = 64;
106 final static int TT_DOLLAROPEN = 127;
107 final static int TT_ARGOPEN = 128;
108 final static int TT_ARGCLOSE = 129;
109 final static int TT_LISTOPEN = 130;
110 final static int TT_LISTCLOSE = 131;
111 final static int TT_PARTOPEN = 132;
112 final static int TT_PARTCLOSE = 133;
113 final static int TT_COMMA = 134;
115 final static int TT_STRING = 136;
116 final static int TT_IDENTIFIER = 138;
117 final static int TT_DIGIT = 139;
118 final static int TT_SEMICOLON = 140;
119 final static int TT_SLOT = 141;
120 final static int TT_SLOTSEQUENCE = 142;
121 final static int TT_DECREMENT = 144;
122 final static int TT_INCREMENT = 145;
123 final static int TT_ADDTO = 146;
124 final static int TT_DIVIDEBY = 147;
125 final static int TT_SUBTRACTFROM = 148;
126 final static int TT_TIMESBY = 149;
127 final static int TT_VARIABLE = 150;
128 final static int TT_INT_NUMBER = 151;
129 final static int TT_DOUBLE_NUMBER = 152;
130 final static int TT_INTERPOLATED_STRING = 153;
131 final static int TT_STRING_CONSTANT = 154;
133 final static int TT_LSHIFT = 155;
134 final static int TT_RSHIFT = 156;
135 final static int TT_EX_EQUAL = 157;
136 final static int TT_EX_UNEQUAL = 158;
137 final static int TT_LINE = 159;
138 // final static int TT_AT = 153; // @
143 *@param sess Description of Parameter
146 public PHPParser(IFile fileToParse) {
147 if (keywordMap == null) {
148 keywordMap = new HashMap();
149 for (int i = 0; i < PHP_KEYWORS.length; i++) {
150 keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
153 this.currentPHPString = 0;
154 this.fileToParse = fileToParse;
160 this.columnCount = 0;
167 * Create marker for the parse error
169 private void setMarker(String message, int lineNumber, int errorLevel) throws CoreException {
170 setMarker(fileToParse, message, lineNumber, errorLevel);
173 public static void setMarker(IFile file, String message, int lineNumber, int errorLevel) throws CoreException {
175 Hashtable attributes = new Hashtable();
176 MarkerUtilities.setMessage(attributes, message);
177 switch (errorLevel) {
179 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
182 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
185 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
188 MarkerUtilities.setLineNumber(attributes, lineNumber);
189 MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
192 private void throwSyntaxError(String error) {
194 if (str.length() < chIndx) {
197 // read until end-of-line
199 while (str.length() > eol) {
200 ch = str.charAt(eol++);
206 throw new SyntaxError(rowCount, chIndx - columnCount + 1, str.substring(columnCount, eol), error);
209 private void throwSyntaxError(String error, int startRow) {
211 throw new SyntaxError(startRow, 0, " ", error);
215 * Method Declaration.
219 private void getChar() {
220 if (str.length() > chIndx) {
221 ch = str.charAt(chIndx++);
226 chIndx = str.length() + 1;
232 private void getNextToken_OldVersion() throws CoreException {
235 while (str.length() > chIndx) {
236 ch = str.charAt(chIndx++);
237 token = TT_UNDEFINED;
240 columnCount = chIndx;
241 continue; // while loop
243 if (str.length() == chIndx) {
246 if (!Character.isWhitespace(ch)) {
248 if (str.length() > chIndx) {
249 if (str.charAt(chIndx) == '{') {
251 token = TT_DOLLAROPEN;
258 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) {
262 if (ch >= '0' && ch <= '9') {
267 if (str.length() > chIndx) {
268 if (str.charAt(chIndx) == '/') {
270 // read comment until end of line:
271 while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
275 } else if (str.charAt(chIndx) == '*') {
277 // multi line comment:
278 while (str.length() > chIndx) {
279 if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
283 ch = str.charAt(chIndx++);
286 columnCount = chIndx;
292 } else if (ch == '#') {
293 // read comment until end of line:
294 while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
298 } else if (ch == '"') {
299 // read string until end
300 boolean openString = true;
301 while (str.length() > chIndx) {
302 ch = str.charAt(chIndx++);
304 if (str.length() > chIndx) {
305 ch = str.charAt(chIndx++);
307 } else if (ch == '"') {
310 } else if (ch == '\n') {
312 columnCount = chIndx;
316 throwSyntaxError("Open string character '\"' at end of file.");
318 token = TT_INTERPOLATED_STRING;
320 } else if (ch == '\'') {
321 // read string until end
322 boolean openString = true;
323 int startRow = rowCount;
324 while (str.length() > chIndx) {
325 ch = str.charAt(chIndx++);
327 if (str.length() > chIndx) {
328 ch = str.charAt(chIndx++);
330 } else if (ch == '\'') {
333 } else if (ch == '\n') {
335 columnCount = chIndx;
339 throwSyntaxError("Open string character \"'\" at end of file.", startRow);
341 token = TT_STRING_CONSTANT;
343 } else if (ch == '`') {
344 // read string until end
345 boolean openString = true;
346 int startRow = rowCount;
347 while (str.length() > chIndx) {
348 ch = str.charAt(chIndx++);
350 if (str.length() > chIndx) {
351 ch = str.charAt(chIndx++);
353 } else if (ch == '`') {
356 } else if (ch == '\n') {
358 columnCount = chIndx;
362 throwSyntaxError("Open string character \"`\" at end of file.", startRow);
364 setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO);
365 token = TT_STRING_CONSTANT;
384 token = TT_LISTCLOSE;
392 token = TT_PARTCLOSE;
400 token = TT_QUESTIONMARK;
407 if (str.length() > chIndx) {
408 if (str.charAt(chIndx) == '=') {
410 token = TT_TILDEASSIGN;
418 if (str.length() > chIndx) {
419 if (str.charAt(chIndx) == '=') {
421 token = TT_DOTASSIGN;
434 if (str.length() > chIndx) {
435 if (str.charAt(chIndx) == '=') {
437 token = TT_MODASSIGN;
444 token = TT_SEMICOLON;
449 if (str.length() > chIndx) {
450 if (str.charAt(chIndx) == '=') {
452 token = TT_POWASSIGN;
461 if (str.length() > chIndx) {
462 if (str.charAt(chIndx) == '=') {
473 if (str.length() > chIndx) {
474 if (str.charAt(chIndx) == '*') {
480 if (str.charAt(chIndx) == '=') {
491 if (str.length() > chIndx) {
492 if (str.charAt(chIndx) == '+') {
494 token = TT_INCREMENT;
498 if (str.charAt(chIndx) == '=') {
508 if (str.length() > chIndx) {
509 if (str.charAt(chIndx) == '-') {
511 token = TT_DECREMENT;
515 if (str.charAt(chIndx) == '=') {
517 token = TT_SUBTRACTFROM;
521 if (str.charAt(chIndx) == '>') {
533 if (str.length() > chIndx) {
534 ch = str.charAt(chIndx);
539 if (str.length() > chIndx) {
540 ch = str.charAt(chIndx);
561 if (str.length() > chIndx) {
562 if (str.charAt(chIndx) == '=') {
565 if (str.length() > chIndx) {
566 ch = str.charAt(chIndx);
570 token = TT_EX_UNEQUAL;
581 if (str.length() > chIndx) {
582 if (str.charAt(chIndx) == '=') {
584 token = TT_GREATEREQUAL;
587 if (str.charAt(chIndx) == '>') {
590 if (str.length() > chIndx) {
591 if (str.charAt(chIndx) == '=') {
593 token = TT_RSHIFTASSIGN;
605 if (str.length() > chIndx) {
606 if (str.charAt(chIndx) == '=') {
608 token = TT_LESSEQUAL;
612 if (str.charAt(chIndx) == '<') {
615 if (str.charAt(chIndx) == '<') {
617 int startRow = rowCount;
618 if (str.length() > chIndx) {
620 ch = str.charAt(++chIndx);
621 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_')) {
624 token = TT_STRING_CONSTANT;
625 while (str.length() > chIndx) {
626 ch = str.charAt(chIndx++);
628 if (str.length() >= chIndx + identifier.length()) {
629 if (str.substring(chIndx, chIndx + identifier.length()).equals(identifier)) {
630 chIndx += identifier.length();
638 throwSyntaxError("Open heredoc syntax after operator '<<<'.", startRow);
639 } else if (str.charAt(chIndx) == '=') {
641 token = TT_LSHIFTASSIGN;
653 if (str.length() > chIndx) {
654 if (str.charAt(chIndx) == '|') {
664 token = TT_AMPERSAND;
665 if (str.length() > chIndx) {
666 if (str.charAt(chIndx) == '&') {
671 if (str.charAt(chIndx) == '=') {
673 token = TT_ANDASSIGN;
682 if (str.length() > chIndx) {
683 if (str.charAt(chIndx) == ':') {
698 throwSyntaxError("unexpected character: '" + ch + "'");
701 if (token == TT_UNDEFINED) {
702 throwSyntaxError("token not found");
709 chIndx = str.length() + 1;
714 if (phpList != null) {
715 if (currentPHPString < phpList.size()) {
716 token = TT_UNDEFINED;
717 temp = (PHPString) phpList.get(currentPHPString++);
718 this.str = temp.getPHPString();
721 this.rowCount = temp.getLineNumber();
722 this.columnCount = 0;
726 token = TT_UNDEFINED;
732 * gets the next token from input
734 private void getNextToken() throws CoreException {
735 boolean phpFound = false;
742 while (str.length() > chIndx) {
743 token = TT_UNDEFINED;
744 ch = str.charAt(chIndx++);
750 ch2 = str.charAt(chIndx++);
752 ch2 = str.charAt(chIndx++);
753 if (Character.isWhitespace(ch2)) {
758 } else if (ch2 == 'p') {
759 ch2 = str.charAt(chIndx++);
761 ch2 = str.charAt(chIndx++);
770 } else if (ch2 == 'P') {
771 ch2 = str.charAt(chIndx++);
773 ch2 = str.charAt(chIndx++);
792 while (str.length() > chIndx) {
793 ch = str.charAt(chIndx++);
794 token = TT_UNDEFINED;
797 columnCount = chIndx;
798 continue; // while loop
800 if (str.length() == chIndx) {
803 if (!Character.isWhitespace(ch)) {
805 if (str.length() > chIndx) {
806 if (str.charAt(chIndx) == '{') {
808 token = TT_DOLLAROPEN;
815 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) {
819 if (ch >= '0' && ch <= '9') {
824 if (str.length() > chIndx) {
825 if (str.charAt(chIndx) == '/') {
828 // read comment until end of line:
829 while ((str.length() > chIndx) && (ch != '\n')) {
830 ch = str.charAt(chIndx++);
832 ch2 = str.charAt(chIndx);
846 } else if (str.charAt(chIndx) == '*') {
848 // multi line comment:
849 while (str.length() > chIndx) {
850 if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
854 ch = str.charAt(chIndx++);
857 columnCount = chIndx;
863 } else if (ch == '#') {
864 // read comment until end of line:
865 while ((str.length() > chIndx) && (ch != '\n')) {
866 ch = str.charAt(chIndx++);
868 ch2 = str.charAt(chIndx);
882 } else if (ch == '"') {
883 // read string until end
884 boolean openString = true;
885 while (str.length() > chIndx) {
886 ch = str.charAt(chIndx++);
888 if (str.length() > chIndx) {
889 ch = str.charAt(chIndx++);
891 } else if (ch == '"') {
894 } else if (ch == '\n') {
896 columnCount = chIndx;
900 throwSyntaxError("Open string character '\"' at end of file.");
902 token = TT_INTERPOLATED_STRING;
904 } else if (ch == '\'') {
905 // read string until end
906 boolean openString = true;
907 int startRow = rowCount;
908 while (str.length() > chIndx) {
909 ch = str.charAt(chIndx++);
911 if (str.length() > chIndx) {
912 ch = str.charAt(chIndx++);
914 } else if (ch == '\'') {
917 } else if (ch == '\n') {
919 columnCount = chIndx;
923 throwSyntaxError("Open string character \"'\" at end of file.", startRow);
925 token = TT_STRING_CONSTANT;
927 } else if (ch == '`') {
928 // read string until end
929 boolean openString = true;
930 int startRow = rowCount;
931 while (str.length() > chIndx) {
932 ch = str.charAt(chIndx++);
934 if (str.length() > chIndx) {
935 ch = str.charAt(chIndx++);
937 } else if (ch == '`') {
940 } else if (ch == '\n') {
942 columnCount = chIndx;
946 throwSyntaxError("Open string character \"`\" at end of file.", startRow);
948 setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO);
949 token = TT_STRING_CONSTANT;
968 token = TT_LISTCLOSE;
976 token = TT_PARTCLOSE;
984 token = TT_QUESTIONMARK;
985 if (str.length() > chIndx) {
986 if (str.charAt(chIndx) == '>') {
1002 if (str.length() > chIndx) {
1003 if (str.charAt(chIndx) == '=') {
1005 token = TT_TILDEASSIGN;
1013 if (str.length() > chIndx) {
1014 if (str.charAt(chIndx) == '=') {
1016 token = TT_DOTASSIGN;
1029 if (str.length() > chIndx) {
1030 if (str.charAt(chIndx) == '=') {
1032 token = TT_MODASSIGN;
1039 token = TT_SEMICOLON;
1044 if (str.length() > chIndx) {
1045 if (str.charAt(chIndx) == '=') {
1047 token = TT_POWASSIGN;
1056 if (str.length() > chIndx) {
1057 if (str.charAt(chIndx) == '=') {
1059 token = TT_DIVIDEBY;
1067 token = TT_MULTIPLY;
1068 if (str.length() > chIndx) {
1069 if (str.charAt(chIndx) == '*') {
1075 if (str.charAt(chIndx) == '=') {
1086 if (str.length() > chIndx) {
1087 if (str.charAt(chIndx) == '+') {
1089 token = TT_INCREMENT;
1093 if (str.charAt(chIndx) == '=') {
1102 token = TT_SUBTRACT;
1103 if (str.length() > chIndx) {
1104 if (str.charAt(chIndx) == '-') {
1106 token = TT_DECREMENT;
1110 if (str.charAt(chIndx) == '=') {
1112 token = TT_SUBTRACTFROM;
1116 if (str.charAt(chIndx) == '>') {
1128 if (str.length() > chIndx) {
1129 ch = str.charAt(chIndx);
1134 if (str.length() > chIndx) {
1135 ch = str.charAt(chIndx);
1139 token = TT_EX_EQUAL;
1156 if (str.length() > chIndx) {
1157 if (str.charAt(chIndx) == '=') {
1160 if (str.length() > chIndx) {
1161 ch = str.charAt(chIndx);
1165 token = TT_EX_UNEQUAL;
1176 if (str.length() > chIndx) {
1177 if (str.charAt(chIndx) == '=') {
1179 token = TT_GREATEREQUAL;
1182 if (str.charAt(chIndx) == '>') {
1185 if (str.length() > chIndx) {
1186 if (str.charAt(chIndx) == '=') {
1188 token = TT_RSHIFTASSIGN;
1200 if (str.length() > chIndx) {
1201 if (str.charAt(chIndx) == '=') {
1203 token = TT_LESSEQUAL;
1207 if (str.charAt(chIndx) == '<') {
1210 if (str.charAt(chIndx) == '<') {
1212 int startRow = rowCount;
1213 if (str.length() > chIndx) {
1215 ch = str.charAt(++chIndx);
1216 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_')) {
1219 token = TT_STRING_CONSTANT;
1220 while (str.length() > chIndx) {
1221 ch = str.charAt(chIndx++);
1223 if (str.length() >= chIndx + identifier.length()) {
1224 if (str.substring(chIndx, chIndx + identifier.length()).equals(identifier)) {
1225 chIndx += identifier.length();
1233 throwSyntaxError("Open heredoc syntax after operator '<<<'.", startRow);
1234 } else if (str.charAt(chIndx) == '=') {
1236 token = TT_LSHIFTASSIGN;
1248 if (str.length() > chIndx) {
1249 if (str.charAt(chIndx) == '|') {
1259 token = TT_AMPERSAND;
1260 if (str.length() > chIndx) {
1261 if (str.charAt(chIndx) == '&') {
1266 if (str.charAt(chIndx) == '=') {
1268 token = TT_ANDASSIGN;
1277 if (str.length() > chIndx) {
1278 if (str.charAt(chIndx) == ':') {
1293 throwSyntaxError("unexpected character: '" + ch + "'");
1296 if (token == TT_UNDEFINED) {
1297 throwSyntaxError("token not found");
1304 } catch (StringIndexOutOfBoundsException e) {
1305 // catched from charAt
1308 chIndx = str.length() + 1;
1313 // if (phpList != null) {
1314 // if (currentPHPString < phpList.size()) {
1315 // token = TT_UNDEFINED;
1316 // temp = (PHPString) phpList.get(currentPHPString++);
1317 // this.str = temp.getPHPString();
1318 // this.token = TT_EOF;
1320 // this.rowCount = temp.getLineNumber();
1321 // this.columnCount = 0;
1325 // token = TT_UNDEFINED;
1331 private void getIdentifier() {
1332 StringBuffer ident = new StringBuffer();
1336 token = TT_VARIABLE;
1338 token = TT_IDENTIFIER;
1341 while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
1345 identifier = ident.toString();
1348 Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
1350 token = i.intValue();
1354 private void getNumber() {
1355 StringBuffer inum = new StringBuffer();
1364 // determine number conversions:
1365 if (firstCh == '0') {
1394 if (numFormat == 16) {
1395 while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
1400 while ((ch >= '0' && ch <= '9') || (ch == '.') || (ch == 'E') || (ch == 'e')) {
1401 if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
1402 if (ch == '.' && dFlag != ' ') {
1405 if ((dFlag == 'E') || (dFlag == 'e')) {
1411 if ((ch == '-') || (ch == '+')) {
1425 doubleNumber = new Double(inum.toString());
1426 token = TT_DOUBLE_NUMBER;
1429 longNumber = Long.valueOf(inum.toString(), numFormat);
1430 token = TT_INT_NUMBER;
1434 } catch (Throwable e) {
1435 throwSyntaxError("Number format error: " + inum.toString());
1439 public void htmlParserTester(String input) {
1441 int startLineNumber = 1;
1445 boolean phpMode = false;
1446 boolean phpFound = false;
1448 phpList = new ArrayList();
1449 currentPHPString = 0;
1453 while (i < input.length()) {
1454 ch = input.charAt(i++);
1458 if ((!phpMode) && ch == '<') {
1459 ch2 = input.charAt(i++);
1461 ch2 = input.charAt(i++);
1462 if (Character.isWhitespace(ch2)) {
1467 startLineNumber = lineNumber;
1469 } else if (ch2 == 'p') {
1470 ch2 = input.charAt(i++);
1472 ch2 = input.charAt(i++);
1477 startLineNumber = lineNumber;
1483 } else if (ch2 == 'P') {
1484 ch2 = input.charAt(i++);
1486 ch2 = input.charAt(i++);
1491 startLineNumber = lineNumber;
1504 if (ch == '/' && i < input.length()) {
1505 ch2 = input.charAt(i++);
1507 while (i < input.length()) {
1508 ch = input.charAt(i++);
1509 if (ch == '?' && i < input.length()) {
1510 ch2 = input.charAt(i++);
1514 phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
1518 } else if (ch == '\n') {
1524 } else if (ch2 == '*') {
1525 // multi-line comment
1526 while (i < input.length()) {
1527 ch = input.charAt(i++);
1530 } else if (ch == '*' && i < input.length()) {
1531 ch2 = input.charAt(i++);
1542 } else if (ch == '#') {
1543 while (i < input.length()) {
1544 ch = input.charAt(i++);
1545 if (ch == '?' && i < input.length()) {
1546 ch2 = input.charAt(i++);
1550 phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
1554 } else if (ch == '\n') {
1560 } else if (ch == '"') {
1562 while (i < input.length()) {
1563 ch = input.charAt(i++);
1566 } else if (ch == '\\' && i < input.length()) { // escape
1568 } else if (ch == '"') {
1573 } else if (ch == '\'') {
1575 while (i < input.length()) {
1576 ch = input.charAt(i++);
1579 } else if (ch == '\\' && i < input.length()) { // escape
1581 } else if (ch == '\'') {
1588 if (ch == '?' && i < input.length()) {
1589 ch2 = input.charAt(i++);
1593 phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
1602 setMarker("No PHP source code found.", lineNumber, PHPParser.INFO);
1605 setMarker("Open PHP tag at end of file.", lineNumber, PHPParser.INFO);
1606 phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
1608 // for (int j=0;j<phpList.size();j++) {
1609 // String temp = ((PHPString)phpList.get(j)).getPHPString();
1610 // int startIndx = temp.length()-10;
1611 // if (startIndx<0) {
1614 // System.out.println(temp.substring(startIndx)+"?>");
1616 phpParserTester(null, 1);
1618 // for(int j=0;j<phpList.size();j++) {
1619 // temp = (PHPString) phpList.get(j);
1620 // parser.start(temp.getPHPString(), temp.getLineNumber());
1623 } catch (CoreException e) {
1627 public void phpParserTester(String s, int rowCount) throws CoreException {
1630 if (phpList.size() != 0) {
1631 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
1634 this.token = TT_EOF;
1636 this.rowCount = rowCount;
1637 this.columnCount = 0;
1638 this.phpEnd = false;
1639 this.phpMode = true;
1643 if (token != TT_EOF && token != TT_UNDEFINED) {
1646 if (token != TT_EOF && token != TT_UNDEFINED) {
1647 if (token == TT_ARGCLOSE) {
1648 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1650 if (token == TT_LISTCLOSE) {
1651 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1653 if (token == TT_PARTCLOSE) {
1654 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1657 if (token == TT_ARGOPEN) {
1658 throwSyntaxError("Read character '('; end-of-file not reached.");
1660 if (token == TT_LISTOPEN) {
1661 throwSyntaxError("Read character '{'; end-of-file not reached.");
1663 if (token == TT_PARTOPEN) {
1664 throwSyntaxError("Read character '['; end-of-file not reached.");
1667 throwSyntaxError("End-of-file not reached.");
1670 } catch (SyntaxError err) {
1674 setMarker(err.getMessage(), err.getLine(), ERROR);
1676 // if an error occured,
1677 // try to find keywords 'class' or 'function'
1678 // to parse the rest of the string
1679 while (token != TT_EOF && token != TT_UNDEFINED) {
1680 if (token == TT_class || token == TT_function) {
1685 if (token == TT_EOF || token == TT_UNDEFINED) {
1694 * Parses a string with php tAGS
1695 * i.e. '<body> <?php phpinfo() ?> </body>'
1697 public void parse(String s) throws CoreException {
1699 this.token = TT_EOF;
1702 this.columnCount = 0;
1703 this.phpEnd = false;
1704 this.phpMode = false;
1708 if (token != TT_EOF && token != TT_UNDEFINED) {
1711 if (token != TT_EOF && token != TT_UNDEFINED) {
1712 if (token == TT_ARGCLOSE) {
1713 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1715 if (token == TT_LISTCLOSE) {
1716 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1718 if (token == TT_PARTCLOSE) {
1719 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1722 if (token == TT_ARGOPEN) {
1723 throwSyntaxError("Read character '('; end-of-file not reached.");
1725 if (token == TT_LISTOPEN) {
1726 throwSyntaxError("Read character '{'; end-of-file not reached.");
1728 if (token == TT_PARTOPEN) {
1729 throwSyntaxError("Read character '['; end-of-file not reached.");
1732 throwSyntaxError("End-of-file not reached.");
1735 } catch (SyntaxError sytaxErr1) {
1736 setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
1738 // if an error occured,
1739 // try to find keywords 'class' or 'function'
1740 // to parse the rest of the string
1741 while (token != TT_EOF && token != TT_UNDEFINED) {
1742 if (token == TT_class || token == TT_function) {
1747 if (token == TT_EOF || token == TT_UNDEFINED) {
1750 } catch (SyntaxError sytaxErr2) {
1751 setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
1759 private void statementList() throws CoreException {
1762 if ((token == TT_LISTCLOSE)
1763 || (token == TT_case)
1764 || (token == TT_default)
1765 || (token == TT_elseif)
1766 || (token == TT_endif)
1767 || (token == TT_endfor)
1768 || (token == TT_endforeach)
1769 || (token == TT_endwhile)
1770 || (token == TT_endswitch)
1771 || (token == TT_EOF)
1772 || (token == TT_UNDEFINED)) {
1778 private void compoundStatement() throws CoreException {
1779 // '{' [statement-list] '}'
1780 if (token == TT_LISTOPEN) {
1783 throwSyntaxError("'{' expected in compound-statement.");
1785 if (token != TT_LISTCLOSE) {
1788 if (token == TT_LISTCLOSE) {
1791 throwSyntaxError("'}' expected in compound-statement.");
1795 private void statement() throws CoreException {
1796 // if (token > TT_KEYWORD && token != TT_list && token != TT_new) {
1797 String keyword = identifier;
1798 if (token == TT_include || token == TT_include_once) {
1801 if (token == TT_SEMICOLON) {
1805 throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1810 } else if (token == TT_require || token == TT_require_once) {
1814 if (token == TT_SEMICOLON) {
1818 throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1823 } else if (token == TT_if) {
1825 if (token == TT_ARGOPEN) {
1828 throwSyntaxError("'(' expected after 'if' keyword.");
1831 if (token == TT_ARGCLOSE) {
1834 throwSyntaxError("')' expected after 'if' condition.");
1839 } else if (token == TT_switch) {
1841 if (token == TT_ARGOPEN) {
1844 throwSyntaxError("'(' expected after 'switch' keyword.");
1847 if (token == TT_ARGCLOSE) {
1850 throwSyntaxError("')' expected after 'switch' condition.");
1854 } else if (token == TT_for) {
1856 if (token == TT_ARGOPEN) {
1859 throwSyntaxError("'(' expected after 'for' keyword.");
1861 if (token == TT_SEMICOLON) {
1865 if (token == TT_SEMICOLON) {
1868 throwSyntaxError("';' expected after 'for'.");
1871 if (token == TT_SEMICOLON) {
1875 if (token == TT_SEMICOLON) {
1878 throwSyntaxError("';' expected after 'for'.");
1881 if (token == TT_ARGCLOSE) {
1885 if (token == TT_ARGCLOSE) {
1888 throwSyntaxError("')' expected after 'for'.");
1893 } else if (token == TT_while) {
1895 if (token == TT_ARGOPEN) {
1898 throwSyntaxError("'(' expected after 'while' keyword.");
1901 if (token == TT_ARGCLOSE) {
1904 throwSyntaxError("')' expected after 'while' condition.");
1908 } else if (token == TT_do) {
1910 if (token == TT_LISTOPEN) {
1913 throwSyntaxError("'{' expected after 'do' keyword.");
1915 if (token != TT_LISTCLOSE) {
1918 if (token == TT_LISTCLOSE) {
1921 throwSyntaxError("'}' expected after 'do' keyword.");
1923 if (token == TT_while) {
1925 if (token == TT_ARGOPEN) {
1928 throwSyntaxError("'(' expected after 'while' keyword.");
1931 if (token == TT_ARGCLOSE) {
1934 throwSyntaxError("')' expected after 'while' condition.");
1937 throwSyntaxError("'while' expected after 'do' keyword.");
1939 if (token == TT_SEMICOLON) {
1943 throwSyntaxError("';' expected after do-while statement.");
1948 } else if (token == TT_foreach) {
1950 if (token == TT_ARGOPEN) {
1953 throwSyntaxError("'(' expected after 'foreach' keyword.");
1956 if (token == TT_as) {
1959 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1962 if (token == TT_FOREACH) {
1966 if (token == TT_ARGCLOSE) {
1969 throwSyntaxError("')' expected after 'foreach' expression.");
1974 } else if (token == TT_continue || token == TT_break || token == TT_return) {
1976 if (token != TT_SEMICOLON) {
1979 if (token == TT_SEMICOLON) {
1983 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1989 } else if (token == TT_echo) {
1992 if (token == TT_SEMICOLON) {
1996 throwSyntaxError("';' expected after 'echo' statement.");
2001 // } else if (token == TT_print) {
2004 // if (token == TT_SEMICOLON) {
2008 // throwSyntaxError("';' expected after 'print' statement.");
2014 } else if (token == TT_global || token == TT_static) {
2017 if (token == TT_SEMICOLON) {
2021 throwSyntaxError("';' expected after 'global' or 'static' statement.");
2027 // } else if (token == TT_unset) {
2029 // if (token == TT_ARGOPEN) {
2032 // throwSyntaxError("'(' expected after 'unset' keyword.");
2035 // if (token == TT_ARGCLOSE) {
2038 // throwSyntaxError("')' expected after 'unset' statement.");
2040 // if (token == TT_SEMICOLON) {
2044 // throwSyntaxError("';' expected after 'unset' statement.");
2050 // } else if (token == TT_exit || token == TT_die) {
2052 // if (token != TT_SEMICOLON) {
2055 // if (token == TT_SEMICOLON) {
2059 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
2065 } else if (token == TT_define) {
2067 if (token == TT_ARGOPEN) {
2070 throwSyntaxError("'(' expected after 'define' keyword.");
2073 if (token == TT_COMMA) {
2076 throwSyntaxError("',' expected after first 'define' constant.");
2079 if (token == TT_COMMA) {
2083 if (token == TT_ARGCLOSE) {
2086 throwSyntaxError("')' expected after 'define' statement.");
2088 if (token == TT_SEMICOLON) {
2092 throwSyntaxError("';' expected after 'define' statement.");
2097 } else if (token == TT_function) {
2099 functionDefinition();
2101 } else if (token == TT_class) {
2107 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
2108 } else if (token == TT_LISTOPEN) {
2109 // compoundStatement
2111 if (token != TT_LISTCLOSE) {
2114 if (token == TT_LISTCLOSE) {
2118 throwSyntaxError("'}' expected.");
2121 if (token != TT_SEMICOLON) {
2124 if (token == TT_SEMICOLON) {
2129 throwSyntaxError("';' expected after expression.");
2136 private void classDeclarator() throws CoreException {
2138 //identifier 'extends' identifier
2139 if (token == TT_IDENTIFIER) {
2141 if (token == TT_extends) {
2143 if (token == TT_IDENTIFIER) {
2146 throwSyntaxError("Class name expected after keyword 'extends'.");
2150 throwSyntaxError("Class name expected after keyword 'class'.");
2154 private void classBody() throws CoreException {
2155 //'{' [class-element-list] '}'
2156 if (token == TT_LISTOPEN) {
2158 if (token != TT_LISTCLOSE) {
2161 if (token == TT_LISTCLOSE) {
2164 throwSyntaxError("'}' expected at end of class body.");
2167 throwSyntaxError("'{' expected at start of class body.");
2171 private void classElementList() throws CoreException {
2174 } while (token == TT_function || token == TT_var);
2177 private void classElement() throws CoreException {
2179 //function-definition
2180 if (token == TT_function) {
2182 functionDefinition();
2183 } else if (token == TT_var) {
2187 throwSyntaxError("'function' or 'var' expected.");
2191 private void classProperty() throws CoreException {
2192 //'var' variable ';'
2193 //'var' variable '=' constant ';'
2195 if (token == TT_VARIABLE) {
2197 if (token == TT_ASSIGN) {
2202 throwSyntaxError("Variable expected after keyword 'var'.");
2204 if (token != TT_COMMA) {
2209 if (token == TT_SEMICOLON) {
2212 throwSyntaxError("';' expected after variable declaration.");
2216 private void functionDefinition() throws CoreException {
2217 functionDeclarator();
2218 compoundStatement();
2221 private void functionDeclarator() throws CoreException {
2222 //identifier '(' [parameter-list] ')'
2223 if (token == TT_AMPERSAND) {
2226 if (token == TT_IDENTIFIER) {
2228 if (token == TT_ARGOPEN) {
2231 throwSyntaxError("'(' expected in function declaration.");
2233 if (token != TT_ARGCLOSE) {
2236 if (token != TT_ARGCLOSE) {
2237 throwSyntaxError("')' expected in function declaration.");
2244 private void parameterList() throws CoreException {
2245 //parameter-declaration
2246 //parameter-list ',' parameter-declaration
2248 parameterDeclaration();
2249 if (token != TT_COMMA) {
2256 private void parameterDeclaration() throws CoreException {
2258 //variable-reference
2259 if (token == TT_AMPERSAND) {
2261 if (token == TT_VARIABLE) {
2264 throwSyntaxError("Variable expected after reference operator '&'.");
2267 //variable '=' constant
2268 if (token == TT_VARIABLE) {
2270 if (token == TT_ASSIGN) {
2278 private void labeledStatementList() throws CoreException {
2279 if (token != TT_case && token != TT_default) {
2280 throwSyntaxError("'case' or 'default' expected.");
2283 if (token == TT_case) {
2286 if (token == TT_DDOT) {
2288 if (token == TT_case || token == TT_default) { // empty case statement ?
2292 } else if (token == TT_SEMICOLON) {
2293 setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO);
2295 if (token == TT_case) { // empty case statement ?
2300 throwSyntaxError("':' character after 'case' constant expected.");
2302 } else { // TT_default
2304 if (token == TT_DDOT) {
2308 throwSyntaxError("':' character after 'default' expected.");
2311 } while (token == TT_case || token == TT_default);
2314 // public void labeledStatement() {
2315 // if (token == TT_case) {
2318 // if (token == TT_DDOT) {
2322 // throwSyntaxError("':' character after 'case' constant expected.");
2325 // } else if (token == TT_default) {
2327 // if (token == TT_DDOT) {
2331 // throwSyntaxError("':' character after 'default' expected.");
2337 // public void expressionStatement() {
2340 // private void inclusionStatement() {
2343 // public void compoundStatement() {
2346 // public void selectionStatement() {
2349 // public void iterationStatement() {
2352 // public void jumpStatement() {
2355 // public void outputStatement() {
2358 // public void scopeStatement() {
2361 // public void flowStatement() {
2364 // public void definitionStatement() {
2367 private void ifStatement() throws CoreException {
2368 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
2369 if (token == TT_DDOT) {
2375 if (token == TT_DDOT) {
2379 if (token == TT_if) { //'else if'
2381 elseifStatementList();
2383 throwSyntaxError("':' expected after 'else'.");
2389 elseifStatementList();
2393 if (token != TT_endif) {
2394 throwSyntaxError("'endif' expected.");
2397 if (token != TT_SEMICOLON) {
2398 throwSyntaxError("';' expected after if-statement.");
2402 // statement [else-statement]
2404 if (token == TT_elseif) {
2406 if (token == TT_ARGOPEN) {
2409 throwSyntaxError("'(' expected after 'elseif' keyword.");
2412 if (token == TT_ARGCLOSE) {
2415 throwSyntaxError("')' expected after 'elseif' condition.");
2418 } else if (token == TT_else) {
2425 private void elseifStatementList() throws CoreException {
2431 if (token == TT_DDOT) {
2436 if (token == TT_if) { //'else if'
2439 throwSyntaxError("':' expected after 'else'.");
2452 private void elseifStatement() throws CoreException {
2453 if (token == TT_ARGOPEN) {
2456 if (token != TT_ARGOPEN) {
2457 throwSyntaxError("')' expected in else-if-statement.");
2460 if (token != TT_DDOT) {
2461 throwSyntaxError("':' expected in else-if-statement.");
2468 private void switchStatement() throws CoreException {
2469 if (token == TT_DDOT) {
2470 // ':' [labeled-statement-list] 'endswitch' ';'
2472 labeledStatementList();
2473 if (token != TT_endswitch) {
2474 throwSyntaxError("'endswitch' expected.");
2477 if (token != TT_SEMICOLON) {
2478 throwSyntaxError("';' expected after switch-statement.");
2482 // '{' [labeled-statement-list] '}'
2483 if (token != TT_LISTOPEN) {
2484 throwSyntaxError("'{' expected in switch statement.");
2487 if (token != TT_LISTCLOSE) {
2488 labeledStatementList();
2490 if (token != TT_LISTCLOSE) {
2491 throwSyntaxError("'}' expected in switch statement.");
2498 private void forStatement() throws CoreException {
2499 if (token == TT_DDOT) {
2502 if (token != TT_endfor) {
2503 throwSyntaxError("'endfor' expected.");
2506 if (token != TT_SEMICOLON) {
2507 throwSyntaxError("';' expected after for-statement.");
2515 private void whileStatement() throws CoreException {
2516 // ':' statement-list 'endwhile' ';'
2517 if (token == TT_DDOT) {
2520 if (token != TT_endwhile) {
2521 throwSyntaxError("'endwhile' expected.");
2524 if (token != TT_SEMICOLON) {
2525 throwSyntaxError("';' expected after while-statement.");
2533 private void foreachStatement() throws CoreException {
2534 if (token == TT_DDOT) {
2537 if (token != TT_endforeach) {
2538 throwSyntaxError("'endforeach' expected.");
2541 if (token != TT_SEMICOLON) {
2542 throwSyntaxError("';' expected after foreach-statement.");
2550 private void exitStatus() throws CoreException {
2551 if (token == TT_ARGOPEN) {
2554 throwSyntaxError("'(' expected in 'exit-status'.");
2556 if (token != TT_ARGCLOSE) {
2559 if (token == TT_ARGCLOSE) {
2562 throwSyntaxError("')' expected after 'exit-status'.");
2566 private void expressionList() throws CoreException {
2569 if (token == TT_COMMA) {
2577 private void expression() throws CoreException {
2578 // if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) {
2581 logicalinclusiveorExpression();
2582 // while (token != TT_SEMICOLON) {
2588 private void postfixExpression() throws CoreException {
2590 boolean castFlag = false;
2605 case TT_STRING_CONSTANT :
2608 case TT_INTERPOLATED_STRING :
2613 if (token == TT_IDENTIFIER) {
2614 // check if identifier is a type:
2616 String str = identifier.toLowerCase();
2617 for (int i = 0; i < PHP_TYPES.length; i++) {
2618 if (PHP_TYPES[i].equals(str)) {
2625 if (token != TT_ARGCLOSE) {
2626 throwSyntaxError(") expected after cast-type '" + ident + "'.");
2636 if (token != TT_ARGCLOSE) {
2637 throwSyntaxError(") expected in postfix-expression.");
2641 case TT_DOUBLE_NUMBER :
2644 case TT_INT_NUMBER :
2647 case TT_DOLLAROPEN :
2650 if (token != TT_LISTCLOSE) {
2651 throwSyntaxError("'}' expected after indirect variable token '${'.");
2658 if (token == TT_LISTOPEN) {
2661 if (token != TT_LISTCLOSE) {
2662 throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression.");
2665 } else if (token == TT_ARGOPEN) {
2667 if (token != TT_ARGCLOSE) {
2669 if (token != TT_ARGCLOSE) {
2670 throwSyntaxError("')' expected after variable '" + ident + "' in postfix-expression.");
2676 case TT_IDENTIFIER :
2679 if (token == TT_ARGOPEN) {
2681 if (token != TT_ARGCLOSE) {
2683 if (token != TT_ARGCLOSE) {
2684 throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
2693 // if (token == TT_SEMICOLON) {
2697 // throwSyntaxError("';' expected after 'print' statement.");
2704 if (token == TT_ARGOPEN) {
2706 if (token == TT_COMMA) {
2710 if (token != TT_ARGCLOSE) {
2711 throwSyntaxError("')' expected after 'list' keyword.");
2714 // if (token == TT_SET) {
2716 // logicalinclusiveorExpression();
2719 throwSyntaxError("'(' expected after 'list' keyword.");
2724 // if (token != TT_SEMICOLON) {
2727 // if (token == TT_SEMICOLON) {
2731 // throwSyntaxError("';' expected after 'exit' expression.");
2738 // if (token != TT_SEMICOLON) {
2741 // if (token == TT_SEMICOLON) {
2745 // throwSyntaxError("';' expected after 'die' expression.");
2752 // if (token == TT_ARGOPEN) {
2754 // if (token == TT_COMMA) {
2757 // expressionList();
2758 // if (token != TT_ARGCLOSE) {
2759 // throwSyntaxError("')' expected after 'list' keyword.");
2762 // if (token == TT_SET) {
2764 // logicalinclusiveorExpression();
2767 // throwSyntaxError("'(' expected after 'list' keyword.");
2771 boolean while_flag = true;
2777 if (token != TT_PARTCLOSE) {
2778 throwSyntaxError("] expected in postfix-expression.");
2782 case TT_DDOT2 : // ::
2785 if (token > TT_KEYWORD) {
2787 setMarker("Avoid using keyword '" + ident + "' as variable name.", rowCount, PHPParser.INFO);
2793 // if (token == TT_ARGOPEN) {
2795 // expressionList();
2796 // if (token != TT_ARGCLOSE) {
2797 // throwSyntaxError(") expected after variable '" + ident + "'.");
2802 case TT_IDENTIFIER :
2809 if (token != TT_LISTCLOSE) {
2810 throwSyntaxError("} expected in postfix-expression.");
2815 throwSyntaxError("Syntax error after '->' token.");
2816 } while (token == TT_PARTOPEN || token == TT_ARGOPEN || token == TT_LISTOPEN) {
2817 if (token == TT_PARTOPEN) {
2820 if (token != TT_PARTCLOSE) {
2821 throwSyntaxError("] expected after '->'.");
2825 if (token == TT_ARGOPEN) {
2828 if (token != TT_ARGCLOSE) {
2829 throwSyntaxError(") expected after '->'.");
2833 if (token == TT_LISTOPEN) {
2836 if (token != TT_LISTCLOSE) {
2837 throwSyntaxError("} expected after '->'.");
2857 private void unaryExpression() throws CoreException {
2867 // '@' '&' '*' '+' '-' '~' '!'
2897 postfixExpression();
2901 private void castExpression() throws CoreException {
2902 // if (token == TT_ARGOPEN) {
2905 // if (token != TT_ARGCLOSE) {
2906 // throwSyntaxError(") expected after cast-expression.");
2913 private void typeName() throws CoreException {
2914 //'string' 'unset' 'array' 'object'
2916 //'real' 'double' 'float'
2919 if (token == TT_IDENTIFIER) {
2921 String str = identifier.toLowerCase();
2923 for (int i = 0; i < PHP_TYPES.length; i++) {
2924 if (PHP_TYPES[i].equals(str)) {
2929 throwSyntaxError("Expected type cast '( <type-name> )'; Got '" + ident + "'.");
2932 private void assignExpression() throws CoreException {
2934 if (token == TT_ASSIGN) { // =
2936 logicalinclusiveorExpression();
2937 } else if (token == TT_DOTASSIGN) { // .=
2939 logicalinclusiveorExpression();
2940 } else if (token == TT_FOREACH) { // =>
2942 logicalinclusiveorExpression();
2943 } else if (token == TT_ADDTO) { // +=
2945 logicalinclusiveorExpression();
2946 } else if (token == TT_SUBTRACTFROM) { // -=
2948 logicalinclusiveorExpression();
2949 } else if (token == TT_TIMESBY) { // *=
2951 logicalinclusiveorExpression();
2952 } else if (token == TT_DIVIDEBY) { // *=
2954 logicalinclusiveorExpression();
2955 } else if (token == TT_MODASSIGN) { // %=
2957 logicalinclusiveorExpression();
2958 } else if (token == TT_ANDASSIGN) { // &=
2960 logicalinclusiveorExpression();
2961 } else if (token == TT_POWASSIGN) { // ^=
2963 logicalinclusiveorExpression();
2964 } else if (token == TT_LSHIFTASSIGN) { // <<=
2966 logicalinclusiveorExpression();
2967 } else if (token == TT_RSHIFTASSIGN) { // >>=
2969 logicalinclusiveorExpression();
2970 } else if (token == TT_TILDEASSIGN) { // ~=
2972 logicalinclusiveorExpression();
2976 private void multiplicativeExpression() throws CoreException {
2979 if (token != TT_MULTIPLY && token != TT_DIV && token != TT_MOD) {
2986 private void concatenationExpression() throws CoreException {
2988 multiplicativeExpression();
2989 if (token != TT_DOT) {
2996 private void additiveExpression() throws CoreException {
2998 concatenationExpression();
2999 if (token != TT_ADD && token != TT_SUBTRACT) {
3006 private void shiftExpression() throws CoreException {
3008 additiveExpression();
3009 if (token != TT_LSHIFT && token != TT_RSHIFT) {
3016 private void relationalExpression() throws CoreException {
3019 if (token != TT_LESS && token != TT_GREATER && token != TT_LESSEQUAL && token != TT_GREATEREQUAL) {
3026 private void identicalExpression() throws CoreException {
3028 relationalExpression();
3029 if (token != TT_EX_EQUAL && token != TT_EX_UNEQUAL) {
3036 private void equalityExpression() throws CoreException {
3038 identicalExpression();
3039 if (token != TT_EQUAL && token != TT_UNEQUAL) {
3046 private void ternaryExpression() throws CoreException {
3047 equalityExpression();
3048 if (token == TT_QUESTIONMARK) {
3051 if (token == TT_DDOT) {
3055 throwSyntaxError("':' expected in ternary operator '? :'.");
3060 private void andExpression() throws CoreException {
3062 ternaryExpression();
3063 if (token != TT_AMPERSAND) {
3070 private void exclusiveorExpression() throws CoreException {
3073 if (token != TT_POW) {
3080 private void inclusiveorExpression() throws CoreException {
3082 exclusiveorExpression();
3083 if (token != TT_LINE) {
3090 private void booleanandExpression() throws CoreException {
3092 inclusiveorExpression();
3093 if (token != TT_AND) {
3100 private void booleanorExpression() throws CoreException {
3102 booleanandExpression();
3103 if (token != TT_OR) {
3110 private void logicalandExpression() throws CoreException {
3112 booleanorExpression();
3113 if (token != TT_and) {
3120 private void logicalexclusiveorExpression() throws CoreException {
3122 logicalandExpression();
3123 if (token != TT_xor) {
3130 private void logicalinclusiveorExpression() throws CoreException {
3132 logicalexclusiveorExpression();
3133 if (token != TT_or) {
3140 // public void assignmentExpression() {
3141 // if (token == TT_VARIABLE) {
3143 // if (token == TT_SET) {
3145 // logicalinclusiveorExpression();
3148 // logicalinclusiveorExpression();
3152 private void variableList() throws CoreException {
3155 if (token == TT_COMMA) {
3163 private void variable() throws CoreException {
3164 if (token == TT_DOLLAROPEN) {
3168 if (token != TT_LISTCLOSE) {
3169 throwSyntaxError("'}' expected after indirect variable token '${'.");
3173 if (token == TT_VARIABLE) {
3175 if (token == TT_PARTOPEN) {
3178 if (token != TT_PARTCLOSE) {
3179 throwSyntaxError("']' expected in variable-list.");
3182 } else if (token == TT_ASSIGN) {
3187 throwSyntaxError("$-variable expected in variable-list.");
3192 private void constant() throws CoreException {
3198 case TT_DOUBLE_NUMBER :
3201 case TT_INT_NUMBER :
3205 throwSyntaxError("Constant expected after '+' presign.");
3211 case TT_DOUBLE_NUMBER :
3214 case TT_INT_NUMBER :
3218 throwSyntaxError("Constant expected after '-' presign.");
3230 case TT_IDENTIFIER :
3233 if (token == TT_ARGOPEN) {
3235 if (token != TT_ARGCLOSE) {
3237 if (token != TT_ARGCLOSE) {
3238 throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
3244 case TT_STRING_CONSTANT :
3247 case TT_INTERPOLATED_STRING :
3250 case TT_DOUBLE_NUMBER :
3253 case TT_INT_NUMBER :
3257 throwSyntaxError("Constant expected.");
3262 * Call the php parse command ( php -l -f <filename> )
3263 * and create markers according to the external parser output
3265 public static void phpExternalParse(IFile file) {
3266 //IFile file = (IFile) resource;
3267 IPath path = file.getFullPath();
3268 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
3269 String filename = file.getLocation().toString();
3271 String[] arguments = { filename };
3272 MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
3273 String command = form.format(arguments);
3275 String parserResult = PHPStartApacheAction.execute(command, "External parser: ");
3278 // parse the buffer to find the errors and warnings
3279 createMarkers(parserResult, file);
3280 } catch (CoreException e) {
3285 * Create markers according to the external parser output
3287 private static void createMarkers(String output, IFile file) throws CoreException {
3288 // delete all markers
3289 file.deleteMarkers(IMarker.PROBLEM, false, 0);
3293 boolean flag = true;
3294 while ((brIndx = output.indexOf("<br />", indx)) != -1) {
3295 // newer php error output (tested with 4.2.3)
3296 scanLine(output, file, indx, brIndx);
3301 while ((brIndx = output.indexOf("<br>", indx)) != -1) {
3302 // older php error output (tested with 4.2.3)
3303 scanLine(output, file, indx, brIndx);
3309 private static void scanLine(String output, IFile file, int indx, int brIndx) throws CoreException {
3311 String outLineNumberString;
3312 StringBuffer lineNumberBuffer = new StringBuffer(10);
3314 current = output.substring(indx, brIndx);
3316 if (current.indexOf(PARSE_WARNING_STRING) != -1 || current.indexOf(PARSE_ERROR_STRING) != -1) {
3317 int onLine = current.indexOf("on line <b>");
3319 lineNumberBuffer.delete(0, lineNumberBuffer.length());
3320 for (int i = onLine; i < current.length(); i++) {
3321 ch = current.charAt(i);
3322 if ('0' <= ch && '9' >= ch) {
3323 lineNumberBuffer.append(ch);
3327 int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
3329 Hashtable attributes = new Hashtable();
3331 current = current.replaceAll("\n", "");
3332 current = current.replaceAll("<b>", "");
3333 current = current.replaceAll("</b>", "");
3334 MarkerUtilities.setMessage(attributes, current);
3336 if (current.indexOf(PARSE_ERROR_STRING) != -1)
3337 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
3338 else if (current.indexOf(PARSE_WARNING_STRING) != -1)
3339 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
3341 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
3342 MarkerUtilities.setLineNumber(attributes, lineNumber);
3343 MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);