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;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Hashtable;
17 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
18 import org.eclipse.core.resources.IFile;
19 import org.eclipse.core.resources.IMarker;
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.ui.texteditor.MarkerUtilities;
23 public class PHPParser extends PHPKeywords {
25 public static final int ERROR = 2;
26 public static final int WARNING = 1;
27 public static final int INFO = 0;
28 private IFile fileToParse;
29 private ArrayList phpList;
31 private int currentPHPString;
32 private boolean phpEnd;
34 private static HashMap keywordMap = null;
42 // row counter for syntax errors:
44 // column counter for syntax errors:
55 final static int TT_EOF = 0;
56 final static int TT_UNDEFINED = 1;
58 final static int TT_MOD = 30;
59 final static int TT_NOT = 31;
60 final static int TT_DOT = 32;
61 final static int TT_POW = 33;
62 final static int TT_DIV = 34;
63 final static int TT_MULTIPLY = 35;
64 final static int TT_SUBTRACT = 36;
65 final static int TT_ADD = 37;
66 final static int TT_EQUAL = 38;
67 final static int TT_UNEQUAL = 39;
68 final static int TT_GREATER = 40;
69 final static int TT_GREATEREQUAL = 41;
70 final static int TT_LESS = 42;
71 final static int TT_LESSEQUAL = 43;
72 final static int TT_AND = 44;
73 final static int TT_OR = 45;
74 final static int TT_HASH = 46;
75 final static int TT_DDOT = 47;
76 final static int TT_DOTASSIGN = 48;
78 final static int TT_ASSIGN = 49;
79 final static int TT_REF = 50;
80 final static int TT_FOREACH = 51;
81 final static int TT_AMPERSAND = 52;
82 final static int TT_DOLLARLISTOPEN = 53;
83 final static int TT_TILDE = 54;
84 final static int TT_TILDEASSIGN = 55;
85 final static int TT_MODASSIGN = 56;
86 final static int TT_POWASSIGN = 57;
87 final static int TT_RSHIFTASSIGN = 58;
88 final static int TT_LSHIFTASSIGN = 59;
89 final static int TT_ANDASSIGN = 60;
90 final static int TT_QUESTIONMARK = 61;
91 final static int TT_DDOT2 = 62;
92 final static int TT_AT = 63;
94 final static int TT_DOLLAROPEN = 127;
95 final static int TT_ARGOPEN = 128;
96 final static int TT_ARGCLOSE = 129;
97 final static int TT_LISTOPEN = 130;
98 final static int TT_LISTCLOSE = 131;
99 final static int TT_PARTOPEN = 132;
100 final static int TT_PARTCLOSE = 133;
101 final static int TT_COMMA = 134;
103 final static int TT_STRING = 136;
104 final static int TT_IDENTIFIER = 138;
105 final static int TT_DIGIT = 139;
106 final static int TT_SEMICOLON = 140;
107 final static int TT_SLOT = 141;
108 final static int TT_SLOTSEQUENCE = 142;
109 final static int TT_DECREMENT = 144;
110 final static int TT_INCREMENT = 145;
111 final static int TT_ADDTO = 146;
112 final static int TT_DIVIDEBY = 147;
113 final static int TT_SUBTRACTFROM = 148;
114 final static int TT_TIMESBY = 149;
115 final static int TT_VARIABLE = 150;
116 final static int TT_INT_NUMBER = 151;
117 final static int TT_DOUBLE_NUMBER = 152;
118 final static int TT_INTERPOLATED_STRING = 153;
119 final static int TT_STRING_CONSTANT = 154;
121 final static int TT_LSHIFT = 155;
122 final static int TT_RSHIFT = 156;
123 final static int TT_EX_EQUAL = 157;
124 final static int TT_EX_UNEQUAL = 158;
125 final static int TT_LINE = 159;
126 // final static int TT_AT = 153; // @
131 *@param sess Description of Parameter
134 public PHPParser(IFile fileToParse) {
135 if (keywordMap == null) {
136 keywordMap = new HashMap();
137 for (int i = 0; i < PHP_KEYWORS.length; i++) {
138 keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
141 this.currentPHPString = 0;
142 this.fileToParse = fileToParse;
148 this.columnCount = 0;
155 * Create marker for the parse error
157 private void setMarker(String message, int lineNumber, int errorLevel) throws CoreException {
158 setMarker(fileToParse, message, lineNumber, errorLevel);
161 public static void setMarker(IFile file, String message, int lineNumber, int errorLevel) throws CoreException {
163 Hashtable attributes = new Hashtable();
164 MarkerUtilities.setMessage(attributes, message);
165 switch (errorLevel) {
167 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
170 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
173 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
176 MarkerUtilities.setLineNumber(attributes, lineNumber);
177 MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
180 private void throwSyntaxError(String error) {
182 if (str.length() < chIndx) {
185 // read until end-of-line
187 while (str.length() > eol) {
188 ch = str.charAt(eol++);
194 throw new SyntaxError(rowCount, chIndx - columnCount + 1, str.substring(columnCount, eol), error);
198 * Method Declaration.
202 private void getChar() {
203 if (str.length() > chIndx) {
204 ch = str.charAt(chIndx++);
209 chIndx = str.length() + 1;
216 * gets the next token from input
218 private void getNextToken() throws CoreException {
221 while (str.length() > chIndx) {
222 ch = str.charAt(chIndx++);
223 token = TT_UNDEFINED;
226 columnCount = chIndx;
227 continue; // while loop
229 if (str.length() == chIndx) {
232 if (!Character.isWhitespace(ch)) {
234 if (str.length() > chIndx) {
235 if (str.charAt(chIndx) == '{') {
237 token = TT_DOLLAROPEN;
244 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) {
248 if (ch >= '0' && ch <= '9') {
253 if (str.length() > chIndx) {
254 if (str.charAt(chIndx) == '/') {
256 // read comment until end of line:
257 while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
261 } else if (str.charAt(chIndx) == '*') {
263 // multi line comment:
264 while (str.length() > chIndx) {
265 if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
269 ch = str.charAt(chIndx++);
272 columnCount = chIndx;
278 } else if (ch == '#') {
279 // read comment until end of line:
280 while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
284 } else if (ch == '"') {
285 // read string until end
286 boolean openString = true;
287 while (str.length() > chIndx) {
288 ch = str.charAt(chIndx++);
290 if (str.length() > chIndx) {
291 ch = str.charAt(chIndx++);
293 } else if (ch == '"') {
296 } else if (ch == '\n') {
298 columnCount = chIndx;
302 throwSyntaxError("Open string character '\"' at end of file.");
304 token = TT_INTERPOLATED_STRING;
306 } else if (ch == '\'') {
307 // read string until end
308 boolean openString = true;
309 while (str.length() > chIndx) {
310 ch = str.charAt(chIndx++);
312 if (str.length() > chIndx) {
313 ch = str.charAt(chIndx++);
315 } else if (ch == '\'') {
318 } else if (ch == '\n') {
320 columnCount = chIndx;
324 throwSyntaxError("Open string character \"'\" at end of file.");
326 token = TT_STRING_CONSTANT;
328 } else if (ch == '`') {
329 // read string until end
330 boolean openString = true;
331 while (str.length() > chIndx) {
332 ch = str.charAt(chIndx++);
334 if (str.length() > chIndx) {
335 ch = str.charAt(chIndx++);
337 } else if (ch == '`') {
340 } else if (ch == '\n') {
342 columnCount = chIndx;
346 throwSyntaxError("Open string character \"`\" at end of file.");
348 setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO);
349 token = TT_STRING_CONSTANT;
368 token = TT_LISTCLOSE;
376 token = TT_PARTCLOSE;
384 token = TT_QUESTIONMARK;
391 if (str.length() > chIndx) {
392 if (str.charAt(chIndx) == '=') {
394 token = TT_TILDEASSIGN;
402 if (str.length() > chIndx) {
403 if (str.charAt(chIndx) == '=') {
405 token = TT_DOTASSIGN;
418 if (str.length() > chIndx) {
419 if (str.charAt(chIndx) == '=') {
421 token = TT_MODASSIGN;
428 token = TT_SEMICOLON;
433 if (str.length() > chIndx) {
434 if (str.charAt(chIndx) == '=') {
436 token = TT_POWASSIGN;
445 if (str.length() > chIndx) {
446 if (str.charAt(chIndx) == '=') {
457 if (str.length() > chIndx) {
458 if (str.charAt(chIndx) == '*') {
464 if (str.charAt(chIndx) == '=') {
475 if (str.length() > chIndx) {
476 if (str.charAt(chIndx) == '+') {
478 token = TT_INCREMENT;
482 if (str.charAt(chIndx) == '=') {
492 if (str.length() > chIndx) {
493 if (str.charAt(chIndx) == '-') {
495 token = TT_DECREMENT;
499 if (str.charAt(chIndx) == '=') {
501 token = TT_SUBTRACTFROM;
505 if (str.charAt(chIndx) == '>') {
517 if (str.length() > chIndx) {
518 ch = str.charAt(chIndx);
523 if (str.length() > chIndx) {
524 ch = str.charAt(chIndx);
545 if (str.length() > chIndx) {
546 if (str.charAt(chIndx) == '=') {
549 if (str.length() > chIndx) {
550 ch = str.charAt(chIndx);
554 token = TT_EX_UNEQUAL;
565 if (str.length() > chIndx) {
566 if (str.charAt(chIndx) == '=') {
568 token = TT_GREATEREQUAL;
571 if (str.charAt(chIndx) == '>') {
574 if (str.length() > chIndx) {
575 if (str.charAt(chIndx) == '=') {
577 token = TT_RSHIFTASSIGN;
589 if (str.length() > chIndx) {
590 if (str.charAt(chIndx) == '=') {
592 token = TT_LESSEQUAL;
596 if (str.charAt(chIndx) == '<') {
599 if (str.length() > chIndx) {
600 if (str.charAt(chIndx) == '=') {
602 token = TT_LSHIFTASSIGN;
615 if (str.length() > chIndx) {
616 if (str.charAt(chIndx) == '|') {
626 token = TT_AMPERSAND;
627 if (str.length() > chIndx) {
628 if (str.charAt(chIndx) == '&') {
633 if (str.charAt(chIndx) == '=') {
635 token = TT_ANDASSIGN;
644 if (str.length() > chIndx) {
645 if (str.charAt(chIndx) == ':') {
660 throwSyntaxError("unexpected character: '" + ch + "'");
663 if (token == TT_UNDEFINED) {
664 throwSyntaxError("token not found");
671 chIndx = str.length() + 1;
676 if (phpList != null) {
677 if (currentPHPString < phpList.size()) {
678 token = TT_UNDEFINED;
679 temp = (PHPString) phpList.get(currentPHPString++);
680 this.str = temp.getPHPString();
683 this.rowCount = temp.getLineNumber();
684 this.columnCount = 0;
688 token = TT_UNDEFINED;
694 private void getIdentifier() {
695 StringBuffer ident = new StringBuffer();
701 token = TT_IDENTIFIER;
704 while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
708 identifier = ident.toString();
711 Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
713 token = i.intValue();
717 private void getNumber() {
718 StringBuffer inum = new StringBuffer();
727 // determine number conversions:
728 if (firstCh == '0') {
757 if (numFormat == 16) {
758 while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
763 while ((ch >= '0' && ch <= '9') || (ch == '.') || (ch == 'E') || (ch == 'e')) {
764 if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
765 if (ch == '.' && dFlag != ' ') {
768 if ((dFlag == 'E') || (dFlag == 'e')) {
774 if ((ch == '-') || (ch == '+')) {
788 doubleNumber = new Double(inum.toString());
789 token = TT_DOUBLE_NUMBER;
792 longNumber = Long.valueOf(inum.toString(), numFormat);
793 token = TT_INT_NUMBER;
797 } catch (Throwable e) {
798 throwSyntaxError("Number format error: " + inum.toString());
802 public void htmlParse(String input) {
804 int startLineNumber = 1;
808 boolean phpMode = false;
809 boolean phpFound = false;
811 phpList = new ArrayList();
812 currentPHPString = 0;
816 while (i < input.length()) {
817 ch = input.charAt(i++);
821 if ((!phpMode) && ch == '<') {
822 ch2 = input.charAt(i++);
824 ch2 = input.charAt(i++);
825 if (Character.isWhitespace(ch2)) {
830 startLineNumber = lineNumber;
832 } else if (ch2 == 'p') {
833 ch2 = input.charAt(i++);
835 ch2 = input.charAt(i++);
840 startLineNumber = lineNumber;
846 } else if (ch2 == 'P') {
847 ch2 = input.charAt(i++);
849 ch2 = input.charAt(i++);
854 startLineNumber = lineNumber;
867 if (ch == '/' && i < input.length()) {
868 ch2 = input.charAt(i++);
870 while (i < input.length()) {
871 ch = input.charAt(i++);
872 if (ch == '?' && i < input.length()) {
873 ch2 = input.charAt(i++);
877 phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
881 } else if (ch == '\n') {
887 } else if (ch2 == '*') {
888 // multi-line comment
889 while (i < input.length()) {
890 ch = input.charAt(i++);
893 } else if (ch == '*' && i < input.length()) {
894 ch2 = input.charAt(i++);
905 } else if (ch == '#') {
906 while (i < input.length()) {
907 ch = input.charAt(i++);
908 if (ch == '?' && i < input.length()) {
909 ch2 = input.charAt(i++);
913 phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
917 } else if (ch == '\n') {
923 } else if (ch == '"') {
925 while (i < input.length()) {
926 ch = input.charAt(i++);
929 } else if (ch == '\\' && i < input.length()) { // escape
931 } else if (ch == '"') {
936 } else if (ch == '\'') {
938 while (i < input.length()) {
939 ch = input.charAt(i++);
942 } else if (ch == '\\' && i < input.length()) { // escape
944 } else if (ch == '\'') {
951 if (ch == '?' && i < input.length()) {
952 ch2 = input.charAt(i++);
956 phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
965 setMarker("No PHP source code found.", lineNumber, PHPParser.INFO);
968 setMarker("Open PHP tag at end of file.", lineNumber, PHPParser.INFO);
969 phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
971 // for (int j=0;j<phpList.size();j++) {
972 // String temp = ((PHPString)phpList.get(j)).getPHPString();
973 // int startIndx = temp.length()-10;
974 // if (startIndx<0) {
977 // System.out.println(temp.substring(startIndx)+"?>");
981 // for(int j=0;j<phpList.size();j++) {
982 // temp = (PHPString) phpList.get(j);
983 // parser.start(temp.getPHPString(), temp.getLineNumber());
986 } catch (CoreException e) {
990 public void phpParse(String s, int rowCount) throws CoreException {
995 if (phpList.size() != 0) {
996 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
1001 this.rowCount = rowCount;
1002 this.columnCount = 0;
1003 this.phpEnd = false;
1005 if (token != TT_EOF && token != TT_UNDEFINED) {
1008 if (token != TT_EOF && token != TT_UNDEFINED) {
1009 if (token == TT_ARGCLOSE) {
1010 throwSyntaxError("too many closing ')'; end-of-file not reached");
1012 if (token == TT_LISTCLOSE) {
1013 throwSyntaxError("too many closing '}'; end-of-file not reached");
1015 if (token == TT_PARTCLOSE) {
1016 throwSyntaxError("too many closing ']'; end-of-file not reached");
1019 if (token == TT_ARGOPEN) {
1020 throwSyntaxError("read character '('; end-of-file not reached");
1022 if (token == TT_LISTOPEN) {
1023 throwSyntaxError("read character '{'; end-of-file not reached");
1025 if (token == TT_PARTOPEN) {
1026 throwSyntaxError("read character '['; end-of-file not reached");
1029 throwSyntaxError("end-of-file not reached");
1031 } catch (SyntaxError err) {
1035 setMarker(err.getMessage(), err.getLine(), ERROR);
1040 private void statementList() throws CoreException {
1043 if ((token == TT_LISTCLOSE)
1044 || (token == TT_case)
1045 || (token == TT_default)
1046 || (token == TT_elseif)
1047 || (token == TT_endif)
1048 || (token == TT_endfor)
1049 || (token == TT_endforeach)
1050 || (token == TT_endwhile)
1051 || (token == TT_endswitch)
1052 || (token == TT_EOF)
1053 || (token == TT_UNDEFINED)) {
1059 private void compoundStatement() throws CoreException {
1060 // '{' [statement-list] '}'
1061 if (token == TT_LISTOPEN) {
1064 throwSyntaxError("'{' expected in compound-statement.");
1066 if (token != TT_LISTCLOSE) {
1069 if (token == TT_LISTCLOSE) {
1072 throwSyntaxError("'}' expected in compound-statement.");
1076 private void statement() throws CoreException {
1077 // if (token > TT_KEYWORD && token != TT_list && token != TT_new) {
1078 String keyword = identifier;
1079 if (token == TT_include || token == TT_include_once) {
1082 if (token == TT_SEMICOLON) {
1086 throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1090 } else if (token == TT_require || token == TT_require_once) {
1094 if (token == TT_SEMICOLON) {
1098 throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1102 } else if (token == TT_if) {
1104 if (token == TT_ARGOPEN) {
1107 throwSyntaxError("'(' expected after 'if' keyword.");
1110 if (token == TT_ARGCLOSE) {
1113 throwSyntaxError("')' expected after 'if' condition.");
1118 } else if (token == TT_switch) {
1120 if (token == TT_ARGOPEN) {
1123 throwSyntaxError("'(' expected after 'switch' keyword.");
1126 if (token == TT_ARGCLOSE) {
1129 throwSyntaxError("')' expected after 'switch' condition.");
1133 } else if (token == TT_for) {
1135 if (token == TT_ARGOPEN) {
1138 throwSyntaxError("'(' expected after 'for' keyword.");
1140 if (token == TT_SEMICOLON) {
1144 if (token == TT_SEMICOLON) {
1147 throwSyntaxError("';' expected after 'for'.");
1150 if (token == TT_SEMICOLON) {
1154 if (token == TT_SEMICOLON) {
1157 throwSyntaxError("';' expected after 'for'.");
1160 if (token == TT_ARGCLOSE) {
1164 if (token == TT_ARGCLOSE) {
1167 throwSyntaxError("')' expected after 'for'.");
1172 } else if (token == TT_while) {
1174 if (token == TT_ARGOPEN) {
1177 throwSyntaxError("'(' expected after 'while' keyword.");
1180 if (token == TT_ARGCLOSE) {
1183 throwSyntaxError("')' expected after 'while' condition.");
1187 } else if (token == TT_do) {
1189 if (token == TT_LISTOPEN) {
1192 throwSyntaxError("'{' expected after 'do' keyword.");
1194 if (token != TT_LISTCLOSE) {
1197 if (token == TT_LISTCLOSE) {
1200 throwSyntaxError("'}' expected after 'do' keyword.");
1202 if (token == TT_while) {
1204 if (token == TT_ARGOPEN) {
1207 throwSyntaxError("'(' expected after 'while' keyword.");
1210 if (token == TT_ARGCLOSE) {
1213 throwSyntaxError("')' expected after 'while' condition.");
1216 throwSyntaxError("'while' expected after 'do' keyword.");
1218 if (token == TT_SEMICOLON) {
1222 throwSyntaxError("';' expected after do-while statement.");
1226 } else if (token == TT_foreach) {
1228 if (token == TT_ARGOPEN) {
1231 throwSyntaxError("'(' expected after 'foreach' keyword.");
1234 if (token == TT_as) {
1237 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1240 if (token == TT_FOREACH) {
1244 if (token == TT_ARGCLOSE) {
1247 throwSyntaxError("')' expected after 'foreach' expression.");
1252 } else if (token == TT_continue || token == TT_break || token == TT_return) {
1254 if (token != TT_SEMICOLON) {
1257 if (token == TT_SEMICOLON) {
1261 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1266 } else if (token == TT_echo) {
1269 if (token == TT_SEMICOLON) {
1273 throwSyntaxError("';' expected after 'echo' statement.");
1277 } else if (token == TT_print) {
1280 if (token == TT_SEMICOLON) {
1284 throwSyntaxError("';' expected after 'print' statement.");
1289 } else if (token == TT_global || token == TT_static) {
1292 if (token == TT_SEMICOLON) {
1296 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1301 // } else if (token == TT_unset) {
1303 // if (token == TT_ARGOPEN) {
1306 // throwSyntaxError("'(' expected after 'unset' keyword.");
1309 // if (token == TT_ARGCLOSE) {
1312 // throwSyntaxError("')' expected after 'unset' statement.");
1314 // if (token == TT_SEMICOLON) {
1318 // throwSyntaxError("';' expected after 'unset' statement.");
1323 // } else if (token == TT_exit || token == TT_die) {
1325 // if (token != TT_SEMICOLON) {
1328 // if (token == TT_SEMICOLON) {
1332 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1337 } else if (token == TT_define) {
1339 if (token == TT_ARGOPEN) {
1342 throwSyntaxError("'(' expected after 'define' keyword.");
1345 if (token == TT_COMMA) {
1348 throwSyntaxError("',' expected after first 'define' constant.");
1351 if (token == TT_COMMA) {
1355 if (token == TT_ARGCLOSE) {
1358 throwSyntaxError("')' expected after 'define' statement.");
1360 if (token == TT_SEMICOLON) {
1364 throwSyntaxError("';' expected after 'define' statement.");
1368 } else if (token == TT_function) {
1370 functionDefinition();
1372 } else if (token == TT_class) {
1378 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1379 } else if (token == TT_LISTOPEN) {
1380 // compoundStatement
1382 if (token != TT_LISTCLOSE) {
1385 if (token == TT_LISTCLOSE) {
1389 throwSyntaxError("'}' expected.");
1392 if (token != TT_SEMICOLON) {
1395 if (token == TT_SEMICOLON) {
1400 throwSyntaxError("';' expected after expression.");
1406 private void classDeclarator() throws CoreException {
1408 //identifier 'extends' identifier
1409 if (token == TT_IDENTIFIER) {
1411 if (token == TT_extends) {
1413 if (token == TT_IDENTIFIER) {
1416 throwSyntaxError("Class name expected after keyword 'extends'.");
1420 throwSyntaxError("Class name expected after keyword 'class'.");
1424 private void classBody() throws CoreException {
1425 //'{' [class-element-list] '}'
1426 if (token == TT_LISTOPEN) {
1428 if (token != TT_LISTCLOSE) {
1431 if (token == TT_LISTCLOSE) {
1434 throwSyntaxError("'}' expected at end of class body.");
1437 throwSyntaxError("'{' expected at start of class body.");
1441 private void classElementList() throws CoreException {
1444 } while (token == TT_function || token == TT_var);
1447 private void classElement() throws CoreException {
1449 //function-definition
1450 if (token == TT_function) {
1452 functionDefinition();
1453 } else if (token == TT_var) {
1457 throwSyntaxError("'function' or 'var' expected.");
1461 private void classProperty() throws CoreException {
1462 //'var' variable ';'
1463 //'var' variable '=' constant ';'
1465 if (token == TT_VARIABLE) {
1467 if (token == TT_ASSIGN) {
1472 throwSyntaxError("Variable expected after keyword 'var'.");
1474 if (token != TT_COMMA) {
1479 if (token == TT_SEMICOLON) {
1482 throwSyntaxError("';' expected after variable declaration.");
1486 private void functionDefinition() throws CoreException {
1487 functionDeclarator();
1488 compoundStatement();
1491 private void functionDeclarator() throws CoreException {
1492 //identifier '(' [parameter-list] ')'
1493 if (token == TT_AMPERSAND) {
1496 if (token == TT_IDENTIFIER) {
1498 if (token == TT_ARGOPEN) {
1501 throwSyntaxError("'(' expected in function declaration.");
1503 if (token != TT_ARGCLOSE) {
1506 if (token != TT_ARGCLOSE) {
1507 throwSyntaxError("')' expected in function declaration.");
1514 private void parameterList() throws CoreException {
1515 //parameter-declaration
1516 //parameter-list ',' parameter-declaration
1518 parameterDeclaration();
1519 if (token != TT_COMMA) {
1526 private void parameterDeclaration() throws CoreException {
1528 //variable-reference
1529 if (token == TT_AMPERSAND) {
1531 if (token == TT_VARIABLE) {
1534 throwSyntaxError("Variable expected after reference operator '&'.");
1537 //variable '=' constant
1538 if (token == TT_VARIABLE) {
1540 if (token == TT_ASSIGN) {
1548 private void labeledStatementList() throws CoreException {
1549 if (token != TT_case && token != TT_default) {
1550 throwSyntaxError("'case' or 'default' expected.");
1553 if (token == TT_case) {
1556 if (token == TT_DDOT) {
1558 if (token == TT_case || token == TT_default) { // empty case statement ?
1562 } else if (token == TT_SEMICOLON) {
1563 setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO);
1565 if (token == TT_case) { // empty case statement ?
1570 throwSyntaxError("':' character after 'case' constant expected.");
1572 } else { // TT_default
1574 if (token == TT_DDOT) {
1578 throwSyntaxError("':' character after 'default' expected.");
1581 } while (token == TT_case || token == TT_default);
1584 // public void labeledStatement() {
1585 // if (token == TT_case) {
1588 // if (token == TT_DDOT) {
1592 // throwSyntaxError("':' character after 'case' constant expected.");
1595 // } else if (token == TT_default) {
1597 // if (token == TT_DDOT) {
1601 // throwSyntaxError("':' character after 'default' expected.");
1607 // public void expressionStatement() {
1610 // private void inclusionStatement() {
1613 // public void compoundStatement() {
1616 // public void selectionStatement() {
1619 // public void iterationStatement() {
1622 // public void jumpStatement() {
1625 // public void outputStatement() {
1628 // public void scopeStatement() {
1631 // public void flowStatement() {
1634 // public void definitionStatement() {
1637 private void ifStatement() throws CoreException {
1638 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1639 if (token == TT_DDOT) {
1645 if (token == TT_DDOT) {
1649 if (token == TT_if) { //'else if'
1651 elseifStatementList();
1653 throwSyntaxError("':' expected after 'else'.");
1659 elseifStatementList();
1663 if (token != TT_endif) {
1664 throwSyntaxError("'endif' expected.");
1667 if (token != TT_SEMICOLON) {
1668 throwSyntaxError("';' expected after if-statement.");
1672 // statement [else-statement]
1674 if (token == TT_elseif) {
1676 if (token == TT_ARGOPEN) {
1679 throwSyntaxError("'(' expected after 'elseif' keyword.");
1682 if (token == TT_ARGCLOSE) {
1685 throwSyntaxError("')' expected after 'elseif' condition.");
1688 } else if (token == TT_else) {
1695 private void elseifStatementList() throws CoreException {
1701 if (token == TT_DDOT) {
1706 if (token == TT_if) { //'else if'
1709 throwSyntaxError("':' expected after 'else'.");
1722 private void elseifStatement() throws CoreException {
1723 if (token == TT_ARGOPEN) {
1726 if (token != TT_ARGOPEN) {
1727 throwSyntaxError("')' expected in else-if-statement.");
1730 if (token != TT_DDOT) {
1731 throwSyntaxError("':' expected in else-if-statement.");
1738 private void switchStatement() throws CoreException {
1739 if (token == TT_DDOT) {
1740 // ':' [labeled-statement-list] 'endswitch' ';'
1742 labeledStatementList();
1743 if (token != TT_endswitch) {
1744 throwSyntaxError("'endswitch' expected.");
1747 if (token != TT_SEMICOLON) {
1748 throwSyntaxError("';' expected after switch-statement.");
1752 // '{' [labeled-statement-list] '}'
1753 if (token != TT_LISTOPEN) {
1754 throwSyntaxError("'{' expected in switch statement.");
1757 if (token != TT_LISTCLOSE) {
1758 labeledStatementList();
1760 if (token != TT_LISTCLOSE) {
1761 throwSyntaxError("'}' expected in switch statement.");
1768 private void forStatement() throws CoreException {
1769 if (token == TT_DDOT) {
1772 if (token != TT_endfor) {
1773 throwSyntaxError("'endfor' expected.");
1776 if (token != TT_SEMICOLON) {
1777 throwSyntaxError("';' expected after for-statement.");
1785 private void whileStatement() throws CoreException {
1786 // ':' statement-list 'endwhile' ';'
1787 if (token == TT_DDOT) {
1790 if (token != TT_endwhile) {
1791 throwSyntaxError("'endwhile' expected.");
1794 if (token != TT_SEMICOLON) {
1795 throwSyntaxError("';' expected after while-statement.");
1803 private void foreachStatement() throws CoreException {
1804 if (token == TT_DDOT) {
1807 if (token != TT_endforeach) {
1808 throwSyntaxError("'endforeach' expected.");
1811 if (token != TT_SEMICOLON) {
1812 throwSyntaxError("';' expected after foreach-statement.");
1820 private void exitStatus() throws CoreException {
1821 if (token == TT_ARGOPEN) {
1824 throwSyntaxError("'(' expected in 'exit-status'.");
1826 if (token != TT_ARGCLOSE) {
1829 if (token == TT_ARGCLOSE) {
1832 throwSyntaxError("')' expected after 'exit-status'.");
1836 private void expressionList() throws CoreException {
1839 if (token == TT_COMMA) {
1847 private void expression() throws CoreException {
1848 // if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) {
1851 logicalinclusiveorExpression();
1852 // while (token != TT_SEMICOLON) {
1858 private void postfixExpression() throws CoreException {
1860 boolean castFlag = false;
1875 case TT_STRING_CONSTANT :
1878 case TT_INTERPOLATED_STRING :
1883 if (token == TT_IDENTIFIER) {
1884 // check if identifier is a type:
1886 String str = identifier.toLowerCase();
1887 for (int i = 0; i < PHP_TYPES.length; i++) {
1888 if (PHP_TYPES[i].equals(str)) {
1895 if (token != TT_ARGCLOSE) {
1896 throwSyntaxError(") expected after cast-type '" + ident + "'.");
1906 if (token != TT_ARGCLOSE) {
1907 throwSyntaxError(") expected in postfix-expression.");
1911 case TT_DOUBLE_NUMBER :
1914 case TT_INT_NUMBER :
1917 case TT_DOLLAROPEN :
1920 if (token != TT_LISTCLOSE) {
1921 throwSyntaxError("'}' expected after indirect variable token '${'.");
1928 if (token == TT_LISTOPEN) {
1931 if (token != TT_LISTCLOSE) {
1932 throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression.");
1935 } else if (token == TT_ARGOPEN) {
1937 if (token != TT_ARGCLOSE) {
1939 if (token != TT_ARGCLOSE) {
1940 throwSyntaxError("')' expected after variable '" + ident + "' in postfix-expression.");
1946 case TT_IDENTIFIER :
1949 if (token == TT_ARGOPEN) {
1951 if (token != TT_ARGCLOSE) {
1953 if (token != TT_ARGCLOSE) {
1954 throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
1962 if (token == TT_ARGOPEN) {
1964 if (token == TT_COMMA) {
1968 if (token != TT_ARGCLOSE) {
1969 throwSyntaxError("')' expected after 'list' keyword.");
1972 // if (token == TT_SET) {
1974 // logicalinclusiveorExpression();
1977 throwSyntaxError("'(' expected after 'list' keyword.");
1982 // if (token != TT_SEMICOLON) {
1985 // if (token == TT_SEMICOLON) {
1989 // throwSyntaxError("';' expected after 'exit' expression.");
1995 // if (token != TT_SEMICOLON) {
1998 // if (token == TT_SEMICOLON) {
2002 // throwSyntaxError("';' expected after 'die' expression.");
2009 // if (token == TT_ARGOPEN) {
2011 // if (token == TT_COMMA) {
2014 // expressionList();
2015 // if (token != TT_ARGCLOSE) {
2016 // throwSyntaxError("')' expected after 'list' keyword.");
2019 // if (token == TT_SET) {
2021 // logicalinclusiveorExpression();
2024 // throwSyntaxError("'(' expected after 'list' keyword.");
2028 boolean while_flag = true;
2034 if (token != TT_PARTCLOSE) {
2035 throwSyntaxError("] expected in postfix-expression.");
2039 case TT_DDOT2 : // ::
2042 if (token > TT_KEYWORD) {
2044 setMarker("Avoid using keyword '" + ident + "' as variable name.", rowCount, PHPParser.INFO);
2046 if (token == TT_ARGOPEN) {
2049 if (token != TT_ARGCLOSE) {
2050 throwSyntaxError(") expected after identifier '" + ident + "'.");
2060 // if (token == TT_ARGOPEN) {
2062 // expressionList();
2063 // if (token != TT_ARGCLOSE) {
2064 // throwSyntaxError(") expected after variable '" + ident + "'.");
2069 case TT_IDENTIFIER :
2072 if (token == TT_ARGOPEN) {
2075 if (token != TT_ARGCLOSE) {
2076 throwSyntaxError(") expected after identifier '" + ident + "'.");
2084 if (token != TT_LISTCLOSE) {
2085 throwSyntaxError("} expected in postfix-expression.");
2090 throwSyntaxError("Syntax error after '->' token.");
2104 } while (while_flag);
2107 private void unaryExpression() throws CoreException {
2117 // '@' '&' '*' '+' '-' '~' '!'
2147 postfixExpression();
2151 private void castExpression() throws CoreException {
2152 // if (token == TT_ARGOPEN) {
2155 // if (token != TT_ARGCLOSE) {
2156 // throwSyntaxError(") expected after cast-expression.");
2163 private void typeName() throws CoreException {
2164 //'string' 'unset' 'array' 'object'
2166 //'real' 'double' 'float'
2169 if (token == TT_IDENTIFIER) {
2171 String str = identifier.toLowerCase();
2173 for (int i = 0; i < PHP_TYPES.length; i++) {
2174 if (PHP_TYPES[i].equals(str)) {
2179 throwSyntaxError("Expected type cast '( <type-name> )'; Got '" + ident + "'.");
2182 private void assignExpression() throws CoreException {
2184 if (token == TT_ASSIGN) { // =
2186 logicalinclusiveorExpression();
2187 } else if (token == TT_DOTASSIGN) { // .=
2189 logicalinclusiveorExpression();
2190 } else if (token == TT_FOREACH) { // =>
2192 logicalinclusiveorExpression();
2193 } else if (token == TT_ADDTO) { // +=
2195 logicalinclusiveorExpression();
2196 } else if (token == TT_SUBTRACTFROM) { // -=
2198 logicalinclusiveorExpression();
2199 } else if (token == TT_TIMESBY) { // *=
2201 logicalinclusiveorExpression();
2202 } else if (token == TT_DIVIDEBY) { // *=
2204 logicalinclusiveorExpression();
2205 } else if (token == TT_MODASSIGN) { // %=
2207 logicalinclusiveorExpression();
2208 } else if (token == TT_ANDASSIGN) { // &=
2210 logicalinclusiveorExpression();
2211 } else if (token == TT_POWASSIGN) { // ^=
2213 logicalinclusiveorExpression();
2214 } else if (token == TT_LSHIFTASSIGN) { // <<=
2216 logicalinclusiveorExpression();
2217 } else if (token == TT_RSHIFTASSIGN) { // >>=
2219 logicalinclusiveorExpression();
2220 } else if (token == TT_TILDEASSIGN) { // ~=
2222 logicalinclusiveorExpression();
2226 private void multiplicativeExpression() throws CoreException {
2229 if (token != TT_MULTIPLY && token != TT_DIV && token != TT_MOD) {
2236 private void concatenationExpression() throws CoreException {
2238 multiplicativeExpression();
2239 if (token != TT_DOT) {
2246 private void additiveExpression() throws CoreException {
2248 concatenationExpression();
2249 if (token != TT_ADD && token != TT_SUBTRACT) {
2256 private void shiftExpression() throws CoreException {
2258 additiveExpression();
2259 if (token != TT_LSHIFT && token != TT_RSHIFT) {
2266 private void relationalExpression() throws CoreException {
2269 if (token != TT_LESS && token != TT_GREATER && token != TT_LESSEQUAL && token != TT_GREATEREQUAL) {
2276 private void identicalExpression() throws CoreException {
2278 relationalExpression();
2279 if (token != TT_EX_EQUAL && token != TT_EX_UNEQUAL) {
2286 private void equalityExpression() throws CoreException {
2288 identicalExpression();
2289 if (token != TT_EQUAL && token != TT_UNEQUAL) {
2296 private void ternaryExpression() throws CoreException {
2297 equalityExpression();
2298 if (token == TT_QUESTIONMARK) {
2301 if (token == TT_DDOT) {
2305 throwSyntaxError("':' expected in ternary operator '? :'.");
2310 private void andExpression() throws CoreException {
2312 ternaryExpression();
2313 if (token != TT_AMPERSAND) {
2320 private void exclusiveorExpression() throws CoreException {
2323 if (token != TT_POW) {
2330 private void inclusiveorExpression() throws CoreException {
2332 exclusiveorExpression();
2333 if (token != TT_LINE) {
2340 private void booleanandExpression() throws CoreException {
2342 inclusiveorExpression();
2343 if (token != TT_AND) {
2350 private void booleanorExpression() throws CoreException {
2352 booleanandExpression();
2353 if (token != TT_OR) {
2360 private void logicalandExpression() throws CoreException {
2362 booleanorExpression();
2363 if (token != TT_and) {
2370 private void logicalexclusiveorExpression() throws CoreException {
2372 logicalandExpression();
2373 if (token != TT_xor) {
2380 private void logicalinclusiveorExpression() throws CoreException {
2382 logicalexclusiveorExpression();
2383 if (token != TT_or) {
2390 // public void assignmentExpression() {
2391 // if (token == TT_VARIABLE) {
2393 // if (token == TT_SET) {
2395 // logicalinclusiveorExpression();
2398 // logicalinclusiveorExpression();
2402 private void variableList() throws CoreException {
2405 if (token == TT_COMMA) {
2413 private void variable() throws CoreException {
2414 if (token == TT_DOLLAROPEN) {
2418 if (token != TT_LISTCLOSE) {
2419 throwSyntaxError("'}' expected after indirect variable token '${'.");
2423 if (token == TT_VARIABLE) {
2425 if (token == TT_PARTOPEN) {
2428 if (token != TT_PARTCLOSE) {
2429 throwSyntaxError("']' expected in variable-list.");
2432 } else if (token == TT_ASSIGN) {
2437 throwSyntaxError("$-variable expected in variable-list.");
2442 private void constant() throws CoreException {
2448 case TT_DOUBLE_NUMBER :
2451 case TT_INT_NUMBER :
2455 throwSyntaxError("Constant expected after '+' presign.");
2461 case TT_DOUBLE_NUMBER :
2464 case TT_INT_NUMBER :
2468 throwSyntaxError("Constant expected after '-' presign.");
2480 case TT_IDENTIFIER :
2483 if (token == TT_ARGOPEN) {
2485 if (token != TT_ARGCLOSE) {
2487 if (token != TT_ARGCLOSE) {
2488 throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
2494 case TT_STRING_CONSTANT :
2497 case TT_INTERPOLATED_STRING :
2500 case TT_DOUBLE_NUMBER :
2503 case TT_INT_NUMBER :
2507 throwSyntaxError("Constant expected.");