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;
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
17 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
18 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
19 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
20 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
21 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
22 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
23 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
28 import net.sourceforge.phpeclipse.phpeditor.PHPString;
30 import org.eclipse.core.resources.IFile;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.jface.preference.IPreferenceStore;
34 import test.PHPParserSuperclass;
36 public class Parser extends PHPParserSuperclass implements ITerminalSymbols, ParserBasicInformation {
37 //internal data for the automat
38 protected final static int StackIncrement = 255;
39 protected int stateStackTop;
40 protected int[] stack = new int[StackIncrement];
41 public int firstToken; // handle for multiple parsing goals
42 public int lastAct; //handle for multiple parsing goals
43 protected RecoveredElement currentElement;
45 public static boolean VERBOSE_RECOVERY = false;
46 protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
49 public Scanner scanner;
51 private ArrayList phpList;
53 private int currentPHPString;
54 private boolean phpEnd;
56 // private static HashMap keywordMap = null;
64 // row counter for syntax errors:
66 // column counter for syntax errors:
71 // // current identifier
77 private String stringValue;
79 /** Contains the current expression. */
80 // private StringBuffer expression;
82 private boolean phpMode;
84 // final static int TokenNameEOF = 0;
85 // final static int TokenNameERROR = 1;
86 // final static int TokenNameHTML = 2;
88 // final static int TokenNameREMAINDER = 30;
89 // final static int TokenNameNOT = 31;
90 // final static int TokenNameDOT = 32;
91 // final static int TokenNameXOR = 33;
92 // final static int TokenNameDIVIDE = 34;
93 // final static int TokenNameMULTIPLY = 35;
94 // final static int TokenNameMINUS = 36;
95 // final static int TokenNamePLUS = 37;
96 // final static int TokenNameEQUAL_EQUAL = 38;
97 // final static int TokenNameNOT_EQUAL = 39;
98 // final static int TokenNameGREATER = 40;
99 // final static int TokenNameGREATER_EQUAL = 41;
100 // final static int TokenNameLESS = 42;
101 // final static int TokenNameLESS_EQUAL = 43;
102 // final static int TokenNameAND_AND = 44;
103 // final static int TokenNameOR_OR = 45;
104 // // final static int TokenNameHASH = 46;
105 // final static int TokenNameCOLON = 47;
106 // final static int TokenNameDOT_EQUAL = 48;
108 // final static int TokenNameEQUAL = 49;
109 // final static int TokenNameMINUS_GREATER = 50; // ->
110 // final static int TokenNameFOREACH = 51;
111 // final static int TokenNameAND = 52;
112 // //final static int TokenNameDOLLARLISTOPEN = 53;
113 // final static int TokenNameTWIDDLE = 54;
114 // final static int TokenNameTWIDDLE_EQUAL = 55;
115 // final static int TokenNameREMAINDER_EQUAL = 56;
116 // final static int TokenNameXOR_EQUAL = 57;
117 // final static int TokenNameRIGHT_SHIFT_EQUAL = 58;
118 // final static int TokenNameLEFT_SHIFT_EQUAL = 59;
119 // final static int TokenNameAND_EQUAL = 60;
120 // final static int TokenNameOR_EQUAL = 61;
121 // final static int TokenNameQUESTION = 62;
122 // final static int TokenNameCOLON_COLON = 63;
123 // final static int TokenNameAT = 63;
124 // // final static int TokenNameHEREDOC = 64;
126 // final static int TokenNameDOLLAROPEN = 127;
127 // final static int TokenNameLPAREN = 128;
128 // final static int TokenNameRPAREN = 129;
129 // final static int TokenNameLBRACE = 130;
130 // final static int TokenNameRBRACE = 131;
131 // final static int TokenNameLBRACKET = 132;
132 // final static int TokenNameRBRACKET = 133;
133 // final static int TokenNameCOMMA = 134;
135 // final static int TokenNameStringLiteral = 136;
136 // final static int TokenNameIdentifier = 138;
137 // // final static int TokenNameDIGIT = 139;
138 // final static int TokenNameSEMICOLON = 140;
139 // // final static int TokenNameSLOT = 141;
140 // // final static int TokenNameSLOTSEQUENCE = 142;
141 // final static int TokenNameMINUS_MINUS = 144;
142 // final static int TokenNamePLUS_PLUS = 145;
143 // final static int TokenNamePLUS_EQUAL = 146;
144 // final static int TokenNameDIVIDE_EQUAL = 147;
145 // final static int TokenNameMINUS_EQUAL = 148;
146 // final static int TokenNameMULTIPLY_EQUAL = 149;
147 // final static int TokenNameVariable = 150;
148 // final static int TokenNameIntegerLiteral = 151;
149 // final static int TokenNameDoubleLiteral = 152;
150 // final static int TokenNameStringInterpolated = 153;
151 // final static int TokenNameStringConstant = 154;
153 // final static int TokenNameLEFT_SHIFT = 155;
154 // final static int TokenNameRIGHT_SHIFT = 156;
155 // final static int TokenNameEQUAL_EQUAL_EQUAL = 157;
156 // final static int TokenNameNOT_EQUAL_EQUAL = 158;
157 // final static int TokenNameOR = 159;
158 // final static int TokenNameAT = 153; // @
161 this.currentPHPString = 0;
162 // PHPParserSuperclass.fileToParse = fileToParse;
165 this.token = TokenNameEOF;
167 // this.rowCount = 1;
168 // this.columnCount = 0;
172 this.initializeScanner();
176 public void setFileToParse(IFile fileToParse) {
177 this.currentPHPString = 0;
178 PHPParserSuperclass.fileToParse = fileToParse;
181 this.token = TokenNameEOF;
183 this.initializeScanner();
186 * ClassDeclaration Constructor.
189 *@param sess Description of Parameter
192 public Parser(IFile fileToParse) {
193 // if (keywordMap == null) {
194 // keywordMap = new HashMap();
195 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
196 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
199 this.currentPHPString = 0;
200 PHPParserSuperclass.fileToParse = fileToParse;
203 this.token = TokenNameEOF;
205 // this.rowCount = 1;
206 // this.columnCount = 0;
210 this.initializeScanner();
213 public void initializeScanner() {
214 this.scanner = new Scanner(false, false, false, false);
217 * Create marker for the parse error
219 private void setMarker(String message, int charStart, int charEnd, int errorLevel) throws CoreException {
220 setMarker(fileToParse, message, charStart, charEnd, errorLevel);
224 * This method will throw the SyntaxError.
225 * It will add the good lines and columns to the Error
226 * @param error the error message
227 * @throws SyntaxError the error raised
229 private void throwSyntaxError(String error) {
231 // if (str.length() < chIndx) {
234 // // read until end-of-line
236 // while (str.length() > eol) {
237 // ch = str.charAt(eol++);
243 // throw new SyntaxError(
245 // chIndx - columnCount + 1,
246 // str.substring(columnCount, eol),
248 throw new SyntaxError(1, 1, "", error);
252 * This method will throw the SyntaxError.
253 * It will add the good lines and columns to the Error
254 * @param error the error message
255 * @throws SyntaxError the error raised
257 private void throwSyntaxError(String error, int startRow) {
258 throw new SyntaxError(startRow, 0, " ", error);
261 private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
262 problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, compilationUnit.compilationResult);
263 throw new SyntaxError(1, 0, " ", error);
266 * Method Declaration.
270 // private void getChar() {
271 // if (str.length() > chIndx) {
272 // ch = str.charAt(chIndx++);
277 // chIndx = str.length() + 1;
279 // // token = TokenNameEOF;
284 * gets the next token from input
286 private void getNextToken() throws CoreException {
288 token = scanner.getNextToken();
290 int currentEndPosition = scanner.getCurrentTokenEndPosition();
291 int currentStartPosition = scanner.getCurrentTokenStartPosition();
293 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
294 System.out.println(scanner.toStringAction(token));
296 } catch (InvalidInputException e) {
297 token = TokenNameERROR;
305 * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
306 * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
307 * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
308 * value {@link Parser#TokenNameINT_NUMBER}
310 // private void getNumber() {
311 // StringBuffer inum = new StringBuffer();
313 // int numFormat = 10;
315 // // save first digit
316 // char firstCh = ch;
320 // // determine number conversions:
321 // if (firstCh == '0') {
350 // if (numFormat == 16) {
351 // while ((ch >= '0' && ch <= '9')
352 // || (ch >= 'a' && ch <= 'f')
353 // || (ch >= 'A' && ch <= 'F')) {
358 // while ((ch >= '0' && ch <= '9')
362 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
363 // if (ch == '.' && dFlag != ' ') {
366 // if ((dFlag == 'E') || (dFlag == 'e')) {
372 // if ((ch == '-') || (ch == '+')) {
385 // if (dFlag != ' ') {
386 // doubleNumber = new Double(inum.toString());
387 // token = TokenNameDoubleLiteral;
390 // longNumber = Long.valueOf(inum.toString(), numFormat);
391 // token = TokenNameIntegerLiteral;
395 // } catch (Throwable e) {
396 // throwSyntaxError("Number format error: " + inum.toString());
402 // * @param openChar the opening char ('\'', '"', '`')
403 // * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
404 // * @param errorMsg the error message in case of parse error in the string
406 // private void getString(
407 // final char openChar,
408 // final int typeString,
409 // final String errorMsg) {
410 // StringBuffer sBuffer = new StringBuffer();
411 // boolean openString = true;
412 // int startRow = rowCount;
413 // while (str.length() > chIndx) {
414 // ch = str.charAt(chIndx++);
416 // sBuffer.append(ch);
417 // if (str.length() > chIndx) {
418 // ch = str.charAt(chIndx++);
419 // sBuffer.append(ch);
421 // } else if (ch == openChar) {
422 // openString = false;
424 // } else if (ch == '\n') {
426 // columnCount = chIndx;
428 // sBuffer.append(ch);
432 // if (typeString == TokenNameStringConstant) {
433 // throwSyntaxError(errorMsg, startRow);
435 // throwSyntaxError(errorMsg);
438 // token = typeString;
439 // stringValue = sBuffer.toString();
442 // public void htmlParserTester(String input) {
443 // int lineNumber = 1;
444 // int startLineNumber = 1;
445 // int startIndex = 0;
448 // boolean phpMode = false;
449 // boolean phpFound = false;
451 // phpList = new ArrayList();
452 // currentPHPString = 0;
456 // while (i < input.length()) {
457 // ch = input.charAt(i++);
461 // if ((!phpMode) && ch == '<') {
462 // ch2 = input.charAt(i++);
464 // ch2 = input.charAt(i++);
465 // if (Character.isWhitespace(ch2)) {
470 // startLineNumber = lineNumber;
472 // } else if (ch2 == 'p') {
473 // ch2 = input.charAt(i++);
475 // ch2 = input.charAt(i++);
480 // startLineNumber = lineNumber;
486 // } else if (ch2 == 'P') {
487 // ch2 = input.charAt(i++);
489 // ch2 = input.charAt(i++);
494 // startLineNumber = lineNumber;
507 // if (ch == '/' && i < input.length()) {
508 // ch2 = input.charAt(i++);
510 // while (i < input.length()) {
511 // ch = input.charAt(i++);
512 // if (ch == '?' && i < input.length()) {
513 // ch2 = input.charAt(i++);
522 // startLineNumber));
526 // } else if (ch == '\n') {
532 // } else if (ch2 == '*') {
533 // // multi-line comment
534 // while (i < input.length()) {
535 // ch = input.charAt(i++);
538 // } else if (ch == '*' && i < input.length()) {
539 // ch2 = input.charAt(i++);
550 // } else if (ch == '#') {
551 // while (i < input.length()) {
552 // ch = input.charAt(i++);
553 // if (ch == '?' && i < input.length()) {
554 // ch2 = input.charAt(i++);
560 // input.substring(startIndex, i - 2),
561 // startLineNumber));
565 // } else if (ch == '\n') {
571 // } else if (ch == '"') {
573 // while (i < input.length()) {
574 // ch = input.charAt(i++);
578 // ch == '\\' && i < input.length()) { // escape
580 // } else if (ch == '"') {
585 // } else if (ch == '\'') {
587 // while (i < input.length()) {
588 // ch = input.charAt(i++);
592 // ch == '\\' && i < input.length()) { // escape
594 // } else if (ch == '\'') {
601 // if (ch == '?' && i < input.length()) {
602 // ch2 = input.charAt(i++);
608 // input.substring(startIndex, i - 2),
609 // startLineNumber));
619 // "No PHP source code found.",
625 // "Open PHP tag at end of file.",
630 // input.substring(startIndex, i - 2),
631 // startLineNumber));
633 // // for (int j=0;j<phpList.size();j++) {
634 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
635 // // int startIndx = temp.length()-10;
636 // // if (startIndx<0) {
639 // // System.out.println(temp.substring(startIndx)+"?>");
641 // phpParserTester(null, 1);
642 // // PHPString temp;
643 // // for(int j=0;j<phpList.size();j++) {
644 // // temp = (PHPString) phpList.get(j);
645 // // parser.start(temp.getPHPString(), temp.getLineNumber());
648 // } catch (CoreException e) {
652 public void phpParserTester(String s, int rowCount) throws CoreException {
655 if (phpList.size() != 0) {
656 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
659 this.token = TokenNameEOF;
661 // this.rowCount = rowCount;
662 // this.columnCount = 0;
665 scanner.setSource(s.toCharArray());
666 scanner.setPHPMode(true);
670 if (token != TokenNameEOF && token != TokenNameERROR) {
673 if (token != TokenNameEOF) {
674 if (token == TokenNameERROR) {
675 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
677 if (token == TokenNameRPAREN) {
678 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
680 if (token == TokenNameRBRACE) {
681 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
683 if (token == TokenNameRBRACKET) {
684 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
687 if (token == TokenNameLPAREN) {
688 throwSyntaxError("Read character '('; end-of-file not reached.");
690 if (token == TokenNameLBRACE) {
691 throwSyntaxError("Read character '{'; end-of-file not reached.");
693 if (token == TokenNameLBRACKET) {
694 throwSyntaxError("Read character '['; end-of-file not reached.");
697 throwSyntaxError("End-of-file not reached.");
700 } catch (SyntaxError err) {
704 // setMarker(err.getMessage(), err.getLine(), ERROR);
705 setMarker(err.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
707 // if an error occured,
708 // try to find keywords 'class' or 'function'
709 // to parse the rest of the string
710 while (token != TokenNameEOF && token != TokenNameERROR) {
711 if (token == TokenNameclass || token == TokenNamefunction) {
716 if (token == TokenNameEOF || token == TokenNameERROR) {
723 public void init(String s) {
725 this.token = TokenNameEOF;
727 // this.rowCount = 1;
728 // this.columnCount = 0;
730 this.phpMode = false;
731 /* scanner initialization */
732 scanner.setSource(s.toCharArray());
733 scanner.setPHPMode(false);
736 protected void initialize(boolean phpMode) {
737 compilationUnit = null;
738 referenceContext = null;
740 this.token = TokenNameEOF;
742 // this.rowCount = 1;
743 // this.columnCount = 0;
745 this.phpMode = phpMode;
746 scanner.setPHPMode(phpMode);
749 * Parses a string with php tags
750 * i.e. '<body> <?php phpinfo() ?> </body>'
752 public void parse(String s) throws CoreException {
758 * Parses a string with php tags
759 * i.e. '<body> <?php phpinfo() ?> </body>'
761 protected void parse() throws CoreException {
765 if (token != TokenNameEOF && token != TokenNameERROR) {
768 if (token != TokenNameEOF) {
769 if (token == TokenNameERROR) {
770 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
772 if (token == TokenNameRPAREN) {
773 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
775 if (token == TokenNameRBRACE) {
776 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
778 if (token == TokenNameRBRACKET) {
779 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
782 if (token == TokenNameLPAREN) {
783 throwSyntaxError("Read character '('; end-of-file not reached.");
785 if (token == TokenNameLBRACE) {
786 throwSyntaxError("Read character '{'; end-of-file not reached.");
788 if (token == TokenNameLBRACKET) {
789 throwSyntaxError("Read character '['; end-of-file not reached.");
792 throwSyntaxError("End-of-file not reached.");
795 } catch (SyntaxError sytaxErr1) {
796 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
797 setMarker(sytaxErr1.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
799 // if an error occured,
800 // try to find keywords 'class' or 'function'
801 // to parse the rest of the string
802 while (token != TokenNameEOF && token != TokenNameERROR) {
803 if (token == TokenNameclass || token == TokenNamefunction) {
808 if (token == TokenNameEOF || token == TokenNameERROR) {
811 } catch (SyntaxError sytaxErr2) {
812 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
813 setMarker(sytaxErr2.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
821 public PHPOutlineInfo parseInfo(Object parent, String s) {
822 PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
823 // Stack stack = new Stack();
824 // stack.push(outlineInfo.getDeclarations());
827 this.token = TokenNameEOF;
829 // this.rowCount = 1;
830 // this.columnCount = 0;
832 this.phpMode = false;
833 scanner.setSource(s.toCharArray());
834 scanner.setPHPMode(false);
838 parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
839 } catch (CoreException e) {
844 private boolean isVariable() {
845 return token == TokenNameVariable || token == TokenNamethis;
848 private void parseDeclarations(PHPOutlineInfo outlineInfo, OutlineableWithChildren current, boolean goBack) {
850 // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
851 PHPSegmentWithChildren temp;
854 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
856 while (token != TokenNameEOF && token != TokenNameERROR) {
857 if (token == TokenNameVariable) {
858 ident = scanner.getCurrentIdentifierSource();
859 outlineInfo.addVariable(new String(ident));
861 } else if (token == TokenNamevar) {
863 if (token == TokenNameVariable && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
864 ident = scanner.getCurrentIdentifierSource();
865 //substring(1) added because PHPVarDeclaration doesn't need the $ anymore
866 String variableName = new String(ident).substring(1);
867 outlineInfo.addVariable(variableName);
869 if (token != TokenNameSEMICOLON) {
872 ident = scanner.getCurrentTokenSource();
873 if (token > TokenNameKEYWORD) {
874 current.add(new PHPVarDeclaration(current, variableName,
875 // chIndx - ident.length,
876 scanner.getCurrentTokenStartPosition(), new String(ident)));
879 case TokenNameVariable :
881 current.add(new PHPVarDeclaration(current, variableName,
882 // chIndx - ident.length,
883 scanner.getCurrentTokenStartPosition(), new String(ident)));
885 case TokenNameIdentifier :
886 current.add(new PHPVarDeclaration(current, variableName,
887 // chIndx - ident.length,
888 scanner.getCurrentTokenStartPosition(), new String(ident)));
890 case TokenNameDoubleLiteral :
891 current.add(new PHPVarDeclaration(current, variableName + doubleNumber,
892 // chIndx - ident.length,
893 scanner.getCurrentTokenStartPosition(), new String(ident)));
895 case TokenNameIntegerLiteral :
896 current.add(new PHPVarDeclaration(current, variableName,
897 // chIndx - ident.length,
898 scanner.getCurrentTokenStartPosition(), new String(ident)));
900 case TokenNameStringInterpolated :
901 case TokenNameStringLiteral :
902 current.add(new PHPVarDeclaration(current, variableName,
903 // chIndx - ident.length,
904 scanner.getCurrentTokenStartPosition(), new String(ident)));
906 case TokenNameStringConstant :
907 current.add(new PHPVarDeclaration(current, variableName,
908 // chIndx - ident.length,
909 scanner.getCurrentTokenStartPosition(), new String(ident)));
912 current.add(new PHPVarDeclaration(current, variableName,
913 // chIndx - ident.length
914 scanner.getCurrentTokenStartPosition()));
920 ident = scanner.getCurrentIdentifierSource();
922 current.add(new PHPVarDeclaration(current, variableName,
923 // chIndx - ident.length
924 scanner.getCurrentTokenStartPosition()));
927 } else if (token == TokenNamefunction) {
929 if (token == TokenNameAND) {
932 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
933 ident = scanner.getCurrentIdentifierSource();
934 outlineInfo.addVariable(new String(ident));
935 temp = new PHPFunctionDeclaration(current, new String(ident),
936 // chIndx - ident.length
937 scanner.getCurrentTokenStartPosition());
940 parseDeclarations(outlineInfo, temp, true);
942 } else if (token == TokenNameclass) {
944 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
945 ident = scanner.getCurrentIdentifierSource();
946 outlineInfo.addVariable(new String(ident));
947 temp = new PHPClassDeclaration(current, new String(ident),
948 // chIndx - ident.len
949 scanner.getCurrentTokenStartPosition());
954 //skip tokens for classname, extends and others until we have the opening '{'
955 while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) {
958 parseDeclarations(outlineInfo, temp, true);
961 } else if ((token == TokenNameLBRACE) || (token == TokenNameDOLLAR_LBRACE)) {
964 } else if (token == TokenNameRBRACE) {
967 if (counter == 0 && goBack) {
970 } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) {
971 ident = scanner.getCurrentTokenSource();
974 int startPosition = scanner.getCurrentTokenStartPosition();
976 char[] expr = scanner.getCurrentTokenSource(startPosition);
977 outlineInfo.addVariable(new String(ident));
978 current.add(new PHPReqIncDeclaration(current, new String(ident),
979 // chIndx - ident.length,
980 startPosition, new String(expr)));
986 } catch (CoreException e) {
987 } catch (SyntaxError sytaxErr) {
989 // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
990 setMarker(sytaxErr.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
991 } catch (CoreException e) {
996 private void statementList() throws CoreException {
998 statement(TokenNameEOF);
999 if ((token == TokenNameRBRACE)
1000 || (token == TokenNamecase)
1001 || (token == TokenNamedefault)
1002 || (token == TokenNameelse)
1003 || (token == TokenNameelseif)
1004 || (token == TokenNameendif)
1005 || (token == TokenNameendfor)
1006 || (token == TokenNameendforeach)
1007 || (token == TokenNameendwhile)
1008 || (token == TokenNameendswitch)
1009 || (token == TokenNameEOF)
1010 || (token == TokenNameERROR)) {
1016 private void functionBody(MethodDeclaration methodDecl) throws CoreException {
1017 // '{' [statement-list] '}'
1018 if (token == TokenNameLBRACE) {
1021 throwSyntaxError("'{' expected in compound-statement.");
1023 if (token != TokenNameRBRACE) {
1026 if (token == TokenNameRBRACE) {
1027 methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1030 throwSyntaxError("'}' expected in compound-statement.");
1034 private void statement(int previousToken) throws CoreException {
1035 // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
1036 // char[] ident = scanner.getCurrentIdentifierSource();
1037 // String keyword = new String(ident);
1038 if (token == TokenNameAT) {
1040 if (token != TokenNamerequire
1041 && token != TokenNamerequire_once
1042 && token != TokenNameinclude
1043 && token != TokenNameinclude_once
1044 && token != TokenNameIdentifier
1045 && token != TokenNameVariable
1046 && token != TokenNamethis
1047 && token != TokenNameStringInterpolated) {
1048 throwSyntaxError("identifier expected after '@'.");
1051 if (token == TokenNameinclude || token == TokenNameinclude_once) {
1053 if (token == TokenNameLPAREN) {
1055 if (token == TokenNameSEMICOLON) {
1058 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
1059 throwSyntaxError("';' expected after 'include' or 'include_once'.");
1064 concatenationExpression();
1068 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1071 if (token == TokenNameLPAREN) {
1073 if (token == TokenNameSEMICOLON) {
1076 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
1077 throwSyntaxError("';' expected after 'require' or 'require_once'.");
1082 concatenationExpression();
1085 } else if (token == TokenNameif) {
1087 if (token == TokenNameLPAREN) {
1090 throwSyntaxError("'(' expected after 'if' keyword.");
1093 if (token == TokenNameRPAREN) {
1096 throwSyntaxError("')' expected after 'if' condition.");
1101 } else if (token == TokenNameswitch) {
1103 if (token == TokenNameLPAREN) {
1106 throwSyntaxError("'(' expected after 'switch' keyword.");
1109 if (token == TokenNameRPAREN) {
1112 throwSyntaxError("')' expected after 'switch' condition.");
1116 } else if (token == TokenNamefor) {
1118 if (token == TokenNameLPAREN) {
1121 throwSyntaxError("'(' expected after 'for' keyword.");
1123 if (token == TokenNameSEMICOLON) {
1127 if (token == TokenNameSEMICOLON) {
1130 throwSyntaxError("';' expected after 'for'.");
1133 if (token == TokenNameSEMICOLON) {
1137 if (token == TokenNameSEMICOLON) {
1140 throwSyntaxError("';' expected after 'for'.");
1143 if (token == TokenNameRPAREN) {
1147 if (token == TokenNameRPAREN) {
1150 throwSyntaxError("')' expected after 'for'.");
1155 } else if (token == TokenNamewhile) {
1157 if (token == TokenNameLPAREN) {
1160 throwSyntaxError("'(' expected after 'while' keyword.");
1163 if (token == TokenNameRPAREN) {
1166 throwSyntaxError("')' expected after 'while' condition.");
1170 } else if (token == TokenNamedo) {
1172 if (token == TokenNameLBRACE) {
1175 throwSyntaxError("'{' expected after 'do' keyword.");
1177 if (token != TokenNameRBRACE) {
1180 if (token == TokenNameRBRACE) {
1183 throwSyntaxError("'}' expected after 'do' keyword.");
1185 if (token == TokenNamewhile) {
1187 if (token == TokenNameLPAREN) {
1190 throwSyntaxError("'(' expected after 'while' keyword.");
1193 if (token == TokenNameRPAREN) {
1196 throwSyntaxError("')' expected after 'while' condition.");
1199 throwSyntaxError("'while' expected after 'do' keyword.");
1201 if (token == TokenNameSEMICOLON) {
1204 if (token != TokenNameStopPHP) {
1205 throwSyntaxError("';' expected after do-while statement.");
1210 } else if (token == TokenNameforeach) {
1212 if (token == TokenNameLPAREN) {
1215 throwSyntaxError("'(' expected after 'foreach' keyword.");
1218 if (token == TokenNameas) {
1221 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1224 if (token == TokenNameEQUAL_GREATER) {
1228 if (token == TokenNameRPAREN) {
1231 throwSyntaxError("')' expected after 'foreach' expression.");
1236 } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
1238 if (token != TokenNameSEMICOLON) {
1241 if (token == TokenNameSEMICOLON) {
1244 if (token != TokenNameStopPHP) {
1245 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1251 } else if (token == TokenNameecho) {
1254 if (token == TokenNameSEMICOLON) {
1257 if (token != TokenNameStopPHP) {
1258 throwSyntaxError("';' expected after 'echo' statement.");
1263 // } else if (token == TokenNameprint) {
1266 // if (token == TokenNameSEMICOLON) {
1269 // if (token != TokenNameStopPHP) {
1270 // throwSyntaxError("';' expected after 'print' statement.");
1276 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1279 if (token == TokenNameSEMICOLON) {
1282 if (token != TokenNameStopPHP) {
1283 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1289 // } else if (token == TokenNameunset) {
1291 // if (token == TokenNameARGOPEN) {
1294 // throwSyntaxError("'(' expected after 'unset' keyword.");
1297 // if (token == TokenNameARGCLOSE) {
1300 // throwSyntaxError("')' expected after 'unset' statement.");
1302 // if (token == TokenNameSEMICOLON) {
1305 // if (token != TokenNameStopPHP) {
1306 // throwSyntaxError("';' expected after 'unset' statement.");
1312 // } else if (token == TokenNameexit || token == TokenNamedie) {
1314 // if (token != TokenNameSEMICOLON) {
1317 // if (token == TokenNameSEMICOLON) {
1320 // if (token != TokenNameStopPHP) {
1321 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1327 } else if (token == TokenNamedefine) {
1329 if (token == TokenNameLPAREN) {
1332 throwSyntaxError("'(' expected after 'define' keyword.");
1335 if (token == TokenNameCOMMA) {
1338 throwSyntaxError("',' expected after first 'define' constant.");
1341 if (token == TokenNameCOMMA) {
1345 if (token == TokenNameRPAREN) {
1348 throwSyntaxError("')' expected after 'define' statement.");
1350 if (token == TokenNameSEMICOLON) {
1353 if (token != TokenNameStopPHP) {
1354 throwSyntaxError("';' expected after 'define' statement.");
1359 } else if (token == TokenNamefunction) {
1360 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1361 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1363 functionDefinition(methodDecl);
1365 } else if (token == TokenNameclass) {
1366 TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
1367 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1368 // default super class
1369 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1370 compilationUnit.types.add(typeDecl);
1372 pushOnAstStack(typeDecl);
1374 classDeclarator(typeDecl);
1375 classBody(typeDecl);
1382 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1383 } else if (token == TokenNameLBRACE) {
1385 if (token != TokenNameRBRACE) {
1388 if (token == TokenNameRBRACE) {
1392 throwSyntaxError("'}' expected.");
1395 if (token != TokenNameSEMICOLON) {
1398 if (token == TokenNameSEMICOLON) {
1402 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1403 throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
1410 private void classDeclarator(TypeDeclaration typeDecl) throws CoreException {
1412 //identifier 'extends' identifier
1414 if (token == TokenNameIdentifier) {
1415 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1416 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1417 typeDecl.name = scanner.getCurrentIdentifierSource();
1419 if (token == TokenNameextends) {
1422 if (token == TokenNameIdentifier) {
1425 reportSyntaxError("Class name expected after keyword 'extends'.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1426 // throwSyntaxError("ClassDeclaration name expected after keyword 'extends'.");
1428 } while (token == TokenNameCOMMA);
1431 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1432 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1434 if (token > TokenNameKEYWORD) {
1435 typeDecl.name = scanner.getCurrentIdentifierSource();
1437 "Don't use keyword for class declaration [" + scanner.toStringAction(token) + "].",
1438 typeDecl.sourceStart,
1439 typeDecl.sourceEnd);
1440 // throwSyntaxError("Don't use keyword for class declaration [" + token + "].");
1442 typeDecl.name = new char[] { ' ' };
1443 reportSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1444 // throwSyntaxError("ClassDeclaration name expected after keyword 'class'.");
1448 private void classBody(TypeDeclaration typeDecl) throws CoreException {
1449 //'{' [class-element-list] '}'
1450 if (token == TokenNameLBRACE) {
1452 if (token != TokenNameRBRACE) {
1455 if (token == TokenNameRBRACE) {
1456 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1459 throwSyntaxError("'}' expected at end of class body.");
1462 throwSyntaxError("'{' expected at start of class body.");
1466 private void classElementList() throws CoreException {
1469 } while (token == TokenNamefunction || token == TokenNamevar);
1472 private void classElement() throws CoreException {
1474 //function-definition
1475 if (token == TokenNamefunction) {
1476 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1477 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1479 functionDefinition(methodDecl);
1480 } else if (token == TokenNamevar) {
1484 throwSyntaxError("'function' or 'var' expected.");
1488 private void classProperty() throws CoreException {
1489 //'var' variable ';'
1490 //'var' variable '=' constant ';'
1492 if (token == TokenNameVariable) {
1494 if (token == TokenNameEQUAL) {
1499 if (token == TokenNamethis) {
1500 throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1502 throwSyntaxError("Variable expected after keyword 'var'.");
1504 if (token != TokenNameCOMMA) {
1509 if (token == TokenNameSEMICOLON) {
1512 throwSyntaxError("';' expected after variable declaration.");
1516 private void functionDefinition(MethodDeclaration methodDecl) throws CoreException {
1518 compilationUnit.types.add(methodDecl);
1520 AstNode node = astStack[astPtr];
1521 if (node instanceof TypeDeclaration) {
1522 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1523 if (typeDecl.methods == null) {
1524 typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
1526 AbstractMethodDeclaration[] newMethods;
1527 System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, typeDecl.methods.length);
1528 newMethods[0] = methodDecl;
1529 typeDecl.methods = newMethods;
1533 functionDeclarator(methodDecl);
1534 functionBody(methodDecl);
1537 private void functionDeclarator(MethodDeclaration methodDecl) throws CoreException {
1538 //identifier '(' [parameter-list] ')'
1539 if (token == TokenNameAND) {
1542 if (token == TokenNameIdentifier) {
1543 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1544 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1545 methodDecl.selector = scanner.getCurrentIdentifierSource();
1547 if (token == TokenNameLPAREN) {
1550 throwSyntaxError("'(' expected in function declaration.");
1552 if (token != TokenNameRPAREN) {
1555 if (token != TokenNameRPAREN) {
1556 throwSyntaxError("')' expected in function declaration.");
1558 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1562 if (token > TokenNameKEYWORD) {
1563 throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
1565 throwSyntaxError("Function name expected after keyword 'function'.");
1569 private void parameterList() throws CoreException {
1570 //parameter-declaration
1571 //parameter-list ',' parameter-declaration
1573 parameterDeclaration();
1574 if (token != TokenNameCOMMA) {
1581 private void parameterDeclaration() throws CoreException {
1583 //variable-reference
1584 if (token == TokenNameAND) {
1589 throwSyntaxError("Variable expected after reference operator '&'.");
1592 //variable '=' constant
1593 if (token == TokenNameVariable) {
1595 if (token == TokenNameEQUAL) {
1601 if (token == TokenNamethis) {
1602 throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1606 private void labeledStatementList() throws CoreException {
1607 if (token != TokenNamecase && token != TokenNamedefault) {
1608 throwSyntaxError("'case' or 'default' expected.");
1611 if (token == TokenNamecase) {
1613 expression(); //constant();
1614 if (token == TokenNameCOLON) {
1616 if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
1620 } else if (token == TokenNameSEMICOLON) {
1622 // "':' expected after 'case' keyword (Found token: "
1623 // + scanner.toStringAction(token)
1628 "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")",
1629 scanner.getCurrentTokenStartPosition(),
1630 scanner.getCurrentTokenEndPosition(),
1633 if (token == TokenNamecase) { // empty case statement ?
1638 throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
1640 } else { // TokenNamedefault
1642 if (token == TokenNameCOLON) {
1646 throwSyntaxError("':' character after 'default' expected.");
1649 } while (token == TokenNamecase || token == TokenNamedefault);
1652 // public void labeledStatement() {
1653 // if (token == TokenNamecase) {
1656 // if (token == TokenNameDDOT) {
1660 // throwSyntaxError("':' character after 'case' constant expected.");
1663 // } else if (token == TokenNamedefault) {
1665 // if (token == TokenNameDDOT) {
1669 // throwSyntaxError("':' character after 'default' expected.");
1675 // public void expressionStatement() {
1678 // private void inclusionStatement() {
1681 // public void compoundStatement() {
1684 // public void selectionStatement() {
1687 // public void iterationStatement() {
1690 // public void jumpStatement() {
1693 // public void outputStatement() {
1696 // public void scopeStatement() {
1699 // public void flowStatement() {
1702 // public void definitionStatement() {
1705 private void ifStatement() throws CoreException {
1706 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1707 if (token == TokenNameCOLON) {
1709 if (token != TokenNameendif) {
1712 case TokenNameelse :
1714 if (token == TokenNameCOLON) {
1716 if (token != TokenNameendif) {
1720 if (token == TokenNameif) { //'else if'
1722 elseifStatementList();
1724 throwSyntaxError("':' expected after 'else'.");
1728 case TokenNameelseif :
1730 elseifStatementList();
1735 if (token != TokenNameendif) {
1736 throwSyntaxError("'endif' expected.");
1739 if (token != TokenNameSEMICOLON) {
1740 throwSyntaxError("';' expected after if-statement.");
1744 // statement [else-statement]
1745 statement(TokenNameEOF);
1746 if (token == TokenNameelseif) {
1748 if (token == TokenNameLPAREN) {
1751 throwSyntaxError("'(' expected after 'elseif' keyword.");
1754 if (token == TokenNameRPAREN) {
1757 throwSyntaxError("')' expected after 'elseif' condition.");
1760 } else if (token == TokenNameelse) {
1762 statement(TokenNameEOF);
1767 private void elseifStatementList() throws CoreException {
1771 case TokenNameelse :
1773 if (token == TokenNameCOLON) {
1775 if (token != TokenNameendif) {
1780 if (token == TokenNameif) { //'else if'
1783 throwSyntaxError("':' expected after 'else'.");
1787 case TokenNameelseif :
1796 private void elseifStatement() throws CoreException {
1797 if (token == TokenNameLPAREN) {
1800 if (token != TokenNameRPAREN) {
1801 throwSyntaxError("')' expected in else-if-statement.");
1804 if (token != TokenNameCOLON) {
1805 throwSyntaxError("':' expected in else-if-statement.");
1808 if (token != TokenNameendif) {
1814 private void switchStatement() throws CoreException {
1815 if (token == TokenNameCOLON) {
1816 // ':' [labeled-statement-list] 'endswitch' ';'
1818 labeledStatementList();
1819 if (token != TokenNameendswitch) {
1820 throwSyntaxError("'endswitch' expected.");
1823 if (token != TokenNameSEMICOLON) {
1824 throwSyntaxError("';' expected after switch-statement.");
1828 // '{' [labeled-statement-list] '}'
1829 if (token != TokenNameLBRACE) {
1830 throwSyntaxError("'{' expected in switch statement.");
1833 if (token != TokenNameRBRACE) {
1834 labeledStatementList();
1836 if (token != TokenNameRBRACE) {
1837 throwSyntaxError("'}' expected in switch statement.");
1844 private void forStatement() throws CoreException {
1845 if (token == TokenNameCOLON) {
1848 if (token != TokenNameendfor) {
1849 throwSyntaxError("'endfor' expected.");
1852 if (token != TokenNameSEMICOLON) {
1853 throwSyntaxError("';' expected after for-statement.");
1857 statement(TokenNameEOF);
1861 private void whileStatement() throws CoreException {
1862 // ':' statement-list 'endwhile' ';'
1863 if (token == TokenNameCOLON) {
1866 if (token != TokenNameendwhile) {
1867 throwSyntaxError("'endwhile' expected.");
1870 if (token != TokenNameSEMICOLON) {
1871 throwSyntaxError("';' expected after while-statement.");
1875 statement(TokenNameEOF);
1879 private void foreachStatement() throws CoreException {
1880 if (token == TokenNameCOLON) {
1883 if (token != TokenNameendforeach) {
1884 throwSyntaxError("'endforeach' expected.");
1887 if (token != TokenNameSEMICOLON) {
1888 throwSyntaxError("';' expected after foreach-statement.");
1892 statement(TokenNameEOF);
1896 private void exitStatus() throws CoreException {
1897 if (token == TokenNameLPAREN) {
1900 throwSyntaxError("'(' expected in 'exit-status'.");
1902 if (token != TokenNameRPAREN) {
1905 if (token == TokenNameRPAREN) {
1908 throwSyntaxError("')' expected after 'exit-status'.");
1912 private void expressionList() throws CoreException {
1915 if (token == TokenNameCOMMA) {
1923 private void expression() throws CoreException {
1924 //todo: find a better way to get the expression
1925 // expression = new StringBuffer();
1926 // for (int i = chIndx; i < str.length(); i++) {
1927 // if (str.charAt(i) == ';') {
1930 // expression.append(str.charAt(i));
1933 // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
1936 logicalinclusiveorExpression();
1937 // while (token != TokenNameSEMICOLON) {
1943 private void postfixExpression() throws CoreException {
1946 boolean castFlag = false;
1947 boolean arrayFlag = false;
1953 case TokenNamenull :
1956 case TokenNamefalse :
1959 case TokenNametrue :
1962 case TokenNameStringConstant :
1965 case TokenNameHEREDOC :
1966 case TokenNameStringInterpolated :
1967 case TokenNameStringLiteral :
1970 case TokenNameLPAREN :
1973 if (token == TokenNameIdentifier) {
1974 // check if identifier is a type:
1975 // ident = identifier;
1976 ident = scanner.getCurrentIdentifierSource();
1977 String str = new String(ident).toLowerCase();
1978 for (int i = 0; i < PHP_TYPES.length; i++) {
1979 if (PHP_TYPES[i].equals(str)) {
1981 if (PHP_TYPES[i].equals("array")) {
1991 if (arrayFlag && token == TokenNameLPAREN) {
1993 if (token == TokenNameRPAREN) {
1997 if (token != TokenNameRPAREN) {
1998 throwSyntaxError(") expected after 'array('.");
2002 if (token != TokenNameRPAREN) {
2003 throwSyntaxError(") expected after cast-type '" + str + "'.");
2011 if (token != TokenNameRPAREN) {
2012 throwSyntaxError(") expected in postfix-expression.");
2016 case TokenNameDoubleLiteral :
2019 case TokenNameIntegerLiteral :
2022 case TokenNameDOLLAR_LBRACE :
2025 if (token != TokenNameRBRACE) {
2026 throwSyntaxError("'}' expected after indirect variable token '${'.");
2030 case TokenNameVariable :
2031 case TokenNamethis :
2032 ident = scanner.getCurrentIdentifierSource();
2034 if (token == TokenNameLBRACE) {
2037 if (token != TokenNameRBRACE) {
2038 throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression.");
2041 } else if (token == TokenNameLPAREN) {
2043 if (token != TokenNameRPAREN) {
2045 if (token != TokenNameRPAREN) {
2046 throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression.");
2052 case TokenNameIdentifier :
2053 ident = scanner.getCurrentIdentifierSource();
2055 if (token == TokenNameLPAREN) {
2057 if (token != TokenNameRPAREN) {
2059 if (token != TokenNameRPAREN) {
2061 "')' expected after identifier '" + new String(ident) + "' in postfix-expression." + "(Found token: " + scanner.toStringAction(token) + ")");
2067 case TokenNameprint :
2070 // if (token == TokenNameSEMICOLON) {
2073 // if (token != TokenNameStopPHP) {
2074 // throwSyntaxError("';' expected after 'print' statement.");
2079 case TokenNamelist :
2081 if (token == TokenNameLPAREN) {
2083 if (token == TokenNameCOMMA) {
2087 if (token != TokenNameRPAREN) {
2088 throwSyntaxError("')' expected after 'list' keyword.");
2091 // if (token == TokenNameSET) {
2093 // logicalinclusiveorExpression();
2096 throwSyntaxError("'(' expected after 'list' keyword.");
2099 // case TokenNameexit :
2101 // if (token != TokenNameSEMICOLON) {
2104 // if (token == TokenNameSEMICOLON) {
2107 // if (token != TokenNameStopPHP) {
2108 // throwSyntaxError("';' expected after 'exit' expression.");
2113 // case TokenNamedie :
2115 // if (token != TokenNameSEMICOLON) {
2118 // if (token == TokenNameSEMICOLON) {
2121 // if (token != TokenNameStopPHP) {
2122 // throwSyntaxError("';' expected after 'die' expression.");
2127 // case TokenNamearray :
2129 // if (token == TokenNameARGOPEN) {
2131 // if (token == TokenNameCOMMA) {
2134 // expressionList();
2135 // if (token != TokenNameARGCLOSE) {
2136 // throwSyntaxError("')' expected after 'list' keyword.");
2139 // if (token == TokenNameSET) {
2141 // logicalinclusiveorExpression();
2144 // throwSyntaxError("'(' expected after 'list' keyword.");
2148 boolean while_flag = true;
2151 case TokenNameLBRACKET :
2154 if (token != TokenNameRBRACKET) {
2155 throwSyntaxError("] expected in postfix-expression.");
2159 case TokenNameCOLON_COLON : // ::
2160 case TokenNameMINUS_GREATER : // ->
2162 if (token > TokenNameKEYWORD) {
2163 ident = scanner.getCurrentIdentifierSource();
2165 // "Avoid using keyword '"
2166 // + new String(ident)
2167 // + "' as variable name.",
2171 "Avoid using keyword '" + new String(ident) + "' as variable name.",
2172 scanner.getCurrentTokenStartPosition(),
2173 scanner.getCurrentTokenEndPosition(),
2177 case TokenNameVariable :
2178 ident = scanner.getCurrentIdentifierSource();
2180 // if (token == TokenNameARGOPEN) {
2182 // expressionList();
2183 // if (token != TokenNameARGCLOSE) {
2184 // throwSyntaxError(") expected after variable '" + ident + "'.");
2189 case TokenNameIdentifier :
2190 //ident = scanner.getCurrentIdentifierSource();
2193 case TokenNameLBRACE :
2196 if (token != TokenNameRBRACE) {
2197 throwSyntaxError("} expected in postfix-expression.");
2202 throwSyntaxError("Syntax error after '->' token.");
2203 } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
2204 if (token == TokenNameLBRACKET) {
2207 if (token != TokenNameRBRACKET) {
2208 throwSyntaxError("] expected after '->'.");
2211 } else if (token == TokenNameLPAREN) {
2214 if (token != TokenNameRPAREN) {
2215 throwSyntaxError(") expected after '->'.");
2218 } else if (token == TokenNameLBRACE) {
2221 if (token != TokenNameRBRACE) {
2222 throwSyntaxError("} expected after '->'.");
2228 case TokenNamePLUS_PLUS :
2231 case TokenNameMINUS_MINUS :
2242 private void unaryExpression() throws CoreException {
2244 case TokenNamePLUS_PLUS :
2248 case TokenNameMINUS_MINUS :
2252 // '@' '&' '*' '+' '-' '~' '!'
2255 if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) {
2256 statement(TokenNameAT);
2258 postfixExpression(); // castExpression();
2265 case TokenNameMULTIPLY :
2269 case TokenNamePLUS :
2273 case TokenNameMINUS :
2277 case TokenNameTWIDDLE :
2286 postfixExpression();
2290 private void castExpression() throws CoreException {
2291 // if (token == TokenNameARGOPEN) {
2294 // if (token != TokenNameARGCLOSE) {
2295 // throwSyntaxError(") expected after cast-expression.");
2302 private void assignExpression() throws CoreException {
2304 if (token == TokenNameEQUAL) { // =
2306 logicalinclusiveorExpression();
2307 } else if (token == TokenNameDOT_EQUAL) { // .=
2309 logicalinclusiveorExpression();
2310 } else if (token == TokenNameEQUAL_GREATER) { // =>
2312 logicalinclusiveorExpression();
2313 } else if (token == TokenNamePLUS_EQUAL) { // +=
2315 logicalinclusiveorExpression();
2316 } else if (token == TokenNameMINUS_EQUAL) { // -=
2318 logicalinclusiveorExpression();
2319 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2321 logicalinclusiveorExpression();
2322 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2324 logicalinclusiveorExpression();
2325 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2327 logicalinclusiveorExpression();
2328 } else if (token == TokenNameAND_EQUAL) { // &=
2330 logicalinclusiveorExpression();
2331 } else if (token == TokenNameOR_EQUAL) { // |=
2333 logicalinclusiveorExpression();
2334 } else if (token == TokenNameXOR_EQUAL) { // ^=
2336 logicalinclusiveorExpression();
2337 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2339 logicalinclusiveorExpression();
2340 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2342 logicalinclusiveorExpression();
2343 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2345 logicalinclusiveorExpression();
2349 private void multiplicativeExpression() throws CoreException {
2352 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
2359 private void concatenationExpression() throws CoreException {
2361 multiplicativeExpression();
2362 if (token != TokenNameDOT) {
2369 private void additiveExpression() throws CoreException {
2371 concatenationExpression();
2372 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2379 private void shiftExpression() throws CoreException {
2381 additiveExpression();
2382 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2389 private void relationalExpression() throws CoreException {
2392 if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2399 private void identicalExpression() throws CoreException {
2401 relationalExpression();
2402 if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
2409 private void equalityExpression() throws CoreException {
2411 identicalExpression();
2412 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2419 private void ternaryExpression() throws CoreException {
2420 equalityExpression();
2421 if (token == TokenNameQUESTION) {
2424 if (token == TokenNameCOLON) {
2428 throwSyntaxError("':' expected in ternary operator '? :'.");
2433 private void andExpression() throws CoreException {
2435 ternaryExpression();
2436 if (token != TokenNameAND) {
2443 private void exclusiveorExpression() throws CoreException {
2446 if (token != TokenNameXOR) {
2453 private void inclusiveorExpression() throws CoreException {
2455 exclusiveorExpression();
2456 if (token != TokenNameOR) {
2463 private void booleanandExpression() throws CoreException {
2465 inclusiveorExpression();
2466 if (token != TokenNameAND_AND) {
2473 private void booleanorExpression() throws CoreException {
2475 booleanandExpression();
2476 if (token != TokenNameOR_OR) {
2483 private void logicalandExpression() throws CoreException {
2485 booleanorExpression();
2486 if (token != TokenNameAND) {
2493 private void logicalexclusiveorExpression() throws CoreException {
2495 logicalandExpression();
2496 if (token != TokenNameXOR) {
2503 private void logicalinclusiveorExpression() throws CoreException {
2505 logicalexclusiveorExpression();
2506 if (token != TokenNameOR) {
2513 // public void assignmentExpression() {
2514 // if (token == TokenNameVARIABLE) {
2516 // if (token == TokenNameSET) {
2518 // logicalinclusiveorExpression();
2521 // logicalinclusiveorExpression();
2525 private void variableList() throws CoreException {
2528 if (token == TokenNameCOMMA) {
2536 private void variable() throws CoreException {
2537 if (token == TokenNameDOLLAR_LBRACE) {
2541 if (token != TokenNameRBRACE) {
2542 throwSyntaxError("'}' expected after indirect variable token '${'.");
2546 if (token == TokenNameVariable) {
2548 if (token == TokenNameLBRACKET) {
2551 if (token != TokenNameRBRACKET) {
2552 throwSyntaxError("']' expected in variable-list.");
2555 } else if (token == TokenNameEQUAL) {
2560 throwSyntaxError("$-variable expected in variable-list.");
2566 * It will look for a value (after a '=' for example)
2567 * @throws CoreException
2569 private void constant() throws CoreException {
2572 case TokenNamePLUS :
2575 case TokenNameDoubleLiteral :
2578 case TokenNameIntegerLiteral :
2582 throwSyntaxError("Constant expected after '+' presign.");
2585 case TokenNameMINUS :
2588 case TokenNameDoubleLiteral :
2591 case TokenNameIntegerLiteral :
2595 throwSyntaxError("Constant expected after '-' presign.");
2598 case TokenNamenull :
2601 case TokenNamefalse :
2604 case TokenNametrue :
2607 case TokenNameIdentifier :
2608 // ident = identifier;
2609 char[] ident = scanner.getCurrentIdentifierSource();
2611 if (token == TokenNameLPAREN) {
2613 if (token != TokenNameRPAREN) {
2615 if (token != TokenNameRPAREN) {
2616 throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression.");
2622 case TokenNameStringLiteral :
2625 case TokenNameStringConstant :
2628 case TokenNameStringInterpolated :
2631 case TokenNameDoubleLiteral :
2634 case TokenNameIntegerLiteral :
2638 throwSyntaxError("Constant expected.");
2642 public void reportSyntaxError() { //int act, int currentKind, int stateStackTop) {
2644 /* remember current scanner position */
2645 int startPos = scanner.startPosition;
2646 int currentPos = scanner.currentPosition;
2648 // String[] expectings;
2649 // String tokenName = name[symbol_index[currentKind]];
2651 //fetch all "accurate" possible terminals that could recover the error
2652 // int start, end = start = asi(stack[stateStackTop]);
2653 // while (asr[end] != 0)
2655 // int length = end - start;
2656 // expectings = new String[length];
2657 // if (length != 0) {
2658 // char[] indexes = new char[length];
2659 // System.arraycopy(asr, start, indexes, 0, length);
2660 // for (int i = 0; i < length; i++) {
2661 // expectings[i] = name[symbol_index[indexes[i]]];
2665 //if the pb is an EOF, try to tell the user that they are some
2666 // if (tokenName.equals(UNEXPECTED_EOF)) {
2667 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2668 // char[] tokenSource;
2670 // tokenSource = this.scanner.getCurrentTokenSource();
2671 // } catch (Exception e) {
2672 // tokenSource = new char[] {};
2674 // problemReporter().parseError(
2675 // this.scanner.startPosition,
2676 // this.scanner.currentPosition - 1,
2681 // } else { //the next test is HEAVILY grammar DEPENDENT.
2682 // if ((length == 14)
2683 // && (expectings[0] == "=") //$NON-NLS-1$
2684 // && (expectings[1] == "*=") //$NON-NLS-1$
2685 // && (expressionPtr > -1)) {
2686 // switch(currentKind) {
2687 // case TokenNameSEMICOLON:
2688 // case TokenNamePLUS:
2689 // case TokenNameMINUS:
2690 // case TokenNameDIVIDE:
2691 // case TokenNameREMAINDER:
2692 // case TokenNameMULTIPLY:
2693 // case TokenNameLEFT_SHIFT:
2694 // case TokenNameRIGHT_SHIFT:
2695 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
2696 // case TokenNameLESS:
2697 // case TokenNameGREATER:
2698 // case TokenNameLESS_EQUAL:
2699 // case TokenNameGREATER_EQUAL:
2700 // case TokenNameEQUAL_EQUAL:
2701 // case TokenNameNOT_EQUAL:
2702 // case TokenNameXOR:
2703 // case TokenNameAND:
2704 // case TokenNameOR:
2705 // case TokenNameOR_OR:
2706 // case TokenNameAND_AND:
2707 // // the ; is not the expected token ==> it ends a statement when an expression is not ended
2708 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
2710 // case TokenNameRBRACE :
2711 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
2714 // char[] tokenSource;
2716 // tokenSource = this.scanner.getCurrentTokenSource();
2717 // } catch (Exception e) {
2718 // tokenSource = new char[] {};
2720 // problemReporter().parseError(
2721 // this.scanner.startPosition,
2722 // this.scanner.currentPosition - 1,
2726 // this.checkAndReportBracketAnomalies(problemReporter());
2731 tokenSource = this.scanner.getCurrentTokenSource();
2732 } catch (Exception e) {
2733 tokenSource = new char[] {
2736 // problemReporter().parseError(
2737 // this.scanner.startPosition,
2738 // this.scanner.currentPosition - 1,
2742 this.checkAndReportBracketAnomalies(problemReporter());
2745 /* reset scanner where it was */
2746 scanner.startPosition = startPos;
2747 scanner.currentPosition = currentPos;
2749 public static final int RoundBracket = 0;
2750 public static final int SquareBracket = 1;
2751 public static final int CurlyBracket = 2;
2752 public static final int BracketKinds = 3;
2754 protected int[] nestedMethod; //the ptr is nestedType
2755 protected int nestedType, dimensions;
2757 final static int AstStackIncrement = 100;
2758 protected int astPtr;
2759 protected AstNode[] astStack = new AstNode[AstStackIncrement];
2760 protected int astLengthPtr;
2761 protected int[] astLengthStack;
2762 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
2764 public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
2765 protected ReferenceContext referenceContext;
2766 protected ProblemReporter problemReporter;
2767 // protected CompilationResult compilationResult;
2770 * Returns this parser's problem reporter initialized with its reference context.
2771 * Also it is assumed that a problem is going to be reported, so initializes
2772 * the compilation result's line positions.
2774 public ProblemReporter problemReporter() {
2775 if (scanner.recordLineSeparator) {
2776 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
2778 problemReporter.referenceContext = referenceContext;
2779 return problemReporter;
2782 * Reconsider the entire source looking for inconsistencies in {} () []
2784 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
2786 scanner.wasAcr = false;
2787 boolean anomaliesDetected = false;
2789 char[] source = scanner.source;
2790 int[] leftCount = { 0, 0, 0 };
2791 int[] rightCount = { 0, 0, 0 };
2792 int[] depths = { 0, 0, 0 };
2793 int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] };
2794 int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] };
2795 int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] };
2796 int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] };
2797 scanner.currentPosition = scanner.initialPosition; //starting point (first-zero-based char)
2798 while (scanner.currentPosition < scanner.eofPosition) { //loop for jumping over comments
2800 // ---------Consume white space and handles startPosition---------
2801 boolean isWhiteSpace;
2803 scanner.startPosition = scanner.currentPosition;
2804 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2805 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
2807 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
2808 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
2809 // only record line positions we have not recorded yet
2810 scanner.pushLineSeparator();
2813 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
2815 } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
2817 // -------consume token until } is found---------
2819 switch (scanner.currentCharacter) {
2822 int index = leftCount[CurlyBracket]++;
2823 if (index == leftPositions[CurlyBracket].length) {
2824 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
2825 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
2827 leftPositions[CurlyBracket][index] = scanner.startPosition;
2828 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
2833 int index = rightCount[CurlyBracket]++;
2834 if (index == rightPositions[CurlyBracket].length) {
2835 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
2836 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
2838 rightPositions[CurlyBracket][index] = scanner.startPosition;
2839 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
2844 int index = leftCount[RoundBracket]++;
2845 if (index == leftPositions[RoundBracket].length) {
2846 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
2847 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
2849 leftPositions[RoundBracket][index] = scanner.startPosition;
2850 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
2855 int index = rightCount[RoundBracket]++;
2856 if (index == rightPositions[RoundBracket].length) {
2857 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
2858 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
2860 rightPositions[RoundBracket][index] = scanner.startPosition;
2861 rightDepths[RoundBracket][index] = --depths[RoundBracket];
2866 int index = leftCount[SquareBracket]++;
2867 if (index == leftPositions[SquareBracket].length) {
2868 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
2869 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
2871 leftPositions[SquareBracket][index] = scanner.startPosition;
2872 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
2877 int index = rightCount[SquareBracket]++;
2878 if (index == rightPositions[SquareBracket].length) {
2879 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
2880 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
2882 rightPositions[SquareBracket][index] = scanner.startPosition;
2883 rightDepths[SquareBracket][index] = --depths[SquareBracket];
2888 if (scanner.getNextChar('\\')) {
2889 scanner.scanEscapeCharacter();
2890 } else { // consume next character
2891 scanner.unicodeAsBackSlash = false;
2892 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2893 // scanner.getNextUnicodeChar();
2895 if (scanner.withoutUnicodePtr != 0) {
2896 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2900 scanner.getNextChar('\'');
2903 case '"' : // consume next character
2904 scanner.unicodeAsBackSlash = false;
2905 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2906 // scanner.getNextUnicodeChar();
2908 if (scanner.withoutUnicodePtr != 0) {
2909 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2912 while (scanner.currentCharacter != '"') {
2913 if (scanner.currentCharacter == '\r') {
2914 if (source[scanner.currentPosition] == '\n')
2915 scanner.currentPosition++;
2916 break; // the string cannot go further that the line
2918 if (scanner.currentCharacter == '\n') {
2919 break; // the string cannot go further that the line
2921 if (scanner.currentCharacter == '\\') {
2922 scanner.scanEscapeCharacter();
2924 // consume next character
2925 scanner.unicodeAsBackSlash = false;
2926 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2927 // scanner.getNextUnicodeChar();
2929 if (scanner.withoutUnicodePtr != 0) {
2930 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2938 if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment
2940 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2941 //-------------unicode traitement ------------
2942 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2943 scanner.currentPosition++;
2944 while (source[scanner.currentPosition] == 'u') {
2945 scanner.currentPosition++;
2947 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2949 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2951 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2953 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2954 || c4 < 0) { //error don't care of the value
2955 scanner.currentCharacter = 'A';
2956 } //something different from \n and \r
2958 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2961 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
2963 scanner.startPosition = scanner.currentPosition;
2964 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2965 //-------------unicode traitement ------------
2966 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2967 scanner.currentPosition++;
2968 while (source[scanner.currentPosition] == 'u') {
2969 scanner.currentPosition++;
2971 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2973 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2975 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2977 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2978 || c4 < 0) { //error don't care of the value
2979 scanner.currentCharacter = 'A';
2980 } //something different from \n and \r
2982 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2986 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
2987 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
2988 // only record line positions we have not recorded yet
2989 scanner.pushLineSeparator();
2990 if (this.scanner.taskTags != null) {
2991 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
2997 if (test > 0) { //traditional and annotation comment
2998 boolean star = false;
2999 // consume next character
3000 scanner.unicodeAsBackSlash = false;
3001 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
3002 // scanner.getNextUnicodeChar();
3004 if (scanner.withoutUnicodePtr != 0) {
3005 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3008 if (scanner.currentCharacter == '*') {
3012 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
3013 //-------------unicode traitement ------------
3014 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3015 scanner.currentPosition++;
3016 while (source[scanner.currentPosition] == 'u') {
3017 scanner.currentPosition++;
3019 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3021 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3023 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3025 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3026 || c4 < 0) { //error don't care of the value
3027 scanner.currentCharacter = 'A';
3028 } //something different from * and /
3030 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3033 //loop until end of comment */
3034 while ((scanner.currentCharacter != '/') || (!star)) {
3035 star = scanner.currentCharacter == '*';
3037 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
3038 //-------------unicode traitement ------------
3039 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3040 scanner.currentPosition++;
3041 while (source[scanner.currentPosition] == 'u') {
3042 scanner.currentPosition++;
3044 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3046 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3048 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3050 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3051 || c4 < 0) { //error don't care of the value
3052 scanner.currentCharacter = 'A';
3053 } //something different from * and /
3055 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3059 if (this.scanner.taskTags != null) {
3060 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
3067 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3068 scanner.scanIdentifierOrKeyword(false);
3071 if (Character.isDigit(scanner.currentCharacter)) {
3072 scanner.scanNumber(false);
3076 //-----------------end switch while try--------------------
3077 } catch (IndexOutOfBoundsException e) {
3078 break; // read until EOF
3079 } catch (InvalidInputException e) {
3080 return false; // no clue
3083 if (scanner.recordLineSeparator) {
3084 // compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3087 // check placement anomalies against other kinds of brackets
3088 for (int kind = 0; kind < BracketKinds; kind++) {
3089 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3090 int start = leftPositions[kind][leftIndex]; // deepest first
3091 // find matching closing bracket
3092 int depth = leftDepths[kind][leftIndex];
3094 for (int i = 0; i < rightCount[kind]; i++) {
3095 int pos = rightPositions[kind][i];
3096 // want matching bracket further in source with same depth
3097 if ((pos > start) && (depth == rightDepths[kind][i])) {
3102 if (end < 0) { // did not find a good closing match
3103 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
3106 // check if even number of opening/closing other brackets in between this pair of brackets
3108 for (int otherKind = 0;(balance == 0) && (otherKind < BracketKinds); otherKind++) {
3109 for (int i = 0; i < leftCount[otherKind]; i++) {
3110 int pos = leftPositions[otherKind][i];
3111 if ((pos > start) && (pos < end))
3114 for (int i = 0; i < rightCount[otherKind]; i++) {
3115 int pos = rightPositions[otherKind][i];
3116 if ((pos > start) && (pos < end))
3120 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly
3125 // too many opening brackets ?
3126 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3127 anomaliesDetected = true;
3128 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, compilationUnit.compilationResult);
3130 // too many closing brackets ?
3131 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3132 anomaliesDetected = true;
3133 problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
3135 if (anomaliesDetected)
3139 return anomaliesDetected;
3140 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3141 return anomaliesDetected;
3142 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3143 return anomaliesDetected;
3147 protected void pushOnAstLengthStack(int pos) {
3149 astLengthStack[++astLengthPtr] = pos;
3150 } catch (IndexOutOfBoundsException e) {
3151 int oldStackLength = astLengthStack.length;
3152 int[] oldPos = astLengthStack;
3153 astLengthStack = new int[oldStackLength + StackIncrement];
3154 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3155 astLengthStack[astLengthPtr] = pos;
3159 protected void pushOnAstStack(AstNode node) {
3160 /*add a new obj on top of the ast stack
3161 astPtr points on the top*/
3164 astStack[++astPtr] = node;
3165 } catch (IndexOutOfBoundsException e) {
3166 int oldStackLength = astStack.length;
3167 AstNode[] oldStack = astStack;
3168 astStack = new AstNode[oldStackLength + AstStackIncrement];
3169 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3170 astPtr = oldStackLength;
3171 astStack[astPtr] = node;
3175 astLengthStack[++astLengthPtr] = 1;
3176 } catch (IndexOutOfBoundsException e) {
3177 int oldStackLength = astLengthStack.length;
3178 int[] oldPos = astLengthStack;
3179 astLengthStack = new int[oldStackLength + AstStackIncrement];
3180 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3181 astLengthStack[astLengthPtr] = 1;