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.util.ArrayList;
14 import java.util.Hashtable;
16 import net.sourceforge.phpdt.core.compiler.*;
17 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
18 import net.sourceforge.phpeclipse.phpeditor.PHPString;
20 import org.eclipse.core.resources.IFile;
21 import org.eclipse.core.resources.IMarker;
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.jface.preference.IPreferenceStore;
24 import org.eclipse.ui.texteditor.MarkerUtilities;
25 import test.PHPParserSuperclass;
27 public class Parser extends PHPParserSuperclass implements ITerminalSymbols {
30 public Scanner scanner;
32 private ArrayList phpList;
34 private int currentPHPString;
35 private boolean phpEnd;
37 // private static HashMap keywordMap = null;
45 // row counter for syntax errors:
47 // column counter for syntax errors:
52 // // current identifier
58 private String stringValue;
60 /** Contains the current expression. */
61 // private StringBuffer expression;
63 private boolean phpMode;
65 // final static int TokenNameEOF = 0;
66 // final static int TokenNameERROR = 1;
67 // final static int TokenNameHTML = 2;
69 // final static int TokenNameREMAINDER = 30;
70 // final static int TokenNameNOT = 31;
71 // final static int TokenNameDOT = 32;
72 // final static int TokenNameXOR = 33;
73 // final static int TokenNameDIVIDE = 34;
74 // final static int TokenNameMULTIPLY = 35;
75 // final static int TokenNameMINUS = 36;
76 // final static int TokenNamePLUS = 37;
77 // final static int TokenNameEQUAL_EQUAL = 38;
78 // final static int TokenNameNOT_EQUAL = 39;
79 // final static int TokenNameGREATER = 40;
80 // final static int TokenNameGREATER_EQUAL = 41;
81 // final static int TokenNameLESS = 42;
82 // final static int TokenNameLESS_EQUAL = 43;
83 // final static int TokenNameAND_AND = 44;
84 // final static int TokenNameOR_OR = 45;
85 // // final static int TokenNameHASH = 46;
86 // final static int TokenNameCOLON = 47;
87 // final static int TokenNameDOT_EQUAL = 48;
89 // final static int TokenNameEQUAL = 49;
90 // final static int TokenNameMINUS_GREATER = 50; // ->
91 // final static int TokenNameFOREACH = 51;
92 // final static int TokenNameAND = 52;
93 // //final static int TokenNameDOLLARLISTOPEN = 53;
94 // final static int TokenNameTWIDDLE = 54;
95 // final static int TokenNameTWIDDLE_EQUAL = 55;
96 // final static int TokenNameREMAINDER_EQUAL = 56;
97 // final static int TokenNameXOR_EQUAL = 57;
98 // final static int TokenNameRIGHT_SHIFT_EQUAL = 58;
99 // final static int TokenNameLEFT_SHIFT_EQUAL = 59;
100 // final static int TokenNameAND_EQUAL = 60;
101 // final static int TokenNameOR_EQUAL = 61;
102 // final static int TokenNameQUESTION = 62;
103 // final static int TokenNameCOLON_COLON = 63;
104 // final static int TokenNameAT = 63;
105 // // final static int TokenNameHEREDOC = 64;
107 // final static int TokenNameDOLLAROPEN = 127;
108 // final static int TokenNameLPAREN = 128;
109 // final static int TokenNameRPAREN = 129;
110 // final static int TokenNameLBRACE = 130;
111 // final static int TokenNameRBRACE = 131;
112 // final static int TokenNameLBRACKET = 132;
113 // final static int TokenNameRBRACKET = 133;
114 // final static int TokenNameCOMMA = 134;
116 // final static int TokenNameStringLiteral = 136;
117 // final static int TokenNameIdentifier = 138;
118 // // final static int TokenNameDIGIT = 139;
119 // final static int TokenNameSEMICOLON = 140;
120 // // final static int TokenNameSLOT = 141;
121 // // final static int TokenNameSLOTSEQUENCE = 142;
122 // final static int TokenNameMINUS_MINUS = 144;
123 // final static int TokenNamePLUS_PLUS = 145;
124 // final static int TokenNamePLUS_EQUAL = 146;
125 // final static int TokenNameDIVIDE_EQUAL = 147;
126 // final static int TokenNameMINUS_EQUAL = 148;
127 // final static int TokenNameMULTIPLY_EQUAL = 149;
128 // final static int TokenNameVariable = 150;
129 // final static int TokenNameIntegerLiteral = 151;
130 // final static int TokenNameDoubleLiteral = 152;
131 // final static int TokenNameStringInterpolated = 153;
132 // final static int TokenNameStringConstant = 154;
134 // final static int TokenNameLEFT_SHIFT = 155;
135 // final static int TokenNameRIGHT_SHIFT = 156;
136 // final static int TokenNameEQUAL_EQUAL_EQUAL = 157;
137 // final static int TokenNameNOT_EQUAL_EQUAL = 158;
138 // final static int TokenNameOR = 159;
139 // final static int TokenNameAT = 153; // @
144 public void setFileToParse(IFile fileToParse) {
145 this.currentPHPString = 0;
146 this.fileToParse = fileToParse;
149 this.token = TokenNameEOF;
151 this.initializeScanner();
154 * ClassDeclaration Constructor.
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(String message, int charStart, int charEnd, int errorLevel) throws CoreException {
188 setMarker(fileToParse, message, charStart, charEnd, errorLevel);
192 * This method will throw the SyntaxError.
193 * It will add the good lines and columns to the Error
194 * @param error the error message
195 * @throws SyntaxError the error raised
197 private void throwSyntaxError(String error) {
199 // if (str.length() < chIndx) {
202 // // read until end-of-line
204 // while (str.length() > eol) {
205 // ch = str.charAt(eol++);
211 // throw new SyntaxError(
213 // chIndx - columnCount + 1,
214 // str.substring(columnCount, eol),
216 throw new SyntaxError(1, 1, "", error);
220 * This method will throw the SyntaxError.
221 * It will add the good lines and columns to the Error
222 * @param error the error message
223 * @throws SyntaxError the error raised
225 private void throwSyntaxError(String error, int startRow) {
226 throw new SyntaxError(startRow, 0, " ", error);
230 * Method Declaration.
234 // private void getChar() {
235 // if (str.length() > chIndx) {
236 // ch = str.charAt(chIndx++);
241 // chIndx = str.length() + 1;
243 // // token = TokenNameEOF;
248 * gets the next token from input
250 private void getNextToken() throws CoreException {
252 token = scanner.getNextToken();
254 int currentEndPosition = scanner.getCurrentTokenEndPosition();
255 int currentStartPosition = scanner.getCurrentTokenStartPosition();
257 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
258 System.out.println(scanner.toStringAction(token));
260 } catch (InvalidInputException e) {
261 token = TokenNameERROR;
265 // boolean phpFound = false;
272 // while (str.length() > chIndx) {
273 // token = TokenNameERROR;
274 // ch = str.charAt(chIndx++);
280 // ch2 = str.charAt(chIndx++);
282 // ch2 = str.charAt(chIndx++);
283 // if (Character.isWhitespace(ch2)) {
288 // } else if (ch2 == 'p' || ch2 == 'P') {
289 // ch2 = str.charAt(chIndx++);
290 // if (ch2 == 'h' || ch2 == 'H') {
291 // ch2 = str.charAt(chIndx++);
292 // if (ch2 == 'p' || ch2 == 'P') {
310 // while (str.length() > chIndx) {
311 // ch = str.charAt(chIndx++);
312 // token = TokenNameERROR;
315 // columnCount = chIndx;
316 // continue; // while loop
318 // if (str.length() == chIndx) {
321 // if (!Character.isWhitespace(ch)) {
323 // if (str.length() > chIndx) {
324 // if (str.charAt(chIndx) == '{') {
326 // token = TokenNameDOLLAROPEN;
333 // if ((ch >= 'a' && ch <= 'z')
334 // || (ch >= 'A' && ch <= 'Z')
340 // if (ch >= '0' && ch <= '9') {
345 // if (str.length() > chIndx) {
346 // if (str.charAt(chIndx) == '/') {
349 // // read comment until end of line:
350 // while ((str.length() > chIndx)
351 // && (ch != '\n')) {
352 // ch = str.charAt(chIndx++);
354 // ch2 = str.charAt(chIndx);
357 // token = TokenNameHTML;
368 // } else if (str.charAt(chIndx) == '*') {
370 // // multi line comment:
371 // while (str.length() > chIndx) {
372 // if (str.charAt(chIndx) == '*'
373 // && (str.length() > (chIndx + 1))
374 // && str.charAt(chIndx + 1) == '/') {
378 // ch = str.charAt(chIndx++);
381 // columnCount = chIndx;
387 // } else if (ch == '#') {
388 // // read comment until end of line:
389 // while ((str.length() > chIndx) && (ch != '\n')) {
390 // ch = str.charAt(chIndx++);
392 // ch2 = str.charAt(chIndx);
395 // token = TokenNameHTML;
406 // } else if (ch == '"') {
409 // TokenNameStringInterpolated,
410 // "Open string character '\"' at end of file.");
412 // } else if (ch == '\'') {
415 // TokenNameStringConstant,
416 // "Open string character \"'\" at end of file.");
418 // } else if (ch == '`') {
421 // TokenNameStringConstant,
422 // "Open string character \"`\" at end of file.");
424 // "Other string delimiters prefered (found \"`\").",
433 // token = TokenNameLPAREN;
437 // token = TokenNameRPAREN;
441 // token = TokenNameLBRACE;
445 // token = TokenNameRBRACE;
449 // token = TokenNameLBRACKET;
453 // token = TokenNameRBRACKET;
457 // token = TokenNameCOMMA;
461 // token = TokenNameQUESTION;
462 // if (str.length() > chIndx) {
463 // if (str.charAt(chIndx) == '>') {
465 // token = TokenNameHTML;
475 // token = TokenNameAT;
478 // token = TokenNameTWIDDLE;
479 // if (str.length() > chIndx) {
480 // if (str.charAt(chIndx) == '=') {
482 // token = TokenNameTWIDDLE_EQUAL;
489 // token = TokenNameDOT;
490 // if (str.length() > chIndx) {
491 // if (str.charAt(chIndx) == '=') {
493 // token = TokenNameDOT_EQUAL;
501 // token = TokenNameStringLiteral;
505 // token = TokenNameREMAINDER;
506 // if (str.length() > chIndx) {
507 // if (str.charAt(chIndx) == '=') {
509 // token = TokenNameREMAINDER_EQUAL;
516 // token = TokenNameSEMICOLON;
520 // token = TokenNameXOR;
521 // if (str.length() > chIndx) {
522 // if (str.charAt(chIndx) == '=') {
524 // token = TokenNameXOR_EQUAL;
531 // token = TokenNameDIVIDE;
533 // if (str.length() > chIndx) {
534 // if (str.charAt(chIndx) == '=') {
536 // token = TokenNameDIVIDE_EQUAL;
544 // token = TokenNameMULTIPLY;
545 // if (str.length() > chIndx) {
546 // if (str.charAt(chIndx) == '*') {
548 // token = TokenNameXOR;
552 // if (str.charAt(chIndx) == '=') {
554 // token = TokenNameMULTIPLY_EQUAL;
562 // token = TokenNamePLUS;
563 // if (str.length() > chIndx) {
564 // if (str.charAt(chIndx) == '+') {
566 // token = TokenNamePLUS_PLUS;
570 // if (str.charAt(chIndx) == '=') {
572 // token = TokenNamePLUS_EQUAL;
579 // token = TokenNameMINUS;
580 // if (str.length() > chIndx) {
581 // if (str.charAt(chIndx) == '-') {
583 // token = TokenNameMINUS_MINUS;
587 // if (str.charAt(chIndx) == '=') {
589 // token = TokenNameMINUS_EQUAL;
593 // if (str.charAt(chIndx) == '>') {
595 // token = TokenNameMINUS_GREATER;
603 // token = TokenNameEQUAL;
605 // if (str.length() > chIndx) {
606 // ch = str.charAt(chIndx);
610 // token = TokenNameEQUAL_EQUAL;
611 // if (str.length() > chIndx) {
612 // ch = str.charAt(chIndx);
617 // TokenNameEQUAL_EQUAL_EQUAL;
624 // token = TokenNameEQUAL_GREATER;
632 // token = TokenNameNOT;
634 // if (str.length() > chIndx) {
635 // if (str.charAt(chIndx) == '=') {
637 // token = TokenNameNOT_EQUAL;
638 // if (str.length() > chIndx) {
639 // ch = str.charAt(chIndx);
644 // TokenNameNOT_EQUAL_EQUAL;
653 // token = TokenNameGREATER;
655 // if (str.length() > chIndx) {
656 // if (str.charAt(chIndx) == '=') {
658 // token = TokenNameGREATER_EQUAL;
661 // if (str.charAt(chIndx) == '>') {
663 // token = TokenNameRIGHT_SHIFT;
664 // if (str.length() > chIndx) {
665 // if (str.charAt(chIndx) == '=') {
668 // TokenNameRIGHT_SHIFT_EQUAL;
678 // token = TokenNameLESS;
680 // if (str.length() > chIndx) {
681 // if (str.charAt(chIndx) == '=') {
683 // token = TokenNameLESS_EQUAL;
687 // if (str.charAt(chIndx) == '<') {
689 // token = TokenNameLEFT_SHIFT;
690 // if (str.charAt(chIndx) == '<') {
692 // int startRow = rowCount;
693 // if (str.length() > chIndx) {
695 // ch = str.charAt(++chIndx);
696 // if ((ch >= 'a' && ch <= 'z')
697 // || (ch >= 'A' && ch <= 'Z')
702 // TokenNameStringConstant;
703 // while (str.length()
719 // .equals(identifier)) {
731 // "Open heredoc syntax after operator '<<<'.",
733 // } else if (str.charAt(chIndx) == '=') {
735 // token = TokenNameLEFT_SHIFT_EQUAL;
745 // token = TokenNameOR;
747 // if (str.length() > chIndx) {
748 // if (str.charAt(chIndx) == '|') {
750 // token = TokenNameOR_OR;
753 // if (str.charAt(chIndx) == '=') {
755 // token = TokenNameOR_EQUAL;
762 // token = TokenNameAND;
763 // if (str.length() > chIndx) {
764 // if (str.charAt(chIndx) == '&') {
766 // token = TokenNameAND_AND;
769 // if (str.charAt(chIndx) == '=') {
771 // token = TokenNameAND_EQUAL;
779 // token = TokenNameCOLON;
780 // if (str.length() > chIndx) {
781 // if (str.charAt(chIndx) == ':') {
783 // token = TokenNameCOLON_COLON;
788 // // token = TokenNameHASH;
792 // // token = TokenNameAT;
797 // "unexpected character: '" + ch + "'");
800 // if (token == TokenNameERROR) {
801 // throwSyntaxError("token not found");
808 // } catch (StringIndexOutOfBoundsException e) {
809 // // catched from charAt
812 // chIndx = str.length() + 1;
814 // token = TokenNameEOF;
817 // // if (phpList != null) {
818 // // if (currentPHPString < phpList.size()) {
819 // // token = TokenNameUNDEFINED;
820 // // temp = (PHPString) phpList.get(currentPHPString++);
821 // // this.str = temp.getPHPString();
822 // // this.token = TokenNameEOF;
823 // // this.chIndx = 0;
824 // // this.rowCount = temp.getLineNumber();
825 // // this.columnCount = 0;
826 // // getNextToken();
829 // // token = TokenNameUNDEFINED;
836 // * Get an identifier.
838 // private void getIdentifier() {
839 // // StringBuffer ident = new StringBuffer();
840 // int startPosition = chIndx - 1;
841 // // ident.append(ch);
844 // // attention recursive call:
846 // token = TokenNameVariable;
849 // token = TokenNameIdentifier;
854 // //this will read the buffer until the next character is a forbidden character for identifier
855 // while ((ch >= 'a' && ch <= 'z')
856 // || (ch >= 'A' && ch <= 'Z')
857 // || (ch >= '0' && ch <= '9')
859 // // ident.append(ch);
862 // int endPosition = chIndx--;
863 // int length = (--endPosition) - startPosition;
865 // identifier = str.substring(startPosition, endPosition);
866 // // System.out.println(identifier);
868 // // determine if this identitfer is a keyword
869 // // @todo improve this in future version
870 // Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
872 // token = i.intValue();
878 * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
879 * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
880 * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
881 * value {@link Parser#TokenNameINT_NUMBER}
883 // private void getNumber() {
884 // StringBuffer inum = new StringBuffer();
886 // int numFormat = 10;
888 // // save first digit
889 // char firstCh = ch;
893 // // determine number conversions:
894 // if (firstCh == '0') {
923 // if (numFormat == 16) {
924 // while ((ch >= '0' && ch <= '9')
925 // || (ch >= 'a' && ch <= 'f')
926 // || (ch >= 'A' && ch <= 'F')) {
931 // while ((ch >= '0' && ch <= '9')
935 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
936 // if (ch == '.' && dFlag != ' ') {
939 // if ((dFlag == 'E') || (dFlag == 'e')) {
945 // if ((ch == '-') || (ch == '+')) {
958 // if (dFlag != ' ') {
959 // doubleNumber = new Double(inum.toString());
960 // token = TokenNameDoubleLiteral;
963 // longNumber = Long.valueOf(inum.toString(), numFormat);
964 // token = TokenNameIntegerLiteral;
968 // } catch (Throwable e) {
969 // throwSyntaxError("Number format error: " + inum.toString());
975 // * @param openChar the opening char ('\'', '"', '`')
976 // * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
977 // * @param errorMsg the error message in case of parse error in the string
979 // private void getString(
980 // final char openChar,
981 // final int typeString,
982 // final String errorMsg) {
983 // StringBuffer sBuffer = new StringBuffer();
984 // boolean openString = true;
985 // int startRow = rowCount;
986 // while (str.length() > chIndx) {
987 // ch = str.charAt(chIndx++);
989 // sBuffer.append(ch);
990 // if (str.length() > chIndx) {
991 // ch = str.charAt(chIndx++);
992 // sBuffer.append(ch);
994 // } else if (ch == openChar) {
995 // openString = false;
997 // } else if (ch == '\n') {
999 // columnCount = chIndx;
1001 // sBuffer.append(ch);
1004 // if (openString) {
1005 // if (typeString == TokenNameStringConstant) {
1006 // throwSyntaxError(errorMsg, startRow);
1008 // throwSyntaxError(errorMsg);
1011 // token = typeString;
1012 // stringValue = sBuffer.toString();
1015 // public void htmlParserTester(String input) {
1016 // int lineNumber = 1;
1017 // int startLineNumber = 1;
1018 // int startIndex = 0;
1021 // boolean phpMode = false;
1022 // boolean phpFound = false;
1024 // phpList = new ArrayList();
1025 // currentPHPString = 0;
1029 // while (i < input.length()) {
1030 // ch = input.charAt(i++);
1031 // if (ch == '\n') {
1034 // if ((!phpMode) && ch == '<') {
1035 // ch2 = input.charAt(i++);
1036 // if (ch2 == '?') {
1037 // ch2 = input.charAt(i++);
1038 // if (Character.isWhitespace(ch2)) {
1043 // startLineNumber = lineNumber;
1045 // } else if (ch2 == 'p') {
1046 // ch2 = input.charAt(i++);
1047 // if (ch2 == 'h') {
1048 // ch2 = input.charAt(i++);
1049 // if (ch2 == 'p') {
1053 // startLineNumber = lineNumber;
1059 // } else if (ch2 == 'P') {
1060 // ch2 = input.charAt(i++);
1061 // if (ch2 == 'H') {
1062 // ch2 = input.charAt(i++);
1063 // if (ch2 == 'P') {
1067 // startLineNumber = lineNumber;
1080 // if (ch == '/' && i < input.length()) {
1081 // ch2 = input.charAt(i++);
1082 // if (ch2 == '/') {
1083 // while (i < input.length()) {
1084 // ch = input.charAt(i++);
1085 // if (ch == '?' && i < input.length()) {
1086 // ch2 = input.charAt(i++);
1087 // if (ch2 == '>') {
1095 // startLineNumber));
1099 // } else if (ch == '\n') {
1105 // } else if (ch2 == '*') {
1106 // // multi-line comment
1107 // while (i < input.length()) {
1108 // ch = input.charAt(i++);
1109 // if (ch == '\n') {
1111 // } else if (ch == '*' && i < input.length()) {
1112 // ch2 = input.charAt(i++);
1113 // if (ch2 == '/') {
1123 // } else if (ch == '#') {
1124 // while (i < input.length()) {
1125 // ch = input.charAt(i++);
1126 // if (ch == '?' && i < input.length()) {
1127 // ch2 = input.charAt(i++);
1128 // if (ch2 == '>') {
1133 // input.substring(startIndex, i - 2),
1134 // startLineNumber));
1138 // } else if (ch == '\n') {
1144 // } else if (ch == '"') {
1146 // while (i < input.length()) {
1147 // ch = input.charAt(i++);
1148 // if (ch == '\n') {
1151 // ch == '\\' && i < input.length()) { // escape
1153 // } else if (ch == '"') {
1158 // } else if (ch == '\'') {
1160 // while (i < input.length()) {
1161 // ch = input.charAt(i++);
1162 // if (ch == '\n') {
1165 // ch == '\\' && i < input.length()) { // escape
1167 // } else if (ch == '\'') {
1174 // if (ch == '?' && i < input.length()) {
1175 // ch2 = input.charAt(i++);
1176 // if (ch2 == '>') {
1181 // input.substring(startIndex, i - 2),
1182 // startLineNumber));
1192 // "No PHP source code found.",
1198 // "Open PHP tag at end of file.",
1203 // input.substring(startIndex, i - 2),
1204 // startLineNumber));
1206 // // for (int j=0;j<phpList.size();j++) {
1207 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
1208 // // int startIndx = temp.length()-10;
1209 // // if (startIndx<0) {
1210 // // startIndx = 0;
1212 // // System.out.println(temp.substring(startIndx)+"?>");
1214 // phpParserTester(null, 1);
1215 // // PHPString temp;
1216 // // for(int j=0;j<phpList.size();j++) {
1217 // // temp = (PHPString) phpList.get(j);
1218 // // parser.start(temp.getPHPString(), temp.getLineNumber());
1221 // } catch (CoreException e) {
1225 public void phpParserTester(String s, int rowCount) throws CoreException {
1228 if (phpList.size() != 0) {
1229 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
1232 this.token = TokenNameEOF;
1234 // this.rowCount = rowCount;
1235 // this.columnCount = 0;
1236 this.phpEnd = false;
1237 this.phpMode = true;
1238 scanner.setSource(s.toCharArray());
1239 scanner.setPHPMode(true);
1243 if (token != TokenNameEOF && token != TokenNameERROR) {
1246 if (token != TokenNameEOF) {
1247 if (token == TokenNameERROR) {
1248 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
1250 if (token == TokenNameRPAREN) {
1251 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1253 if (token == TokenNameRBRACE) {
1254 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1256 if (token == TokenNameRBRACKET) {
1257 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1260 if (token == TokenNameLPAREN) {
1261 throwSyntaxError("Read character '('; end-of-file not reached.");
1263 if (token == TokenNameLBRACE) {
1264 throwSyntaxError("Read character '{'; end-of-file not reached.");
1266 if (token == TokenNameLBRACKET) {
1267 throwSyntaxError("Read character '['; end-of-file not reached.");
1270 throwSyntaxError("End-of-file not reached.");
1273 } catch (SyntaxError err) {
1277 // setMarker(err.getMessage(), err.getLine(), ERROR);
1278 setMarker(err.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
1280 // if an error occured,
1281 // try to find keywords 'class' or 'function'
1282 // to parse the rest of the string
1283 while (token != TokenNameEOF && token != TokenNameERROR) {
1284 if (token == TokenNameclass || token == TokenNamefunction) {
1289 if (token == TokenNameEOF || token == TokenNameERROR) {
1298 * Parses a string with php tags
1299 * i.e. '<body> <?php phpinfo() ?> </body>'
1301 public void parse(String s) throws CoreException {
1303 this.token = TokenNameEOF;
1305 // this.rowCount = 1;
1306 // this.columnCount = 0;
1307 this.phpEnd = false;
1308 this.phpMode = false;
1309 /* scanner initialization */
1310 scanner.setSource(s.toCharArray());
1311 scanner.setPHPMode(false);
1315 if (token != TokenNameEOF && token != TokenNameERROR) {
1318 if (token != TokenNameEOF) {
1319 if (token == TokenNameERROR) {
1320 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
1322 if (token == TokenNameRPAREN) {
1323 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1325 if (token == TokenNameRBRACE) {
1326 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1328 if (token == TokenNameRBRACKET) {
1329 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1332 if (token == TokenNameLPAREN) {
1333 throwSyntaxError("Read character '('; end-of-file not reached.");
1335 if (token == TokenNameLBRACE) {
1336 throwSyntaxError("Read character '{'; end-of-file not reached.");
1338 if (token == TokenNameLBRACKET) {
1339 throwSyntaxError("Read character '['; end-of-file not reached.");
1342 throwSyntaxError("End-of-file not reached.");
1345 } catch (SyntaxError sytaxErr1) {
1346 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
1347 setMarker(sytaxErr1.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
1349 // if an error occured,
1350 // try to find keywords 'class' or 'function'
1351 // to parse the rest of the string
1352 while (token != TokenNameEOF && token != TokenNameERROR) {
1353 if (token == TokenNameclass || token == TokenNamefunction) {
1358 if (token == TokenNameEOF || token == TokenNameERROR) {
1361 } catch (SyntaxError sytaxErr2) {
1362 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
1363 setMarker(sytaxErr2.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
1371 public PHPOutlineInfo parseInfo(Object parent, String s) {
1372 PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
1373 // Stack stack = new Stack();
1374 // stack.push(outlineInfo.getDeclarations());
1377 this.token = TokenNameEOF;
1379 // this.rowCount = 1;
1380 // this.columnCount = 0;
1381 this.phpEnd = false;
1382 this.phpMode = false;
1383 scanner.setSource(s.toCharArray());
1384 scanner.setPHPMode(false);
1388 parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
1389 } catch (CoreException e) {
1394 private void parseDeclarations(PHPOutlineInfo outlineInfo, OutlineableWithChildren current, boolean goBack) {
1396 // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
1397 PHPSegmentWithChildren temp;
1400 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
1402 while (token != TokenNameEOF && token != TokenNameERROR) {
1403 if (token == TokenNameVariable) {
1404 ident = scanner.getCurrentIdentifierSource();
1405 outlineInfo.addVariable(new String(ident));
1407 } else if (token == TokenNamevar) {
1409 if (token == TokenNameVariable && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
1410 ident = scanner.getCurrentIdentifierSource();
1411 //substring(1) added because PHPVarDeclaration doesn't need the $ anymore
1412 String variableName = new String(ident).substring(1);
1413 outlineInfo.addVariable(variableName);
1415 if (token != TokenNameSEMICOLON) {
1418 ident = scanner.getCurrentTokenSource();
1419 if (token > TokenNameKEYWORD) {
1420 current.add(new PHPVarDeclaration(current, variableName,
1421 // chIndx - ident.length,
1422 scanner.getCurrentTokenStartPosition(), new String(ident)));
1425 case TokenNameVariable :
1426 current.add(new PHPVarDeclaration(current, variableName,
1427 // chIndx - ident.length,
1428 scanner.getCurrentTokenStartPosition(), new String(ident)));
1430 case TokenNameIdentifier :
1431 current.add(new PHPVarDeclaration(current, variableName,
1432 // chIndx - ident.length,
1433 scanner.getCurrentTokenStartPosition(), new String(ident)));
1435 case TokenNameDoubleLiteral :
1436 current.add(new PHPVarDeclaration(current, variableName + doubleNumber,
1437 // chIndx - ident.length,
1438 scanner.getCurrentTokenStartPosition(), new String(ident)));
1440 case TokenNameIntegerLiteral :
1441 current.add(new PHPVarDeclaration(current, variableName,
1442 // chIndx - ident.length,
1443 scanner.getCurrentTokenStartPosition(), new String(ident)));
1445 case TokenNameStringInterpolated :
1446 case TokenNameStringLiteral :
1447 current.add(new PHPVarDeclaration(current, variableName,
1448 // chIndx - ident.length,
1449 scanner.getCurrentTokenStartPosition(), new String(ident)));
1451 case TokenNameStringConstant :
1452 current.add(new PHPVarDeclaration(current, variableName,
1453 // chIndx - ident.length,
1454 scanner.getCurrentTokenStartPosition(), new String(ident)));
1457 current.add(new PHPVarDeclaration(current, variableName,
1458 // chIndx - ident.length
1459 scanner.getCurrentTokenStartPosition()));
1465 ident = scanner.getCurrentIdentifierSource();
1467 current.add(new PHPVarDeclaration(current, variableName,
1468 // chIndx - ident.length
1469 scanner.getCurrentTokenStartPosition()));
1472 } else if (token == TokenNamefunction) {
1474 if (token == TokenNameAND) {
1477 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
1478 ident = scanner.getCurrentIdentifierSource();
1479 outlineInfo.addVariable(new String(ident));
1480 temp = new PHPFunctionDeclaration(current, new String(ident),
1481 // chIndx - ident.length
1482 scanner.getCurrentTokenStartPosition());
1485 parseDeclarations(outlineInfo, temp, true);
1487 } else if (token == TokenNameclass) {
1489 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
1490 ident = scanner.getCurrentIdentifierSource();
1491 outlineInfo.addVariable(new String(ident));
1492 temp = new PHPClassDeclaration(current, new String(ident),
1493 // chIndx - ident.len
1494 scanner.getCurrentTokenStartPosition());
1496 // stack.push(temp);
1499 //skip tokens for classname, extends and others until we have the opening '{'
1500 while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) {
1503 parseDeclarations(outlineInfo, temp, true);
1506 } else if ((token == TokenNameLBRACE) || (token == TokenNameDOLLAR_LBRACE)) {
1509 } else if (token == TokenNameRBRACE) {
1512 if (counter == 0 && goBack) {
1516 token == TokenNamerequire
1517 || token == TokenNamerequire_once
1518 || token == TokenNameinclude
1519 || token == TokenNameinclude_once) {
1520 ident = scanner.getCurrentTokenSource();
1523 int startPosition = scanner.getCurrentTokenStartPosition();
1525 char[] expr = scanner.getCurrentTokenSource(startPosition);
1526 outlineInfo.addVariable(new String(ident));
1527 current.add(new PHPReqIncDeclaration(current, new String(ident),
1528 // chIndx - ident.length,
1529 startPosition, new String(expr)));
1535 } catch (CoreException e) {
1536 } catch (SyntaxError sytaxErr) {
1538 // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
1539 setMarker(sytaxErr.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
1540 } catch (CoreException e) {
1545 private void statementList() throws CoreException {
1548 if ((token == TokenNameRBRACE)
1549 || (token == TokenNamecase)
1550 || (token == TokenNamedefault)
1551 || (token == TokenNameelseif)
1552 || (token == TokenNameendif)
1553 || (token == TokenNameendfor)
1554 || (token == TokenNameendforeach)
1555 || (token == TokenNameendwhile)
1556 || (token == TokenNameendswitch)
1557 || (token == TokenNameEOF)
1558 || (token == TokenNameERROR)) {
1564 private void compoundStatement() throws CoreException {
1565 // '{' [statement-list] '}'
1566 if (token == TokenNameLBRACE) {
1569 throwSyntaxError("'{' expected in compound-statement.");
1571 if (token != TokenNameRBRACE) {
1574 if (token == TokenNameRBRACE) {
1577 throwSyntaxError("'}' expected in compound-statement.");
1581 private void statement() throws CoreException {
1582 // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
1583 // char[] ident = scanner.getCurrentIdentifierSource();
1584 // String keyword = new String(ident);
1585 if (token == TokenNameinclude || token == TokenNameinclude_once) {
1588 if (token == TokenNameSEMICOLON) {
1591 if (token != TokenNameStopPHP) {
1592 throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1597 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1601 if (token == TokenNameSEMICOLON) {
1604 if (token != TokenNameStopPHP) {
1605 throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1610 } else if (token == TokenNameif) {
1612 if (token == TokenNameLPAREN) {
1615 throwSyntaxError("'(' expected after 'if' keyword.");
1618 if (token == TokenNameRPAREN) {
1621 throwSyntaxError("')' expected after 'if' condition.");
1626 } else if (token == TokenNameswitch) {
1628 if (token == TokenNameLPAREN) {
1631 throwSyntaxError("'(' expected after 'switch' keyword.");
1634 if (token == TokenNameRPAREN) {
1637 throwSyntaxError("')' expected after 'switch' condition.");
1641 } else if (token == TokenNamefor) {
1643 if (token == TokenNameLPAREN) {
1646 throwSyntaxError("'(' expected after 'for' keyword.");
1648 if (token == TokenNameSEMICOLON) {
1652 if (token == TokenNameSEMICOLON) {
1655 throwSyntaxError("';' expected after 'for'.");
1658 if (token == TokenNameSEMICOLON) {
1662 if (token == TokenNameSEMICOLON) {
1665 throwSyntaxError("';' expected after 'for'.");
1668 if (token == TokenNameRPAREN) {
1672 if (token == TokenNameRPAREN) {
1675 throwSyntaxError("')' expected after 'for'.");
1680 } else if (token == TokenNamewhile) {
1682 if (token == TokenNameLPAREN) {
1685 throwSyntaxError("'(' expected after 'while' keyword.");
1688 if (token == TokenNameRPAREN) {
1691 throwSyntaxError("')' expected after 'while' condition.");
1695 } else if (token == TokenNamedo) {
1697 if (token == TokenNameLBRACE) {
1700 throwSyntaxError("'{' expected after 'do' keyword.");
1702 if (token != TokenNameRBRACE) {
1705 if (token == TokenNameRBRACE) {
1708 throwSyntaxError("'}' expected after 'do' keyword.");
1710 if (token == TokenNamewhile) {
1712 if (token == TokenNameLPAREN) {
1715 throwSyntaxError("'(' expected after 'while' keyword.");
1718 if (token == TokenNameRPAREN) {
1721 throwSyntaxError("')' expected after 'while' condition.");
1724 throwSyntaxError("'while' expected after 'do' keyword.");
1726 if (token == TokenNameSEMICOLON) {
1729 if (token != TokenNameStopPHP) {
1730 throwSyntaxError("';' expected after do-while statement.");
1735 } else if (token == TokenNameforeach) {
1737 if (token == TokenNameLPAREN) {
1740 throwSyntaxError("'(' expected after 'foreach' keyword.");
1743 if (token == TokenNameas) {
1746 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1749 if (token == TokenNameEQUAL_GREATER) {
1753 if (token == TokenNameRPAREN) {
1756 throwSyntaxError("')' expected after 'foreach' expression.");
1761 } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
1763 if (token != TokenNameSEMICOLON) {
1766 if (token == TokenNameSEMICOLON) {
1769 if (token != TokenNameStopPHP) {
1770 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1776 } else if (token == TokenNameecho) {
1779 if (token == TokenNameSEMICOLON) {
1782 if (token != TokenNameStopPHP) {
1783 throwSyntaxError("';' expected after 'echo' statement.");
1788 // } else if (token == TokenNameprint) {
1791 // if (token == TokenNameSEMICOLON) {
1794 // if (token != TokenNameStopPHP) {
1795 // throwSyntaxError("';' expected after 'print' statement.");
1801 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1804 if (token == TokenNameSEMICOLON) {
1807 if (token != TokenNameStopPHP) {
1808 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1814 // } else if (token == TokenNameunset) {
1816 // if (token == TokenNameARGOPEN) {
1819 // throwSyntaxError("'(' expected after 'unset' keyword.");
1822 // if (token == TokenNameARGCLOSE) {
1825 // throwSyntaxError("')' expected after 'unset' statement.");
1827 // if (token == TokenNameSEMICOLON) {
1830 // if (token != TokenNameStopPHP) {
1831 // throwSyntaxError("';' expected after 'unset' statement.");
1837 // } else if (token == TokenNameexit || token == TokenNamedie) {
1839 // if (token != TokenNameSEMICOLON) {
1842 // if (token == TokenNameSEMICOLON) {
1845 // if (token != TokenNameStopPHP) {
1846 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1852 } else if (token == TokenNamedefine) {
1854 if (token == TokenNameLPAREN) {
1857 throwSyntaxError("'(' expected after 'define' keyword.");
1860 if (token == TokenNameCOMMA) {
1863 throwSyntaxError("',' expected after first 'define' constant.");
1866 if (token == TokenNameCOMMA) {
1870 if (token == TokenNameRPAREN) {
1873 throwSyntaxError("')' expected after 'define' statement.");
1875 if (token == TokenNameSEMICOLON) {
1878 if (token != TokenNameStopPHP) {
1879 throwSyntaxError("';' expected after 'define' statement.");
1884 } else if (token == TokenNamefunction) {
1886 functionDefinition();
1888 } else if (token == TokenNameclass) {
1894 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1895 } else if (token == TokenNameLBRACE) {
1896 // compoundStatement
1898 if (token != TokenNameRBRACE) {
1901 if (token == TokenNameRBRACE) {
1905 throwSyntaxError("'}' expected.");
1908 if (token != TokenNameSEMICOLON) {
1911 if (token == TokenNameSEMICOLON) {
1915 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1916 throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
1923 private void classDeclarator() throws CoreException {
1925 //identifier 'extends' identifier
1926 if (token == TokenNameIdentifier) {
1928 if (token == TokenNameextends) {
1930 if (token == TokenNameIdentifier) {
1933 throwSyntaxError("ClassDeclaration name expected after keyword 'extends'.");
1937 if (token > TokenNameKEYWORD) {
1938 throwSyntaxError("Don't use keyword for class declaration [" + token + "].");
1940 throwSyntaxError("ClassDeclaration name expected after keyword 'class'.");
1944 private void classBody() throws CoreException {
1945 //'{' [class-element-list] '}'
1946 if (token == TokenNameLBRACE) {
1948 if (token != TokenNameRBRACE) {
1951 if (token == TokenNameRBRACE) {
1954 throwSyntaxError("'}' expected at end of class body.");
1957 throwSyntaxError("'{' expected at start of class body.");
1961 private void classElementList() throws CoreException {
1964 } while (token == TokenNamefunction || token == TokenNamevar);
1967 private void classElement() throws CoreException {
1969 //function-definition
1970 if (token == TokenNamefunction) {
1972 functionDefinition();
1973 } else if (token == TokenNamevar) {
1977 throwSyntaxError("'function' or 'var' expected.");
1981 private void classProperty() throws CoreException {
1982 //'var' variable ';'
1983 //'var' variable '=' constant ';'
1985 if (token == TokenNameVariable) {
1987 if (token == TokenNameEQUAL) {
1992 throwSyntaxError("Variable expected after keyword 'var'.");
1994 if (token != TokenNameCOMMA) {
1999 if (token == TokenNameSEMICOLON) {
2002 throwSyntaxError("';' expected after variable declaration.");
2006 private void functionDefinition() throws CoreException {
2007 functionDeclarator();
2008 compoundStatement();
2011 private void functionDeclarator() throws CoreException {
2012 //identifier '(' [parameter-list] ')'
2013 if (token == TokenNameAND) {
2016 if (token == TokenNameIdentifier) {
2018 if (token == TokenNameLPAREN) {
2021 throwSyntaxError("'(' expected in function declaration.");
2023 if (token != TokenNameRPAREN) {
2026 if (token != TokenNameRPAREN) {
2027 throwSyntaxError("')' expected in function declaration.");
2032 if (token > TokenNameKEYWORD) {
2033 throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
2035 throwSyntaxError("Function name expected after keyword 'function'.");
2039 private void parameterList() throws CoreException {
2040 //parameter-declaration
2041 //parameter-list ',' parameter-declaration
2043 parameterDeclaration();
2044 if (token != TokenNameCOMMA) {
2051 private void parameterDeclaration() throws CoreException {
2053 //variable-reference
2054 if (token == TokenNameAND) {
2056 if (token == TokenNameVariable) {
2059 throwSyntaxError("Variable expected after reference operator '&'.");
2062 //variable '=' constant
2063 if (token == TokenNameVariable) {
2065 if (token == TokenNameEQUAL) {
2073 private void labeledStatementList() throws CoreException {
2074 if (token != TokenNamecase && token != TokenNamedefault) {
2075 throwSyntaxError("'case' or 'default' expected.");
2078 if (token == TokenNamecase) {
2081 if (token == TokenNameCOLON) {
2083 if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
2087 } else if (token == TokenNameSEMICOLON) {
2089 // "':' expected after 'case' keyword (Found token: "
2090 // + scanner.toStringAction(token)
2095 "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")",
2096 scanner.getCurrentTokenStartPosition(),
2097 scanner.getCurrentTokenEndPosition(),
2100 if (token == TokenNamecase) { // empty case statement ?
2105 throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
2107 } else { // TokenNamedefault
2109 if (token == TokenNameCOLON) {
2113 throwSyntaxError("':' character after 'default' expected.");
2116 } while (token == TokenNamecase || token == TokenNamedefault);
2119 // public void labeledStatement() {
2120 // if (token == TokenNamecase) {
2123 // if (token == TokenNameDDOT) {
2127 // throwSyntaxError("':' character after 'case' constant expected.");
2130 // } else if (token == TokenNamedefault) {
2132 // if (token == TokenNameDDOT) {
2136 // throwSyntaxError("':' character after 'default' expected.");
2142 // public void expressionStatement() {
2145 // private void inclusionStatement() {
2148 // public void compoundStatement() {
2151 // public void selectionStatement() {
2154 // public void iterationStatement() {
2157 // public void jumpStatement() {
2160 // public void outputStatement() {
2163 // public void scopeStatement() {
2166 // public void flowStatement() {
2169 // public void definitionStatement() {
2172 private void ifStatement() throws CoreException {
2173 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
2174 if (token == TokenNameCOLON) {
2178 case TokenNameelse :
2180 if (token == TokenNameCOLON) {
2184 if (token == TokenNameif) { //'else if'
2186 elseifStatementList();
2188 throwSyntaxError("':' expected after 'else'.");
2192 case TokenNameelseif :
2194 elseifStatementList();
2198 if (token != TokenNameendif) {
2199 throwSyntaxError("'endif' expected.");
2202 if (token != TokenNameSEMICOLON) {
2203 throwSyntaxError("';' expected after if-statement.");
2207 // statement [else-statement]
2209 if (token == TokenNameelseif) {
2211 if (token == TokenNameLPAREN) {
2214 throwSyntaxError("'(' expected after 'elseif' keyword.");
2217 if (token == TokenNameRPAREN) {
2220 throwSyntaxError("')' expected after 'elseif' condition.");
2223 } else if (token == TokenNameelse) {
2230 private void elseifStatementList() throws CoreException {
2234 case TokenNameelse :
2236 if (token == TokenNameCOLON) {
2241 if (token == TokenNameif) { //'else if'
2244 throwSyntaxError("':' expected after 'else'.");
2248 case TokenNameelseif :
2257 private void elseifStatement() throws CoreException {
2258 if (token == TokenNameLPAREN) {
2261 if (token != TokenNameLPAREN) {
2262 throwSyntaxError("')' expected in else-if-statement.");
2265 if (token != TokenNameCOLON) {
2266 throwSyntaxError("':' expected in else-if-statement.");
2273 private void switchStatement() throws CoreException {
2274 if (token == TokenNameCOLON) {
2275 // ':' [labeled-statement-list] 'endswitch' ';'
2277 labeledStatementList();
2278 if (token != TokenNameendswitch) {
2279 throwSyntaxError("'endswitch' expected.");
2282 if (token != TokenNameSEMICOLON) {
2283 throwSyntaxError("';' expected after switch-statement.");
2287 // '{' [labeled-statement-list] '}'
2288 if (token != TokenNameLBRACE) {
2289 throwSyntaxError("'{' expected in switch statement.");
2292 if (token != TokenNameRBRACE) {
2293 labeledStatementList();
2295 if (token != TokenNameRBRACE) {
2296 throwSyntaxError("'}' expected in switch statement.");
2303 private void forStatement() throws CoreException {
2304 if (token == TokenNameCOLON) {
2307 if (token != TokenNameendfor) {
2308 throwSyntaxError("'endfor' expected.");
2311 if (token != TokenNameSEMICOLON) {
2312 throwSyntaxError("';' expected after for-statement.");
2320 private void whileStatement() throws CoreException {
2321 // ':' statement-list 'endwhile' ';'
2322 if (token == TokenNameCOLON) {
2325 if (token != TokenNameendwhile) {
2326 throwSyntaxError("'endwhile' expected.");
2329 if (token != TokenNameSEMICOLON) {
2330 throwSyntaxError("';' expected after while-statement.");
2338 private void foreachStatement() throws CoreException {
2339 if (token == TokenNameCOLON) {
2342 if (token != TokenNameendforeach) {
2343 throwSyntaxError("'endforeach' expected.");
2346 if (token != TokenNameSEMICOLON) {
2347 throwSyntaxError("';' expected after foreach-statement.");
2355 private void exitStatus() throws CoreException {
2356 if (token == TokenNameLPAREN) {
2359 throwSyntaxError("'(' expected in 'exit-status'.");
2361 if (token != TokenNameRPAREN) {
2364 if (token == TokenNameRPAREN) {
2367 throwSyntaxError("')' expected after 'exit-status'.");
2371 private void expressionList() throws CoreException {
2374 if (token == TokenNameCOMMA) {
2382 private void expression() throws CoreException {
2383 //todo: find a better way to get the expression
2384 // expression = new StringBuffer();
2385 // for (int i = chIndx; i < str.length(); i++) {
2386 // if (str.charAt(i) == ';') {
2389 // expression.append(str.charAt(i));
2392 // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
2395 logicalinclusiveorExpression();
2396 // while (token != TokenNameSEMICOLON) {
2402 private void postfixExpression() throws CoreException {
2405 boolean castFlag = false;
2411 case TokenNamenull :
2414 case TokenNamefalse :
2417 case TokenNametrue :
2420 case TokenNameStringConstant :
2423 case TokenNameHEREDOC :
2424 case TokenNameStringInterpolated :
2425 case TokenNameStringLiteral :
2428 case TokenNameLPAREN :
2430 if (token == TokenNameIdentifier) {
2431 // check if identifier is a type:
2432 // ident = identifier;
2433 ident = scanner.getCurrentIdentifierSource();
2434 String str = new String(ident).toLowerCase();
2435 for (int i = 0; i < PHP_TYPES.length; i++) {
2436 if (PHP_TYPES[i].equals(str)) {
2443 if (token != TokenNameRPAREN) {
2444 throwSyntaxError(") expected after cast-type '" + str + "'.");
2454 if (token != TokenNameRPAREN) {
2455 throwSyntaxError(") expected in postfix-expression.");
2459 case TokenNameDoubleLiteral :
2462 case TokenNameIntegerLiteral :
2465 case TokenNameDOLLAR_LBRACE :
2468 if (token != TokenNameRBRACE) {
2469 throwSyntaxError("'}' expected after indirect variable token '${'.");
2473 case TokenNameVariable :
2474 ident = scanner.getCurrentIdentifierSource();
2476 if (token == TokenNameLBRACE) {
2479 if (token != TokenNameRBRACE) {
2480 throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression.");
2483 } else if (token == TokenNameLPAREN) {
2485 if (token != TokenNameRPAREN) {
2487 if (token != TokenNameRPAREN) {
2488 throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression.");
2494 case TokenNameIdentifier :
2495 ident = scanner.getCurrentIdentifierSource();
2497 if (token == TokenNameLPAREN) {
2499 if (token != TokenNameRPAREN) {
2501 if (token != TokenNameRPAREN) {
2503 "')' expected after identifier '"
2505 + "' in postfix-expression."
2507 + scanner.toStringAction(token)
2514 case TokenNameprint :
2517 // if (token == TokenNameSEMICOLON) {
2520 // if (token != TokenNameStopPHP) {
2521 // throwSyntaxError("';' expected after 'print' statement.");
2526 case TokenNamelist :
2528 if (token == TokenNameLPAREN) {
2530 if (token == TokenNameCOMMA) {
2534 if (token != TokenNameRPAREN) {
2535 throwSyntaxError("')' expected after 'list' keyword.");
2538 // if (token == TokenNameSET) {
2540 // logicalinclusiveorExpression();
2543 throwSyntaxError("'(' expected after 'list' keyword.");
2546 // case TokenNameexit :
2548 // if (token != TokenNameSEMICOLON) {
2551 // if (token == TokenNameSEMICOLON) {
2554 // if (token != TokenNameStopPHP) {
2555 // throwSyntaxError("';' expected after 'exit' expression.");
2560 // case TokenNamedie :
2562 // if (token != TokenNameSEMICOLON) {
2565 // if (token == TokenNameSEMICOLON) {
2568 // if (token != TokenNameStopPHP) {
2569 // throwSyntaxError("';' expected after 'die' expression.");
2574 // case TokenNamearray :
2576 // if (token == TokenNameARGOPEN) {
2578 // if (token == TokenNameCOMMA) {
2581 // expressionList();
2582 // if (token != TokenNameARGCLOSE) {
2583 // throwSyntaxError("')' expected after 'list' keyword.");
2586 // if (token == TokenNameSET) {
2588 // logicalinclusiveorExpression();
2591 // throwSyntaxError("'(' expected after 'list' keyword.");
2595 boolean while_flag = true;
2598 case TokenNameLBRACKET :
2601 if (token != TokenNameRBRACKET) {
2602 throwSyntaxError("] expected in postfix-expression.");
2606 case TokenNameCOLON_COLON : // ::
2607 case TokenNameMINUS_GREATER : // ->
2609 if (token > TokenNameKEYWORD) {
2610 ident = scanner.getCurrentIdentifierSource();
2612 // "Avoid using keyword '"
2613 // + new String(ident)
2614 // + "' as variable name.",
2618 "Avoid using keyword '" + new String(ident) + "' as variable name.",
2619 scanner.getCurrentTokenStartPosition(),
2620 scanner.getCurrentTokenEndPosition(),
2624 case TokenNameVariable :
2625 ident = scanner.getCurrentIdentifierSource();
2627 // if (token == TokenNameARGOPEN) {
2629 // expressionList();
2630 // if (token != TokenNameARGCLOSE) {
2631 // throwSyntaxError(") expected after variable '" + ident + "'.");
2636 case TokenNameIdentifier :
2637 //ident = scanner.getCurrentIdentifierSource();
2640 case TokenNameLBRACE :
2643 if (token != TokenNameRBRACE) {
2644 throwSyntaxError("} expected in postfix-expression.");
2649 throwSyntaxError("Syntax error after '->' token.");
2650 } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
2651 if (token == TokenNameLBRACKET) {
2654 if (token != TokenNameRBRACKET) {
2655 throwSyntaxError("] expected after '->'.");
2659 if (token == TokenNameLPAREN) {
2662 if (token != TokenNameRPAREN) {
2663 throwSyntaxError(") expected after '->'.");
2667 if (token == TokenNameLBRACE) {
2670 if (token != TokenNameRBRACE) {
2671 throwSyntaxError("} expected after '->'.");
2677 case TokenNamePLUS_PLUS :
2680 case TokenNameMINUS_MINUS :
2691 private void unaryExpression() throws CoreException {
2693 case TokenNamePLUS_PLUS :
2697 case TokenNameMINUS_MINUS :
2701 // '@' '&' '*' '+' '-' '~' '!'
2710 case TokenNameMULTIPLY :
2714 case TokenNamePLUS :
2718 case TokenNameMINUS :
2722 case TokenNameTWIDDLE :
2731 postfixExpression();
2735 private void castExpression() throws CoreException {
2736 // if (token == TokenNameARGOPEN) {
2739 // if (token != TokenNameARGCLOSE) {
2740 // throwSyntaxError(") expected after cast-expression.");
2747 // private void typeName() throws CoreException {
2748 // //'string' 'unset' 'array' 'object'
2749 // //'bool' 'boolean'
2750 // //'real' 'double' 'float'
2751 // //'int' 'integer'
2752 // String identifier = "";
2753 // if (token == TokenNameIdentifier) {
2754 // char[] ident = scanner.getCurrentIdentifierSource();
2755 // identifier = new String(ident);
2756 // String str = identifier.toLowerCase();
2758 // for (int i = 0; i < PHP_TYPES.length; i++) {
2759 // if (PHP_TYPES[i].equals(str)) {
2764 // throwSyntaxError(
2765 // "Expected type cast '( <type-name> )'; Got '" + identifier + "'.");
2768 private void assignExpression() throws CoreException {
2770 if (token == TokenNameEQUAL) { // =
2772 logicalinclusiveorExpression();
2773 } else if (token == TokenNameDOT_EQUAL) { // .=
2775 logicalinclusiveorExpression();
2776 } else if (token == TokenNameEQUAL_GREATER) { // =>
2778 logicalinclusiveorExpression();
2779 } else if (token == TokenNamePLUS_EQUAL) { // +=
2781 logicalinclusiveorExpression();
2782 } else if (token == TokenNameMINUS_EQUAL) { // -=
2784 logicalinclusiveorExpression();
2785 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2787 logicalinclusiveorExpression();
2788 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2790 logicalinclusiveorExpression();
2791 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2793 logicalinclusiveorExpression();
2794 } else if (token == TokenNameAND_EQUAL) { // &=
2796 logicalinclusiveorExpression();
2797 } else if (token == TokenNameOR_EQUAL) { // |=
2799 logicalinclusiveorExpression();
2800 } else if (token == TokenNameXOR_EQUAL) { // ^=
2802 logicalinclusiveorExpression();
2803 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2805 logicalinclusiveorExpression();
2806 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2808 logicalinclusiveorExpression();
2809 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2811 logicalinclusiveorExpression();
2815 private void multiplicativeExpression() throws CoreException {
2818 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
2825 private void concatenationExpression() throws CoreException {
2827 multiplicativeExpression();
2828 if (token != TokenNameDOT) {
2835 private void additiveExpression() throws CoreException {
2837 concatenationExpression();
2838 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2845 private void shiftExpression() throws CoreException {
2847 additiveExpression();
2848 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2855 private void relationalExpression() throws CoreException {
2858 if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2865 private void identicalExpression() throws CoreException {
2867 relationalExpression();
2868 if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
2875 private void equalityExpression() throws CoreException {
2877 identicalExpression();
2878 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2885 private void ternaryExpression() throws CoreException {
2886 equalityExpression();
2887 if (token == TokenNameQUESTION) {
2890 if (token == TokenNameCOLON) {
2894 throwSyntaxError("':' expected in ternary operator '? :'.");
2899 private void andExpression() throws CoreException {
2901 ternaryExpression();
2902 if (token != TokenNameAND) {
2909 private void exclusiveorExpression() throws CoreException {
2912 if (token != TokenNameXOR) {
2919 private void inclusiveorExpression() throws CoreException {
2921 exclusiveorExpression();
2922 if (token != TokenNameOR) {
2929 private void booleanandExpression() throws CoreException {
2931 inclusiveorExpression();
2932 if (token != TokenNameAND_AND) {
2939 private void booleanorExpression() throws CoreException {
2941 booleanandExpression();
2942 if (token != TokenNameOR_OR) {
2949 private void logicalandExpression() throws CoreException {
2951 booleanorExpression();
2952 if (token != TokenNameAND) {
2959 private void logicalexclusiveorExpression() throws CoreException {
2961 logicalandExpression();
2962 if (token != TokenNameXOR) {
2969 private void logicalinclusiveorExpression() throws CoreException {
2971 logicalexclusiveorExpression();
2972 if (token != TokenNameOR) {
2979 // public void assignmentExpression() {
2980 // if (token == TokenNameVARIABLE) {
2982 // if (token == TokenNameSET) {
2984 // logicalinclusiveorExpression();
2987 // logicalinclusiveorExpression();
2991 private void variableList() throws CoreException {
2994 if (token == TokenNameCOMMA) {
3002 private void variable() throws CoreException {
3003 if (token == TokenNameDOLLAR_LBRACE) {
3007 if (token != TokenNameRBRACE) {
3008 throwSyntaxError("'}' expected after indirect variable token '${'.");
3012 if (token == TokenNameVariable) {
3014 if (token == TokenNameLBRACKET) {
3017 if (token != TokenNameRBRACKET) {
3018 throwSyntaxError("']' expected in variable-list.");
3021 } else if (token == TokenNameEQUAL) {
3026 throwSyntaxError("$-variable expected in variable-list.");
3032 * It will look for a value (after a '=' for example)
3033 * @throws CoreException
3035 private void constant() throws CoreException {
3038 case TokenNamePLUS :
3041 case TokenNameDoubleLiteral :
3044 case TokenNameIntegerLiteral :
3048 throwSyntaxError("Constant expected after '+' presign.");
3051 case TokenNameMINUS :
3054 case TokenNameDoubleLiteral :
3057 case TokenNameIntegerLiteral :
3061 throwSyntaxError("Constant expected after '-' presign.");
3064 case TokenNamenull :
3067 case TokenNamefalse :
3070 case TokenNametrue :
3073 case TokenNameIdentifier :
3074 // ident = identifier;
3075 char[] ident = scanner.getCurrentIdentifierSource();
3077 if (token == TokenNameLPAREN) {
3079 if (token != TokenNameRPAREN) {
3081 if (token != TokenNameRPAREN) {
3082 throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression.");
3088 case TokenNameStringLiteral :
3091 case TokenNameStringConstant :
3094 case TokenNameStringInterpolated :
3097 case TokenNameDoubleLiteral :
3100 case TokenNameIntegerLiteral :
3104 throwSyntaxError("Constant expected.");