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.Hashtable;
17 import net.sourceforge.phpdt.core.compiler.*;
18 import net.sourceforge.phpdt.internal.compiler.parser.*;
19 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
20 import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
21 import net.sourceforge.phpeclipse.phpeditor.PHPString;
22 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
24 import org.eclipse.core.resources.IFile;
25 import org.eclipse.core.resources.IMarker;
26 import org.eclipse.core.runtime.CoreException;
27 import org.eclipse.core.runtime.IPath;
28 import org.eclipse.jface.preference.IPreferenceStore;
29 import org.eclipse.ui.texteditor.MarkerUtilities;
31 public class Parser extends PHPKeywords implements ITerminalSymbols {
32 // strings for external parser call
33 private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
34 private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
36 public static final int ERROR = 2;
37 public static final int WARNING = 1;
38 public static final int INFO = 0;
40 public static final boolean DEBUG = false;
42 public Scanner scanner;
44 private IFile fileToParse;
45 private ArrayList phpList;
47 private int currentPHPString;
48 private boolean phpEnd;
50 // private static HashMap keywordMap = null;
58 // row counter for syntax errors:
60 // column counter for syntax errors:
65 // // current identifier
71 private String stringValue;
73 /** Contains the current expression. */
74 // private StringBuffer expression;
76 private boolean phpMode;
78 // final static int TokenNameEOF = 0;
79 // final static int TokenNameERROR = 1;
80 // final static int TokenNameHTML = 2;
82 // final static int TokenNameREMAINDER = 30;
83 // final static int TokenNameNOT = 31;
84 // final static int TokenNameDOT = 32;
85 // final static int TokenNameXOR = 33;
86 // final static int TokenNameDIVIDE = 34;
87 // final static int TokenNameMULTIPLY = 35;
88 // final static int TokenNameMINUS = 36;
89 // final static int TokenNamePLUS = 37;
90 // final static int TokenNameEQUAL_EQUAL = 38;
91 // final static int TokenNameNOT_EQUAL = 39;
92 // final static int TokenNameGREATER = 40;
93 // final static int TokenNameGREATER_EQUAL = 41;
94 // final static int TokenNameLESS = 42;
95 // final static int TokenNameLESS_EQUAL = 43;
96 // final static int TokenNameAND_AND = 44;
97 // final static int TokenNameOR_OR = 45;
98 // // final static int TokenNameHASH = 46;
99 // final static int TokenNameCOLON = 47;
100 // final static int TokenNameDOT_EQUAL = 48;
102 // final static int TokenNameEQUAL = 49;
103 // final static int TokenNameMINUS_GREATER = 50; // ->
104 // final static int TokenNameFOREACH = 51;
105 // final static int TokenNameAND = 52;
106 // //final static int TokenNameDOLLARLISTOPEN = 53;
107 // final static int TokenNameTWIDDLE = 54;
108 // final static int TokenNameTWIDDLE_EQUAL = 55;
109 // final static int TokenNameREMAINDER_EQUAL = 56;
110 // final static int TokenNameXOR_EQUAL = 57;
111 // final static int TokenNameRIGHT_SHIFT_EQUAL = 58;
112 // final static int TokenNameLEFT_SHIFT_EQUAL = 59;
113 // final static int TokenNameAND_EQUAL = 60;
114 // final static int TokenNameOR_EQUAL = 61;
115 // final static int TokenNameQUESTION = 62;
116 // final static int TokenNameCOLON_COLON = 63;
117 // final static int TokenNameAT = 63;
118 // // final static int TokenNameHEREDOC = 64;
120 // final static int TokenNameDOLLAROPEN = 127;
121 // final static int TokenNameLPAREN = 128;
122 // final static int TokenNameRPAREN = 129;
123 // final static int TokenNameLBRACE = 130;
124 // final static int TokenNameRBRACE = 131;
125 // final static int TokenNameLBRACKET = 132;
126 // final static int TokenNameRBRACKET = 133;
127 // final static int TokenNameCOMMA = 134;
129 // final static int TokenNameStringLiteral = 136;
130 // final static int TokenNameIdentifier = 138;
131 // // final static int TokenNameDIGIT = 139;
132 // final static int TokenNameSEMICOLON = 140;
133 // // final static int TokenNameSLOT = 141;
134 // // final static int TokenNameSLOTSEQUENCE = 142;
135 // final static int TokenNameMINUS_MINUS = 144;
136 // final static int TokenNamePLUS_PLUS = 145;
137 // final static int TokenNamePLUS_EQUAL = 146;
138 // final static int TokenNameDIVIDE_EQUAL = 147;
139 // final static int TokenNameMINUS_EQUAL = 148;
140 // final static int TokenNameMULTIPLY_EQUAL = 149;
141 // final static int TokenNameVariable = 150;
142 // final static int TokenNameIntegerLiteral = 151;
143 // final static int TokenNameDoubleLiteral = 152;
144 // final static int TokenNameStringInterpolated = 153;
145 // final static int TokenNameStringConstant = 154;
147 // final static int TokenNameLEFT_SHIFT = 155;
148 // final static int TokenNameRIGHT_SHIFT = 156;
149 // final static int TokenNameEQUAL_EQUAL_EQUAL = 157;
150 // final static int TokenNameNOT_EQUAL_EQUAL = 158;
151 // final static int TokenNameOR = 159;
152 // final static int TokenNameAT = 153; // @
157 *@param sess Description of Parameter
160 public Parser(IFile fileToParse) {
161 // if (keywordMap == null) {
162 // keywordMap = new HashMap();
163 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
164 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
167 this.currentPHPString = 0;
168 this.fileToParse = fileToParse;
171 this.token = TokenNameEOF;
173 // this.rowCount = 1;
174 // this.columnCount = 0;
178 this.initializeScanner();
181 public void initializeScanner() {
182 this.scanner = new Scanner(false, false, false, false);
185 * Create marker for the parse error
187 private void setMarker(
192 throws CoreException {
193 setMarker(fileToParse, message, charStart, charEnd, errorLevel);
196 public static void setMarker(
202 throws CoreException {
204 Hashtable attributes = new Hashtable();
205 MarkerUtilities.setMessage(attributes, message);
206 switch (errorLevel) {
208 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
213 new Integer(IMarker.SEVERITY_WARNING));
216 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
219 MarkerUtilities.setCharStart(attributes, charStart);
220 MarkerUtilities.setCharEnd(attributes, charEnd);
221 // setLineNumber(attributes, lineNumber);
222 MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
227 * This method will throw the SyntaxError.
228 * It will add the good lines and columns to the Error
229 * @param error the error message
230 * @throws SyntaxError the error raised
232 private void throwSyntaxError(String error) {
234 // if (str.length() < chIndx) {
237 // // read until end-of-line
239 // while (str.length() > eol) {
240 // ch = str.charAt(eol++);
246 // throw new SyntaxError(
248 // chIndx - columnCount + 1,
249 // str.substring(columnCount, eol),
251 throw new SyntaxError(
259 * This method will throw the SyntaxError.
260 * It will add the good lines and columns to the Error
261 * @param error the error message
262 * @throws SyntaxError the error raised
264 private void throwSyntaxError(String error, int startRow) {
265 throw new SyntaxError(startRow, 0, " ", error);
269 * Method Declaration.
273 // private void getChar() {
274 // if (str.length() > chIndx) {
275 // ch = str.charAt(chIndx++);
280 // chIndx = str.length() + 1;
282 // // token = TokenNameEOF;
287 * gets the next token from input
289 private void getNextToken() throws CoreException {
291 token = scanner.getNextToken();
293 int currentEndPosition = scanner.getCurrentTokenEndPosition();
294 int currentStartPosition = scanner.getCurrentTokenStartPosition();
297 currentStartPosition + "," + currentEndPosition + ": ");
298 System.out.println(scanner.toStringAction(token));
300 } catch (InvalidInputException e) {
301 token = TokenNameERROR;
305 // boolean phpFound = false;
312 // while (str.length() > chIndx) {
313 // token = TokenNameERROR;
314 // ch = str.charAt(chIndx++);
320 // ch2 = str.charAt(chIndx++);
322 // ch2 = str.charAt(chIndx++);
323 // if (Character.isWhitespace(ch2)) {
328 // } else if (ch2 == 'p' || ch2 == 'P') {
329 // ch2 = str.charAt(chIndx++);
330 // if (ch2 == 'h' || ch2 == 'H') {
331 // ch2 = str.charAt(chIndx++);
332 // if (ch2 == 'p' || ch2 == 'P') {
350 // while (str.length() > chIndx) {
351 // ch = str.charAt(chIndx++);
352 // token = TokenNameERROR;
355 // columnCount = chIndx;
356 // continue; // while loop
358 // if (str.length() == chIndx) {
361 // if (!Character.isWhitespace(ch)) {
363 // if (str.length() > chIndx) {
364 // if (str.charAt(chIndx) == '{') {
366 // token = TokenNameDOLLAROPEN;
373 // if ((ch >= 'a' && ch <= 'z')
374 // || (ch >= 'A' && ch <= 'Z')
380 // if (ch >= '0' && ch <= '9') {
385 // if (str.length() > chIndx) {
386 // if (str.charAt(chIndx) == '/') {
389 // // read comment until end of line:
390 // while ((str.length() > chIndx)
391 // && (ch != '\n')) {
392 // ch = str.charAt(chIndx++);
394 // ch2 = str.charAt(chIndx);
397 // token = TokenNameHTML;
408 // } else if (str.charAt(chIndx) == '*') {
410 // // multi line comment:
411 // while (str.length() > chIndx) {
412 // if (str.charAt(chIndx) == '*'
413 // && (str.length() > (chIndx + 1))
414 // && str.charAt(chIndx + 1) == '/') {
418 // ch = str.charAt(chIndx++);
421 // columnCount = chIndx;
427 // } else if (ch == '#') {
428 // // read comment until end of line:
429 // while ((str.length() > chIndx) && (ch != '\n')) {
430 // ch = str.charAt(chIndx++);
432 // ch2 = str.charAt(chIndx);
435 // token = TokenNameHTML;
446 // } else if (ch == '"') {
449 // TokenNameStringInterpolated,
450 // "Open string character '\"' at end of file.");
452 // } else if (ch == '\'') {
455 // TokenNameStringConstant,
456 // "Open string character \"'\" at end of file.");
458 // } else if (ch == '`') {
461 // TokenNameStringConstant,
462 // "Open string character \"`\" at end of file.");
464 // "Other string delimiters prefered (found \"`\").",
473 // token = TokenNameLPAREN;
477 // token = TokenNameRPAREN;
481 // token = TokenNameLBRACE;
485 // token = TokenNameRBRACE;
489 // token = TokenNameLBRACKET;
493 // token = TokenNameRBRACKET;
497 // token = TokenNameCOMMA;
501 // token = TokenNameQUESTION;
502 // if (str.length() > chIndx) {
503 // if (str.charAt(chIndx) == '>') {
505 // token = TokenNameHTML;
515 // token = TokenNameAT;
518 // token = TokenNameTWIDDLE;
519 // if (str.length() > chIndx) {
520 // if (str.charAt(chIndx) == '=') {
522 // token = TokenNameTWIDDLE_EQUAL;
529 // token = TokenNameDOT;
530 // if (str.length() > chIndx) {
531 // if (str.charAt(chIndx) == '=') {
533 // token = TokenNameDOT_EQUAL;
541 // token = TokenNameStringLiteral;
545 // token = TokenNameREMAINDER;
546 // if (str.length() > chIndx) {
547 // if (str.charAt(chIndx) == '=') {
549 // token = TokenNameREMAINDER_EQUAL;
556 // token = TokenNameSEMICOLON;
560 // token = TokenNameXOR;
561 // if (str.length() > chIndx) {
562 // if (str.charAt(chIndx) == '=') {
564 // token = TokenNameXOR_EQUAL;
571 // token = TokenNameDIVIDE;
573 // if (str.length() > chIndx) {
574 // if (str.charAt(chIndx) == '=') {
576 // token = TokenNameDIVIDE_EQUAL;
584 // token = TokenNameMULTIPLY;
585 // if (str.length() > chIndx) {
586 // if (str.charAt(chIndx) == '*') {
588 // token = TokenNameXOR;
592 // if (str.charAt(chIndx) == '=') {
594 // token = TokenNameMULTIPLY_EQUAL;
602 // token = TokenNamePLUS;
603 // if (str.length() > chIndx) {
604 // if (str.charAt(chIndx) == '+') {
606 // token = TokenNamePLUS_PLUS;
610 // if (str.charAt(chIndx) == '=') {
612 // token = TokenNamePLUS_EQUAL;
619 // token = TokenNameMINUS;
620 // if (str.length() > chIndx) {
621 // if (str.charAt(chIndx) == '-') {
623 // token = TokenNameMINUS_MINUS;
627 // if (str.charAt(chIndx) == '=') {
629 // token = TokenNameMINUS_EQUAL;
633 // if (str.charAt(chIndx) == '>') {
635 // token = TokenNameMINUS_GREATER;
643 // token = TokenNameEQUAL;
645 // if (str.length() > chIndx) {
646 // ch = str.charAt(chIndx);
650 // token = TokenNameEQUAL_EQUAL;
651 // if (str.length() > chIndx) {
652 // ch = str.charAt(chIndx);
657 // TokenNameEQUAL_EQUAL_EQUAL;
664 // token = TokenNameEQUAL_GREATER;
672 // token = TokenNameNOT;
674 // if (str.length() > chIndx) {
675 // if (str.charAt(chIndx) == '=') {
677 // token = TokenNameNOT_EQUAL;
678 // if (str.length() > chIndx) {
679 // ch = str.charAt(chIndx);
684 // TokenNameNOT_EQUAL_EQUAL;
693 // token = TokenNameGREATER;
695 // if (str.length() > chIndx) {
696 // if (str.charAt(chIndx) == '=') {
698 // token = TokenNameGREATER_EQUAL;
701 // if (str.charAt(chIndx) == '>') {
703 // token = TokenNameRIGHT_SHIFT;
704 // if (str.length() > chIndx) {
705 // if (str.charAt(chIndx) == '=') {
708 // TokenNameRIGHT_SHIFT_EQUAL;
718 // token = TokenNameLESS;
720 // if (str.length() > chIndx) {
721 // if (str.charAt(chIndx) == '=') {
723 // token = TokenNameLESS_EQUAL;
727 // if (str.charAt(chIndx) == '<') {
729 // token = TokenNameLEFT_SHIFT;
730 // if (str.charAt(chIndx) == '<') {
732 // int startRow = rowCount;
733 // if (str.length() > chIndx) {
735 // ch = str.charAt(++chIndx);
736 // if ((ch >= 'a' && ch <= 'z')
737 // || (ch >= 'A' && ch <= 'Z')
742 // TokenNameStringConstant;
743 // while (str.length()
759 // .equals(identifier)) {
771 // "Open heredoc syntax after operator '<<<'.",
773 // } else if (str.charAt(chIndx) == '=') {
775 // token = TokenNameLEFT_SHIFT_EQUAL;
785 // token = TokenNameOR;
787 // if (str.length() > chIndx) {
788 // if (str.charAt(chIndx) == '|') {
790 // token = TokenNameOR_OR;
793 // if (str.charAt(chIndx) == '=') {
795 // token = TokenNameOR_EQUAL;
802 // token = TokenNameAND;
803 // if (str.length() > chIndx) {
804 // if (str.charAt(chIndx) == '&') {
806 // token = TokenNameAND_AND;
809 // if (str.charAt(chIndx) == '=') {
811 // token = TokenNameAND_EQUAL;
819 // token = TokenNameCOLON;
820 // if (str.length() > chIndx) {
821 // if (str.charAt(chIndx) == ':') {
823 // token = TokenNameCOLON_COLON;
828 // // token = TokenNameHASH;
832 // // token = TokenNameAT;
837 // "unexpected character: '" + ch + "'");
840 // if (token == TokenNameERROR) {
841 // throwSyntaxError("token not found");
848 // } catch (StringIndexOutOfBoundsException e) {
849 // // catched from charAt
852 // chIndx = str.length() + 1;
854 // token = TokenNameEOF;
857 // // if (phpList != null) {
858 // // if (currentPHPString < phpList.size()) {
859 // // token = TokenNameUNDEFINED;
860 // // temp = (PHPString) phpList.get(currentPHPString++);
861 // // this.str = temp.getPHPString();
862 // // this.token = TokenNameEOF;
863 // // this.chIndx = 0;
864 // // this.rowCount = temp.getLineNumber();
865 // // this.columnCount = 0;
866 // // getNextToken();
869 // // token = TokenNameUNDEFINED;
876 // * Get an identifier.
878 // private void getIdentifier() {
879 // // StringBuffer ident = new StringBuffer();
880 // int startPosition = chIndx - 1;
881 // // ident.append(ch);
884 // // attention recursive call:
886 // token = TokenNameVariable;
889 // token = TokenNameIdentifier;
894 // //this will read the buffer until the next character is a forbidden character for identifier
895 // while ((ch >= 'a' && ch <= 'z')
896 // || (ch >= 'A' && ch <= 'Z')
897 // || (ch >= '0' && ch <= '9')
899 // // ident.append(ch);
902 // int endPosition = chIndx--;
903 // int length = (--endPosition) - startPosition;
905 // identifier = str.substring(startPosition, endPosition);
906 // // System.out.println(identifier);
908 // // determine if this identitfer is a keyword
909 // // @todo improve this in future version
910 // Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
912 // token = i.intValue();
918 * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
919 * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
920 * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
921 * value {@link Parser#TokenNameINT_NUMBER}
923 // private void getNumber() {
924 // StringBuffer inum = new StringBuffer();
926 // int numFormat = 10;
928 // // save first digit
929 // char firstCh = ch;
933 // // determine number conversions:
934 // if (firstCh == '0') {
963 // if (numFormat == 16) {
964 // while ((ch >= '0' && ch <= '9')
965 // || (ch >= 'a' && ch <= 'f')
966 // || (ch >= 'A' && ch <= 'F')) {
971 // while ((ch >= '0' && ch <= '9')
975 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
976 // if (ch == '.' && dFlag != ' ') {
979 // if ((dFlag == 'E') || (dFlag == 'e')) {
985 // if ((ch == '-') || (ch == '+')) {
998 // if (dFlag != ' ') {
999 // doubleNumber = new Double(inum.toString());
1000 // token = TokenNameDoubleLiteral;
1003 // longNumber = Long.valueOf(inum.toString(), numFormat);
1004 // token = TokenNameIntegerLiteral;
1008 // } catch (Throwable e) {
1009 // throwSyntaxError("Number format error: " + inum.toString());
1015 // * @param openChar the opening char ('\'', '"', '`')
1016 // * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
1017 // * @param errorMsg the error message in case of parse error in the string
1019 // private void getString(
1020 // final char openChar,
1021 // final int typeString,
1022 // final String errorMsg) {
1023 // StringBuffer sBuffer = new StringBuffer();
1024 // boolean openString = true;
1025 // int startRow = rowCount;
1026 // while (str.length() > chIndx) {
1027 // ch = str.charAt(chIndx++);
1028 // if (ch == '\\') {
1029 // sBuffer.append(ch);
1030 // if (str.length() > chIndx) {
1031 // ch = str.charAt(chIndx++);
1032 // sBuffer.append(ch);
1034 // } else if (ch == openChar) {
1035 // openString = false;
1037 // } else if (ch == '\n') {
1039 // columnCount = chIndx;
1041 // sBuffer.append(ch);
1044 // if (openString) {
1045 // if (typeString == TokenNameStringConstant) {
1046 // throwSyntaxError(errorMsg, startRow);
1048 // throwSyntaxError(errorMsg);
1051 // token = typeString;
1052 // stringValue = sBuffer.toString();
1055 // public void htmlParserTester(String input) {
1056 // int lineNumber = 1;
1057 // int startLineNumber = 1;
1058 // int startIndex = 0;
1061 // boolean phpMode = false;
1062 // boolean phpFound = false;
1064 // phpList = new ArrayList();
1065 // currentPHPString = 0;
1069 // while (i < input.length()) {
1070 // ch = input.charAt(i++);
1071 // if (ch == '\n') {
1074 // if ((!phpMode) && ch == '<') {
1075 // ch2 = input.charAt(i++);
1076 // if (ch2 == '?') {
1077 // ch2 = input.charAt(i++);
1078 // if (Character.isWhitespace(ch2)) {
1083 // startLineNumber = lineNumber;
1085 // } else if (ch2 == 'p') {
1086 // ch2 = input.charAt(i++);
1087 // if (ch2 == 'h') {
1088 // ch2 = input.charAt(i++);
1089 // if (ch2 == 'p') {
1093 // startLineNumber = lineNumber;
1099 // } else if (ch2 == 'P') {
1100 // ch2 = input.charAt(i++);
1101 // if (ch2 == 'H') {
1102 // ch2 = input.charAt(i++);
1103 // if (ch2 == 'P') {
1107 // startLineNumber = lineNumber;
1120 // if (ch == '/' && i < input.length()) {
1121 // ch2 = input.charAt(i++);
1122 // if (ch2 == '/') {
1123 // while (i < input.length()) {
1124 // ch = input.charAt(i++);
1125 // if (ch == '?' && i < input.length()) {
1126 // ch2 = input.charAt(i++);
1127 // if (ch2 == '>') {
1135 // startLineNumber));
1139 // } else if (ch == '\n') {
1145 // } else if (ch2 == '*') {
1146 // // multi-line comment
1147 // while (i < input.length()) {
1148 // ch = input.charAt(i++);
1149 // if (ch == '\n') {
1151 // } else if (ch == '*' && i < input.length()) {
1152 // ch2 = input.charAt(i++);
1153 // if (ch2 == '/') {
1163 // } else if (ch == '#') {
1164 // while (i < input.length()) {
1165 // ch = input.charAt(i++);
1166 // if (ch == '?' && i < input.length()) {
1167 // ch2 = input.charAt(i++);
1168 // if (ch2 == '>') {
1173 // input.substring(startIndex, i - 2),
1174 // startLineNumber));
1178 // } else if (ch == '\n') {
1184 // } else if (ch == '"') {
1186 // while (i < input.length()) {
1187 // ch = input.charAt(i++);
1188 // if (ch == '\n') {
1191 // ch == '\\' && i < input.length()) { // escape
1193 // } else if (ch == '"') {
1198 // } else if (ch == '\'') {
1200 // while (i < input.length()) {
1201 // ch = input.charAt(i++);
1202 // if (ch == '\n') {
1205 // ch == '\\' && i < input.length()) { // escape
1207 // } else if (ch == '\'') {
1214 // if (ch == '?' && i < input.length()) {
1215 // ch2 = input.charAt(i++);
1216 // if (ch2 == '>') {
1221 // input.substring(startIndex, i - 2),
1222 // startLineNumber));
1232 // "No PHP source code found.",
1238 // "Open PHP tag at end of file.",
1243 // input.substring(startIndex, i - 2),
1244 // startLineNumber));
1246 // // for (int j=0;j<phpList.size();j++) {
1247 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
1248 // // int startIndx = temp.length()-10;
1249 // // if (startIndx<0) {
1250 // // startIndx = 0;
1252 // // System.out.println(temp.substring(startIndx)+"?>");
1254 // phpParserTester(null, 1);
1255 // // PHPString temp;
1256 // // for(int j=0;j<phpList.size();j++) {
1257 // // temp = (PHPString) phpList.get(j);
1258 // // parser.start(temp.getPHPString(), temp.getLineNumber());
1261 // } catch (CoreException e) {
1265 public void phpParserTester(String s, int rowCount) throws CoreException {
1268 if (phpList.size() != 0) {
1269 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
1272 this.token = TokenNameEOF;
1274 // this.rowCount = rowCount;
1275 // this.columnCount = 0;
1276 this.phpEnd = false;
1277 this.phpMode = true;
1278 scanner.setSource(s.toCharArray());
1279 scanner.setPHPMode(true);
1283 if (token != TokenNameEOF && token != TokenNameERROR) {
1286 if (token != TokenNameEOF && token != TokenNameERROR) {
1287 if (token == TokenNameRPAREN) {
1288 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1290 if (token == TokenNameRBRACE) {
1291 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1293 if (token == TokenNameRBRACKET) {
1294 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1297 if (token == TokenNameLPAREN) {
1298 throwSyntaxError("Read character '('; end-of-file not reached.");
1300 if (token == TokenNameLBRACE) {
1301 throwSyntaxError("Read character '{'; end-of-file not reached.");
1303 if (token == TokenNameLBRACKET) {
1304 throwSyntaxError("Read character '['; end-of-file not reached.");
1307 throwSyntaxError("End-of-file not reached.");
1310 } catch (SyntaxError err) {
1314 // setMarker(err.getMessage(), err.getLine(), ERROR);
1317 scanner.getCurrentTokenStartPosition(),
1318 scanner.getCurrentTokenEndPosition(),
1321 // if an error occured,
1322 // try to find keywords 'class' or 'function'
1323 // to parse the rest of the string
1324 while (token != TokenNameEOF && token != TokenNameERROR) {
1325 if (token == TokenNameclass || token == TokenNamefunction) {
1330 if (token == TokenNameEOF || token == TokenNameERROR) {
1339 * Parses a string with php tags
1340 * i.e. '<body> <?php phpinfo() ?> </body>'
1342 public void parse(String s) throws CoreException {
1344 this.token = TokenNameEOF;
1346 // this.rowCount = 1;
1347 // this.columnCount = 0;
1348 this.phpEnd = false;
1349 this.phpMode = false;
1350 /* scanner initialization */
1351 scanner.setSource(s.toCharArray());
1352 scanner.setPHPMode(false);
1356 if (token != TokenNameEOF && token != TokenNameERROR) {
1359 if (token != TokenNameEOF && token != TokenNameERROR) {
1360 if (token == TokenNameRPAREN) {
1361 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1363 if (token == TokenNameRBRACE) {
1364 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1366 if (token == TokenNameRBRACKET) {
1367 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1370 if (token == TokenNameLPAREN) {
1371 throwSyntaxError("Read character '('; end-of-file not reached.");
1373 if (token == TokenNameLBRACE) {
1374 throwSyntaxError("Read character '{'; end-of-file not reached.");
1376 if (token == TokenNameLBRACKET) {
1377 throwSyntaxError("Read character '['; end-of-file not reached.");
1380 throwSyntaxError("End-of-file not reached.");
1383 } catch (SyntaxError sytaxErr1) {
1384 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
1386 sytaxErr1.getMessage(),
1387 scanner.getCurrentTokenStartPosition(),
1388 scanner.getCurrentTokenEndPosition(),
1391 // if an error occured,
1392 // try to find keywords 'class' or 'function'
1393 // to parse the rest of the string
1394 while (token != TokenNameEOF && token != TokenNameERROR) {
1395 if (token == TokenNameclass || token == TokenNamefunction) {
1400 if (token == TokenNameEOF || token == TokenNameERROR) {
1403 } catch (SyntaxError sytaxErr2) {
1404 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
1406 sytaxErr2.getMessage(),
1407 scanner.getCurrentTokenStartPosition(),
1408 scanner.getCurrentTokenEndPosition(),
1417 public PHPOutlineInfo parseInfo(Object parent, String s) {
1418 PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
1419 // Stack stack = new Stack();
1420 // stack.push(outlineInfo.getDeclarations());
1423 this.token = TokenNameEOF;
1425 // this.rowCount = 1;
1426 // this.columnCount = 0;
1427 this.phpEnd = false;
1428 this.phpMode = false;
1429 scanner.setSource(s.toCharArray());
1430 scanner.setPHPMode(false);
1434 parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
1435 } catch (CoreException e) {
1440 private void parseDeclarations(
1441 PHPOutlineInfo outlineInfo,
1442 PHPSegmentWithChildren current,
1445 // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
1446 PHPSegmentWithChildren temp;
1449 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
1451 while (token != TokenNameEOF && token != TokenNameERROR) {
1452 if (token == TokenNameVariable) {
1453 ident = scanner.getCurrentIdentifierSource();
1454 outlineInfo.addVariable(new String(ident));
1456 } else if (token == TokenNamevar) {
1458 if (token == TokenNameVariable
1459 && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
1460 ident = scanner.getCurrentIdentifierSource();
1461 String variableName = new String(ident);
1462 outlineInfo.addVariable(variableName);
1464 if (token != TokenNameSEMICOLON) {
1467 ident = scanner.getCurrentTokenSource();
1468 if (token > TokenNameKEYWORD) {
1469 current.add(new PHPVarDeclaration(current, variableName,
1470 // chIndx - ident.length,
1471 scanner.getCurrentTokenStartPosition(), new String(ident)));
1474 case TokenNameVariable :
1475 current.add(new PHPVarDeclaration(current, variableName,
1476 // chIndx - ident.length,
1477 scanner.getCurrentTokenStartPosition(), new String(ident)));
1479 case TokenNameIdentifier :
1480 current.add(new PHPVarDeclaration(current, variableName,
1481 // chIndx - ident.length,
1482 scanner.getCurrentTokenStartPosition(), new String(ident)));
1484 case TokenNameDoubleLiteral :
1486 .add(new PHPVarDeclaration(
1488 variableName + doubleNumber,
1489 // chIndx - ident.length,
1490 scanner.getCurrentTokenStartPosition(), new String(ident)));
1492 case TokenNameIntegerLiteral :
1493 current.add(new PHPVarDeclaration(current, variableName,
1494 // chIndx - ident.length,
1495 scanner.getCurrentTokenStartPosition(), new String(ident)));
1497 case TokenNameStringInterpolated :
1498 case TokenNameStringLiteral :
1499 current.add(new PHPVarDeclaration(current, variableName,
1500 // chIndx - ident.length,
1501 scanner.getCurrentTokenStartPosition(), new String(ident)));
1503 case TokenNameStringConstant :
1504 current.add(new PHPVarDeclaration(current, variableName,
1505 // chIndx - ident.length,
1506 scanner.getCurrentTokenStartPosition(), new String(ident)));
1509 current.add(new PHPVarDeclaration(current, variableName,
1510 // chIndx - ident.length
1511 scanner.getCurrentTokenStartPosition()));
1517 ident = scanner.getCurrentIdentifierSource();
1519 current.add(new PHPVarDeclaration(current, variableName,
1520 // chIndx - ident.length
1521 scanner.getCurrentTokenStartPosition()));
1524 } else if (token == TokenNamefunction) {
1526 if (token == TokenNameAND) {
1529 if (token == TokenNameIdentifier
1530 && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
1531 ident = scanner.getCurrentIdentifierSource();
1532 outlineInfo.addVariable(new String(ident));
1533 temp = new PHPFunctionDeclaration(current, new String(ident),
1534 // chIndx - ident.length
1535 scanner.getCurrentTokenStartPosition());
1538 parseDeclarations(outlineInfo, temp, true);
1540 } else if (token == TokenNameclass) {
1542 if (token == TokenNameIdentifier
1543 && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
1544 ident = scanner.getCurrentIdentifierSource();
1545 outlineInfo.addVariable(new String(ident));
1546 temp = new PHPClassDeclaration(current, new String(ident),
1547 // chIndx - ident.len
1548 scanner.getCurrentTokenStartPosition());
1550 // stack.push(temp);
1553 //skip tokens for classname, extends and others until we have the opening '{'
1554 while (token != TokenNameLBRACE
1555 && token != TokenNameEOF
1556 && token != TokenNameERROR) {
1559 parseDeclarations(outlineInfo, temp, true);
1562 } else if (token == TokenNameLBRACE) {
1565 } else if (token == TokenNameRBRACE) {
1568 if (counter == 0 && goBack) {
1572 token == TokenNamerequire
1573 || token == TokenNamerequire_once
1574 || token == TokenNameinclude
1575 || token == TokenNameinclude_once) {
1576 ident = scanner.getCurrentTokenSource();
1579 int startPosition = scanner.getCurrentTokenStartPosition();
1581 char[] expr = scanner.getCurrentTokenSource(startPosition);
1582 outlineInfo.addVariable(new String(ident));
1583 current.add(new PHPReqIncDeclaration(current, new String(ident),
1584 // chIndx - ident.length,
1585 startPosition, new String(expr)));
1591 } catch (CoreException e) {
1592 } catch (SyntaxError sytaxErr) {
1594 // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
1596 sytaxErr.getMessage(),
1597 scanner.getCurrentTokenStartPosition(),
1598 scanner.getCurrentTokenEndPosition(),
1600 } catch (CoreException e) {
1605 private void statementList() throws CoreException {
1608 if ((token == TokenNameRBRACE)
1609 || (token == TokenNamecase)
1610 || (token == TokenNamedefault)
1611 || (token == TokenNameelseif)
1612 || (token == TokenNameendif)
1613 || (token == TokenNameendfor)
1614 || (token == TokenNameendforeach)
1615 || (token == TokenNameendwhile)
1616 || (token == TokenNameendswitch)
1617 || (token == TokenNameEOF)
1618 || (token == TokenNameERROR)) {
1624 private void compoundStatement() throws CoreException {
1625 // '{' [statement-list] '}'
1626 if (token == TokenNameLBRACE) {
1629 throwSyntaxError("'{' expected in compound-statement.");
1631 if (token != TokenNameRBRACE) {
1634 if (token == TokenNameRBRACE) {
1637 throwSyntaxError("'}' expected in compound-statement.");
1641 private void statement() throws CoreException {
1642 // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
1643 // char[] ident = scanner.getCurrentIdentifierSource();
1644 // String keyword = new String(ident);
1645 if (token == TokenNameinclude || token == TokenNameinclude_once) {
1648 if (token == TokenNameSEMICOLON) {
1651 if (token != TokenNameStopPHP) {
1652 throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1657 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1661 if (token == TokenNameSEMICOLON) {
1664 if (token != TokenNameStopPHP) {
1665 throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1670 } else if (token == TokenNameif) {
1672 if (token == TokenNameLPAREN) {
1675 throwSyntaxError("'(' expected after 'if' keyword.");
1678 if (token == TokenNameRPAREN) {
1681 throwSyntaxError("')' expected after 'if' condition.");
1686 } else if (token == TokenNameswitch) {
1688 if (token == TokenNameLPAREN) {
1691 throwSyntaxError("'(' expected after 'switch' keyword.");
1694 if (token == TokenNameRPAREN) {
1697 throwSyntaxError("')' expected after 'switch' condition.");
1701 } else if (token == TokenNamefor) {
1703 if (token == TokenNameLPAREN) {
1706 throwSyntaxError("'(' expected after 'for' keyword.");
1708 if (token == TokenNameSEMICOLON) {
1712 if (token == TokenNameSEMICOLON) {
1715 throwSyntaxError("';' expected after 'for'.");
1718 if (token == TokenNameSEMICOLON) {
1722 if (token == TokenNameSEMICOLON) {
1725 throwSyntaxError("';' expected after 'for'.");
1728 if (token == TokenNameRPAREN) {
1732 if (token == TokenNameRPAREN) {
1735 throwSyntaxError("')' expected after 'for'.");
1740 } else if (token == TokenNamewhile) {
1742 if (token == TokenNameLPAREN) {
1745 throwSyntaxError("'(' expected after 'while' keyword.");
1748 if (token == TokenNameRPAREN) {
1751 throwSyntaxError("')' expected after 'while' condition.");
1755 } else if (token == TokenNamedo) {
1757 if (token == TokenNameLBRACE) {
1760 throwSyntaxError("'{' expected after 'do' keyword.");
1762 if (token != TokenNameRBRACE) {
1765 if (token == TokenNameRBRACE) {
1768 throwSyntaxError("'}' expected after 'do' keyword.");
1770 if (token == TokenNamewhile) {
1772 if (token == TokenNameLPAREN) {
1775 throwSyntaxError("'(' expected after 'while' keyword.");
1778 if (token == TokenNameRPAREN) {
1781 throwSyntaxError("')' expected after 'while' condition.");
1784 throwSyntaxError("'while' expected after 'do' keyword.");
1786 if (token == TokenNameSEMICOLON) {
1789 if (token != TokenNameStopPHP) {
1790 throwSyntaxError("';' expected after do-while statement.");
1795 } else if (token == TokenNameforeach) {
1797 if (token == TokenNameLPAREN) {
1800 throwSyntaxError("'(' expected after 'foreach' keyword.");
1803 if (token == TokenNameas) {
1806 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1809 if (token == TokenNameEQUAL_GREATER) {
1813 if (token == TokenNameRPAREN) {
1816 throwSyntaxError("')' expected after 'foreach' expression.");
1822 token == TokenNamecontinue
1823 || token == TokenNamebreak
1824 || token == TokenNamereturn) {
1826 if (token != TokenNameSEMICOLON) {
1829 if (token == TokenNameSEMICOLON) {
1832 if (token != TokenNameStopPHP) {
1833 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1839 } else if (token == TokenNameecho) {
1842 if (token == TokenNameSEMICOLON) {
1845 if (token != TokenNameStopPHP) {
1846 throwSyntaxError("';' expected after 'echo' statement.");
1851 // } else if (token == TokenNameprint) {
1854 // if (token == TokenNameSEMICOLON) {
1857 // if (token != TokenNameStopPHP) {
1858 // throwSyntaxError("';' expected after 'print' statement.");
1864 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1867 if (token == TokenNameSEMICOLON) {
1870 if (token != TokenNameStopPHP) {
1871 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1877 // } else if (token == TokenNameunset) {
1879 // if (token == TokenNameARGOPEN) {
1882 // throwSyntaxError("'(' expected after 'unset' keyword.");
1885 // if (token == TokenNameARGCLOSE) {
1888 // throwSyntaxError("')' expected after 'unset' statement.");
1890 // if (token == TokenNameSEMICOLON) {
1893 // if (token != TokenNameStopPHP) {
1894 // throwSyntaxError("';' expected after 'unset' statement.");
1900 // } else if (token == TokenNameexit || token == TokenNamedie) {
1902 // if (token != TokenNameSEMICOLON) {
1905 // if (token == TokenNameSEMICOLON) {
1908 // if (token != TokenNameStopPHP) {
1909 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1915 } else if (token == TokenNamedefine) {
1917 if (token == TokenNameLPAREN) {
1920 throwSyntaxError("'(' expected after 'define' keyword.");
1923 if (token == TokenNameCOMMA) {
1926 throwSyntaxError("',' expected after first 'define' constant.");
1929 if (token == TokenNameCOMMA) {
1933 if (token == TokenNameRPAREN) {
1936 throwSyntaxError("')' expected after 'define' statement.");
1938 if (token == TokenNameSEMICOLON) {
1941 if (token != TokenNameStopPHP) {
1942 throwSyntaxError("';' expected after 'define' statement.");
1947 } else if (token == TokenNamefunction) {
1949 functionDefinition();
1951 } else if (token == TokenNameclass) {
1957 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1958 } else if (token == TokenNameLBRACE) {
1959 // compoundStatement
1961 if (token != TokenNameRBRACE) {
1964 if (token == TokenNameRBRACE) {
1968 throwSyntaxError("'}' expected.");
1971 if (token != TokenNameSEMICOLON) {
1974 if (token == TokenNameSEMICOLON) {
1978 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1980 "';' expected after expression (Found token: "
1981 + scanner.toStringAction(token)
1989 private void classDeclarator() throws CoreException {
1991 //identifier 'extends' identifier
1992 if (token == TokenNameIdentifier) {
1994 if (token == TokenNameextends) {
1996 if (token == TokenNameIdentifier) {
1999 throwSyntaxError("Class name expected after keyword 'extends'.");
2003 throwSyntaxError("Class name expected after keyword 'class'.");
2007 private void classBody() throws CoreException {
2008 //'{' [class-element-list] '}'
2009 if (token == TokenNameLBRACE) {
2011 if (token != TokenNameRBRACE) {
2014 if (token == TokenNameRBRACE) {
2017 throwSyntaxError("'}' expected at end of class body.");
2020 throwSyntaxError("'{' expected at start of class body.");
2024 private void classElementList() throws CoreException {
2027 } while (token == TokenNamefunction || token == TokenNamevar);
2030 private void classElement() throws CoreException {
2032 //function-definition
2033 if (token == TokenNamefunction) {
2035 functionDefinition();
2036 } else if (token == TokenNamevar) {
2040 throwSyntaxError("'function' or 'var' expected.");
2044 private void classProperty() throws CoreException {
2045 //'var' variable ';'
2046 //'var' variable '=' constant ';'
2048 if (token == TokenNameVariable) {
2050 if (token == TokenNameEQUAL) {
2055 throwSyntaxError("Variable expected after keyword 'var'.");
2057 if (token != TokenNameCOMMA) {
2062 if (token == TokenNameSEMICOLON) {
2065 throwSyntaxError("';' expected after variable declaration.");
2069 private void functionDefinition() throws CoreException {
2070 functionDeclarator();
2071 compoundStatement();
2074 private void functionDeclarator() throws CoreException {
2075 //identifier '(' [parameter-list] ')'
2076 if (token == TokenNameAND) {
2079 if (token == TokenNameIdentifier) {
2081 if (token == TokenNameLPAREN) {
2084 throwSyntaxError("'(' expected in function declaration.");
2086 if (token != TokenNameRPAREN) {
2089 if (token != TokenNameRPAREN) {
2090 throwSyntaxError("')' expected in function declaration.");
2097 private void parameterList() throws CoreException {
2098 //parameter-declaration
2099 //parameter-list ',' parameter-declaration
2101 parameterDeclaration();
2102 if (token != TokenNameCOMMA) {
2109 private void parameterDeclaration() throws CoreException {
2111 //variable-reference
2112 if (token == TokenNameAND) {
2114 if (token == TokenNameVariable) {
2117 throwSyntaxError("Variable expected after reference operator '&'.");
2120 //variable '=' constant
2121 if (token == TokenNameVariable) {
2123 if (token == TokenNameEQUAL) {
2131 private void labeledStatementList() throws CoreException {
2132 if (token != TokenNamecase && token != TokenNamedefault) {
2133 throwSyntaxError("'case' or 'default' expected.");
2136 if (token == TokenNamecase) {
2139 if (token == TokenNameCOLON) {
2141 if (token == TokenNamecase
2142 || token == TokenNamedefault) { // empty case statement ?
2146 } else if (token == TokenNameSEMICOLON) {
2148 // "':' expected after 'case' keyword (Found token: "
2149 // + scanner.toStringAction(token)
2154 "':' expected after 'case' keyword (Found token: "
2155 + scanner.toStringAction(token)
2157 scanner.getCurrentTokenStartPosition(),
2158 scanner.getCurrentTokenEndPosition(),
2161 if (token == TokenNamecase) { // empty case statement ?
2167 "':' character after 'case' constant expected (Found token: "
2168 + scanner.toStringAction(token)
2171 } else { // TokenNamedefault
2173 if (token == TokenNameCOLON) {
2177 throwSyntaxError("':' character after 'default' expected.");
2180 } while (token == TokenNamecase || token == TokenNamedefault);
2183 // public void labeledStatement() {
2184 // if (token == TokenNamecase) {
2187 // if (token == TokenNameDDOT) {
2191 // throwSyntaxError("':' character after 'case' constant expected.");
2194 // } else if (token == TokenNamedefault) {
2196 // if (token == TokenNameDDOT) {
2200 // throwSyntaxError("':' character after 'default' expected.");
2206 // public void expressionStatement() {
2209 // private void inclusionStatement() {
2212 // public void compoundStatement() {
2215 // public void selectionStatement() {
2218 // public void iterationStatement() {
2221 // public void jumpStatement() {
2224 // public void outputStatement() {
2227 // public void scopeStatement() {
2230 // public void flowStatement() {
2233 // public void definitionStatement() {
2236 private void ifStatement() throws CoreException {
2237 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
2238 if (token == TokenNameCOLON) {
2242 case TokenNameelse :
2244 if (token == TokenNameCOLON) {
2248 if (token == TokenNameif) { //'else if'
2250 elseifStatementList();
2252 throwSyntaxError("':' expected after 'else'.");
2256 case TokenNameelseif :
2258 elseifStatementList();
2262 if (token != TokenNameendif) {
2263 throwSyntaxError("'endif' expected.");
2266 if (token != TokenNameSEMICOLON) {
2267 throwSyntaxError("';' expected after if-statement.");
2271 // statement [else-statement]
2273 if (token == TokenNameelseif) {
2275 if (token == TokenNameLPAREN) {
2278 throwSyntaxError("'(' expected after 'elseif' keyword.");
2281 if (token == TokenNameRPAREN) {
2284 throwSyntaxError("')' expected after 'elseif' condition.");
2287 } else if (token == TokenNameelse) {
2294 private void elseifStatementList() throws CoreException {
2298 case TokenNameelse :
2300 if (token == TokenNameCOLON) {
2305 if (token == TokenNameif) { //'else if'
2308 throwSyntaxError("':' expected after 'else'.");
2312 case TokenNameelseif :
2321 private void elseifStatement() throws CoreException {
2322 if (token == TokenNameLPAREN) {
2325 if (token != TokenNameLPAREN) {
2326 throwSyntaxError("')' expected in else-if-statement.");
2329 if (token != TokenNameCOLON) {
2330 throwSyntaxError("':' expected in else-if-statement.");
2337 private void switchStatement() throws CoreException {
2338 if (token == TokenNameCOLON) {
2339 // ':' [labeled-statement-list] 'endswitch' ';'
2341 labeledStatementList();
2342 if (token != TokenNameendswitch) {
2343 throwSyntaxError("'endswitch' expected.");
2346 if (token != TokenNameSEMICOLON) {
2347 throwSyntaxError("';' expected after switch-statement.");
2351 // '{' [labeled-statement-list] '}'
2352 if (token != TokenNameLBRACE) {
2353 throwSyntaxError("'{' expected in switch statement.");
2356 if (token != TokenNameRBRACE) {
2357 labeledStatementList();
2359 if (token != TokenNameRBRACE) {
2360 throwSyntaxError("'}' expected in switch statement.");
2367 private void forStatement() throws CoreException {
2368 if (token == TokenNameCOLON) {
2371 if (token != TokenNameendfor) {
2372 throwSyntaxError("'endfor' expected.");
2375 if (token != TokenNameSEMICOLON) {
2376 throwSyntaxError("';' expected after for-statement.");
2384 private void whileStatement() throws CoreException {
2385 // ':' statement-list 'endwhile' ';'
2386 if (token == TokenNameCOLON) {
2389 if (token != TokenNameendwhile) {
2390 throwSyntaxError("'endwhile' expected.");
2393 if (token != TokenNameSEMICOLON) {
2394 throwSyntaxError("';' expected after while-statement.");
2402 private void foreachStatement() throws CoreException {
2403 if (token == TokenNameCOLON) {
2406 if (token != TokenNameendforeach) {
2407 throwSyntaxError("'endforeach' expected.");
2410 if (token != TokenNameSEMICOLON) {
2411 throwSyntaxError("';' expected after foreach-statement.");
2419 private void exitStatus() throws CoreException {
2420 if (token == TokenNameLPAREN) {
2423 throwSyntaxError("'(' expected in 'exit-status'.");
2425 if (token != TokenNameRPAREN) {
2428 if (token == TokenNameRPAREN) {
2431 throwSyntaxError("')' expected after 'exit-status'.");
2435 private void expressionList() throws CoreException {
2438 if (token == TokenNameCOMMA) {
2446 private void expression() throws CoreException {
2447 //todo: find a better way to get the expression
2448 // expression = new StringBuffer();
2449 // for (int i = chIndx; i < str.length(); i++) {
2450 // if (str.charAt(i) == ';') {
2453 // expression.append(str.charAt(i));
2456 // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
2459 logicalinclusiveorExpression();
2460 // while (token != TokenNameSEMICOLON) {
2466 private void postfixExpression() throws CoreException {
2469 boolean castFlag = false;
2475 case TokenNamenull :
2478 case TokenNamefalse :
2481 case TokenNametrue :
2484 case TokenNameStringConstant :
2487 case TokenNameHEREDOC :
2488 case TokenNameStringInterpolated :
2489 case TokenNameStringLiteral :
2492 case TokenNameLPAREN :
2494 if (token == TokenNameIdentifier) {
2495 // check if identifier is a type:
2496 // ident = identifier;
2497 ident = scanner.getCurrentIdentifierSource();
2498 String str = new String(ident).toLowerCase();
2499 for (int i = 0; i < PHP_TYPES.length; i++) {
2500 if (PHP_TYPES[i].equals(str)) {
2507 if (token != TokenNameRPAREN) {
2508 throwSyntaxError(") expected after cast-type '" + str + "'.");
2518 if (token != TokenNameRPAREN) {
2519 throwSyntaxError(") expected in postfix-expression.");
2523 case TokenNameDoubleLiteral :
2526 case TokenNameIntegerLiteral :
2529 case TokenNameDOLLAR_LBRACE :
2532 if (token != TokenNameRBRACE) {
2533 throwSyntaxError("'}' expected after indirect variable token '${'.");
2537 case TokenNameVariable :
2538 ident = scanner.getCurrentIdentifierSource();
2540 if (token == TokenNameLBRACE) {
2543 if (token != TokenNameRBRACE) {
2545 "'}' expected after variable '"
2547 + "' in variable-expression.");
2550 } else if (token == TokenNameLPAREN) {
2552 if (token != TokenNameRPAREN) {
2554 if (token != TokenNameRPAREN) {
2556 "')' expected after variable '"
2558 + "' in postfix-expression.");
2564 case TokenNameIdentifier :
2565 ident = scanner.getCurrentIdentifierSource();
2567 if (token == TokenNameLPAREN) {
2569 if (token != TokenNameRPAREN) {
2571 if (token != TokenNameRPAREN) {
2573 "')' expected after identifier '"
2575 + "' in postfix-expression."
2577 + scanner.toStringAction(token)
2584 case TokenNameprint :
2587 // if (token == TokenNameSEMICOLON) {
2590 // if (token != TokenNameStopPHP) {
2591 // throwSyntaxError("';' expected after 'print' statement.");
2596 case TokenNamelist :
2598 if (token == TokenNameLPAREN) {
2600 if (token == TokenNameCOMMA) {
2604 if (token != TokenNameRPAREN) {
2605 throwSyntaxError("')' expected after 'list' keyword.");
2608 // if (token == TokenNameSET) {
2610 // logicalinclusiveorExpression();
2613 throwSyntaxError("'(' expected after 'list' keyword.");
2616 // case TokenNameexit :
2618 // if (token != TokenNameSEMICOLON) {
2621 // if (token == TokenNameSEMICOLON) {
2624 // if (token != TokenNameStopPHP) {
2625 // throwSyntaxError("';' expected after 'exit' expression.");
2630 // case TokenNamedie :
2632 // if (token != TokenNameSEMICOLON) {
2635 // if (token == TokenNameSEMICOLON) {
2638 // if (token != TokenNameStopPHP) {
2639 // throwSyntaxError("';' expected after 'die' expression.");
2644 // case TokenNamearray :
2646 // if (token == TokenNameARGOPEN) {
2648 // if (token == TokenNameCOMMA) {
2651 // expressionList();
2652 // if (token != TokenNameARGCLOSE) {
2653 // throwSyntaxError("')' expected after 'list' keyword.");
2656 // if (token == TokenNameSET) {
2658 // logicalinclusiveorExpression();
2661 // throwSyntaxError("'(' expected after 'list' keyword.");
2665 boolean while_flag = true;
2668 case TokenNameLBRACKET :
2671 if (token != TokenNameRBRACKET) {
2672 throwSyntaxError("] expected in postfix-expression.");
2676 case TokenNameCOLON_COLON : // ::
2677 case TokenNameMINUS_GREATER : // ->
2679 if (token > TokenNameKEYWORD) {
2680 ident = scanner.getCurrentIdentifierSource();
2682 // "Avoid using keyword '"
2683 // + new String(ident)
2684 // + "' as variable name.",
2688 "Avoid using keyword '"
2690 + "' as variable name.",
2691 scanner.getCurrentTokenStartPosition(),
2692 scanner.getCurrentTokenEndPosition(),
2696 case TokenNameVariable :
2697 ident = scanner.getCurrentIdentifierSource();
2699 // if (token == TokenNameARGOPEN) {
2701 // expressionList();
2702 // if (token != TokenNameARGCLOSE) {
2703 // throwSyntaxError(") expected after variable '" + ident + "'.");
2708 case TokenNameIdentifier :
2709 //ident = scanner.getCurrentIdentifierSource();
2712 case TokenNameLBRACE :
2715 if (token != TokenNameRBRACE) {
2716 throwSyntaxError("} expected in postfix-expression.");
2721 throwSyntaxError("Syntax error after '->' token.");
2723 token == TokenNameLBRACKET
2724 || token == TokenNameLPAREN
2725 || token == TokenNameLBRACE) {
2726 if (token == TokenNameLBRACKET) {
2729 if (token != TokenNameRBRACKET) {
2730 throwSyntaxError("] expected after '->'.");
2734 if (token == TokenNameLPAREN) {
2737 if (token != TokenNameRPAREN) {
2738 throwSyntaxError(") expected after '->'.");
2742 if (token == TokenNameLBRACE) {
2745 if (token != TokenNameRBRACE) {
2746 throwSyntaxError("} expected after '->'.");
2752 case TokenNamePLUS_PLUS :
2755 case TokenNameMINUS_MINUS :
2766 private void unaryExpression() throws CoreException {
2768 case TokenNamePLUS_PLUS :
2772 case TokenNameMINUS_MINUS :
2776 // '@' '&' '*' '+' '-' '~' '!'
2785 case TokenNameMULTIPLY :
2789 case TokenNamePLUS :
2793 case TokenNameMINUS :
2797 case TokenNameTWIDDLE :
2806 postfixExpression();
2810 private void castExpression() throws CoreException {
2811 // if (token == TokenNameARGOPEN) {
2814 // if (token != TokenNameARGCLOSE) {
2815 // throwSyntaxError(") expected after cast-expression.");
2822 private void typeName() throws CoreException {
2823 //'string' 'unset' 'array' 'object'
2825 //'real' 'double' 'float'
2827 String identifier = "";
2828 if (token == TokenNameIdentifier) {
2829 char[] ident = scanner.getCurrentIdentifierSource();
2830 identifier = new String(ident);
2831 String str = identifier.toLowerCase();
2833 for (int i = 0; i < PHP_TYPES.length; i++) {
2834 if (PHP_TYPES[i].equals(str)) {
2840 "Expected type cast '( <type-name> )'; Got '" + identifier + "'.");
2843 private void assignExpression() throws CoreException {
2845 if (token == TokenNameEQUAL) { // =
2847 logicalinclusiveorExpression();
2848 } else if (token == TokenNameDOT_EQUAL) { // .=
2850 logicalinclusiveorExpression();
2851 } else if (token == TokenNameEQUAL_GREATER) { // =>
2853 logicalinclusiveorExpression();
2854 } else if (token == TokenNamePLUS_EQUAL) { // +=
2856 logicalinclusiveorExpression();
2857 } else if (token == TokenNameMINUS_EQUAL) { // -=
2859 logicalinclusiveorExpression();
2860 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2862 logicalinclusiveorExpression();
2863 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2865 logicalinclusiveorExpression();
2866 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2868 logicalinclusiveorExpression();
2869 } else if (token == TokenNameAND_EQUAL) { // &=
2871 logicalinclusiveorExpression();
2872 } else if (token == TokenNameOR_EQUAL) { // |=
2874 logicalinclusiveorExpression();
2875 } else if (token == TokenNameXOR_EQUAL) { // ^=
2877 logicalinclusiveorExpression();
2878 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2880 logicalinclusiveorExpression();
2881 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2883 logicalinclusiveorExpression();
2884 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2886 logicalinclusiveorExpression();
2890 private void multiplicativeExpression() throws CoreException {
2893 if (token != TokenNameMULTIPLY
2894 && token != TokenNameDIVIDE
2895 && token != TokenNameREMAINDER) {
2902 private void concatenationExpression() throws CoreException {
2904 multiplicativeExpression();
2905 if (token != TokenNameDOT) {
2912 private void additiveExpression() throws CoreException {
2914 concatenationExpression();
2915 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2922 private void shiftExpression() throws CoreException {
2924 additiveExpression();
2925 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2932 private void relationalExpression() throws CoreException {
2935 if (token != TokenNameLESS
2936 && token != TokenNameGREATER
2937 && token != TokenNameLESS_EQUAL
2938 && token != TokenNameGREATER_EQUAL) {
2945 private void identicalExpression() throws CoreException {
2947 relationalExpression();
2948 if (token != TokenNameEQUAL_EQUAL_EQUAL
2949 && token != TokenNameNOT_EQUAL_EQUAL) {
2956 private void equalityExpression() throws CoreException {
2958 identicalExpression();
2959 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2966 private void ternaryExpression() throws CoreException {
2967 equalityExpression();
2968 if (token == TokenNameQUESTION) {
2971 if (token == TokenNameCOLON) {
2975 throwSyntaxError("':' expected in ternary operator '? :'.");
2980 private void andExpression() throws CoreException {
2982 ternaryExpression();
2983 if (token != TokenNameAND) {
2990 private void exclusiveorExpression() throws CoreException {
2993 if (token != TokenNameXOR) {
3000 private void inclusiveorExpression() throws CoreException {
3002 exclusiveorExpression();
3003 if (token != TokenNameOR) {
3010 private void booleanandExpression() throws CoreException {
3012 inclusiveorExpression();
3013 if (token != TokenNameAND_AND) {
3020 private void booleanorExpression() throws CoreException {
3022 booleanandExpression();
3023 if (token != TokenNameOR_OR) {
3030 private void logicalandExpression() throws CoreException {
3032 booleanorExpression();
3033 if (token != TokenNameAND) {
3040 private void logicalexclusiveorExpression() throws CoreException {
3042 logicalandExpression();
3043 if (token != TokenNameXOR) {
3050 private void logicalinclusiveorExpression() throws CoreException {
3052 logicalexclusiveorExpression();
3053 if (token != TokenNameOR) {
3060 // public void assignmentExpression() {
3061 // if (token == TokenNameVARIABLE) {
3063 // if (token == TokenNameSET) {
3065 // logicalinclusiveorExpression();
3068 // logicalinclusiveorExpression();
3072 private void variableList() throws CoreException {
3075 if (token == TokenNameCOMMA) {
3083 private void variable() throws CoreException {
3084 if (token == TokenNameDOLLAR_LBRACE) {
3088 if (token != TokenNameRBRACE) {
3089 throwSyntaxError("'}' expected after indirect variable token '${'.");
3093 if (token == TokenNameVariable) {
3095 if (token == TokenNameLBRACKET) {
3098 if (token != TokenNameRBRACKET) {
3099 throwSyntaxError("']' expected in variable-list.");
3102 } else if (token == TokenNameEQUAL) {
3107 throwSyntaxError("$-variable expected in variable-list.");
3113 * It will look for a value (after a '=' for example)
3114 * @throws CoreException
3116 private void constant() throws CoreException {
3119 case TokenNamePLUS :
3122 case TokenNameDoubleLiteral :
3125 case TokenNameIntegerLiteral :
3129 throwSyntaxError("Constant expected after '+' presign.");
3132 case TokenNameMINUS :
3135 case TokenNameDoubleLiteral :
3138 case TokenNameIntegerLiteral :
3142 throwSyntaxError("Constant expected after '-' presign.");
3145 case TokenNamenull :
3148 case TokenNamefalse :
3151 case TokenNametrue :
3154 case TokenNameIdentifier :
3155 // ident = identifier;
3156 char[] ident = scanner.getCurrentIdentifierSource();
3158 if (token == TokenNameLPAREN) {
3160 if (token != TokenNameRPAREN) {
3162 if (token != TokenNameRPAREN) {
3164 "')' expected after identifier '"
3166 + "' in postfix-expression.");
3172 case TokenNameStringLiteral :
3175 case TokenNameStringConstant :
3178 case TokenNameStringInterpolated :
3181 case TokenNameDoubleLiteral :
3184 case TokenNameIntegerLiteral :
3188 throwSyntaxError("Constant expected.");
3193 * Call the php parse command ( php -l -f <filename> )
3194 * and create markers according to the external parser output
3196 public static void phpExternalParse(IFile file) {
3197 //IFile file = (IFile) resource;
3198 IPath path = file.getFullPath();
3199 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
3200 String filename = file.getLocation().toString();
3202 String[] arguments = { filename };
3203 MessageFormat form =
3204 new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
3205 String command = form.format(arguments);
3207 String parserResult =
3208 PHPStartApacheAction.getParserOutput(command, "External parser: ");
3211 // parse the buffer to find the errors and warnings
3212 createMarkers(parserResult, file);
3213 } catch (CoreException e) {
3218 * Create markers according to the external parser output
3220 private static void createMarkers(String output, IFile file)
3221 throws CoreException {
3222 // delete all markers
3223 file.deleteMarkers(IMarker.PROBLEM, false, 0);
3227 boolean flag = true;
3228 while ((brIndx = output.indexOf("<br />", indx)) != -1) {
3229 // newer php error output (tested with 4.2.3)
3230 scanLine(output, file, indx, brIndx);
3235 while ((brIndx = output.indexOf("<br>", indx)) != -1) {
3236 // older php error output (tested with 4.2.3)
3237 scanLine(output, file, indx, brIndx);
3243 private static void scanLine(String output, IFile file, int indx, int brIndx)
3244 throws CoreException {
3246 String outLineNumberString;
3247 StringBuffer lineNumberBuffer = new StringBuffer(10);
3249 current = output.substring(indx, brIndx);
3251 if (current.indexOf(PARSE_WARNING_STRING) != -1
3252 || current.indexOf(PARSE_ERROR_STRING) != -1) {
3253 int onLine = current.indexOf("on line <b>");
3255 lineNumberBuffer.delete(0, lineNumberBuffer.length());
3256 for (int i = onLine; i < current.length(); i++) {
3257 ch = current.charAt(i);
3258 if ('0' <= ch && '9' >= ch) {
3259 lineNumberBuffer.append(ch);
3263 int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
3265 Hashtable attributes = new Hashtable();
3267 current = current.replaceAll("\n", "");
3268 current = current.replaceAll("<b>", "");
3269 current = current.replaceAll("</b>", "");
3270 MarkerUtilities.setMessage(attributes, current);
3272 if (current.indexOf(PARSE_ERROR_STRING) != -1)
3273 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
3274 else if (current.indexOf(PARSE_WARNING_STRING) != -1)
3277 new Integer(IMarker.SEVERITY_WARNING));
3279 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
3280 MarkerUtilities.setLineNumber(attributes, lineNumber);
3281 MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);