1 /**********************************************************************
2 Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Common Public License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/legal/cpl-v10.html
9 Klaus Hartlage - www.eclipseproject.de
10 **********************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.parser;
13 import java.util.ArrayList;
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
17 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
18 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
19 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
20 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
21 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
22 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
23 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
28 import net.sourceforge.phpeclipse.phpeditor.PHPString;
30 import org.eclipse.core.resources.IFile;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.jface.preference.IPreferenceStore;
34 import test.PHPParserSuperclass;
36 public class Parser extends PHPParserSuperclass implements ITerminalSymbols, ParserBasicInformation {
37 //internal data for the automat
38 protected final static int StackIncrement = 255;
39 protected int stateStackTop;
40 protected int[] stack = new int[StackIncrement];
41 public int firstToken; // handle for multiple parsing goals
42 public int lastAct; //handle for multiple parsing goals
43 protected RecoveredElement currentElement;
45 public static boolean VERBOSE_RECOVERY = false;
46 protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
49 public Scanner scanner;
51 private ArrayList phpList;
53 private int currentPHPString;
54 private boolean phpEnd;
56 // private static HashMap keywordMap = null;
64 // row counter for syntax errors:
66 // column counter for syntax errors:
71 // // current identifier
77 private String stringValue;
79 /** Contains the current expression. */
80 // private StringBuffer expression;
82 private boolean phpMode;
84 // final static int TokenNameEOF = 0;
85 // final static int TokenNameERROR = 1;
86 // final static int TokenNameHTML = 2;
88 // final static int TokenNameREMAINDER = 30;
89 // final static int TokenNameNOT = 31;
90 // final static int TokenNameDOT = 32;
91 // final static int TokenNameXOR = 33;
92 // final static int TokenNameDIVIDE = 34;
93 // final static int TokenNameMULTIPLY = 35;
94 // final static int TokenNameMINUS = 36;
95 // final static int TokenNamePLUS = 37;
96 // final static int TokenNameEQUAL_EQUAL = 38;
97 // final static int TokenNameNOT_EQUAL = 39;
98 // final static int TokenNameGREATER = 40;
99 // final static int TokenNameGREATER_EQUAL = 41;
100 // final static int TokenNameLESS = 42;
101 // final static int TokenNameLESS_EQUAL = 43;
102 // final static int TokenNameAND_AND = 44;
103 // final static int TokenNameOR_OR = 45;
104 // // final static int TokenNameHASH = 46;
105 // final static int TokenNameCOLON = 47;
106 // final static int TokenNameDOT_EQUAL = 48;
108 // final static int TokenNameEQUAL = 49;
109 // final static int TokenNameMINUS_GREATER = 50; // ->
110 // final static int TokenNameFOREACH = 51;
111 // final static int TokenNameAND = 52;
112 // //final static int TokenNameDOLLARLISTOPEN = 53;
113 // final static int TokenNameTWIDDLE = 54;
114 // final static int TokenNameTWIDDLE_EQUAL = 55;
115 // final static int TokenNameREMAINDER_EQUAL = 56;
116 // final static int TokenNameXOR_EQUAL = 57;
117 // final static int TokenNameRIGHT_SHIFT_EQUAL = 58;
118 // final static int TokenNameLEFT_SHIFT_EQUAL = 59;
119 // final static int TokenNameAND_EQUAL = 60;
120 // final static int TokenNameOR_EQUAL = 61;
121 // final static int TokenNameQUESTION = 62;
122 // final static int TokenNameCOLON_COLON = 63;
123 // final static int TokenNameAT = 63;
124 // // final static int TokenNameHEREDOC = 64;
126 // final static int TokenNameDOLLAROPEN = 127;
127 // final static int TokenNameLPAREN = 128;
128 // final static int TokenNameRPAREN = 129;
129 // final static int TokenNameLBRACE = 130;
130 // final static int TokenNameRBRACE = 131;
131 // final static int TokenNameLBRACKET = 132;
132 // final static int TokenNameRBRACKET = 133;
133 // final static int TokenNameCOMMA = 134;
135 // final static int TokenNameStringLiteral = 136;
136 // final static int TokenNameIdentifier = 138;
137 // // final static int TokenNameDIGIT = 139;
138 // final static int TokenNameSEMICOLON = 140;
139 // // final static int TokenNameSLOT = 141;
140 // // final static int TokenNameSLOTSEQUENCE = 142;
141 // final static int TokenNameMINUS_MINUS = 144;
142 // final static int TokenNamePLUS_PLUS = 145;
143 // final static int TokenNamePLUS_EQUAL = 146;
144 // final static int TokenNameDIVIDE_EQUAL = 147;
145 // final static int TokenNameMINUS_EQUAL = 148;
146 // final static int TokenNameMULTIPLY_EQUAL = 149;
147 // final static int TokenNameVariable = 150;
148 // final static int TokenNameIntegerLiteral = 151;
149 // final static int TokenNameDoubleLiteral = 152;
150 // final static int TokenNameStringInterpolated = 153;
151 // final static int TokenNameStringConstant = 154;
153 // final static int TokenNameLEFT_SHIFT = 155;
154 // final static int TokenNameRIGHT_SHIFT = 156;
155 // final static int TokenNameEQUAL_EQUAL_EQUAL = 157;
156 // final static int TokenNameNOT_EQUAL_EQUAL = 158;
157 // final static int TokenNameOR = 159;
158 // final static int TokenNameAT = 153; // @
161 this.currentPHPString = 0;
162 // PHPParserSuperclass.fileToParse = fileToParse;
165 this.token = TokenNameEOF;
167 // this.rowCount = 1;
168 // this.columnCount = 0;
172 this.initializeScanner();
176 public void setFileToParse(IFile fileToParse) {
177 this.currentPHPString = 0;
178 PHPParserSuperclass.fileToParse = fileToParse;
181 this.token = TokenNameEOF;
183 this.initializeScanner();
186 * ClassDeclaration Constructor.
189 *@param sess Description of Parameter
192 public Parser(IFile fileToParse) {
193 // if (keywordMap == null) {
194 // keywordMap = new HashMap();
195 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
196 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
199 this.currentPHPString = 0;
200 PHPParserSuperclass.fileToParse = fileToParse;
203 this.token = TokenNameEOF;
205 // this.rowCount = 1;
206 // this.columnCount = 0;
210 this.initializeScanner();
213 public void initializeScanner() {
214 this.scanner = new Scanner(false, false, false, false);
217 * Create marker for the parse error
219 // private void setMarker(String message, int charStart, int charEnd, int errorLevel) throws CoreException {
220 // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
224 * This method will throw the SyntaxError.
225 * It will add the good lines and columns to the Error
226 * @param error the error message
227 * @throws SyntaxError the error raised
229 private void throwSyntaxError(String error) {
230 int problemStartPosition = scanner.getCurrentTokenStartPosition();
231 int problemEndPosition = scanner.getCurrentTokenEndPosition();
232 reportSyntaxError(error,problemStartPosition,problemEndPosition);
236 * This method will throw the SyntaxError.
237 * It will add the good lines and columns to the Error
238 * @param error the error message
239 * @throws SyntaxError the error raised
241 // private void throwSyntaxError(String error, int startRow) {
242 // throw new SyntaxError(startRow, 0, " ", error);
245 private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
246 problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, compilationUnit.compilationResult);
247 throw new SyntaxError(1, 0, " ", error);
250 * Method Declaration.
254 // private void getChar() {
255 // if (str.length() > chIndx) {
256 // ch = str.charAt(chIndx++);
261 // chIndx = str.length() + 1;
263 // // token = TokenNameEOF;
268 * gets the next token from input
270 private void getNextToken() throws CoreException {
272 token = scanner.getNextToken();
274 int currentEndPosition = scanner.getCurrentTokenEndPosition();
275 int currentStartPosition = scanner.getCurrentTokenStartPosition();
277 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
278 System.out.println(scanner.toStringAction(token));
280 } catch (InvalidInputException e) {
281 token = TokenNameERROR;
289 * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
290 * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
291 * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
292 * value {@link Parser#TokenNameINT_NUMBER}
294 // private void getNumber() {
295 // StringBuffer inum = new StringBuffer();
297 // int numFormat = 10;
299 // // save first digit
300 // char firstCh = ch;
304 // // determine number conversions:
305 // if (firstCh == '0') {
334 // if (numFormat == 16) {
335 // while ((ch >= '0' && ch <= '9')
336 // || (ch >= 'a' && ch <= 'f')
337 // || (ch >= 'A' && ch <= 'F')) {
342 // while ((ch >= '0' && ch <= '9')
346 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
347 // if (ch == '.' && dFlag != ' ') {
350 // if ((dFlag == 'E') || (dFlag == 'e')) {
356 // if ((ch == '-') || (ch == '+')) {
369 // if (dFlag != ' ') {
370 // doubleNumber = new Double(inum.toString());
371 // token = TokenNameDoubleLiteral;
374 // longNumber = Long.valueOf(inum.toString(), numFormat);
375 // token = TokenNameIntegerLiteral;
379 // } catch (Throwable e) {
380 // throwSyntaxError("Number format error: " + inum.toString());
386 // * @param openChar the opening char ('\'', '"', '`')
387 // * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
388 // * @param errorMsg the error message in case of parse error in the string
390 // private void getString(
391 // final char openChar,
392 // final int typeString,
393 // final String errorMsg) {
394 // StringBuffer sBuffer = new StringBuffer();
395 // boolean openString = true;
396 // int startRow = rowCount;
397 // while (str.length() > chIndx) {
398 // ch = str.charAt(chIndx++);
400 // sBuffer.append(ch);
401 // if (str.length() > chIndx) {
402 // ch = str.charAt(chIndx++);
403 // sBuffer.append(ch);
405 // } else if (ch == openChar) {
406 // openString = false;
408 // } else if (ch == '\n') {
410 // columnCount = chIndx;
412 // sBuffer.append(ch);
416 // if (typeString == TokenNameStringConstant) {
417 // throwSyntaxError(errorMsg, startRow);
419 // throwSyntaxError(errorMsg);
422 // token = typeString;
423 // stringValue = sBuffer.toString();
426 // public void htmlParserTester(String input) {
427 // int lineNumber = 1;
428 // int startLineNumber = 1;
429 // int startIndex = 0;
432 // boolean phpMode = false;
433 // boolean phpFound = false;
435 // phpList = new ArrayList();
436 // currentPHPString = 0;
440 // while (i < input.length()) {
441 // ch = input.charAt(i++);
445 // if ((!phpMode) && ch == '<') {
446 // ch2 = input.charAt(i++);
448 // ch2 = input.charAt(i++);
449 // if (Character.isWhitespace(ch2)) {
454 // startLineNumber = lineNumber;
456 // } else if (ch2 == 'p') {
457 // ch2 = input.charAt(i++);
459 // ch2 = input.charAt(i++);
464 // startLineNumber = lineNumber;
470 // } else if (ch2 == 'P') {
471 // ch2 = input.charAt(i++);
473 // ch2 = input.charAt(i++);
478 // startLineNumber = lineNumber;
491 // if (ch == '/' && i < input.length()) {
492 // ch2 = input.charAt(i++);
494 // while (i < input.length()) {
495 // ch = input.charAt(i++);
496 // if (ch == '?' && i < input.length()) {
497 // ch2 = input.charAt(i++);
506 // startLineNumber));
510 // } else if (ch == '\n') {
516 // } else if (ch2 == '*') {
517 // // multi-line comment
518 // while (i < input.length()) {
519 // ch = input.charAt(i++);
522 // } else if (ch == '*' && i < input.length()) {
523 // ch2 = input.charAt(i++);
534 // } else if (ch == '#') {
535 // while (i < input.length()) {
536 // ch = input.charAt(i++);
537 // if (ch == '?' && i < input.length()) {
538 // ch2 = input.charAt(i++);
544 // input.substring(startIndex, i - 2),
545 // startLineNumber));
549 // } else if (ch == '\n') {
555 // } else if (ch == '"') {
557 // while (i < input.length()) {
558 // ch = input.charAt(i++);
562 // ch == '\\' && i < input.length()) { // escape
564 // } else if (ch == '"') {
569 // } else if (ch == '\'') {
571 // while (i < input.length()) {
572 // ch = input.charAt(i++);
576 // ch == '\\' && i < input.length()) { // escape
578 // } else if (ch == '\'') {
585 // if (ch == '?' && i < input.length()) {
586 // ch2 = input.charAt(i++);
592 // input.substring(startIndex, i - 2),
593 // startLineNumber));
603 // "No PHP source code found.",
609 // "Open PHP tag at end of file.",
614 // input.substring(startIndex, i - 2),
615 // startLineNumber));
617 // // for (int j=0;j<phpList.size();j++) {
618 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
619 // // int startIndx = temp.length()-10;
620 // // if (startIndx<0) {
623 // // System.out.println(temp.substring(startIndx)+"?>");
625 // phpParserTester(null, 1);
626 // // PHPString temp;
627 // // for(int j=0;j<phpList.size();j++) {
628 // // temp = (PHPString) phpList.get(j);
629 // // parser.start(temp.getPHPString(), temp.getLineNumber());
632 // } catch (CoreException e) {
636 public void phpParserTester(String s, int rowCount) throws CoreException {
639 if (phpList.size() != 0) {
640 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
643 this.token = TokenNameEOF;
645 // this.rowCount = rowCount;
646 // this.columnCount = 0;
649 scanner.setSource(s.toCharArray());
650 scanner.setPHPMode(true);
654 if (token != TokenNameEOF && token != TokenNameERROR) {
657 if (token != TokenNameEOF) {
658 if (token == TokenNameERROR) {
659 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
661 if (token == TokenNameRPAREN) {
662 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
664 if (token == TokenNameRBRACE) {
665 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
667 if (token == TokenNameRBRACKET) {
668 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
671 if (token == TokenNameLPAREN) {
672 throwSyntaxError("Read character '('; end-of-file not reached.");
674 if (token == TokenNameLBRACE) {
675 throwSyntaxError("Read character '{'; end-of-file not reached.");
677 if (token == TokenNameLBRACKET) {
678 throwSyntaxError("Read character '['; end-of-file not reached.");
681 throwSyntaxError("End-of-file not reached.");
684 } catch (SyntaxError err) {
688 // setMarker(err.getMessage(), err.getLine(), ERROR);
689 // setMarker(err.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
691 // if an error occured,
692 // try to find keywords 'class' or 'function'
693 // to parse the rest of the string
694 while (token != TokenNameEOF && token != TokenNameERROR) {
695 if (token == TokenNameclass || token == TokenNamefunction) {
700 if (token == TokenNameEOF || token == TokenNameERROR) {
707 public void init(String s) {
709 this.token = TokenNameEOF;
711 // this.rowCount = 1;
712 // this.columnCount = 0;
714 this.phpMode = false;
715 /* scanner initialization */
716 scanner.setSource(s.toCharArray());
717 scanner.setPHPMode(false);
720 protected void initialize(boolean phpMode) {
721 compilationUnit = null;
722 referenceContext = null;
724 this.token = TokenNameEOF;
726 // this.rowCount = 1;
727 // this.columnCount = 0;
729 this.phpMode = phpMode;
730 scanner.setPHPMode(phpMode);
733 * Parses a string with php tags
734 * i.e. '<body> <?php phpinfo() ?> </body>'
736 public void parse(String s) throws CoreException {
742 * Parses a string with php tags
743 * i.e. '<body> <?php phpinfo() ?> </body>'
745 protected void parse() throws CoreException {
749 if (token != TokenNameEOF && token != TokenNameERROR) {
752 if (token != TokenNameEOF) {
753 if (token == TokenNameERROR) {
754 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
756 if (token == TokenNameRPAREN) {
757 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
759 if (token == TokenNameRBRACE) {
760 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
762 if (token == TokenNameRBRACKET) {
763 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
766 if (token == TokenNameLPAREN) {
767 throwSyntaxError("Read character '('; end-of-file not reached.");
769 if (token == TokenNameLBRACE) {
770 throwSyntaxError("Read character '{'; end-of-file not reached.");
772 if (token == TokenNameLBRACKET) {
773 throwSyntaxError("Read character '['; end-of-file not reached.");
776 throwSyntaxError("End-of-file not reached.");
779 } catch (SyntaxError sytaxErr1) {
780 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
781 // setMarker(sytaxErr1.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
783 // if an error occured,
784 // try to find keywords 'class' or 'function'
785 // to parse the rest of the string
786 while (token != TokenNameEOF && token != TokenNameERROR) {
787 if (token == TokenNameclass || token == TokenNamefunction) {
792 if (token == TokenNameEOF || token == TokenNameERROR) {
795 } catch (SyntaxError sytaxErr2) {
796 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
797 // setMarker(sytaxErr2.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
805 public PHPOutlineInfo parseInfo(Object parent, String s) {
806 PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
807 // Stack stack = new Stack();
808 // stack.push(outlineInfo.getDeclarations());
811 this.token = TokenNameEOF;
813 // this.rowCount = 1;
814 // this.columnCount = 0;
816 this.phpMode = false;
817 scanner.setSource(s.toCharArray());
818 scanner.setPHPMode(false);
822 parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
823 } catch (CoreException e) {
828 private boolean isVariable() {
829 return token == TokenNameVariable || token == TokenNamethis;
832 private void parseDeclarations(PHPOutlineInfo outlineInfo, OutlineableWithChildren current, boolean goBack) {
834 // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
835 PHPSegmentWithChildren temp;
838 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
840 while (token != TokenNameEOF && token != TokenNameERROR) {
841 if (token == TokenNameVariable) {
842 ident = scanner.getCurrentIdentifierSource();
843 outlineInfo.addVariable(new String(ident));
845 } else if (token == TokenNamevar) {
847 if (token == TokenNameVariable && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
848 ident = scanner.getCurrentIdentifierSource();
849 //substring(1) added because PHPVarDeclaration doesn't need the $ anymore
850 String variableName = new String(ident).substring(1);
851 outlineInfo.addVariable(variableName);
853 if (token != TokenNameSEMICOLON) {
856 ident = scanner.getCurrentTokenSource();
857 if (token > TokenNameKEYWORD) {
858 current.add(new PHPVarDeclaration(current, variableName,
859 // chIndx - ident.length,
860 scanner.getCurrentTokenStartPosition(), new String(ident)));
863 case TokenNameVariable :
865 current.add(new PHPVarDeclaration(current, variableName,
866 // chIndx - ident.length,
867 scanner.getCurrentTokenStartPosition(), new String(ident)));
869 case TokenNameIdentifier :
870 current.add(new PHPVarDeclaration(current, variableName,
871 // chIndx - ident.length,
872 scanner.getCurrentTokenStartPosition(), new String(ident)));
874 case TokenNameDoubleLiteral :
875 current.add(new PHPVarDeclaration(current, variableName + doubleNumber,
876 // chIndx - ident.length,
877 scanner.getCurrentTokenStartPosition(), new String(ident)));
879 case TokenNameIntegerLiteral :
880 current.add(new PHPVarDeclaration(current, variableName,
881 // chIndx - ident.length,
882 scanner.getCurrentTokenStartPosition(), new String(ident)));
884 case TokenNameStringInterpolated :
885 case TokenNameStringLiteral :
886 current.add(new PHPVarDeclaration(current, variableName,
887 // chIndx - ident.length,
888 scanner.getCurrentTokenStartPosition(), new String(ident)));
890 case TokenNameStringConstant :
891 current.add(new PHPVarDeclaration(current, variableName,
892 // chIndx - ident.length,
893 scanner.getCurrentTokenStartPosition(), new String(ident)));
896 current.add(new PHPVarDeclaration(current, variableName,
897 // chIndx - ident.length
898 scanner.getCurrentTokenStartPosition()));
904 ident = scanner.getCurrentIdentifierSource();
906 current.add(new PHPVarDeclaration(current, variableName,
907 // chIndx - ident.length
908 scanner.getCurrentTokenStartPosition()));
911 } else if (token == TokenNamefunction) {
913 if (token == TokenNameAND) {
916 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
917 ident = scanner.getCurrentIdentifierSource();
918 outlineInfo.addVariable(new String(ident));
919 temp = new PHPFunctionDeclaration(current, new String(ident),
920 // chIndx - ident.length
921 scanner.getCurrentTokenStartPosition());
924 parseDeclarations(outlineInfo, temp, true);
926 } else if (token == TokenNameclass) {
928 if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
929 ident = scanner.getCurrentIdentifierSource();
930 outlineInfo.addVariable(new String(ident));
931 temp = new PHPClassDeclaration(current, new String(ident),
932 // chIndx - ident.len
933 scanner.getCurrentTokenStartPosition());
938 //skip tokens for classname, extends and others until we have the opening '{'
939 while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) {
942 parseDeclarations(outlineInfo, temp, true);
945 } else if ((token == TokenNameLBRACE) || (token == TokenNameDOLLAR_LBRACE)) {
948 } else if (token == TokenNameRBRACE) {
951 if (counter == 0 && goBack) {
954 } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) {
955 ident = scanner.getCurrentTokenSource();
958 int startPosition = scanner.getCurrentTokenStartPosition();
960 char[] expr = scanner.getCurrentTokenSource(startPosition);
961 outlineInfo.addVariable(new String(ident));
962 current.add(new PHPReqIncDeclaration(current, new String(ident),
963 // chIndx - ident.length,
964 startPosition, new String(expr)));
970 } catch (CoreException e) {
971 } catch (SyntaxError sytaxErr) {
973 // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
974 // setMarker(sytaxErr.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR);
975 // } catch (CoreException e) {
980 private void statementList() throws CoreException {
982 statement(TokenNameEOF);
983 if ((token == TokenNameRBRACE)
984 || (token == TokenNamecase)
985 || (token == TokenNamedefault)
986 || (token == TokenNameelse)
987 || (token == TokenNameelseif)
988 || (token == TokenNameendif)
989 || (token == TokenNameendfor)
990 || (token == TokenNameendforeach)
991 || (token == TokenNameendwhile)
992 || (token == TokenNameendswitch)
993 || (token == TokenNameEOF)
994 || (token == TokenNameERROR)) {
1000 private void functionBody(MethodDeclaration methodDecl) throws CoreException {
1001 // '{' [statement-list] '}'
1002 if (token == TokenNameLBRACE) {
1005 throwSyntaxError("'{' expected in compound-statement.");
1007 if (token != TokenNameRBRACE) {
1010 if (token == TokenNameRBRACE) {
1011 methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1014 throwSyntaxError("'}' expected in compound-statement.");
1018 private void statement(int previousToken) throws CoreException {
1019 // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
1020 // char[] ident = scanner.getCurrentIdentifierSource();
1021 // String keyword = new String(ident);
1022 if (token == TokenNameAT) {
1024 if (token != TokenNamerequire
1025 && token != TokenNamerequire_once
1026 && token != TokenNameinclude
1027 && token != TokenNameinclude_once
1028 && token != TokenNameIdentifier
1029 && token != TokenNameVariable
1030 && token != TokenNamethis
1031 && token != TokenNameStringInterpolated) {
1032 throwSyntaxError("identifier expected after '@'.");
1035 if (token == TokenNameinclude || token == TokenNameinclude_once) {
1037 if (token == TokenNameLPAREN) {
1039 if (token == TokenNameSEMICOLON) {
1042 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
1043 throwSyntaxError("';' expected after 'include' or 'include_once'.");
1048 concatenationExpression();
1052 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1055 if (token == TokenNameLPAREN) {
1057 if (token == TokenNameSEMICOLON) {
1060 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
1061 throwSyntaxError("';' expected after 'require' or 'require_once'.");
1066 concatenationExpression();
1069 } else if (token == TokenNameif) {
1071 if (token == TokenNameLPAREN) {
1074 throwSyntaxError("'(' expected after 'if' keyword.");
1077 if (token == TokenNameRPAREN) {
1080 throwSyntaxError("')' expected after 'if' condition.");
1085 } else if (token == TokenNameswitch) {
1087 if (token == TokenNameLPAREN) {
1090 throwSyntaxError("'(' expected after 'switch' keyword.");
1093 if (token == TokenNameRPAREN) {
1096 throwSyntaxError("')' expected after 'switch' condition.");
1100 } else if (token == TokenNamefor) {
1102 if (token == TokenNameLPAREN) {
1105 throwSyntaxError("'(' expected after 'for' keyword.");
1107 if (token == TokenNameSEMICOLON) {
1111 if (token == TokenNameSEMICOLON) {
1114 throwSyntaxError("';' expected after 'for'.");
1117 if (token == TokenNameSEMICOLON) {
1121 if (token == TokenNameSEMICOLON) {
1124 throwSyntaxError("';' expected after 'for'.");
1127 if (token == TokenNameRPAREN) {
1131 if (token == TokenNameRPAREN) {
1134 throwSyntaxError("')' expected after 'for'.");
1139 } else if (token == TokenNamewhile) {
1141 if (token == TokenNameLPAREN) {
1144 throwSyntaxError("'(' expected after 'while' keyword.");
1147 if (token == TokenNameRPAREN) {
1150 throwSyntaxError("')' expected after 'while' condition.");
1154 } else if (token == TokenNamedo) {
1156 if (token == TokenNameLBRACE) {
1159 throwSyntaxError("'{' expected after 'do' keyword.");
1161 if (token != TokenNameRBRACE) {
1164 if (token == TokenNameRBRACE) {
1167 throwSyntaxError("'}' expected after 'do' keyword.");
1169 if (token == TokenNamewhile) {
1171 if (token == TokenNameLPAREN) {
1174 throwSyntaxError("'(' expected after 'while' keyword.");
1177 if (token == TokenNameRPAREN) {
1180 throwSyntaxError("')' expected after 'while' condition.");
1183 throwSyntaxError("'while' expected after 'do' keyword.");
1185 if (token == TokenNameSEMICOLON) {
1188 if (token != TokenNameStopPHP) {
1189 throwSyntaxError("';' expected after do-while statement.");
1194 } else if (token == TokenNameforeach) {
1196 if (token == TokenNameLPAREN) {
1199 throwSyntaxError("'(' expected after 'foreach' keyword.");
1202 if (token == TokenNameas) {
1205 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1208 if (token == TokenNameEQUAL_GREATER) {
1212 if (token == TokenNameRPAREN) {
1215 throwSyntaxError("')' expected after 'foreach' expression.");
1220 } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
1222 if (token != TokenNameSEMICOLON) {
1225 if (token == TokenNameSEMICOLON) {
1228 if (token != TokenNameStopPHP) {
1229 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1235 } else if (token == TokenNameecho) {
1238 if (token == TokenNameSEMICOLON) {
1241 if (token != TokenNameStopPHP) {
1242 throwSyntaxError("';' expected after 'echo' statement.");
1247 // } else if (token == TokenNameprint) {
1250 // if (token == TokenNameSEMICOLON) {
1253 // if (token != TokenNameStopPHP) {
1254 // throwSyntaxError("';' expected after 'print' statement.");
1260 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1263 if (token == TokenNameSEMICOLON) {
1266 if (token != TokenNameStopPHP) {
1267 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1273 // } else if (token == TokenNameunset) {
1275 // if (token == TokenNameARGOPEN) {
1278 // throwSyntaxError("'(' expected after 'unset' keyword.");
1281 // if (token == TokenNameARGCLOSE) {
1284 // throwSyntaxError("')' expected after 'unset' statement.");
1286 // if (token == TokenNameSEMICOLON) {
1289 // if (token != TokenNameStopPHP) {
1290 // throwSyntaxError("';' expected after 'unset' statement.");
1296 // } else if (token == TokenNameexit || token == TokenNamedie) {
1298 // if (token != TokenNameSEMICOLON) {
1301 // if (token == TokenNameSEMICOLON) {
1304 // if (token != TokenNameStopPHP) {
1305 // throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1311 } else if (token == TokenNamedefine) {
1313 if (token == TokenNameLPAREN) {
1316 throwSyntaxError("'(' expected after 'define' keyword.");
1319 if (token == TokenNameCOMMA) {
1322 throwSyntaxError("',' expected after first 'define' constant.");
1325 if (token == TokenNameCOMMA) {
1329 if (token == TokenNameRPAREN) {
1332 throwSyntaxError("')' expected after 'define' statement.");
1334 if (token == TokenNameSEMICOLON) {
1337 if (token != TokenNameStopPHP) {
1338 throwSyntaxError("';' expected after 'define' statement.");
1343 } else if (token == TokenNamefunction) {
1344 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1345 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1347 functionDefinition(methodDecl);
1349 } else if (token == TokenNameclass) {
1350 TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
1351 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1352 // default super class
1353 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1354 compilationUnit.types.add(typeDecl);
1356 pushOnAstStack(typeDecl);
1358 classDeclarator(typeDecl);
1359 classBody(typeDecl);
1366 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1367 } else if (token == TokenNameLBRACE) {
1369 if (token != TokenNameRBRACE) {
1372 if (token == TokenNameRBRACE) {
1376 throwSyntaxError("'}' expected.");
1379 if (token != TokenNameSEMICOLON) {
1382 if (token == TokenNameSEMICOLON) {
1386 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1387 throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
1394 private void classDeclarator(TypeDeclaration typeDecl) throws CoreException {
1396 //identifier 'extends' identifier
1399 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1400 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1401 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1402 typeDecl.name = scanner.getCurrentIdentifierSource();
1403 if (token > TokenNameKEYWORD) {
1405 "Don't use keyword for class declaration [" + scanner.toStringAction(token) + "].",
1406 typeDecl.sourceStart,
1407 typeDecl.sourceEnd);
1410 if (token == TokenNameextends) {
1413 if (token == TokenNameIdentifier) {
1416 reportSyntaxError("Class name expected after keyword 'extends'.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1418 } while (token == TokenNameCOMMA);
1421 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1422 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1424 typeDecl.name = new char[] { ' ' };
1425 reportSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1426 // throwSyntaxError("ClassDeclaration name expected after keyword 'class'.");
1430 private void classBody(TypeDeclaration typeDecl) throws CoreException {
1431 //'{' [class-element-list] '}'
1432 if (token == TokenNameLBRACE) {
1434 if (token != TokenNameRBRACE) {
1437 if (token == TokenNameRBRACE) {
1438 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1441 throwSyntaxError("'}' expected at end of class body.");
1444 throwSyntaxError("'{' expected at start of class body.");
1448 private void classElementList() throws CoreException {
1451 } while (token == TokenNamefunction || token == TokenNamevar);
1454 private void classElement() throws CoreException {
1456 //function-definition
1457 if (token == TokenNamefunction) {
1458 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1459 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1461 functionDefinition(methodDecl);
1462 } else if (token == TokenNamevar) {
1466 throwSyntaxError("'function' or 'var' expected.");
1470 private void classProperty() throws CoreException {
1471 //'var' variable ';'
1472 //'var' variable '=' constant ';'
1474 if (token == TokenNameVariable) {
1476 if (token == TokenNameEQUAL) {
1481 if (token == TokenNamethis) {
1482 throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1484 throwSyntaxError("Variable expected after keyword 'var'.");
1486 if (token != TokenNameCOMMA) {
1491 if (token == TokenNameSEMICOLON) {
1494 throwSyntaxError("';' expected after variable declaration.");
1498 private void functionDefinition(MethodDeclaration methodDecl) throws CoreException {
1500 compilationUnit.types.add(methodDecl);
1502 AstNode node = astStack[astPtr];
1503 if (node instanceof TypeDeclaration) {
1504 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1505 if (typeDecl.methods == null) {
1506 typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
1508 AbstractMethodDeclaration[] newMethods;
1509 System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, typeDecl.methods.length);
1510 newMethods[0] = methodDecl;
1511 typeDecl.methods = newMethods;
1515 functionDeclarator(methodDecl);
1516 functionBody(methodDecl);
1519 private void functionDeclarator(MethodDeclaration methodDecl) throws CoreException {
1520 //identifier '(' [parameter-list] ')'
1521 if (token == TokenNameAND) {
1524 if (token == TokenNameIdentifier) {
1525 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1526 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1527 methodDecl.selector = scanner.getCurrentIdentifierSource();
1529 if (token == TokenNameLPAREN) {
1532 throwSyntaxError("'(' expected in function declaration.");
1534 if (token != TokenNameRPAREN) {
1537 if (token != TokenNameRPAREN) {
1538 throwSyntaxError("')' expected in function declaration.");
1540 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1544 if (token > TokenNameKEYWORD) {
1545 throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
1547 throwSyntaxError("Function name expected after keyword 'function'.");
1551 private void parameterList() throws CoreException {
1552 //parameter-declaration
1553 //parameter-list ',' parameter-declaration
1555 parameterDeclaration();
1556 if (token != TokenNameCOMMA) {
1563 private void parameterDeclaration() throws CoreException {
1565 //variable-reference
1566 if (token == TokenNameAND) {
1571 throwSyntaxError("Variable expected after reference operator '&'.");
1574 //variable '=' constant
1575 if (token == TokenNameVariable) {
1577 if (token == TokenNameEQUAL) {
1583 if (token == TokenNamethis) {
1584 throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1588 private void labeledStatementList() throws CoreException {
1589 if (token != TokenNamecase && token != TokenNamedefault) {
1590 throwSyntaxError("'case' or 'default' expected.");
1593 if (token == TokenNamecase) {
1595 expression(); //constant();
1596 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1598 if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
1603 // else if (token == TokenNameSEMICOLON) {
1605 // "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")",
1606 // scanner.getCurrentTokenStartPosition(),
1607 // scanner.getCurrentTokenEndPosition(),
1610 // if (token == TokenNamecase) { // empty case statement ?
1616 throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
1618 } else { // TokenNamedefault
1620 if (token == TokenNameCOLON) {
1624 throwSyntaxError("':' character after 'default' expected.");
1627 } while (token == TokenNamecase || token == TokenNamedefault);
1630 // public void labeledStatement() {
1631 // if (token == TokenNamecase) {
1634 // if (token == TokenNameDDOT) {
1638 // throwSyntaxError("':' character after 'case' constant expected.");
1641 // } else if (token == TokenNamedefault) {
1643 // if (token == TokenNameDDOT) {
1647 // throwSyntaxError("':' character after 'default' expected.");
1653 // public void expressionStatement() {
1656 // private void inclusionStatement() {
1659 // public void compoundStatement() {
1662 // public void selectionStatement() {
1665 // public void iterationStatement() {
1668 // public void jumpStatement() {
1671 // public void outputStatement() {
1674 // public void scopeStatement() {
1677 // public void flowStatement() {
1680 // public void definitionStatement() {
1683 private void ifStatement() throws CoreException {
1684 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1685 if (token == TokenNameCOLON) {
1687 if (token != TokenNameendif) {
1690 case TokenNameelse :
1692 if (token == TokenNameCOLON) {
1694 if (token != TokenNameendif) {
1698 if (token == TokenNameif) { //'else if'
1700 elseifStatementList();
1702 throwSyntaxError("':' expected after 'else'.");
1706 case TokenNameelseif :
1708 elseifStatementList();
1713 if (token != TokenNameendif) {
1714 throwSyntaxError("'endif' expected.");
1717 if (token != TokenNameSEMICOLON) {
1718 throwSyntaxError("';' expected after if-statement.");
1722 // statement [else-statement]
1723 statement(TokenNameEOF);
1724 if (token == TokenNameelseif) {
1726 if (token == TokenNameLPAREN) {
1729 throwSyntaxError("'(' expected after 'elseif' keyword.");
1732 if (token == TokenNameRPAREN) {
1735 throwSyntaxError("')' expected after 'elseif' condition.");
1738 } else if (token == TokenNameelse) {
1740 statement(TokenNameEOF);
1745 private void elseifStatementList() throws CoreException {
1749 case TokenNameelse :
1751 if (token == TokenNameCOLON) {
1753 if (token != TokenNameendif) {
1758 if (token == TokenNameif) { //'else if'
1761 throwSyntaxError("':' expected after 'else'.");
1765 case TokenNameelseif :
1774 private void elseifStatement() throws CoreException {
1775 if (token == TokenNameLPAREN) {
1778 if (token != TokenNameRPAREN) {
1779 throwSyntaxError("')' expected in else-if-statement.");
1782 if (token != TokenNameCOLON) {
1783 throwSyntaxError("':' expected in else-if-statement.");
1786 if (token != TokenNameendif) {
1792 private void switchStatement() throws CoreException {
1793 if (token == TokenNameCOLON) {
1794 // ':' [labeled-statement-list] 'endswitch' ';'
1796 labeledStatementList();
1797 if (token != TokenNameendswitch) {
1798 throwSyntaxError("'endswitch' expected.");
1801 if (token != TokenNameSEMICOLON) {
1802 throwSyntaxError("';' expected after switch-statement.");
1806 // '{' [labeled-statement-list] '}'
1807 if (token != TokenNameLBRACE) {
1808 throwSyntaxError("'{' expected in switch statement.");
1811 if (token != TokenNameRBRACE) {
1812 labeledStatementList();
1814 if (token != TokenNameRBRACE) {
1815 throwSyntaxError("'}' expected in switch statement.");
1822 private void forStatement() throws CoreException {
1823 if (token == TokenNameCOLON) {
1826 if (token != TokenNameendfor) {
1827 throwSyntaxError("'endfor' expected.");
1830 if (token != TokenNameSEMICOLON) {
1831 throwSyntaxError("';' expected after for-statement.");
1835 statement(TokenNameEOF);
1839 private void whileStatement() throws CoreException {
1840 // ':' statement-list 'endwhile' ';'
1841 if (token == TokenNameCOLON) {
1844 if (token != TokenNameendwhile) {
1845 throwSyntaxError("'endwhile' expected.");
1848 if (token != TokenNameSEMICOLON) {
1849 throwSyntaxError("';' expected after while-statement.");
1853 statement(TokenNameEOF);
1857 private void foreachStatement() throws CoreException {
1858 if (token == TokenNameCOLON) {
1861 if (token != TokenNameendforeach) {
1862 throwSyntaxError("'endforeach' expected.");
1865 if (token != TokenNameSEMICOLON) {
1866 throwSyntaxError("';' expected after foreach-statement.");
1870 statement(TokenNameEOF);
1874 private void exitStatus() throws CoreException {
1875 if (token == TokenNameLPAREN) {
1878 throwSyntaxError("'(' expected in 'exit-status'.");
1880 if (token != TokenNameRPAREN) {
1883 if (token == TokenNameRPAREN) {
1886 throwSyntaxError("')' expected after 'exit-status'.");
1890 private void expressionList() throws CoreException {
1893 if (token == TokenNameCOMMA) {
1901 private void expression() throws CoreException {
1902 //todo: find a better way to get the expression
1903 // expression = new StringBuffer();
1904 // for (int i = chIndx; i < str.length(); i++) {
1905 // if (str.charAt(i) == ';') {
1908 // expression.append(str.charAt(i));
1911 // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
1914 logicalinclusiveorExpression();
1915 // while (token != TokenNameSEMICOLON) {
1921 private void postfixExpression() throws CoreException {
1924 boolean castFlag = false;
1925 boolean arrayFlag = false;
1931 case TokenNamenull :
1934 case TokenNamefalse :
1937 case TokenNametrue :
1940 case TokenNameStringConstant :
1943 case TokenNameHEREDOC :
1944 case TokenNameStringInterpolated :
1945 case TokenNameStringLiteral :
1948 case TokenNameLPAREN :
1951 if (token == TokenNameIdentifier) {
1952 // check if identifier is a type:
1953 // ident = identifier;
1954 ident = scanner.getCurrentIdentifierSource();
1955 String str = new String(ident).toLowerCase();
1956 for (int i = 0; i < PHP_TYPES.length; i++) {
1957 if (PHP_TYPES[i].equals(str)) {
1959 if (PHP_TYPES[i].equals("array")) {
1969 if (arrayFlag && token == TokenNameLPAREN) {
1971 if (token == TokenNameRPAREN) {
1975 if (token != TokenNameRPAREN) {
1976 throwSyntaxError(") expected after 'array('.");
1980 if (token != TokenNameRPAREN) {
1981 throwSyntaxError(") expected after cast-type '" + str + "'.");
1989 if (token != TokenNameRPAREN) {
1990 throwSyntaxError(") expected in postfix-expression.");
1994 case TokenNameDoubleLiteral :
1997 case TokenNameIntegerLiteral :
2000 case TokenNameDOLLAR_LBRACE :
2003 if (token != TokenNameRBRACE) {
2004 throwSyntaxError("'}' expected after indirect variable token '${'.");
2008 case TokenNameVariable :
2009 case TokenNamethis :
2010 ident = scanner.getCurrentIdentifierSource();
2012 if (token == TokenNameLBRACE) {
2015 if (token != TokenNameRBRACE) {
2016 throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression.");
2019 } else if (token == TokenNameLPAREN) {
2021 if (token != TokenNameRPAREN) {
2023 if (token != TokenNameRPAREN) {
2024 throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression.");
2030 case TokenNameIdentifier :
2031 ident = scanner.getCurrentIdentifierSource();
2033 if (token == TokenNameLPAREN) {
2035 if (token != TokenNameRPAREN) {
2037 if (token != TokenNameRPAREN) {
2039 "')' expected after identifier '" + new String(ident) + "' in postfix-expression." + "(Found token: " + scanner.toStringAction(token) + ")");
2045 case TokenNameprint :
2048 // if (token == TokenNameSEMICOLON) {
2051 // if (token != TokenNameStopPHP) {
2052 // throwSyntaxError("';' expected after 'print' statement.");
2057 case TokenNamelist :
2059 if (token == TokenNameLPAREN) {
2061 if (token == TokenNameCOMMA) {
2065 if (token != TokenNameRPAREN) {
2066 throwSyntaxError("')' expected after 'list' keyword.");
2069 // if (token == TokenNameSET) {
2071 // logicalinclusiveorExpression();
2074 throwSyntaxError("'(' expected after 'list' keyword.");
2077 // case TokenNameexit :
2079 // if (token != TokenNameSEMICOLON) {
2082 // if (token == TokenNameSEMICOLON) {
2085 // if (token != TokenNameStopPHP) {
2086 // throwSyntaxError("';' expected after 'exit' expression.");
2091 // case TokenNamedie :
2093 // if (token != TokenNameSEMICOLON) {
2096 // if (token == TokenNameSEMICOLON) {
2099 // if (token != TokenNameStopPHP) {
2100 // throwSyntaxError("';' expected after 'die' expression.");
2105 // case TokenNamearray :
2107 // if (token == TokenNameARGOPEN) {
2109 // if (token == TokenNameCOMMA) {
2112 // expressionList();
2113 // if (token != TokenNameARGCLOSE) {
2114 // throwSyntaxError("')' expected after 'list' keyword.");
2117 // if (token == TokenNameSET) {
2119 // logicalinclusiveorExpression();
2122 // throwSyntaxError("'(' expected after 'list' keyword.");
2126 boolean while_flag = true;
2129 case TokenNameLBRACKET :
2132 if (token != TokenNameRBRACKET) {
2133 throwSyntaxError("] expected in postfix-expression.");
2137 case TokenNameCOLON_COLON : // ::
2138 case TokenNameMINUS_GREATER : // ->
2140 if (token > TokenNameKEYWORD) {
2141 ident = scanner.getCurrentIdentifierSource();
2143 // "Avoid using keyword '"
2144 // + new String(ident)
2145 // + "' as variable name.",
2149 // "Avoid using keyword '" + new String(ident) + "' as variable name.",
2150 // scanner.getCurrentTokenStartPosition(),
2151 // scanner.getCurrentTokenEndPosition(),
2155 case TokenNameVariable :
2156 ident = scanner.getCurrentIdentifierSource();
2158 // if (token == TokenNameARGOPEN) {
2160 // expressionList();
2161 // if (token != TokenNameARGCLOSE) {
2162 // throwSyntaxError(") expected after variable '" + ident + "'.");
2167 case TokenNameIdentifier :
2168 //ident = scanner.getCurrentIdentifierSource();
2171 case TokenNameLBRACE :
2174 if (token != TokenNameRBRACE) {
2175 throwSyntaxError("} expected in postfix-expression.");
2180 throwSyntaxError("Syntax error after '->' token.");
2181 } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
2182 if (token == TokenNameLBRACKET) {
2185 if (token != TokenNameRBRACKET) {
2186 throwSyntaxError("] expected after '->'.");
2189 } else if (token == TokenNameLPAREN) {
2192 if (token != TokenNameRPAREN) {
2193 throwSyntaxError(") expected after '->'.");
2196 } else if (token == TokenNameLBRACE) {
2199 if (token != TokenNameRBRACE) {
2200 throwSyntaxError("} expected after '->'.");
2206 case TokenNamePLUS_PLUS :
2209 case TokenNameMINUS_MINUS :
2220 private void unaryExpression() throws CoreException {
2222 case TokenNamePLUS_PLUS :
2226 case TokenNameMINUS_MINUS :
2230 // '@' '&' '*' '+' '-' '~' '!'
2233 if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) {
2234 statement(TokenNameAT);
2236 postfixExpression(); // castExpression();
2243 case TokenNameMULTIPLY :
2247 case TokenNamePLUS :
2251 case TokenNameMINUS :
2255 case TokenNameTWIDDLE :
2264 postfixExpression();
2268 private void castExpression() throws CoreException {
2269 // if (token == TokenNameARGOPEN) {
2272 // if (token != TokenNameARGCLOSE) {
2273 // throwSyntaxError(") expected after cast-expression.");
2280 private void assignExpression() throws CoreException {
2282 if (token == TokenNameEQUAL) { // =
2284 logicalinclusiveorExpression();
2285 } else if (token == TokenNameDOT_EQUAL) { // .=
2287 logicalinclusiveorExpression();
2288 } else if (token == TokenNameEQUAL_GREATER) { // =>
2290 logicalinclusiveorExpression();
2291 } else if (token == TokenNamePLUS_EQUAL) { // +=
2293 logicalinclusiveorExpression();
2294 } else if (token == TokenNameMINUS_EQUAL) { // -=
2296 logicalinclusiveorExpression();
2297 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2299 logicalinclusiveorExpression();
2300 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2302 logicalinclusiveorExpression();
2303 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2305 logicalinclusiveorExpression();
2306 } else if (token == TokenNameAND_EQUAL) { // &=
2308 logicalinclusiveorExpression();
2309 } else if (token == TokenNameOR_EQUAL) { // |=
2311 logicalinclusiveorExpression();
2312 } else if (token == TokenNameXOR_EQUAL) { // ^=
2314 logicalinclusiveorExpression();
2315 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2317 logicalinclusiveorExpression();
2318 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2320 logicalinclusiveorExpression();
2321 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2323 logicalinclusiveorExpression();
2327 private void multiplicativeExpression() throws CoreException {
2330 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
2337 private void concatenationExpression() throws CoreException {
2339 multiplicativeExpression();
2340 if (token != TokenNameDOT) {
2347 private void additiveExpression() throws CoreException {
2349 concatenationExpression();
2350 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2357 private void shiftExpression() throws CoreException {
2359 additiveExpression();
2360 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2367 private void relationalExpression() throws CoreException {
2370 if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2377 private void identicalExpression() throws CoreException {
2379 relationalExpression();
2380 if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
2387 private void equalityExpression() throws CoreException {
2389 identicalExpression();
2390 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2397 private void ternaryExpression() throws CoreException {
2398 equalityExpression();
2399 if (token == TokenNameQUESTION) {
2402 if (token == TokenNameCOLON) {
2406 throwSyntaxError("':' expected in ternary operator '? :'.");
2411 private void andExpression() throws CoreException {
2413 ternaryExpression();
2414 if (token != TokenNameAND) {
2421 private void exclusiveorExpression() throws CoreException {
2424 if (token != TokenNameXOR) {
2431 private void inclusiveorExpression() throws CoreException {
2433 exclusiveorExpression();
2434 if (token != TokenNameOR) {
2441 private void booleanandExpression() throws CoreException {
2443 inclusiveorExpression();
2444 if (token != TokenNameAND_AND) {
2451 private void booleanorExpression() throws CoreException {
2453 booleanandExpression();
2454 if (token != TokenNameOR_OR) {
2461 private void logicalandExpression() throws CoreException {
2463 booleanorExpression();
2464 if (token != TokenNameAND) {
2471 private void logicalexclusiveorExpression() throws CoreException {
2473 logicalandExpression();
2474 if (token != TokenNameXOR) {
2481 private void logicalinclusiveorExpression() throws CoreException {
2483 logicalexclusiveorExpression();
2484 if (token != TokenNameOR) {
2491 // public void assignmentExpression() {
2492 // if (token == TokenNameVARIABLE) {
2494 // if (token == TokenNameSET) {
2496 // logicalinclusiveorExpression();
2499 // logicalinclusiveorExpression();
2503 private void variableList() throws CoreException {
2506 if (token == TokenNameCOMMA) {
2514 private void variable() throws CoreException {
2515 if (token == TokenNameDOLLAR_LBRACE) {
2519 if (token != TokenNameRBRACE) {
2520 throwSyntaxError("'}' expected after indirect variable token '${'.");
2524 if (token == TokenNameVariable) {
2526 if (token == TokenNameLBRACKET) {
2529 if (token != TokenNameRBRACKET) {
2530 throwSyntaxError("']' expected in variable-list.");
2533 } else if (token == TokenNameEQUAL) {
2538 throwSyntaxError("$-variable expected in variable-list.");
2544 * It will look for a value (after a '=' for example)
2545 * @throws CoreException
2547 private void constant() throws CoreException {
2550 case TokenNamePLUS :
2553 case TokenNameDoubleLiteral :
2556 case TokenNameIntegerLiteral :
2560 throwSyntaxError("Constant expected after '+' presign.");
2563 case TokenNameMINUS :
2566 case TokenNameDoubleLiteral :
2569 case TokenNameIntegerLiteral :
2573 throwSyntaxError("Constant expected after '-' presign.");
2576 case TokenNamenull :
2579 case TokenNamefalse :
2582 case TokenNametrue :
2585 case TokenNameIdentifier :
2586 // ident = identifier;
2587 char[] ident = scanner.getCurrentIdentifierSource();
2589 if (token == TokenNameLPAREN) {
2591 if (token != TokenNameRPAREN) {
2593 if (token != TokenNameRPAREN) {
2594 throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression.");
2600 case TokenNameStringLiteral :
2603 case TokenNameStringConstant :
2606 case TokenNameStringInterpolated :
2609 case TokenNameDoubleLiteral :
2612 case TokenNameIntegerLiteral :
2616 throwSyntaxError("Constant expected.");
2620 public void reportSyntaxError() { //int act, int currentKind, int stateStackTop) {
2622 /* remember current scanner position */
2623 int startPos = scanner.startPosition;
2624 int currentPos = scanner.currentPosition;
2626 // String[] expectings;
2627 // String tokenName = name[symbol_index[currentKind]];
2629 //fetch all "accurate" possible terminals that could recover the error
2630 // int start, end = start = asi(stack[stateStackTop]);
2631 // while (asr[end] != 0)
2633 // int length = end - start;
2634 // expectings = new String[length];
2635 // if (length != 0) {
2636 // char[] indexes = new char[length];
2637 // System.arraycopy(asr, start, indexes, 0, length);
2638 // for (int i = 0; i < length; i++) {
2639 // expectings[i] = name[symbol_index[indexes[i]]];
2643 //if the pb is an EOF, try to tell the user that they are some
2644 // if (tokenName.equals(UNEXPECTED_EOF)) {
2645 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2646 // char[] tokenSource;
2648 // tokenSource = this.scanner.getCurrentTokenSource();
2649 // } catch (Exception e) {
2650 // tokenSource = new char[] {};
2652 // problemReporter().parseError(
2653 // this.scanner.startPosition,
2654 // this.scanner.currentPosition - 1,
2659 // } else { //the next test is HEAVILY grammar DEPENDENT.
2660 // if ((length == 14)
2661 // && (expectings[0] == "=") //$NON-NLS-1$
2662 // && (expectings[1] == "*=") //$NON-NLS-1$
2663 // && (expressionPtr > -1)) {
2664 // switch(currentKind) {
2665 // case TokenNameSEMICOLON:
2666 // case TokenNamePLUS:
2667 // case TokenNameMINUS:
2668 // case TokenNameDIVIDE:
2669 // case TokenNameREMAINDER:
2670 // case TokenNameMULTIPLY:
2671 // case TokenNameLEFT_SHIFT:
2672 // case TokenNameRIGHT_SHIFT:
2673 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
2674 // case TokenNameLESS:
2675 // case TokenNameGREATER:
2676 // case TokenNameLESS_EQUAL:
2677 // case TokenNameGREATER_EQUAL:
2678 // case TokenNameEQUAL_EQUAL:
2679 // case TokenNameNOT_EQUAL:
2680 // case TokenNameXOR:
2681 // case TokenNameAND:
2682 // case TokenNameOR:
2683 // case TokenNameOR_OR:
2684 // case TokenNameAND_AND:
2685 // // the ; is not the expected token ==> it ends a statement when an expression is not ended
2686 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
2688 // case TokenNameRBRACE :
2689 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
2692 // char[] tokenSource;
2694 // tokenSource = this.scanner.getCurrentTokenSource();
2695 // } catch (Exception e) {
2696 // tokenSource = new char[] {};
2698 // problemReporter().parseError(
2699 // this.scanner.startPosition,
2700 // this.scanner.currentPosition - 1,
2704 // this.checkAndReportBracketAnomalies(problemReporter());
2709 tokenSource = this.scanner.getCurrentTokenSource();
2710 } catch (Exception e) {
2711 tokenSource = new char[] {
2714 // problemReporter().parseError(
2715 // this.scanner.startPosition,
2716 // this.scanner.currentPosition - 1,
2720 this.checkAndReportBracketAnomalies(problemReporter());
2723 /* reset scanner where it was */
2724 scanner.startPosition = startPos;
2725 scanner.currentPosition = currentPos;
2727 public static final int RoundBracket = 0;
2728 public static final int SquareBracket = 1;
2729 public static final int CurlyBracket = 2;
2730 public static final int BracketKinds = 3;
2732 protected int[] nestedMethod; //the ptr is nestedType
2733 protected int nestedType, dimensions;
2735 final static int AstStackIncrement = 100;
2736 protected int astPtr;
2737 protected AstNode[] astStack = new AstNode[AstStackIncrement];
2738 protected int astLengthPtr;
2739 protected int[] astLengthStack;
2740 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
2742 public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
2743 protected ReferenceContext referenceContext;
2744 protected ProblemReporter problemReporter;
2745 // protected CompilationResult compilationResult;
2748 * Returns this parser's problem reporter initialized with its reference context.
2749 * Also it is assumed that a problem is going to be reported, so initializes
2750 * the compilation result's line positions.
2752 public ProblemReporter problemReporter() {
2753 if (scanner.recordLineSeparator) {
2754 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
2756 problemReporter.referenceContext = referenceContext;
2757 return problemReporter;
2760 * Reconsider the entire source looking for inconsistencies in {} () []
2762 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
2764 scanner.wasAcr = false;
2765 boolean anomaliesDetected = false;
2767 char[] source = scanner.source;
2768 int[] leftCount = { 0, 0, 0 };
2769 int[] rightCount = { 0, 0, 0 };
2770 int[] depths = { 0, 0, 0 };
2771 int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] };
2772 int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] };
2773 int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] };
2774 int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] };
2775 scanner.currentPosition = scanner.initialPosition; //starting point (first-zero-based char)
2776 while (scanner.currentPosition < scanner.eofPosition) { //loop for jumping over comments
2778 // ---------Consume white space and handles startPosition---------
2779 boolean isWhiteSpace;
2781 scanner.startPosition = scanner.currentPosition;
2782 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2783 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
2785 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
2786 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
2787 // only record line positions we have not recorded yet
2788 scanner.pushLineSeparator();
2791 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
2793 } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
2795 // -------consume token until } is found---------
2797 switch (scanner.currentCharacter) {
2800 int index = leftCount[CurlyBracket]++;
2801 if (index == leftPositions[CurlyBracket].length) {
2802 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
2803 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
2805 leftPositions[CurlyBracket][index] = scanner.startPosition;
2806 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
2811 int index = rightCount[CurlyBracket]++;
2812 if (index == rightPositions[CurlyBracket].length) {
2813 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
2814 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
2816 rightPositions[CurlyBracket][index] = scanner.startPosition;
2817 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
2822 int index = leftCount[RoundBracket]++;
2823 if (index == leftPositions[RoundBracket].length) {
2824 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
2825 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
2827 leftPositions[RoundBracket][index] = scanner.startPosition;
2828 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
2833 int index = rightCount[RoundBracket]++;
2834 if (index == rightPositions[RoundBracket].length) {
2835 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
2836 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
2838 rightPositions[RoundBracket][index] = scanner.startPosition;
2839 rightDepths[RoundBracket][index] = --depths[RoundBracket];
2844 int index = leftCount[SquareBracket]++;
2845 if (index == leftPositions[SquareBracket].length) {
2846 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
2847 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
2849 leftPositions[SquareBracket][index] = scanner.startPosition;
2850 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
2855 int index = rightCount[SquareBracket]++;
2856 if (index == rightPositions[SquareBracket].length) {
2857 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
2858 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
2860 rightPositions[SquareBracket][index] = scanner.startPosition;
2861 rightDepths[SquareBracket][index] = --depths[SquareBracket];
2866 if (scanner.getNextChar('\\')) {
2867 scanner.scanEscapeCharacter();
2868 } else { // consume next character
2869 scanner.unicodeAsBackSlash = false;
2870 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2871 // scanner.getNextUnicodeChar();
2873 if (scanner.withoutUnicodePtr != 0) {
2874 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2878 scanner.getNextChar('\'');
2881 case '"' : // consume next character
2882 scanner.unicodeAsBackSlash = false;
2883 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2884 // scanner.getNextUnicodeChar();
2886 if (scanner.withoutUnicodePtr != 0) {
2887 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2890 while (scanner.currentCharacter != '"') {
2891 if (scanner.currentCharacter == '\r') {
2892 if (source[scanner.currentPosition] == '\n')
2893 scanner.currentPosition++;
2894 break; // the string cannot go further that the line
2896 if (scanner.currentCharacter == '\n') {
2897 break; // the string cannot go further that the line
2899 if (scanner.currentCharacter == '\\') {
2900 scanner.scanEscapeCharacter();
2902 // 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;
2916 if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment
2918 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2919 //-------------unicode traitement ------------
2920 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2921 scanner.currentPosition++;
2922 while (source[scanner.currentPosition] == 'u') {
2923 scanner.currentPosition++;
2925 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2927 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2929 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2931 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2932 || c4 < 0) { //error don't care of the value
2933 scanner.currentCharacter = 'A';
2934 } //something different from \n and \r
2936 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2939 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
2941 scanner.startPosition = scanner.currentPosition;
2942 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2943 //-------------unicode traitement ------------
2944 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2945 scanner.currentPosition++;
2946 while (source[scanner.currentPosition] == 'u') {
2947 scanner.currentPosition++;
2949 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2951 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2953 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2955 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2956 || c4 < 0) { //error don't care of the value
2957 scanner.currentCharacter = 'A';
2958 } //something different from \n and \r
2960 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2964 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
2965 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
2966 // only record line positions we have not recorded yet
2967 scanner.pushLineSeparator();
2968 if (this.scanner.taskTags != null) {
2969 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
2975 if (test > 0) { //traditional and annotation comment
2976 boolean star = false;
2977 // consume next character
2978 scanner.unicodeAsBackSlash = false;
2979 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2980 // scanner.getNextUnicodeChar();
2982 if (scanner.withoutUnicodePtr != 0) {
2983 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
2986 if (scanner.currentCharacter == '*') {
2990 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
2991 //-------------unicode traitement ------------
2992 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2993 scanner.currentPosition++;
2994 while (source[scanner.currentPosition] == 'u') {
2995 scanner.currentPosition++;
2997 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
2999 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3001 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3003 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3004 || c4 < 0) { //error don't care of the value
3005 scanner.currentCharacter = 'A';
3006 } //something different from * and /
3008 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3011 //loop until end of comment */
3012 while ((scanner.currentCharacter != '/') || (!star)) {
3013 star = scanner.currentCharacter == '*';
3015 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
3016 //-------------unicode traitement ------------
3017 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3018 scanner.currentPosition++;
3019 while (source[scanner.currentPosition] == 'u') {
3020 scanner.currentPosition++;
3022 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3024 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3026 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3028 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15
3029 || c4 < 0) { //error don't care of the value
3030 scanner.currentCharacter = 'A';
3031 } //something different from * and /
3033 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3037 if (this.scanner.taskTags != null) {
3038 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
3045 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3046 scanner.scanIdentifierOrKeyword(false);
3049 if (Character.isDigit(scanner.currentCharacter)) {
3050 scanner.scanNumber(false);
3054 //-----------------end switch while try--------------------
3055 } catch (IndexOutOfBoundsException e) {
3056 break; // read until EOF
3057 } catch (InvalidInputException e) {
3058 return false; // no clue
3061 if (scanner.recordLineSeparator) {
3062 // compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3065 // check placement anomalies against other kinds of brackets
3066 for (int kind = 0; kind < BracketKinds; kind++) {
3067 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3068 int start = leftPositions[kind][leftIndex]; // deepest first
3069 // find matching closing bracket
3070 int depth = leftDepths[kind][leftIndex];
3072 for (int i = 0; i < rightCount[kind]; i++) {
3073 int pos = rightPositions[kind][i];
3074 // want matching bracket further in source with same depth
3075 if ((pos > start) && (depth == rightDepths[kind][i])) {
3080 if (end < 0) { // did not find a good closing match
3081 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
3084 // check if even number of opening/closing other brackets in between this pair of brackets
3086 for (int otherKind = 0;(balance == 0) && (otherKind < BracketKinds); otherKind++) {
3087 for (int i = 0; i < leftCount[otherKind]; i++) {
3088 int pos = leftPositions[otherKind][i];
3089 if ((pos > start) && (pos < end))
3092 for (int i = 0; i < rightCount[otherKind]; i++) {
3093 int pos = rightPositions[otherKind][i];
3094 if ((pos > start) && (pos < end))
3098 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly
3103 // too many opening brackets ?
3104 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3105 anomaliesDetected = true;
3106 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, compilationUnit.compilationResult);
3108 // too many closing brackets ?
3109 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3110 anomaliesDetected = true;
3111 problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
3113 if (anomaliesDetected)
3117 return anomaliesDetected;
3118 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3119 return anomaliesDetected;
3120 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3121 return anomaliesDetected;
3125 protected void pushOnAstLengthStack(int pos) {
3127 astLengthStack[++astLengthPtr] = pos;
3128 } catch (IndexOutOfBoundsException e) {
3129 int oldStackLength = astLengthStack.length;
3130 int[] oldPos = astLengthStack;
3131 astLengthStack = new int[oldStackLength + StackIncrement];
3132 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3133 astLengthStack[astLengthPtr] = pos;
3137 protected void pushOnAstStack(AstNode node) {
3138 /*add a new obj on top of the ast stack
3139 astPtr points on the top*/
3142 astStack[++astPtr] = node;
3143 } catch (IndexOutOfBoundsException e) {
3144 int oldStackLength = astStack.length;
3145 AstNode[] oldStack = astStack;
3146 astStack = new AstNode[oldStackLength + AstStackIncrement];
3147 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3148 astPtr = oldStackLength;
3149 astStack[astPtr] = node;
3153 astLengthStack[++astLengthPtr] = 1;
3154 } catch (IndexOutOfBoundsException e) {
3155 int oldStackLength = astLengthStack.length;
3156 int[] oldPos = astLengthStack;
3157 astLengthStack = new int[oldStackLength + AstStackIncrement];
3158 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3159 astLengthStack[astLengthPtr] = 1;