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;
12 import java.util.ArrayList;
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
15 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
16 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
17 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
18 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
19 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
20 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
21 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
22 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
23 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
26 import net.sourceforge.phpeclipse.phpeditor.PHPString;
27 import org.eclipse.core.resources.IFile;
28 public class Parser //extends PHPParserSuperclass
29 implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
30 //internal data for the automat
31 protected final static int StackIncrement = 255;
32 protected int stateStackTop;
33 protected int[] stack = new int[StackIncrement];
34 public int firstToken; // handle for multiple parsing goals
35 public int lastAct; //handle for multiple parsing goals
36 protected RecoveredElement currentElement;
37 public static boolean VERBOSE_RECOVERY = false;
38 protected boolean diet = false; //tells the scanner to jump over some
39 // parts of the code/expressions like
42 public Scanner scanner;
43 private ArrayList phpList;
44 private int currentPHPString;
45 private boolean phpEnd;
46 // private static HashMap keywordMap = null;
52 // row counter for syntax errors:
54 // column counter for syntax errors:
58 // // current identifier
62 private String stringValue;
63 /** Contains the current expression. */
64 // private StringBuffer expression;
65 private boolean phpMode;
66 protected int modifiers;
67 protected int modifiersSourceStart;
69 this.currentPHPString = 0;
70 // PHPParserSuperclass.fileToParse = fileToParse;
73 this.token = TokenNameEOF;
76 // this.columnCount = 0;
79 this.initializeScanner();
81 public void setFileToParse(IFile fileToParse) {
82 this.currentPHPString = 0;
83 // PHPParserSuperclass.fileToParse = fileToParse;
86 this.token = TokenNameEOF;
88 this.initializeScanner();
91 * ClassDeclaration Constructor.
95 * Description of Parameter
98 public Parser(IFile fileToParse) {
99 // if (keywordMap == null) {
100 // keywordMap = new HashMap();
101 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
102 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
105 this.currentPHPString = 0;
106 // PHPParserSuperclass.fileToParse = fileToParse;
109 this.token = TokenNameEOF;
111 // this.rowCount = 1;
112 // this.columnCount = 0;
115 this.initializeScanner();
117 public void initializeScanner() {
118 this.scanner = new Scanner(false, false, false, false);
121 * Create marker for the parse error
123 // private void setMarker(String message, int charStart, int charEnd, int
125 // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
128 * This method will throw the SyntaxError. It will add the good lines and
129 * columns to the Error
133 * @throws SyntaxError
136 private void throwSyntaxError(String error) {
137 int problemStartPosition = scanner.getCurrentTokenStartPosition();
138 int problemEndPosition = scanner.getCurrentTokenEndPosition();
139 throwSyntaxError(error, problemStartPosition, problemEndPosition);
142 * This method will throw the SyntaxError. It will add the good lines and
143 * columns to the Error
147 * @throws SyntaxError
150 // private void throwSyntaxError(String error, int startRow) {
151 // throw new SyntaxError(startRow, 0, " ", error);
153 private void throwSyntaxError(String error, int problemStartPosition,
154 int problemEndPosition) {
156 .phpParsingError(new String[]{error}, problemStartPosition,
157 problemEndPosition, referenceContext,
158 compilationUnit.compilationResult);
159 throw new SyntaxError(1, 0, " ", error);
161 private void reportSyntaxError(String error, int problemStartPosition,
162 int problemEndPosition) {
164 .phpParsingError(new String[]{error}, problemStartPosition,
165 problemEndPosition, referenceContext,
166 compilationUnit.compilationResult);
168 private void reportSyntaxWarning(String error, int problemStartPosition,
169 int problemEndPosition) {
170 problemReporter.phpParsingWarning(new String[]{error},
171 problemStartPosition, problemEndPosition, referenceContext,
172 compilationUnit.compilationResult);
175 * Method Declaration.
179 // private void getChar() {
180 // if (str.length() > chIndx) {
181 // ch = str.charAt(chIndx++);
186 // chIndx = str.length() + 1;
188 // // token = TokenNameEOF;
192 * gets the next token from input
194 private void getNextToken() {
196 token = scanner.getNextToken();
198 int currentEndPosition = scanner.getCurrentTokenEndPosition();
199 int currentStartPosition = scanner.getCurrentTokenStartPosition();
201 .print(currentStartPosition + "," + currentEndPosition + ": ");
202 System.out.println(scanner.toStringAction(token));
204 } catch (InvalidInputException e) {
205 token = TokenNameERROR;
210 * Get a number. if it's a <code>double</code> the number will be stored in
211 * <code>doubleNumber</code> and the token will have the value
212 * {@link Parser#TokenNameDOUBLE_NUMBER}<br />
213 * if it's a <code>double</code> the number will be stored in <code>longNumber</code>
214 * and the token will have the value {@link Parser#TokenNameINT_NUMBER}
216 // private void getNumber() {
217 // StringBuffer inum = new StringBuffer();
219 // int numFormat = 10;
221 // // save first digit
222 // char firstCh = ch;
226 // // determine number conversions:
227 // if (firstCh == '0') {
256 // if (numFormat == 16) {
257 // while ((ch >= '0' && ch <= '9')
258 // || (ch >= 'a' && ch <= 'f')
259 // || (ch >= 'A' && ch <= 'F')) {
264 // while ((ch >= '0' && ch <= '9')
268 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
269 // if (ch == '.' && dFlag != ' ') {
272 // if ((dFlag == 'E') || (dFlag == 'e')) {
278 // if ((ch == '-') || (ch == '+')) {
291 // if (dFlag != ' ') {
292 // doubleNumber = new Double(inum.toString());
293 // token = TokenNameDoubleLiteral;
296 // longNumber = Long.valueOf(inum.toString(), numFormat);
297 // token = TokenNameIntegerLiteral;
301 // } catch (Throwable e) {
302 // throwSyntaxError("Number format error: " + inum.toString());
308 // * @param openChar the opening char ('\'', '"', '`')
309 // * @param typeString the type of string {@link
310 // #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
311 // * @param errorMsg the error message in case of parse error in the string
313 // private void getString(
314 // final char openChar,
315 // final int typeString,
316 // final String errorMsg) {
317 // StringBuffer sBuffer = new StringBuffer();
318 // boolean openString = true;
319 // int startRow = rowCount;
320 // while (str.length() > chIndx) {
321 // ch = str.charAt(chIndx++);
323 // sBuffer.append(ch);
324 // if (str.length() > chIndx) {
325 // ch = str.charAt(chIndx++);
326 // sBuffer.append(ch);
328 // } else if (ch == openChar) {
329 // openString = false;
331 // } else if (ch == '\n') {
333 // columnCount = chIndx;
335 // sBuffer.append(ch);
339 // if (typeString == TokenNameStringConstant) {
340 // throwSyntaxError(errorMsg, startRow);
342 // throwSyntaxError(errorMsg);
345 // token = typeString;
346 // stringValue = sBuffer.toString();
348 // public void htmlParserTester(String input) {
349 // int lineNumber = 1;
350 // int startLineNumber = 1;
351 // int startIndex = 0;
354 // boolean phpMode = false;
355 // boolean phpFound = false;
357 // phpList = new ArrayList();
358 // currentPHPString = 0;
362 // while (i < input.length()) {
363 // ch = input.charAt(i++);
367 // if ((!phpMode) && ch == '<') {
368 // ch2 = input.charAt(i++);
370 // ch2 = input.charAt(i++);
371 // if (Character.isWhitespace(ch2)) {
376 // startLineNumber = lineNumber;
378 // } else if (ch2 == 'p') {
379 // ch2 = input.charAt(i++);
381 // ch2 = input.charAt(i++);
386 // startLineNumber = lineNumber;
392 // } else if (ch2 == 'P') {
393 // ch2 = input.charAt(i++);
395 // ch2 = input.charAt(i++);
400 // startLineNumber = lineNumber;
413 // if (ch == '/' && i < input.length()) {
414 // ch2 = input.charAt(i++);
416 // while (i < input.length()) {
417 // ch = input.charAt(i++);
418 // if (ch == '?' && i < input.length()) {
419 // ch2 = input.charAt(i++);
428 // startLineNumber));
432 // } else if (ch == '\n') {
438 // } else if (ch2 == '*') {
439 // // multi-line comment
440 // while (i < input.length()) {
441 // ch = input.charAt(i++);
444 // } else if (ch == '*' && i < input.length()) {
445 // ch2 = input.charAt(i++);
456 // } else if (ch == '#') {
457 // while (i < input.length()) {
458 // ch = input.charAt(i++);
459 // if (ch == '?' && i < input.length()) {
460 // ch2 = input.charAt(i++);
466 // input.substring(startIndex, i - 2),
467 // startLineNumber));
471 // } else if (ch == '\n') {
477 // } else if (ch == '"') {
479 // while (i < input.length()) {
480 // ch = input.charAt(i++);
484 // ch == '\\' && i < input.length()) { // escape
486 // } else if (ch == '"') {
491 // } else if (ch == '\'') {
493 // while (i < input.length()) {
494 // ch = input.charAt(i++);
498 // ch == '\\' && i < input.length()) { // escape
500 // } else if (ch == '\'') {
507 // if (ch == '?' && i < input.length()) {
508 // ch2 = input.charAt(i++);
514 // input.substring(startIndex, i - 2),
515 // startLineNumber));
525 // "No PHP source code found.",
531 // "Open PHP tag at end of file.",
536 // input.substring(startIndex, i - 2),
537 // startLineNumber));
539 // // for (int j=0;j<phpList.size();j++) {
540 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
541 // // int startIndx = temp.length()-10;
542 // // if (startIndx<0) {
545 // // System.out.println(temp.substring(startIndx)+"?>");
547 // phpParserTester(null, 1);
548 // // PHPString temp;
549 // // for(int j=0;j<phpList.size();j++) {
550 // // temp = (PHPString) phpList.get(j);
551 // // parser.start(temp.getPHPString(), temp.getLineNumber());
554 // } catch (CoreException e) {
557 public void phpParserTester(String s, int rowCount) {
560 if (phpList.size() != 0) {
561 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
564 this.token = TokenNameEOF;
566 // this.rowCount = rowCount;
567 // this.columnCount = 0;
570 scanner.setSource(s.toCharArray());
571 scanner.setPHPMode(true);
575 if (token != TokenNameEOF && token != TokenNameERROR) {
578 if (token != TokenNameEOF) {
579 if (token == TokenNameERROR) {
580 throwSyntaxError("Scanner error (Found unknown token: "
581 + scanner.toStringAction(token) + ")");
583 if (token == TokenNameRPAREN) {
584 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
586 if (token == TokenNameRBRACE) {
587 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
589 if (token == TokenNameRBRACKET) {
590 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
592 if (token == TokenNameLPAREN) {
593 throwSyntaxError("Read character '('; end-of-file not reached.");
595 if (token == TokenNameLBRACE) {
596 throwSyntaxError("Read character '{'; end-of-file not reached.");
598 if (token == TokenNameLBRACKET) {
599 throwSyntaxError("Read character '['; end-of-file not reached.");
601 throwSyntaxError("End-of-file not reached.");
604 } catch (SyntaxError err) {
608 // setMarker(err.getMessage(), err.getLine(), ERROR);
609 // setMarker(err.getMessage(),
610 // scanner.getCurrentTokenStartPosition(),
611 // scanner.getCurrentTokenEndPosition(), ERROR);
613 // if an error occured,
614 // try to find keywords 'class' or 'function'
615 // to parse the rest of the string
616 while (token != TokenNameEOF && token != TokenNameERROR) {
617 if (token == TokenNameabstract || token == TokenNamefinal
618 || token == TokenNameclass || token == TokenNamefunction) {
623 if (token == TokenNameEOF || token == TokenNameERROR) {
629 public void init(String s) {
631 this.token = TokenNameEOF;
633 // this.rowCount = 1;
634 // this.columnCount = 0;
636 this.phpMode = false;
637 /* scanner initialization */
638 scanner.setSource(s.toCharArray());
639 scanner.setPHPMode(false);
641 protected void initialize(boolean phpMode) {
642 compilationUnit = null;
643 referenceContext = null;
645 this.token = TokenNameEOF;
647 // this.rowCount = 1;
648 // this.columnCount = 0;
650 this.phpMode = phpMode;
651 scanner.setPHPMode(phpMode);
654 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
657 public void parse(String s) {
662 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
665 protected void parse() {
669 if (token != TokenNameEOF && token != TokenNameERROR) {
672 if (token != TokenNameEOF) {
673 if (token == TokenNameERROR) {
674 throwSyntaxError("Scanner error (Found unknown token: "
675 + scanner.toStringAction(token) + ")");
677 if (token == TokenNameRPAREN) {
678 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
680 if (token == TokenNameRBRACE) {
681 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
683 if (token == TokenNameRBRACKET) {
684 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
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.");
695 throwSyntaxError("End-of-file not reached.");
698 } catch (SyntaxError sytaxErr1) {
699 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
701 // setMarker(sytaxErr1.getMessage(),
702 // scanner.getCurrentTokenStartPosition(),
703 // scanner.getCurrentTokenEndPosition(), ERROR);
705 // if an error occured,
706 // try to find keywords 'class' or 'function'
707 // to parse the rest of the string
708 while (token != TokenNameEOF && token != TokenNameERROR) {
709 if (token == TokenNameabstract || token == TokenNamefinal
710 || token == TokenNameclass || token == TokenNamefunction) {
715 if (token == TokenNameEOF || token == TokenNameERROR) {
718 } catch (SyntaxError sytaxErr2) {
719 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
721 // setMarker(sytaxErr2.getMessage(),
722 // scanner.getCurrentTokenStartPosition(),
723 // scanner.getCurrentTokenEndPosition(), ERROR);
729 // public PHPOutlineInfo parseInfo(Object parent, String s) {
730 // PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
731 // // Stack stack = new Stack();
732 // // stack.push(outlineInfo.getDeclarations());
734 // this.token = TokenNameEOF;
735 // // this.chIndx = 0;
736 // // this.rowCount = 1;
737 // // this.columnCount = 0;
738 // this.phpEnd = false;
739 // this.phpMode = false;
740 // scanner.setSource(s.toCharArray());
741 // scanner.setPHPMode(false);
744 // parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
746 // return outlineInfo;
748 private boolean isVariable() {
749 return token == TokenNameVariable || token == TokenNamethis;
751 // private void parseDeclarations(PHPOutlineInfo outlineInfo,
752 // OutlineableWithChildren current, boolean goBack) {
754 // // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
755 // PHPSegmentWithChildren temp;
757 // IPreferenceStore store =
758 // PHPeclipsePlugin.getDefault().getPreferenceStore();
760 // while (token != TokenNameEOF && token != TokenNameERROR) {
761 // if (token == TokenNameVariable) {
762 // ident = scanner.getCurrentIdentifierSource();
763 // outlineInfo.addVariable(new String(ident));
765 // } else if (token == TokenNamevar) {
767 // if (token == TokenNameVariable
768 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
769 // ident = scanner.getCurrentIdentifierSource();
770 // //substring(1) added because PHPVarDeclaration doesn't
771 // // need the $ anymore
772 // String variableName = new String(ident).substring(1);
773 // outlineInfo.addVariable(variableName);
775 // if (token != TokenNameSEMICOLON) {
777 // ident = scanner.getCurrentTokenSource();
778 // if (token > TokenNameKEYWORD) {
779 // current.add(new PHPVarDeclaration(current, variableName,
780 // // chIndx - ident.length,
781 // scanner.getCurrentTokenStartPosition(), new String(ident)));
784 // case TokenNameVariable :
785 // case TokenNamethis :
786 // current.add(new PHPVarDeclaration(current, variableName,
789 // scanner.getCurrentTokenStartPosition(), new String(
792 // case TokenNameIdentifier :
793 // current.add(new PHPVarDeclaration(current, variableName,
796 // scanner.getCurrentTokenStartPosition(), new String(
799 // case TokenNameDoubleLiteral :
800 // current.add(new PHPVarDeclaration(current, variableName
804 // scanner.getCurrentTokenStartPosition(), new String(
807 // case TokenNameIntegerLiteral :
808 // current.add(new PHPVarDeclaration(current, variableName,
811 // scanner.getCurrentTokenStartPosition(), new String(
814 // case TokenNameStringInterpolated :
815 // case TokenNameStringLiteral :
816 // current.add(new PHPVarDeclaration(current, variableName,
819 // scanner.getCurrentTokenStartPosition(), new String(
822 // case TokenNameStringConstant :
823 // current.add(new PHPVarDeclaration(current, variableName,
826 // scanner.getCurrentTokenStartPosition(), new String(
830 // current.add(new PHPVarDeclaration(current, variableName,
833 // scanner.getCurrentTokenStartPosition()));
838 // ident = scanner.getCurrentIdentifierSource();
839 // current.add(new PHPVarDeclaration(current, variableName,
840 // // chIndx - ident.length
841 // scanner.getCurrentTokenStartPosition()));
844 // } else if (token == TokenNamefunction) {
846 // if (token == TokenNameAND) {
849 // if (token == TokenNameIdentifier
850 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
851 // ident = scanner.getCurrentIdentifierSource();
852 // outlineInfo.addVariable(new String(ident));
853 // temp = new PHPFunctionDeclaration(current, new String(ident),
854 // // chIndx - ident.length
855 // scanner.getCurrentTokenStartPosition());
856 // current.add(temp);
858 // parseDeclarations(outlineInfo, temp, true);
860 // } else if (token == TokenNameclass) {
862 // if (token == TokenNameIdentifier
863 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
864 // ident = scanner.getCurrentIdentifierSource();
865 // outlineInfo.addVariable(new String(ident));
866 // temp = new PHPClassDeclaration(current, new String(ident),
867 // // chIndx - ident.len
868 // scanner.getCurrentTokenStartPosition());
869 // current.add(temp);
870 // // stack.push(temp);
872 // //skip tokens for classname, extends and others until
873 // // we have the opening '{'
874 // while (token != TokenNameLBRACE && token != TokenNameEOF
875 // && token != TokenNameERROR) {
878 // parseDeclarations(outlineInfo, temp, true);
881 // } else if ((token == TokenNameLBRACE)
882 // || (token == TokenNameDOLLAR_LBRACE)) {
885 // } else if (token == TokenNameRBRACE) {
888 // if (counter == 0 && goBack) {
891 // } else if (token == TokenNamerequire || token == TokenNamerequire_once
892 // || token == TokenNameinclude || token == TokenNameinclude_once) {
893 // ident = scanner.getCurrentTokenSource();
895 // int startPosition = scanner.getCurrentTokenStartPosition();
897 // char[] expr = scanner.getCurrentTokenSource(startPosition);
898 // outlineInfo.addVariable(new String(ident));
899 // current.add(new PHPReqIncDeclaration(current, new String(ident),
900 // // chIndx - ident.length,
901 // startPosition, new String(expr)));
907 // } catch (SyntaxError sytaxErr) {
909 // // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
910 // // setMarker(sytaxErr.getMessage(),
911 // // scanner.getCurrentTokenStartPosition(),
912 // // scanner.getCurrentTokenEndPosition(), ERROR);
913 // // } catch (CoreException e) {
917 private void statementList() {
919 statement(TokenNameEOF);
920 if ((token == TokenNameRBRACE) || (token == TokenNamecase)
921 || (token == TokenNamedefault) || (token == TokenNameelse)
922 || (token == TokenNameelseif) || (token == TokenNameendif)
923 || (token == TokenNameendfor) || (token == TokenNameendforeach)
924 || (token == TokenNameendwhile) || (token == TokenNameendswitch)
925 || (token == TokenNameEOF) || (token == TokenNameERROR)) {
930 private void functionBody(MethodDeclaration methodDecl) {
931 // '{' [statement-list] '}'
932 if (token == TokenNameLBRACE) {
935 throwSyntaxError("'{' expected in compound-statement.");
937 if (token != TokenNameRBRACE) {
940 if (token == TokenNameRBRACE) {
941 methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
944 throwSyntaxError("'}' expected in compound-statement.");
947 private void statement(int previousToken) {
948 // if (token > TokenNameKEYWORD && token != TokenNamelist && token !=
950 // char[] ident = scanner.getCurrentIdentifierSource();
951 // String keyword = new String(ident);
952 if (token == TokenNameAT) {
954 if (token != TokenNamerequire && token != TokenNamerequire_once
955 && token != TokenNameinclude && token != TokenNameinclude_once
956 && token != TokenNameIdentifier && token != TokenNameVariable
957 && token != TokenNamethis && token != TokenNameStringInterpolated) {
958 throwSyntaxError("identifier expected after '@'.");
961 if (token == TokenNameinclude || token == TokenNameinclude_once) {
963 if (token == TokenNameLPAREN) {
965 if (token == TokenNameSEMICOLON) {
968 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
969 throwSyntaxError("';' expected after 'include' or 'include_once'.");
974 concatenationExpression();
977 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
980 if (token == TokenNameLPAREN) {
982 if (token == TokenNameSEMICOLON) {
985 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
986 throwSyntaxError("';' expected after 'require' or 'require_once'.");
991 concatenationExpression();
994 } else if (token == TokenNameif) {
996 if (token == TokenNameLPAREN) {
999 throwSyntaxError("'(' expected after 'if' keyword.");
1002 if (token == TokenNameRPAREN) {
1005 throwSyntaxError("')' expected after 'if' condition.");
1009 } else if (token == TokenNameswitch) {
1011 if (token == TokenNameLPAREN) {
1014 throwSyntaxError("'(' expected after 'switch' keyword.");
1017 if (token == TokenNameRPAREN) {
1020 throwSyntaxError("')' expected after 'switch' condition.");
1024 } else if (token == TokenNamefor) {
1026 if (token == TokenNameLPAREN) {
1029 throwSyntaxError("'(' expected after 'for' keyword.");
1031 if (token == TokenNameSEMICOLON) {
1035 if (token == TokenNameSEMICOLON) {
1038 throwSyntaxError("';' expected after 'for'.");
1041 if (token == TokenNameSEMICOLON) {
1045 if (token == TokenNameSEMICOLON) {
1048 throwSyntaxError("';' expected after 'for'.");
1051 if (token == TokenNameRPAREN) {
1055 if (token == TokenNameRPAREN) {
1058 throwSyntaxError("')' expected after 'for'.");
1063 } else if (token == TokenNamewhile) {
1065 if (token == TokenNameLPAREN) {
1068 throwSyntaxError("'(' expected after 'while' keyword.");
1071 if (token == TokenNameRPAREN) {
1074 throwSyntaxError("')' expected after 'while' condition.");
1078 } else if (token == TokenNamedo) {
1080 if (token == TokenNameLBRACE) {
1083 throwSyntaxError("'{' expected after 'do' keyword.");
1085 if (token != TokenNameRBRACE) {
1088 if (token == TokenNameRBRACE) {
1091 throwSyntaxError("'}' expected after 'do' keyword.");
1093 if (token == TokenNamewhile) {
1095 if (token == TokenNameLPAREN) {
1098 throwSyntaxError("'(' expected after 'while' keyword.");
1101 if (token == TokenNameRPAREN) {
1104 throwSyntaxError("')' expected after 'while' condition.");
1107 throwSyntaxError("'while' expected after 'do' keyword.");
1109 if (token == TokenNameSEMICOLON) {
1112 if (token != TokenNameStopPHP) {
1113 throwSyntaxError("';' expected after do-while statement.");
1118 } else if (token == TokenNameforeach) {
1120 if (token == TokenNameLPAREN) {
1123 throwSyntaxError("'(' expected after 'foreach' keyword.");
1126 if (token == TokenNameas) {
1129 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1132 if (token == TokenNameEQUAL_GREATER) {
1136 if (token == TokenNameRPAREN) {
1139 throwSyntaxError("')' expected after 'foreach' expression.");
1143 } else if (token == TokenNamecontinue || token == TokenNamebreak
1144 || token == TokenNamereturn) {
1146 if (token != TokenNameSEMICOLON) {
1149 if (token == TokenNameSEMICOLON) {
1152 if (token != TokenNameStopPHP) {
1153 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1158 } else if (token == TokenNameecho) {
1161 if (token == TokenNameSEMICOLON) {
1164 if (token != TokenNameStopPHP) {
1165 throwSyntaxError("';' expected after 'echo' statement.");
1170 // } else if (token == TokenNameprint) {
1173 // if (token == TokenNameSEMICOLON) {
1176 // if (token != TokenNameStopPHP) {
1177 // throwSyntaxError("';' expected after 'print' statement.");
1182 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1185 if (token == TokenNameSEMICOLON) {
1188 if (token != TokenNameStopPHP) {
1189 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1194 } else if (token == TokenNameunset) {
1196 if (token == TokenNameLPAREN) {
1199 throwSyntaxError("'(' expected after 'unset' statement.");
1202 if (token == TokenNameRPAREN) {
1205 throwSyntaxError("')' expected after 'unset' statement.");
1207 if (token == TokenNameSEMICOLON) {
1210 if (token != TokenNameStopPHP) {
1211 throwSyntaxError("';' expected after 'unset' statement.");
1216 // } else if (token == TokenNameexit || token == TokenNamedie) {
1218 // if (token != TokenNameSEMICOLON) {
1221 // if (token == TokenNameSEMICOLON) {
1224 // if (token != TokenNameStopPHP) {
1225 // throwSyntaxError("';' expected after 'exit' or 'die'
1231 // } else if (token == TokenNamedefine) {
1233 // if (token == TokenNameLPAREN) {
1236 // throwSyntaxError("'(' expected after 'define' keyword.");
1239 // if (token == TokenNameCOMMA) {
1242 // throwSyntaxError("',' expected after first 'define' constant.");
1245 // if (token == TokenNameCOMMA) {
1249 // if (token == TokenNameRPAREN) {
1252 // throwSyntaxError("')' expected after 'define' statement.");
1254 // if (token == TokenNameSEMICOLON) {
1257 // if (token != TokenNameStopPHP) {
1258 // throwSyntaxError("';' expected after 'define' statement.");
1263 } else if (token == TokenNamefunction) {
1264 MethodDeclaration methodDecl = new MethodDeclaration(
1265 this.compilationUnit.compilationResult);
1266 methodDecl.declarationSourceStart = scanner
1267 .getCurrentTokenStartPosition();
1269 functionDefinition(methodDecl);
1271 } else if (token == TokenNamefinal || token == TokenNameabstract
1272 || token == TokenNameclass || token == TokenNameinterface) {
1273 TypeDeclaration typeDecl = new TypeDeclaration(
1274 this.compilationUnit.compilationResult);
1275 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1276 // default super class
1277 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1278 compilationUnit.types.add(typeDecl);
1280 pushOnAstStack(typeDecl);
1281 unticked_class_declaration_statement(typeDecl);
1282 // classBody(typeDecl);
1289 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1290 } else if (token == TokenNameLBRACE) {
1292 if (token != TokenNameRBRACE) {
1295 if (token == TokenNameRBRACE) {
1299 throwSyntaxError("'}' expected.");
1302 if (token != TokenNameSEMICOLON) {
1305 if (token == TokenNameSEMICOLON) {
1309 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1310 throwSyntaxError("';' expected after expression (Found token: "
1311 + scanner.toStringAction(token) + ")");
1317 private void unset_variables() {
1320 // | unset_variables ',' unset_variable
1325 if (token != TokenNameCOMMA) {
1331 private final void initializeModifiers() {
1333 this.modifiersSourceStart = -1;
1335 private final void checkAndSetModifiers(int flag) {
1336 this.modifiers |= flag;
1337 if (this.modifiersSourceStart < 0)
1338 this.modifiersSourceStart = this.scanner.startPosition;
1340 private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1341 initializeModifiers();
1342 if (token == TokenNameinterface) {
1343 // interface_entry T_STRING
1344 // interface_extends_list
1345 // '{' class_statement_list '}'
1346 checkAndSetModifiers(AccInterface);
1348 typeDecl.modifiers = this.modifiers;
1349 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1350 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1351 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1352 typeDecl.name = scanner.getCurrentIdentifierSource();
1353 if (token > TokenNameKEYWORD) {
1354 throwSyntaxError("Don't use a keyword for interface declaration ["
1355 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1356 typeDecl.sourceEnd);
1359 interface_extends_list();
1361 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1362 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1363 typeDecl.name = new char[]{' '};
1364 throwSyntaxError("Interface name expected after keyword 'interface'.",
1365 typeDecl.sourceStart, typeDecl.sourceEnd);
1369 // class_entry_type T_STRING extends_from
1371 // '{' class_statement_list'}'
1373 typeDecl.modifiers = this.modifiers;
1375 //identifier 'extends' identifier
1376 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1377 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1378 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1379 typeDecl.name = scanner.getCurrentIdentifierSource();
1380 if (token > TokenNameKEYWORD) {
1381 throwSyntaxError("Don't use a keyword for class declaration ["
1382 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1383 typeDecl.sourceEnd);
1388 // | T_EXTENDS fully_qualified_class_name
1389 if (token == TokenNameextends) {
1391 if (token == TokenNameIdentifier) {
1394 throwSyntaxError("Class name expected after keyword 'extends'.",
1395 scanner.getCurrentTokenStartPosition(), scanner
1396 .getCurrentTokenEndPosition());
1401 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1402 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1403 typeDecl.name = new char[]{' '};
1404 throwSyntaxError("Class name expected after keyword 'class'.",
1405 typeDecl.sourceStart, typeDecl.sourceEnd);
1409 // '{' class_statement_list '}'
1410 if (token == TokenNameLBRACE) {
1412 if (token != TokenNameRBRACE) {
1413 class_statement_list();
1415 if (token == TokenNameRBRACE) {
1416 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1419 throwSyntaxError("'}' expected at end of class body.");
1422 throwSyntaxError("'{' expected at start of class body.");
1425 private void class_entry_type() {
1427 // | T_ABSTRACT T_CLASS
1428 // | T_FINAL T_CLASS
1429 if (token == TokenNameclass) {
1431 } else if (token == TokenNameabstract) {
1432 checkAndSetModifiers(AccAbstract);
1434 if (token != TokenNameclass) {
1435 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1438 } else if (token == TokenNamefinal) {
1439 checkAndSetModifiers(AccFinal);
1441 if (token != TokenNameclass) {
1442 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1446 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1449 private void interface_extends_list() {
1451 // | T_EXTENDS interface_list
1452 if (token == TokenNameextends) {
1457 private void implements_list() {
1459 // | T_IMPLEMENTS interface_list
1460 if (token == TokenNameimplements) {
1465 private void interface_list() {
1467 // fully_qualified_class_name
1468 //| interface_list ',' fully_qualified_class_name
1470 if (token == TokenNameIdentifier) {
1473 throwSyntaxError("Interface name expected after keyword 'implements'.");
1475 if (token != TokenNameCOMMA) {
1481 // private void classBody(TypeDeclaration typeDecl) {
1482 // //'{' [class-element-list] '}'
1483 // if (token == TokenNameLBRACE) {
1485 // if (token != TokenNameRBRACE) {
1486 // class_statement_list();
1488 // if (token == TokenNameRBRACE) {
1489 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1492 // throwSyntaxError("'}' expected at end of class body.");
1495 // throwSyntaxError("'{' expected at start of class body.");
1498 private void class_statement_list() {
1501 } while (token == TokenNamepublic || token == TokenNameprotected
1502 || token == TokenNameprivate || token == TokenNamestatic
1503 || token == TokenNameabstract || token == TokenNamefinal
1504 || token == TokenNamefunction || token == TokenNamevar);
1506 private void class_statement() {
1508 // variable_modifiers class_variable_declaration ';'
1509 // | class_constant_declaration ';'
1510 // | method_modifiers T_FUNCTION is_reference T_STRING
1511 // '(' parameter_list ')' method_body
1512 initializeModifiers();
1513 if (token == TokenNamevar) {
1514 checkAndSetModifiers(AccPublic);
1515 problemReporter.phpVarDeprecatedWarning(scanner
1516 .getCurrentTokenStartPosition(),
1517 scanner.getCurrentTokenEndPosition(), referenceContext,
1518 compilationUnit.compilationResult);
1520 class_variable_declaration();
1522 boolean hasModifiers = member_modifiers();
1523 if (token == TokenNamefunction) {
1524 if (!hasModifiers) {
1525 checkAndSetModifiers(AccPublic);
1527 MethodDeclaration methodDecl = new MethodDeclaration(
1528 this.compilationUnit.compilationResult);
1529 methodDecl.declarationSourceStart = scanner
1530 .getCurrentTokenStartPosition();
1531 methodDecl.modifiers = this.modifiers;
1533 functionDefinition(methodDecl);
1535 if (!hasModifiers) {
1536 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1538 class_variable_declaration();
1541 // if (token == TokenNamefunction) {
1542 // MethodDeclaration methodDecl = new MethodDeclaration(
1543 // this.compilationUnit.compilationResult);
1544 // methodDecl.declarationSourceStart = scanner
1545 // .getCurrentTokenStartPosition();
1547 // functionDefinition(methodDecl);
1548 // } else if (token == TokenNamevar) {
1552 // throwSyntaxError("'function' or 'var' expected.");
1555 // private void variable_modifiers() {
1556 // // variable_modifiers:
1557 // // non_empty_member_modifiers
1559 // initializeModifiers();
1560 // if (token == TokenNamevar) {
1561 // checkAndSetModifiers(AccPublic);
1562 // reportSyntaxError(
1563 // "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
1564 // modifier for field declarations.",
1565 // scanner.getCurrentTokenStartPosition(), scanner
1566 // .getCurrentTokenEndPosition());
1569 // if (!member_modifiers()) {
1570 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1571 // field declarations.");
1575 // private void method_modifiers() {
1576 // //method_modifiers:
1578 // //| non_empty_member_modifiers
1579 // initializeModifiers();
1580 // if (!member_modifiers()) {
1581 // checkAndSetModifiers(AccPublic);
1584 private boolean member_modifiers() {
1591 boolean foundToken = false;
1593 if (token == TokenNamepublic) {
1594 checkAndSetModifiers(AccPublic);
1597 } else if (token == TokenNameprotected) {
1598 checkAndSetModifiers(AccProtected);
1601 } else if (token == TokenNameprivate) {
1602 checkAndSetModifiers(AccPrivate);
1605 } else if (token == TokenNamestatic) {
1606 checkAndSetModifiers(AccStatic);
1609 } else if (token == TokenNameabstract) {
1610 checkAndSetModifiers(AccAbstract);
1613 } else if (token == TokenNamefinal) {
1614 checkAndSetModifiers(AccFinal);
1623 private void class_variable_declaration() {
1624 // class_variable_declaration:
1625 // class_variable_declaration ',' T_VARIABLE
1626 // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1628 // | T_VARIABLE '=' static_scalar
1630 if (token == TokenNameVariable) {
1632 if (token == TokenNameEQUAL) {
1637 if (token == TokenNamethis) {
1638 throwSyntaxError("'$this' not allowed after keyword 'public' 'protected' 'private' 'var'.");
1640 throwSyntaxError("Variable expected keyword 'public' 'protected' 'private' 'var'.");
1642 if (token != TokenNameCOMMA) {
1647 if (token != TokenNameSEMICOLON) {
1648 throwSyntaxError("';' expected after field declaration.");
1652 private void functionDefinition(MethodDeclaration methodDecl) {
1654 compilationUnit.types.add(methodDecl);
1656 AstNode node = astStack[astPtr];
1657 if (node instanceof TypeDeclaration) {
1658 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1659 if (typeDecl.methods == null) {
1660 typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1662 AbstractMethodDeclaration[] newMethods;
1667 newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1668 1, typeDecl.methods.length);
1669 newMethods[0] = methodDecl;
1670 typeDecl.methods = newMethods;
1674 functionDeclarator(methodDecl);
1675 functionBody(methodDecl);
1677 private void functionDeclarator(MethodDeclaration methodDecl) {
1678 //identifier '(' [parameter-list] ')'
1679 if (token == TokenNameAND) {
1682 if (token == TokenNameIdentifier) {
1683 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1684 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1685 methodDecl.selector = scanner.getCurrentIdentifierSource();
1687 if (token == TokenNameLPAREN) {
1690 throwSyntaxError("'(' expected in function declaration.");
1692 if (token != TokenNameRPAREN) {
1695 if (token != TokenNameRPAREN) {
1696 throwSyntaxError("')' expected in function declaration.");
1698 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1702 if (token > TokenNameKEYWORD) {
1703 throwSyntaxError("Don't use keyword for function declaration [" + token
1706 throwSyntaxError("Function name expected after keyword 'function'.");
1710 private void parameterList() {
1711 //parameter-declaration
1712 //parameter-list ',' parameter-declaration
1714 parameterDeclaration();
1715 if (token != TokenNameCOMMA) {
1721 private void parameterDeclaration() {
1723 //variable-reference
1724 if (token == TokenNameAND) {
1729 throwSyntaxError("Variable expected after reference operator '&'.");
1732 //variable '=' constant
1733 if (token == TokenNameVariable) {
1735 if (token == TokenNameEQUAL) {
1741 if (token == TokenNamethis) {
1742 throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1745 private void labeledStatementList() {
1746 if (token != TokenNamecase && token != TokenNamedefault) {
1747 throwSyntaxError("'case' or 'default' expected.");
1750 if (token == TokenNamecase) {
1752 expr(); //constant();
1753 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1755 if (token == TokenNamecase || token == TokenNamedefault) { // empty
1763 // else if (token == TokenNameSEMICOLON) {
1765 // "':' expected after 'case' keyword (Found token: " +
1766 // scanner.toStringAction(token) + ")",
1767 // scanner.getCurrentTokenStartPosition(),
1768 // scanner.getCurrentTokenEndPosition(),
1771 // if (token == TokenNamecase) { // empty case statement ?
1777 throwSyntaxError("':' character after 'case' constant expected (Found token: "
1778 + scanner.toStringAction(token) + ")");
1780 } else { // TokenNamedefault
1782 if (token == TokenNameCOLON) {
1786 throwSyntaxError("':' character after 'default' expected.");
1789 } while (token == TokenNamecase || token == TokenNamedefault);
1791 // public void labeledStatement() {
1792 // if (token == TokenNamecase) {
1795 // if (token == TokenNameDDOT) {
1799 // throwSyntaxError("':' character after 'case' constant expected.");
1802 // } else if (token == TokenNamedefault) {
1804 // if (token == TokenNameDDOT) {
1808 // throwSyntaxError("':' character after 'default' expected.");
1813 // public void expressionStatement() {
1815 // private void inclusionStatement() {
1817 // public void compoundStatement() {
1819 // public void selectionStatement() {
1822 // public void iterationStatement() {
1825 // public void jumpStatement() {
1828 // public void outputStatement() {
1831 // public void scopeStatement() {
1834 // public void flowStatement() {
1837 // public void definitionStatement() {
1839 private void ifStatement() {
1840 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1841 if (token == TokenNameCOLON) {
1843 if (token != TokenNameendif) {
1846 case TokenNameelse :
1848 if (token == TokenNameCOLON) {
1850 if (token != TokenNameendif) {
1854 if (token == TokenNameif) { //'else if'
1856 elseifStatementList();
1858 throwSyntaxError("':' expected after 'else'.");
1862 case TokenNameelseif :
1864 elseifStatementList();
1868 if (token != TokenNameendif) {
1869 throwSyntaxError("'endif' expected.");
1872 if (token != TokenNameSEMICOLON) {
1873 throwSyntaxError("';' expected after if-statement.");
1877 // statement [else-statement]
1878 statement(TokenNameEOF);
1879 if (token == TokenNameelseif) {
1881 if (token == TokenNameLPAREN) {
1884 throwSyntaxError("'(' expected after 'elseif' keyword.");
1887 if (token == TokenNameRPAREN) {
1890 throwSyntaxError("')' expected after 'elseif' condition.");
1893 } else if (token == TokenNameelse) {
1895 statement(TokenNameEOF);
1899 private void elseifStatementList() {
1903 case TokenNameelse :
1905 if (token == TokenNameCOLON) {
1907 if (token != TokenNameendif) {
1912 if (token == TokenNameif) { //'else if'
1915 throwSyntaxError("':' expected after 'else'.");
1919 case TokenNameelseif :
1927 private void elseifStatement() {
1928 if (token == TokenNameLPAREN) {
1931 if (token != TokenNameRPAREN) {
1932 throwSyntaxError("')' expected in else-if-statement.");
1935 if (token != TokenNameCOLON) {
1936 throwSyntaxError("':' expected in else-if-statement.");
1939 if (token != TokenNameendif) {
1944 private void switchStatement() {
1945 if (token == TokenNameCOLON) {
1946 // ':' [labeled-statement-list] 'endswitch' ';'
1948 labeledStatementList();
1949 if (token != TokenNameendswitch) {
1950 throwSyntaxError("'endswitch' expected.");
1953 if (token != TokenNameSEMICOLON) {
1954 throwSyntaxError("';' expected after switch-statement.");
1958 // '{' [labeled-statement-list] '}'
1959 if (token != TokenNameLBRACE) {
1960 throwSyntaxError("'{' expected in switch statement.");
1963 if (token != TokenNameRBRACE) {
1964 labeledStatementList();
1966 if (token != TokenNameRBRACE) {
1967 throwSyntaxError("'}' expected in switch statement.");
1972 private void forStatement() {
1973 if (token == TokenNameCOLON) {
1976 if (token != TokenNameendfor) {
1977 throwSyntaxError("'endfor' expected.");
1980 if (token != TokenNameSEMICOLON) {
1981 throwSyntaxError("';' expected after for-statement.");
1985 statement(TokenNameEOF);
1988 private void whileStatement() {
1989 // ':' statement-list 'endwhile' ';'
1990 if (token == TokenNameCOLON) {
1993 if (token != TokenNameendwhile) {
1994 throwSyntaxError("'endwhile' expected.");
1997 if (token != TokenNameSEMICOLON) {
1998 throwSyntaxError("';' expected after while-statement.");
2002 statement(TokenNameEOF);
2005 private void foreachStatement() {
2006 if (token == TokenNameCOLON) {
2009 if (token != TokenNameendforeach) {
2010 throwSyntaxError("'endforeach' expected.");
2013 if (token != TokenNameSEMICOLON) {
2014 throwSyntaxError("';' expected after foreach-statement.");
2018 statement(TokenNameEOF);
2021 // private void exitStatus() {
2022 // if (token == TokenNameLPAREN) {
2025 // throwSyntaxError("'(' expected in 'exit-status'.");
2027 // if (token != TokenNameRPAREN) {
2030 // if (token == TokenNameRPAREN) {
2033 // throwSyntaxError("')' expected after 'exit-status'.");
2036 private void expressionList() {
2039 if (token == TokenNameCOMMA) {
2046 private void expr() {
2047 //todo: find a better way to get the expression
2048 // expression = new StringBuffer();
2049 // for (int i = chIndx; i < str.length(); i++) {
2050 // if (str.charAt(i) == ';') {
2053 // expression.append(str.charAt(i));
2055 // if (token == TokenNameSTRING_CONSTANT || token ==
2056 // TokenNameINTERPOLATED_STRING) {
2059 logicalinclusiveorExpression();
2060 // while (token != TokenNameSEMICOLON) {
2065 private void expr_without_variable() {
2068 boolean castFlag = false;
2069 boolean arrayFlag = false;
2071 case TokenNameisset :
2072 case TokenNameempty :
2073 case TokenNameeval :
2074 case TokenNameinclude :
2075 case TokenNameinclude_once :
2076 case TokenNamerequire :
2077 case TokenNamerequire_once :
2078 internal_functions_in_yacc();
2085 // case TokenNamenull :
2088 // case TokenNamefalse :
2091 // case TokenNametrue :
2094 case TokenNameStringConstant :
2097 case TokenNameHEREDOC :
2098 case TokenNameStringInterpolated :
2099 case TokenNameStringLiteral :
2102 case TokenNameLPAREN :
2104 if (token == TokenNameIdentifier) {
2105 // check if identifier is a type:
2106 // ident = identifier;
2107 ident = scanner.getCurrentIdentifierSource();
2108 String str = new String(ident).toLowerCase();
2109 for (int i = 0; i < PHP_TYPES.length; i++) {
2110 if (PHP_TYPES[i].equals(str)) {
2112 if (PHP_TYPES[i].equals("array")) {
2121 if (arrayFlag && token == TokenNameLPAREN) {
2123 if (token == TokenNameRPAREN) {
2127 if (token != TokenNameRPAREN) {
2128 throwSyntaxError(") expected after 'array('.");
2132 if (token != TokenNameRPAREN) {
2133 throwSyntaxError(") expected after cast-type '" + str + "'.");
2141 if (token != TokenNameRPAREN) {
2142 throwSyntaxError(") expected in postfix-expression.");
2146 case TokenNameDoubleLiteral :
2149 case TokenNameIntegerLiteral :
2152 case TokenNameDOLLAR_LBRACE :
2155 if (token != TokenNameRBRACE) {
2156 throwSyntaxError("'}' expected after indirect variable token '${'.");
2160 case TokenNameVariable :
2161 case TokenNamethis :
2162 ident = scanner.getCurrentIdentifierSource();
2164 if (token == TokenNameLBRACE) {
2167 if (token != TokenNameRBRACE) {
2168 throwSyntaxError("'}' expected after variable '"
2169 + new String(ident) + "' in variable-expression.");
2172 } else if (token == TokenNameLPAREN) {
2174 if (token != TokenNameRPAREN) {
2176 if (token != TokenNameRPAREN) {
2177 throwSyntaxError("')' expected after variable '"
2178 + new String(ident) + "' in postfix-expression.");
2184 case TokenNameIdentifier :
2185 ident = scanner.getCurrentIdentifierSource();
2187 if (token == TokenNameLPAREN) {
2189 if (token != TokenNameRPAREN) {
2191 if (token != TokenNameRPAREN) {
2192 throwSyntaxError("')' expected after identifier '"
2193 + new String(ident) + "' in postfix-expression."
2194 + "(Found token: " + scanner.toStringAction(token) + ")");
2200 case TokenNamearray :
2201 // T_ARRAY '(' array_pair_list ')'
2203 if (token == TokenNameLPAREN) {
2205 if (token == TokenNameRPAREN) {
2210 if (token != TokenNameRPAREN) {
2211 throwSyntaxError("')' expected after keyword 'array'"
2212 + "(Found token: " + scanner.toStringAction(token) + ")");
2216 throwSyntaxError("'(' expected after keyword 'array'"
2217 + "(Found token: " + scanner.toStringAction(token) + ")");
2220 case TokenNameprint :
2224 case TokenNameexit :
2228 case TokenNamelist :
2230 if (token == TokenNameLPAREN) {
2232 if (token == TokenNameCOMMA) {
2236 if (token != TokenNameRPAREN) {
2237 throwSyntaxError("')' expected after 'list' keyword.");
2240 // if (token == TokenNameSET) {
2242 // logicalinclusiveorExpression();
2245 throwSyntaxError("'(' expected after 'list' keyword.");
2248 // case TokenNameexit :
2250 // if (token != TokenNameSEMICOLON) {
2253 // if (token == TokenNameSEMICOLON) {
2256 // if (token != TokenNameStopPHP) {
2257 // throwSyntaxError("';' expected after 'exit' expression.");
2262 // case TokenNamedie :
2264 // if (token != TokenNameSEMICOLON) {
2267 // if (token == TokenNameSEMICOLON) {
2270 // if (token != TokenNameStopPHP) {
2271 // throwSyntaxError("';' expected after 'die' expression.");
2275 // case TokenNamearray :
2277 // if (token == TokenNameARGOPEN) {
2279 // if (token == TokenNameCOMMA) {
2282 // expressionList();
2283 // if (token != TokenNameARGCLOSE) {
2284 // throwSyntaxError("')' expected after 'list' keyword.");
2287 // if (token == TokenNameSET) {
2289 // logicalinclusiveorExpression();
2292 // throwSyntaxError("'(' expected after 'list' keyword.");
2296 boolean while_flag = true;
2299 case TokenNameLBRACKET :
2302 if (token != TokenNameRBRACKET) {
2303 throwSyntaxError("] expected in postfix-expression.");
2307 case TokenNamePAAMAYIM_NEKUDOTAYIM :
2309 case TokenNameMINUS_GREATER :
2312 if (token > TokenNameKEYWORD) {
2313 ident = scanner.getCurrentIdentifierSource();
2315 // "Avoid using keyword '"
2316 // + new String(ident)
2317 // + "' as variable name.",
2321 // "Avoid using keyword '" + new String(ident) + "' as
2323 // scanner.getCurrentTokenStartPosition(),
2324 // scanner.getCurrentTokenEndPosition(),
2328 case TokenNameVariable :
2329 ident = scanner.getCurrentIdentifierSource();
2331 // if (token == TokenNameARGOPEN) {
2333 // expressionList();
2334 // if (token != TokenNameARGCLOSE) {
2335 // throwSyntaxError(") expected after variable '" +
2341 case TokenNameIdentifier :
2342 //ident = scanner.getCurrentIdentifierSource();
2345 case TokenNameLBRACE :
2348 if (token != TokenNameRBRACE) {
2349 throwSyntaxError("} expected in postfix-expression.");
2354 throwSyntaxError("Syntax error after '->' token.");
2356 while (token == TokenNameLBRACKET || token == TokenNameLPAREN
2357 || token == TokenNameLBRACE) {
2358 if (token == TokenNameLBRACKET) {
2361 if (token != TokenNameRBRACKET) {
2362 throwSyntaxError("] expected after '->'.");
2365 } else if (token == TokenNameLPAREN) {
2368 if (token != TokenNameRPAREN) {
2369 throwSyntaxError(") expected after '->'.");
2372 } else if (token == TokenNameLBRACE) {
2375 if (token != TokenNameRBRACE) {
2376 throwSyntaxError("} expected after '->'.");
2382 case TokenNamePLUS_PLUS :
2385 case TokenNameMINUS_MINUS :
2391 } while (while_flag);
2393 private void array_pair_list() {
2396 //| non_empty_array_pair_list possible_comma
2397 non_empty_array_pair_list();
2398 if (token == TokenNameCOMMA) {
2402 private void non_empty_array_pair_list() {
2403 //non_empty_array_pair_list:
2404 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2405 //| non_empty_array_pair_list ',' expr
2406 //| expr T_DOUBLE_ARROW expr
2408 //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2409 //| non_empty_array_pair_list ',' '&' w_variable
2410 //| expr T_DOUBLE_ARROW '&' w_variable
2414 if (token == TokenNameAND) {
2418 } else if (token == TokenNameEQUAL_GREATER) {
2420 if (token == TokenNameAND) {
2427 if (token != TokenNameCOMMA) {
2431 if (token == TokenNameRPAREN) {
2436 private void unaryExpression() {
2438 case TokenNamePLUS_PLUS :
2442 case TokenNameMINUS_MINUS :
2446 // '@' '&' '*' '+' '-' '~' '!'
2449 if (token == TokenNameinclude || token == TokenNameinclude_once
2450 || token == TokenNamerequire || token == TokenNamerequire_once) {
2451 statement(TokenNameAT);
2453 expr_without_variable(); // castExpression();
2460 case TokenNameMULTIPLY :
2464 case TokenNamePLUS :
2468 case TokenNameMINUS :
2472 case TokenNameTWIDDLE :
2481 expr_without_variable();
2484 private void castExpression() {
2485 // if (token == TokenNameARGOPEN) {
2488 // if (token != TokenNameARGCLOSE) {
2489 // throwSyntaxError(") expected after cast-expression.");
2495 private void assignExpression() {
2497 if (token == TokenNameEQUAL) { // =
2499 logicalinclusiveorExpression();
2500 } else if (token == TokenNameDOT_EQUAL) { // .=
2502 logicalinclusiveorExpression();
2503 } else if (token == TokenNameEQUAL_GREATER) { // =>
2505 logicalinclusiveorExpression();
2506 } else if (token == TokenNamePLUS_EQUAL) { // +=
2508 logicalinclusiveorExpression();
2509 } else if (token == TokenNameMINUS_EQUAL) { // -=
2511 logicalinclusiveorExpression();
2512 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2514 logicalinclusiveorExpression();
2515 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2517 logicalinclusiveorExpression();
2518 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2520 logicalinclusiveorExpression();
2521 } else if (token == TokenNameAND_EQUAL) { // &=
2523 logicalinclusiveorExpression();
2524 } else if (token == TokenNameOR_EQUAL) { // |=
2526 logicalinclusiveorExpression();
2527 } else if (token == TokenNameXOR_EQUAL) { // ^=
2529 logicalinclusiveorExpression();
2530 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2532 logicalinclusiveorExpression();
2533 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2535 logicalinclusiveorExpression();
2536 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2538 logicalinclusiveorExpression();
2541 private void multiplicativeExpression() {
2544 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE
2545 && token != TokenNameREMAINDER) {
2551 private void concatenationExpression() {
2553 multiplicativeExpression();
2554 if (token != TokenNameDOT) {
2560 private void additiveExpression() {
2562 concatenationExpression();
2563 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2569 private void shiftExpression() {
2571 additiveExpression();
2572 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2578 private void relationalExpression() {
2581 if (token != TokenNameLESS && token != TokenNameGREATER
2582 && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2588 private void identicalExpression() {
2590 relationalExpression();
2591 if (token != TokenNameEQUAL_EQUAL_EQUAL
2592 && token != TokenNameNOT_EQUAL_EQUAL) {
2598 private void equalityExpression() {
2600 identicalExpression();
2601 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2607 private void ternaryExpression() {
2608 equalityExpression();
2609 if (token == TokenNameQUESTION) {
2612 if (token == TokenNameCOLON) {
2616 throwSyntaxError("':' expected in ternary operator '? :'.");
2620 private void andExpression() {
2622 ternaryExpression();
2623 if (token != TokenNameAND) {
2629 private void exclusiveorExpression() {
2632 if (token != TokenNameXOR) {
2638 private void inclusiveorExpression() {
2640 exclusiveorExpression();
2641 if (token != TokenNameOR) {
2647 private void booleanandExpression() {
2649 inclusiveorExpression();
2650 if (token != TokenNameAND_AND) {
2656 private void booleanorExpression() {
2658 booleanandExpression();
2659 if (token != TokenNameOR_OR) {
2665 private void logicalandExpression() {
2667 booleanorExpression();
2668 if (token != TokenNameAND) {
2674 private void logicalexclusiveorExpression() {
2676 logicalandExpression();
2677 if (token != TokenNameXOR) {
2683 private void logicalinclusiveorExpression() {
2685 logicalexclusiveorExpression();
2686 if (token != TokenNameOR) {
2692 // public void assignmentExpression() {
2693 // if (token == TokenNameVARIABLE) {
2695 // if (token == TokenNameSET) {
2697 // logicalinclusiveorExpression();
2700 // logicalinclusiveorExpression();
2703 private void variableList() {
2706 if (token == TokenNameCOMMA) {
2713 private void variable() {
2714 if (token == TokenNameDOLLAR_LBRACE) {
2718 if (token != TokenNameRBRACE) {
2719 throwSyntaxError("'}' expected after indirect variable token '${'.");
2723 if (token == TokenNameVariable) {
2725 if (token == TokenNameLBRACKET) {
2728 if (token != TokenNameRBRACKET) {
2729 throwSyntaxError("']' expected in variable-list.");
2732 } else if (token == TokenNameEQUAL) {
2737 throwSyntaxError("$-variable expected in variable-list.");
2741 private void exit_expr() {
2745 if (token != TokenNameLPAREN) {
2749 if (token == TokenNameRPAREN) {
2754 if (token != TokenNameRPAREN) {
2755 throwSyntaxError("')' expected after keyword 'exit'");
2759 private void internal_functions_in_yacc() {
2761 case TokenNameisset :
2762 // T_ISSET '(' isset_variables ')'
2764 if (token != TokenNameLPAREN) {
2765 throwSyntaxError("'(' expected after keyword 'isset'");
2769 if (token != TokenNameRPAREN) {
2770 throwSyntaxError("')' expected after keyword 'isset'");
2774 case TokenNameempty :
2775 // T_EMPTY '(' variable ')'
2777 if (token != TokenNameLPAREN) {
2778 throwSyntaxError("'(' expected after keyword 'empty'");
2782 if (token != TokenNameRPAREN) {
2783 throwSyntaxError("')' expected after keyword 'empty'");
2787 case TokenNameinclude :
2792 case TokenNameinclude_once :
2793 // T_INCLUDE_ONCE expr
2797 case TokenNameeval :
2798 // T_EVAL '(' expr ')'
2800 if (token != TokenNameLPAREN) {
2801 throwSyntaxError("'(' expected after keyword 'eval'");
2805 if (token != TokenNameRPAREN) {
2806 throwSyntaxError("')' expected after keyword 'eval'");
2810 case TokenNamerequire :
2815 case TokenNamerequire_once :
2816 // T_REQUIRE_ONCE expr
2822 private void isset_variables() {
2824 // | isset_variables ','
2825 if (token == TokenNameRPAREN) {
2826 throwSyntaxError("Variable expected after keyword 'isset'");
2830 if (token == TokenNameCOMMA) {
2837 private boolean common_scalar() {
2841 // | T_CONSTANT_ENCAPSED_STRING
2848 case TokenNameIntegerLiteral :
2851 case TokenNameDoubleLiteral :
2854 case TokenNameStringLiteral :
2857 case TokenNameStringConstant :
2860 case TokenNameStringInterpolated :
2863 case TokenNameFILE :
2866 case TokenNameLINE :
2869 case TokenNameCLASS_C :
2872 case TokenNameMETHOD_C :
2875 case TokenNameFUNC_C :
2881 private void static_scalar() {
2882 // static_scalar: /* compile-time evaluated scalars */
2885 // | '+' static_scalar
2886 // | '-' static_scalar
2887 // | T_ARRAY '(' static_array_pair_list ')'
2888 // | static_class_constant
2889 if (common_scalar()) {
2893 case TokenNameIdentifier :
2895 // static_class_constant:
2896 // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
2897 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
2899 if (token == TokenNameIdentifier) {
2902 throwSyntaxError("Identifier expected after '::' operator.");
2906 case TokenNamePLUS :
2910 case TokenNameMINUS :
2914 case TokenNamearray :
2916 if (token != TokenNameLPAREN) {
2917 throwSyntaxError("'(' expected after keyword 'array'");
2920 if (token == TokenNameRPAREN) {
2924 non_empty_static_array_pair_list();
2925 if (token != TokenNameRPAREN) {
2926 throwSyntaxError("')' expected after keyword 'array'");
2930 // case TokenNamenull :
2933 // case TokenNamefalse :
2936 // case TokenNametrue :
2940 throwSyntaxError("Static scalar/constant expected.");
2943 private void non_empty_static_array_pair_list() {
2944 // non_empty_static_array_pair_list:
2945 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
2947 //| non_empty_static_array_pair_list ',' static_scalar
2948 //| static_scalar T_DOUBLE_ARROW static_scalar
2952 if (token == TokenNameEQUAL_GREATER) {
2956 if (token != TokenNameCOMMA) {
2960 if (token != TokenNameRPAREN) {
2965 public void reportSyntaxError() { //int act, int currentKind, int
2967 /* remember current scanner position */
2968 int startPos = scanner.startPosition;
2969 int currentPos = scanner.currentPosition;
2970 // String[] expectings;
2971 // String tokenName = name[symbol_index[currentKind]];
2972 //fetch all "accurate" possible terminals that could recover the error
2973 // int start, end = start = asi(stack[stateStackTop]);
2974 // while (asr[end] != 0)
2976 // int length = end - start;
2977 // expectings = new String[length];
2978 // if (length != 0) {
2979 // char[] indexes = new char[length];
2980 // System.arraycopy(asr, start, indexes, 0, length);
2981 // for (int i = 0; i < length; i++) {
2982 // expectings[i] = name[symbol_index[indexes[i]]];
2985 //if the pb is an EOF, try to tell the user that they are some
2986 // if (tokenName.equals(UNEXPECTED_EOF)) {
2987 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2988 // char[] tokenSource;
2990 // tokenSource = this.scanner.getCurrentTokenSource();
2991 // } catch (Exception e) {
2992 // tokenSource = new char[] {};
2994 // problemReporter().parseError(
2995 // this.scanner.startPosition,
2996 // this.scanner.currentPosition - 1,
3001 // } else { //the next test is HEAVILY grammar DEPENDENT.
3002 // if ((length == 14)
3003 // && (expectings[0] == "=") //$NON-NLS-1$
3004 // && (expectings[1] == "*=") //$NON-NLS-1$
3005 // && (expressionPtr > -1)) {
3006 // switch(currentKind) {
3007 // case TokenNameSEMICOLON:
3008 // case TokenNamePLUS:
3009 // case TokenNameMINUS:
3010 // case TokenNameDIVIDE:
3011 // case TokenNameREMAINDER:
3012 // case TokenNameMULTIPLY:
3013 // case TokenNameLEFT_SHIFT:
3014 // case TokenNameRIGHT_SHIFT:
3015 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3016 // case TokenNameLESS:
3017 // case TokenNameGREATER:
3018 // case TokenNameLESS_EQUAL:
3019 // case TokenNameGREATER_EQUAL:
3020 // case TokenNameEQUAL_EQUAL:
3021 // case TokenNameNOT_EQUAL:
3022 // case TokenNameXOR:
3023 // case TokenNameAND:
3024 // case TokenNameOR:
3025 // case TokenNameOR_OR:
3026 // case TokenNameAND_AND:
3027 // // the ; is not the expected token ==> it ends a statement when an
3028 // expression is not ended
3029 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3031 // case TokenNameRBRACE :
3032 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3035 // char[] tokenSource;
3037 // tokenSource = this.scanner.getCurrentTokenSource();
3038 // } catch (Exception e) {
3039 // tokenSource = new char[] {};
3041 // problemReporter().parseError(
3042 // this.scanner.startPosition,
3043 // this.scanner.currentPosition - 1,
3047 // this.checkAndReportBracketAnomalies(problemReporter());
3052 tokenSource = this.scanner.getCurrentTokenSource();
3053 } catch (Exception e) {
3054 tokenSource = new char[]{};
3056 // problemReporter().parseError(
3057 // this.scanner.startPosition,
3058 // this.scanner.currentPosition - 1,
3062 this.checkAndReportBracketAnomalies(problemReporter());
3065 /* reset scanner where it was */
3066 scanner.startPosition = startPos;
3067 scanner.currentPosition = currentPos;
3069 public static final int RoundBracket = 0;
3070 public static final int SquareBracket = 1;
3071 public static final int CurlyBracket = 2;
3072 public static final int BracketKinds = 3;
3073 protected int[] nestedMethod; //the ptr is nestedType
3074 protected int nestedType, dimensions;
3076 final static int AstStackIncrement = 100;
3077 protected int astPtr;
3078 protected AstNode[] astStack = new AstNode[AstStackIncrement];
3079 protected int astLengthPtr;
3080 protected int[] astLengthStack;
3081 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3082 public CompilationUnitDeclaration compilationUnit; /*
3083 * the result from parse()
3085 protected ReferenceContext referenceContext;
3086 protected ProblemReporter problemReporter;
3087 // protected CompilationResult compilationResult;
3089 * Returns this parser's problem reporter initialized with its reference
3090 * context. Also it is assumed that a problem is going to be reported, so
3091 * initializes the compilation result's line positions.
3093 public ProblemReporter problemReporter() {
3094 if (scanner.recordLineSeparator) {
3095 compilationUnit.compilationResult.lineSeparatorPositions = scanner
3098 problemReporter.referenceContext = referenceContext;
3099 return problemReporter;
3102 * Reconsider the entire source looking for inconsistencies in {} () []
3104 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3105 scanner.wasAcr = false;
3106 boolean anomaliesDetected = false;
3108 char[] source = scanner.source;
3109 int[] leftCount = {0, 0, 0};
3110 int[] rightCount = {0, 0, 0};
3111 int[] depths = {0, 0, 0};
3112 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3113 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3114 int[][] rightPositions = new int[][]{new int[10], new int[10],
3116 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3117 scanner.currentPosition = scanner.initialPosition; //starting
3119 // (first-zero-based
3121 while (scanner.currentPosition < scanner.eofPosition) { //loop for
3126 // ---------Consume white space and handles
3127 // startPosition---------
3128 boolean isWhiteSpace;
3130 scanner.startPosition = scanner.currentPosition;
3131 // if (((scanner.currentCharacter =
3132 // source[scanner.currentPosition++]) == '\\') &&
3133 // (source[scanner.currentPosition] == 'u')) {
3134 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3136 if (scanner.recordLineSeparator
3137 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3138 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3139 // only record line positions we have not
3141 scanner.pushLineSeparator();
3144 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3146 } while (isWhiteSpace
3147 && (scanner.currentPosition < scanner.eofPosition));
3148 // -------consume token until } is found---------
3149 switch (scanner.currentCharacter) {
3152 int index = leftCount[CurlyBracket]++;
3153 if (index == leftPositions[CurlyBracket].length) {
3154 System.arraycopy(leftPositions[CurlyBracket], 0,
3155 (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3158 .arraycopy(leftDepths[CurlyBracket], 0,
3159 (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3162 leftPositions[CurlyBracket][index] = scanner.startPosition;
3163 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3168 int index = rightCount[CurlyBracket]++;
3169 if (index == rightPositions[CurlyBracket].length) {
3170 System.arraycopy(rightPositions[CurlyBracket], 0,
3171 (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3173 System.arraycopy(rightDepths[CurlyBracket], 0,
3174 (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3177 rightPositions[CurlyBracket][index] = scanner.startPosition;
3178 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3183 int index = leftCount[RoundBracket]++;
3184 if (index == leftPositions[RoundBracket].length) {
3185 System.arraycopy(leftPositions[RoundBracket], 0,
3186 (leftPositions[RoundBracket] = new int[index * 2]), 0,
3189 .arraycopy(leftDepths[RoundBracket], 0,
3190 (leftDepths[RoundBracket] = new int[index * 2]), 0,
3193 leftPositions[RoundBracket][index] = scanner.startPosition;
3194 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3199 int index = rightCount[RoundBracket]++;
3200 if (index == rightPositions[RoundBracket].length) {
3201 System.arraycopy(rightPositions[RoundBracket], 0,
3202 (rightPositions[RoundBracket] = new int[index * 2]), 0,
3204 System.arraycopy(rightDepths[RoundBracket], 0,
3205 (rightDepths[RoundBracket] = new int[index * 2]), 0,
3208 rightPositions[RoundBracket][index] = scanner.startPosition;
3209 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3214 int index = leftCount[SquareBracket]++;
3215 if (index == leftPositions[SquareBracket].length) {
3216 System.arraycopy(leftPositions[SquareBracket], 0,
3217 (leftPositions[SquareBracket] = new int[index * 2]), 0,
3219 System.arraycopy(leftDepths[SquareBracket], 0,
3220 (leftDepths[SquareBracket] = new int[index * 2]), 0,
3223 leftPositions[SquareBracket][index] = scanner.startPosition;
3224 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3229 int index = rightCount[SquareBracket]++;
3230 if (index == rightPositions[SquareBracket].length) {
3231 System.arraycopy(rightPositions[SquareBracket], 0,
3232 (rightPositions[SquareBracket] = new int[index * 2]), 0,
3234 System.arraycopy(rightDepths[SquareBracket], 0,
3235 (rightDepths[SquareBracket] = new int[index * 2]), 0,
3238 rightPositions[SquareBracket][index] = scanner.startPosition;
3239 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3244 if (scanner.getNextChar('\\')) {
3245 scanner.scanEscapeCharacter();
3246 } else { // consume next character
3247 scanner.unicodeAsBackSlash = false;
3248 // if (((scanner.currentCharacter =
3249 // source[scanner.currentPosition++]) ==
3251 // (source[scanner.currentPosition] ==
3253 // scanner.getNextUnicodeChar();
3255 if (scanner.withoutUnicodePtr != 0) {
3256 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3260 scanner.getNextChar('\'');
3264 // consume next character
3265 scanner.unicodeAsBackSlash = false;
3266 // if (((scanner.currentCharacter =
3267 // source[scanner.currentPosition++]) == '\\') &&
3268 // (source[scanner.currentPosition] == 'u')) {
3269 // scanner.getNextUnicodeChar();
3271 if (scanner.withoutUnicodePtr != 0) {
3272 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3275 while (scanner.currentCharacter != '"') {
3276 if (scanner.currentCharacter == '\r') {
3277 if (source[scanner.currentPosition] == '\n')
3278 scanner.currentPosition++;
3279 break; // the string cannot go further that
3282 if (scanner.currentCharacter == '\n') {
3283 break; // the string cannot go further that
3286 if (scanner.currentCharacter == '\\') {
3287 scanner.scanEscapeCharacter();
3289 // consume next character
3290 scanner.unicodeAsBackSlash = false;
3291 // if (((scanner.currentCharacter =
3292 // source[scanner.currentPosition++]) == '\\')
3293 // && (source[scanner.currentPosition] == 'u'))
3295 // scanner.getNextUnicodeChar();
3297 if (scanner.withoutUnicodePtr != 0) {
3298 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3306 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3309 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3310 && (source[scanner.currentPosition] == 'u')) {
3311 //-------------unicode traitement
3313 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3314 scanner.currentPosition++;
3315 while (source[scanner.currentPosition] == 'u') {
3316 scanner.currentPosition++;
3319 .getNumericValue(source[scanner.currentPosition++])) > 15
3322 .getNumericValue(source[scanner.currentPosition++])) > 15
3325 .getNumericValue(source[scanner.currentPosition++])) > 15
3328 .getNumericValue(source[scanner.currentPosition++])) > 15
3329 || c4 < 0) { //error don't
3332 scanner.currentCharacter = 'A';
3333 } //something different from \n and \r
3335 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3338 while (scanner.currentCharacter != '\r'
3339 && scanner.currentCharacter != '\n') {
3341 scanner.startPosition = scanner.currentPosition;
3342 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3343 && (source[scanner.currentPosition] == 'u')) {
3344 //-------------unicode traitement
3346 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3347 scanner.currentPosition++;
3348 while (source[scanner.currentPosition] == 'u') {
3349 scanner.currentPosition++;
3352 .getNumericValue(source[scanner.currentPosition++])) > 15
3355 .getNumericValue(source[scanner.currentPosition++])) > 15
3358 .getNumericValue(source[scanner.currentPosition++])) > 15
3361 .getNumericValue(source[scanner.currentPosition++])) > 15
3362 || c4 < 0) { //error don't
3365 scanner.currentCharacter = 'A';
3366 } //something different from \n
3369 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3373 if (scanner.recordLineSeparator
3374 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3375 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3376 // only record line positions we
3377 // have not recorded yet
3378 scanner.pushLineSeparator();
3379 if (this.scanner.taskTags != null) {
3380 this.scanner.checkTaskTag(this.scanner
3381 .getCurrentTokenStartPosition(), this.scanner
3382 .getCurrentTokenEndPosition());
3388 if (test > 0) { //traditional and annotation
3390 boolean star = false;
3391 // consume next character
3392 scanner.unicodeAsBackSlash = false;
3393 // if (((scanner.currentCharacter =
3394 // source[scanner.currentPosition++]) ==
3396 // (source[scanner.currentPosition] ==
3398 // scanner.getNextUnicodeChar();
3400 if (scanner.withoutUnicodePtr != 0) {
3401 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3404 if (scanner.currentCharacter == '*') {
3408 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3409 && (source[scanner.currentPosition] == 'u')) {
3410 //-------------unicode traitement
3412 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3413 scanner.currentPosition++;
3414 while (source[scanner.currentPosition] == 'u') {
3415 scanner.currentPosition++;
3418 .getNumericValue(source[scanner.currentPosition++])) > 15
3421 .getNumericValue(source[scanner.currentPosition++])) > 15
3424 .getNumericValue(source[scanner.currentPosition++])) > 15
3427 .getNumericValue(source[scanner.currentPosition++])) > 15
3428 || c4 < 0) { //error don't
3431 scanner.currentCharacter = 'A';
3432 } //something different from * and /
3434 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3437 //loop until end of comment */
3438 while ((scanner.currentCharacter != '/') || (!star)) {
3439 star = scanner.currentCharacter == '*';
3441 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3442 && (source[scanner.currentPosition] == 'u')) {
3443 //-------------unicode traitement
3445 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3446 scanner.currentPosition++;
3447 while (source[scanner.currentPosition] == 'u') {
3448 scanner.currentPosition++;
3451 .getNumericValue(source[scanner.currentPosition++])) > 15
3454 .getNumericValue(source[scanner.currentPosition++])) > 15
3457 .getNumericValue(source[scanner.currentPosition++])) > 15
3460 .getNumericValue(source[scanner.currentPosition++])) > 15
3461 || c4 < 0) { //error don't
3464 scanner.currentCharacter = 'A';
3465 } //something different from * and
3468 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3472 if (this.scanner.taskTags != null) {
3473 this.scanner.checkTaskTag(this.scanner
3474 .getCurrentTokenStartPosition(), this.scanner
3475 .getCurrentTokenEndPosition());
3482 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3483 scanner.scanIdentifierOrKeyword(false);
3486 if (Character.isDigit(scanner.currentCharacter)) {
3487 scanner.scanNumber(false);
3491 //-----------------end switch while
3492 // try--------------------
3493 } catch (IndexOutOfBoundsException e) {
3494 break; // read until EOF
3495 } catch (InvalidInputException e) {
3496 return false; // no clue
3499 if (scanner.recordLineSeparator) {
3500 // compilationUnit.compilationResult.lineSeparatorPositions =
3501 // scanner.getLineEnds();
3503 // check placement anomalies against other kinds of brackets
3504 for (int kind = 0; kind < BracketKinds; kind++) {
3505 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3506 int start = leftPositions[kind][leftIndex]; // deepest
3508 // find matching closing bracket
3509 int depth = leftDepths[kind][leftIndex];
3511 for (int i = 0; i < rightCount[kind]; i++) {
3512 int pos = rightPositions[kind][i];
3513 // want matching bracket further in source with same
3515 if ((pos > start) && (depth == rightDepths[kind][i])) {
3520 if (end < 0) { // did not find a good closing match
3521 problemReporter.unmatchedBracket(start, referenceContext,
3522 compilationUnit.compilationResult);
3525 // check if even number of opening/closing other brackets
3526 // in between this pair of brackets
3528 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3529 for (int i = 0; i < leftCount[otherKind]; i++) {
3530 int pos = leftPositions[otherKind][i];
3531 if ((pos > start) && (pos < end))
3534 for (int i = 0; i < rightCount[otherKind]; i++) {
3535 int pos = rightPositions[otherKind][i];
3536 if ((pos > start) && (pos < end))
3540 problemReporter.unmatchedBracket(start, referenceContext,
3541 compilationUnit.compilationResult); //bracket
3547 // too many opening brackets ?
3548 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3549 anomaliesDetected = true;
3550 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3551 - i - 1], referenceContext, compilationUnit.compilationResult);
3553 // too many closing brackets ?
3554 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3555 anomaliesDetected = true;
3556 problemReporter.unmatchedBracket(rightPositions[kind][i],
3557 referenceContext, compilationUnit.compilationResult);
3559 if (anomaliesDetected)
3562 return anomaliesDetected;
3563 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3564 return anomaliesDetected;
3565 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3566 return anomaliesDetected;
3569 protected void pushOnAstLengthStack(int pos) {
3571 astLengthStack[++astLengthPtr] = pos;
3572 } catch (IndexOutOfBoundsException e) {
3573 int oldStackLength = astLengthStack.length;
3574 int[] oldPos = astLengthStack;
3575 astLengthStack = new int[oldStackLength + StackIncrement];
3576 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3577 astLengthStack[astLengthPtr] = pos;
3580 protected void pushOnAstStack(AstNode node) {
3582 * add a new obj on top of the ast stack
3585 astStack[++astPtr] = node;
3586 } catch (IndexOutOfBoundsException e) {
3587 int oldStackLength = astStack.length;
3588 AstNode[] oldStack = astStack;
3589 astStack = new AstNode[oldStackLength + AstStackIncrement];
3590 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3591 astPtr = oldStackLength;
3592 astStack[astPtr] = node;
3595 astLengthStack[++astLengthPtr] = 1;
3596 } catch (IndexOutOfBoundsException e) {
3597 int oldStackLength = astLengthStack.length;
3598 int[] oldPos = astLengthStack;
3599 astLengthStack = new int[oldStackLength + AstStackIncrement];
3600 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3601 astLengthStack[astLengthPtr] = 1;