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();
175 public void setFileToParse(IFile fileToParse) {
176 this.currentPHPString = 0;
177 PHPParserSuperclass.fileToParse = fileToParse;
180 this.token = TokenNameEOF;
182 this.initializeScanner();
185 * ClassDeclaration Constructor.
188 *@param sess Description of Parameter
191 public Parser(IFile fileToParse) {
192 // if (keywordMap == null) {
193 // keywordMap = new HashMap();
194 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
195 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
198 this.currentPHPString = 0;
199 PHPParserSuperclass.fileToParse = fileToParse;
202 this.token = TokenNameEOF;
204 // this.rowCount = 1;
205 // this.columnCount = 0;
209 this.initializeScanner();
212 public void initializeScanner() {
213 this.scanner = new Scanner(false, false, false, false);
216 * Create marker for the parse error
218 private void setMarker(String message, int charStart, int charEnd, int errorLevel) throws CoreException {
219 setMarker(fileToParse, message, charStart, charEnd, errorLevel);
223 * This method will throw the SyntaxError.
224 * It will add the good lines and columns to the Error
225 * @param error the error message
226 * @throws SyntaxError the error raised
228 private void throwSyntaxError(String error) {
230 // if (str.length() < chIndx) {
233 // // read until end-of-line
235 // while (str.length() > eol) {
236 // ch = str.charAt(eol++);
242 // throw new SyntaxError(
244 // chIndx - columnCount + 1,
245 // str.substring(columnCount, eol),
247 throw new SyntaxError(1, 1, "", error);
251 * This method will throw the SyntaxError.
252 * It will add the good lines and columns to the Error
253 * @param error the error message
254 * @throws SyntaxError the error raised
256 private void throwSyntaxError(String error, int startRow) {
257 throw new SyntaxError(startRow, 0, " ", error);
260 private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
261 problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, compilationUnit.compilationResult);
262 throw new SyntaxError(1, 0, " ", error);
265 * Method Declaration.
269 // private void getChar() {
270 // if (str.length() > chIndx) {
271 // ch = str.charAt(chIndx++);
276 // chIndx = str.length() + 1;
278 // // token = TokenNameEOF;
283 * gets the next token from input
285 private void getNextToken() throws CoreException {
287 token = scanner.getNextToken();
289 int currentEndPosition = scanner.getCurrentTokenEndPosition();
290 int currentStartPosition = scanner.getCurrentTokenStartPosition();
292 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
293 System.out.println(scanner.toStringAction(token));
295 } catch (InvalidInputException e) {
296 token = TokenNameERROR;
304 * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
305 * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
306 * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
307 * value {@link Parser#TokenNameINT_NUMBER}
309 // private void getNumber() {
310 // StringBuffer inum = new StringBuffer();
312 // int numFormat = 10;
314 // // save first digit
315 // char firstCh = ch;
319 // // determine number conversions:
320 // if (firstCh == '0') {
349 // if (numFormat == 16) {
350 // while ((ch >= '0' && ch <= '9')
351 // || (ch >= 'a' && ch <= 'f')
352 // || (ch >= 'A' && ch <= 'F')) {
357 // while ((ch >= '0' && ch <= '9')
361 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
362 // if (ch == '.' && dFlag != ' ') {
365 // if ((dFlag == 'E') || (dFlag == 'e')) {
371 // if ((ch == '-') || (ch == '+')) {
384 // if (dFlag != ' ') {
385 // doubleNumber = new Double(inum.toString());
386 // token = TokenNameDoubleLiteral;
389 // longNumber = Long.valueOf(inum.toString(), numFormat);
390 // token = TokenNameIntegerLiteral;
394 // } catch (Throwable e) {
395 // throwSyntaxError("Number format error: " + inum.toString());
401 // * @param openChar the opening char ('\'', '"', '`')
402 // * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
403 // * @param errorMsg the error message in case of parse error in the string
405 // private void getString(
406 // final char openChar,
407 // final int typeString,
408 // final String errorMsg) {
409 // StringBuffer sBuffer = new StringBuffer();
410 // boolean openString = true;
411 // int startRow = rowCount;
412 // while (str.length() > chIndx) {
413 // ch = str.charAt(chIndx++);
415 // sBuffer.append(ch);
416 // if (str.length() > chIndx) {
417 // ch = str.charAt(chIndx++);
418 // sBuffer.append(ch);
420 // } else if (ch == openChar) {
421 // openString = false;
423 // } else if (ch == '\n') {
425 // columnCount = chIndx;
427 // sBuffer.append(ch);
431 // if (typeString == TokenNameStringConstant) {
432 // throwSyntaxError(errorMsg, startRow);
434 // throwSyntaxError(errorMsg);
437 // token = typeString;
438 // stringValue = sBuffer.toString();
441 // public void htmlParserTester(String input) {
442 // int lineNumber = 1;
443 // int startLineNumber = 1;
444 // int startIndex = 0;
447 // boolean phpMode = false;
448 // boolean phpFound = false;
450 // phpList = new ArrayList();
451 // currentPHPString = 0;
455 // while (i < input.length()) {
456 // ch = input.charAt(i++);
460 // if ((!phpMode) && ch == '<') {
461 // ch2 = input.charAt(i++);
463 // ch2 = input.charAt(i++);
464 // if (Character.isWhitespace(ch2)) {
469 // startLineNumber = lineNumber;
471 // } else if (ch2 == 'p') {
472 // ch2 = input.charAt(i++);
474 // ch2 = input.charAt(i++);
479 // startLineNumber = lineNumber;
485 // } else if (ch2 == 'P') {
486 // ch2 = input.charAt(i++);
488 // ch2 = input.charAt(i++);
493 // startLineNumber = lineNumber;
506 // if (ch == '/' && i < input.length()) {
507 // ch2 = input.charAt(i++);
509 // while (i < input.length()) {
510 // ch = input.charAt(i++);
511 // if (ch == '?' && i < input.length()) {
512 // ch2 = input.charAt(i++);
521 // startLineNumber));
525 // } else if (ch == '\n') {
531 // } else if (ch2 == '*') {
532 // // multi-line comment
533 // while (i < input.length()) {
534 // ch = input.charAt(i++);
537 // } else if (ch == '*' && i < input.length()) {
538 // ch2 = input.charAt(i++);
549 // } else if (ch == '#') {
550 // while (i < input.length()) {
551 // ch = input.charAt(i++);
552 // if (ch == '?' && i < input.length()) {
553 // ch2 = input.charAt(i++);
559 // input.substring(startIndex, i - 2),
560 // startLineNumber));
564 // } else if (ch == '\n') {
570 // } else if (ch == '"') {
572 // while (i < input.length()) {
573 // ch = input.charAt(i++);
577 // ch == '\\' && i < input.length()) { // escape
579 // } else if (ch == '"') {
584 // } else if (ch == '\'') {
586 // while (i < input.length()) {
587 // ch = input.charAt(i++);
591 // ch == '\\' && i < input.length()) { // escape
593 // } else if (ch == '\'') {
600 // if (ch == '?' && i < input.length()) {
601 // ch2 = input.charAt(i++);
607 // input.substring(startIndex, i - 2),
608 // startLineNumber));
618 // "No PHP source code found.",
624 // "Open PHP tag at end of file.",
629 // input.substring(startIndex, i - 2),
630 // startLineNumber));
632 // // for (int j=0;j<phpList.size();j++) {
633 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
634 // // int startIndx = temp.length()-10;
635 // // if (startIndx<0) {
638 // // System.out.println(temp.substring(startIndx)+"?>");
640 // phpParserTester(null, 1);
641 // // PHPString temp;
642 // // for(int j=0;j<phpList.size();j++) {
643 // // temp = (PHPString) phpList.get(j);
644 // // parser.start(temp.getPHPString(), temp.getLineNumber());
647 // } catch (CoreException e) {
651 public void phpParserTester(String s, int rowCount) throws CoreException {
654 if (phpList.size() != 0) {
655 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
658 this.token = TokenNameEOF;
660 // this.rowCount = rowCount;
661 // this.columnCount = 0;
664 scanner.setSource(s.toCharArray());
665 scanner.setPHPMode(true);
669 if (token != TokenNameEOF && token != TokenNameERROR) {
672 if (token != TokenNameEOF) {
673 if (token == TokenNameERROR) {
674 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
676 if (token == TokenNameRPAREN) {
677 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
679 if (token == TokenNameRBRACE) {
680 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
682 if (token == TokenNameRBRACKET) {
683 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
686 if (token == TokenNameLPAREN) {
687 throwSyntaxError("Read character '('; end-of-file not reached.");
689 if (token == TokenNameLBRACE) {
690 throwSyntaxError("Read character '{'; end-of-file not reached.");
692 if (token == TokenNameLBRACKET) {
693 throwSyntaxError("Read character '['; end-of-file not reached.");
696 throwSyntaxError("End-of-file not reached.");
699 } catch (SyntaxError err) {
703 // setMarker(err.getMessage(), err.getLine(), ERROR);
704 setMarker(err.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
706 // if an error occured,
707 // try to find keywords 'class' or 'function'
708 // to parse the rest of the string
709 while (token != TokenNameEOF && token != TokenNameERROR) {
710 if (token == TokenNameclass || token == TokenNamefunction) {
715 if (token == TokenNameEOF || token == TokenNameERROR) {
722 public void init(String s) {
724 this.token = TokenNameEOF;
726 // this.rowCount = 1;
727 // this.columnCount = 0;
729 this.phpMode = false;
730 /* scanner initialization */
731 scanner.setSource(s.toCharArray());
732 scanner.setPHPMode(false);
735 protected void initialize() {
736 compilationUnit = null;
737 referenceContext = null;
739 this.token = TokenNameEOF;
741 // this.rowCount = 1;
742 // this.columnCount = 0;
744 this.phpMode = false;
745 scanner.setPHPMode(false);
748 * Parses a string with php tags
749 * i.e. '<body> <?php phpinfo() ?> </body>'
751 public void parse(String s) throws CoreException {
757 * Parses a string with php tags
758 * i.e. '<body> <?php phpinfo() ?> </body>'
760 protected void parse() throws CoreException {
764 if (token != TokenNameEOF && token != TokenNameERROR) {
767 if (token != TokenNameEOF) {
768 if (token == TokenNameERROR) {
769 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
771 if (token == TokenNameRPAREN) {
772 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
774 if (token == TokenNameRBRACE) {
775 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
777 if (token == TokenNameRBRACKET) {
778 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
781 if (token == TokenNameLPAREN) {
782 throwSyntaxError("Read character '('; end-of-file not reached.");
784 if (token == TokenNameLBRACE) {
785 throwSyntaxError("Read character '{'; end-of-file not reached.");
787 if (token == TokenNameLBRACKET) {
788 throwSyntaxError("Read character '['; end-of-file not reached.");
791 throwSyntaxError("End-of-file not reached.");
794 } catch (SyntaxError sytaxErr1) {
795 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
796 setMarker(sytaxErr1.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
798 // if an error occured,
799 // try to find keywords 'class' or 'function'
800 // to parse the rest of the string
801 while (token != TokenNameEOF && token != TokenNameERROR) {
802 if (token == TokenNameclass || token == TokenNamefunction) {
807 if (token == TokenNameEOF || token == TokenNameERROR) {
810 } catch (SyntaxError sytaxErr2) {
811 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
812 setMarker(sytaxErr2.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
820 public PHPOutlineInfo parseInfo(Object parent, String s) {
821 PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
822 // Stack stack = new Stack();
823 // stack.push(outlineInfo.getDeclarations());
826 this.token = TokenNameEOF;
828 // this.rowCount = 1;
829 // this.columnCount = 0;
831 this.phpMode = false;
832 scanner.setSource(s.toCharArray());
833 scanner.setPHPMode(false);
837 parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
838 } catch (CoreException e) {
843 private boolean isVariable() {
844 return token == TokenNameVariable || token == TokenNamethis;
847 private void parseDeclarations(PHPOutlineInfo outlineInfo, OutlineableWithChildren current, boolean goBack) {
849 // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
850 PHPSegmentWithChildren temp;
853 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
855 while (token != TokenNameEOF && token != TokenNameERROR) {
856 if (token == TokenNameVariable) {
857 ident = scanner.getCurrentIdentifierSource();
858 outlineInfo.addVariable(new String(ident));
860 } else if (token == TokenNamevar) {
862 if (token == TokenNameVariable && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
863 ident = scanner.getCurrentIdentifierSource();
864 //substring(1) added because PHPVarDeclaration doesn't need the $ anymore
865 String variableName = new String(ident).substring(1);
866 outlineInfo.addVariable(variableName);
868 if (token != TokenNameSEMICOLON) {
871 ident = scanner.getCurrentTokenSource();
872 if (token > TokenNameKEYWORD) {
873 current.add(new PHPVarDeclaration(current, variableName,
874 // chIndx - ident.length,
875 scanner.getCurrentTokenStartPosition(), new String(ident)));
878 case TokenNameVariable :
880 current.add(new PHPVarDeclaration(current, variableName,
881 // chIndx - ident.length,
882 scanner.getCurrentTokenStartPosition(), new String(ident)));
884 case TokenNameIdentifier :
885 current.add(new PHPVarDeclaration(current, variableName,
886 // chIndx - ident.length,
887 scanner.getCurrentTokenStartPosition(), new String(ident)));
889 case TokenNameDoubleLiteral :
890 current.add(new PHPVarDeclaration(current, variableName + doubleNumber,
891 // chIndx - ident.length,
892 scanner.getCurrentTokenStartPosition(), new String(ident)));
894 case TokenNameIntegerLiteral :
895 current.add(new PHPVarDeclaration(current, variableName,
896 // chIndx - ident.length,
897 scanner.getCurrentTokenStartPosition(), new String(ident)));
899 case TokenNameStringInterpolated :
900 case TokenNameStringLiteral :
901 current.add(new PHPVarDeclaration(current, variableName,
902 // chIndx - ident.length,
903 scanner.getCurrentTokenStartPosition(), new String(ident)));
905 case TokenNameStringConstant :
906 current.add(new PHPVarDeclaration(current, variableName,
907 // chIndx - ident.length,
908 scanner.getCurrentTokenStartPosition(), new String(ident)));
911 current.add(new PHPVarDeclaration(current, variableName,
912 // chIndx - ident.length
913 scanner.getCurrentTokenStartPosition()));
919 ident = scanner.getCurrentIdentifierSource();
921 current.add(new PHPVarDeclaration(current, variableName,
922 // chIndx - ident.length
923 scanner.getCurrentTokenStartPosition()));
926 } else if (token == TokenNamefunction) {
928 if (token == TokenNameAND) {
931 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
932 ident = scanner.getCurrentIdentifierSource();
933 outlineInfo.addVariable(new String(ident));
934 temp = new PHPFunctionDeclaration(current, new String(ident),
935 // chIndx - ident.length
936 scanner.getCurrentTokenStartPosition());
939 parseDeclarations(outlineInfo, temp, true);
941 } else if (token == TokenNameclass) {
943 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
944 ident = scanner.getCurrentIdentifierSource();
945 outlineInfo.addVariable(new String(ident));
946 temp = new PHPClassDeclaration(current, new String(ident),
947 // chIndx - ident.len
948 scanner.getCurrentTokenStartPosition());
953 //skip tokens for classname, extends and others until we have the opening '{'
954 while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) {
957 parseDeclarations(outlineInfo, temp, true);
960 } else if ((token == TokenNameLBRACE) || (token == TokenNameDOLLAR_LBRACE)) {
963 } else if (token == TokenNameRBRACE) {
966 if (counter == 0 && goBack) {
969 } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) {
970 ident = scanner.getCurrentTokenSource();
973 int startPosition = scanner.getCurrentTokenStartPosition();
975 char[] expr = scanner.getCurrentTokenSource(startPosition);
976 outlineInfo.addVariable(new String(ident));
977 current.add(new PHPReqIncDeclaration(current, new String(ident),
978 // chIndx - ident.length,
979 startPosition, new String(expr)));
985 } catch (CoreException e) {
986 } catch (SyntaxError sytaxErr) {
988 // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
989 setMarker(sytaxErr.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
990 } catch (CoreException e) {
995 private void statementList() throws CoreException {
997 statement(TokenNameEOF);
998 if ((token == TokenNameRBRACE)
999 || (token == TokenNamecase)
1000 || (token == TokenNamedefault)
1001 || (token == TokenNameelse)
1002 || (token == TokenNameelseif)
1003 || (token == TokenNameendif)
1004 || (token == TokenNameendfor)
1005 || (token == TokenNameendforeach)
1006 || (token == TokenNameendwhile)
1007 || (token == TokenNameendswitch)
1008 || (token == TokenNameEOF)
1009 || (token == TokenNameERROR)) {
1015 private void functionBody(MethodDeclaration methodDecl) throws CoreException {
1016 // '{' [statement-list] '}'
1017 if (token == TokenNameLBRACE) {
1020 throwSyntaxError("'{' expected in compound-statement.");
1022 if (token != TokenNameRBRACE) {
1025 if (token == TokenNameRBRACE) {
1026 methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1029 throwSyntaxError("'}' expected in compound-statement.");
1033 private void statement(int previousToken) throws CoreException {
1034 // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
1035 // char[] ident = scanner.getCurrentIdentifierSource();
1036 // String keyword = new String(ident);
1037 if (token == TokenNameAT) {
1039 if (token != TokenNamerequire
1040 && token != TokenNamerequire_once
1041 && token != TokenNameinclude
1042 && token != TokenNameinclude_once
1043 && token != TokenNameIdentifier
1044 && token != TokenNameVariable
1045 && token != TokenNamethis
1046 && token != TokenNameStringInterpolated) {
1047 throwSyntaxError("identifier expected after '@'.");
1050 if (token == TokenNameinclude || token == TokenNameinclude_once) {
1052 if (token == TokenNameLPAREN) {
1054 if (token == TokenNameSEMICOLON) {
1057 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
1058 throwSyntaxError("';' expected after 'include' or 'include_once'.");
1063 concatenationExpression();
1067 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1070 if (token == TokenNameLPAREN) {
1072 if (token == TokenNameSEMICOLON) {
1075 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
1076 throwSyntaxError("';' expected after 'require' or 'require_once'.");
1081 concatenationExpression();
1084 } else if (token == TokenNameif) {
1086 if (token == TokenNameLPAREN) {
1089 throwSyntaxError("'(' expected after 'if' keyword.");
1092 if (token == TokenNameRPAREN) {
1095 throwSyntaxError("')' expected after 'if' condition.");
1100 } else if (token == TokenNameswitch) {
1102 if (token == TokenNameLPAREN) {
1105 throwSyntaxError("'(' expected after 'switch' keyword.");
1108 if (token == TokenNameRPAREN) {
1111 throwSyntaxError("')' expected after 'switch' condition.");
1115 } else if (token == TokenNamefor) {
1117 if (token == TokenNameLPAREN) {
1120 throwSyntaxError("'(' expected after 'for' keyword.");
1122 if (token == TokenNameSEMICOLON) {
1126 if (token == TokenNameSEMICOLON) {
1129 throwSyntaxError("';' expected after 'for'.");
1132 if (token == TokenNameSEMICOLON) {
1136 if (token == TokenNameSEMICOLON) {
1139 throwSyntaxError("';' expected after 'for'.");
1142 if (token == TokenNameRPAREN) {
1146 if (token == TokenNameRPAREN) {
1149 throwSyntaxError("')' expected after 'for'.");
1154 } else if (token == TokenNamewhile) {
1156 if (token == TokenNameLPAREN) {
1159 throwSyntaxError("'(' expected after 'while' keyword.");
1162 if (token == TokenNameRPAREN) {
1165 throwSyntaxError("')' expected after 'while' condition.");
1169 } else if (token == TokenNamedo) {
1171 if (token == TokenNameLBRACE) {
1174 throwSyntaxError("'{' expected after 'do' keyword.");
1176 if (token != TokenNameRBRACE) {
1179 if (token == TokenNameRBRACE) {
1182 throwSyntaxError("'}' expected after 'do' keyword.");
1184 if (token == TokenNamewhile) {
1186 if (token == TokenNameLPAREN) {
1189 throwSyntaxError("'(' expected after 'while' keyword.");
1192 if (token == TokenNameRPAREN) {
1195 throwSyntaxError("')' expected after 'while' condition.");
1198 throwSyntaxError("'while' expected after 'do' keyword.");
1200 if (token == TokenNameSEMICOLON) {
1203 if (token != TokenNameStopPHP) {
1204 throwSyntaxError("';' expected after do-while statement.");
1209 } else if (token == TokenNameforeach) {
1211 if (token == TokenNameLPAREN) {
1214 throwSyntaxError("'(' expected after 'foreach' keyword.");
1217 if (token == TokenNameas) {
1220 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1223 if (token == TokenNameEQUAL_GREATER) {
1227 if (token == TokenNameRPAREN) {
1230 throwSyntaxError("')' expected after 'foreach' expression.");
1235 } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
1237 if (token != TokenNameSEMICOLON) {
1240 if (token == TokenNameSEMICOLON) {
1243 if (token != TokenNameStopPHP) {
1244 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1250 } else if (token == TokenNameecho) {
1253 if (token == TokenNameSEMICOLON) {
1256 if (token != TokenNameStopPHP) {
1257 throwSyntaxError("';' expected after 'echo' statement.");
1262 // } else if (token == TokenNameprint) {
1265 // if (token == TokenNameSEMICOLON) {
1268 // if (token != TokenNameStopPHP) {
1269 // throwSyntaxError("';' expected after 'print' statement.");
1275 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1278 if (token == TokenNameSEMICOLON) {
1281 if (token != TokenNameStopPHP) {
1282 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1288 // } else if (token == TokenNameunset) {
1290 // if (token == TokenNameARGOPEN) {
1293 // throwSyntaxError("'(' expected after 'unset' keyword.");
1296 // if (token == TokenNameARGCLOSE) {
1299 // throwSyntaxError("')' expected after 'unset' statement.");
1301 // if (token == TokenNameSEMICOLON) {
1304 // if (token != TokenNameStopPHP) {
1305 // throwSyntaxError("';' expected after 'unset' statement.");
1311 // } else if (token == TokenNameexit || token == TokenNamedie) {
1313 // if (token != TokenNameSEMICOLON) {
1316 // if (token == TokenNameSEMICOLON) {
1319 // if (token != TokenNameStopPHP) {
1320 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1326 } else if (token == TokenNamedefine) {
1328 if (token == TokenNameLPAREN) {
1331 throwSyntaxError("'(' expected after 'define' keyword.");
1334 if (token == TokenNameCOMMA) {
1337 throwSyntaxError("',' expected after first 'define' constant.");
1340 if (token == TokenNameCOMMA) {
1344 if (token == TokenNameRPAREN) {
1347 throwSyntaxError("')' expected after 'define' statement.");
1349 if (token == TokenNameSEMICOLON) {
1352 if (token != TokenNameStopPHP) {
1353 throwSyntaxError("';' expected after 'define' statement.");
1358 } else if (token == TokenNamefunction) {
1359 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1360 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1362 functionDefinition(methodDecl);
1364 } else if (token == TokenNameclass) {
1365 TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
1366 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1367 // default super class
1368 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1369 compilationUnit.types.add(typeDecl);
1371 pushOnAstStack(typeDecl);
1373 classDeclarator(typeDecl);
1374 classBody(typeDecl);
1381 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1382 } else if (token == TokenNameLBRACE) {
1384 if (token != TokenNameRBRACE) {
1387 if (token == TokenNameRBRACE) {
1391 throwSyntaxError("'}' expected.");
1394 if (token != TokenNameSEMICOLON) {
1397 if (token == TokenNameSEMICOLON) {
1401 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1402 throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
1409 private void classDeclarator(TypeDeclaration typeDecl) throws CoreException {
1411 //identifier 'extends' identifier
1413 if (token == TokenNameIdentifier) {
1414 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1415 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1416 typeDecl.name = scanner.getCurrentIdentifierSource();
1418 if (token == TokenNameextends) {
1421 if (token == TokenNameIdentifier) {
1424 reportSyntaxError("Class name expected after keyword 'extends'.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1425 // throwSyntaxError("ClassDeclaration name expected after keyword 'extends'.");
1427 } while (token == TokenNameCOMMA);
1430 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1431 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1433 if (token > TokenNameKEYWORD) {
1434 typeDecl.name = scanner.getCurrentIdentifierSource();
1436 "Don't use keyword for class declaration [" + scanner.toStringAction(token) + "].",
1437 typeDecl.sourceStart,
1438 typeDecl.sourceEnd);
1439 // throwSyntaxError("Don't use keyword for class declaration [" + token + "].");
1441 typeDecl.name = new char[] { ' ' };
1442 reportSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1443 // throwSyntaxError("ClassDeclaration name expected after keyword 'class'.");
1447 private void classBody(TypeDeclaration typeDecl) throws CoreException {
1448 //'{' [class-element-list] '}'
1449 if (token == TokenNameLBRACE) {
1451 if (token != TokenNameRBRACE) {
1454 if (token == TokenNameRBRACE) {
1455 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1458 throwSyntaxError("'}' expected at end of class body.");
1461 throwSyntaxError("'{' expected at start of class body.");
1465 private void classElementList() throws CoreException {
1468 } while (token == TokenNamefunction || token == TokenNamevar);
1471 private void classElement() throws CoreException {
1473 //function-definition
1474 if (token == TokenNamefunction) {
1475 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1476 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1478 functionDefinition(methodDecl);
1479 } else if (token == TokenNamevar) {
1483 throwSyntaxError("'function' or 'var' expected.");
1487 private void classProperty() throws CoreException {
1488 //'var' variable ';'
1489 //'var' variable '=' constant ';'
1491 if (token == TokenNameVariable) {
1493 if (token == TokenNameEQUAL) {
1498 if (token == TokenNamethis) {
1499 throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1501 throwSyntaxError("Variable expected after keyword 'var'.");
1503 if (token != TokenNameCOMMA) {
1508 if (token == TokenNameSEMICOLON) {
1511 throwSyntaxError("';' expected after variable declaration.");
1515 private void functionDefinition(MethodDeclaration methodDecl) throws CoreException {
1517 compilationUnit.types.add(methodDecl);
1519 AstNode node = astStack[astPtr];
1520 if (node instanceof TypeDeclaration) {
1521 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1522 if (typeDecl.methods == null) {
1523 typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
1525 AbstractMethodDeclaration[] newMethods;
1526 System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, typeDecl.methods.length);
1527 newMethods[0] = methodDecl;
1528 typeDecl.methods = newMethods;
1532 functionDeclarator(methodDecl);
1533 functionBody(methodDecl);
1536 private void functionDeclarator(MethodDeclaration methodDecl) throws CoreException {
1537 //identifier '(' [parameter-list] ')'
1538 if (token == TokenNameAND) {
1541 if (token == TokenNameIdentifier) {
1542 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1543 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1544 methodDecl.selector = scanner.getCurrentIdentifierSource();
1546 if (token == TokenNameLPAREN) {
1549 throwSyntaxError("'(' expected in function declaration.");
1551 if (token != TokenNameRPAREN) {
1554 if (token != TokenNameRPAREN) {
1555 throwSyntaxError("')' expected in function declaration.");
1557 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1561 if (token > TokenNameKEYWORD) {
1562 throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
1564 throwSyntaxError("Function name expected after keyword 'function'.");
1568 private void parameterList() throws CoreException {
1569 //parameter-declaration
1570 //parameter-list ',' parameter-declaration
1572 parameterDeclaration();
1573 if (token != TokenNameCOMMA) {
1580 private void parameterDeclaration() throws CoreException {
1582 //variable-reference
1583 if (token == TokenNameAND) {
1588 throwSyntaxError("Variable expected after reference operator '&'.");
1591 //variable '=' constant
1592 if (token == TokenNameVariable) {
1594 if (token == TokenNameEQUAL) {
1600 if (token == TokenNamethis) {
1601 throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1605 private void labeledStatementList() throws CoreException {
1606 if (token != TokenNamecase && token != TokenNamedefault) {
1607 throwSyntaxError("'case' or 'default' expected.");
1610 if (token == TokenNamecase) {
1612 expression(); //constant();
1613 if (token == TokenNameCOLON) {
1615 if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
1619 } else if (token == TokenNameSEMICOLON) {
1621 // "':' expected after 'case' keyword (Found token: "
1622 // + scanner.toStringAction(token)
1627 "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")",
1628 scanner.getCurrentTokenStartPosition(),
1629 scanner.getCurrentTokenEndPosition(),
1632 if (token == TokenNamecase) { // empty case statement ?
1637 throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
1639 } else { // TokenNamedefault
1641 if (token == TokenNameCOLON) {
1645 throwSyntaxError("':' character after 'default' expected.");
1648 } while (token == TokenNamecase || token == TokenNamedefault);
1651 // public void labeledStatement() {
1652 // if (token == TokenNamecase) {
1655 // if (token == TokenNameDDOT) {
1659 // throwSyntaxError("':' character after 'case' constant expected.");
1662 // } else if (token == TokenNamedefault) {
1664 // if (token == TokenNameDDOT) {
1668 // throwSyntaxError("':' character after 'default' expected.");
1674 // public void expressionStatement() {
1677 // private void inclusionStatement() {
1680 // public void compoundStatement() {
1683 // public void selectionStatement() {
1686 // public void iterationStatement() {
1689 // public void jumpStatement() {
1692 // public void outputStatement() {
1695 // public void scopeStatement() {
1698 // public void flowStatement() {
1701 // public void definitionStatement() {
1704 private void ifStatement() throws CoreException {
1705 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1706 if (token == TokenNameCOLON) {
1708 if (token != TokenNameendif) {
1711 case TokenNameelse :
1713 if (token == TokenNameCOLON) {
1715 if (token != TokenNameendif) {
1719 if (token == TokenNameif) { //'else if'
1721 elseifStatementList();
1723 throwSyntaxError("':' expected after 'else'.");
1727 case TokenNameelseif :
1729 elseifStatementList();
1734 if (token != TokenNameendif) {
1735 throwSyntaxError("'endif' expected.");
1738 if (token != TokenNameSEMICOLON) {
1739 throwSyntaxError("';' expected after if-statement.");
1743 // statement [else-statement]
1744 statement(TokenNameEOF);
1745 if (token == TokenNameelseif) {
1747 if (token == TokenNameLPAREN) {
1750 throwSyntaxError("'(' expected after 'elseif' keyword.");
1753 if (token == TokenNameRPAREN) {
1756 throwSyntaxError("')' expected after 'elseif' condition.");
1759 } else if (token == TokenNameelse) {
1761 statement(TokenNameEOF);
1766 private void elseifStatementList() throws CoreException {
1770 case TokenNameelse :
1772 if (token == TokenNameCOLON) {
1774 if (token != TokenNameendif) {
1779 if (token == TokenNameif) { //'else if'
1782 throwSyntaxError("':' expected after 'else'.");
1786 case TokenNameelseif :
1795 private void elseifStatement() throws CoreException {
1796 if (token == TokenNameLPAREN) {
1799 if (token != TokenNameRPAREN) {
1800 throwSyntaxError("')' expected in else-if-statement.");
1803 if (token != TokenNameCOLON) {
1804 throwSyntaxError("':' expected in else-if-statement.");
1807 if (token != TokenNameendif) {
1813 private void switchStatement() throws CoreException {
1814 if (token == TokenNameCOLON) {
1815 // ':' [labeled-statement-list] 'endswitch' ';'
1817 labeledStatementList();
1818 if (token != TokenNameendswitch) {
1819 throwSyntaxError("'endswitch' expected.");
1822 if (token != TokenNameSEMICOLON) {
1823 throwSyntaxError("';' expected after switch-statement.");
1827 // '{' [labeled-statement-list] '}'
1828 if (token != TokenNameLBRACE) {
1829 throwSyntaxError("'{' expected in switch statement.");
1832 if (token != TokenNameRBRACE) {
1833 labeledStatementList();
1835 if (token != TokenNameRBRACE) {
1836 throwSyntaxError("'}' expected in switch statement.");
1843 private void forStatement() throws CoreException {
1844 if (token == TokenNameCOLON) {
1847 if (token != TokenNameendfor) {
1848 throwSyntaxError("'endfor' expected.");
1851 if (token != TokenNameSEMICOLON) {
1852 throwSyntaxError("';' expected after for-statement.");
1856 statement(TokenNameEOF);
1860 private void whileStatement() throws CoreException {
1861 // ':' statement-list 'endwhile' ';'
1862 if (token == TokenNameCOLON) {
1865 if (token != TokenNameendwhile) {
1866 throwSyntaxError("'endwhile' expected.");
1869 if (token != TokenNameSEMICOLON) {
1870 throwSyntaxError("';' expected after while-statement.");
1874 statement(TokenNameEOF);
1878 private void foreachStatement() throws CoreException {
1879 if (token == TokenNameCOLON) {
1882 if (token != TokenNameendforeach) {
1883 throwSyntaxError("'endforeach' expected.");
1886 if (token != TokenNameSEMICOLON) {
1887 throwSyntaxError("';' expected after foreach-statement.");
1891 statement(TokenNameEOF);
1895 private void exitStatus() throws CoreException {
1896 if (token == TokenNameLPAREN) {
1899 throwSyntaxError("'(' expected in 'exit-status'.");
1901 if (token != TokenNameRPAREN) {
1904 if (token == TokenNameRPAREN) {
1907 throwSyntaxError("')' expected after 'exit-status'.");
1911 private void expressionList() throws CoreException {
1914 if (token == TokenNameCOMMA) {
1922 private void expression() throws CoreException {
1923 //todo: find a better way to get the expression
1924 // expression = new StringBuffer();
1925 // for (int i = chIndx; i < str.length(); i++) {
1926 // if (str.charAt(i) == ';') {
1929 // expression.append(str.charAt(i));
1932 // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
1935 logicalinclusiveorExpression();
1936 // while (token != TokenNameSEMICOLON) {
1942 private void postfixExpression() throws CoreException {
1945 boolean castFlag = false;
1946 boolean arrayFlag = false;
1952 case TokenNamenull :
1955 case TokenNamefalse :
1958 case TokenNametrue :
1961 case TokenNameStringConstant :
1964 case TokenNameHEREDOC :
1965 case TokenNameStringInterpolated :
1966 case TokenNameStringLiteral :
1969 case TokenNameLPAREN :
1972 if (token == TokenNameIdentifier) {
1973 // check if identifier is a type:
1974 // ident = identifier;
1975 ident = scanner.getCurrentIdentifierSource();
1976 String str = new String(ident).toLowerCase();
1977 for (int i = 0; i < PHP_TYPES.length; i++) {
1978 if (PHP_TYPES[i].equals(str)) {
1980 if (PHP_TYPES[i].equals("array")) {
1990 if (arrayFlag && token == TokenNameLPAREN) {
1992 if (token == TokenNameRPAREN) {
1996 if (token != TokenNameRPAREN) {
1997 throwSyntaxError(") expected after 'array('.");
2001 if (token != TokenNameRPAREN) {
2002 throwSyntaxError(") expected after cast-type '" + str + "'.");
2010 if (token != TokenNameRPAREN) {
2011 throwSyntaxError(") expected in postfix-expression.");
2015 case TokenNameDoubleLiteral :
2018 case TokenNameIntegerLiteral :
2021 case TokenNameDOLLAR_LBRACE :
2024 if (token != TokenNameRBRACE) {
2025 throwSyntaxError("'}' expected after indirect variable token '${'.");
2029 case TokenNameVariable :
2030 case TokenNamethis :
2031 ident = scanner.getCurrentIdentifierSource();
2033 if (token == TokenNameLBRACE) {
2036 if (token != TokenNameRBRACE) {
2037 throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression.");
2040 } else if (token == TokenNameLPAREN) {
2042 if (token != TokenNameRPAREN) {
2044 if (token != TokenNameRPAREN) {
2045 throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression.");
2051 case TokenNameIdentifier :
2052 ident = scanner.getCurrentIdentifierSource();
2054 if (token == TokenNameLPAREN) {
2056 if (token != TokenNameRPAREN) {
2058 if (token != TokenNameRPAREN) {
2060 "')' expected after identifier '" + new String(ident) + "' in postfix-expression." + "(Found token: " + scanner.toStringAction(token) + ")");
2066 case TokenNameprint :
2069 // if (token == TokenNameSEMICOLON) {
2072 // if (token != TokenNameStopPHP) {
2073 // throwSyntaxError("';' expected after 'print' statement.");
2078 case TokenNamelist :
2080 if (token == TokenNameLPAREN) {
2082 if (token == TokenNameCOMMA) {
2086 if (token != TokenNameRPAREN) {
2087 throwSyntaxError("')' expected after 'list' keyword.");
2090 // if (token == TokenNameSET) {
2092 // logicalinclusiveorExpression();
2095 throwSyntaxError("'(' expected after 'list' keyword.");
2098 // case TokenNameexit :
2100 // if (token != TokenNameSEMICOLON) {
2103 // if (token == TokenNameSEMICOLON) {
2106 // if (token != TokenNameStopPHP) {
2107 // throwSyntaxError("';' expected after 'exit' expression.");
2112 // case TokenNamedie :
2114 // if (token != TokenNameSEMICOLON) {
2117 // if (token == TokenNameSEMICOLON) {
2120 // if (token != TokenNameStopPHP) {
2121 // throwSyntaxError("';' expected after 'die' expression.");
2126 // case TokenNamearray :
2128 // if (token == TokenNameARGOPEN) {
2130 // if (token == TokenNameCOMMA) {
2133 // expressionList();
2134 // if (token != TokenNameARGCLOSE) {
2135 // throwSyntaxError("')' expected after 'list' keyword.");
2138 // if (token == TokenNameSET) {
2140 // logicalinclusiveorExpression();
2143 // throwSyntaxError("'(' expected after 'list' keyword.");
2147 boolean while_flag = true;
2150 case TokenNameLBRACKET :
2153 if (token != TokenNameRBRACKET) {
2154 throwSyntaxError("] expected in postfix-expression.");
2158 case TokenNameCOLON_COLON : // ::
2159 case TokenNameMINUS_GREATER : // ->
2161 if (token > TokenNameKEYWORD) {
2162 ident = scanner.getCurrentIdentifierSource();
2164 // "Avoid using keyword '"
2165 // + new String(ident)
2166 // + "' as variable name.",
2170 "Avoid using keyword '" + new String(ident) + "' as variable name.",
2171 scanner.getCurrentTokenStartPosition(),
2172 scanner.getCurrentTokenEndPosition(),
2176 case TokenNameVariable :
2177 ident = scanner.getCurrentIdentifierSource();
2179 // if (token == TokenNameARGOPEN) {
2181 // expressionList();
2182 // if (token != TokenNameARGCLOSE) {
2183 // throwSyntaxError(") expected after variable '" + ident + "'.");
2188 case TokenNameIdentifier :
2189 //ident = scanner.getCurrentIdentifierSource();
2192 case TokenNameLBRACE :
2195 if (token != TokenNameRBRACE) {
2196 throwSyntaxError("} expected in postfix-expression.");
2201 throwSyntaxError("Syntax error after '->' token.");
2202 } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
2203 if (token == TokenNameLBRACKET) {
2206 if (token != TokenNameRBRACKET) {
2207 throwSyntaxError("] expected after '->'.");
2210 } else if (token == TokenNameLPAREN) {
2213 if (token != TokenNameRPAREN) {
2214 throwSyntaxError(") expected after '->'.");
2217 } else if (token == TokenNameLBRACE) {
2220 if (token != TokenNameRBRACE) {
2221 throwSyntaxError("} expected after '->'.");
2227 case TokenNamePLUS_PLUS :
2230 case TokenNameMINUS_MINUS :
2241 private void unaryExpression() throws CoreException {
2243 case TokenNamePLUS_PLUS :
2247 case TokenNameMINUS_MINUS :
2251 // '@' '&' '*' '+' '-' '~' '!'
2254 if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) {
2255 statement(TokenNameAT);
2257 postfixExpression(); // castExpression();
2264 case TokenNameMULTIPLY :
2268 case TokenNamePLUS :
2272 case TokenNameMINUS :
2276 case TokenNameTWIDDLE :
2285 postfixExpression();
2289 private void castExpression() throws CoreException {
2290 // if (token == TokenNameARGOPEN) {
2293 // if (token != TokenNameARGCLOSE) {
2294 // throwSyntaxError(") expected after cast-expression.");
2301 private void assignExpression() throws CoreException {
2303 if (token == TokenNameEQUAL) { // =
2305 logicalinclusiveorExpression();
2306 } else if (token == TokenNameDOT_EQUAL) { // .=
2308 logicalinclusiveorExpression();
2309 } else if (token == TokenNameEQUAL_GREATER) { // =>
2311 logicalinclusiveorExpression();
2312 } else if (token == TokenNamePLUS_EQUAL) { // +=
2314 logicalinclusiveorExpression();
2315 } else if (token == TokenNameMINUS_EQUAL) { // -=
2317 logicalinclusiveorExpression();
2318 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2320 logicalinclusiveorExpression();
2321 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2323 logicalinclusiveorExpression();
2324 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2326 logicalinclusiveorExpression();
2327 } else if (token == TokenNameAND_EQUAL) { // &=
2329 logicalinclusiveorExpression();
2330 } else if (token == TokenNameOR_EQUAL) { // |=
2332 logicalinclusiveorExpression();
2333 } else if (token == TokenNameXOR_EQUAL) { // ^=
2335 logicalinclusiveorExpression();
2336 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2338 logicalinclusiveorExpression();
2339 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2341 logicalinclusiveorExpression();
2342 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2344 logicalinclusiveorExpression();
2348 private void multiplicativeExpression() throws CoreException {
2351 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
2358 private void concatenationExpression() throws CoreException {
2360 multiplicativeExpression();
2361 if (token != TokenNameDOT) {
2368 private void additiveExpression() throws CoreException {
2370 concatenationExpression();
2371 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2378 private void shiftExpression() throws CoreException {
2380 additiveExpression();
2381 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2388 private void relationalExpression() throws CoreException {
2391 if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2398 private void identicalExpression() throws CoreException {
2400 relationalExpression();
2401 if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
2408 private void equalityExpression() throws CoreException {
2410 identicalExpression();
2411 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2418 private void ternaryExpression() throws CoreException {
2419 equalityExpression();
2420 if (token == TokenNameQUESTION) {
2423 if (token == TokenNameCOLON) {
2427 throwSyntaxError("':' expected in ternary operator '? :'.");
2432 private void andExpression() throws CoreException {
2434 ternaryExpression();
2435 if (token != TokenNameAND) {
2442 private void exclusiveorExpression() throws CoreException {
2445 if (token != TokenNameXOR) {
2452 private void inclusiveorExpression() throws CoreException {
2454 exclusiveorExpression();
2455 if (token != TokenNameOR) {
2462 private void booleanandExpression() throws CoreException {
2464 inclusiveorExpression();
2465 if (token != TokenNameAND_AND) {
2472 private void booleanorExpression() throws CoreException {
2474 booleanandExpression();
2475 if (token != TokenNameOR_OR) {
2482 private void logicalandExpression() throws CoreException {
2484 booleanorExpression();
2485 if (token != TokenNameAND) {
2492 private void logicalexclusiveorExpression() throws CoreException {
2494 logicalandExpression();
2495 if (token != TokenNameXOR) {
2502 private void logicalinclusiveorExpression() throws CoreException {
2504 logicalexclusiveorExpression();
2505 if (token != TokenNameOR) {
2512 // public void assignmentExpression() {
2513 // if (token == TokenNameVARIABLE) {
2515 // if (token == TokenNameSET) {
2517 // logicalinclusiveorExpression();
2520 // logicalinclusiveorExpression();
2524 private void variableList() throws CoreException {
2527 if (token == TokenNameCOMMA) {
2535 private void variable() throws CoreException {
2536 if (token == TokenNameDOLLAR_LBRACE) {
2540 if (token != TokenNameRBRACE) {
2541 throwSyntaxError("'}' expected after indirect variable token '${'.");
2545 if (token == TokenNameVariable) {
2547 if (token == TokenNameLBRACKET) {
2550 if (token != TokenNameRBRACKET) {
2551 throwSyntaxError("']' expected in variable-list.");
2554 } else if (token == TokenNameEQUAL) {
2559 throwSyntaxError("$-variable expected in variable-list.");
2565 * It will look for a value (after a '=' for example)
2566 * @throws CoreException
2568 private void constant() throws CoreException {
2571 case TokenNamePLUS :
2574 case TokenNameDoubleLiteral :
2577 case TokenNameIntegerLiteral :
2581 throwSyntaxError("Constant expected after '+' presign.");
2584 case TokenNameMINUS :
2587 case TokenNameDoubleLiteral :
2590 case TokenNameIntegerLiteral :
2594 throwSyntaxError("Constant expected after '-' presign.");
2597 case TokenNamenull :
2600 case TokenNamefalse :
2603 case TokenNametrue :
2606 case TokenNameIdentifier :
2607 // ident = identifier;
2608 char[] ident = scanner.getCurrentIdentifierSource();
2610 if (token == TokenNameLPAREN) {
2612 if (token != TokenNameRPAREN) {
2614 if (token != TokenNameRPAREN) {
2615 throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression.");
2621 case TokenNameStringLiteral :
2624 case TokenNameStringConstant :
2627 case TokenNameStringInterpolated :
2630 case TokenNameDoubleLiteral :
2633 case TokenNameIntegerLiteral :
2637 throwSyntaxError("Constant expected.");
2641 public void reportSyntaxError() { //int act, int currentKind, int stateStackTop) {
2643 /* remember current scanner position */
2644 int startPos = scanner.startPosition;
2645 int currentPos = scanner.currentPosition;
2647 // String[] expectings;
2648 // String tokenName = name[symbol_index[currentKind]];
2650 //fetch all "accurate" possible terminals that could recover the error
2651 // int start, end = start = asi(stack[stateStackTop]);
2652 // while (asr[end] != 0)
2654 // int length = end - start;
2655 // expectings = new String[length];
2656 // if (length != 0) {
2657 // char[] indexes = new char[length];
2658 // System.arraycopy(asr, start, indexes, 0, length);
2659 // for (int i = 0; i < length; i++) {
2660 // expectings[i] = name[symbol_index[indexes[i]]];
2664 //if the pb is an EOF, try to tell the user that they are some
2665 // if (tokenName.equals(UNEXPECTED_EOF)) {
2666 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2667 // char[] tokenSource;
2669 // tokenSource = this.scanner.getCurrentTokenSource();
2670 // } catch (Exception e) {
2671 // tokenSource = new char[] {};
2673 // problemReporter().parseError(
2674 // this.scanner.startPosition,
2675 // this.scanner.currentPosition - 1,
2680 // } else { //the next test is HEAVILY grammar DEPENDENT.
2681 // if ((length == 14)
2682 // && (expectings[0] == "=") //$NON-NLS-1$
2683 // && (expectings[1] == "*=") //$NON-NLS-1$
2684 // && (expressionPtr > -1)) {
2685 // switch(currentKind) {
2686 // case TokenNameSEMICOLON:
2687 // case TokenNamePLUS:
2688 // case TokenNameMINUS:
2689 // case TokenNameDIVIDE:
2690 // case TokenNameREMAINDER:
2691 // case TokenNameMULTIPLY:
2692 // case TokenNameLEFT_SHIFT:
2693 // case TokenNameRIGHT_SHIFT:
2694 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
2695 // case TokenNameLESS:
2696 // case TokenNameGREATER:
2697 // case TokenNameLESS_EQUAL:
2698 // case TokenNameGREATER_EQUAL:
2699 // case TokenNameEQUAL_EQUAL:
2700 // case TokenNameNOT_EQUAL:
2701 // case TokenNameXOR:
2702 // case TokenNameAND:
2703 // case TokenNameOR:
2704 // case TokenNameOR_OR:
2705 // case TokenNameAND_AND:
2706 // // the ; is not the expected token ==> it ends a statement when an expression is not ended
2707 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
2709 // case TokenNameRBRACE :
2710 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
2713 // char[] tokenSource;
2715 // tokenSource = this.scanner.getCurrentTokenSource();
2716 // } catch (Exception e) {
2717 // tokenSource = new char[] {};
2719 // problemReporter().parseError(
2720 // this.scanner.startPosition,
2721 // this.scanner.currentPosition - 1,
2725 // this.checkAndReportBracketAnomalies(problemReporter());
2730 tokenSource = this.scanner.getCurrentTokenSource();
2731 } catch (Exception e) {
2732 tokenSource = new char[] {
2735 // problemReporter().parseError(
2736 // this.scanner.startPosition,
2737 // this.scanner.currentPosition - 1,
2741 this.checkAndReportBracketAnomalies(problemReporter());
2744 /* reset scanner where it was */
2745 scanner.startPosition = startPos;
2746 scanner.currentPosition = currentPos;
2748 public static final int RoundBracket = 0;
2749 public static final int SquareBracket = 1;
2750 public static final int CurlyBracket = 2;
2751 public static final int BracketKinds = 3;
2753 protected int[] nestedMethod; //the ptr is nestedType
2754 protected int nestedType, dimensions;
2756 final static int AstStackIncrement = 100;
2757 protected int astPtr;
2758 protected AstNode[] astStack = new AstNode[AstStackIncrement];
2759 protected int astLengthPtr;
2760 protected int[] astLengthStack;
2761 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
2763 public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
2764 protected ReferenceContext referenceContext;
2765 protected ProblemReporter problemReporter;
2766 // protected CompilationResult compilationResult;
2769 * Returns this parser's problem reporter initialized with its reference context.
2770 * Also it is assumed that a problem is going to be reported, so initializes
2771 * the compilation result's line positions.
2773 public ProblemReporter problemReporter() {
2774 if (scanner.recordLineSeparator) {
2775 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
2777 problemReporter.referenceContext = referenceContext;
2778 return problemReporter;
2781 * Reconsider the entire source looking for inconsistencies in {} () []
2783 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
2785 scanner.wasAcr = false;
2786 boolean anomaliesDetected = false;
2788 char[] source = scanner.source;
2789 int[] leftCount = { 0, 0, 0 };
2790 int[] rightCount = { 0, 0, 0 };
2791 int[] depths = { 0, 0, 0 };
2792 int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] };
2793 int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] };
2794 int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] };
2795 int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] };
2796 scanner.currentPosition = scanner.initialPosition; //starting point (first-zero-based char)
2797 while (scanner.currentPosition < scanner.eofPosition) { //loop for jumping over comments
2799 // ---------Consume white space and handles startPosition---------
2800 boolean isWhiteSpace;
2802 scanner.startPosition = scanner.currentPosition;
2803 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2804 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
2806 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
2807 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
2808 // only record line positions we have not recorded yet
2809 scanner.pushLineSeparator();
2812 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
2814 } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
2816 // -------consume token until } is found---------
2818 switch (scanner.currentCharacter) {
2821 int index = leftCount[CurlyBracket]++;
2822 if (index == leftPositions[CurlyBracket].length) {
2823 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
2824 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
2826 leftPositions[CurlyBracket][index] = scanner.startPosition;
2827 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
2832 int index = rightCount[CurlyBracket]++;
2833 if (index == rightPositions[CurlyBracket].length) {
2834 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
2835 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
2837 rightPositions[CurlyBracket][index] = scanner.startPosition;
2838 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
2843 int index = leftCount[RoundBracket]++;
2844 if (index == leftPositions[RoundBracket].length) {
2845 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
2846 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
2848 leftPositions[RoundBracket][index] = scanner.startPosition;
2849 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
2854 int index = rightCount[RoundBracket]++;
2855 if (index == rightPositions[RoundBracket].length) {
2856 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
2857 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
2859 rightPositions[RoundBracket][index] = scanner.startPosition;
2860 rightDepths[RoundBracket][index] = --depths[RoundBracket];
2865 int index = leftCount[SquareBracket]++;
2866 if (index == leftPositions[SquareBracket].length) {
2867 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
2868 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
2870 leftPositions[SquareBracket][index] = scanner.startPosition;
2871 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
2876 int index = rightCount[SquareBracket]++;
2877 if (index == rightPositions[SquareBracket].length) {
2878 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
2879 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
2881 rightPositions[SquareBracket][index] = scanner.startPosition;
2882 rightDepths[SquareBracket][index] = --depths[SquareBracket];
2887 if (scanner.getNextChar('\\')) {
2888 scanner.scanEscapeCharacter();
2889 } else { // consume next character
2890 scanner.unicodeAsBackSlash = false;
2891 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2892 // scanner.getNextUnicodeChar();
2894 if (scanner.withoutUnicodePtr != 0) {
2895 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2899 scanner.getNextChar('\'');
2902 case '"' : // consume next character
2903 scanner.unicodeAsBackSlash = false;
2904 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2905 // scanner.getNextUnicodeChar();
2907 if (scanner.withoutUnicodePtr != 0) {
2908 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2911 while (scanner.currentCharacter != '"') {
2912 if (scanner.currentCharacter == '\r') {
2913 if (source[scanner.currentPosition] == '\n')
2914 scanner.currentPosition++;
2915 break; // the string cannot go further that the line
2917 if (scanner.currentCharacter == '\n') {
2918 break; // the string cannot go further that the line
2920 if (scanner.currentCharacter == '\\') {
2921 scanner.scanEscapeCharacter();
2923 // consume next character
2924 scanner.unicodeAsBackSlash = false;
2925 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2926 // scanner.getNextUnicodeChar();
2928 if (scanner.withoutUnicodePtr != 0) {
2929 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2937 if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment
2939 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2940 //-------------unicode traitement ------------
2941 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2942 scanner.currentPosition++;
2943 while (source[scanner.currentPosition] == 'u') {
2944 scanner.currentPosition++;
2946 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2948 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2950 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2952 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2953 || c4 < 0) { //error don't care of the value
2954 scanner.currentCharacter = 'A';
2955 } //something different from \n and \r
2957 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2960 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
2962 scanner.startPosition = scanner.currentPosition;
2963 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2964 //-------------unicode traitement ------------
2965 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2966 scanner.currentPosition++;
2967 while (source[scanner.currentPosition] == 'u') {
2968 scanner.currentPosition++;
2970 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2972 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2974 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2976 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2977 || c4 < 0) { //error don't care of the value
2978 scanner.currentCharacter = 'A';
2979 } //something different from \n and \r
2981 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2985 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
2986 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
2987 // only record line positions we have not recorded yet
2988 scanner.pushLineSeparator();
2989 if (this.scanner.taskTags != null) {
2990 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
2996 if (test > 0) { //traditional and annotation comment
2997 boolean star = false;
2998 // consume next character
2999 scanner.unicodeAsBackSlash = false;
3000 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
3001 // scanner.getNextUnicodeChar();
3003 if (scanner.withoutUnicodePtr != 0) {
3004 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3007 if (scanner.currentCharacter == '*') {
3011 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
3012 //-------------unicode traitement ------------
3013 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3014 scanner.currentPosition++;
3015 while (source[scanner.currentPosition] == 'u') {
3016 scanner.currentPosition++;
3018 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3020 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3022 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3024 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3025 || c4 < 0) { //error don't care of the value
3026 scanner.currentCharacter = 'A';
3027 } //something different from * and /
3029 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3032 //loop until end of comment */
3033 while ((scanner.currentCharacter != '/') || (!star)) {
3034 star = scanner.currentCharacter == '*';
3036 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
3037 //-------------unicode traitement ------------
3038 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3039 scanner.currentPosition++;
3040 while (source[scanner.currentPosition] == 'u') {
3041 scanner.currentPosition++;
3043 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3045 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3047 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3049 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3050 || c4 < 0) { //error don't care of the value
3051 scanner.currentCharacter = 'A';
3052 } //something different from * and /
3054 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3058 if (this.scanner.taskTags != null) {
3059 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
3066 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3067 scanner.scanIdentifierOrKeyword(false);
3070 if (Character.isDigit(scanner.currentCharacter)) {
3071 scanner.scanNumber(false);
3075 //-----------------end switch while try--------------------
3076 } catch (IndexOutOfBoundsException e) {
3077 break; // read until EOF
3078 } catch (InvalidInputException e) {
3079 return false; // no clue
3082 if (scanner.recordLineSeparator) {
3083 // compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3086 // check placement anomalies against other kinds of brackets
3087 for (int kind = 0; kind < BracketKinds; kind++) {
3088 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3089 int start = leftPositions[kind][leftIndex]; // deepest first
3090 // find matching closing bracket
3091 int depth = leftDepths[kind][leftIndex];
3093 for (int i = 0; i < rightCount[kind]; i++) {
3094 int pos = rightPositions[kind][i];
3095 // want matching bracket further in source with same depth
3096 if ((pos > start) && (depth == rightDepths[kind][i])) {
3101 if (end < 0) { // did not find a good closing match
3102 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
3105 // check if even number of opening/closing other brackets in between this pair of brackets
3107 for (int otherKind = 0;(balance == 0) && (otherKind < BracketKinds); otherKind++) {
3108 for (int i = 0; i < leftCount[otherKind]; i++) {
3109 int pos = leftPositions[otherKind][i];
3110 if ((pos > start) && (pos < end))
3113 for (int i = 0; i < rightCount[otherKind]; i++) {
3114 int pos = rightPositions[otherKind][i];
3115 if ((pos > start) && (pos < end))
3119 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly
3124 // too many opening brackets ?
3125 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3126 anomaliesDetected = true;
3127 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, compilationUnit.compilationResult);
3129 // too many closing brackets ?
3130 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3131 anomaliesDetected = true;
3132 problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
3134 if (anomaliesDetected)
3138 return anomaliesDetected;
3139 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3140 return anomaliesDetected;
3141 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3142 return anomaliesDetected;
3146 protected void pushOnAstLengthStack(int pos) {
3148 astLengthStack[++astLengthPtr] = pos;
3149 } catch (IndexOutOfBoundsException e) {
3150 int oldStackLength = astLengthStack.length;
3151 int[] oldPos = astLengthStack;
3152 astLengthStack = new int[oldStackLength + StackIncrement];
3153 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3154 astLengthStack[astLengthPtr] = pos;
3158 protected void pushOnAstStack(AstNode node) {
3159 /*add a new obj on top of the ast stack
3160 astPtr points on the top*/
3163 astStack[++astPtr] = node;
3164 } catch (IndexOutOfBoundsException e) {
3165 int oldStackLength = astStack.length;
3166 AstNode[] oldStack = astStack;
3167 astStack = new AstNode[oldStackLength + AstStackIncrement];
3168 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3169 astPtr = oldStackLength;
3170 astStack[astPtr] = node;
3174 astLengthStack[++astLengthPtr] = 1;
3175 } catch (IndexOutOfBoundsException e) {
3176 int oldStackLength = astLengthStack.length;
3177 int[] oldPos = astLengthStack;
3178 astLengthStack = new int[oldStackLength + AstStackIncrement];
3179 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3180 astLengthStack[astLengthPtr] = 1;