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 == TokenNameinclude || token == TokenNameinclude_once) {
1039 if (token == TokenNameLPAREN) {
1041 if (token == TokenNameSEMICOLON) {
1044 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
1045 throwSyntaxError("';' expected after 'include' or 'include_once'.");
1050 concatenationExpression();
1054 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1057 if (token == TokenNameLPAREN) {
1059 if (token == TokenNameSEMICOLON) {
1062 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
1063 throwSyntaxError("';' expected after 'require' or 'require_once'.");
1068 concatenationExpression();
1071 } else if (token == TokenNameif) {
1073 if (token == TokenNameLPAREN) {
1076 throwSyntaxError("'(' expected after 'if' keyword.");
1079 if (token == TokenNameRPAREN) {
1082 throwSyntaxError("')' expected after 'if' condition.");
1087 } else if (token == TokenNameswitch) {
1089 if (token == TokenNameLPAREN) {
1092 throwSyntaxError("'(' expected after 'switch' keyword.");
1095 if (token == TokenNameRPAREN) {
1098 throwSyntaxError("')' expected after 'switch' condition.");
1102 } else if (token == TokenNamefor) {
1104 if (token == TokenNameLPAREN) {
1107 throwSyntaxError("'(' expected after 'for' keyword.");
1109 if (token == TokenNameSEMICOLON) {
1113 if (token == TokenNameSEMICOLON) {
1116 throwSyntaxError("';' expected after 'for'.");
1119 if (token == TokenNameSEMICOLON) {
1123 if (token == TokenNameSEMICOLON) {
1126 throwSyntaxError("';' expected after 'for'.");
1129 if (token == TokenNameRPAREN) {
1133 if (token == TokenNameRPAREN) {
1136 throwSyntaxError("')' expected after 'for'.");
1141 } else if (token == TokenNamewhile) {
1143 if (token == TokenNameLPAREN) {
1146 throwSyntaxError("'(' expected after 'while' keyword.");
1149 if (token == TokenNameRPAREN) {
1152 throwSyntaxError("')' expected after 'while' condition.");
1156 } else if (token == TokenNamedo) {
1158 if (token == TokenNameLBRACE) {
1161 throwSyntaxError("'{' expected after 'do' keyword.");
1163 if (token != TokenNameRBRACE) {
1166 if (token == TokenNameRBRACE) {
1169 throwSyntaxError("'}' expected after 'do' keyword.");
1171 if (token == TokenNamewhile) {
1173 if (token == TokenNameLPAREN) {
1176 throwSyntaxError("'(' expected after 'while' keyword.");
1179 if (token == TokenNameRPAREN) {
1182 throwSyntaxError("')' expected after 'while' condition.");
1185 throwSyntaxError("'while' expected after 'do' keyword.");
1187 if (token == TokenNameSEMICOLON) {
1190 if (token != TokenNameStopPHP) {
1191 throwSyntaxError("';' expected after do-while statement.");
1196 } else if (token == TokenNameforeach) {
1198 if (token == TokenNameLPAREN) {
1201 throwSyntaxError("'(' expected after 'foreach' keyword.");
1204 if (token == TokenNameas) {
1207 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1210 if (token == TokenNameEQUAL_GREATER) {
1214 if (token == TokenNameRPAREN) {
1217 throwSyntaxError("')' expected after 'foreach' expression.");
1222 } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
1224 if (token != TokenNameSEMICOLON) {
1227 if (token == TokenNameSEMICOLON) {
1230 if (token != TokenNameStopPHP) {
1231 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1237 } else if (token == TokenNameecho) {
1240 if (token == TokenNameSEMICOLON) {
1243 if (token != TokenNameStopPHP) {
1244 throwSyntaxError("';' expected after 'echo' statement.");
1249 // } else if (token == TokenNameprint) {
1252 // if (token == TokenNameSEMICOLON) {
1255 // if (token != TokenNameStopPHP) {
1256 // throwSyntaxError("';' expected after 'print' statement.");
1262 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1265 if (token == TokenNameSEMICOLON) {
1268 if (token != TokenNameStopPHP) {
1269 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1275 // } else if (token == TokenNameunset) {
1277 // if (token == TokenNameARGOPEN) {
1280 // throwSyntaxError("'(' expected after 'unset' keyword.");
1283 // if (token == TokenNameARGCLOSE) {
1286 // throwSyntaxError("')' expected after 'unset' statement.");
1288 // if (token == TokenNameSEMICOLON) {
1291 // if (token != TokenNameStopPHP) {
1292 // throwSyntaxError("';' expected after 'unset' statement.");
1298 // } else if (token == TokenNameexit || token == TokenNamedie) {
1300 // if (token != TokenNameSEMICOLON) {
1303 // if (token == TokenNameSEMICOLON) {
1306 // if (token != TokenNameStopPHP) {
1307 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1313 } else if (token == TokenNamedefine) {
1315 if (token == TokenNameLPAREN) {
1318 throwSyntaxError("'(' expected after 'define' keyword.");
1321 if (token == TokenNameCOMMA) {
1324 throwSyntaxError("',' expected after first 'define' constant.");
1327 if (token == TokenNameCOMMA) {
1331 if (token == TokenNameRPAREN) {
1334 throwSyntaxError("')' expected after 'define' statement.");
1336 if (token == TokenNameSEMICOLON) {
1339 if (token != TokenNameStopPHP) {
1340 throwSyntaxError("';' expected after 'define' statement.");
1345 } else if (token == TokenNamefunction) {
1346 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1347 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1349 functionDefinition(methodDecl);
1351 } else if (token == TokenNameclass) {
1352 TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
1353 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1354 // default super class
1355 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1356 compilationUnit.types.add(typeDecl);
1358 pushOnAstStack(typeDecl);
1360 classDeclarator(typeDecl);
1361 classBody(typeDecl);
1368 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1369 } else if (token == TokenNameLBRACE) {
1371 if (token != TokenNameRBRACE) {
1374 if (token == TokenNameRBRACE) {
1378 throwSyntaxError("'}' expected.");
1381 if (token != TokenNameSEMICOLON) {
1384 if (token == TokenNameSEMICOLON) {
1388 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1389 throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
1396 private void classDeclarator(TypeDeclaration typeDecl) throws CoreException {
1398 //identifier 'extends' identifier
1400 if (token == TokenNameIdentifier) {
1401 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1402 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1403 typeDecl.name = scanner.getCurrentIdentifierSource();
1405 if (token == TokenNameextends) {
1408 if (token == TokenNameIdentifier) {
1411 reportSyntaxError("Class name expected after keyword 'extends'.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1412 // throwSyntaxError("ClassDeclaration name expected after keyword 'extends'.");
1414 } while (token == TokenNameCOMMA);
1417 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1418 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1420 if (token > TokenNameKEYWORD) {
1421 typeDecl.name = scanner.getCurrentIdentifierSource();
1423 "Don't use keyword for class declaration [" + scanner.toStringAction(token) + "].",
1424 typeDecl.sourceStart,
1425 typeDecl.sourceEnd);
1426 // throwSyntaxError("Don't use keyword for class declaration [" + token + "].");
1428 typeDecl.name = new char[] { ' ' };
1429 reportSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1430 // throwSyntaxError("ClassDeclaration name expected after keyword 'class'.");
1434 private void classBody(TypeDeclaration typeDecl) throws CoreException {
1435 //'{' [class-element-list] '}'
1436 if (token == TokenNameLBRACE) {
1438 if (token != TokenNameRBRACE) {
1441 if (token == TokenNameRBRACE) {
1442 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1445 throwSyntaxError("'}' expected at end of class body.");
1448 throwSyntaxError("'{' expected at start of class body.");
1452 private void classElementList() throws CoreException {
1455 } while (token == TokenNamefunction || token == TokenNamevar);
1458 private void classElement() throws CoreException {
1460 //function-definition
1461 if (token == TokenNamefunction) {
1462 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1463 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1465 functionDefinition(methodDecl);
1466 } else if (token == TokenNamevar) {
1470 throwSyntaxError("'function' or 'var' expected.");
1474 private void classProperty() throws CoreException {
1475 //'var' variable ';'
1476 //'var' variable '=' constant ';'
1478 if (token == TokenNameVariable) {
1480 if (token == TokenNameEQUAL) {
1485 if (token == TokenNamethis) {
1486 throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1488 throwSyntaxError("Variable expected after keyword 'var'.");
1490 if (token != TokenNameCOMMA) {
1495 if (token == TokenNameSEMICOLON) {
1498 throwSyntaxError("';' expected after variable declaration.");
1502 private void functionDefinition(MethodDeclaration methodDecl) throws CoreException {
1504 compilationUnit.types.add(methodDecl);
1506 AstNode node = astStack[astPtr];
1507 if (node instanceof TypeDeclaration) {
1508 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1509 if (typeDecl.methods == null) {
1510 typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
1512 AbstractMethodDeclaration[] newMethods;
1513 System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, typeDecl.methods.length);
1514 newMethods[0] = methodDecl;
1515 typeDecl.methods = newMethods;
1519 functionDeclarator(methodDecl);
1520 functionBody(methodDecl);
1523 private void functionDeclarator(MethodDeclaration methodDecl) throws CoreException {
1524 //identifier '(' [parameter-list] ')'
1525 if (token == TokenNameAND) {
1528 if (token == TokenNameIdentifier) {
1529 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1530 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1531 methodDecl.selector = scanner.getCurrentIdentifierSource();
1533 if (token == TokenNameLPAREN) {
1536 throwSyntaxError("'(' expected in function declaration.");
1538 if (token != TokenNameRPAREN) {
1541 if (token != TokenNameRPAREN) {
1542 throwSyntaxError("')' expected in function declaration.");
1544 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1548 if (token > TokenNameKEYWORD) {
1549 throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
1551 throwSyntaxError("Function name expected after keyword 'function'.");
1555 private void parameterList() throws CoreException {
1556 //parameter-declaration
1557 //parameter-list ',' parameter-declaration
1559 parameterDeclaration();
1560 if (token != TokenNameCOMMA) {
1567 private void parameterDeclaration() throws CoreException {
1569 //variable-reference
1570 if (token == TokenNameAND) {
1575 throwSyntaxError("Variable expected after reference operator '&'.");
1578 //variable '=' constant
1579 if (token == TokenNameVariable) {
1581 if (token == TokenNameEQUAL) {
1587 if (token == TokenNamethis) {
1588 throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1592 private void labeledStatementList() throws CoreException {
1593 if (token != TokenNamecase && token != TokenNamedefault) {
1594 throwSyntaxError("'case' or 'default' expected.");
1597 if (token == TokenNamecase) {
1599 expression(); //constant();
1600 if (token == TokenNameCOLON) {
1602 if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
1606 } else if (token == TokenNameSEMICOLON) {
1608 // "':' expected after 'case' keyword (Found token: "
1609 // + scanner.toStringAction(token)
1614 "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")",
1615 scanner.getCurrentTokenStartPosition(),
1616 scanner.getCurrentTokenEndPosition(),
1619 if (token == TokenNamecase) { // empty case statement ?
1624 throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
1626 } else { // TokenNamedefault
1628 if (token == TokenNameCOLON) {
1632 throwSyntaxError("':' character after 'default' expected.");
1635 } while (token == TokenNamecase || token == TokenNamedefault);
1638 // public void labeledStatement() {
1639 // if (token == TokenNamecase) {
1642 // if (token == TokenNameDDOT) {
1646 // throwSyntaxError("':' character after 'case' constant expected.");
1649 // } else if (token == TokenNamedefault) {
1651 // if (token == TokenNameDDOT) {
1655 // throwSyntaxError("':' character after 'default' expected.");
1661 // public void expressionStatement() {
1664 // private void inclusionStatement() {
1667 // public void compoundStatement() {
1670 // public void selectionStatement() {
1673 // public void iterationStatement() {
1676 // public void jumpStatement() {
1679 // public void outputStatement() {
1682 // public void scopeStatement() {
1685 // public void flowStatement() {
1688 // public void definitionStatement() {
1691 private void ifStatement() throws CoreException {
1692 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1693 if (token == TokenNameCOLON) {
1695 if (token != TokenNameendif) {
1698 case TokenNameelse :
1700 if (token == TokenNameCOLON) {
1702 if (token != TokenNameendif) {
1706 if (token == TokenNameif) { //'else if'
1708 elseifStatementList();
1710 throwSyntaxError("':' expected after 'else'.");
1714 case TokenNameelseif :
1716 elseifStatementList();
1721 if (token != TokenNameendif) {
1722 throwSyntaxError("'endif' expected.");
1725 if (token != TokenNameSEMICOLON) {
1726 throwSyntaxError("';' expected after if-statement.");
1730 // statement [else-statement]
1731 statement(TokenNameEOF);
1732 if (token == TokenNameelseif) {
1734 if (token == TokenNameLPAREN) {
1737 throwSyntaxError("'(' expected after 'elseif' keyword.");
1740 if (token == TokenNameRPAREN) {
1743 throwSyntaxError("')' expected after 'elseif' condition.");
1746 } else if (token == TokenNameelse) {
1748 statement(TokenNameEOF);
1753 private void elseifStatementList() throws CoreException {
1757 case TokenNameelse :
1759 if (token == TokenNameCOLON) {
1761 if (token != TokenNameendif) {
1766 if (token == TokenNameif) { //'else if'
1769 throwSyntaxError("':' expected after 'else'.");
1773 case TokenNameelseif :
1782 private void elseifStatement() throws CoreException {
1783 if (token == TokenNameLPAREN) {
1786 if (token != TokenNameRPAREN) {
1787 throwSyntaxError("')' expected in else-if-statement.");
1790 if (token != TokenNameCOLON) {
1791 throwSyntaxError("':' expected in else-if-statement.");
1794 if (token != TokenNameendif) {
1800 private void switchStatement() throws CoreException {
1801 if (token == TokenNameCOLON) {
1802 // ':' [labeled-statement-list] 'endswitch' ';'
1804 labeledStatementList();
1805 if (token != TokenNameendswitch) {
1806 throwSyntaxError("'endswitch' expected.");
1809 if (token != TokenNameSEMICOLON) {
1810 throwSyntaxError("';' expected after switch-statement.");
1814 // '{' [labeled-statement-list] '}'
1815 if (token != TokenNameLBRACE) {
1816 throwSyntaxError("'{' expected in switch statement.");
1819 if (token != TokenNameRBRACE) {
1820 labeledStatementList();
1822 if (token != TokenNameRBRACE) {
1823 throwSyntaxError("'}' expected in switch statement.");
1830 private void forStatement() throws CoreException {
1831 if (token == TokenNameCOLON) {
1834 if (token != TokenNameendfor) {
1835 throwSyntaxError("'endfor' expected.");
1838 if (token != TokenNameSEMICOLON) {
1839 throwSyntaxError("';' expected after for-statement.");
1843 statement(TokenNameEOF);
1847 private void whileStatement() throws CoreException {
1848 // ':' statement-list 'endwhile' ';'
1849 if (token == TokenNameCOLON) {
1852 if (token != TokenNameendwhile) {
1853 throwSyntaxError("'endwhile' expected.");
1856 if (token != TokenNameSEMICOLON) {
1857 throwSyntaxError("';' expected after while-statement.");
1861 statement(TokenNameEOF);
1865 private void foreachStatement() throws CoreException {
1866 if (token == TokenNameCOLON) {
1869 if (token != TokenNameendforeach) {
1870 throwSyntaxError("'endforeach' expected.");
1873 if (token != TokenNameSEMICOLON) {
1874 throwSyntaxError("';' expected after foreach-statement.");
1878 statement(TokenNameEOF);
1882 private void exitStatus() throws CoreException {
1883 if (token == TokenNameLPAREN) {
1886 throwSyntaxError("'(' expected in 'exit-status'.");
1888 if (token != TokenNameRPAREN) {
1891 if (token == TokenNameRPAREN) {
1894 throwSyntaxError("')' expected after 'exit-status'.");
1898 private void expressionList() throws CoreException {
1901 if (token == TokenNameCOMMA) {
1909 private void expression() throws CoreException {
1910 //todo: find a better way to get the expression
1911 // expression = new StringBuffer();
1912 // for (int i = chIndx; i < str.length(); i++) {
1913 // if (str.charAt(i) == ';') {
1916 // expression.append(str.charAt(i));
1919 // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
1922 logicalinclusiveorExpression();
1923 // while (token != TokenNameSEMICOLON) {
1929 private void postfixExpression() throws CoreException {
1932 boolean castFlag = false;
1933 boolean arrayFlag = false;
1939 case TokenNamenull :
1942 case TokenNamefalse :
1945 case TokenNametrue :
1948 case TokenNameStringConstant :
1951 case TokenNameHEREDOC :
1952 case TokenNameStringInterpolated :
1953 case TokenNameStringLiteral :
1956 case TokenNameLPAREN :
1959 if (token == TokenNameIdentifier) {
1960 // check if identifier is a type:
1961 // ident = identifier;
1962 ident = scanner.getCurrentIdentifierSource();
1963 String str = new String(ident).toLowerCase();
1964 for (int i = 0; i < PHP_TYPES.length; i++) {
1965 if (PHP_TYPES[i].equals(str)) {
1967 if (PHP_TYPES[i].equals("array")) {
1977 if (arrayFlag && token == TokenNameLPAREN) {
1979 if (token == TokenNameRPAREN) {
1983 if (token != TokenNameRPAREN) {
1984 throwSyntaxError(") expected after 'array('.");
1988 if (token != TokenNameRPAREN) {
1989 throwSyntaxError(") expected after cast-type '" + str + "'.");
1997 if (token != TokenNameRPAREN) {
1998 throwSyntaxError(") expected in postfix-expression.");
2002 case TokenNameDoubleLiteral :
2005 case TokenNameIntegerLiteral :
2008 case TokenNameDOLLAR_LBRACE :
2011 if (token != TokenNameRBRACE) {
2012 throwSyntaxError("'}' expected after indirect variable token '${'.");
2016 case TokenNameVariable :
2017 case TokenNamethis :
2018 ident = scanner.getCurrentIdentifierSource();
2020 if (token == TokenNameLBRACE) {
2023 if (token != TokenNameRBRACE) {
2024 throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression.");
2027 } else if (token == TokenNameLPAREN) {
2029 if (token != TokenNameRPAREN) {
2031 if (token != TokenNameRPAREN) {
2032 throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression.");
2038 case TokenNameIdentifier :
2039 ident = scanner.getCurrentIdentifierSource();
2041 if (token == TokenNameLPAREN) {
2043 if (token != TokenNameRPAREN) {
2045 if (token != TokenNameRPAREN) {
2047 "')' expected after identifier '" + new String(ident) + "' in postfix-expression." + "(Found token: " + scanner.toStringAction(token) + ")");
2053 case TokenNameprint :
2056 // if (token == TokenNameSEMICOLON) {
2059 // if (token != TokenNameStopPHP) {
2060 // throwSyntaxError("';' expected after 'print' statement.");
2065 case TokenNamelist :
2067 if (token == TokenNameLPAREN) {
2069 if (token == TokenNameCOMMA) {
2073 if (token != TokenNameRPAREN) {
2074 throwSyntaxError("')' expected after 'list' keyword.");
2077 // if (token == TokenNameSET) {
2079 // logicalinclusiveorExpression();
2082 throwSyntaxError("'(' expected after 'list' keyword.");
2085 // case TokenNameexit :
2087 // if (token != TokenNameSEMICOLON) {
2090 // if (token == TokenNameSEMICOLON) {
2093 // if (token != TokenNameStopPHP) {
2094 // throwSyntaxError("';' expected after 'exit' expression.");
2099 // case TokenNamedie :
2101 // if (token != TokenNameSEMICOLON) {
2104 // if (token == TokenNameSEMICOLON) {
2107 // if (token != TokenNameStopPHP) {
2108 // throwSyntaxError("';' expected after 'die' expression.");
2113 // case TokenNamearray :
2115 // if (token == TokenNameARGOPEN) {
2117 // if (token == TokenNameCOMMA) {
2120 // expressionList();
2121 // if (token != TokenNameARGCLOSE) {
2122 // throwSyntaxError("')' expected after 'list' keyword.");
2125 // if (token == TokenNameSET) {
2127 // logicalinclusiveorExpression();
2130 // throwSyntaxError("'(' expected after 'list' keyword.");
2134 boolean while_flag = true;
2137 case TokenNameLBRACKET :
2140 if (token != TokenNameRBRACKET) {
2141 throwSyntaxError("] expected in postfix-expression.");
2145 case TokenNameCOLON_COLON : // ::
2146 case TokenNameMINUS_GREATER : // ->
2148 if (token > TokenNameKEYWORD) {
2149 ident = scanner.getCurrentIdentifierSource();
2151 // "Avoid using keyword '"
2152 // + new String(ident)
2153 // + "' as variable name.",
2157 "Avoid using keyword '" + new String(ident) + "' as variable name.",
2158 scanner.getCurrentTokenStartPosition(),
2159 scanner.getCurrentTokenEndPosition(),
2163 case TokenNameVariable :
2164 ident = scanner.getCurrentIdentifierSource();
2166 // if (token == TokenNameARGOPEN) {
2168 // expressionList();
2169 // if (token != TokenNameARGCLOSE) {
2170 // throwSyntaxError(") expected after variable '" + ident + "'.");
2175 case TokenNameIdentifier :
2176 //ident = scanner.getCurrentIdentifierSource();
2179 case TokenNameLBRACE :
2182 if (token != TokenNameRBRACE) {
2183 throwSyntaxError("} expected in postfix-expression.");
2188 throwSyntaxError("Syntax error after '->' token.");
2189 } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
2190 if (token == TokenNameLBRACKET) {
2193 if (token != TokenNameRBRACKET) {
2194 throwSyntaxError("] expected after '->'.");
2197 } else if (token == TokenNameLPAREN) {
2200 if (token != TokenNameRPAREN) {
2201 throwSyntaxError(") expected after '->'.");
2204 } else if (token == TokenNameLBRACE) {
2207 if (token != TokenNameRBRACE) {
2208 throwSyntaxError("} expected after '->'.");
2214 case TokenNamePLUS_PLUS :
2217 case TokenNameMINUS_MINUS :
2228 private void unaryExpression() throws CoreException {
2230 case TokenNamePLUS_PLUS :
2234 case TokenNameMINUS_MINUS :
2238 // '@' '&' '*' '+' '-' '~' '!'
2241 if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) {
2242 statement(TokenNameAT);
2244 postfixExpression(); // castExpression();
2251 case TokenNameMULTIPLY :
2255 case TokenNamePLUS :
2259 case TokenNameMINUS :
2263 case TokenNameTWIDDLE :
2272 postfixExpression();
2276 private void castExpression() throws CoreException {
2277 // if (token == TokenNameARGOPEN) {
2280 // if (token != TokenNameARGCLOSE) {
2281 // throwSyntaxError(") expected after cast-expression.");
2288 private void assignExpression() throws CoreException {
2290 if (token == TokenNameEQUAL) { // =
2292 logicalinclusiveorExpression();
2293 } else if (token == TokenNameDOT_EQUAL) { // .=
2295 logicalinclusiveorExpression();
2296 } else if (token == TokenNameEQUAL_GREATER) { // =>
2298 logicalinclusiveorExpression();
2299 } else if (token == TokenNamePLUS_EQUAL) { // +=
2301 logicalinclusiveorExpression();
2302 } else if (token == TokenNameMINUS_EQUAL) { // -=
2304 logicalinclusiveorExpression();
2305 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2307 logicalinclusiveorExpression();
2308 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2310 logicalinclusiveorExpression();
2311 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2313 logicalinclusiveorExpression();
2314 } else if (token == TokenNameAND_EQUAL) { // &=
2316 logicalinclusiveorExpression();
2317 } else if (token == TokenNameOR_EQUAL) { // |=
2319 logicalinclusiveorExpression();
2320 } else if (token == TokenNameXOR_EQUAL) { // ^=
2322 logicalinclusiveorExpression();
2323 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2325 logicalinclusiveorExpression();
2326 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2328 logicalinclusiveorExpression();
2329 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2331 logicalinclusiveorExpression();
2335 private void multiplicativeExpression() throws CoreException {
2338 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
2345 private void concatenationExpression() throws CoreException {
2347 multiplicativeExpression();
2348 if (token != TokenNameDOT) {
2355 private void additiveExpression() throws CoreException {
2357 concatenationExpression();
2358 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2365 private void shiftExpression() throws CoreException {
2367 additiveExpression();
2368 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2375 private void relationalExpression() throws CoreException {
2378 if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2385 private void identicalExpression() throws CoreException {
2387 relationalExpression();
2388 if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
2395 private void equalityExpression() throws CoreException {
2397 identicalExpression();
2398 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2405 private void ternaryExpression() throws CoreException {
2406 equalityExpression();
2407 if (token == TokenNameQUESTION) {
2410 if (token == TokenNameCOLON) {
2414 throwSyntaxError("':' expected in ternary operator '? :'.");
2419 private void andExpression() throws CoreException {
2421 ternaryExpression();
2422 if (token != TokenNameAND) {
2429 private void exclusiveorExpression() throws CoreException {
2432 if (token != TokenNameXOR) {
2439 private void inclusiveorExpression() throws CoreException {
2441 exclusiveorExpression();
2442 if (token != TokenNameOR) {
2449 private void booleanandExpression() throws CoreException {
2451 inclusiveorExpression();
2452 if (token != TokenNameAND_AND) {
2459 private void booleanorExpression() throws CoreException {
2461 booleanandExpression();
2462 if (token != TokenNameOR_OR) {
2469 private void logicalandExpression() throws CoreException {
2471 booleanorExpression();
2472 if (token != TokenNameAND) {
2479 private void logicalexclusiveorExpression() throws CoreException {
2481 logicalandExpression();
2482 if (token != TokenNameXOR) {
2489 private void logicalinclusiveorExpression() throws CoreException {
2491 logicalexclusiveorExpression();
2492 if (token != TokenNameOR) {
2499 // public void assignmentExpression() {
2500 // if (token == TokenNameVARIABLE) {
2502 // if (token == TokenNameSET) {
2504 // logicalinclusiveorExpression();
2507 // logicalinclusiveorExpression();
2511 private void variableList() throws CoreException {
2514 if (token == TokenNameCOMMA) {
2522 private void variable() throws CoreException {
2523 if (token == TokenNameDOLLAR_LBRACE) {
2527 if (token != TokenNameRBRACE) {
2528 throwSyntaxError("'}' expected after indirect variable token '${'.");
2532 if (token == TokenNameVariable) {
2534 if (token == TokenNameLBRACKET) {
2537 if (token != TokenNameRBRACKET) {
2538 throwSyntaxError("']' expected in variable-list.");
2541 } else if (token == TokenNameEQUAL) {
2546 throwSyntaxError("$-variable expected in variable-list.");
2552 * It will look for a value (after a '=' for example)
2553 * @throws CoreException
2555 private void constant() throws CoreException {
2558 case TokenNamePLUS :
2561 case TokenNameDoubleLiteral :
2564 case TokenNameIntegerLiteral :
2568 throwSyntaxError("Constant expected after '+' presign.");
2571 case TokenNameMINUS :
2574 case TokenNameDoubleLiteral :
2577 case TokenNameIntegerLiteral :
2581 throwSyntaxError("Constant expected after '-' presign.");
2584 case TokenNamenull :
2587 case TokenNamefalse :
2590 case TokenNametrue :
2593 case TokenNameIdentifier :
2594 // ident = identifier;
2595 char[] ident = scanner.getCurrentIdentifierSource();
2597 if (token == TokenNameLPAREN) {
2599 if (token != TokenNameRPAREN) {
2601 if (token != TokenNameRPAREN) {
2602 throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression.");
2608 case TokenNameStringLiteral :
2611 case TokenNameStringConstant :
2614 case TokenNameStringInterpolated :
2617 case TokenNameDoubleLiteral :
2620 case TokenNameIntegerLiteral :
2624 throwSyntaxError("Constant expected.");
2628 public void reportSyntaxError() { //int act, int currentKind, int stateStackTop) {
2630 /* remember current scanner position */
2631 int startPos = scanner.startPosition;
2632 int currentPos = scanner.currentPosition;
2634 // String[] expectings;
2635 // String tokenName = name[symbol_index[currentKind]];
2637 //fetch all "accurate" possible terminals that could recover the error
2638 // int start, end = start = asi(stack[stateStackTop]);
2639 // while (asr[end] != 0)
2641 // int length = end - start;
2642 // expectings = new String[length];
2643 // if (length != 0) {
2644 // char[] indexes = new char[length];
2645 // System.arraycopy(asr, start, indexes, 0, length);
2646 // for (int i = 0; i < length; i++) {
2647 // expectings[i] = name[symbol_index[indexes[i]]];
2651 //if the pb is an EOF, try to tell the user that they are some
2652 // if (tokenName.equals(UNEXPECTED_EOF)) {
2653 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2654 // char[] tokenSource;
2656 // tokenSource = this.scanner.getCurrentTokenSource();
2657 // } catch (Exception e) {
2658 // tokenSource = new char[] {};
2660 // problemReporter().parseError(
2661 // this.scanner.startPosition,
2662 // this.scanner.currentPosition - 1,
2667 // } else { //the next test is HEAVILY grammar DEPENDENT.
2668 // if ((length == 14)
2669 // && (expectings[0] == "=") //$NON-NLS-1$
2670 // && (expectings[1] == "*=") //$NON-NLS-1$
2671 // && (expressionPtr > -1)) {
2672 // switch(currentKind) {
2673 // case TokenNameSEMICOLON:
2674 // case TokenNamePLUS:
2675 // case TokenNameMINUS:
2676 // case TokenNameDIVIDE:
2677 // case TokenNameREMAINDER:
2678 // case TokenNameMULTIPLY:
2679 // case TokenNameLEFT_SHIFT:
2680 // case TokenNameRIGHT_SHIFT:
2681 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
2682 // case TokenNameLESS:
2683 // case TokenNameGREATER:
2684 // case TokenNameLESS_EQUAL:
2685 // case TokenNameGREATER_EQUAL:
2686 // case TokenNameEQUAL_EQUAL:
2687 // case TokenNameNOT_EQUAL:
2688 // case TokenNameXOR:
2689 // case TokenNameAND:
2690 // case TokenNameOR:
2691 // case TokenNameOR_OR:
2692 // case TokenNameAND_AND:
2693 // // the ; is not the expected token ==> it ends a statement when an expression is not ended
2694 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
2696 // case TokenNameRBRACE :
2697 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
2700 // char[] tokenSource;
2702 // tokenSource = this.scanner.getCurrentTokenSource();
2703 // } catch (Exception e) {
2704 // tokenSource = new char[] {};
2706 // problemReporter().parseError(
2707 // this.scanner.startPosition,
2708 // this.scanner.currentPosition - 1,
2712 // this.checkAndReportBracketAnomalies(problemReporter());
2717 tokenSource = this.scanner.getCurrentTokenSource();
2718 } catch (Exception e) {
2719 tokenSource = new char[] {
2722 // problemReporter().parseError(
2723 // this.scanner.startPosition,
2724 // this.scanner.currentPosition - 1,
2728 this.checkAndReportBracketAnomalies(problemReporter());
2731 /* reset scanner where it was */
2732 scanner.startPosition = startPos;
2733 scanner.currentPosition = currentPos;
2735 public static final int RoundBracket = 0;
2736 public static final int SquareBracket = 1;
2737 public static final int CurlyBracket = 2;
2738 public static final int BracketKinds = 3;
2740 protected int[] nestedMethod; //the ptr is nestedType
2741 protected int nestedType, dimensions;
2743 final static int AstStackIncrement = 100;
2744 protected int astPtr;
2745 protected AstNode[] astStack = new AstNode[AstStackIncrement];
2746 protected int astLengthPtr;
2747 protected int[] astLengthStack;
2748 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
2750 public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
2751 protected ReferenceContext referenceContext;
2752 protected ProblemReporter problemReporter;
2753 // protected CompilationResult compilationResult;
2756 * Returns this parser's problem reporter initialized with its reference context.
2757 * Also it is assumed that a problem is going to be reported, so initializes
2758 * the compilation result's line positions.
2760 public ProblemReporter problemReporter() {
2761 if (scanner.recordLineSeparator) {
2762 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
2764 problemReporter.referenceContext = referenceContext;
2765 return problemReporter;
2768 * Reconsider the entire source looking for inconsistencies in {} () []
2770 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
2772 scanner.wasAcr = false;
2773 boolean anomaliesDetected = false;
2775 char[] source = scanner.source;
2776 int[] leftCount = { 0, 0, 0 };
2777 int[] rightCount = { 0, 0, 0 };
2778 int[] depths = { 0, 0, 0 };
2779 int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] };
2780 int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] };
2781 int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] };
2782 int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] };
2783 scanner.currentPosition = scanner.initialPosition; //starting point (first-zero-based char)
2784 while (scanner.currentPosition < scanner.eofPosition) { //loop for jumping over comments
2786 // ---------Consume white space and handles startPosition---------
2787 boolean isWhiteSpace;
2789 scanner.startPosition = scanner.currentPosition;
2790 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2791 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
2793 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
2794 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
2795 // only record line positions we have not recorded yet
2796 scanner.pushLineSeparator();
2799 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
2801 } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
2803 // -------consume token until } is found---------
2805 switch (scanner.currentCharacter) {
2808 int index = leftCount[CurlyBracket]++;
2809 if (index == leftPositions[CurlyBracket].length) {
2810 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
2811 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
2813 leftPositions[CurlyBracket][index] = scanner.startPosition;
2814 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
2819 int index = rightCount[CurlyBracket]++;
2820 if (index == rightPositions[CurlyBracket].length) {
2821 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
2822 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
2824 rightPositions[CurlyBracket][index] = scanner.startPosition;
2825 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
2830 int index = leftCount[RoundBracket]++;
2831 if (index == leftPositions[RoundBracket].length) {
2832 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
2833 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
2835 leftPositions[RoundBracket][index] = scanner.startPosition;
2836 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
2841 int index = rightCount[RoundBracket]++;
2842 if (index == rightPositions[RoundBracket].length) {
2843 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
2844 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
2846 rightPositions[RoundBracket][index] = scanner.startPosition;
2847 rightDepths[RoundBracket][index] = --depths[RoundBracket];
2852 int index = leftCount[SquareBracket]++;
2853 if (index == leftPositions[SquareBracket].length) {
2854 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
2855 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
2857 leftPositions[SquareBracket][index] = scanner.startPosition;
2858 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
2863 int index = rightCount[SquareBracket]++;
2864 if (index == rightPositions[SquareBracket].length) {
2865 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
2866 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
2868 rightPositions[SquareBracket][index] = scanner.startPosition;
2869 rightDepths[SquareBracket][index] = --depths[SquareBracket];
2874 if (scanner.getNextChar('\\')) {
2875 scanner.scanEscapeCharacter();
2876 } else { // consume next character
2877 scanner.unicodeAsBackSlash = false;
2878 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2879 // scanner.getNextUnicodeChar();
2881 if (scanner.withoutUnicodePtr != 0) {
2882 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2886 scanner.getNextChar('\'');
2889 case '"' : // 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;
2898 while (scanner.currentCharacter != '"') {
2899 if (scanner.currentCharacter == '\r') {
2900 if (source[scanner.currentPosition] == '\n')
2901 scanner.currentPosition++;
2902 break; // the string cannot go further that the line
2904 if (scanner.currentCharacter == '\n') {
2905 break; // the string cannot go further that the line
2907 if (scanner.currentCharacter == '\\') {
2908 scanner.scanEscapeCharacter();
2910 // consume next character
2911 scanner.unicodeAsBackSlash = false;
2912 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2913 // scanner.getNextUnicodeChar();
2915 if (scanner.withoutUnicodePtr != 0) {
2916 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2924 if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment
2926 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2927 //-------------unicode traitement ------------
2928 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2929 scanner.currentPosition++;
2930 while (source[scanner.currentPosition] == 'u') {
2931 scanner.currentPosition++;
2933 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2935 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2937 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2939 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2940 || c4 < 0) { //error don't care of the value
2941 scanner.currentCharacter = 'A';
2942 } //something different from \n and \r
2944 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2947 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
2949 scanner.startPosition = scanner.currentPosition;
2950 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2951 //-------------unicode traitement ------------
2952 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2953 scanner.currentPosition++;
2954 while (source[scanner.currentPosition] == 'u') {
2955 scanner.currentPosition++;
2957 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2959 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2961 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2963 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2964 || c4 < 0) { //error don't care of the value
2965 scanner.currentCharacter = 'A';
2966 } //something different from \n and \r
2968 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2972 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
2973 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
2974 // only record line positions we have not recorded yet
2975 scanner.pushLineSeparator();
2976 if (this.scanner.taskTags != null) {
2977 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
2983 if (test > 0) { //traditional and annotation comment
2984 boolean star = false;
2985 // consume next character
2986 scanner.unicodeAsBackSlash = false;
2987 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2988 // scanner.getNextUnicodeChar();
2990 if (scanner.withoutUnicodePtr != 0) {
2991 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2994 if (scanner.currentCharacter == '*') {
2998 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2999 //-------------unicode traitement ------------
3000 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3001 scanner.currentPosition++;
3002 while (source[scanner.currentPosition] == 'u') {
3003 scanner.currentPosition++;
3005 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3007 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3009 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3011 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3012 || c4 < 0) { //error don't care of the value
3013 scanner.currentCharacter = 'A';
3014 } //something different from * and /
3016 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3019 //loop until end of comment */
3020 while ((scanner.currentCharacter != '/') || (!star)) {
3021 star = scanner.currentCharacter == '*';
3023 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
3024 //-------------unicode traitement ------------
3025 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3026 scanner.currentPosition++;
3027 while (source[scanner.currentPosition] == 'u') {
3028 scanner.currentPosition++;
3030 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3032 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3034 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3036 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3037 || c4 < 0) { //error don't care of the value
3038 scanner.currentCharacter = 'A';
3039 } //something different from * and /
3041 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3045 if (this.scanner.taskTags != null) {
3046 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
3053 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3054 scanner.scanIdentifierOrKeyword(false);
3057 if (Character.isDigit(scanner.currentCharacter)) {
3058 scanner.scanNumber(false);
3062 //-----------------end switch while try--------------------
3063 } catch (IndexOutOfBoundsException e) {
3064 break; // read until EOF
3065 } catch (InvalidInputException e) {
3066 return false; // no clue
3069 if (scanner.recordLineSeparator) {
3070 // compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3073 // check placement anomalies against other kinds of brackets
3074 for (int kind = 0; kind < BracketKinds; kind++) {
3075 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3076 int start = leftPositions[kind][leftIndex]; // deepest first
3077 // find matching closing bracket
3078 int depth = leftDepths[kind][leftIndex];
3080 for (int i = 0; i < rightCount[kind]; i++) {
3081 int pos = rightPositions[kind][i];
3082 // want matching bracket further in source with same depth
3083 if ((pos > start) && (depth == rightDepths[kind][i])) {
3088 if (end < 0) { // did not find a good closing match
3089 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
3092 // check if even number of opening/closing other brackets in between this pair of brackets
3094 for (int otherKind = 0;(balance == 0) && (otherKind < BracketKinds); otherKind++) {
3095 for (int i = 0; i < leftCount[otherKind]; i++) {
3096 int pos = leftPositions[otherKind][i];
3097 if ((pos > start) && (pos < end))
3100 for (int i = 0; i < rightCount[otherKind]; i++) {
3101 int pos = rightPositions[otherKind][i];
3102 if ((pos > start) && (pos < end))
3106 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly
3111 // too many opening brackets ?
3112 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3113 anomaliesDetected = true;
3114 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, compilationUnit.compilationResult);
3116 // too many closing brackets ?
3117 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3118 anomaliesDetected = true;
3119 problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
3121 if (anomaliesDetected)
3125 return anomaliesDetected;
3126 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3127 return anomaliesDetected;
3128 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3129 return anomaliesDetected;
3133 protected void pushOnAstLengthStack(int pos) {
3135 astLengthStack[++astLengthPtr] = pos;
3136 } catch (IndexOutOfBoundsException e) {
3137 int oldStackLength = astLengthStack.length;
3138 int[] oldPos = astLengthStack;
3139 astLengthStack = new int[oldStackLength + StackIncrement];
3140 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3141 astLengthStack[astLengthPtr] = pos;
3145 protected void pushOnAstStack(AstNode node) {
3146 /*add a new obj on top of the ast stack
3147 astPtr points on the top*/
3150 astStack[++astPtr] = node;
3151 } catch (IndexOutOfBoundsException e) {
3152 int oldStackLength = astStack.length;
3153 AstNode[] oldStack = astStack;
3154 astStack = new AstNode[oldStackLength + AstStackIncrement];
3155 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3156 astPtr = oldStackLength;
3157 astStack[astPtr] = node;
3161 astLengthStack[++astLengthPtr] = 1;
3162 } catch (IndexOutOfBoundsException e) {
3163 int oldStackLength = astLengthStack.length;
3164 int[] oldPos = astLengthStack;
3165 astLengthStack = new int[oldStackLength + AstStackIncrement];
3166 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3167 astLengthStack[astLengthPtr] = 1;