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);
169 * Method Declaration.
173 // private void getChar() {
174 // if (str.length() > chIndx) {
175 // ch = str.charAt(chIndx++);
180 // chIndx = str.length() + 1;
182 // // token = TokenNameEOF;
186 * gets the next token from input
188 private void getNextToken() {
190 token = scanner.getNextToken();
192 int currentEndPosition = scanner.getCurrentTokenEndPosition();
193 int currentStartPosition = scanner.getCurrentTokenStartPosition();
195 .print(currentStartPosition + "," + currentEndPosition + ": ");
196 System.out.println(scanner.toStringAction(token));
198 } catch (InvalidInputException e) {
199 token = TokenNameERROR;
204 * Get a number. if it's a <code>double</code> the number will be stored in
205 * <code>doubleNumber</code> and the token will have the value
206 * {@link Parser#TokenNameDOUBLE_NUMBER}<br />
207 * if it's a <code>double</code> the number will be stored in <code>longNumber</code>
208 * and the token will have the value {@link Parser#TokenNameINT_NUMBER}
210 // private void getNumber() {
211 // StringBuffer inum = new StringBuffer();
213 // int numFormat = 10;
215 // // save first digit
216 // char firstCh = ch;
220 // // determine number conversions:
221 // if (firstCh == '0') {
250 // if (numFormat == 16) {
251 // while ((ch >= '0' && ch <= '9')
252 // || (ch >= 'a' && ch <= 'f')
253 // || (ch >= 'A' && ch <= 'F')) {
258 // while ((ch >= '0' && ch <= '9')
262 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
263 // if (ch == '.' && dFlag != ' ') {
266 // if ((dFlag == 'E') || (dFlag == 'e')) {
272 // if ((ch == '-') || (ch == '+')) {
285 // if (dFlag != ' ') {
286 // doubleNumber = new Double(inum.toString());
287 // token = TokenNameDoubleLiteral;
290 // longNumber = Long.valueOf(inum.toString(), numFormat);
291 // token = TokenNameIntegerLiteral;
295 // } catch (Throwable e) {
296 // throwSyntaxError("Number format error: " + inum.toString());
302 // * @param openChar the opening char ('\'', '"', '`')
303 // * @param typeString the type of string {@link
304 // #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
305 // * @param errorMsg the error message in case of parse error in the string
307 // private void getString(
308 // final char openChar,
309 // final int typeString,
310 // final String errorMsg) {
311 // StringBuffer sBuffer = new StringBuffer();
312 // boolean openString = true;
313 // int startRow = rowCount;
314 // while (str.length() > chIndx) {
315 // ch = str.charAt(chIndx++);
317 // sBuffer.append(ch);
318 // if (str.length() > chIndx) {
319 // ch = str.charAt(chIndx++);
320 // sBuffer.append(ch);
322 // } else if (ch == openChar) {
323 // openString = false;
325 // } else if (ch == '\n') {
327 // columnCount = chIndx;
329 // sBuffer.append(ch);
333 // if (typeString == TokenNameStringConstant) {
334 // throwSyntaxError(errorMsg, startRow);
336 // throwSyntaxError(errorMsg);
339 // token = typeString;
340 // stringValue = sBuffer.toString();
342 // public void htmlParserTester(String input) {
343 // int lineNumber = 1;
344 // int startLineNumber = 1;
345 // int startIndex = 0;
348 // boolean phpMode = false;
349 // boolean phpFound = false;
351 // phpList = new ArrayList();
352 // currentPHPString = 0;
356 // while (i < input.length()) {
357 // ch = input.charAt(i++);
361 // if ((!phpMode) && ch == '<') {
362 // ch2 = input.charAt(i++);
364 // ch2 = input.charAt(i++);
365 // if (Character.isWhitespace(ch2)) {
370 // startLineNumber = lineNumber;
372 // } else if (ch2 == 'p') {
373 // ch2 = input.charAt(i++);
375 // ch2 = input.charAt(i++);
380 // startLineNumber = lineNumber;
386 // } else if (ch2 == 'P') {
387 // ch2 = input.charAt(i++);
389 // ch2 = input.charAt(i++);
394 // startLineNumber = lineNumber;
407 // if (ch == '/' && i < input.length()) {
408 // ch2 = input.charAt(i++);
410 // while (i < input.length()) {
411 // ch = input.charAt(i++);
412 // if (ch == '?' && i < input.length()) {
413 // ch2 = input.charAt(i++);
422 // startLineNumber));
426 // } else if (ch == '\n') {
432 // } else if (ch2 == '*') {
433 // // multi-line comment
434 // while (i < input.length()) {
435 // ch = input.charAt(i++);
438 // } else if (ch == '*' && i < input.length()) {
439 // ch2 = input.charAt(i++);
450 // } else if (ch == '#') {
451 // while (i < input.length()) {
452 // ch = input.charAt(i++);
453 // if (ch == '?' && i < input.length()) {
454 // ch2 = input.charAt(i++);
460 // input.substring(startIndex, i - 2),
461 // startLineNumber));
465 // } else if (ch == '\n') {
471 // } else if (ch == '"') {
473 // while (i < input.length()) {
474 // ch = input.charAt(i++);
478 // ch == '\\' && i < input.length()) { // escape
480 // } else if (ch == '"') {
485 // } else if (ch == '\'') {
487 // while (i < input.length()) {
488 // ch = input.charAt(i++);
492 // ch == '\\' && i < input.length()) { // escape
494 // } else if (ch == '\'') {
501 // if (ch == '?' && i < input.length()) {
502 // ch2 = input.charAt(i++);
508 // input.substring(startIndex, i - 2),
509 // startLineNumber));
519 // "No PHP source code found.",
525 // "Open PHP tag at end of file.",
530 // input.substring(startIndex, i - 2),
531 // startLineNumber));
533 // // for (int j=0;j<phpList.size();j++) {
534 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
535 // // int startIndx = temp.length()-10;
536 // // if (startIndx<0) {
539 // // System.out.println(temp.substring(startIndx)+"?>");
541 // phpParserTester(null, 1);
542 // // PHPString temp;
543 // // for(int j=0;j<phpList.size();j++) {
544 // // temp = (PHPString) phpList.get(j);
545 // // parser.start(temp.getPHPString(), temp.getLineNumber());
548 // } catch (CoreException e) {
551 public void phpParserTester(String s, int rowCount) {
554 if (phpList.size() != 0) {
555 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
558 this.token = TokenNameEOF;
560 // this.rowCount = rowCount;
561 // this.columnCount = 0;
564 scanner.setSource(s.toCharArray());
565 scanner.setPHPMode(true);
569 if (token != TokenNameEOF && token != TokenNameERROR) {
572 if (token != TokenNameEOF) {
573 if (token == TokenNameERROR) {
574 throwSyntaxError("Scanner error (Found unknown token: "
575 + scanner.toStringAction(token) + ")");
577 if (token == TokenNameRPAREN) {
578 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
580 if (token == TokenNameRBRACE) {
581 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
583 if (token == TokenNameRBRACKET) {
584 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
586 if (token == TokenNameLPAREN) {
587 throwSyntaxError("Read character '('; end-of-file not reached.");
589 if (token == TokenNameLBRACE) {
590 throwSyntaxError("Read character '{'; end-of-file not reached.");
592 if (token == TokenNameLBRACKET) {
593 throwSyntaxError("Read character '['; end-of-file not reached.");
595 throwSyntaxError("End-of-file not reached.");
598 } catch (SyntaxError err) {
602 // setMarker(err.getMessage(), err.getLine(), ERROR);
603 // setMarker(err.getMessage(),
604 // scanner.getCurrentTokenStartPosition(),
605 // scanner.getCurrentTokenEndPosition(), ERROR);
607 // if an error occured,
608 // try to find keywords 'class' or 'function'
609 // to parse the rest of the string
610 while (token != TokenNameEOF && token != TokenNameERROR) {
611 if (token == TokenNameabstract || token == TokenNamefinal
612 || token == TokenNameclass || token == TokenNamefunction) {
617 if (token == TokenNameEOF || token == TokenNameERROR) {
623 public void init(String s) {
625 this.token = TokenNameEOF;
627 // this.rowCount = 1;
628 // this.columnCount = 0;
630 this.phpMode = false;
631 /* scanner initialization */
632 scanner.setSource(s.toCharArray());
633 scanner.setPHPMode(false);
635 protected void initialize(boolean phpMode) {
636 compilationUnit = null;
637 referenceContext = null;
639 this.token = TokenNameEOF;
641 // this.rowCount = 1;
642 // this.columnCount = 0;
644 this.phpMode = phpMode;
645 scanner.setPHPMode(phpMode);
648 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
651 public void parse(String s) {
656 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
659 protected void parse() {
663 if (token != TokenNameEOF && token != TokenNameERROR) {
666 if (token != TokenNameEOF) {
667 if (token == TokenNameERROR) {
668 throwSyntaxError("Scanner error (Found unknown token: "
669 + scanner.toStringAction(token) + ")");
671 if (token == TokenNameRPAREN) {
672 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
674 if (token == TokenNameRBRACE) {
675 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
677 if (token == TokenNameRBRACKET) {
678 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
680 if (token == TokenNameLPAREN) {
681 throwSyntaxError("Read character '('; end-of-file not reached.");
683 if (token == TokenNameLBRACE) {
684 throwSyntaxError("Read character '{'; end-of-file not reached.");
686 if (token == TokenNameLBRACKET) {
687 throwSyntaxError("Read character '['; end-of-file not reached.");
689 throwSyntaxError("End-of-file not reached.");
692 } catch (SyntaxError sytaxErr1) {
693 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
695 // setMarker(sytaxErr1.getMessage(),
696 // scanner.getCurrentTokenStartPosition(),
697 // scanner.getCurrentTokenEndPosition(), ERROR);
699 // if an error occured,
700 // try to find keywords 'class' or 'function'
701 // to parse the rest of the string
702 while (token != TokenNameEOF && token != TokenNameERROR) {
703 if (token == TokenNameabstract || token == TokenNamefinal
704 || token == TokenNameclass || token == TokenNamefunction) {
709 if (token == TokenNameEOF || token == TokenNameERROR) {
712 } catch (SyntaxError sytaxErr2) {
713 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
715 // setMarker(sytaxErr2.getMessage(),
716 // scanner.getCurrentTokenStartPosition(),
717 // scanner.getCurrentTokenEndPosition(), ERROR);
723 // public PHPOutlineInfo parseInfo(Object parent, String s) {
724 // PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
725 // // Stack stack = new Stack();
726 // // stack.push(outlineInfo.getDeclarations());
728 // this.token = TokenNameEOF;
729 // // this.chIndx = 0;
730 // // this.rowCount = 1;
731 // // this.columnCount = 0;
732 // this.phpEnd = false;
733 // this.phpMode = false;
734 // scanner.setSource(s.toCharArray());
735 // scanner.setPHPMode(false);
738 // parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
740 // return outlineInfo;
742 private boolean isVariable() {
743 return token == TokenNameVariable || token == TokenNamethis;
745 // private void parseDeclarations(PHPOutlineInfo outlineInfo,
746 // OutlineableWithChildren current, boolean goBack) {
748 // // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
749 // PHPSegmentWithChildren temp;
751 // IPreferenceStore store =
752 // PHPeclipsePlugin.getDefault().getPreferenceStore();
754 // while (token != TokenNameEOF && token != TokenNameERROR) {
755 // if (token == TokenNameVariable) {
756 // ident = scanner.getCurrentIdentifierSource();
757 // outlineInfo.addVariable(new String(ident));
759 // } else if (token == TokenNamevar) {
761 // if (token == TokenNameVariable
762 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
763 // ident = scanner.getCurrentIdentifierSource();
764 // //substring(1) added because PHPVarDeclaration doesn't
765 // // need the $ anymore
766 // String variableName = new String(ident).substring(1);
767 // outlineInfo.addVariable(variableName);
769 // if (token != TokenNameSEMICOLON) {
771 // ident = scanner.getCurrentTokenSource();
772 // if (token > TokenNameKEYWORD) {
773 // current.add(new PHPVarDeclaration(current, variableName,
774 // // chIndx - ident.length,
775 // scanner.getCurrentTokenStartPosition(), new String(ident)));
778 // case TokenNameVariable :
779 // case TokenNamethis :
780 // current.add(new PHPVarDeclaration(current, variableName,
783 // scanner.getCurrentTokenStartPosition(), new String(
786 // case TokenNameIdentifier :
787 // current.add(new PHPVarDeclaration(current, variableName,
790 // scanner.getCurrentTokenStartPosition(), new String(
793 // case TokenNameDoubleLiteral :
794 // current.add(new PHPVarDeclaration(current, variableName
798 // scanner.getCurrentTokenStartPosition(), new String(
801 // case TokenNameIntegerLiteral :
802 // current.add(new PHPVarDeclaration(current, variableName,
805 // scanner.getCurrentTokenStartPosition(), new String(
808 // case TokenNameStringInterpolated :
809 // case TokenNameStringLiteral :
810 // current.add(new PHPVarDeclaration(current, variableName,
813 // scanner.getCurrentTokenStartPosition(), new String(
816 // case TokenNameStringConstant :
817 // current.add(new PHPVarDeclaration(current, variableName,
820 // scanner.getCurrentTokenStartPosition(), new String(
824 // current.add(new PHPVarDeclaration(current, variableName,
827 // scanner.getCurrentTokenStartPosition()));
832 // ident = scanner.getCurrentIdentifierSource();
833 // current.add(new PHPVarDeclaration(current, variableName,
834 // // chIndx - ident.length
835 // scanner.getCurrentTokenStartPosition()));
838 // } else if (token == TokenNamefunction) {
840 // if (token == TokenNameAND) {
843 // if (token == TokenNameIdentifier
844 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
845 // ident = scanner.getCurrentIdentifierSource();
846 // outlineInfo.addVariable(new String(ident));
847 // temp = new PHPFunctionDeclaration(current, new String(ident),
848 // // chIndx - ident.length
849 // scanner.getCurrentTokenStartPosition());
850 // current.add(temp);
852 // parseDeclarations(outlineInfo, temp, true);
854 // } else if (token == TokenNameclass) {
856 // if (token == TokenNameIdentifier
857 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
858 // ident = scanner.getCurrentIdentifierSource();
859 // outlineInfo.addVariable(new String(ident));
860 // temp = new PHPClassDeclaration(current, new String(ident),
861 // // chIndx - ident.len
862 // scanner.getCurrentTokenStartPosition());
863 // current.add(temp);
864 // // stack.push(temp);
866 // //skip tokens for classname, extends and others until
867 // // we have the opening '{'
868 // while (token != TokenNameLBRACE && token != TokenNameEOF
869 // && token != TokenNameERROR) {
872 // parseDeclarations(outlineInfo, temp, true);
875 // } else if ((token == TokenNameLBRACE)
876 // || (token == TokenNameDOLLAR_LBRACE)) {
879 // } else if (token == TokenNameRBRACE) {
882 // if (counter == 0 && goBack) {
885 // } else if (token == TokenNamerequire || token == TokenNamerequire_once
886 // || token == TokenNameinclude || token == TokenNameinclude_once) {
887 // ident = scanner.getCurrentTokenSource();
889 // int startPosition = scanner.getCurrentTokenStartPosition();
891 // char[] expr = scanner.getCurrentTokenSource(startPosition);
892 // outlineInfo.addVariable(new String(ident));
893 // current.add(new PHPReqIncDeclaration(current, new String(ident),
894 // // chIndx - ident.length,
895 // startPosition, new String(expr)));
901 // } catch (SyntaxError sytaxErr) {
903 // // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
904 // // setMarker(sytaxErr.getMessage(),
905 // // scanner.getCurrentTokenStartPosition(),
906 // // scanner.getCurrentTokenEndPosition(), ERROR);
907 // // } catch (CoreException e) {
911 private void statementList() {
913 statement(TokenNameEOF);
914 if ((token == TokenNameRBRACE) || (token == TokenNamecase)
915 || (token == TokenNamedefault) || (token == TokenNameelse)
916 || (token == TokenNameelseif) || (token == TokenNameendif)
917 || (token == TokenNameendfor) || (token == TokenNameendforeach)
918 || (token == TokenNameendwhile) || (token == TokenNameendswitch)
919 || (token == TokenNameEOF) || (token == TokenNameERROR)) {
924 private void functionBody(MethodDeclaration methodDecl) {
925 // '{' [statement-list] '}'
926 if (token == TokenNameLBRACE) {
929 throwSyntaxError("'{' expected in compound-statement.");
931 if (token != TokenNameRBRACE) {
934 if (token == TokenNameRBRACE) {
935 methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
938 throwSyntaxError("'}' expected in compound-statement.");
941 private void statement(int previousToken) {
942 // if (token > TokenNameKEYWORD && token != TokenNamelist && token !=
944 // char[] ident = scanner.getCurrentIdentifierSource();
945 // String keyword = new String(ident);
946 if (token == TokenNameAT) {
948 if (token != TokenNamerequire && token != TokenNamerequire_once
949 && token != TokenNameinclude && token != TokenNameinclude_once
950 && token != TokenNameIdentifier && token != TokenNameVariable
951 && token != TokenNamethis && token != TokenNameStringInterpolated) {
952 throwSyntaxError("identifier expected after '@'.");
955 if (token == TokenNameinclude || token == TokenNameinclude_once) {
957 if (token == TokenNameLPAREN) {
959 if (token == TokenNameSEMICOLON) {
962 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
963 throwSyntaxError("';' expected after 'include' or 'include_once'.");
968 concatenationExpression();
971 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
974 if (token == TokenNameLPAREN) {
976 if (token == TokenNameSEMICOLON) {
979 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
980 throwSyntaxError("';' expected after 'require' or 'require_once'.");
985 concatenationExpression();
988 } else if (token == TokenNameif) {
990 if (token == TokenNameLPAREN) {
993 throwSyntaxError("'(' expected after 'if' keyword.");
996 if (token == TokenNameRPAREN) {
999 throwSyntaxError("')' expected after 'if' condition.");
1003 } else if (token == TokenNameswitch) {
1005 if (token == TokenNameLPAREN) {
1008 throwSyntaxError("'(' expected after 'switch' keyword.");
1011 if (token == TokenNameRPAREN) {
1014 throwSyntaxError("')' expected after 'switch' condition.");
1018 } else if (token == TokenNamefor) {
1020 if (token == TokenNameLPAREN) {
1023 throwSyntaxError("'(' expected after 'for' keyword.");
1025 if (token == TokenNameSEMICOLON) {
1029 if (token == TokenNameSEMICOLON) {
1032 throwSyntaxError("';' expected after 'for'.");
1035 if (token == TokenNameSEMICOLON) {
1039 if (token == TokenNameSEMICOLON) {
1042 throwSyntaxError("';' expected after 'for'.");
1045 if (token == TokenNameRPAREN) {
1049 if (token == TokenNameRPAREN) {
1052 throwSyntaxError("')' expected after 'for'.");
1057 } else if (token == TokenNamewhile) {
1059 if (token == TokenNameLPAREN) {
1062 throwSyntaxError("'(' expected after 'while' keyword.");
1065 if (token == TokenNameRPAREN) {
1068 throwSyntaxError("')' expected after 'while' condition.");
1072 } else if (token == TokenNamedo) {
1074 if (token == TokenNameLBRACE) {
1077 throwSyntaxError("'{' expected after 'do' keyword.");
1079 if (token != TokenNameRBRACE) {
1082 if (token == TokenNameRBRACE) {
1085 throwSyntaxError("'}' expected after 'do' keyword.");
1087 if (token == TokenNamewhile) {
1089 if (token == TokenNameLPAREN) {
1092 throwSyntaxError("'(' expected after 'while' keyword.");
1095 if (token == TokenNameRPAREN) {
1098 throwSyntaxError("')' expected after 'while' condition.");
1101 throwSyntaxError("'while' expected after 'do' keyword.");
1103 if (token == TokenNameSEMICOLON) {
1106 if (token != TokenNameStopPHP) {
1107 throwSyntaxError("';' expected after do-while statement.");
1112 } else if (token == TokenNameforeach) {
1114 if (token == TokenNameLPAREN) {
1117 throwSyntaxError("'(' expected after 'foreach' keyword.");
1120 if (token == TokenNameas) {
1123 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1126 if (token == TokenNameEQUAL_GREATER) {
1130 if (token == TokenNameRPAREN) {
1133 throwSyntaxError("')' expected after 'foreach' expression.");
1137 } else if (token == TokenNamecontinue || token == TokenNamebreak
1138 || token == TokenNamereturn) {
1140 if (token != TokenNameSEMICOLON) {
1143 if (token == TokenNameSEMICOLON) {
1146 if (token != TokenNameStopPHP) {
1147 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1152 } else if (token == TokenNameecho) {
1155 if (token == TokenNameSEMICOLON) {
1158 if (token != TokenNameStopPHP) {
1159 throwSyntaxError("';' expected after 'echo' statement.");
1164 // } else if (token == TokenNameprint) {
1167 // if (token == TokenNameSEMICOLON) {
1170 // if (token != TokenNameStopPHP) {
1171 // throwSyntaxError("';' expected after 'print' statement.");
1176 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1179 if (token == TokenNameSEMICOLON) {
1182 if (token != TokenNameStopPHP) {
1183 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1188 } else if (token == TokenNameunset) {
1190 if (token == TokenNameLPAREN) {
1193 throwSyntaxError("'(' expected after 'unset' statement.");
1196 if (token == TokenNameRPAREN) {
1199 throwSyntaxError("')' expected after 'unset' statement.");
1201 if (token == TokenNameSEMICOLON) {
1204 if (token != TokenNameStopPHP) {
1205 throwSyntaxError("';' expected after 'unset' statement.");
1210 // } else if (token == TokenNameexit || token == TokenNamedie) {
1212 // if (token != TokenNameSEMICOLON) {
1215 // if (token == TokenNameSEMICOLON) {
1218 // if (token != TokenNameStopPHP) {
1219 // throwSyntaxError("';' expected after 'exit' or 'die'
1225 // } else if (token == TokenNamedefine) {
1227 // if (token == TokenNameLPAREN) {
1230 // throwSyntaxError("'(' expected after 'define' keyword.");
1233 // if (token == TokenNameCOMMA) {
1236 // throwSyntaxError("',' expected after first 'define' constant.");
1239 // if (token == TokenNameCOMMA) {
1243 // if (token == TokenNameRPAREN) {
1246 // throwSyntaxError("')' expected after 'define' statement.");
1248 // if (token == TokenNameSEMICOLON) {
1251 // if (token != TokenNameStopPHP) {
1252 // throwSyntaxError("';' expected after 'define' statement.");
1257 } else if (token == TokenNamefunction) {
1258 MethodDeclaration methodDecl = new MethodDeclaration(
1259 this.compilationUnit.compilationResult);
1260 methodDecl.declarationSourceStart = scanner
1261 .getCurrentTokenStartPosition();
1263 functionDefinition(methodDecl);
1265 } else if (token == TokenNamefinal || token == TokenNameabstract
1266 || token == TokenNameclass || token == TokenNameinterface) {
1267 TypeDeclaration typeDecl = new TypeDeclaration(
1268 this.compilationUnit.compilationResult);
1269 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1270 // default super class
1271 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1272 compilationUnit.types.add(typeDecl);
1274 pushOnAstStack(typeDecl);
1275 unticked_class_declaration_statement(typeDecl);
1276 // classBody(typeDecl);
1283 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1284 } else if (token == TokenNameLBRACE) {
1286 if (token != TokenNameRBRACE) {
1289 if (token == TokenNameRBRACE) {
1293 throwSyntaxError("'}' expected.");
1296 if (token != TokenNameSEMICOLON) {
1299 if (token == TokenNameSEMICOLON) {
1303 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1304 throwSyntaxError("';' expected after expression (Found token: "
1305 + scanner.toStringAction(token) + ")");
1311 private void unset_variables() {
1314 // | unset_variables ',' unset_variable
1319 if (token != TokenNameCOMMA) {
1325 private final void initializeModifiers() {
1327 this.modifiersSourceStart = -1;
1329 private final void checkAndSetModifiers(int flag) {
1330 this.modifiers |= flag;
1331 if (this.modifiersSourceStart < 0)
1332 this.modifiersSourceStart = this.scanner.startPosition;
1334 private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1335 initializeModifiers();
1336 if (token == TokenNameinterface) {
1337 // interface_entry T_STRING
1338 // interface_extends_list
1339 // '{' class_statement_list '}'
1340 checkAndSetModifiers(AccInterface);
1342 typeDecl.modifiers = this.modifiers;
1343 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1344 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1345 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1346 typeDecl.name = scanner.getCurrentIdentifierSource();
1347 if (token > TokenNameKEYWORD) {
1348 throwSyntaxError("Don't use a keyword for interface declaration ["
1349 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1350 typeDecl.sourceEnd);
1353 interface_extends_list();
1355 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1356 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1357 typeDecl.name = new char[]{' '};
1358 throwSyntaxError("Interface name expected after keyword 'interface'.",
1359 typeDecl.sourceStart, typeDecl.sourceEnd);
1363 // class_entry_type T_STRING extends_from
1365 // '{' class_statement_list'}'
1367 typeDecl.modifiers = this.modifiers;
1369 //identifier 'extends' identifier
1370 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1371 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1372 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1373 typeDecl.name = scanner.getCurrentIdentifierSource();
1374 if (token > TokenNameKEYWORD) {
1375 throwSyntaxError("Don't use a keyword for class declaration ["
1376 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1377 typeDecl.sourceEnd);
1382 // | T_EXTENDS fully_qualified_class_name
1383 if (token == TokenNameextends) {
1385 if (token == TokenNameIdentifier) {
1388 throwSyntaxError("Class name expected after keyword 'extends'.",
1389 scanner.getCurrentTokenStartPosition(), scanner
1390 .getCurrentTokenEndPosition());
1395 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1396 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1397 typeDecl.name = new char[]{' '};
1398 throwSyntaxError("Class name expected after keyword 'class'.",
1399 typeDecl.sourceStart, typeDecl.sourceEnd);
1403 // '{' class_statement_list '}'
1404 if (token == TokenNameLBRACE) {
1406 if (token != TokenNameRBRACE) {
1407 class_statement_list();
1409 if (token == TokenNameRBRACE) {
1410 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1413 throwSyntaxError("'}' expected at end of class body.");
1416 throwSyntaxError("'{' expected at start of class body.");
1419 private void class_entry_type() {
1421 // | T_ABSTRACT T_CLASS
1422 // | T_FINAL T_CLASS
1423 if (token == TokenNameclass) {
1425 } else if (token == TokenNameabstract) {
1426 checkAndSetModifiers(AccAbstract);
1428 if (token != TokenNameclass) {
1429 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1432 } else if (token == TokenNamefinal) {
1433 checkAndSetModifiers(AccFinal);
1435 if (token != TokenNameclass) {
1436 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1440 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1443 private void interface_extends_list() {
1445 // | T_EXTENDS interface_list
1446 if (token == TokenNameextends) {
1451 private void implements_list() {
1453 // | T_IMPLEMENTS interface_list
1454 if (token == TokenNameimplements) {
1459 private void interface_list() {
1461 // fully_qualified_class_name
1462 //| interface_list ',' fully_qualified_class_name
1464 if (token == TokenNameIdentifier) {
1467 throwSyntaxError("Interface name expected after keyword 'implements'.");
1469 if (token != TokenNameCOMMA) {
1475 // private void classBody(TypeDeclaration typeDecl) {
1476 // //'{' [class-element-list] '}'
1477 // if (token == TokenNameLBRACE) {
1479 // if (token != TokenNameRBRACE) {
1480 // class_statement_list();
1482 // if (token == TokenNameRBRACE) {
1483 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1486 // throwSyntaxError("'}' expected at end of class body.");
1489 // throwSyntaxError("'{' expected at start of class body.");
1492 private void class_statement_list() {
1495 } while (token == TokenNamepublic ||
1496 token == TokenNameprotected ||
1497 token == TokenNameprivate ||
1498 token == TokenNamestatic ||
1499 token == TokenNameabstract ||
1500 token == TokenNamefinal ||
1501 token == TokenNamefunction ||
1502 token == TokenNamevar);
1504 private void class_statement() {
1506 // variable_modifiers class_variable_declaration ';'
1507 // | class_constant_declaration ';'
1508 // | method_modifiers T_FUNCTION is_reference T_STRING
1509 // '(' parameter_list ')' method_body
1510 initializeModifiers();
1511 if (token == TokenNamevar) {
1512 checkAndSetModifiers(AccPublic);
1514 "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected' modifier for field declarations.",
1515 scanner.getCurrentTokenStartPosition(), scanner
1516 .getCurrentTokenEndPosition());
1520 boolean hasModifiers = member_modifiers();
1521 if (token == TokenNamefunction) {
1522 if (!hasModifiers) {
1523 checkAndSetModifiers(AccPublic);
1525 MethodDeclaration methodDecl = new MethodDeclaration(
1526 this.compilationUnit.compilationResult);
1527 methodDecl.declarationSourceStart = scanner
1528 .getCurrentTokenStartPosition();
1529 methodDecl.modifiers = this.modifiers;
1531 functionDefinition(methodDecl);
1533 if (!hasModifiers) {
1534 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1539 // if (token == TokenNamefunction) {
1540 // MethodDeclaration methodDecl = new MethodDeclaration(
1541 // this.compilationUnit.compilationResult);
1542 // methodDecl.declarationSourceStart = scanner
1543 // .getCurrentTokenStartPosition();
1545 // functionDefinition(methodDecl);
1546 // } else if (token == TokenNamevar) {
1550 // throwSyntaxError("'function' or 'var' expected.");
1553 // private void variable_modifiers() {
1554 // // variable_modifiers:
1555 // // non_empty_member_modifiers
1557 // initializeModifiers();
1558 // if (token == TokenNamevar) {
1559 // checkAndSetModifiers(AccPublic);
1560 // reportSyntaxError(
1561 // "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
1562 // modifier for field declarations.",
1563 // scanner.getCurrentTokenStartPosition(), scanner
1564 // .getCurrentTokenEndPosition());
1567 // if (!member_modifiers()) {
1568 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1569 // field declarations.");
1573 // private void method_modifiers() {
1574 // //method_modifiers:
1576 // //| non_empty_member_modifiers
1577 // initializeModifiers();
1578 // if (!member_modifiers()) {
1579 // checkAndSetModifiers(AccPublic);
1582 private boolean member_modifiers() {
1589 boolean foundToken = false;
1591 if (token == TokenNamepublic) {
1592 checkAndSetModifiers(AccPublic);
1595 } else if (token == TokenNameprotected) {
1596 checkAndSetModifiers(AccProtected);
1599 } else if (token == TokenNameprivate) {
1600 checkAndSetModifiers(AccPrivate);
1603 } else if (token == TokenNamestatic) {
1604 checkAndSetModifiers(AccStatic);
1607 } else if (token == TokenNameabstract) {
1608 checkAndSetModifiers(AccAbstract);
1611 } else if (token == TokenNamefinal) {
1612 checkAndSetModifiers(AccFinal);
1621 private void classProperty() {
1622 //'var' variable ';'
1623 //'var' variable '=' constant ';'
1625 if (token == TokenNameVariable) {
1627 if (token == TokenNameEQUAL) {
1632 if (token == TokenNamethis) {
1633 throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1635 throwSyntaxError("Variable expected after keyword 'var'.");
1637 if (token != TokenNameCOMMA) {
1642 if (token == TokenNameSEMICOLON) {
1645 throwSyntaxError("';' expected after variable declaration.");
1648 private void functionDefinition(MethodDeclaration methodDecl) {
1650 compilationUnit.types.add(methodDecl);
1652 AstNode node = astStack[astPtr];
1653 if (node instanceof TypeDeclaration) {
1654 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1655 if (typeDecl.methods == null) {
1656 typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1658 AbstractMethodDeclaration[] newMethods;
1663 newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1664 1, typeDecl.methods.length);
1665 newMethods[0] = methodDecl;
1666 typeDecl.methods = newMethods;
1670 functionDeclarator(methodDecl);
1671 functionBody(methodDecl);
1673 private void functionDeclarator(MethodDeclaration methodDecl) {
1674 //identifier '(' [parameter-list] ')'
1675 if (token == TokenNameAND) {
1678 if (token == TokenNameIdentifier) {
1679 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1680 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1681 methodDecl.selector = scanner.getCurrentIdentifierSource();
1683 if (token == TokenNameLPAREN) {
1686 throwSyntaxError("'(' expected in function declaration.");
1688 if (token != TokenNameRPAREN) {
1691 if (token != TokenNameRPAREN) {
1692 throwSyntaxError("')' expected in function declaration.");
1694 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1698 if (token > TokenNameKEYWORD) {
1699 throwSyntaxError("Don't use keyword for function declaration [" + token
1702 throwSyntaxError("Function name expected after keyword 'function'.");
1706 private void parameterList() {
1707 //parameter-declaration
1708 //parameter-list ',' parameter-declaration
1710 parameterDeclaration();
1711 if (token != TokenNameCOMMA) {
1717 private void parameterDeclaration() {
1719 //variable-reference
1720 if (token == TokenNameAND) {
1725 throwSyntaxError("Variable expected after reference operator '&'.");
1728 //variable '=' constant
1729 if (token == TokenNameVariable) {
1731 if (token == TokenNameEQUAL) {
1737 if (token == TokenNamethis) {
1738 throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1741 private void labeledStatementList() {
1742 if (token != TokenNamecase && token != TokenNamedefault) {
1743 throwSyntaxError("'case' or 'default' expected.");
1746 if (token == TokenNamecase) {
1748 expr(); //constant();
1749 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1751 if (token == TokenNamecase || token == TokenNamedefault) { // empty
1759 // else if (token == TokenNameSEMICOLON) {
1761 // "':' expected after 'case' keyword (Found token: " +
1762 // scanner.toStringAction(token) + ")",
1763 // scanner.getCurrentTokenStartPosition(),
1764 // scanner.getCurrentTokenEndPosition(),
1767 // if (token == TokenNamecase) { // empty case statement ?
1773 throwSyntaxError("':' character after 'case' constant expected (Found token: "
1774 + scanner.toStringAction(token) + ")");
1776 } else { // TokenNamedefault
1778 if (token == TokenNameCOLON) {
1782 throwSyntaxError("':' character after 'default' expected.");
1785 } while (token == TokenNamecase || token == TokenNamedefault);
1787 // public void labeledStatement() {
1788 // if (token == TokenNamecase) {
1791 // if (token == TokenNameDDOT) {
1795 // throwSyntaxError("':' character after 'case' constant expected.");
1798 // } else if (token == TokenNamedefault) {
1800 // if (token == TokenNameDDOT) {
1804 // throwSyntaxError("':' character after 'default' expected.");
1809 // public void expressionStatement() {
1811 // private void inclusionStatement() {
1813 // public void compoundStatement() {
1815 // public void selectionStatement() {
1818 // public void iterationStatement() {
1821 // public void jumpStatement() {
1824 // public void outputStatement() {
1827 // public void scopeStatement() {
1830 // public void flowStatement() {
1833 // public void definitionStatement() {
1835 private void ifStatement() {
1836 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1837 if (token == TokenNameCOLON) {
1839 if (token != TokenNameendif) {
1842 case TokenNameelse :
1844 if (token == TokenNameCOLON) {
1846 if (token != TokenNameendif) {
1850 if (token == TokenNameif) { //'else if'
1852 elseifStatementList();
1854 throwSyntaxError("':' expected after 'else'.");
1858 case TokenNameelseif :
1860 elseifStatementList();
1864 if (token != TokenNameendif) {
1865 throwSyntaxError("'endif' expected.");
1868 if (token != TokenNameSEMICOLON) {
1869 throwSyntaxError("';' expected after if-statement.");
1873 // statement [else-statement]
1874 statement(TokenNameEOF);
1875 if (token == TokenNameelseif) {
1877 if (token == TokenNameLPAREN) {
1880 throwSyntaxError("'(' expected after 'elseif' keyword.");
1883 if (token == TokenNameRPAREN) {
1886 throwSyntaxError("')' expected after 'elseif' condition.");
1889 } else if (token == TokenNameelse) {
1891 statement(TokenNameEOF);
1895 private void elseifStatementList() {
1899 case TokenNameelse :
1901 if (token == TokenNameCOLON) {
1903 if (token != TokenNameendif) {
1908 if (token == TokenNameif) { //'else if'
1911 throwSyntaxError("':' expected after 'else'.");
1915 case TokenNameelseif :
1923 private void elseifStatement() {
1924 if (token == TokenNameLPAREN) {
1927 if (token != TokenNameRPAREN) {
1928 throwSyntaxError("')' expected in else-if-statement.");
1931 if (token != TokenNameCOLON) {
1932 throwSyntaxError("':' expected in else-if-statement.");
1935 if (token != TokenNameendif) {
1940 private void switchStatement() {
1941 if (token == TokenNameCOLON) {
1942 // ':' [labeled-statement-list] 'endswitch' ';'
1944 labeledStatementList();
1945 if (token != TokenNameendswitch) {
1946 throwSyntaxError("'endswitch' expected.");
1949 if (token != TokenNameSEMICOLON) {
1950 throwSyntaxError("';' expected after switch-statement.");
1954 // '{' [labeled-statement-list] '}'
1955 if (token != TokenNameLBRACE) {
1956 throwSyntaxError("'{' expected in switch statement.");
1959 if (token != TokenNameRBRACE) {
1960 labeledStatementList();
1962 if (token != TokenNameRBRACE) {
1963 throwSyntaxError("'}' expected in switch statement.");
1968 private void forStatement() {
1969 if (token == TokenNameCOLON) {
1972 if (token != TokenNameendfor) {
1973 throwSyntaxError("'endfor' expected.");
1976 if (token != TokenNameSEMICOLON) {
1977 throwSyntaxError("';' expected after for-statement.");
1981 statement(TokenNameEOF);
1984 private void whileStatement() {
1985 // ':' statement-list 'endwhile' ';'
1986 if (token == TokenNameCOLON) {
1989 if (token != TokenNameendwhile) {
1990 throwSyntaxError("'endwhile' expected.");
1993 if (token != TokenNameSEMICOLON) {
1994 throwSyntaxError("';' expected after while-statement.");
1998 statement(TokenNameEOF);
2001 private void foreachStatement() {
2002 if (token == TokenNameCOLON) {
2005 if (token != TokenNameendforeach) {
2006 throwSyntaxError("'endforeach' expected.");
2009 if (token != TokenNameSEMICOLON) {
2010 throwSyntaxError("';' expected after foreach-statement.");
2014 statement(TokenNameEOF);
2017 // private void exitStatus() {
2018 // if (token == TokenNameLPAREN) {
2021 // throwSyntaxError("'(' expected in 'exit-status'.");
2023 // if (token != TokenNameRPAREN) {
2026 // if (token == TokenNameRPAREN) {
2029 // throwSyntaxError("')' expected after 'exit-status'.");
2032 private void expressionList() {
2035 if (token == TokenNameCOMMA) {
2042 private void expr() {
2043 //todo: find a better way to get the expression
2044 // expression = new StringBuffer();
2045 // for (int i = chIndx; i < str.length(); i++) {
2046 // if (str.charAt(i) == ';') {
2049 // expression.append(str.charAt(i));
2051 // if (token == TokenNameSTRING_CONSTANT || token ==
2052 // TokenNameINTERPOLATED_STRING) {
2055 logicalinclusiveorExpression();
2056 // while (token != TokenNameSEMICOLON) {
2061 private void expr_without_variable() {
2064 boolean castFlag = false;
2065 boolean arrayFlag = false;
2067 case TokenNameisset :
2068 case TokenNameempty :
2069 case TokenNameeval :
2070 case TokenNameinclude :
2071 case TokenNameinclude_once :
2072 case TokenNamerequire :
2073 case TokenNamerequire_once :
2074 internal_functions_in_yacc();
2080 case TokenNamenull :
2083 case TokenNamefalse :
2086 case TokenNametrue :
2089 case TokenNameStringConstant :
2092 case TokenNameHEREDOC :
2093 case TokenNameStringInterpolated :
2094 case TokenNameStringLiteral :
2097 case TokenNameLPAREN :
2099 if (token == TokenNameIdentifier) {
2100 // check if identifier is a type:
2101 // ident = identifier;
2102 ident = scanner.getCurrentIdentifierSource();
2103 String str = new String(ident).toLowerCase();
2104 for (int i = 0; i < PHP_TYPES.length; i++) {
2105 if (PHP_TYPES[i].equals(str)) {
2107 if (PHP_TYPES[i].equals("array")) {
2116 if (arrayFlag && token == TokenNameLPAREN) {
2118 if (token == TokenNameRPAREN) {
2122 if (token != TokenNameRPAREN) {
2123 throwSyntaxError(") expected after 'array('.");
2127 if (token != TokenNameRPAREN) {
2128 throwSyntaxError(") expected after cast-type '" + str + "'.");
2136 if (token != TokenNameRPAREN) {
2137 throwSyntaxError(") expected in postfix-expression.");
2141 case TokenNameDoubleLiteral :
2144 case TokenNameIntegerLiteral :
2147 case TokenNameDOLLAR_LBRACE :
2150 if (token != TokenNameRBRACE) {
2151 throwSyntaxError("'}' expected after indirect variable token '${'.");
2155 case TokenNameVariable :
2156 case TokenNamethis :
2157 ident = scanner.getCurrentIdentifierSource();
2159 if (token == TokenNameLBRACE) {
2162 if (token != TokenNameRBRACE) {
2163 throwSyntaxError("'}' expected after variable '"
2164 + new String(ident) + "' in variable-expression.");
2167 } else if (token == TokenNameLPAREN) {
2169 if (token != TokenNameRPAREN) {
2171 if (token != TokenNameRPAREN) {
2172 throwSyntaxError("')' expected after variable '"
2173 + new String(ident) + "' in postfix-expression.");
2179 case TokenNameIdentifier :
2180 ident = scanner.getCurrentIdentifierSource();
2182 if (token == TokenNameLPAREN) {
2184 if (token != TokenNameRPAREN) {
2186 if (token != TokenNameRPAREN) {
2187 throwSyntaxError("')' expected after identifier '"
2188 + new String(ident) + "' in postfix-expression."
2189 + "(Found token: " + scanner.toStringAction(token) + ")");
2195 case TokenNamearray :
2196 // T_ARRAY '(' array_pair_list ')'
2198 if (token == TokenNameLPAREN) {
2200 if (token == TokenNameRPAREN) {
2205 if (token != TokenNameRPAREN) {
2206 throwSyntaxError("')' expected after keyword 'array'"
2207 + "(Found token: " + scanner.toStringAction(token) + ")");
2211 throwSyntaxError("'(' expected after keyword 'array'"
2212 + "(Found token: " + scanner.toStringAction(token) + ")");
2215 case TokenNameprint :
2219 case TokenNameexit :
2223 case TokenNamelist :
2225 if (token == TokenNameLPAREN) {
2227 if (token == TokenNameCOMMA) {
2231 if (token != TokenNameRPAREN) {
2232 throwSyntaxError("')' expected after 'list' keyword.");
2235 // if (token == TokenNameSET) {
2237 // logicalinclusiveorExpression();
2240 throwSyntaxError("'(' expected after 'list' keyword.");
2243 // case TokenNameexit :
2245 // if (token != TokenNameSEMICOLON) {
2248 // if (token == TokenNameSEMICOLON) {
2251 // if (token != TokenNameStopPHP) {
2252 // throwSyntaxError("';' expected after 'exit' expression.");
2257 // case TokenNamedie :
2259 // if (token != TokenNameSEMICOLON) {
2262 // if (token == TokenNameSEMICOLON) {
2265 // if (token != TokenNameStopPHP) {
2266 // throwSyntaxError("';' expected after 'die' expression.");
2270 // case TokenNamearray :
2272 // if (token == TokenNameARGOPEN) {
2274 // if (token == TokenNameCOMMA) {
2277 // expressionList();
2278 // if (token != TokenNameARGCLOSE) {
2279 // throwSyntaxError("')' expected after 'list' keyword.");
2282 // if (token == TokenNameSET) {
2284 // logicalinclusiveorExpression();
2287 // throwSyntaxError("'(' expected after 'list' keyword.");
2291 boolean while_flag = true;
2294 case TokenNameLBRACKET :
2297 if (token != TokenNameRBRACKET) {
2298 throwSyntaxError("] expected in postfix-expression.");
2302 case TokenNameCOLON_COLON :
2304 case TokenNameMINUS_GREATER :
2307 if (token > TokenNameKEYWORD) {
2308 ident = scanner.getCurrentIdentifierSource();
2310 // "Avoid using keyword '"
2311 // + new String(ident)
2312 // + "' as variable name.",
2316 // "Avoid using keyword '" + new String(ident) + "' as
2318 // scanner.getCurrentTokenStartPosition(),
2319 // scanner.getCurrentTokenEndPosition(),
2323 case TokenNameVariable :
2324 ident = scanner.getCurrentIdentifierSource();
2326 // if (token == TokenNameARGOPEN) {
2328 // expressionList();
2329 // if (token != TokenNameARGCLOSE) {
2330 // throwSyntaxError(") expected after variable '" +
2336 case TokenNameIdentifier :
2337 //ident = scanner.getCurrentIdentifierSource();
2340 case TokenNameLBRACE :
2343 if (token != TokenNameRBRACE) {
2344 throwSyntaxError("} expected in postfix-expression.");
2349 throwSyntaxError("Syntax error after '->' token.");
2351 while (token == TokenNameLBRACKET || token == TokenNameLPAREN
2352 || token == TokenNameLBRACE) {
2353 if (token == TokenNameLBRACKET) {
2356 if (token != TokenNameRBRACKET) {
2357 throwSyntaxError("] expected after '->'.");
2360 } else if (token == TokenNameLPAREN) {
2363 if (token != TokenNameRPAREN) {
2364 throwSyntaxError(") expected after '->'.");
2367 } else if (token == TokenNameLBRACE) {
2370 if (token != TokenNameRBRACE) {
2371 throwSyntaxError("} expected after '->'.");
2377 case TokenNamePLUS_PLUS :
2380 case TokenNameMINUS_MINUS :
2386 } while (while_flag);
2388 private void array_pair_list() {
2391 //| non_empty_array_pair_list possible_comma
2392 non_empty_array_pair_list();
2393 if (token == TokenNameCOMMA) {
2399 private void non_empty_array_pair_list() {
2400 //non_empty_array_pair_list:
2401 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2402 //| non_empty_array_pair_list ',' expr
2403 //| expr T_DOUBLE_ARROW expr
2405 //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2406 //| non_empty_array_pair_list ',' '&' w_variable
2407 //| expr T_DOUBLE_ARROW '&' w_variable
2411 private void unaryExpression() {
2413 case TokenNamePLUS_PLUS :
2417 case TokenNameMINUS_MINUS :
2421 // '@' '&' '*' '+' '-' '~' '!'
2424 if (token == TokenNameinclude || token == TokenNameinclude_once
2425 || token == TokenNamerequire || token == TokenNamerequire_once) {
2426 statement(TokenNameAT);
2428 expr_without_variable(); // castExpression();
2435 case TokenNameMULTIPLY :
2439 case TokenNamePLUS :
2443 case TokenNameMINUS :
2447 case TokenNameTWIDDLE :
2456 expr_without_variable();
2459 private void castExpression() {
2460 // if (token == TokenNameARGOPEN) {
2463 // if (token != TokenNameARGCLOSE) {
2464 // throwSyntaxError(") expected after cast-expression.");
2470 private void assignExpression() {
2472 if (token == TokenNameEQUAL) { // =
2474 logicalinclusiveorExpression();
2475 } else if (token == TokenNameDOT_EQUAL) { // .=
2477 logicalinclusiveorExpression();
2478 } else if (token == TokenNameEQUAL_GREATER) { // =>
2480 logicalinclusiveorExpression();
2481 } else if (token == TokenNamePLUS_EQUAL) { // +=
2483 logicalinclusiveorExpression();
2484 } else if (token == TokenNameMINUS_EQUAL) { // -=
2486 logicalinclusiveorExpression();
2487 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2489 logicalinclusiveorExpression();
2490 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2492 logicalinclusiveorExpression();
2493 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2495 logicalinclusiveorExpression();
2496 } else if (token == TokenNameAND_EQUAL) { // &=
2498 logicalinclusiveorExpression();
2499 } else if (token == TokenNameOR_EQUAL) { // |=
2501 logicalinclusiveorExpression();
2502 } else if (token == TokenNameXOR_EQUAL) { // ^=
2504 logicalinclusiveorExpression();
2505 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2507 logicalinclusiveorExpression();
2508 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2510 logicalinclusiveorExpression();
2511 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2513 logicalinclusiveorExpression();
2516 private void multiplicativeExpression() {
2519 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE
2520 && token != TokenNameREMAINDER) {
2526 private void concatenationExpression() {
2528 multiplicativeExpression();
2529 if (token != TokenNameDOT) {
2535 private void additiveExpression() {
2537 concatenationExpression();
2538 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2544 private void shiftExpression() {
2546 additiveExpression();
2547 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2553 private void relationalExpression() {
2556 if (token != TokenNameLESS && token != TokenNameGREATER
2557 && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2563 private void identicalExpression() {
2565 relationalExpression();
2566 if (token != TokenNameEQUAL_EQUAL_EQUAL
2567 && token != TokenNameNOT_EQUAL_EQUAL) {
2573 private void equalityExpression() {
2575 identicalExpression();
2576 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2582 private void ternaryExpression() {
2583 equalityExpression();
2584 if (token == TokenNameQUESTION) {
2587 if (token == TokenNameCOLON) {
2591 throwSyntaxError("':' expected in ternary operator '? :'.");
2595 private void andExpression() {
2597 ternaryExpression();
2598 if (token != TokenNameAND) {
2604 private void exclusiveorExpression() {
2607 if (token != TokenNameXOR) {
2613 private void inclusiveorExpression() {
2615 exclusiveorExpression();
2616 if (token != TokenNameOR) {
2622 private void booleanandExpression() {
2624 inclusiveorExpression();
2625 if (token != TokenNameAND_AND) {
2631 private void booleanorExpression() {
2633 booleanandExpression();
2634 if (token != TokenNameOR_OR) {
2640 private void logicalandExpression() {
2642 booleanorExpression();
2643 if (token != TokenNameAND) {
2649 private void logicalexclusiveorExpression() {
2651 logicalandExpression();
2652 if (token != TokenNameXOR) {
2658 private void logicalinclusiveorExpression() {
2660 logicalexclusiveorExpression();
2661 if (token != TokenNameOR) {
2667 // public void assignmentExpression() {
2668 // if (token == TokenNameVARIABLE) {
2670 // if (token == TokenNameSET) {
2672 // logicalinclusiveorExpression();
2675 // logicalinclusiveorExpression();
2678 private void variableList() {
2681 if (token == TokenNameCOMMA) {
2688 private void variable() {
2689 if (token == TokenNameDOLLAR_LBRACE) {
2693 if (token != TokenNameRBRACE) {
2694 throwSyntaxError("'}' expected after indirect variable token '${'.");
2698 if (token == TokenNameVariable) {
2700 if (token == TokenNameLBRACKET) {
2703 if (token != TokenNameRBRACKET) {
2704 throwSyntaxError("']' expected in variable-list.");
2707 } else if (token == TokenNameEQUAL) {
2712 throwSyntaxError("$-variable expected in variable-list.");
2716 private void exit_expr() {
2720 if (token != TokenNameLPAREN) {
2724 if (token == TokenNameRPAREN) {
2729 if (token != TokenNameRPAREN) {
2730 throwSyntaxError("')' expected after keyword 'exit'");
2734 private void internal_functions_in_yacc() {
2736 case TokenNameisset :
2737 // T_ISSET '(' isset_variables ')'
2739 if (token != TokenNameLPAREN) {
2740 throwSyntaxError("'(' expected after keyword 'isset'");
2744 if (token != TokenNameRPAREN) {
2745 throwSyntaxError("')' expected after keyword 'isset'");
2749 case TokenNameempty :
2750 // T_EMPTY '(' variable ')'
2752 if (token != TokenNameLPAREN) {
2753 throwSyntaxError("'(' expected after keyword 'empty'");
2757 if (token != TokenNameRPAREN) {
2758 throwSyntaxError("')' expected after keyword 'empty'");
2762 case TokenNameinclude :
2767 case TokenNameinclude_once :
2768 // T_INCLUDE_ONCE expr
2772 case TokenNameeval :
2773 // T_EVAL '(' expr ')'
2775 if (token != TokenNameLPAREN) {
2776 throwSyntaxError("'(' expected after keyword 'eval'");
2780 if (token != TokenNameRPAREN) {
2781 throwSyntaxError("')' expected after keyword 'eval'");
2785 case TokenNamerequire :
2790 case TokenNamerequire_once :
2791 // T_REQUIRE_ONCE expr
2797 private void isset_variables() {
2799 // | isset_variables ','
2800 if (token == TokenNameRPAREN) {
2801 throwSyntaxError("Variable expected after keyword 'isset'");
2805 if (token == TokenNameCOMMA) {
2813 * It will look for a value (after a '=' for example) @
2815 private void constant() {
2818 case TokenNamePLUS :
2821 case TokenNameDoubleLiteral :
2824 case TokenNameIntegerLiteral :
2828 throwSyntaxError("Constant expected after '+' presign.");
2831 case TokenNameMINUS :
2834 case TokenNameDoubleLiteral :
2837 case TokenNameIntegerLiteral :
2841 throwSyntaxError("Constant expected after '-' presign.");
2844 case TokenNamenull :
2847 case TokenNamefalse :
2850 case TokenNametrue :
2853 case TokenNameIdentifier :
2854 // ident = identifier;
2855 char[] ident = scanner.getCurrentIdentifierSource();
2857 if (token == TokenNameLPAREN) {
2859 if (token != TokenNameRPAREN) {
2861 if (token != TokenNameRPAREN) {
2862 throwSyntaxError("')' expected after identifier '"
2863 + new String(ident) + "' in postfix-expression.");
2869 case TokenNameStringLiteral :
2872 case TokenNameStringConstant :
2875 case TokenNameStringInterpolated :
2878 case TokenNameDoubleLiteral :
2881 case TokenNameIntegerLiteral :
2885 throwSyntaxError("Constant expected.");
2888 public void reportSyntaxError() { //int act, int currentKind, int
2890 /* remember current scanner position */
2891 int startPos = scanner.startPosition;
2892 int currentPos = scanner.currentPosition;
2893 // String[] expectings;
2894 // String tokenName = name[symbol_index[currentKind]];
2895 //fetch all "accurate" possible terminals that could recover the error
2896 // int start, end = start = asi(stack[stateStackTop]);
2897 // while (asr[end] != 0)
2899 // int length = end - start;
2900 // expectings = new String[length];
2901 // if (length != 0) {
2902 // char[] indexes = new char[length];
2903 // System.arraycopy(asr, start, indexes, 0, length);
2904 // for (int i = 0; i < length; i++) {
2905 // expectings[i] = name[symbol_index[indexes[i]]];
2908 //if the pb is an EOF, try to tell the user that they are some
2909 // if (tokenName.equals(UNEXPECTED_EOF)) {
2910 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2911 // char[] tokenSource;
2913 // tokenSource = this.scanner.getCurrentTokenSource();
2914 // } catch (Exception e) {
2915 // tokenSource = new char[] {};
2917 // problemReporter().parseError(
2918 // this.scanner.startPosition,
2919 // this.scanner.currentPosition - 1,
2924 // } else { //the next test is HEAVILY grammar DEPENDENT.
2925 // if ((length == 14)
2926 // && (expectings[0] == "=") //$NON-NLS-1$
2927 // && (expectings[1] == "*=") //$NON-NLS-1$
2928 // && (expressionPtr > -1)) {
2929 // switch(currentKind) {
2930 // case TokenNameSEMICOLON:
2931 // case TokenNamePLUS:
2932 // case TokenNameMINUS:
2933 // case TokenNameDIVIDE:
2934 // case TokenNameREMAINDER:
2935 // case TokenNameMULTIPLY:
2936 // case TokenNameLEFT_SHIFT:
2937 // case TokenNameRIGHT_SHIFT:
2938 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
2939 // case TokenNameLESS:
2940 // case TokenNameGREATER:
2941 // case TokenNameLESS_EQUAL:
2942 // case TokenNameGREATER_EQUAL:
2943 // case TokenNameEQUAL_EQUAL:
2944 // case TokenNameNOT_EQUAL:
2945 // case TokenNameXOR:
2946 // case TokenNameAND:
2947 // case TokenNameOR:
2948 // case TokenNameOR_OR:
2949 // case TokenNameAND_AND:
2950 // // the ; is not the expected token ==> it ends a statement when an
2951 // expression is not ended
2952 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
2954 // case TokenNameRBRACE :
2955 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
2958 // char[] tokenSource;
2960 // tokenSource = this.scanner.getCurrentTokenSource();
2961 // } catch (Exception e) {
2962 // tokenSource = new char[] {};
2964 // problemReporter().parseError(
2965 // this.scanner.startPosition,
2966 // this.scanner.currentPosition - 1,
2970 // this.checkAndReportBracketAnomalies(problemReporter());
2975 tokenSource = this.scanner.getCurrentTokenSource();
2976 } catch (Exception e) {
2977 tokenSource = new char[]{};
2979 // problemReporter().parseError(
2980 // this.scanner.startPosition,
2981 // this.scanner.currentPosition - 1,
2985 this.checkAndReportBracketAnomalies(problemReporter());
2988 /* reset scanner where it was */
2989 scanner.startPosition = startPos;
2990 scanner.currentPosition = currentPos;
2992 public static final int RoundBracket = 0;
2993 public static final int SquareBracket = 1;
2994 public static final int CurlyBracket = 2;
2995 public static final int BracketKinds = 3;
2996 protected int[] nestedMethod; //the ptr is nestedType
2997 protected int nestedType, dimensions;
2999 final static int AstStackIncrement = 100;
3000 protected int astPtr;
3001 protected AstNode[] astStack = new AstNode[AstStackIncrement];
3002 protected int astLengthPtr;
3003 protected int[] astLengthStack;
3004 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3005 public CompilationUnitDeclaration compilationUnit; /*
3006 * the result from parse()
3008 protected ReferenceContext referenceContext;
3009 protected ProblemReporter problemReporter;
3010 // protected CompilationResult compilationResult;
3012 * Returns this parser's problem reporter initialized with its reference
3013 * context. Also it is assumed that a problem is going to be reported, so
3014 * initializes the compilation result's line positions.
3016 public ProblemReporter problemReporter() {
3017 if (scanner.recordLineSeparator) {
3018 compilationUnit.compilationResult.lineSeparatorPositions = scanner
3021 problemReporter.referenceContext = referenceContext;
3022 return problemReporter;
3025 * Reconsider the entire source looking for inconsistencies in {} () []
3027 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3028 scanner.wasAcr = false;
3029 boolean anomaliesDetected = false;
3031 char[] source = scanner.source;
3032 int[] leftCount = {0, 0, 0};
3033 int[] rightCount = {0, 0, 0};
3034 int[] depths = {0, 0, 0};
3035 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3036 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3037 int[][] rightPositions = new int[][]{new int[10], new int[10],
3039 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3040 scanner.currentPosition = scanner.initialPosition; //starting
3042 // (first-zero-based
3044 while (scanner.currentPosition < scanner.eofPosition) { //loop for
3049 // ---------Consume white space and handles
3050 // startPosition---------
3051 boolean isWhiteSpace;
3053 scanner.startPosition = scanner.currentPosition;
3054 // if (((scanner.currentCharacter =
3055 // source[scanner.currentPosition++]) == '\\') &&
3056 // (source[scanner.currentPosition] == 'u')) {
3057 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3059 if (scanner.recordLineSeparator
3060 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3061 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3062 // only record line positions we have not
3064 scanner.pushLineSeparator();
3067 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3069 } while (isWhiteSpace
3070 && (scanner.currentPosition < scanner.eofPosition));
3071 // -------consume token until } is found---------
3072 switch (scanner.currentCharacter) {
3075 int index = leftCount[CurlyBracket]++;
3076 if (index == leftPositions[CurlyBracket].length) {
3077 System.arraycopy(leftPositions[CurlyBracket], 0,
3078 (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3081 .arraycopy(leftDepths[CurlyBracket], 0,
3082 (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3085 leftPositions[CurlyBracket][index] = scanner.startPosition;
3086 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3091 int index = rightCount[CurlyBracket]++;
3092 if (index == rightPositions[CurlyBracket].length) {
3093 System.arraycopy(rightPositions[CurlyBracket], 0,
3094 (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3096 System.arraycopy(rightDepths[CurlyBracket], 0,
3097 (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3100 rightPositions[CurlyBracket][index] = scanner.startPosition;
3101 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3106 int index = leftCount[RoundBracket]++;
3107 if (index == leftPositions[RoundBracket].length) {
3108 System.arraycopy(leftPositions[RoundBracket], 0,
3109 (leftPositions[RoundBracket] = new int[index * 2]), 0,
3112 .arraycopy(leftDepths[RoundBracket], 0,
3113 (leftDepths[RoundBracket] = new int[index * 2]), 0,
3116 leftPositions[RoundBracket][index] = scanner.startPosition;
3117 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3122 int index = rightCount[RoundBracket]++;
3123 if (index == rightPositions[RoundBracket].length) {
3124 System.arraycopy(rightPositions[RoundBracket], 0,
3125 (rightPositions[RoundBracket] = new int[index * 2]), 0,
3127 System.arraycopy(rightDepths[RoundBracket], 0,
3128 (rightDepths[RoundBracket] = new int[index * 2]), 0,
3131 rightPositions[RoundBracket][index] = scanner.startPosition;
3132 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3137 int index = leftCount[SquareBracket]++;
3138 if (index == leftPositions[SquareBracket].length) {
3139 System.arraycopy(leftPositions[SquareBracket], 0,
3140 (leftPositions[SquareBracket] = new int[index * 2]), 0,
3142 System.arraycopy(leftDepths[SquareBracket], 0,
3143 (leftDepths[SquareBracket] = new int[index * 2]), 0,
3146 leftPositions[SquareBracket][index] = scanner.startPosition;
3147 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3152 int index = rightCount[SquareBracket]++;
3153 if (index == rightPositions[SquareBracket].length) {
3154 System.arraycopy(rightPositions[SquareBracket], 0,
3155 (rightPositions[SquareBracket] = new int[index * 2]), 0,
3157 System.arraycopy(rightDepths[SquareBracket], 0,
3158 (rightDepths[SquareBracket] = new int[index * 2]), 0,
3161 rightPositions[SquareBracket][index] = scanner.startPosition;
3162 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3167 if (scanner.getNextChar('\\')) {
3168 scanner.scanEscapeCharacter();
3169 } else { // consume next character
3170 scanner.unicodeAsBackSlash = false;
3171 // if (((scanner.currentCharacter =
3172 // source[scanner.currentPosition++]) ==
3174 // (source[scanner.currentPosition] ==
3176 // scanner.getNextUnicodeChar();
3178 if (scanner.withoutUnicodePtr != 0) {
3179 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3183 scanner.getNextChar('\'');
3187 // consume next character
3188 scanner.unicodeAsBackSlash = false;
3189 // if (((scanner.currentCharacter =
3190 // source[scanner.currentPosition++]) == '\\') &&
3191 // (source[scanner.currentPosition] == 'u')) {
3192 // scanner.getNextUnicodeChar();
3194 if (scanner.withoutUnicodePtr != 0) {
3195 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3198 while (scanner.currentCharacter != '"') {
3199 if (scanner.currentCharacter == '\r') {
3200 if (source[scanner.currentPosition] == '\n')
3201 scanner.currentPosition++;
3202 break; // the string cannot go further that
3205 if (scanner.currentCharacter == '\n') {
3206 break; // the string cannot go further that
3209 if (scanner.currentCharacter == '\\') {
3210 scanner.scanEscapeCharacter();
3212 // consume next character
3213 scanner.unicodeAsBackSlash = false;
3214 // if (((scanner.currentCharacter =
3215 // source[scanner.currentPosition++]) == '\\')
3216 // && (source[scanner.currentPosition] == 'u'))
3218 // scanner.getNextUnicodeChar();
3220 if (scanner.withoutUnicodePtr != 0) {
3221 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3229 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3232 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3233 && (source[scanner.currentPosition] == 'u')) {
3234 //-------------unicode traitement
3236 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3237 scanner.currentPosition++;
3238 while (source[scanner.currentPosition] == 'u') {
3239 scanner.currentPosition++;
3242 .getNumericValue(source[scanner.currentPosition++])) > 15
3245 .getNumericValue(source[scanner.currentPosition++])) > 15
3248 .getNumericValue(source[scanner.currentPosition++])) > 15
3251 .getNumericValue(source[scanner.currentPosition++])) > 15
3252 || c4 < 0) { //error don't
3255 scanner.currentCharacter = 'A';
3256 } //something different from \n and \r
3258 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3261 while (scanner.currentCharacter != '\r'
3262 && scanner.currentCharacter != '\n') {
3264 scanner.startPosition = scanner.currentPosition;
3265 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3266 && (source[scanner.currentPosition] == 'u')) {
3267 //-------------unicode traitement
3269 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3270 scanner.currentPosition++;
3271 while (source[scanner.currentPosition] == 'u') {
3272 scanner.currentPosition++;
3275 .getNumericValue(source[scanner.currentPosition++])) > 15
3278 .getNumericValue(source[scanner.currentPosition++])) > 15
3281 .getNumericValue(source[scanner.currentPosition++])) > 15
3284 .getNumericValue(source[scanner.currentPosition++])) > 15
3285 || c4 < 0) { //error don't
3288 scanner.currentCharacter = 'A';
3289 } //something different from \n
3292 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3296 if (scanner.recordLineSeparator
3297 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3298 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3299 // only record line positions we
3300 // have not recorded yet
3301 scanner.pushLineSeparator();
3302 if (this.scanner.taskTags != null) {
3303 this.scanner.checkTaskTag(this.scanner
3304 .getCurrentTokenStartPosition(), this.scanner
3305 .getCurrentTokenEndPosition());
3311 if (test > 0) { //traditional and annotation
3313 boolean star = false;
3314 // consume next character
3315 scanner.unicodeAsBackSlash = false;
3316 // if (((scanner.currentCharacter =
3317 // source[scanner.currentPosition++]) ==
3319 // (source[scanner.currentPosition] ==
3321 // scanner.getNextUnicodeChar();
3323 if (scanner.withoutUnicodePtr != 0) {
3324 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3327 if (scanner.currentCharacter == '*') {
3331 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3332 && (source[scanner.currentPosition] == 'u')) {
3333 //-------------unicode traitement
3335 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3336 scanner.currentPosition++;
3337 while (source[scanner.currentPosition] == 'u') {
3338 scanner.currentPosition++;
3341 .getNumericValue(source[scanner.currentPosition++])) > 15
3344 .getNumericValue(source[scanner.currentPosition++])) > 15
3347 .getNumericValue(source[scanner.currentPosition++])) > 15
3350 .getNumericValue(source[scanner.currentPosition++])) > 15
3351 || c4 < 0) { //error don't
3354 scanner.currentCharacter = 'A';
3355 } //something different from * and /
3357 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3360 //loop until end of comment */
3361 while ((scanner.currentCharacter != '/') || (!star)) {
3362 star = scanner.currentCharacter == '*';
3364 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3365 && (source[scanner.currentPosition] == 'u')) {
3366 //-------------unicode traitement
3368 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3369 scanner.currentPosition++;
3370 while (source[scanner.currentPosition] == 'u') {
3371 scanner.currentPosition++;
3374 .getNumericValue(source[scanner.currentPosition++])) > 15
3377 .getNumericValue(source[scanner.currentPosition++])) > 15
3380 .getNumericValue(source[scanner.currentPosition++])) > 15
3383 .getNumericValue(source[scanner.currentPosition++])) > 15
3384 || c4 < 0) { //error don't
3387 scanner.currentCharacter = 'A';
3388 } //something different from * and
3391 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3395 if (this.scanner.taskTags != null) {
3396 this.scanner.checkTaskTag(this.scanner
3397 .getCurrentTokenStartPosition(), this.scanner
3398 .getCurrentTokenEndPosition());
3405 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3406 scanner.scanIdentifierOrKeyword(false);
3409 if (Character.isDigit(scanner.currentCharacter)) {
3410 scanner.scanNumber(false);
3414 //-----------------end switch while
3415 // try--------------------
3416 } catch (IndexOutOfBoundsException e) {
3417 break; // read until EOF
3418 } catch (InvalidInputException e) {
3419 return false; // no clue
3422 if (scanner.recordLineSeparator) {
3423 // compilationUnit.compilationResult.lineSeparatorPositions =
3424 // scanner.getLineEnds();
3426 // check placement anomalies against other kinds of brackets
3427 for (int kind = 0; kind < BracketKinds; kind++) {
3428 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3429 int start = leftPositions[kind][leftIndex]; // deepest
3431 // find matching closing bracket
3432 int depth = leftDepths[kind][leftIndex];
3434 for (int i = 0; i < rightCount[kind]; i++) {
3435 int pos = rightPositions[kind][i];
3436 // want matching bracket further in source with same
3438 if ((pos > start) && (depth == rightDepths[kind][i])) {
3443 if (end < 0) { // did not find a good closing match
3444 problemReporter.unmatchedBracket(start, referenceContext,
3445 compilationUnit.compilationResult);
3448 // check if even number of opening/closing other brackets
3449 // in between this pair of brackets
3451 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3452 for (int i = 0; i < leftCount[otherKind]; i++) {
3453 int pos = leftPositions[otherKind][i];
3454 if ((pos > start) && (pos < end))
3457 for (int i = 0; i < rightCount[otherKind]; i++) {
3458 int pos = rightPositions[otherKind][i];
3459 if ((pos > start) && (pos < end))
3463 problemReporter.unmatchedBracket(start, referenceContext,
3464 compilationUnit.compilationResult); //bracket
3470 // too many opening brackets ?
3471 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3472 anomaliesDetected = true;
3473 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3474 - i - 1], referenceContext, compilationUnit.compilationResult);
3476 // too many closing brackets ?
3477 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3478 anomaliesDetected = true;
3479 problemReporter.unmatchedBracket(rightPositions[kind][i],
3480 referenceContext, compilationUnit.compilationResult);
3482 if (anomaliesDetected)
3485 return anomaliesDetected;
3486 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3487 return anomaliesDetected;
3488 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3489 return anomaliesDetected;
3492 protected void pushOnAstLengthStack(int pos) {
3494 astLengthStack[++astLengthPtr] = pos;
3495 } catch (IndexOutOfBoundsException e) {
3496 int oldStackLength = astLengthStack.length;
3497 int[] oldPos = astLengthStack;
3498 astLengthStack = new int[oldStackLength + StackIncrement];
3499 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3500 astLengthStack[astLengthPtr] = pos;
3503 protected void pushOnAstStack(AstNode node) {
3505 * add a new obj on top of the ast stack
3508 astStack[++astPtr] = node;
3509 } catch (IndexOutOfBoundsException e) {
3510 int oldStackLength = astStack.length;
3511 AstNode[] oldStack = astStack;
3512 astStack = new AstNode[oldStackLength + AstStackIncrement];
3513 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3514 astPtr = oldStackLength;
3515 astStack[astPtr] = node;
3518 astLengthStack[++astLengthPtr] = 1;
3519 } catch (IndexOutOfBoundsException e) {
3520 int oldStackLength = astLengthStack.length;
3521 int[] oldPos = astLengthStack;
3522 astLengthStack = new int[oldStackLength + AstStackIncrement];
3523 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3524 astLengthStack[astLengthPtr] = 1;