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();
155 * ClassDeclaration Constructor.
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(String message, int charStart, int charEnd, int errorLevel) throws CoreException {
189 setMarker(fileToParse, message, charStart, charEnd, errorLevel);
193 * This method will throw the SyntaxError.
194 * It will add the good lines and columns to the Error
195 * @param error the error message
196 * @throws SyntaxError the error raised
198 private void throwSyntaxError(String error) {
200 // if (str.length() < chIndx) {
203 // // read until end-of-line
205 // while (str.length() > eol) {
206 // ch = str.charAt(eol++);
212 // throw new SyntaxError(
214 // chIndx - columnCount + 1,
215 // str.substring(columnCount, eol),
217 throw new SyntaxError(1, 1, "", error);
221 * This method will throw the SyntaxError.
222 * It will add the good lines and columns to the Error
223 * @param error the error message
224 * @throws SyntaxError the error raised
226 private void throwSyntaxError(String error, int startRow) {
227 throw new SyntaxError(startRow, 0, " ", error);
231 * Method Declaration.
235 // private void getChar() {
236 // if (str.length() > chIndx) {
237 // ch = str.charAt(chIndx++);
242 // chIndx = str.length() + 1;
244 // // token = TokenNameEOF;
249 * gets the next token from input
251 private void getNextToken() throws CoreException {
253 token = scanner.getNextToken();
255 int currentEndPosition = scanner.getCurrentTokenEndPosition();
256 int currentStartPosition = scanner.getCurrentTokenStartPosition();
258 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
259 System.out.println(scanner.toStringAction(token));
261 } catch (InvalidInputException e) {
262 token = TokenNameERROR;
266 // boolean phpFound = false;
273 // while (str.length() > chIndx) {
274 // token = TokenNameERROR;
275 // ch = str.charAt(chIndx++);
281 // ch2 = str.charAt(chIndx++);
283 // ch2 = str.charAt(chIndx++);
284 // if (Character.isWhitespace(ch2)) {
289 // } else if (ch2 == 'p' || ch2 == 'P') {
290 // ch2 = str.charAt(chIndx++);
291 // if (ch2 == 'h' || ch2 == 'H') {
292 // ch2 = str.charAt(chIndx++);
293 // if (ch2 == 'p' || ch2 == 'P') {
311 // while (str.length() > chIndx) {
312 // ch = str.charAt(chIndx++);
313 // token = TokenNameERROR;
316 // columnCount = chIndx;
317 // continue; // while loop
319 // if (str.length() == chIndx) {
322 // if (!Character.isWhitespace(ch)) {
324 // if (str.length() > chIndx) {
325 // if (str.charAt(chIndx) == '{') {
327 // token = TokenNameDOLLAROPEN;
334 // if ((ch >= 'a' && ch <= 'z')
335 // || (ch >= 'A' && ch <= 'Z')
341 // if (ch >= '0' && ch <= '9') {
346 // if (str.length() > chIndx) {
347 // if (str.charAt(chIndx) == '/') {
350 // // read comment until end of line:
351 // while ((str.length() > chIndx)
352 // && (ch != '\n')) {
353 // ch = str.charAt(chIndx++);
355 // ch2 = str.charAt(chIndx);
358 // token = TokenNameHTML;
369 // } else if (str.charAt(chIndx) == '*') {
371 // // multi line comment:
372 // while (str.length() > chIndx) {
373 // if (str.charAt(chIndx) == '*'
374 // && (str.length() > (chIndx + 1))
375 // && str.charAt(chIndx + 1) == '/') {
379 // ch = str.charAt(chIndx++);
382 // columnCount = chIndx;
388 // } else if (ch == '#') {
389 // // read comment until end of line:
390 // while ((str.length() > chIndx) && (ch != '\n')) {
391 // ch = str.charAt(chIndx++);
393 // ch2 = str.charAt(chIndx);
396 // token = TokenNameHTML;
407 // } else if (ch == '"') {
410 // TokenNameStringInterpolated,
411 // "Open string character '\"' at end of file.");
413 // } else if (ch == '\'') {
416 // TokenNameStringConstant,
417 // "Open string character \"'\" at end of file.");
419 // } else if (ch == '`') {
422 // TokenNameStringConstant,
423 // "Open string character \"`\" at end of file.");
425 // "Other string delimiters prefered (found \"`\").",
434 // token = TokenNameLPAREN;
438 // token = TokenNameRPAREN;
442 // token = TokenNameLBRACE;
446 // token = TokenNameRBRACE;
450 // token = TokenNameLBRACKET;
454 // token = TokenNameRBRACKET;
458 // token = TokenNameCOMMA;
462 // token = TokenNameQUESTION;
463 // if (str.length() > chIndx) {
464 // if (str.charAt(chIndx) == '>') {
466 // token = TokenNameHTML;
476 // token = TokenNameAT;
479 // token = TokenNameTWIDDLE;
480 // if (str.length() > chIndx) {
481 // if (str.charAt(chIndx) == '=') {
483 // token = TokenNameTWIDDLE_EQUAL;
490 // token = TokenNameDOT;
491 // if (str.length() > chIndx) {
492 // if (str.charAt(chIndx) == '=') {
494 // token = TokenNameDOT_EQUAL;
502 // token = TokenNameStringLiteral;
506 // token = TokenNameREMAINDER;
507 // if (str.length() > chIndx) {
508 // if (str.charAt(chIndx) == '=') {
510 // token = TokenNameREMAINDER_EQUAL;
517 // token = TokenNameSEMICOLON;
521 // token = TokenNameXOR;
522 // if (str.length() > chIndx) {
523 // if (str.charAt(chIndx) == '=') {
525 // token = TokenNameXOR_EQUAL;
532 // token = TokenNameDIVIDE;
534 // if (str.length() > chIndx) {
535 // if (str.charAt(chIndx) == '=') {
537 // token = TokenNameDIVIDE_EQUAL;
545 // token = TokenNameMULTIPLY;
546 // if (str.length() > chIndx) {
547 // if (str.charAt(chIndx) == '*') {
549 // token = TokenNameXOR;
553 // if (str.charAt(chIndx) == '=') {
555 // token = TokenNameMULTIPLY_EQUAL;
563 // token = TokenNamePLUS;
564 // if (str.length() > chIndx) {
565 // if (str.charAt(chIndx) == '+') {
567 // token = TokenNamePLUS_PLUS;
571 // if (str.charAt(chIndx) == '=') {
573 // token = TokenNamePLUS_EQUAL;
580 // token = TokenNameMINUS;
581 // if (str.length() > chIndx) {
582 // if (str.charAt(chIndx) == '-') {
584 // token = TokenNameMINUS_MINUS;
588 // if (str.charAt(chIndx) == '=') {
590 // token = TokenNameMINUS_EQUAL;
594 // if (str.charAt(chIndx) == '>') {
596 // token = TokenNameMINUS_GREATER;
604 // token = TokenNameEQUAL;
606 // if (str.length() > chIndx) {
607 // ch = str.charAt(chIndx);
611 // token = TokenNameEQUAL_EQUAL;
612 // if (str.length() > chIndx) {
613 // ch = str.charAt(chIndx);
618 // TokenNameEQUAL_EQUAL_EQUAL;
625 // token = TokenNameEQUAL_GREATER;
633 // token = TokenNameNOT;
635 // if (str.length() > chIndx) {
636 // if (str.charAt(chIndx) == '=') {
638 // token = TokenNameNOT_EQUAL;
639 // if (str.length() > chIndx) {
640 // ch = str.charAt(chIndx);
645 // TokenNameNOT_EQUAL_EQUAL;
654 // token = TokenNameGREATER;
656 // if (str.length() > chIndx) {
657 // if (str.charAt(chIndx) == '=') {
659 // token = TokenNameGREATER_EQUAL;
662 // if (str.charAt(chIndx) == '>') {
664 // token = TokenNameRIGHT_SHIFT;
665 // if (str.length() > chIndx) {
666 // if (str.charAt(chIndx) == '=') {
669 // TokenNameRIGHT_SHIFT_EQUAL;
679 // token = TokenNameLESS;
681 // if (str.length() > chIndx) {
682 // if (str.charAt(chIndx) == '=') {
684 // token = TokenNameLESS_EQUAL;
688 // if (str.charAt(chIndx) == '<') {
690 // token = TokenNameLEFT_SHIFT;
691 // if (str.charAt(chIndx) == '<') {
693 // int startRow = rowCount;
694 // if (str.length() > chIndx) {
696 // ch = str.charAt(++chIndx);
697 // if ((ch >= 'a' && ch <= 'z')
698 // || (ch >= 'A' && ch <= 'Z')
703 // TokenNameStringConstant;
704 // while (str.length()
720 // .equals(identifier)) {
732 // "Open heredoc syntax after operator '<<<'.",
734 // } else if (str.charAt(chIndx) == '=') {
736 // token = TokenNameLEFT_SHIFT_EQUAL;
746 // token = TokenNameOR;
748 // if (str.length() > chIndx) {
749 // if (str.charAt(chIndx) == '|') {
751 // token = TokenNameOR_OR;
754 // if (str.charAt(chIndx) == '=') {
756 // token = TokenNameOR_EQUAL;
763 // token = TokenNameAND;
764 // if (str.length() > chIndx) {
765 // if (str.charAt(chIndx) == '&') {
767 // token = TokenNameAND_AND;
770 // if (str.charAt(chIndx) == '=') {
772 // token = TokenNameAND_EQUAL;
780 // token = TokenNameCOLON;
781 // if (str.length() > chIndx) {
782 // if (str.charAt(chIndx) == ':') {
784 // token = TokenNameCOLON_COLON;
789 // // token = TokenNameHASH;
793 // // token = TokenNameAT;
798 // "unexpected character: '" + ch + "'");
801 // if (token == TokenNameERROR) {
802 // throwSyntaxError("token not found");
809 // } catch (StringIndexOutOfBoundsException e) {
810 // // catched from charAt
813 // chIndx = str.length() + 1;
815 // token = TokenNameEOF;
818 // // if (phpList != null) {
819 // // if (currentPHPString < phpList.size()) {
820 // // token = TokenNameUNDEFINED;
821 // // temp = (PHPString) phpList.get(currentPHPString++);
822 // // this.str = temp.getPHPString();
823 // // this.token = TokenNameEOF;
824 // // this.chIndx = 0;
825 // // this.rowCount = temp.getLineNumber();
826 // // this.columnCount = 0;
827 // // getNextToken();
830 // // token = TokenNameUNDEFINED;
837 // * Get an identifier.
839 // private void getIdentifier() {
840 // // StringBuffer ident = new StringBuffer();
841 // int startPosition = chIndx - 1;
842 // // ident.append(ch);
845 // // attention recursive call:
847 // token = TokenNameVariable;
850 // token = TokenNameIdentifier;
855 // //this will read the buffer until the next character is a forbidden character for identifier
856 // while ((ch >= 'a' && ch <= 'z')
857 // || (ch >= 'A' && ch <= 'Z')
858 // || (ch >= '0' && ch <= '9')
860 // // ident.append(ch);
863 // int endPosition = chIndx--;
864 // int length = (--endPosition) - startPosition;
866 // identifier = str.substring(startPosition, endPosition);
867 // // System.out.println(identifier);
869 // // determine if this identitfer is a keyword
870 // // @todo improve this in future version
871 // Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
873 // token = i.intValue();
879 * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
880 * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
881 * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
882 * value {@link Parser#TokenNameINT_NUMBER}
884 // private void getNumber() {
885 // StringBuffer inum = new StringBuffer();
887 // int numFormat = 10;
889 // // save first digit
890 // char firstCh = ch;
894 // // determine number conversions:
895 // if (firstCh == '0') {
924 // if (numFormat == 16) {
925 // while ((ch >= '0' && ch <= '9')
926 // || (ch >= 'a' && ch <= 'f')
927 // || (ch >= 'A' && ch <= 'F')) {
932 // while ((ch >= '0' && ch <= '9')
936 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
937 // if (ch == '.' && dFlag != ' ') {
940 // if ((dFlag == 'E') || (dFlag == 'e')) {
946 // if ((ch == '-') || (ch == '+')) {
959 // if (dFlag != ' ') {
960 // doubleNumber = new Double(inum.toString());
961 // token = TokenNameDoubleLiteral;
964 // longNumber = Long.valueOf(inum.toString(), numFormat);
965 // token = TokenNameIntegerLiteral;
969 // } catch (Throwable e) {
970 // throwSyntaxError("Number format error: " + inum.toString());
976 // * @param openChar the opening char ('\'', '"', '`')
977 // * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
978 // * @param errorMsg the error message in case of parse error in the string
980 // private void getString(
981 // final char openChar,
982 // final int typeString,
983 // final String errorMsg) {
984 // StringBuffer sBuffer = new StringBuffer();
985 // boolean openString = true;
986 // int startRow = rowCount;
987 // while (str.length() > chIndx) {
988 // ch = str.charAt(chIndx++);
990 // sBuffer.append(ch);
991 // if (str.length() > chIndx) {
992 // ch = str.charAt(chIndx++);
993 // sBuffer.append(ch);
995 // } else if (ch == openChar) {
996 // openString = false;
998 // } else if (ch == '\n') {
1000 // columnCount = chIndx;
1002 // sBuffer.append(ch);
1005 // if (openString) {
1006 // if (typeString == TokenNameStringConstant) {
1007 // throwSyntaxError(errorMsg, startRow);
1009 // throwSyntaxError(errorMsg);
1012 // token = typeString;
1013 // stringValue = sBuffer.toString();
1016 // public void htmlParserTester(String input) {
1017 // int lineNumber = 1;
1018 // int startLineNumber = 1;
1019 // int startIndex = 0;
1022 // boolean phpMode = false;
1023 // boolean phpFound = false;
1025 // phpList = new ArrayList();
1026 // currentPHPString = 0;
1030 // while (i < input.length()) {
1031 // ch = input.charAt(i++);
1032 // if (ch == '\n') {
1035 // if ((!phpMode) && ch == '<') {
1036 // ch2 = input.charAt(i++);
1037 // if (ch2 == '?') {
1038 // ch2 = input.charAt(i++);
1039 // if (Character.isWhitespace(ch2)) {
1044 // startLineNumber = lineNumber;
1046 // } else if (ch2 == 'p') {
1047 // ch2 = input.charAt(i++);
1048 // if (ch2 == 'h') {
1049 // ch2 = input.charAt(i++);
1050 // if (ch2 == 'p') {
1054 // startLineNumber = lineNumber;
1060 // } else if (ch2 == 'P') {
1061 // ch2 = input.charAt(i++);
1062 // if (ch2 == 'H') {
1063 // ch2 = input.charAt(i++);
1064 // if (ch2 == 'P') {
1068 // startLineNumber = lineNumber;
1081 // if (ch == '/' && i < input.length()) {
1082 // ch2 = input.charAt(i++);
1083 // if (ch2 == '/') {
1084 // while (i < input.length()) {
1085 // ch = input.charAt(i++);
1086 // if (ch == '?' && i < input.length()) {
1087 // ch2 = input.charAt(i++);
1088 // if (ch2 == '>') {
1096 // startLineNumber));
1100 // } else if (ch == '\n') {
1106 // } else if (ch2 == '*') {
1107 // // multi-line comment
1108 // while (i < input.length()) {
1109 // ch = input.charAt(i++);
1110 // if (ch == '\n') {
1112 // } else if (ch == '*' && i < input.length()) {
1113 // ch2 = input.charAt(i++);
1114 // if (ch2 == '/') {
1124 // } else if (ch == '#') {
1125 // while (i < input.length()) {
1126 // ch = input.charAt(i++);
1127 // if (ch == '?' && i < input.length()) {
1128 // ch2 = input.charAt(i++);
1129 // if (ch2 == '>') {
1134 // input.substring(startIndex, i - 2),
1135 // startLineNumber));
1139 // } else if (ch == '\n') {
1145 // } else if (ch == '"') {
1147 // while (i < input.length()) {
1148 // ch = input.charAt(i++);
1149 // if (ch == '\n') {
1152 // ch == '\\' && i < input.length()) { // escape
1154 // } else if (ch == '"') {
1159 // } else if (ch == '\'') {
1161 // while (i < input.length()) {
1162 // ch = input.charAt(i++);
1163 // if (ch == '\n') {
1166 // ch == '\\' && i < input.length()) { // escape
1168 // } else if (ch == '\'') {
1175 // if (ch == '?' && i < input.length()) {
1176 // ch2 = input.charAt(i++);
1177 // if (ch2 == '>') {
1182 // input.substring(startIndex, i - 2),
1183 // startLineNumber));
1193 // "No PHP source code found.",
1199 // "Open PHP tag at end of file.",
1204 // input.substring(startIndex, i - 2),
1205 // startLineNumber));
1207 // // for (int j=0;j<phpList.size();j++) {
1208 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
1209 // // int startIndx = temp.length()-10;
1210 // // if (startIndx<0) {
1211 // // startIndx = 0;
1213 // // System.out.println(temp.substring(startIndx)+"?>");
1215 // phpParserTester(null, 1);
1216 // // PHPString temp;
1217 // // for(int j=0;j<phpList.size();j++) {
1218 // // temp = (PHPString) phpList.get(j);
1219 // // parser.start(temp.getPHPString(), temp.getLineNumber());
1222 // } catch (CoreException e) {
1226 public void phpParserTester(String s, int rowCount) throws CoreException {
1229 if (phpList.size() != 0) {
1230 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
1233 this.token = TokenNameEOF;
1235 // this.rowCount = rowCount;
1236 // this.columnCount = 0;
1237 this.phpEnd = false;
1238 this.phpMode = true;
1239 scanner.setSource(s.toCharArray());
1240 scanner.setPHPMode(true);
1244 if (token != TokenNameEOF && token != TokenNameERROR) {
1247 if (token != TokenNameEOF) {
1248 if (token == TokenNameERROR) {
1249 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
1251 if (token == TokenNameRPAREN) {
1252 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1254 if (token == TokenNameRBRACE) {
1255 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1257 if (token == TokenNameRBRACKET) {
1258 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1261 if (token == TokenNameLPAREN) {
1262 throwSyntaxError("Read character '('; end-of-file not reached.");
1264 if (token == TokenNameLBRACE) {
1265 throwSyntaxError("Read character '{'; end-of-file not reached.");
1267 if (token == TokenNameLBRACKET) {
1268 throwSyntaxError("Read character '['; end-of-file not reached.");
1271 throwSyntaxError("End-of-file not reached.");
1274 } catch (SyntaxError err) {
1278 // setMarker(err.getMessage(), err.getLine(), ERROR);
1279 setMarker(err.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
1281 // if an error occured,
1282 // try to find keywords 'class' or 'function'
1283 // to parse the rest of the string
1284 while (token != TokenNameEOF && token != TokenNameERROR) {
1285 if (token == TokenNameclass || token == TokenNamefunction) {
1290 if (token == TokenNameEOF || token == TokenNameERROR) {
1299 * Parses a string with php tags
1300 * i.e. '<body> <?php phpinfo() ?> </body>'
1302 public void parse(String s) throws CoreException {
1304 this.token = TokenNameEOF;
1306 // this.rowCount = 1;
1307 // this.columnCount = 0;
1308 this.phpEnd = false;
1309 this.phpMode = false;
1310 /* scanner initialization */
1311 scanner.setSource(s.toCharArray());
1312 scanner.setPHPMode(false);
1316 if (token != TokenNameEOF && token != TokenNameERROR) {
1319 if (token != TokenNameEOF) {
1320 if (token == TokenNameERROR) {
1321 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
1323 if (token == TokenNameRPAREN) {
1324 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1326 if (token == TokenNameRBRACE) {
1327 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1329 if (token == TokenNameRBRACKET) {
1330 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1333 if (token == TokenNameLPAREN) {
1334 throwSyntaxError("Read character '('; end-of-file not reached.");
1336 if (token == TokenNameLBRACE) {
1337 throwSyntaxError("Read character '{'; end-of-file not reached.");
1339 if (token == TokenNameLBRACKET) {
1340 throwSyntaxError("Read character '['; end-of-file not reached.");
1343 throwSyntaxError("End-of-file not reached.");
1346 } catch (SyntaxError sytaxErr1) {
1347 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
1348 setMarker(sytaxErr1.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
1350 // if an error occured,
1351 // try to find keywords 'class' or 'function'
1352 // to parse the rest of the string
1353 while (token != TokenNameEOF && token != TokenNameERROR) {
1354 if (token == TokenNameclass || token == TokenNamefunction) {
1359 if (token == TokenNameEOF || token == TokenNameERROR) {
1362 } catch (SyntaxError sytaxErr2) {
1363 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
1364 setMarker(sytaxErr2.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
1372 public PHPOutlineInfo parseInfo(Object parent, String s) {
1373 PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
1374 // Stack stack = new Stack();
1375 // stack.push(outlineInfo.getDeclarations());
1378 this.token = TokenNameEOF;
1380 // this.rowCount = 1;
1381 // this.columnCount = 0;
1382 this.phpEnd = false;
1383 this.phpMode = false;
1384 scanner.setSource(s.toCharArray());
1385 scanner.setPHPMode(false);
1389 parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
1390 } catch (CoreException e) {
1395 private void parseDeclarations(PHPOutlineInfo outlineInfo, OutlineableWithChildren current, boolean goBack) {
1397 // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
1398 PHPSegmentWithChildren temp;
1401 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
1403 while (token != TokenNameEOF && token != TokenNameERROR) {
1404 if (token == TokenNameVariable) {
1405 ident = scanner.getCurrentIdentifierSource();
1406 outlineInfo.addVariable(new String(ident));
1408 } else if (token == TokenNamevar) {
1410 if (token == TokenNameVariable && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
1411 ident = scanner.getCurrentIdentifierSource();
1412 //substring(1) added because PHPVarDeclaration doesn't need the $ anymore
1413 String variableName = new String(ident).substring(1);
1414 outlineInfo.addVariable(variableName);
1416 if (token != TokenNameSEMICOLON) {
1419 ident = scanner.getCurrentTokenSource();
1420 if (token > TokenNameKEYWORD) {
1421 current.add(new PHPVarDeclaration(current, variableName,
1422 // chIndx - ident.length,
1423 scanner.getCurrentTokenStartPosition(), new String(ident)));
1426 case TokenNameVariable :
1427 current.add(new PHPVarDeclaration(current, variableName,
1428 // chIndx - ident.length,
1429 scanner.getCurrentTokenStartPosition(), new String(ident)));
1431 case TokenNameIdentifier :
1432 current.add(new PHPVarDeclaration(current, variableName,
1433 // chIndx - ident.length,
1434 scanner.getCurrentTokenStartPosition(), new String(ident)));
1436 case TokenNameDoubleLiteral :
1437 current.add(new PHPVarDeclaration(current, variableName + doubleNumber,
1438 // chIndx - ident.length,
1439 scanner.getCurrentTokenStartPosition(), new String(ident)));
1441 case TokenNameIntegerLiteral :
1442 current.add(new PHPVarDeclaration(current, variableName,
1443 // chIndx - ident.length,
1444 scanner.getCurrentTokenStartPosition(), new String(ident)));
1446 case TokenNameStringInterpolated :
1447 case TokenNameStringLiteral :
1448 current.add(new PHPVarDeclaration(current, variableName,
1449 // chIndx - ident.length,
1450 scanner.getCurrentTokenStartPosition(), new String(ident)));
1452 case TokenNameStringConstant :
1453 current.add(new PHPVarDeclaration(current, variableName,
1454 // chIndx - ident.length,
1455 scanner.getCurrentTokenStartPosition(), new String(ident)));
1458 current.add(new PHPVarDeclaration(current, variableName,
1459 // chIndx - ident.length
1460 scanner.getCurrentTokenStartPosition()));
1466 ident = scanner.getCurrentIdentifierSource();
1468 current.add(new PHPVarDeclaration(current, variableName,
1469 // chIndx - ident.length
1470 scanner.getCurrentTokenStartPosition()));
1473 } else if (token == TokenNamefunction) {
1475 if (token == TokenNameAND) {
1478 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
1479 ident = scanner.getCurrentIdentifierSource();
1480 outlineInfo.addVariable(new String(ident));
1481 temp = new PHPFunctionDeclaration(current, new String(ident),
1482 // chIndx - ident.length
1483 scanner.getCurrentTokenStartPosition());
1486 parseDeclarations(outlineInfo, temp, true);
1488 } else if (token == TokenNameclass) {
1490 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
1491 ident = scanner.getCurrentIdentifierSource();
1492 outlineInfo.addVariable(new String(ident));
1493 temp = new PHPClassDeclaration(current, new String(ident),
1494 // chIndx - ident.len
1495 scanner.getCurrentTokenStartPosition());
1497 // stack.push(temp);
1500 //skip tokens for classname, extends and others until we have the opening '{'
1501 while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) {
1504 parseDeclarations(outlineInfo, temp, true);
1507 } else if ((token == TokenNameLBRACE) || (token == TokenNameDOLLAR_LBRACE)) {
1510 } else if (token == TokenNameRBRACE) {
1513 if (counter == 0 && goBack) {
1517 token == TokenNamerequire
1518 || token == TokenNamerequire_once
1519 || token == TokenNameinclude
1520 || token == TokenNameinclude_once) {
1521 ident = scanner.getCurrentTokenSource();
1524 int startPosition = scanner.getCurrentTokenStartPosition();
1526 char[] expr = scanner.getCurrentTokenSource(startPosition);
1527 outlineInfo.addVariable(new String(ident));
1528 current.add(new PHPReqIncDeclaration(current, new String(ident),
1529 // chIndx - ident.length,
1530 startPosition, new String(expr)));
1536 } catch (CoreException e) {
1537 } catch (SyntaxError sytaxErr) {
1539 // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
1540 setMarker(sytaxErr.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
1541 } catch (CoreException e) {
1546 private void statementList() throws CoreException {
1549 if ((token == TokenNameRBRACE)
1550 || (token == TokenNamecase)
1551 || (token == TokenNamedefault)
1552 || (token == TokenNameelseif)
1553 || (token == TokenNameendif)
1554 || (token == TokenNameendfor)
1555 || (token == TokenNameendforeach)
1556 || (token == TokenNameendwhile)
1557 || (token == TokenNameendswitch)
1558 || (token == TokenNameEOF)
1559 || (token == TokenNameERROR)) {
1565 private void compoundStatement() throws CoreException {
1566 // '{' [statement-list] '}'
1567 if (token == TokenNameLBRACE) {
1570 throwSyntaxError("'{' expected in compound-statement.");
1572 if (token != TokenNameRBRACE) {
1575 if (token == TokenNameRBRACE) {
1578 throwSyntaxError("'}' expected in compound-statement.");
1582 private void statement() throws CoreException {
1583 // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
1584 // char[] ident = scanner.getCurrentIdentifierSource();
1585 // String keyword = new String(ident);
1586 if (token == TokenNameinclude || token == TokenNameinclude_once) {
1589 if (token == TokenNameSEMICOLON) {
1592 if (token != TokenNameStopPHP) {
1593 throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1598 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1602 if (token == TokenNameSEMICOLON) {
1605 if (token != TokenNameStopPHP) {
1606 throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1611 } else if (token == TokenNameif) {
1613 if (token == TokenNameLPAREN) {
1616 throwSyntaxError("'(' expected after 'if' keyword.");
1619 if (token == TokenNameRPAREN) {
1622 throwSyntaxError("')' expected after 'if' condition.");
1627 } else if (token == TokenNameswitch) {
1629 if (token == TokenNameLPAREN) {
1632 throwSyntaxError("'(' expected after 'switch' keyword.");
1635 if (token == TokenNameRPAREN) {
1638 throwSyntaxError("')' expected after 'switch' condition.");
1642 } else if (token == TokenNamefor) {
1644 if (token == TokenNameLPAREN) {
1647 throwSyntaxError("'(' expected after 'for' keyword.");
1649 if (token == TokenNameSEMICOLON) {
1653 if (token == TokenNameSEMICOLON) {
1656 throwSyntaxError("';' expected after 'for'.");
1659 if (token == TokenNameSEMICOLON) {
1663 if (token == TokenNameSEMICOLON) {
1666 throwSyntaxError("';' expected after 'for'.");
1669 if (token == TokenNameRPAREN) {
1673 if (token == TokenNameRPAREN) {
1676 throwSyntaxError("')' expected after 'for'.");
1681 } else if (token == TokenNamewhile) {
1683 if (token == TokenNameLPAREN) {
1686 throwSyntaxError("'(' expected after 'while' keyword.");
1689 if (token == TokenNameRPAREN) {
1692 throwSyntaxError("')' expected after 'while' condition.");
1696 } else if (token == TokenNamedo) {
1698 if (token == TokenNameLBRACE) {
1701 throwSyntaxError("'{' expected after 'do' keyword.");
1703 if (token != TokenNameRBRACE) {
1706 if (token == TokenNameRBRACE) {
1709 throwSyntaxError("'}' expected after 'do' keyword.");
1711 if (token == TokenNamewhile) {
1713 if (token == TokenNameLPAREN) {
1716 throwSyntaxError("'(' expected after 'while' keyword.");
1719 if (token == TokenNameRPAREN) {
1722 throwSyntaxError("')' expected after 'while' condition.");
1725 throwSyntaxError("'while' expected after 'do' keyword.");
1727 if (token == TokenNameSEMICOLON) {
1730 if (token != TokenNameStopPHP) {
1731 throwSyntaxError("';' expected after do-while statement.");
1736 } else if (token == TokenNameforeach) {
1738 if (token == TokenNameLPAREN) {
1741 throwSyntaxError("'(' expected after 'foreach' keyword.");
1744 if (token == TokenNameas) {
1747 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1750 if (token == TokenNameEQUAL_GREATER) {
1754 if (token == TokenNameRPAREN) {
1757 throwSyntaxError("')' expected after 'foreach' expression.");
1762 } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
1764 if (token != TokenNameSEMICOLON) {
1767 if (token == TokenNameSEMICOLON) {
1770 if (token != TokenNameStopPHP) {
1771 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1777 } else if (token == TokenNameecho) {
1780 if (token == TokenNameSEMICOLON) {
1783 if (token != TokenNameStopPHP) {
1784 throwSyntaxError("';' expected after 'echo' statement.");
1789 // } else if (token == TokenNameprint) {
1792 // if (token == TokenNameSEMICOLON) {
1795 // if (token != TokenNameStopPHP) {
1796 // throwSyntaxError("';' expected after 'print' statement.");
1802 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1805 if (token == TokenNameSEMICOLON) {
1808 if (token != TokenNameStopPHP) {
1809 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1815 // } else if (token == TokenNameunset) {
1817 // if (token == TokenNameARGOPEN) {
1820 // throwSyntaxError("'(' expected after 'unset' keyword.");
1823 // if (token == TokenNameARGCLOSE) {
1826 // throwSyntaxError("')' expected after 'unset' statement.");
1828 // if (token == TokenNameSEMICOLON) {
1831 // if (token != TokenNameStopPHP) {
1832 // throwSyntaxError("';' expected after 'unset' statement.");
1838 // } else if (token == TokenNameexit || token == TokenNamedie) {
1840 // if (token != TokenNameSEMICOLON) {
1843 // if (token == TokenNameSEMICOLON) {
1846 // if (token != TokenNameStopPHP) {
1847 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1853 } else if (token == TokenNamedefine) {
1855 if (token == TokenNameLPAREN) {
1858 throwSyntaxError("'(' expected after 'define' keyword.");
1861 if (token == TokenNameCOMMA) {
1864 throwSyntaxError("',' expected after first 'define' constant.");
1867 if (token == TokenNameCOMMA) {
1871 if (token == TokenNameRPAREN) {
1874 throwSyntaxError("')' expected after 'define' statement.");
1876 if (token == TokenNameSEMICOLON) {
1879 if (token != TokenNameStopPHP) {
1880 throwSyntaxError("';' expected after 'define' statement.");
1885 } else if (token == TokenNamefunction) {
1887 functionDefinition();
1889 } else if (token == TokenNameclass) {
1895 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1896 } else if (token == TokenNameLBRACE) {
1897 // compoundStatement
1899 if (token != TokenNameRBRACE) {
1902 if (token == TokenNameRBRACE) {
1906 throwSyntaxError("'}' expected.");
1909 if (token != TokenNameSEMICOLON) {
1912 if (token == TokenNameSEMICOLON) {
1916 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1917 throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
1924 private void classDeclarator() throws CoreException {
1926 //identifier 'extends' identifier
1927 if (token == TokenNameIdentifier) {
1929 if (token == TokenNameextends) {
1931 if (token == TokenNameIdentifier) {
1934 throwSyntaxError("ClassDeclaration name expected after keyword 'extends'.");
1938 if (token > TokenNameKEYWORD) {
1939 throwSyntaxError("Don't use keyword for class declaration [" + token + "].");
1941 throwSyntaxError("ClassDeclaration name expected after keyword 'class'.");
1945 private void classBody() throws CoreException {
1946 //'{' [class-element-list] '}'
1947 if (token == TokenNameLBRACE) {
1949 if (token != TokenNameRBRACE) {
1952 if (token == TokenNameRBRACE) {
1955 throwSyntaxError("'}' expected at end of class body.");
1958 throwSyntaxError("'{' expected at start of class body.");
1962 private void classElementList() throws CoreException {
1965 } while (token == TokenNamefunction || token == TokenNamevar);
1968 private void classElement() throws CoreException {
1970 //function-definition
1971 if (token == TokenNamefunction) {
1973 functionDefinition();
1974 } else if (token == TokenNamevar) {
1978 throwSyntaxError("'function' or 'var' expected.");
1982 private void classProperty() throws CoreException {
1983 //'var' variable ';'
1984 //'var' variable '=' constant ';'
1986 if (token == TokenNameVariable) {
1988 if (token == TokenNameEQUAL) {
1993 throwSyntaxError("Variable expected after keyword 'var'.");
1995 if (token != TokenNameCOMMA) {
2000 if (token == TokenNameSEMICOLON) {
2003 throwSyntaxError("';' expected after variable declaration.");
2007 private void functionDefinition() throws CoreException {
2008 functionDeclarator();
2009 compoundStatement();
2012 private void functionDeclarator() throws CoreException {
2013 //identifier '(' [parameter-list] ')'
2014 if (token == TokenNameAND) {
2017 if (token == TokenNameIdentifier) {
2019 if (token == TokenNameLPAREN) {
2022 throwSyntaxError("'(' expected in function declaration.");
2024 if (token != TokenNameRPAREN) {
2027 if (token != TokenNameRPAREN) {
2028 throwSyntaxError("')' expected in function declaration.");
2033 if (token > TokenNameKEYWORD) {
2034 throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
2036 throwSyntaxError("Function name expected after keyword 'function'.");
2040 private void parameterList() throws CoreException {
2041 //parameter-declaration
2042 //parameter-list ',' parameter-declaration
2044 parameterDeclaration();
2045 if (token != TokenNameCOMMA) {
2052 private void parameterDeclaration() throws CoreException {
2054 //variable-reference
2055 if (token == TokenNameAND) {
2057 if (token == TokenNameVariable) {
2060 throwSyntaxError("Variable expected after reference operator '&'.");
2063 //variable '=' constant
2064 if (token == TokenNameVariable) {
2066 if (token == TokenNameEQUAL) {
2074 private void labeledStatementList() throws CoreException {
2075 if (token != TokenNamecase && token != TokenNamedefault) {
2076 throwSyntaxError("'case' or 'default' expected.");
2079 if (token == TokenNamecase) {
2082 if (token == TokenNameCOLON) {
2084 if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
2088 } else if (token == TokenNameSEMICOLON) {
2090 // "':' expected after 'case' keyword (Found token: "
2091 // + scanner.toStringAction(token)
2096 "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")",
2097 scanner.getCurrentTokenStartPosition(),
2098 scanner.getCurrentTokenEndPosition(),
2101 if (token == TokenNamecase) { // empty case statement ?
2106 throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
2108 } else { // TokenNamedefault
2110 if (token == TokenNameCOLON) {
2114 throwSyntaxError("':' character after 'default' expected.");
2117 } while (token == TokenNamecase || token == TokenNamedefault);
2120 // public void labeledStatement() {
2121 // if (token == TokenNamecase) {
2124 // if (token == TokenNameDDOT) {
2128 // throwSyntaxError("':' character after 'case' constant expected.");
2131 // } else if (token == TokenNamedefault) {
2133 // if (token == TokenNameDDOT) {
2137 // throwSyntaxError("':' character after 'default' expected.");
2143 // public void expressionStatement() {
2146 // private void inclusionStatement() {
2149 // public void compoundStatement() {
2152 // public void selectionStatement() {
2155 // public void iterationStatement() {
2158 // public void jumpStatement() {
2161 // public void outputStatement() {
2164 // public void scopeStatement() {
2167 // public void flowStatement() {
2170 // public void definitionStatement() {
2173 private void ifStatement() throws CoreException {
2174 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
2175 if (token == TokenNameCOLON) {
2179 case TokenNameelse :
2181 if (token == TokenNameCOLON) {
2185 if (token == TokenNameif) { //'else if'
2187 elseifStatementList();
2189 throwSyntaxError("':' expected after 'else'.");
2193 case TokenNameelseif :
2195 elseifStatementList();
2199 if (token != TokenNameendif) {
2200 throwSyntaxError("'endif' expected.");
2203 if (token != TokenNameSEMICOLON) {
2204 throwSyntaxError("';' expected after if-statement.");
2208 // statement [else-statement]
2210 if (token == TokenNameelseif) {
2212 if (token == TokenNameLPAREN) {
2215 throwSyntaxError("'(' expected after 'elseif' keyword.");
2218 if (token == TokenNameRPAREN) {
2221 throwSyntaxError("')' expected after 'elseif' condition.");
2224 } else if (token == TokenNameelse) {
2231 private void elseifStatementList() throws CoreException {
2235 case TokenNameelse :
2237 if (token == TokenNameCOLON) {
2242 if (token == TokenNameif) { //'else if'
2245 throwSyntaxError("':' expected after 'else'.");
2249 case TokenNameelseif :
2258 private void elseifStatement() throws CoreException {
2259 if (token == TokenNameLPAREN) {
2262 if (token != TokenNameLPAREN) {
2263 throwSyntaxError("')' expected in else-if-statement.");
2266 if (token != TokenNameCOLON) {
2267 throwSyntaxError("':' expected in else-if-statement.");
2274 private void switchStatement() throws CoreException {
2275 if (token == TokenNameCOLON) {
2276 // ':' [labeled-statement-list] 'endswitch' ';'
2278 labeledStatementList();
2279 if (token != TokenNameendswitch) {
2280 throwSyntaxError("'endswitch' expected.");
2283 if (token != TokenNameSEMICOLON) {
2284 throwSyntaxError("';' expected after switch-statement.");
2288 // '{' [labeled-statement-list] '}'
2289 if (token != TokenNameLBRACE) {
2290 throwSyntaxError("'{' expected in switch statement.");
2293 if (token != TokenNameRBRACE) {
2294 labeledStatementList();
2296 if (token != TokenNameRBRACE) {
2297 throwSyntaxError("'}' expected in switch statement.");
2304 private void forStatement() throws CoreException {
2305 if (token == TokenNameCOLON) {
2308 if (token != TokenNameendfor) {
2309 throwSyntaxError("'endfor' expected.");
2312 if (token != TokenNameSEMICOLON) {
2313 throwSyntaxError("';' expected after for-statement.");
2321 private void whileStatement() throws CoreException {
2322 // ':' statement-list 'endwhile' ';'
2323 if (token == TokenNameCOLON) {
2326 if (token != TokenNameendwhile) {
2327 throwSyntaxError("'endwhile' expected.");
2330 if (token != TokenNameSEMICOLON) {
2331 throwSyntaxError("';' expected after while-statement.");
2339 private void foreachStatement() throws CoreException {
2340 if (token == TokenNameCOLON) {
2343 if (token != TokenNameendforeach) {
2344 throwSyntaxError("'endforeach' expected.");
2347 if (token != TokenNameSEMICOLON) {
2348 throwSyntaxError("';' expected after foreach-statement.");
2356 private void exitStatus() throws CoreException {
2357 if (token == TokenNameLPAREN) {
2360 throwSyntaxError("'(' expected in 'exit-status'.");
2362 if (token != TokenNameRPAREN) {
2365 if (token == TokenNameRPAREN) {
2368 throwSyntaxError("')' expected after 'exit-status'.");
2372 private void expressionList() throws CoreException {
2375 if (token == TokenNameCOMMA) {
2383 private void expression() throws CoreException {
2384 //todo: find a better way to get the expression
2385 // expression = new StringBuffer();
2386 // for (int i = chIndx; i < str.length(); i++) {
2387 // if (str.charAt(i) == ';') {
2390 // expression.append(str.charAt(i));
2393 // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
2396 logicalinclusiveorExpression();
2397 // while (token != TokenNameSEMICOLON) {
2403 private void postfixExpression() throws CoreException {
2406 boolean castFlag = false;
2412 case TokenNamenull :
2415 case TokenNamefalse :
2418 case TokenNametrue :
2421 case TokenNameStringConstant :
2424 case TokenNameHEREDOC :
2425 case TokenNameStringInterpolated :
2426 case TokenNameStringLiteral :
2429 case TokenNameLPAREN :
2431 if (token == TokenNameIdentifier) {
2432 // check if identifier is a type:
2433 // ident = identifier;
2434 ident = scanner.getCurrentIdentifierSource();
2435 String str = new String(ident).toLowerCase();
2436 for (int i = 0; i < PHP_TYPES.length; i++) {
2437 if (PHP_TYPES[i].equals(str)) {
2444 if (token != TokenNameRPAREN) {
2445 throwSyntaxError(") expected after cast-type '" + str + "'.");
2455 if (token != TokenNameRPAREN) {
2456 throwSyntaxError(") expected in postfix-expression.");
2460 case TokenNameDoubleLiteral :
2463 case TokenNameIntegerLiteral :
2466 case TokenNameDOLLAR_LBRACE :
2469 if (token != TokenNameRBRACE) {
2470 throwSyntaxError("'}' expected after indirect variable token '${'.");
2474 case TokenNameVariable :
2475 ident = scanner.getCurrentIdentifierSource();
2477 if (token == TokenNameLBRACE) {
2480 if (token != TokenNameRBRACE) {
2481 throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression.");
2484 } else if (token == TokenNameLPAREN) {
2486 if (token != TokenNameRPAREN) {
2488 if (token != TokenNameRPAREN) {
2489 throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression.");
2495 case TokenNameIdentifier :
2496 ident = scanner.getCurrentIdentifierSource();
2498 if (token == TokenNameLPAREN) {
2500 if (token != TokenNameRPAREN) {
2502 if (token != TokenNameRPAREN) {
2504 "')' expected after identifier '"
2506 + "' in postfix-expression."
2508 + scanner.toStringAction(token)
2515 case TokenNameprint :
2518 // if (token == TokenNameSEMICOLON) {
2521 // if (token != TokenNameStopPHP) {
2522 // throwSyntaxError("';' expected after 'print' statement.");
2527 case TokenNamelist :
2529 if (token == TokenNameLPAREN) {
2531 if (token == TokenNameCOMMA) {
2535 if (token != TokenNameRPAREN) {
2536 throwSyntaxError("')' expected after 'list' keyword.");
2539 // if (token == TokenNameSET) {
2541 // logicalinclusiveorExpression();
2544 throwSyntaxError("'(' expected after 'list' keyword.");
2547 // case TokenNameexit :
2549 // if (token != TokenNameSEMICOLON) {
2552 // if (token == TokenNameSEMICOLON) {
2555 // if (token != TokenNameStopPHP) {
2556 // throwSyntaxError("';' expected after 'exit' expression.");
2561 // case TokenNamedie :
2563 // if (token != TokenNameSEMICOLON) {
2566 // if (token == TokenNameSEMICOLON) {
2569 // if (token != TokenNameStopPHP) {
2570 // throwSyntaxError("';' expected after 'die' expression.");
2575 // case TokenNamearray :
2577 // if (token == TokenNameARGOPEN) {
2579 // if (token == TokenNameCOMMA) {
2582 // expressionList();
2583 // if (token != TokenNameARGCLOSE) {
2584 // throwSyntaxError("')' expected after 'list' keyword.");
2587 // if (token == TokenNameSET) {
2589 // logicalinclusiveorExpression();
2592 // throwSyntaxError("'(' expected after 'list' keyword.");
2596 boolean while_flag = true;
2599 case TokenNameLBRACKET :
2602 if (token != TokenNameRBRACKET) {
2603 throwSyntaxError("] expected in postfix-expression.");
2607 case TokenNameCOLON_COLON : // ::
2608 case TokenNameMINUS_GREATER : // ->
2610 if (token > TokenNameKEYWORD) {
2611 ident = scanner.getCurrentIdentifierSource();
2613 // "Avoid using keyword '"
2614 // + new String(ident)
2615 // + "' as variable name.",
2619 "Avoid using keyword '" + new String(ident) + "' as variable name.",
2620 scanner.getCurrentTokenStartPosition(),
2621 scanner.getCurrentTokenEndPosition(),
2625 case TokenNameVariable :
2626 ident = scanner.getCurrentIdentifierSource();
2628 // if (token == TokenNameARGOPEN) {
2630 // expressionList();
2631 // if (token != TokenNameARGCLOSE) {
2632 // throwSyntaxError(") expected after variable '" + ident + "'.");
2637 case TokenNameIdentifier :
2638 //ident = scanner.getCurrentIdentifierSource();
2641 case TokenNameLBRACE :
2644 if (token != TokenNameRBRACE) {
2645 throwSyntaxError("} expected in postfix-expression.");
2650 throwSyntaxError("Syntax error after '->' token.");
2651 } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
2652 if (token == TokenNameLBRACKET) {
2655 if (token != TokenNameRBRACKET) {
2656 throwSyntaxError("] expected after '->'.");
2660 if (token == TokenNameLPAREN) {
2663 if (token != TokenNameRPAREN) {
2664 throwSyntaxError(") expected after '->'.");
2668 if (token == TokenNameLBRACE) {
2671 if (token != TokenNameRBRACE) {
2672 throwSyntaxError("} expected after '->'.");
2678 case TokenNamePLUS_PLUS :
2681 case TokenNameMINUS_MINUS :
2692 private void unaryExpression() throws CoreException {
2694 case TokenNamePLUS_PLUS :
2698 case TokenNameMINUS_MINUS :
2702 // '@' '&' '*' '+' '-' '~' '!'
2711 case TokenNameMULTIPLY :
2715 case TokenNamePLUS :
2719 case TokenNameMINUS :
2723 case TokenNameTWIDDLE :
2732 postfixExpression();
2736 private void castExpression() throws CoreException {
2737 // if (token == TokenNameARGOPEN) {
2740 // if (token != TokenNameARGCLOSE) {
2741 // throwSyntaxError(") expected after cast-expression.");
2748 // private void typeName() throws CoreException {
2749 // //'string' 'unset' 'array' 'object'
2750 // //'bool' 'boolean'
2751 // //'real' 'double' 'float'
2752 // //'int' 'integer'
2753 // String identifier = "";
2754 // if (token == TokenNameIdentifier) {
2755 // char[] ident = scanner.getCurrentIdentifierSource();
2756 // identifier = new String(ident);
2757 // String str = identifier.toLowerCase();
2759 // for (int i = 0; i < PHP_TYPES.length; i++) {
2760 // if (PHP_TYPES[i].equals(str)) {
2765 // throwSyntaxError(
2766 // "Expected type cast '( <type-name> )'; Got '" + identifier + "'.");
2769 private void assignExpression() throws CoreException {
2771 if (token == TokenNameEQUAL) { // =
2773 logicalinclusiveorExpression();
2774 } else if (token == TokenNameDOT_EQUAL) { // .=
2776 logicalinclusiveorExpression();
2777 } else if (token == TokenNameEQUAL_GREATER) { // =>
2779 logicalinclusiveorExpression();
2780 } else if (token == TokenNamePLUS_EQUAL) { // +=
2782 logicalinclusiveorExpression();
2783 } else if (token == TokenNameMINUS_EQUAL) { // -=
2785 logicalinclusiveorExpression();
2786 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2788 logicalinclusiveorExpression();
2789 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2791 logicalinclusiveorExpression();
2792 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2794 logicalinclusiveorExpression();
2795 } else if (token == TokenNameAND_EQUAL) { // &=
2797 logicalinclusiveorExpression();
2798 } else if (token == TokenNameOR_EQUAL) { // |=
2800 logicalinclusiveorExpression();
2801 } else if (token == TokenNameXOR_EQUAL) { // ^=
2803 logicalinclusiveorExpression();
2804 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2806 logicalinclusiveorExpression();
2807 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2809 logicalinclusiveorExpression();
2810 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2812 logicalinclusiveorExpression();
2816 private void multiplicativeExpression() throws CoreException {
2819 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
2826 private void concatenationExpression() throws CoreException {
2828 multiplicativeExpression();
2829 if (token != TokenNameDOT) {
2836 private void additiveExpression() throws CoreException {
2838 concatenationExpression();
2839 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2846 private void shiftExpression() throws CoreException {
2848 additiveExpression();
2849 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2856 private void relationalExpression() throws CoreException {
2859 if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2866 private void identicalExpression() throws CoreException {
2868 relationalExpression();
2869 if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
2876 private void equalityExpression() throws CoreException {
2878 identicalExpression();
2879 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2886 private void ternaryExpression() throws CoreException {
2887 equalityExpression();
2888 if (token == TokenNameQUESTION) {
2891 if (token == TokenNameCOLON) {
2895 throwSyntaxError("':' expected in ternary operator '? :'.");
2900 private void andExpression() throws CoreException {
2902 ternaryExpression();
2903 if (token != TokenNameAND) {
2910 private void exclusiveorExpression() throws CoreException {
2913 if (token != TokenNameXOR) {
2920 private void inclusiveorExpression() throws CoreException {
2922 exclusiveorExpression();
2923 if (token != TokenNameOR) {
2930 private void booleanandExpression() throws CoreException {
2932 inclusiveorExpression();
2933 if (token != TokenNameAND_AND) {
2940 private void booleanorExpression() throws CoreException {
2942 booleanandExpression();
2943 if (token != TokenNameOR_OR) {
2950 private void logicalandExpression() throws CoreException {
2952 booleanorExpression();
2953 if (token != TokenNameAND) {
2960 private void logicalexclusiveorExpression() throws CoreException {
2962 logicalandExpression();
2963 if (token != TokenNameXOR) {
2970 private void logicalinclusiveorExpression() throws CoreException {
2972 logicalexclusiveorExpression();
2973 if (token != TokenNameOR) {
2980 // public void assignmentExpression() {
2981 // if (token == TokenNameVARIABLE) {
2983 // if (token == TokenNameSET) {
2985 // logicalinclusiveorExpression();
2988 // logicalinclusiveorExpression();
2992 private void variableList() throws CoreException {
2995 if (token == TokenNameCOMMA) {
3003 private void variable() throws CoreException {
3004 if (token == TokenNameDOLLAR_LBRACE) {
3008 if (token != TokenNameRBRACE) {
3009 throwSyntaxError("'}' expected after indirect variable token '${'.");
3013 if (token == TokenNameVariable) {
3015 if (token == TokenNameLBRACKET) {
3018 if (token != TokenNameRBRACKET) {
3019 throwSyntaxError("']' expected in variable-list.");
3022 } else if (token == TokenNameEQUAL) {
3027 throwSyntaxError("$-variable expected in variable-list.");
3033 * It will look for a value (after a '=' for example)
3034 * @throws CoreException
3036 private void constant() throws CoreException {
3039 case TokenNamePLUS :
3042 case TokenNameDoubleLiteral :
3045 case TokenNameIntegerLiteral :
3049 throwSyntaxError("Constant expected after '+' presign.");
3052 case TokenNameMINUS :
3055 case TokenNameDoubleLiteral :
3058 case TokenNameIntegerLiteral :
3062 throwSyntaxError("Constant expected after '-' presign.");
3065 case TokenNamenull :
3068 case TokenNamefalse :
3071 case TokenNametrue :
3074 case TokenNameIdentifier :
3075 // ident = identifier;
3076 char[] ident = scanner.getCurrentIdentifierSource();
3078 if (token == TokenNameLPAREN) {
3080 if (token != TokenNameRPAREN) {
3082 if (token != TokenNameRPAREN) {
3083 throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression.");
3089 case TokenNameStringLiteral :
3092 case TokenNameStringConstant :
3095 case TokenNameStringInterpolated :
3098 case TokenNameDoubleLiteral :
3101 case TokenNameIntegerLiteral :
3105 throwSyntaxError("Constant expected.");