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 IFile fileToParse;
33 private ArrayList phpList;
35 private int currentPHPString;
36 private boolean phpEnd;
38 // private static HashMap keywordMap = null;
46 // row counter for syntax errors:
48 // column counter for syntax errors:
53 // // current identifier
59 private String stringValue;
61 /** Contains the current expression. */
62 // private StringBuffer expression;
64 private boolean phpMode;
66 // final static int TokenNameEOF = 0;
67 // final static int TokenNameERROR = 1;
68 // final static int TokenNameHTML = 2;
70 // final static int TokenNameREMAINDER = 30;
71 // final static int TokenNameNOT = 31;
72 // final static int TokenNameDOT = 32;
73 // final static int TokenNameXOR = 33;
74 // final static int TokenNameDIVIDE = 34;
75 // final static int TokenNameMULTIPLY = 35;
76 // final static int TokenNameMINUS = 36;
77 // final static int TokenNamePLUS = 37;
78 // final static int TokenNameEQUAL_EQUAL = 38;
79 // final static int TokenNameNOT_EQUAL = 39;
80 // final static int TokenNameGREATER = 40;
81 // final static int TokenNameGREATER_EQUAL = 41;
82 // final static int TokenNameLESS = 42;
83 // final static int TokenNameLESS_EQUAL = 43;
84 // final static int TokenNameAND_AND = 44;
85 // final static int TokenNameOR_OR = 45;
86 // // final static int TokenNameHASH = 46;
87 // final static int TokenNameCOLON = 47;
88 // final static int TokenNameDOT_EQUAL = 48;
90 // final static int TokenNameEQUAL = 49;
91 // final static int TokenNameMINUS_GREATER = 50; // ->
92 // final static int TokenNameFOREACH = 51;
93 // final static int TokenNameAND = 52;
94 // //final static int TokenNameDOLLARLISTOPEN = 53;
95 // final static int TokenNameTWIDDLE = 54;
96 // final static int TokenNameTWIDDLE_EQUAL = 55;
97 // final static int TokenNameREMAINDER_EQUAL = 56;
98 // final static int TokenNameXOR_EQUAL = 57;
99 // final static int TokenNameRIGHT_SHIFT_EQUAL = 58;
100 // final static int TokenNameLEFT_SHIFT_EQUAL = 59;
101 // final static int TokenNameAND_EQUAL = 60;
102 // final static int TokenNameOR_EQUAL = 61;
103 // final static int TokenNameQUESTION = 62;
104 // final static int TokenNameCOLON_COLON = 63;
105 // final static int TokenNameAT = 63;
106 // // final static int TokenNameHEREDOC = 64;
108 // final static int TokenNameDOLLAROPEN = 127;
109 // final static int TokenNameLPAREN = 128;
110 // final static int TokenNameRPAREN = 129;
111 // final static int TokenNameLBRACE = 130;
112 // final static int TokenNameRBRACE = 131;
113 // final static int TokenNameLBRACKET = 132;
114 // final static int TokenNameRBRACKET = 133;
115 // final static int TokenNameCOMMA = 134;
117 // final static int TokenNameStringLiteral = 136;
118 // final static int TokenNameIdentifier = 138;
119 // // final static int TokenNameDIGIT = 139;
120 // final static int TokenNameSEMICOLON = 140;
121 // // final static int TokenNameSLOT = 141;
122 // // final static int TokenNameSLOTSEQUENCE = 142;
123 // final static int TokenNameMINUS_MINUS = 144;
124 // final static int TokenNamePLUS_PLUS = 145;
125 // final static int TokenNamePLUS_EQUAL = 146;
126 // final static int TokenNameDIVIDE_EQUAL = 147;
127 // final static int TokenNameMINUS_EQUAL = 148;
128 // final static int TokenNameMULTIPLY_EQUAL = 149;
129 // final static int TokenNameVariable = 150;
130 // final static int TokenNameIntegerLiteral = 151;
131 // final static int TokenNameDoubleLiteral = 152;
132 // final static int TokenNameStringInterpolated = 153;
133 // final static int TokenNameStringConstant = 154;
135 // final static int TokenNameLEFT_SHIFT = 155;
136 // final static int TokenNameRIGHT_SHIFT = 156;
137 // final static int TokenNameEQUAL_EQUAL_EQUAL = 157;
138 // final static int TokenNameNOT_EQUAL_EQUAL = 158;
139 // final static int TokenNameOR = 159;
140 // final static int TokenNameAT = 153; // @
145 public void setFileToParse(IFile fileToParse) {
146 this.currentPHPString = 0;
147 this.fileToParse = fileToParse;
150 this.token = TokenNameEOF;
152 this.initializeScanner();
158 *@param sess Description of Parameter
161 public Parser(IFile fileToParse) {
162 // if (keywordMap == null) {
163 // keywordMap = new HashMap();
164 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
165 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
168 this.currentPHPString = 0;
169 this.fileToParse = fileToParse;
172 this.token = TokenNameEOF;
174 // this.rowCount = 1;
175 // this.columnCount = 0;
179 this.initializeScanner();
182 public void initializeScanner() {
183 this.scanner = new Scanner(false, false, false, false);
186 * Create marker for the parse error
188 private void setMarker(
193 throws CoreException {
194 setMarker(fileToParse, message, charStart, charEnd, errorLevel);
198 * This method will throw the SyntaxError.
199 * It will add the good lines and columns to the Error
200 * @param error the error message
201 * @throws SyntaxError the error raised
203 private void throwSyntaxError(String error) {
205 // if (str.length() < chIndx) {
208 // // read until end-of-line
210 // while (str.length() > eol) {
211 // ch = str.charAt(eol++);
217 // throw new SyntaxError(
219 // chIndx - columnCount + 1,
220 // str.substring(columnCount, eol),
222 throw new SyntaxError(1, 1, "", error);
226 * This method will throw the SyntaxError.
227 * It will add the good lines and columns to the Error
228 * @param error the error message
229 * @throws SyntaxError the error raised
231 private void throwSyntaxError(String error, int startRow) {
232 throw new SyntaxError(startRow, 0, " ", error);
236 * Method Declaration.
240 // private void getChar() {
241 // if (str.length() > chIndx) {
242 // ch = str.charAt(chIndx++);
247 // chIndx = str.length() + 1;
249 // // token = TokenNameEOF;
254 * gets the next token from input
256 private void getNextToken() throws CoreException {
258 token = scanner.getNextToken();
260 int currentEndPosition = scanner.getCurrentTokenEndPosition();
261 int currentStartPosition = scanner.getCurrentTokenStartPosition();
264 currentStartPosition + "," + currentEndPosition + ": ");
265 System.out.println(scanner.toStringAction(token));
267 } catch (InvalidInputException e) {
268 token = TokenNameERROR;
272 // boolean phpFound = false;
279 // while (str.length() > chIndx) {
280 // token = TokenNameERROR;
281 // ch = str.charAt(chIndx++);
287 // ch2 = str.charAt(chIndx++);
289 // ch2 = str.charAt(chIndx++);
290 // if (Character.isWhitespace(ch2)) {
295 // } else if (ch2 == 'p' || ch2 == 'P') {
296 // ch2 = str.charAt(chIndx++);
297 // if (ch2 == 'h' || ch2 == 'H') {
298 // ch2 = str.charAt(chIndx++);
299 // if (ch2 == 'p' || ch2 == 'P') {
317 // while (str.length() > chIndx) {
318 // ch = str.charAt(chIndx++);
319 // token = TokenNameERROR;
322 // columnCount = chIndx;
323 // continue; // while loop
325 // if (str.length() == chIndx) {
328 // if (!Character.isWhitespace(ch)) {
330 // if (str.length() > chIndx) {
331 // if (str.charAt(chIndx) == '{') {
333 // token = TokenNameDOLLAROPEN;
340 // if ((ch >= 'a' && ch <= 'z')
341 // || (ch >= 'A' && ch <= 'Z')
347 // if (ch >= '0' && ch <= '9') {
352 // if (str.length() > chIndx) {
353 // if (str.charAt(chIndx) == '/') {
356 // // read comment until end of line:
357 // while ((str.length() > chIndx)
358 // && (ch != '\n')) {
359 // ch = str.charAt(chIndx++);
361 // ch2 = str.charAt(chIndx);
364 // token = TokenNameHTML;
375 // } else if (str.charAt(chIndx) == '*') {
377 // // multi line comment:
378 // while (str.length() > chIndx) {
379 // if (str.charAt(chIndx) == '*'
380 // && (str.length() > (chIndx + 1))
381 // && str.charAt(chIndx + 1) == '/') {
385 // ch = str.charAt(chIndx++);
388 // columnCount = chIndx;
394 // } else if (ch == '#') {
395 // // read comment until end of line:
396 // while ((str.length() > chIndx) && (ch != '\n')) {
397 // ch = str.charAt(chIndx++);
399 // ch2 = str.charAt(chIndx);
402 // token = TokenNameHTML;
413 // } else if (ch == '"') {
416 // TokenNameStringInterpolated,
417 // "Open string character '\"' at end of file.");
419 // } else if (ch == '\'') {
422 // TokenNameStringConstant,
423 // "Open string character \"'\" at end of file.");
425 // } else if (ch == '`') {
428 // TokenNameStringConstant,
429 // "Open string character \"`\" at end of file.");
431 // "Other string delimiters prefered (found \"`\").",
440 // token = TokenNameLPAREN;
444 // token = TokenNameRPAREN;
448 // token = TokenNameLBRACE;
452 // token = TokenNameRBRACE;
456 // token = TokenNameLBRACKET;
460 // token = TokenNameRBRACKET;
464 // token = TokenNameCOMMA;
468 // token = TokenNameQUESTION;
469 // if (str.length() > chIndx) {
470 // if (str.charAt(chIndx) == '>') {
472 // token = TokenNameHTML;
482 // token = TokenNameAT;
485 // token = TokenNameTWIDDLE;
486 // if (str.length() > chIndx) {
487 // if (str.charAt(chIndx) == '=') {
489 // token = TokenNameTWIDDLE_EQUAL;
496 // token = TokenNameDOT;
497 // if (str.length() > chIndx) {
498 // if (str.charAt(chIndx) == '=') {
500 // token = TokenNameDOT_EQUAL;
508 // token = TokenNameStringLiteral;
512 // token = TokenNameREMAINDER;
513 // if (str.length() > chIndx) {
514 // if (str.charAt(chIndx) == '=') {
516 // token = TokenNameREMAINDER_EQUAL;
523 // token = TokenNameSEMICOLON;
527 // token = TokenNameXOR;
528 // if (str.length() > chIndx) {
529 // if (str.charAt(chIndx) == '=') {
531 // token = TokenNameXOR_EQUAL;
538 // token = TokenNameDIVIDE;
540 // if (str.length() > chIndx) {
541 // if (str.charAt(chIndx) == '=') {
543 // token = TokenNameDIVIDE_EQUAL;
551 // token = TokenNameMULTIPLY;
552 // if (str.length() > chIndx) {
553 // if (str.charAt(chIndx) == '*') {
555 // token = TokenNameXOR;
559 // if (str.charAt(chIndx) == '=') {
561 // token = TokenNameMULTIPLY_EQUAL;
569 // token = TokenNamePLUS;
570 // if (str.length() > chIndx) {
571 // if (str.charAt(chIndx) == '+') {
573 // token = TokenNamePLUS_PLUS;
577 // if (str.charAt(chIndx) == '=') {
579 // token = TokenNamePLUS_EQUAL;
586 // token = TokenNameMINUS;
587 // if (str.length() > chIndx) {
588 // if (str.charAt(chIndx) == '-') {
590 // token = TokenNameMINUS_MINUS;
594 // if (str.charAt(chIndx) == '=') {
596 // token = TokenNameMINUS_EQUAL;
600 // if (str.charAt(chIndx) == '>') {
602 // token = TokenNameMINUS_GREATER;
610 // token = TokenNameEQUAL;
612 // if (str.length() > chIndx) {
613 // ch = str.charAt(chIndx);
617 // token = TokenNameEQUAL_EQUAL;
618 // if (str.length() > chIndx) {
619 // ch = str.charAt(chIndx);
624 // TokenNameEQUAL_EQUAL_EQUAL;
631 // token = TokenNameEQUAL_GREATER;
639 // token = TokenNameNOT;
641 // if (str.length() > chIndx) {
642 // if (str.charAt(chIndx) == '=') {
644 // token = TokenNameNOT_EQUAL;
645 // if (str.length() > chIndx) {
646 // ch = str.charAt(chIndx);
651 // TokenNameNOT_EQUAL_EQUAL;
660 // token = TokenNameGREATER;
662 // if (str.length() > chIndx) {
663 // if (str.charAt(chIndx) == '=') {
665 // token = TokenNameGREATER_EQUAL;
668 // if (str.charAt(chIndx) == '>') {
670 // token = TokenNameRIGHT_SHIFT;
671 // if (str.length() > chIndx) {
672 // if (str.charAt(chIndx) == '=') {
675 // TokenNameRIGHT_SHIFT_EQUAL;
685 // token = TokenNameLESS;
687 // if (str.length() > chIndx) {
688 // if (str.charAt(chIndx) == '=') {
690 // token = TokenNameLESS_EQUAL;
694 // if (str.charAt(chIndx) == '<') {
696 // token = TokenNameLEFT_SHIFT;
697 // if (str.charAt(chIndx) == '<') {
699 // int startRow = rowCount;
700 // if (str.length() > chIndx) {
702 // ch = str.charAt(++chIndx);
703 // if ((ch >= 'a' && ch <= 'z')
704 // || (ch >= 'A' && ch <= 'Z')
709 // TokenNameStringConstant;
710 // while (str.length()
726 // .equals(identifier)) {
738 // "Open heredoc syntax after operator '<<<'.",
740 // } else if (str.charAt(chIndx) == '=') {
742 // token = TokenNameLEFT_SHIFT_EQUAL;
752 // token = TokenNameOR;
754 // if (str.length() > chIndx) {
755 // if (str.charAt(chIndx) == '|') {
757 // token = TokenNameOR_OR;
760 // if (str.charAt(chIndx) == '=') {
762 // token = TokenNameOR_EQUAL;
769 // token = TokenNameAND;
770 // if (str.length() > chIndx) {
771 // if (str.charAt(chIndx) == '&') {
773 // token = TokenNameAND_AND;
776 // if (str.charAt(chIndx) == '=') {
778 // token = TokenNameAND_EQUAL;
786 // token = TokenNameCOLON;
787 // if (str.length() > chIndx) {
788 // if (str.charAt(chIndx) == ':') {
790 // token = TokenNameCOLON_COLON;
795 // // token = TokenNameHASH;
799 // // token = TokenNameAT;
804 // "unexpected character: '" + ch + "'");
807 // if (token == TokenNameERROR) {
808 // throwSyntaxError("token not found");
815 // } catch (StringIndexOutOfBoundsException e) {
816 // // catched from charAt
819 // chIndx = str.length() + 1;
821 // token = TokenNameEOF;
824 // // if (phpList != null) {
825 // // if (currentPHPString < phpList.size()) {
826 // // token = TokenNameUNDEFINED;
827 // // temp = (PHPString) phpList.get(currentPHPString++);
828 // // this.str = temp.getPHPString();
829 // // this.token = TokenNameEOF;
830 // // this.chIndx = 0;
831 // // this.rowCount = temp.getLineNumber();
832 // // this.columnCount = 0;
833 // // getNextToken();
836 // // token = TokenNameUNDEFINED;
843 // * Get an identifier.
845 // private void getIdentifier() {
846 // // StringBuffer ident = new StringBuffer();
847 // int startPosition = chIndx - 1;
848 // // ident.append(ch);
851 // // attention recursive call:
853 // token = TokenNameVariable;
856 // token = TokenNameIdentifier;
861 // //this will read the buffer until the next character is a forbidden character for identifier
862 // while ((ch >= 'a' && ch <= 'z')
863 // || (ch >= 'A' && ch <= 'Z')
864 // || (ch >= '0' && ch <= '9')
866 // // ident.append(ch);
869 // int endPosition = chIndx--;
870 // int length = (--endPosition) - startPosition;
872 // identifier = str.substring(startPosition, endPosition);
873 // // System.out.println(identifier);
875 // // determine if this identitfer is a keyword
876 // // @todo improve this in future version
877 // Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
879 // token = i.intValue();
885 * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
886 * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
887 * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
888 * value {@link Parser#TokenNameINT_NUMBER}
890 // private void getNumber() {
891 // StringBuffer inum = new StringBuffer();
893 // int numFormat = 10;
895 // // save first digit
896 // char firstCh = ch;
900 // // determine number conversions:
901 // if (firstCh == '0') {
930 // if (numFormat == 16) {
931 // while ((ch >= '0' && ch <= '9')
932 // || (ch >= 'a' && ch <= 'f')
933 // || (ch >= 'A' && ch <= 'F')) {
938 // while ((ch >= '0' && ch <= '9')
942 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
943 // if (ch == '.' && dFlag != ' ') {
946 // if ((dFlag == 'E') || (dFlag == 'e')) {
952 // if ((ch == '-') || (ch == '+')) {
965 // if (dFlag != ' ') {
966 // doubleNumber = new Double(inum.toString());
967 // token = TokenNameDoubleLiteral;
970 // longNumber = Long.valueOf(inum.toString(), numFormat);
971 // token = TokenNameIntegerLiteral;
975 // } catch (Throwable e) {
976 // throwSyntaxError("Number format error: " + inum.toString());
982 // * @param openChar the opening char ('\'', '"', '`')
983 // * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
984 // * @param errorMsg the error message in case of parse error in the string
986 // private void getString(
987 // final char openChar,
988 // final int typeString,
989 // final String errorMsg) {
990 // StringBuffer sBuffer = new StringBuffer();
991 // boolean openString = true;
992 // int startRow = rowCount;
993 // while (str.length() > chIndx) {
994 // ch = str.charAt(chIndx++);
996 // sBuffer.append(ch);
997 // if (str.length() > chIndx) {
998 // ch = str.charAt(chIndx++);
999 // sBuffer.append(ch);
1001 // } else if (ch == openChar) {
1002 // openString = false;
1004 // } else if (ch == '\n') {
1006 // columnCount = chIndx;
1008 // sBuffer.append(ch);
1011 // if (openString) {
1012 // if (typeString == TokenNameStringConstant) {
1013 // throwSyntaxError(errorMsg, startRow);
1015 // throwSyntaxError(errorMsg);
1018 // token = typeString;
1019 // stringValue = sBuffer.toString();
1022 // public void htmlParserTester(String input) {
1023 // int lineNumber = 1;
1024 // int startLineNumber = 1;
1025 // int startIndex = 0;
1028 // boolean phpMode = false;
1029 // boolean phpFound = false;
1031 // phpList = new ArrayList();
1032 // currentPHPString = 0;
1036 // while (i < input.length()) {
1037 // ch = input.charAt(i++);
1038 // if (ch == '\n') {
1041 // if ((!phpMode) && ch == '<') {
1042 // ch2 = input.charAt(i++);
1043 // if (ch2 == '?') {
1044 // ch2 = input.charAt(i++);
1045 // if (Character.isWhitespace(ch2)) {
1050 // startLineNumber = lineNumber;
1052 // } else if (ch2 == 'p') {
1053 // ch2 = input.charAt(i++);
1054 // if (ch2 == 'h') {
1055 // ch2 = input.charAt(i++);
1056 // if (ch2 == 'p') {
1060 // startLineNumber = lineNumber;
1066 // } else if (ch2 == 'P') {
1067 // ch2 = input.charAt(i++);
1068 // if (ch2 == 'H') {
1069 // ch2 = input.charAt(i++);
1070 // if (ch2 == 'P') {
1074 // startLineNumber = lineNumber;
1087 // if (ch == '/' && i < input.length()) {
1088 // ch2 = input.charAt(i++);
1089 // if (ch2 == '/') {
1090 // while (i < input.length()) {
1091 // ch = input.charAt(i++);
1092 // if (ch == '?' && i < input.length()) {
1093 // ch2 = input.charAt(i++);
1094 // if (ch2 == '>') {
1102 // startLineNumber));
1106 // } else if (ch == '\n') {
1112 // } else if (ch2 == '*') {
1113 // // multi-line comment
1114 // while (i < input.length()) {
1115 // ch = input.charAt(i++);
1116 // if (ch == '\n') {
1118 // } else if (ch == '*' && i < input.length()) {
1119 // ch2 = input.charAt(i++);
1120 // if (ch2 == '/') {
1130 // } else if (ch == '#') {
1131 // while (i < input.length()) {
1132 // ch = input.charAt(i++);
1133 // if (ch == '?' && i < input.length()) {
1134 // ch2 = input.charAt(i++);
1135 // if (ch2 == '>') {
1140 // input.substring(startIndex, i - 2),
1141 // startLineNumber));
1145 // } else if (ch == '\n') {
1151 // } else if (ch == '"') {
1153 // while (i < input.length()) {
1154 // ch = input.charAt(i++);
1155 // if (ch == '\n') {
1158 // ch == '\\' && i < input.length()) { // escape
1160 // } else if (ch == '"') {
1165 // } else if (ch == '\'') {
1167 // while (i < input.length()) {
1168 // ch = input.charAt(i++);
1169 // if (ch == '\n') {
1172 // ch == '\\' && i < input.length()) { // escape
1174 // } else if (ch == '\'') {
1181 // if (ch == '?' && i < input.length()) {
1182 // ch2 = input.charAt(i++);
1183 // if (ch2 == '>') {
1188 // input.substring(startIndex, i - 2),
1189 // startLineNumber));
1199 // "No PHP source code found.",
1205 // "Open PHP tag at end of file.",
1210 // input.substring(startIndex, i - 2),
1211 // startLineNumber));
1213 // // for (int j=0;j<phpList.size();j++) {
1214 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
1215 // // int startIndx = temp.length()-10;
1216 // // if (startIndx<0) {
1217 // // startIndx = 0;
1219 // // System.out.println(temp.substring(startIndx)+"?>");
1221 // phpParserTester(null, 1);
1222 // // PHPString temp;
1223 // // for(int j=0;j<phpList.size();j++) {
1224 // // temp = (PHPString) phpList.get(j);
1225 // // parser.start(temp.getPHPString(), temp.getLineNumber());
1228 // } catch (CoreException e) {
1232 public void phpParserTester(String s, int rowCount) throws CoreException {
1235 if (phpList.size() != 0) {
1236 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
1239 this.token = TokenNameEOF;
1241 // this.rowCount = rowCount;
1242 // this.columnCount = 0;
1243 this.phpEnd = false;
1244 this.phpMode = true;
1245 scanner.setSource(s.toCharArray());
1246 scanner.setPHPMode(true);
1250 if (token != TokenNameEOF && token != TokenNameERROR) {
1253 if (token != TokenNameEOF) {
1254 if (token == TokenNameERROR) {
1256 "Scanner error (Found unknown token: "
1257 + scanner.toStringAction(token)
1260 if (token == TokenNameRPAREN) {
1261 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1263 if (token == TokenNameRBRACE) {
1264 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1266 if (token == TokenNameRBRACKET) {
1267 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1270 if (token == TokenNameLPAREN) {
1271 throwSyntaxError("Read character '('; end-of-file not reached.");
1273 if (token == TokenNameLBRACE) {
1274 throwSyntaxError("Read character '{'; end-of-file not reached.");
1276 if (token == TokenNameLBRACKET) {
1277 throwSyntaxError("Read character '['; end-of-file not reached.");
1280 throwSyntaxError("End-of-file not reached.");
1283 } catch (SyntaxError err) {
1287 // setMarker(err.getMessage(), err.getLine(), ERROR);
1290 scanner.getCurrentTokenStartPosition(),
1291 scanner.getCurrentTokenEndPosition(),
1294 // if an error occured,
1295 // try to find keywords 'class' or 'function'
1296 // to parse the rest of the string
1297 while (token != TokenNameEOF && token != TokenNameERROR) {
1298 if (token == TokenNameclass || token == TokenNamefunction) {
1303 if (token == TokenNameEOF || token == TokenNameERROR) {
1312 * Parses a string with php tags
1313 * i.e. '<body> <?php phpinfo() ?> </body>'
1315 public void parse(String s) throws CoreException {
1317 this.token = TokenNameEOF;
1319 // this.rowCount = 1;
1320 // this.columnCount = 0;
1321 this.phpEnd = false;
1322 this.phpMode = false;
1323 /* scanner initialization */
1324 scanner.setSource(s.toCharArray());
1325 scanner.setPHPMode(false);
1329 if (token != TokenNameEOF && token != TokenNameERROR) {
1332 if (token != TokenNameEOF) {
1333 if (token == TokenNameERROR) {
1335 "Scanner error (Found unknown token: "
1336 + scanner.toStringAction(token)
1339 if (token == TokenNameRPAREN) {
1340 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1342 if (token == TokenNameRBRACE) {
1343 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1345 if (token == TokenNameRBRACKET) {
1346 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1349 if (token == TokenNameLPAREN) {
1350 throwSyntaxError("Read character '('; end-of-file not reached.");
1352 if (token == TokenNameLBRACE) {
1353 throwSyntaxError("Read character '{'; end-of-file not reached.");
1355 if (token == TokenNameLBRACKET) {
1356 throwSyntaxError("Read character '['; end-of-file not reached.");
1359 throwSyntaxError("End-of-file not reached.");
1362 } catch (SyntaxError sytaxErr1) {
1363 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
1365 sytaxErr1.getMessage(),
1366 scanner.getCurrentTokenStartPosition(),
1367 scanner.getCurrentTokenEndPosition(),
1370 // if an error occured,
1371 // try to find keywords 'class' or 'function'
1372 // to parse the rest of the string
1373 while (token != TokenNameEOF && token != TokenNameERROR) {
1374 if (token == TokenNameclass || token == TokenNamefunction) {
1379 if (token == TokenNameEOF || token == TokenNameERROR) {
1382 } catch (SyntaxError sytaxErr2) {
1383 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
1385 sytaxErr2.getMessage(),
1386 scanner.getCurrentTokenStartPosition(),
1387 scanner.getCurrentTokenEndPosition(),
1396 public PHPOutlineInfo parseInfo(Object parent, String s) {
1397 PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
1398 // Stack stack = new Stack();
1399 // stack.push(outlineInfo.getDeclarations());
1402 this.token = TokenNameEOF;
1404 // this.rowCount = 1;
1405 // this.columnCount = 0;
1406 this.phpEnd = false;
1407 this.phpMode = false;
1408 scanner.setSource(s.toCharArray());
1409 scanner.setPHPMode(false);
1413 parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
1414 } catch (CoreException e) {
1419 private void parseDeclarations(
1420 PHPOutlineInfo outlineInfo,
1421 PHPSegmentWithChildren current,
1424 // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
1425 PHPSegmentWithChildren temp;
1428 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
1430 while (token != TokenNameEOF && token != TokenNameERROR) {
1431 if (token == TokenNameVariable) {
1432 ident = scanner.getCurrentIdentifierSource();
1433 outlineInfo.addVariable(new String(ident));
1435 } else if (token == TokenNamevar) {
1437 if (token == TokenNameVariable
1438 && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
1439 ident = scanner.getCurrentIdentifierSource();
1440 //substring(1) added because PHPVarDeclaration doesn't need the $ anymore
1441 String variableName = new String(ident).substring(1);
1442 outlineInfo.addVariable(variableName);
1444 if (token != TokenNameSEMICOLON) {
1447 ident = scanner.getCurrentTokenSource();
1448 if (token > TokenNameKEYWORD) {
1449 current.add(new PHPVarDeclaration(current, variableName,
1450 // chIndx - ident.length,
1451 scanner.getCurrentTokenStartPosition(), new String(ident)));
1454 case TokenNameVariable :
1455 current.add(new PHPVarDeclaration(current, variableName,
1456 // chIndx - ident.length,
1457 scanner.getCurrentTokenStartPosition(), new String(ident)));
1459 case TokenNameIdentifier :
1460 current.add(new PHPVarDeclaration(current, variableName,
1461 // chIndx - ident.length,
1462 scanner.getCurrentTokenStartPosition(), new String(ident)));
1464 case TokenNameDoubleLiteral :
1466 .add(new PHPVarDeclaration(
1468 variableName + doubleNumber,
1469 // chIndx - ident.length,
1470 scanner.getCurrentTokenStartPosition(), new String(ident)));
1472 case TokenNameIntegerLiteral :
1473 current.add(new PHPVarDeclaration(current, variableName,
1474 // chIndx - ident.length,
1475 scanner.getCurrentTokenStartPosition(), new String(ident)));
1477 case TokenNameStringInterpolated :
1478 case TokenNameStringLiteral :
1479 current.add(new PHPVarDeclaration(current, variableName,
1480 // chIndx - ident.length,
1481 scanner.getCurrentTokenStartPosition(), new String(ident)));
1483 case TokenNameStringConstant :
1484 current.add(new PHPVarDeclaration(current, variableName,
1485 // chIndx - ident.length,
1486 scanner.getCurrentTokenStartPosition(), new String(ident)));
1489 current.add(new PHPVarDeclaration(current, variableName,
1490 // chIndx - ident.length
1491 scanner.getCurrentTokenStartPosition()));
1497 ident = scanner.getCurrentIdentifierSource();
1499 current.add(new PHPVarDeclaration(current, variableName,
1500 // chIndx - ident.length
1501 scanner.getCurrentTokenStartPosition()));
1504 } else if (token == TokenNamefunction) {
1506 if (token == TokenNameAND) {
1509 if (token == TokenNameIdentifier
1510 && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
1511 ident = scanner.getCurrentIdentifierSource();
1512 outlineInfo.addVariable(new String(ident));
1513 temp = new PHPFunctionDeclaration(current, new String(ident),
1514 // chIndx - ident.length
1515 scanner.getCurrentTokenStartPosition());
1518 parseDeclarations(outlineInfo, temp, true);
1520 } else if (token == TokenNameclass) {
1522 if (token == TokenNameIdentifier
1523 && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
1524 ident = scanner.getCurrentIdentifierSource();
1525 outlineInfo.addVariable(new String(ident));
1526 temp = new PHPClassDeclaration(current, new String(ident),
1527 // chIndx - ident.len
1528 scanner.getCurrentTokenStartPosition());
1530 // stack.push(temp);
1533 //skip tokens for classname, extends and others until we have the opening '{'
1534 while (token != TokenNameLBRACE
1535 && token != TokenNameEOF
1536 && token != TokenNameERROR) {
1539 parseDeclarations(outlineInfo, temp, true);
1542 } else if (token == TokenNameLBRACE) {
1545 } else if (token == TokenNameRBRACE) {
1548 if (counter == 0 && goBack) {
1552 token == TokenNamerequire
1553 || token == TokenNamerequire_once
1554 || token == TokenNameinclude
1555 || token == TokenNameinclude_once) {
1556 ident = scanner.getCurrentTokenSource();
1559 int startPosition = scanner.getCurrentTokenStartPosition();
1561 char[] expr = scanner.getCurrentTokenSource(startPosition);
1562 outlineInfo.addVariable(new String(ident));
1563 current.add(new PHPReqIncDeclaration(current, new String(ident),
1564 // chIndx - ident.length,
1565 startPosition, new String(expr)));
1571 } catch (CoreException e) {
1572 } catch (SyntaxError sytaxErr) {
1574 // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
1576 sytaxErr.getMessage(),
1577 scanner.getCurrentTokenStartPosition(),
1578 scanner.getCurrentTokenEndPosition(),
1580 } catch (CoreException e) {
1585 private void statementList() throws CoreException {
1588 if ((token == TokenNameRBRACE)
1589 || (token == TokenNamecase)
1590 || (token == TokenNamedefault)
1591 || (token == TokenNameelseif)
1592 || (token == TokenNameendif)
1593 || (token == TokenNameendfor)
1594 || (token == TokenNameendforeach)
1595 || (token == TokenNameendwhile)
1596 || (token == TokenNameendswitch)
1597 || (token == TokenNameEOF)
1598 || (token == TokenNameERROR)) {
1604 private void compoundStatement() throws CoreException {
1605 // '{' [statement-list] '}'
1606 if (token == TokenNameLBRACE) {
1609 throwSyntaxError("'{' expected in compound-statement.");
1611 if (token != TokenNameRBRACE) {
1614 if (token == TokenNameRBRACE) {
1617 throwSyntaxError("'}' expected in compound-statement.");
1621 private void statement() throws CoreException {
1622 // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
1623 // char[] ident = scanner.getCurrentIdentifierSource();
1624 // String keyword = new String(ident);
1625 if (token == TokenNameinclude || token == TokenNameinclude_once) {
1628 if (token == TokenNameSEMICOLON) {
1631 if (token != TokenNameStopPHP) {
1632 throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1637 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1641 if (token == TokenNameSEMICOLON) {
1644 if (token != TokenNameStopPHP) {
1645 throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1650 } else if (token == TokenNameif) {
1652 if (token == TokenNameLPAREN) {
1655 throwSyntaxError("'(' expected after 'if' keyword.");
1658 if (token == TokenNameRPAREN) {
1661 throwSyntaxError("')' expected after 'if' condition.");
1666 } else if (token == TokenNameswitch) {
1668 if (token == TokenNameLPAREN) {
1671 throwSyntaxError("'(' expected after 'switch' keyword.");
1674 if (token == TokenNameRPAREN) {
1677 throwSyntaxError("')' expected after 'switch' condition.");
1681 } else if (token == TokenNamefor) {
1683 if (token == TokenNameLPAREN) {
1686 throwSyntaxError("'(' expected after 'for' keyword.");
1688 if (token == TokenNameSEMICOLON) {
1692 if (token == TokenNameSEMICOLON) {
1695 throwSyntaxError("';' expected after 'for'.");
1698 if (token == TokenNameSEMICOLON) {
1702 if (token == TokenNameSEMICOLON) {
1705 throwSyntaxError("';' expected after 'for'.");
1708 if (token == TokenNameRPAREN) {
1712 if (token == TokenNameRPAREN) {
1715 throwSyntaxError("')' expected after 'for'.");
1720 } else if (token == TokenNamewhile) {
1722 if (token == TokenNameLPAREN) {
1725 throwSyntaxError("'(' expected after 'while' keyword.");
1728 if (token == TokenNameRPAREN) {
1731 throwSyntaxError("')' expected after 'while' condition.");
1735 } else if (token == TokenNamedo) {
1737 if (token == TokenNameLBRACE) {
1740 throwSyntaxError("'{' expected after 'do' keyword.");
1742 if (token != TokenNameRBRACE) {
1745 if (token == TokenNameRBRACE) {
1748 throwSyntaxError("'}' expected after 'do' keyword.");
1750 if (token == TokenNamewhile) {
1752 if (token == TokenNameLPAREN) {
1755 throwSyntaxError("'(' expected after 'while' keyword.");
1758 if (token == TokenNameRPAREN) {
1761 throwSyntaxError("')' expected after 'while' condition.");
1764 throwSyntaxError("'while' expected after 'do' keyword.");
1766 if (token == TokenNameSEMICOLON) {
1769 if (token != TokenNameStopPHP) {
1770 throwSyntaxError("';' expected after do-while statement.");
1775 } else if (token == TokenNameforeach) {
1777 if (token == TokenNameLPAREN) {
1780 throwSyntaxError("'(' expected after 'foreach' keyword.");
1783 if (token == TokenNameas) {
1786 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1789 if (token == TokenNameEQUAL_GREATER) {
1793 if (token == TokenNameRPAREN) {
1796 throwSyntaxError("')' expected after 'foreach' expression.");
1802 token == TokenNamecontinue
1803 || token == TokenNamebreak
1804 || token == TokenNamereturn) {
1806 if (token != TokenNameSEMICOLON) {
1809 if (token == TokenNameSEMICOLON) {
1812 if (token != TokenNameStopPHP) {
1813 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1819 } else if (token == TokenNameecho) {
1822 if (token == TokenNameSEMICOLON) {
1825 if (token != TokenNameStopPHP) {
1826 throwSyntaxError("';' expected after 'echo' statement.");
1831 // } else if (token == TokenNameprint) {
1834 // if (token == TokenNameSEMICOLON) {
1837 // if (token != TokenNameStopPHP) {
1838 // throwSyntaxError("';' expected after 'print' statement.");
1844 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1847 if (token == TokenNameSEMICOLON) {
1850 if (token != TokenNameStopPHP) {
1851 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1857 // } else if (token == TokenNameunset) {
1859 // if (token == TokenNameARGOPEN) {
1862 // throwSyntaxError("'(' expected after 'unset' keyword.");
1865 // if (token == TokenNameARGCLOSE) {
1868 // throwSyntaxError("')' expected after 'unset' statement.");
1870 // if (token == TokenNameSEMICOLON) {
1873 // if (token != TokenNameStopPHP) {
1874 // throwSyntaxError("';' expected after 'unset' statement.");
1880 // } else if (token == TokenNameexit || token == TokenNamedie) {
1882 // if (token != TokenNameSEMICOLON) {
1885 // if (token == TokenNameSEMICOLON) {
1888 // if (token != TokenNameStopPHP) {
1889 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1895 } else if (token == TokenNamedefine) {
1897 if (token == TokenNameLPAREN) {
1900 throwSyntaxError("'(' expected after 'define' keyword.");
1903 if (token == TokenNameCOMMA) {
1906 throwSyntaxError("',' expected after first 'define' constant.");
1909 if (token == TokenNameCOMMA) {
1913 if (token == TokenNameRPAREN) {
1916 throwSyntaxError("')' expected after 'define' statement.");
1918 if (token == TokenNameSEMICOLON) {
1921 if (token != TokenNameStopPHP) {
1922 throwSyntaxError("';' expected after 'define' statement.");
1927 } else if (token == TokenNamefunction) {
1929 functionDefinition();
1931 } else if (token == TokenNameclass) {
1937 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1938 } else if (token == TokenNameLBRACE) {
1939 // compoundStatement
1941 if (token != TokenNameRBRACE) {
1944 if (token == TokenNameRBRACE) {
1948 throwSyntaxError("'}' expected.");
1951 if (token != TokenNameSEMICOLON) {
1954 if (token == TokenNameSEMICOLON) {
1958 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1960 "';' expected after expression (Found token: "
1961 + scanner.toStringAction(token)
1969 private void classDeclarator() throws CoreException {
1971 //identifier 'extends' identifier
1972 if (token == TokenNameIdentifier) {
1974 if (token == TokenNameextends) {
1976 if (token == TokenNameIdentifier) {
1979 throwSyntaxError("Class name expected after keyword 'extends'.");
1983 if (token > TokenNameKEYWORD) {
1985 "Don't use keyword for class declaration [" + token + "].");
1987 throwSyntaxError("Class name expected after keyword 'class'.");
1991 private void classBody() throws CoreException {
1992 //'{' [class-element-list] '}'
1993 if (token == TokenNameLBRACE) {
1995 if (token != TokenNameRBRACE) {
1998 if (token == TokenNameRBRACE) {
2001 throwSyntaxError("'}' expected at end of class body.");
2004 throwSyntaxError("'{' expected at start of class body.");
2008 private void classElementList() throws CoreException {
2011 } while (token == TokenNamefunction || token == TokenNamevar);
2014 private void classElement() throws CoreException {
2016 //function-definition
2017 if (token == TokenNamefunction) {
2019 functionDefinition();
2020 } else if (token == TokenNamevar) {
2024 throwSyntaxError("'function' or 'var' expected.");
2028 private void classProperty() throws CoreException {
2029 //'var' variable ';'
2030 //'var' variable '=' constant ';'
2032 if (token == TokenNameVariable) {
2034 if (token == TokenNameEQUAL) {
2039 throwSyntaxError("Variable expected after keyword 'var'.");
2041 if (token != TokenNameCOMMA) {
2046 if (token == TokenNameSEMICOLON) {
2049 throwSyntaxError("';' expected after variable declaration.");
2053 private void functionDefinition() throws CoreException {
2054 functionDeclarator();
2055 compoundStatement();
2058 private void functionDeclarator() throws CoreException {
2059 //identifier '(' [parameter-list] ')'
2060 if (token == TokenNameAND) {
2063 if (token == TokenNameIdentifier) {
2065 if (token == TokenNameLPAREN) {
2068 throwSyntaxError("'(' expected in function declaration.");
2070 if (token != TokenNameRPAREN) {
2073 if (token != TokenNameRPAREN) {
2074 throwSyntaxError("')' expected in function declaration.");
2079 if (token > TokenNameKEYWORD) {
2081 "Don't use keyword for function declaration [" + token + "].");
2083 throwSyntaxError("Function name expected after keyword 'function'.");
2087 private void parameterList() throws CoreException {
2088 //parameter-declaration
2089 //parameter-list ',' parameter-declaration
2091 parameterDeclaration();
2092 if (token != TokenNameCOMMA) {
2099 private void parameterDeclaration() throws CoreException {
2101 //variable-reference
2102 if (token == TokenNameAND) {
2104 if (token == TokenNameVariable) {
2107 throwSyntaxError("Variable expected after reference operator '&'.");
2110 //variable '=' constant
2111 if (token == TokenNameVariable) {
2113 if (token == TokenNameEQUAL) {
2121 private void labeledStatementList() throws CoreException {
2122 if (token != TokenNamecase && token != TokenNamedefault) {
2123 throwSyntaxError("'case' or 'default' expected.");
2126 if (token == TokenNamecase) {
2129 if (token == TokenNameCOLON) {
2131 if (token == TokenNamecase
2132 || token == TokenNamedefault) { // empty case statement ?
2136 } else if (token == TokenNameSEMICOLON) {
2138 // "':' expected after 'case' keyword (Found token: "
2139 // + scanner.toStringAction(token)
2144 "':' expected after 'case' keyword (Found token: "
2145 + scanner.toStringAction(token)
2147 scanner.getCurrentTokenStartPosition(),
2148 scanner.getCurrentTokenEndPosition(),
2151 if (token == TokenNamecase) { // empty case statement ?
2157 "':' character after 'case' constant expected (Found token: "
2158 + scanner.toStringAction(token)
2161 } else { // TokenNamedefault
2163 if (token == TokenNameCOLON) {
2167 throwSyntaxError("':' character after 'default' expected.");
2170 } while (token == TokenNamecase || token == TokenNamedefault);
2173 // public void labeledStatement() {
2174 // if (token == TokenNamecase) {
2177 // if (token == TokenNameDDOT) {
2181 // throwSyntaxError("':' character after 'case' constant expected.");
2184 // } else if (token == TokenNamedefault) {
2186 // if (token == TokenNameDDOT) {
2190 // throwSyntaxError("':' character after 'default' expected.");
2196 // public void expressionStatement() {
2199 // private void inclusionStatement() {
2202 // public void compoundStatement() {
2205 // public void selectionStatement() {
2208 // public void iterationStatement() {
2211 // public void jumpStatement() {
2214 // public void outputStatement() {
2217 // public void scopeStatement() {
2220 // public void flowStatement() {
2223 // public void definitionStatement() {
2226 private void ifStatement() throws CoreException {
2227 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
2228 if (token == TokenNameCOLON) {
2232 case TokenNameelse :
2234 if (token == TokenNameCOLON) {
2238 if (token == TokenNameif) { //'else if'
2240 elseifStatementList();
2242 throwSyntaxError("':' expected after 'else'.");
2246 case TokenNameelseif :
2248 elseifStatementList();
2252 if (token != TokenNameendif) {
2253 throwSyntaxError("'endif' expected.");
2256 if (token != TokenNameSEMICOLON) {
2257 throwSyntaxError("';' expected after if-statement.");
2261 // statement [else-statement]
2263 if (token == TokenNameelseif) {
2265 if (token == TokenNameLPAREN) {
2268 throwSyntaxError("'(' expected after 'elseif' keyword.");
2271 if (token == TokenNameRPAREN) {
2274 throwSyntaxError("')' expected after 'elseif' condition.");
2277 } else if (token == TokenNameelse) {
2284 private void elseifStatementList() throws CoreException {
2288 case TokenNameelse :
2290 if (token == TokenNameCOLON) {
2295 if (token == TokenNameif) { //'else if'
2298 throwSyntaxError("':' expected after 'else'.");
2302 case TokenNameelseif :
2311 private void elseifStatement() throws CoreException {
2312 if (token == TokenNameLPAREN) {
2315 if (token != TokenNameLPAREN) {
2316 throwSyntaxError("')' expected in else-if-statement.");
2319 if (token != TokenNameCOLON) {
2320 throwSyntaxError("':' expected in else-if-statement.");
2327 private void switchStatement() throws CoreException {
2328 if (token == TokenNameCOLON) {
2329 // ':' [labeled-statement-list] 'endswitch' ';'
2331 labeledStatementList();
2332 if (token != TokenNameendswitch) {
2333 throwSyntaxError("'endswitch' expected.");
2336 if (token != TokenNameSEMICOLON) {
2337 throwSyntaxError("';' expected after switch-statement.");
2341 // '{' [labeled-statement-list] '}'
2342 if (token != TokenNameLBRACE) {
2343 throwSyntaxError("'{' expected in switch statement.");
2346 if (token != TokenNameRBRACE) {
2347 labeledStatementList();
2349 if (token != TokenNameRBRACE) {
2350 throwSyntaxError("'}' expected in switch statement.");
2357 private void forStatement() throws CoreException {
2358 if (token == TokenNameCOLON) {
2361 if (token != TokenNameendfor) {
2362 throwSyntaxError("'endfor' expected.");
2365 if (token != TokenNameSEMICOLON) {
2366 throwSyntaxError("';' expected after for-statement.");
2374 private void whileStatement() throws CoreException {
2375 // ':' statement-list 'endwhile' ';'
2376 if (token == TokenNameCOLON) {
2379 if (token != TokenNameendwhile) {
2380 throwSyntaxError("'endwhile' expected.");
2383 if (token != TokenNameSEMICOLON) {
2384 throwSyntaxError("';' expected after while-statement.");
2392 private void foreachStatement() throws CoreException {
2393 if (token == TokenNameCOLON) {
2396 if (token != TokenNameendforeach) {
2397 throwSyntaxError("'endforeach' expected.");
2400 if (token != TokenNameSEMICOLON) {
2401 throwSyntaxError("';' expected after foreach-statement.");
2409 private void exitStatus() throws CoreException {
2410 if (token == TokenNameLPAREN) {
2413 throwSyntaxError("'(' expected in 'exit-status'.");
2415 if (token != TokenNameRPAREN) {
2418 if (token == TokenNameRPAREN) {
2421 throwSyntaxError("')' expected after 'exit-status'.");
2425 private void expressionList() throws CoreException {
2428 if (token == TokenNameCOMMA) {
2436 private void expression() throws CoreException {
2437 //todo: find a better way to get the expression
2438 // expression = new StringBuffer();
2439 // for (int i = chIndx; i < str.length(); i++) {
2440 // if (str.charAt(i) == ';') {
2443 // expression.append(str.charAt(i));
2446 // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
2449 logicalinclusiveorExpression();
2450 // while (token != TokenNameSEMICOLON) {
2456 private void postfixExpression() throws CoreException {
2459 boolean castFlag = false;
2465 case TokenNamenull :
2468 case TokenNamefalse :
2471 case TokenNametrue :
2474 case TokenNameStringConstant :
2477 case TokenNameHEREDOC :
2478 case TokenNameStringInterpolated :
2479 case TokenNameStringLiteral :
2482 case TokenNameLPAREN :
2484 if (token == TokenNameIdentifier) {
2485 // check if identifier is a type:
2486 // ident = identifier;
2487 ident = scanner.getCurrentIdentifierSource();
2488 String str = new String(ident).toLowerCase();
2489 for (int i = 0; i < PHP_TYPES.length; i++) {
2490 if (PHP_TYPES[i].equals(str)) {
2497 if (token != TokenNameRPAREN) {
2498 throwSyntaxError(") expected after cast-type '" + str + "'.");
2508 if (token != TokenNameRPAREN) {
2509 throwSyntaxError(") expected in postfix-expression.");
2513 case TokenNameDoubleLiteral :
2516 case TokenNameIntegerLiteral :
2519 case TokenNameDOLLAR_LBRACE :
2522 if (token != TokenNameRBRACE) {
2523 throwSyntaxError("'}' expected after indirect variable token '${'.");
2527 case TokenNameVariable :
2528 ident = scanner.getCurrentIdentifierSource();
2530 if (token == TokenNameLBRACE) {
2533 if (token != TokenNameRBRACE) {
2535 "'}' expected after variable '"
2537 + "' in variable-expression.");
2540 } else if (token == TokenNameLPAREN) {
2542 if (token != TokenNameRPAREN) {
2544 if (token != TokenNameRPAREN) {
2546 "')' expected after variable '"
2548 + "' in postfix-expression.");
2554 case TokenNameIdentifier :
2555 ident = scanner.getCurrentIdentifierSource();
2557 if (token == TokenNameLPAREN) {
2559 if (token != TokenNameRPAREN) {
2561 if (token != TokenNameRPAREN) {
2563 "')' expected after identifier '"
2565 + "' in postfix-expression."
2567 + scanner.toStringAction(token)
2574 case TokenNameprint :
2577 // if (token == TokenNameSEMICOLON) {
2580 // if (token != TokenNameStopPHP) {
2581 // throwSyntaxError("';' expected after 'print' statement.");
2586 case TokenNamelist :
2588 if (token == TokenNameLPAREN) {
2590 if (token == TokenNameCOMMA) {
2594 if (token != TokenNameRPAREN) {
2595 throwSyntaxError("')' expected after 'list' keyword.");
2598 // if (token == TokenNameSET) {
2600 // logicalinclusiveorExpression();
2603 throwSyntaxError("'(' expected after 'list' keyword.");
2606 // case TokenNameexit :
2608 // if (token != TokenNameSEMICOLON) {
2611 // if (token == TokenNameSEMICOLON) {
2614 // if (token != TokenNameStopPHP) {
2615 // throwSyntaxError("';' expected after 'exit' expression.");
2620 // case TokenNamedie :
2622 // if (token != TokenNameSEMICOLON) {
2625 // if (token == TokenNameSEMICOLON) {
2628 // if (token != TokenNameStopPHP) {
2629 // throwSyntaxError("';' expected after 'die' expression.");
2634 // case TokenNamearray :
2636 // if (token == TokenNameARGOPEN) {
2638 // if (token == TokenNameCOMMA) {
2641 // expressionList();
2642 // if (token != TokenNameARGCLOSE) {
2643 // throwSyntaxError("')' expected after 'list' keyword.");
2646 // if (token == TokenNameSET) {
2648 // logicalinclusiveorExpression();
2651 // throwSyntaxError("'(' expected after 'list' keyword.");
2655 boolean while_flag = true;
2658 case TokenNameLBRACKET :
2661 if (token != TokenNameRBRACKET) {
2662 throwSyntaxError("] expected in postfix-expression.");
2666 case TokenNameCOLON_COLON : // ::
2667 case TokenNameMINUS_GREATER : // ->
2669 if (token > TokenNameKEYWORD) {
2670 ident = scanner.getCurrentIdentifierSource();
2672 // "Avoid using keyword '"
2673 // + new String(ident)
2674 // + "' as variable name.",
2678 "Avoid using keyword '"
2680 + "' as variable name.",
2681 scanner.getCurrentTokenStartPosition(),
2682 scanner.getCurrentTokenEndPosition(),
2686 case TokenNameVariable :
2687 ident = scanner.getCurrentIdentifierSource();
2689 // if (token == TokenNameARGOPEN) {
2691 // expressionList();
2692 // if (token != TokenNameARGCLOSE) {
2693 // throwSyntaxError(") expected after variable '" + ident + "'.");
2698 case TokenNameIdentifier :
2699 //ident = scanner.getCurrentIdentifierSource();
2702 case TokenNameLBRACE :
2705 if (token != TokenNameRBRACE) {
2706 throwSyntaxError("} expected in postfix-expression.");
2711 throwSyntaxError("Syntax error after '->' token.");
2713 token == TokenNameLBRACKET
2714 || token == TokenNameLPAREN
2715 || token == TokenNameLBRACE) {
2716 if (token == TokenNameLBRACKET) {
2719 if (token != TokenNameRBRACKET) {
2720 throwSyntaxError("] expected after '->'.");
2724 if (token == TokenNameLPAREN) {
2727 if (token != TokenNameRPAREN) {
2728 throwSyntaxError(") expected after '->'.");
2732 if (token == TokenNameLBRACE) {
2735 if (token != TokenNameRBRACE) {
2736 throwSyntaxError("} expected after '->'.");
2742 case TokenNamePLUS_PLUS :
2745 case TokenNameMINUS_MINUS :
2756 private void unaryExpression() throws CoreException {
2758 case TokenNamePLUS_PLUS :
2762 case TokenNameMINUS_MINUS :
2766 // '@' '&' '*' '+' '-' '~' '!'
2775 case TokenNameMULTIPLY :
2779 case TokenNamePLUS :
2783 case TokenNameMINUS :
2787 case TokenNameTWIDDLE :
2796 postfixExpression();
2800 private void castExpression() throws CoreException {
2801 // if (token == TokenNameARGOPEN) {
2804 // if (token != TokenNameARGCLOSE) {
2805 // throwSyntaxError(") expected after cast-expression.");
2812 // private void typeName() throws CoreException {
2813 // //'string' 'unset' 'array' 'object'
2814 // //'bool' 'boolean'
2815 // //'real' 'double' 'float'
2816 // //'int' 'integer'
2817 // String identifier = "";
2818 // if (token == TokenNameIdentifier) {
2819 // char[] ident = scanner.getCurrentIdentifierSource();
2820 // identifier = new String(ident);
2821 // String str = identifier.toLowerCase();
2823 // for (int i = 0; i < PHP_TYPES.length; i++) {
2824 // if (PHP_TYPES[i].equals(str)) {
2829 // throwSyntaxError(
2830 // "Expected type cast '( <type-name> )'; Got '" + identifier + "'.");
2833 private void assignExpression() throws CoreException {
2835 if (token == TokenNameEQUAL) { // =
2837 logicalinclusiveorExpression();
2838 } else if (token == TokenNameDOT_EQUAL) { // .=
2840 logicalinclusiveorExpression();
2841 } else if (token == TokenNameEQUAL_GREATER) { // =>
2843 logicalinclusiveorExpression();
2844 } else if (token == TokenNamePLUS_EQUAL) { // +=
2846 logicalinclusiveorExpression();
2847 } else if (token == TokenNameMINUS_EQUAL) { // -=
2849 logicalinclusiveorExpression();
2850 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2852 logicalinclusiveorExpression();
2853 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2855 logicalinclusiveorExpression();
2856 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2858 logicalinclusiveorExpression();
2859 } else if (token == TokenNameAND_EQUAL) { // &=
2861 logicalinclusiveorExpression();
2862 } else if (token == TokenNameOR_EQUAL) { // |=
2864 logicalinclusiveorExpression();
2865 } else if (token == TokenNameXOR_EQUAL) { // ^=
2867 logicalinclusiveorExpression();
2868 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2870 logicalinclusiveorExpression();
2871 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2873 logicalinclusiveorExpression();
2874 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2876 logicalinclusiveorExpression();
2880 private void multiplicativeExpression() throws CoreException {
2883 if (token != TokenNameMULTIPLY
2884 && token != TokenNameDIVIDE
2885 && token != TokenNameREMAINDER) {
2892 private void concatenationExpression() throws CoreException {
2894 multiplicativeExpression();
2895 if (token != TokenNameDOT) {
2902 private void additiveExpression() throws CoreException {
2904 concatenationExpression();
2905 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2912 private void shiftExpression() throws CoreException {
2914 additiveExpression();
2915 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2922 private void relationalExpression() throws CoreException {
2925 if (token != TokenNameLESS
2926 && token != TokenNameGREATER
2927 && token != TokenNameLESS_EQUAL
2928 && token != TokenNameGREATER_EQUAL) {
2935 private void identicalExpression() throws CoreException {
2937 relationalExpression();
2938 if (token != TokenNameEQUAL_EQUAL_EQUAL
2939 && token != TokenNameNOT_EQUAL_EQUAL) {
2946 private void equalityExpression() throws CoreException {
2948 identicalExpression();
2949 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2956 private void ternaryExpression() throws CoreException {
2957 equalityExpression();
2958 if (token == TokenNameQUESTION) {
2961 if (token == TokenNameCOLON) {
2965 throwSyntaxError("':' expected in ternary operator '? :'.");
2970 private void andExpression() throws CoreException {
2972 ternaryExpression();
2973 if (token != TokenNameAND) {
2980 private void exclusiveorExpression() throws CoreException {
2983 if (token != TokenNameXOR) {
2990 private void inclusiveorExpression() throws CoreException {
2992 exclusiveorExpression();
2993 if (token != TokenNameOR) {
3000 private void booleanandExpression() throws CoreException {
3002 inclusiveorExpression();
3003 if (token != TokenNameAND_AND) {
3010 private void booleanorExpression() throws CoreException {
3012 booleanandExpression();
3013 if (token != TokenNameOR_OR) {
3020 private void logicalandExpression() throws CoreException {
3022 booleanorExpression();
3023 if (token != TokenNameAND) {
3030 private void logicalexclusiveorExpression() throws CoreException {
3032 logicalandExpression();
3033 if (token != TokenNameXOR) {
3040 private void logicalinclusiveorExpression() throws CoreException {
3042 logicalexclusiveorExpression();
3043 if (token != TokenNameOR) {
3050 // public void assignmentExpression() {
3051 // if (token == TokenNameVARIABLE) {
3053 // if (token == TokenNameSET) {
3055 // logicalinclusiveorExpression();
3058 // logicalinclusiveorExpression();
3062 private void variableList() throws CoreException {
3065 if (token == TokenNameCOMMA) {
3073 private void variable() throws CoreException {
3074 if (token == TokenNameDOLLAR_LBRACE) {
3078 if (token != TokenNameRBRACE) {
3079 throwSyntaxError("'}' expected after indirect variable token '${'.");
3083 if (token == TokenNameVariable) {
3085 if (token == TokenNameLBRACKET) {
3088 if (token != TokenNameRBRACKET) {
3089 throwSyntaxError("']' expected in variable-list.");
3092 } else if (token == TokenNameEQUAL) {
3097 throwSyntaxError("$-variable expected in variable-list.");
3103 * It will look for a value (after a '=' for example)
3104 * @throws CoreException
3106 private void constant() throws CoreException {
3109 case TokenNamePLUS :
3112 case TokenNameDoubleLiteral :
3115 case TokenNameIntegerLiteral :
3119 throwSyntaxError("Constant expected after '+' presign.");
3122 case TokenNameMINUS :
3125 case TokenNameDoubleLiteral :
3128 case TokenNameIntegerLiteral :
3132 throwSyntaxError("Constant expected after '-' presign.");
3135 case TokenNamenull :
3138 case TokenNamefalse :
3141 case TokenNametrue :
3144 case TokenNameIdentifier :
3145 // ident = identifier;
3146 char[] ident = scanner.getCurrentIdentifierSource();
3148 if (token == TokenNameLPAREN) {
3150 if (token != TokenNameRPAREN) {
3152 if (token != TokenNameRPAREN) {
3154 "')' expected after identifier '"
3156 + "' in postfix-expression.");
3162 case TokenNameStringLiteral :
3165 case TokenNameStringConstant :
3168 case TokenNameStringInterpolated :
3171 case TokenNameDoubleLiteral :
3174 case TokenNameIntegerLiteral :
3178 throwSyntaxError("Constant expected.");