1 /**********************************************************************
2 Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de
3 All rights reserved. This program and the accompanying material
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;
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;
565 // // this.chIndx = 0;
566 // // this.rowCount = rowCount;
567 // // this.columnCount = 0;
568 // this.phpEnd = false;
569 // this.phpMode = true;
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 != 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'.");
971 // // getNextToken();
974 // concatenationExpression();
977 // } else if (token == TokenNamerequire || token == TokenNamerequire_once)
981 // if (token == TokenNameLPAREN) {
983 // if (token == TokenNameSEMICOLON) {
986 // if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
987 // throwSyntaxError("';' expected after 'require' or 'require_once'.");
989 // // getNextToken();
992 // concatenationExpression();
996 if (token == TokenNameif) {
998 if (token == TokenNameLPAREN) {
1001 throwSyntaxError("'(' expected after 'if' keyword.");
1004 if (token == TokenNameRPAREN) {
1007 throwSyntaxError("')' expected after 'if' condition.");
1011 } else if (token == TokenNameswitch) {
1013 if (token == TokenNameLPAREN) {
1016 throwSyntaxError("'(' expected after 'switch' keyword.");
1019 if (token == TokenNameRPAREN) {
1022 throwSyntaxError("')' expected after 'switch' condition.");
1026 } else if (token == TokenNamefor) {
1028 if (token == TokenNameLPAREN) {
1031 throwSyntaxError("'(' expected after 'for' keyword.");
1033 if (token == TokenNameSEMICOLON) {
1037 if (token == TokenNameSEMICOLON) {
1040 throwSyntaxError("';' expected after 'for'.");
1043 if (token == TokenNameSEMICOLON) {
1047 if (token == TokenNameSEMICOLON) {
1050 throwSyntaxError("';' expected after 'for'.");
1053 if (token == TokenNameRPAREN) {
1057 if (token == TokenNameRPAREN) {
1060 throwSyntaxError("')' expected after 'for'.");
1065 } else if (token == TokenNamewhile) {
1067 if (token == TokenNameLPAREN) {
1070 throwSyntaxError("'(' expected after 'while' keyword.");
1073 if (token == TokenNameRPAREN) {
1076 throwSyntaxError("')' expected after 'while' condition.");
1080 } else if (token == TokenNamedo) {
1082 if (token == TokenNameLBRACE) {
1085 throwSyntaxError("'{' expected after 'do' keyword.");
1087 if (token != TokenNameRBRACE) {
1090 if (token == TokenNameRBRACE) {
1093 throwSyntaxError("'}' expected after 'do' keyword.");
1095 if (token == TokenNamewhile) {
1097 if (token == TokenNameLPAREN) {
1100 throwSyntaxError("'(' expected after 'while' keyword.");
1103 if (token == TokenNameRPAREN) {
1106 throwSyntaxError("')' expected after 'while' condition.");
1109 throwSyntaxError("'while' expected after 'do' keyword.");
1111 if (token == TokenNameSEMICOLON) {
1114 if (token != TokenNameINLINE_HTML) {
1115 throwSyntaxError("';' expected after do-while statement.");
1120 } else if (token == TokenNameforeach) {
1122 if (token == TokenNameLPAREN) {
1125 throwSyntaxError("'(' expected after 'foreach' keyword.");
1128 if (token == TokenNameas) {
1131 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1134 if (token == TokenNameEQUAL_GREATER) {
1138 if (token == TokenNameRPAREN) {
1141 throwSyntaxError("')' expected after 'foreach' expression.");
1145 } else if (token == TokenNamecontinue || token == TokenNamebreak
1146 || token == TokenNamereturn) {
1148 if (token != TokenNameSEMICOLON) {
1151 if (token == TokenNameSEMICOLON) {
1154 if (token != TokenNameINLINE_HTML) {
1155 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1160 } else if (token == TokenNameecho) {
1163 if (token == TokenNameSEMICOLON) {
1166 if (token != TokenNameINLINE_HTML) {
1167 throwSyntaxError("';' expected after 'echo' statement.");
1172 } else if (token == TokenNameINLINE_HTML) {
1175 // } else if (token == TokenNameprint) {
1178 // if (token == TokenNameSEMICOLON) {
1181 // if (token != TokenNameStopPHP) {
1182 // throwSyntaxError("';' expected after 'print' statement.");
1187 } else if (token == TokenNameglobal) {
1190 if (token == TokenNameSEMICOLON) {
1193 if (token != TokenNameINLINE_HTML) {
1194 throwSyntaxError("';' expected after 'global' statement.");
1199 } else if (token == TokenNamestatic) {
1202 if (token == TokenNameSEMICOLON) {
1205 if (token != TokenNameINLINE_HTML) {
1206 throwSyntaxError("';' expected after 'static' statement.");
1211 }else if (token == TokenNameunset) {
1213 if (token == TokenNameLPAREN) {
1216 throwSyntaxError("'(' expected after 'unset' statement.");
1219 if (token == TokenNameRPAREN) {
1222 throwSyntaxError("')' expected after 'unset' statement.");
1224 if (token == TokenNameSEMICOLON) {
1227 if (token != TokenNameINLINE_HTML) {
1228 throwSyntaxError("';' expected after 'unset' statement.");
1233 } else if (token == TokenNamefunction) {
1234 MethodDeclaration methodDecl = new MethodDeclaration(
1235 this.compilationUnit.compilationResult);
1236 methodDecl.declarationSourceStart = scanner
1237 .getCurrentTokenStartPosition();
1239 functionDefinition(methodDecl);
1241 } else if (token == TokenNametry) {
1243 if (token != TokenNameLBRACE) {
1244 throwSyntaxError("'{' expected in 'try' statement.");
1248 if (token != TokenNameRBRACE) {
1249 throwSyntaxError("'}' expected in 'try' statement.");
1253 } else if (token == TokenNamecatch) {
1255 if (token != TokenNameLPAREN) {
1256 throwSyntaxError("'(' expected in 'catch' statement.");
1259 fully_qualified_class_name();
1260 if (token != TokenNameVariable) {
1261 throwSyntaxError("Variable expected in 'catch' statement.");
1265 if (token != TokenNameRBRACE) {
1266 throwSyntaxError("')' expected in 'catch' statement.");
1270 if (token != TokenNameLBRACE) {
1271 throwSyntaxError("'{' expected in 'catch' statement.");
1275 if (token != TokenNameRBRACE) {
1276 throwSyntaxError("'}' expected in 'catch' statement.");
1279 additional_catches();
1281 } else if (token == TokenNamethrow) {
1285 if (token == TokenNameSEMICOLON) {
1288 throwSyntaxError("';' expected after 'throw' exxpression.");
1292 } else if (token == TokenNamefinal || token == TokenNameabstract
1293 || token == TokenNameclass || token == TokenNameinterface) {
1294 TypeDeclaration typeDecl = new TypeDeclaration(
1295 this.compilationUnit.compilationResult);
1296 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1297 // default super class
1298 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1299 compilationUnit.types.add(typeDecl);
1301 pushOnAstStack(typeDecl);
1302 unticked_class_declaration_statement(typeDecl);
1303 // classBody(typeDecl);
1310 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1311 } else if (token == TokenNameLBRACE) {
1313 if (token != TokenNameRBRACE) {
1316 if (token == TokenNameRBRACE) {
1320 throwSyntaxError("'}' expected.");
1323 if (token != TokenNameSEMICOLON) {
1326 if (token == TokenNameSEMICOLON) {
1330 if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
1331 throwSyntaxError("';' expected after expression (Found token: "
1332 + scanner.toStringAction(token) + ")");
1338 private void additional_catches() {
1339 while (token == TokenNamecatch) {
1341 if (token != TokenNameLPAREN) {
1342 throwSyntaxError("'(' expected in 'catch' statement.");
1345 fully_qualified_class_name();
1346 if (token != TokenNameVariable) {
1347 throwSyntaxError("Variable expected in 'catch' statement.");
1351 if (token != TokenNameRBRACE) {
1352 throwSyntaxError("')' expected in 'catch' statement.");
1356 if (token != TokenNameLBRACE) {
1357 throwSyntaxError("'{' expected in 'catch' statement.");
1361 if (token != TokenNameRBRACE) {
1362 throwSyntaxError("'}' expected in 'catch' statement.");
1368 private void global_var_list() {
1370 // global_var_list ',' global_var
1374 if (token != TokenNameCOMMA) {
1380 private void global_var() {
1384 //| '$' '{' expr '}'
1385 if (token == TokenNameVariable) {
1387 } else if (token == TokenNameDOLLAR) {
1389 if (token == TokenNameLPAREN) {
1392 if (token != TokenNameLPAREN) {
1393 throwSyntaxError("')' expected in global variable.");
1401 private void static_var_list() {
1403 // static_var_list ',' T_VARIABLE
1404 //| static_var_list ',' T_VARIABLE '=' static_scalar
1406 //| T_VARIABLE '=' static_scalar
1408 if (token == TokenNameVariable) {
1410 if (token == TokenNameEQUAL) {
1414 if (token != TokenNameCOMMA) {
1423 private void unset_variables() {
1426 // | unset_variables ',' unset_variable
1431 if (token != TokenNameCOMMA) {
1437 private final void initializeModifiers() {
1439 this.modifiersSourceStart = -1;
1441 private final void checkAndSetModifiers(int flag) {
1442 this.modifiers |= flag;
1443 if (this.modifiersSourceStart < 0)
1444 this.modifiersSourceStart = this.scanner.startPosition;
1446 private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1447 initializeModifiers();
1448 if (token == TokenNameinterface) {
1449 // interface_entry T_STRING
1450 // interface_extends_list
1451 // '{' class_statement_list '}'
1452 checkAndSetModifiers(AccInterface);
1454 typeDecl.modifiers = this.modifiers;
1455 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1456 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1457 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1458 typeDecl.name = scanner.getCurrentIdentifierSource();
1459 if (token > TokenNameKEYWORD) {
1460 throwSyntaxError("Don't use a keyword for interface declaration ["
1461 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1462 typeDecl.sourceEnd);
1465 interface_extends_list();
1467 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1468 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1469 typeDecl.name = new char[]{' '};
1470 throwSyntaxError("Interface name expected after keyword 'interface'.",
1471 typeDecl.sourceStart, typeDecl.sourceEnd);
1475 // class_entry_type T_STRING extends_from
1477 // '{' class_statement_list'}'
1479 typeDecl.modifiers = this.modifiers;
1481 //identifier 'extends' identifier
1482 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1483 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1484 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1485 typeDecl.name = scanner.getCurrentIdentifierSource();
1486 if (token > TokenNameKEYWORD) {
1487 throwSyntaxError("Don't use a keyword for class declaration ["
1488 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1489 typeDecl.sourceEnd);
1494 // | T_EXTENDS fully_qualified_class_name
1495 if (token == TokenNameextends) {
1497 if (token == TokenNameIdentifier) {
1500 throwSyntaxError("Class name expected after keyword 'extends'.",
1501 scanner.getCurrentTokenStartPosition(), scanner
1502 .getCurrentTokenEndPosition());
1507 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1508 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1509 typeDecl.name = new char[]{' '};
1510 throwSyntaxError("Class name expected after keyword 'class'.",
1511 typeDecl.sourceStart, typeDecl.sourceEnd);
1515 // '{' class_statement_list '}'
1516 if (token == TokenNameLBRACE) {
1518 if (token != TokenNameRBRACE) {
1519 class_statement_list();
1521 if (token == TokenNameRBRACE) {
1522 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1525 throwSyntaxError("'}' expected at end of class body.");
1528 throwSyntaxError("'{' expected at start of class body.");
1531 private void class_entry_type() {
1533 // | T_ABSTRACT T_CLASS
1534 // | T_FINAL T_CLASS
1535 if (token == TokenNameclass) {
1537 } else if (token == TokenNameabstract) {
1538 checkAndSetModifiers(AccAbstract);
1540 if (token != TokenNameclass) {
1541 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1544 } else if (token == TokenNamefinal) {
1545 checkAndSetModifiers(AccFinal);
1547 if (token != TokenNameclass) {
1548 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1552 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1555 private void interface_extends_list() {
1557 // | T_EXTENDS interface_list
1558 if (token == TokenNameextends) {
1563 private void implements_list() {
1565 // | T_IMPLEMENTS interface_list
1566 if (token == TokenNameimplements) {
1571 private void interface_list() {
1573 // fully_qualified_class_name
1574 //| interface_list ',' fully_qualified_class_name
1576 if (token == TokenNameIdentifier) {
1579 throwSyntaxError("Interface name expected after keyword 'implements'.");
1581 if (token != TokenNameCOMMA) {
1587 // private void classBody(TypeDeclaration typeDecl) {
1588 // //'{' [class-element-list] '}'
1589 // if (token == TokenNameLBRACE) {
1591 // if (token != TokenNameRBRACE) {
1592 // class_statement_list();
1594 // if (token == TokenNameRBRACE) {
1595 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1598 // throwSyntaxError("'}' expected at end of class body.");
1601 // throwSyntaxError("'{' expected at start of class body.");
1604 private void class_statement_list() {
1607 } while (token == TokenNamepublic || token == TokenNameprotected
1608 || token == TokenNameprivate || token == TokenNamestatic
1609 || token == TokenNameabstract || token == TokenNamefinal
1610 || token == TokenNamefunction || token == TokenNamevar);
1612 private void class_statement() {
1614 // variable_modifiers class_variable_declaration ';'
1615 // | class_constant_declaration ';'
1616 // | method_modifiers T_FUNCTION is_reference T_STRING
1617 // '(' parameter_list ')' method_body
1618 initializeModifiers();
1619 if (token == TokenNamevar) {
1620 checkAndSetModifiers(AccPublic);
1621 problemReporter.phpVarDeprecatedWarning(scanner
1622 .getCurrentTokenStartPosition(),
1623 scanner.getCurrentTokenEndPosition(), referenceContext,
1624 compilationUnit.compilationResult);
1626 class_variable_declaration();
1628 boolean hasModifiers = member_modifiers();
1629 if (token == TokenNamefunction) {
1630 if (!hasModifiers) {
1631 checkAndSetModifiers(AccPublic);
1633 MethodDeclaration methodDecl = new MethodDeclaration(
1634 this.compilationUnit.compilationResult);
1635 methodDecl.declarationSourceStart = scanner
1636 .getCurrentTokenStartPosition();
1637 methodDecl.modifiers = this.modifiers;
1639 functionDefinition(methodDecl);
1641 if (!hasModifiers) {
1642 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1644 class_variable_declaration();
1647 // if (token == TokenNamefunction) {
1648 // MethodDeclaration methodDecl = new MethodDeclaration(
1649 // this.compilationUnit.compilationResult);
1650 // methodDecl.declarationSourceStart = scanner
1651 // .getCurrentTokenStartPosition();
1653 // functionDefinition(methodDecl);
1654 // } else if (token == TokenNamevar) {
1658 // throwSyntaxError("'function' or 'var' expected.");
1661 // private void variable_modifiers() {
1662 // // variable_modifiers:
1663 // // non_empty_member_modifiers
1665 // initializeModifiers();
1666 // if (token == TokenNamevar) {
1667 // checkAndSetModifiers(AccPublic);
1668 // reportSyntaxError(
1669 // "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
1670 // modifier for field declarations.",
1671 // scanner.getCurrentTokenStartPosition(), scanner
1672 // .getCurrentTokenEndPosition());
1675 // if (!member_modifiers()) {
1676 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1677 // field declarations.");
1681 // private void method_modifiers() {
1682 // //method_modifiers:
1684 // //| non_empty_member_modifiers
1685 // initializeModifiers();
1686 // if (!member_modifiers()) {
1687 // checkAndSetModifiers(AccPublic);
1690 private boolean member_modifiers() {
1697 boolean foundToken = false;
1699 if (token == TokenNamepublic) {
1700 checkAndSetModifiers(AccPublic);
1703 } else if (token == TokenNameprotected) {
1704 checkAndSetModifiers(AccProtected);
1707 } else if (token == TokenNameprivate) {
1708 checkAndSetModifiers(AccPrivate);
1711 } else if (token == TokenNamestatic) {
1712 checkAndSetModifiers(AccStatic);
1715 } else if (token == TokenNameabstract) {
1716 checkAndSetModifiers(AccAbstract);
1719 } else if (token == TokenNamefinal) {
1720 checkAndSetModifiers(AccFinal);
1729 private void class_variable_declaration() {
1730 // class_variable_declaration:
1731 // class_variable_declaration ',' T_VARIABLE
1732 // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1734 // | T_VARIABLE '=' static_scalar
1736 if (token == TokenNameVariable) {
1738 if (token == TokenNameEQUAL) {
1743 // if (token == TokenNamethis) {
1744 // throwSyntaxError("'$this' not allowed after keyword 'public'
1745 // 'protected' 'private' 'var'.");
1747 throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1749 if (token != TokenNameCOMMA) {
1754 if (token != TokenNameSEMICOLON) {
1755 throwSyntaxError("';' expected after field declaration.");
1759 private void functionDefinition(MethodDeclaration methodDecl) {
1761 compilationUnit.types.add(methodDecl);
1763 AstNode node = astStack[astPtr];
1764 if (node instanceof TypeDeclaration) {
1765 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1766 if (typeDecl.methods == null) {
1767 typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1769 AbstractMethodDeclaration[] newMethods;
1774 newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1775 1, typeDecl.methods.length);
1776 newMethods[0] = methodDecl;
1777 typeDecl.methods = newMethods;
1781 functionDeclarator(methodDecl);
1782 functionBody(methodDecl);
1784 private void functionDeclarator(MethodDeclaration methodDecl) {
1785 //identifier '(' [parameter-list] ')'
1786 if (token == TokenNameAND) {
1789 if (token == TokenNameIdentifier) {
1790 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1791 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1792 methodDecl.selector = scanner.getCurrentIdentifierSource();
1794 if (token == TokenNameLPAREN) {
1797 throwSyntaxError("'(' expected in function declaration.");
1799 if (token != TokenNameRPAREN) {
1802 if (token != TokenNameRPAREN) {
1803 throwSyntaxError("')' expected in function declaration.");
1805 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1809 if (token > TokenNameKEYWORD) {
1810 throwSyntaxError("Don't use keyword for function declaration [" + token
1813 throwSyntaxError("Function name expected after keyword 'function'.");
1817 private void parameterList() {
1818 //parameter-declaration
1819 //parameter-list ',' parameter-declaration
1821 parameterDeclaration();
1822 if (token != TokenNameCOMMA) {
1828 private void parameterDeclaration() {
1830 //variable-reference
1831 if (token == TokenNameAND) {
1836 throwSyntaxError("Variable expected after reference operator '&'.");
1839 //variable '=' constant
1840 if (token == TokenNameVariable) {
1842 if (token == TokenNameEQUAL) {
1848 // if (token == TokenNamethis) {
1849 // throwSyntaxError("Reserved word '$this' not allowed in parameter
1853 private void labeledStatementList() {
1854 if (token != TokenNamecase && token != TokenNamedefault) {
1855 throwSyntaxError("'case' or 'default' expected.");
1858 if (token == TokenNamecase) {
1860 expr(); //constant();
1861 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1863 if (token == TokenNamecase || token == TokenNamedefault) { // empty
1871 // else if (token == TokenNameSEMICOLON) {
1873 // "':' expected after 'case' keyword (Found token: " +
1874 // scanner.toStringAction(token) + ")",
1875 // scanner.getCurrentTokenStartPosition(),
1876 // scanner.getCurrentTokenEndPosition(),
1879 // if (token == TokenNamecase) { // empty case statement ?
1885 throwSyntaxError("':' character after 'case' constant expected (Found token: "
1886 + scanner.toStringAction(token) + ")");
1888 } else { // TokenNamedefault
1890 if (token == TokenNameCOLON) {
1894 throwSyntaxError("':' character after 'default' expected.");
1897 } while (token == TokenNamecase || token == TokenNamedefault);
1899 // public void labeledStatement() {
1900 // if (token == TokenNamecase) {
1903 // if (token == TokenNameDDOT) {
1907 // throwSyntaxError("':' character after 'case' constant expected.");
1910 // } else if (token == TokenNamedefault) {
1912 // if (token == TokenNameDDOT) {
1916 // throwSyntaxError("':' character after 'default' expected.");
1921 // public void expressionStatement() {
1923 // private void inclusionStatement() {
1925 // public void compoundStatement() {
1927 // public void selectionStatement() {
1930 // public void iterationStatement() {
1933 // public void jumpStatement() {
1936 // public void outputStatement() {
1939 // public void scopeStatement() {
1942 // public void flowStatement() {
1945 // public void definitionStatement() {
1947 private void ifStatement() {
1948 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1949 if (token == TokenNameCOLON) {
1951 if (token != TokenNameendif) {
1954 case TokenNameelse :
1956 if (token == TokenNameCOLON) {
1958 if (token != TokenNameendif) {
1962 if (token == TokenNameif) { //'else if'
1964 elseifStatementList();
1966 throwSyntaxError("':' expected after 'else'.");
1970 case TokenNameelseif :
1972 elseifStatementList();
1976 if (token != TokenNameendif) {
1977 throwSyntaxError("'endif' expected.");
1980 if (token != TokenNameSEMICOLON) {
1981 throwSyntaxError("';' expected after if-statement.");
1985 // statement [else-statement]
1986 statement(TokenNameEOF);
1987 if (token == TokenNameelseif) {
1989 if (token == TokenNameLPAREN) {
1992 throwSyntaxError("'(' expected after 'elseif' keyword.");
1995 if (token == TokenNameRPAREN) {
1998 throwSyntaxError("')' expected after 'elseif' condition.");
2001 } else if (token == TokenNameelse) {
2003 statement(TokenNameEOF);
2007 private void elseifStatementList() {
2011 case TokenNameelse :
2013 if (token == TokenNameCOLON) {
2015 if (token != TokenNameendif) {
2020 if (token == TokenNameif) { //'else if'
2023 throwSyntaxError("':' expected after 'else'.");
2027 case TokenNameelseif :
2035 private void elseifStatement() {
2036 if (token == TokenNameLPAREN) {
2039 if (token != TokenNameRPAREN) {
2040 throwSyntaxError("')' expected in else-if-statement.");
2043 if (token != TokenNameCOLON) {
2044 throwSyntaxError("':' expected in else-if-statement.");
2047 if (token != TokenNameendif) {
2052 private void switchStatement() {
2053 if (token == TokenNameCOLON) {
2054 // ':' [labeled-statement-list] 'endswitch' ';'
2056 labeledStatementList();
2057 if (token != TokenNameendswitch) {
2058 throwSyntaxError("'endswitch' expected.");
2061 if (token != TokenNameSEMICOLON) {
2062 throwSyntaxError("';' expected after switch-statement.");
2066 // '{' [labeled-statement-list] '}'
2067 if (token != TokenNameLBRACE) {
2068 throwSyntaxError("'{' expected in switch statement.");
2071 if (token != TokenNameRBRACE) {
2072 labeledStatementList();
2074 if (token != TokenNameRBRACE) {
2075 throwSyntaxError("'}' expected in switch statement.");
2080 private void forStatement() {
2081 if (token == TokenNameCOLON) {
2084 if (token != TokenNameendfor) {
2085 throwSyntaxError("'endfor' expected.");
2088 if (token != TokenNameSEMICOLON) {
2089 throwSyntaxError("';' expected after for-statement.");
2093 statement(TokenNameEOF);
2096 private void whileStatement() {
2097 // ':' statement-list 'endwhile' ';'
2098 if (token == TokenNameCOLON) {
2101 if (token != TokenNameendwhile) {
2102 throwSyntaxError("'endwhile' expected.");
2105 if (token != TokenNameSEMICOLON) {
2106 throwSyntaxError("';' expected after while-statement.");
2110 statement(TokenNameEOF);
2113 private void foreachStatement() {
2114 if (token == TokenNameCOLON) {
2117 if (token != TokenNameendforeach) {
2118 throwSyntaxError("'endforeach' expected.");
2121 if (token != TokenNameSEMICOLON) {
2122 throwSyntaxError("';' expected after foreach-statement.");
2126 statement(TokenNameEOF);
2129 // private void exitStatus() {
2130 // if (token == TokenNameLPAREN) {
2133 // throwSyntaxError("'(' expected in 'exit-status'.");
2135 // if (token != TokenNameRPAREN) {
2138 // if (token == TokenNameRPAREN) {
2141 // throwSyntaxError("')' expected after 'exit-status'.");
2144 private void expressionList() {
2147 if (token == TokenNameCOMMA) {
2154 private void expr() {
2156 // | expr_without_variable
2157 // if (token!=TokenNameEOF) {
2158 if (Scanner.TRACE) {
2159 System.out.println("TRACE: expr()");
2161 expr_without_variable(true);
2164 private void expr_without_variable(boolean only_variable) {
2165 // internal_functions_in_yacc
2174 // | T_INC rw_variable
2175 // | T_DEC rw_variable
2176 // | T_INT_CAST expr
2177 // | T_DOUBLE_CAST expr
2178 // | T_STRING_CAST expr
2179 // | T_ARRAY_CAST expr
2180 // | T_OBJECT_CAST expr
2181 // | T_BOOL_CAST expr
2182 // | T_UNSET_CAST expr
2183 // | T_EXIT exit_expr
2185 // | T_ARRAY '(' array_pair_list ')'
2186 // | '`' encaps_list '`'
2187 // | T_LIST '(' assignment_list ')' '=' expr
2188 // | T_NEW class_name_reference ctor_arguments
2189 // | variable '=' expr
2190 // | variable '=' '&' variable
2191 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2192 // | variable T_PLUS_EQUAL expr
2193 // | variable T_MINUS_EQUAL expr
2194 // | variable T_MUL_EQUAL expr
2195 // | variable T_DIV_EQUAL expr
2196 // | variable T_CONCAT_EQUAL expr
2197 // | variable T_MOD_EQUAL expr
2198 // | variable T_AND_EQUAL expr
2199 // | variable T_OR_EQUAL expr
2200 // | variable T_XOR_EQUAL expr
2201 // | variable T_SL_EQUAL expr
2202 // | variable T_SR_EQUAL expr
2203 // | rw_variable T_INC
2204 // | rw_variable T_DEC
2205 // | expr T_BOOLEAN_OR expr
2206 // | expr T_BOOLEAN_AND expr
2207 // | expr T_LOGICAL_OR expr
2208 // | expr T_LOGICAL_AND expr
2209 // | expr T_LOGICAL_XOR expr
2221 // | expr T_IS_IDENTICAL expr
2222 // | expr T_IS_NOT_IDENTICAL expr
2223 // | expr T_IS_EQUAL expr
2224 // | expr T_IS_NOT_EQUAL expr
2226 // | expr T_IS_SMALLER_OR_EQUAL expr
2228 // | expr T_IS_GREATER_OR_EQUAL expr
2229 // | expr T_INSTANCEOF class_name_reference
2230 // | expr '?' expr ':' expr
2231 if (Scanner.TRACE) {
2232 System.out.println("TRACE: expr_without_variable() PART 1");
2235 case TokenNameisset :
2236 case TokenNameempty :
2237 case TokenNameeval :
2238 case TokenNameinclude :
2239 case TokenNameinclude_once :
2240 case TokenNamerequire :
2241 case TokenNamerequire_once :
2242 internal_functions_in_yacc();
2245 case TokenNameLPAREN :
2248 if (token == TokenNameRPAREN) {
2251 throwSyntaxError("')' expected in expression.");
2261 // | T_INT_CAST expr
2262 // | T_DOUBLE_CAST expr
2263 // | T_STRING_CAST expr
2264 // | T_ARRAY_CAST expr
2265 // | T_OBJECT_CAST expr
2266 // | T_BOOL_CAST expr
2267 // | T_UNSET_CAST expr
2268 case TokenNameclone :
2269 case TokenNameprint :
2271 case TokenNamePLUS :
2272 case TokenNameMINUS :
2274 case TokenNameTWIDDLE :
2275 case TokenNameintCAST :
2276 case TokenNamedoubleCAST :
2277 case TokenNamestringCAST :
2278 case TokenNamearrayCAST :
2279 case TokenNameobjectCAST :
2280 case TokenNameboolCAST :
2281 case TokenNameunsetCAST :
2285 case TokenNameexit :
2291 //| T_STRING_VARNAME
2293 //| '"' encaps_list '"'
2294 //| '\'' encaps_list '\''
2295 //| T_START_HEREDOC encaps_list T_END_HEREDOC
2296 // | '`' encaps_list '`'
2298 case TokenNameIntegerLiteral :
2299 case TokenNameDoubleLiteral :
2300 case TokenNameStringLiteral :
2301 case TokenNameStringConstant :
2302 case TokenNameStringInterpolated :
2303 case TokenNameFILE :
2304 case TokenNameLINE :
2305 case TokenNameCLASS_C :
2306 case TokenNameMETHOD_C :
2307 case TokenNameFUNC_C :
2310 case TokenNameHEREDOC :
2313 case TokenNamearray :
2314 // T_ARRAY '(' array_pair_list ')'
2316 if (token == TokenNameLPAREN) {
2318 if (token == TokenNameRPAREN) {
2323 if (token != TokenNameRPAREN) {
2324 throwSyntaxError("')' expected after keyword 'array'"
2325 + "(Found token: " + scanner.toStringAction(token) + ")");
2329 throwSyntaxError("'(' expected after keyword 'array'"
2330 + "(Found token: " + scanner.toStringAction(token) + ")");
2333 case TokenNamelist :
2334 // | T_LIST '(' assignment_list ')' '=' expr
2336 if (token == TokenNameLPAREN) {
2339 if (token != TokenNameRPAREN) {
2340 throwSyntaxError("')' expected after 'list' keyword.");
2343 if (token != TokenNameEQUAL) {
2344 throwSyntaxError("'=' expected after 'list' keyword.");
2349 throwSyntaxError("'(' expected after 'list' keyword.");
2353 // | T_NEW class_name_reference ctor_arguments
2355 class_name_reference();
2358 // | T_INC rw_variable
2359 // | T_DEC rw_variable
2360 case TokenNamePLUS_PLUS :
2361 case TokenNameMINUS_MINUS :
2365 // | variable '=' expr
2366 // | variable '=' '&' variable
2367 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2368 // | variable T_PLUS_EQUAL expr
2369 // | variable T_MINUS_EQUAL expr
2370 // | variable T_MUL_EQUAL expr
2371 // | variable T_DIV_EQUAL expr
2372 // | variable T_CONCAT_EQUAL expr
2373 // | variable T_MOD_EQUAL expr
2374 // | variable T_AND_EQUAL expr
2375 // | variable T_OR_EQUAL expr
2376 // | variable T_XOR_EQUAL expr
2377 // | variable T_SL_EQUAL expr
2378 // | variable T_SR_EQUAL expr
2379 // | rw_variable T_INC
2380 // | rw_variable T_DEC
2381 case TokenNameIdentifier :
2382 case TokenNameVariable :
2383 case TokenNameDOLLAR :
2386 case TokenNameEQUAL :
2388 if (token == TokenNameAND) {
2390 if (token == TokenNamenew) {
2392 throwSyntaxError("not yet implemented (= & new)");
2393 // class_name_reference();
2394 // ctor_arguments();
2402 case TokenNamePLUS_EQUAL :
2403 case TokenNameMINUS_EQUAL :
2404 case TokenNameMULTIPLY_EQUAL :
2405 case TokenNameDIVIDE_EQUAL :
2406 case TokenNameDOT_EQUAL :
2407 case TokenNameREMAINDER_EQUAL :
2408 case TokenNameAND_EQUAL :
2409 case TokenNameOR_EQUAL :
2410 case TokenNameXOR_EQUAL :
2411 case TokenNameRIGHT_SHIFT_EQUAL :
2412 case TokenNameLEFT_SHIFT_EQUAL :
2416 case TokenNamePLUS_PLUS :
2417 case TokenNameMINUS_MINUS :
2421 if (!only_variable) {
2422 throwSyntaxError("Variable expression not allowed (found token '"
2423 + scanner.toStringAction(token) + "').");
2428 if (token != TokenNameINLINE_HTML) {
2429 throwSyntaxError("Error in expression (found token '"
2430 + scanner.toStringAction(token) + "').");
2434 if (Scanner.TRACE) {
2435 System.out.println("TRACE: expr_without_variable() PART 2");
2437 // | expr T_BOOLEAN_OR expr
2438 // | expr T_BOOLEAN_AND expr
2439 // | expr T_LOGICAL_OR expr
2440 // | expr T_LOGICAL_AND expr
2441 // | expr T_LOGICAL_XOR expr
2453 // | expr T_IS_IDENTICAL expr
2454 // | expr T_IS_NOT_IDENTICAL expr
2455 // | expr T_IS_EQUAL expr
2456 // | expr T_IS_NOT_EQUAL expr
2458 // | expr T_IS_SMALLER_OR_EQUAL expr
2460 // | expr T_IS_GREATER_OR_EQUAL expr
2463 case TokenNameOR_OR :
2464 case TokenNameAND_AND :
2472 case TokenNamePLUS :
2473 case TokenNameMINUS :
2474 case TokenNameMULTIPLY :
2475 case TokenNameDIVIDE :
2476 case TokenNameREMAINDER :
2477 case TokenNameLEFT_SHIFT :
2478 case TokenNameRIGHT_SHIFT :
2479 case TokenNameEQUAL_EQUAL_EQUAL :
2480 case TokenNameNOT_EQUAL_EQUAL :
2481 case TokenNameEQUAL_EQUAL :
2482 case TokenNameNOT_EQUAL :
2483 case TokenNameLESS :
2484 case TokenNameLESS_EQUAL :
2485 case TokenNameGREATER :
2486 case TokenNameGREATER_EQUAL :
2490 // | expr T_INSTANCEOF class_name_reference
2491 // | expr '?' expr ':' expr
2492 case TokenNameinstanceof :
2494 throwSyntaxError("not yet implemented (class_name_reference)");
2495 // class_name_reference();
2497 case TokenNameQUESTION :
2500 if (token == TokenNameCOLON) {
2510 private void class_name_reference() {
2511 // class_name_reference:
2513 //| dynamic_class_name_reference
2514 if (Scanner.TRACE) {
2515 System.out.println("TRACE: class_name_reference()");
2517 if (token == TokenNameIdentifier) {
2520 dynamic_class_name_reference();
2523 private void dynamic_class_name_reference() {
2524 //dynamic_class_name_reference:
2525 // base_variable T_OBJECT_OPERATOR object_property
2526 // dynamic_class_name_variable_properties
2528 if (Scanner.TRACE) {
2529 System.out.println("TRACE: dynamic_class_name_reference()");
2532 if (token == TokenNameMINUS_GREATER) {
2535 dynamic_class_name_variable_properties();
2538 private void dynamic_class_name_variable_properties() {
2539 // dynamic_class_name_variable_properties:
2540 // dynamic_class_name_variable_properties
2541 // dynamic_class_name_variable_property
2543 if (Scanner.TRACE) {
2544 System.out.println("TRACE: dynamic_class_name_variable_properties()");
2546 while (token == TokenNameMINUS_GREATER) {
2547 dynamic_class_name_variable_property();
2550 private void dynamic_class_name_variable_property() {
2551 // dynamic_class_name_variable_property:
2552 // T_OBJECT_OPERATOR object_property
2553 if (Scanner.TRACE) {
2554 System.out.println("TRACE: dynamic_class_name_variable_property()");
2556 if (token == TokenNameMINUS_GREATER) {
2561 private void ctor_arguments() {
2564 //| '(' function_call_parameter_list ')'
2565 if (token == TokenNameLPAREN) {
2567 if (token == TokenNameRPAREN) {
2571 non_empty_function_call_parameter_list();
2572 if (token != TokenNameRPAREN) {
2573 throwSyntaxError("')' expected in ctor_arguments.");
2578 private void assignment_list() {
2580 // assignment_list ',' assignment_list_element
2581 //| assignment_list_element
2583 assignment_list_element();
2584 if (token != TokenNameCOMMA) {
2590 private void assignment_list_element() {
2591 //assignment_list_element:
2593 //| T_LIST '(' assignment_list ')'
2595 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2598 if (token == TokenNamelist) {
2600 if (token == TokenNameLPAREN) {
2603 if (token != TokenNameRPAREN) {
2604 throwSyntaxError("')' expected after 'list' keyword.");
2608 throwSyntaxError("'(' expected after 'list' keyword.");
2613 private void array_pair_list() {
2616 //| non_empty_array_pair_list possible_comma
2617 non_empty_array_pair_list();
2618 if (token == TokenNameCOMMA) {
2622 private void non_empty_array_pair_list() {
2623 //non_empty_array_pair_list:
2624 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2625 //| non_empty_array_pair_list ',' expr
2626 //| expr T_DOUBLE_ARROW expr
2628 //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2629 //| non_empty_array_pair_list ',' '&' w_variable
2630 //| expr T_DOUBLE_ARROW '&' w_variable
2634 if (token == TokenNameAND) {
2638 } else if (token == TokenNameEQUAL_GREATER) {
2640 if (token == TokenNameAND) {
2647 if (token != TokenNameCOMMA) {
2651 if (token == TokenNameRPAREN) {
2656 // private void variableList() {
2659 // if (token == TokenNameCOMMA) {
2666 private void variable_without_objects() {
2667 // variable_without_objects:
2668 // reference_variable
2669 // | simple_indirect_reference reference_variable
2670 if (Scanner.TRACE) {
2671 System.out.println("TRACE: variable_without_objects()");
2673 while (token == TokenNameDOLLAR) {
2676 reference_variable();
2678 private void function_call() {
2680 // T_STRING '(' function_call_parameter_list ')'
2681 //| class_constant '(' function_call_parameter_list ')'
2682 //| static_member '(' function_call_parameter_list ')'
2683 //| variable_without_objects '(' function_call_parameter_list ')'
2684 if (Scanner.TRACE) {
2685 System.out.println("TRACE: function_call()");
2687 if (token == TokenNameIdentifier) {
2690 case TokenNamePAAMAYIM_NEKUDOTAYIM :
2693 if (token == TokenNameIdentifier) {
2698 variable_without_objects();
2703 variable_without_objects();
2705 if (token != TokenNameLPAREN) {
2706 // TODO is this ok ?
2708 // throwSyntaxError("'(' expected in function call.");
2711 if (token == TokenNameRPAREN) {
2715 non_empty_function_call_parameter_list();
2716 if (token != TokenNameRPAREN) {
2717 throwSyntaxError("')' expected in function call.");
2721 // private void function_call_parameter_list() {
2722 // function_call_parameter_list:
2723 // non_empty_function_call_parameter_list { $$ = $1; }
2726 private void non_empty_function_call_parameter_list() {
2727 //non_empty_function_call_parameter_list:
2728 // expr_without_variable
2731 // | non_empty_function_call_parameter_list ',' expr_without_variable
2732 // | non_empty_function_call_parameter_list ',' variable
2733 // | non_empty_function_call_parameter_list ',' '&' w_variable
2734 if (Scanner.TRACE) {
2735 System.out.println("TRACE: non_empty_function_call_parameter_list()");
2738 if (token == TokenNameAND) {
2742 // if (token == TokenNameIdentifier || token == TokenNameVariable
2743 // || token == TokenNameDOLLAR) {
2746 expr_without_variable(true);
2749 if (token != TokenNameCOMMA) {
2755 private void fully_qualified_class_name() {
2756 if (token == TokenNameIdentifier) {
2759 throwSyntaxError("Class name expected.");
2762 private void static_member() {
2764 // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2765 // variable_without_objects
2766 if (Scanner.TRACE) {
2767 System.out.println("TRACE: static_member()");
2769 fully_qualified_class_name();
2770 if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2771 throwSyntaxError("'::' expected after class name (static_member).");
2774 variable_without_objects();
2776 private void base_variable_with_function_calls() {
2777 // base_variable_with_function_calls:
2780 boolean functionCall = false;
2781 if (Scanner.TRACE) {
2782 System.out.println("TRACE: base_variable_with_function_calls()");
2784 if (token == TokenNameIdentifier) {
2785 functionCall = true;
2786 } else if (token == TokenNameVariable) {
2787 int tempToken = token;
2788 int tempPosition = scanner.currentPosition;
2790 if (token == TokenNameLPAREN) {
2791 functionCall = true;
2794 scanner.currentPosition = tempPosition;
2795 scanner.phpMode = true;
2803 private void base_variable() {
2805 // reference_variable
2806 // | simple_indirect_reference reference_variable
2808 if (Scanner.TRACE) {
2809 System.out.println("TRACE: base_variable()");
2811 if (token == TokenNameIdentifier) {
2814 while (token == TokenNameDOLLAR) {
2817 reference_variable();
2820 // private void simple_indirect_reference() {
2821 // // simple_indirect_reference:
2823 // //| simple_indirect_reference '$'
2825 private void reference_variable() {
2826 // reference_variable:
2827 // reference_variable '[' dim_offset ']'
2828 // | reference_variable '{' expr '}'
2829 // | compound_variable
2830 if (Scanner.TRACE) {
2831 System.out.println("TRACE: reference_variable()");
2833 compound_variable();
2835 if (token == TokenNameLBRACE) {
2838 if (token != TokenNameRBRACE) {
2839 throwSyntaxError("'}' expected in reference variable.");
2842 } else if (token == TokenNameLBRACKET) {
2844 if (token != TokenNameRBRACKET) {
2847 if (token != TokenNameRBRACKET) {
2848 throwSyntaxError("']' expected in reference variable.");
2857 private void compound_variable() {
2858 // compound_variable:
2860 // | '$' '{' expr '}'
2861 if (Scanner.TRACE) {
2862 System.out.println("TRACE: compound_variable()");
2864 if (token == TokenNameVariable) {
2867 // because of simple_indirect_reference
2868 while (token == TokenNameDOLLAR) {
2871 if (token != TokenNameLBRACE) {
2872 throwSyntaxError("'{' expected after compound variable token '$'.");
2876 if (token != TokenNameRBRACE) {
2877 throwSyntaxError("'}' expected after compound variable token '$'.");
2882 // private void dim_offset() {
2888 private void object_property() {
2891 //| variable_without_objects
2892 if (Scanner.TRACE) {
2893 System.out.println("TRACE: object_property()");
2895 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2896 variable_without_objects();
2901 private void object_dim_list() {
2903 // object_dim_list '[' dim_offset ']'
2904 //| object_dim_list '{' expr '}'
2906 if (Scanner.TRACE) {
2907 System.out.println("TRACE: object_dim_list()");
2911 if (token == TokenNameLBRACE) {
2914 if (token != TokenNameRBRACE) {
2915 throwSyntaxError("'}' expected in object_dim_list.");
2918 } else if (token == TokenNameLBRACKET) {
2920 if (token == TokenNameRBRACKET) {
2925 if (token != TokenNameRBRACKET) {
2926 throwSyntaxError("']' expected in object_dim_list.");
2934 private void variable_name() {
2938 if (Scanner.TRACE) {
2939 System.out.println("TRACE: variable_name()");
2941 if (token == TokenNameIdentifier) {
2944 if (token != TokenNameLBRACE) {
2945 throwSyntaxError("'{' expected in variable name.");
2949 if (token != TokenNameRBRACE) {
2950 throwSyntaxError("'}' expected in variable name.");
2954 private void r_variable() {
2957 private void w_variable() {
2960 private void rw_variable() {
2963 private void variable() {
2965 // base_variable_with_function_calls T_OBJECT_OPERATOR
2966 // object_property method_or_not variable_properties
2967 // | base_variable_with_function_calls
2968 base_variable_with_function_calls();
2969 if (token == TokenNameMINUS_GREATER) {
2973 variable_properties();
2975 // if (token == TokenNameDOLLAR_LBRACE) {
2979 // if (token != TokenNameRBRACE) {
2980 // throwSyntaxError("'}' expected after indirect variable token '${'.");
2984 // if (token == TokenNameVariable) {
2986 // if (token == TokenNameLBRACKET) {
2989 // if (token != TokenNameRBRACKET) {
2990 // throwSyntaxError("']' expected in variable-list.");
2993 // } else if (token == TokenNameEQUAL) {
2998 // throwSyntaxError("$-variable expected in variable-list.");
3002 private void variable_properties() {
3003 // variable_properties:
3004 // variable_properties variable_property
3006 while (token == TokenNameMINUS_GREATER) {
3007 variable_property();
3010 private void variable_property() {
3011 // variable_property:
3012 // T_OBJECT_OPERATOR object_property method_or_not
3013 if (Scanner.TRACE) {
3014 System.out.println("TRACE: variable_property()");
3016 if (token == TokenNameMINUS_GREATER) {
3021 throwSyntaxError("'->' expected in variable_property.");
3024 private void method_or_not() {
3026 // '(' function_call_parameter_list ')'
3028 if (Scanner.TRACE) {
3029 System.out.println("TRACE: method_or_not()");
3031 if (token == TokenNameLPAREN) {
3033 if (token == TokenNameRPAREN) {
3037 non_empty_function_call_parameter_list();
3038 if (token != TokenNameRPAREN) {
3039 throwSyntaxError("')' expected in method_or_not.");
3044 private void exit_expr() {
3048 if (token != TokenNameLPAREN) {
3052 if (token == TokenNameRPAREN) {
3057 if (token != TokenNameRPAREN) {
3058 throwSyntaxError("')' expected after keyword 'exit'");
3062 private void internal_functions_in_yacc() {
3064 case TokenNameisset :
3065 // T_ISSET '(' isset_variables ')'
3067 if (token != TokenNameLPAREN) {
3068 throwSyntaxError("'(' expected after keyword 'isset'");
3072 if (token != TokenNameRPAREN) {
3073 throwSyntaxError("')' expected after keyword 'isset'");
3077 case TokenNameempty :
3078 // T_EMPTY '(' variable ')'
3080 if (token != TokenNameLPAREN) {
3081 throwSyntaxError("'(' expected after keyword 'empty'");
3085 if (token != TokenNameRPAREN) {
3086 throwSyntaxError("')' expected after keyword 'empty'");
3090 case TokenNameinclude :
3095 case TokenNameinclude_once :
3096 // T_INCLUDE_ONCE expr
3100 case TokenNameeval :
3101 // T_EVAL '(' expr ')'
3103 if (token != TokenNameLPAREN) {
3104 throwSyntaxError("'(' expected after keyword 'eval'");
3108 if (token != TokenNameRPAREN) {
3109 throwSyntaxError("')' expected after keyword 'eval'");
3113 case TokenNamerequire :
3118 case TokenNamerequire_once :
3119 // T_REQUIRE_ONCE expr
3125 private void isset_variables() {
3127 // | isset_variables ','
3128 if (token == TokenNameRPAREN) {
3129 throwSyntaxError("Variable expected after keyword 'isset'");
3133 if (token == TokenNameCOMMA) {
3140 private boolean common_scalar() {
3144 // | T_CONSTANT_ENCAPSED_STRING
3151 case TokenNameIntegerLiteral :
3154 case TokenNameDoubleLiteral :
3157 case TokenNameStringLiteral :
3160 case TokenNameStringConstant :
3163 case TokenNameStringInterpolated :
3166 case TokenNameFILE :
3169 case TokenNameLINE :
3172 case TokenNameCLASS_C :
3175 case TokenNameMETHOD_C :
3178 case TokenNameFUNC_C :
3184 private void scalar() {
3187 //| T_STRING_VARNAME
3190 //| '"' encaps_list '"'
3191 //| '\'' encaps_list '\''
3192 //| T_START_HEREDOC encaps_list T_END_HEREDOC
3193 throwSyntaxError("Not yet implemented (scalar).");
3195 private void static_scalar() {
3196 // static_scalar: /* compile-time evaluated scalars */
3199 // | '+' static_scalar
3200 // | '-' static_scalar
3201 // | T_ARRAY '(' static_array_pair_list ')'
3202 // | static_class_constant
3203 if (common_scalar()) {
3207 case TokenNameIdentifier :
3209 // static_class_constant:
3210 // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3211 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3213 if (token == TokenNameIdentifier) {
3216 throwSyntaxError("Identifier expected after '::' operator.");
3220 case TokenNamePLUS :
3224 case TokenNameMINUS :
3228 case TokenNamearray :
3230 if (token != TokenNameLPAREN) {
3231 throwSyntaxError("'(' expected after keyword 'array'");
3234 if (token == TokenNameRPAREN) {
3238 non_empty_static_array_pair_list();
3239 if (token != TokenNameRPAREN) {
3240 throwSyntaxError("')' expected after keyword 'array'");
3244 // case TokenNamenull :
3247 // case TokenNamefalse :
3250 // case TokenNametrue :
3254 throwSyntaxError("Static scalar/constant expected.");
3257 private void non_empty_static_array_pair_list() {
3258 // non_empty_static_array_pair_list:
3259 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3261 //| non_empty_static_array_pair_list ',' static_scalar
3262 //| static_scalar T_DOUBLE_ARROW static_scalar
3266 if (token == TokenNameEQUAL_GREATER) {
3270 if (token != TokenNameCOMMA) {
3274 if (token == TokenNameRPAREN) {
3279 public void reportSyntaxError() { //int act, int currentKind, int
3281 /* remember current scanner position */
3282 int startPos = scanner.startPosition;
3283 int currentPos = scanner.currentPosition;
3284 // String[] expectings;
3285 // String tokenName = name[symbol_index[currentKind]];
3286 //fetch all "accurate" possible terminals that could recover the error
3287 // int start, end = start = asi(stack[stateStackTop]);
3288 // while (asr[end] != 0)
3290 // int length = end - start;
3291 // expectings = new String[length];
3292 // if (length != 0) {
3293 // char[] indexes = new char[length];
3294 // System.arraycopy(asr, start, indexes, 0, length);
3295 // for (int i = 0; i < length; i++) {
3296 // expectings[i] = name[symbol_index[indexes[i]]];
3299 //if the pb is an EOF, try to tell the user that they are some
3300 // if (tokenName.equals(UNEXPECTED_EOF)) {
3301 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3302 // char[] tokenSource;
3304 // tokenSource = this.scanner.getCurrentTokenSource();
3305 // } catch (Exception e) {
3306 // tokenSource = new char[] {};
3308 // problemReporter().parseError(
3309 // this.scanner.startPosition,
3310 // this.scanner.currentPosition - 1,
3315 // } else { //the next test is HEAVILY grammar DEPENDENT.
3316 // if ((length == 14)
3317 // && (expectings[0] == "=") //$NON-NLS-1$
3318 // && (expectings[1] == "*=") //$NON-NLS-1$
3319 // && (expressionPtr > -1)) {
3320 // switch(currentKind) {
3321 // case TokenNameSEMICOLON:
3322 // case TokenNamePLUS:
3323 // case TokenNameMINUS:
3324 // case TokenNameDIVIDE:
3325 // case TokenNameREMAINDER:
3326 // case TokenNameMULTIPLY:
3327 // case TokenNameLEFT_SHIFT:
3328 // case TokenNameRIGHT_SHIFT:
3329 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3330 // case TokenNameLESS:
3331 // case TokenNameGREATER:
3332 // case TokenNameLESS_EQUAL:
3333 // case TokenNameGREATER_EQUAL:
3334 // case TokenNameEQUAL_EQUAL:
3335 // case TokenNameNOT_EQUAL:
3336 // case TokenNameXOR:
3337 // case TokenNameAND:
3338 // case TokenNameOR:
3339 // case TokenNameOR_OR:
3340 // case TokenNameAND_AND:
3341 // // the ; is not the expected token ==> it ends a statement when an
3342 // expression is not ended
3343 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3345 // case TokenNameRBRACE :
3346 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3349 // char[] tokenSource;
3351 // tokenSource = this.scanner.getCurrentTokenSource();
3352 // } catch (Exception e) {
3353 // tokenSource = new char[] {};
3355 // problemReporter().parseError(
3356 // this.scanner.startPosition,
3357 // this.scanner.currentPosition - 1,
3361 // this.checkAndReportBracketAnomalies(problemReporter());
3366 tokenSource = this.scanner.getCurrentTokenSource();
3367 } catch (Exception e) {
3368 tokenSource = new char[]{};
3370 // problemReporter().parseError(
3371 // this.scanner.startPosition,
3372 // this.scanner.currentPosition - 1,
3376 this.checkAndReportBracketAnomalies(problemReporter());
3379 /* reset scanner where it was */
3380 scanner.startPosition = startPos;
3381 scanner.currentPosition = currentPos;
3383 public static final int RoundBracket = 0;
3384 public static final int SquareBracket = 1;
3385 public static final int CurlyBracket = 2;
3386 public static final int BracketKinds = 3;
3387 protected int[] nestedMethod; //the ptr is nestedType
3388 protected int nestedType, dimensions;
3390 final static int AstStackIncrement = 100;
3391 protected int astPtr;
3392 protected AstNode[] astStack = new AstNode[AstStackIncrement];
3393 protected int astLengthPtr;
3394 protected int[] astLengthStack;
3395 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3396 public CompilationUnitDeclaration compilationUnit; /*
3397 * the result from parse()
3399 protected ReferenceContext referenceContext;
3400 protected ProblemReporter problemReporter;
3401 // protected CompilationResult compilationResult;
3403 * Returns this parser's problem reporter initialized with its reference
3404 * context. Also it is assumed that a problem is going to be reported, so
3405 * initializes the compilation result's line positions.
3407 public ProblemReporter problemReporter() {
3408 if (scanner.recordLineSeparator) {
3409 compilationUnit.compilationResult.lineSeparatorPositions = scanner
3412 problemReporter.referenceContext = referenceContext;
3413 return problemReporter;
3416 * Reconsider the entire source looking for inconsistencies in {} () []
3418 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3419 scanner.wasAcr = false;
3420 boolean anomaliesDetected = false;
3422 char[] source = scanner.source;
3423 int[] leftCount = {0, 0, 0};
3424 int[] rightCount = {0, 0, 0};
3425 int[] depths = {0, 0, 0};
3426 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3427 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3428 int[][] rightPositions = new int[][]{new int[10], new int[10],
3430 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3431 scanner.currentPosition = scanner.initialPosition; //starting
3433 // (first-zero-based
3435 while (scanner.currentPosition < scanner.eofPosition) { //loop for
3440 // ---------Consume white space and handles
3441 // startPosition---------
3442 boolean isWhiteSpace;
3444 scanner.startPosition = scanner.currentPosition;
3445 // if (((scanner.currentCharacter =
3446 // source[scanner.currentPosition++]) == '\\') &&
3447 // (source[scanner.currentPosition] == 'u')) {
3448 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3450 if (scanner.recordLineSeparator
3451 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3452 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3453 // only record line positions we have not
3455 scanner.pushLineSeparator();
3458 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3460 } while (isWhiteSpace
3461 && (scanner.currentPosition < scanner.eofPosition));
3462 // -------consume token until } is found---------
3463 switch (scanner.currentCharacter) {
3466 int index = leftCount[CurlyBracket]++;
3467 if (index == leftPositions[CurlyBracket].length) {
3468 System.arraycopy(leftPositions[CurlyBracket], 0,
3469 (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3472 .arraycopy(leftDepths[CurlyBracket], 0,
3473 (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3476 leftPositions[CurlyBracket][index] = scanner.startPosition;
3477 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3482 int index = rightCount[CurlyBracket]++;
3483 if (index == rightPositions[CurlyBracket].length) {
3484 System.arraycopy(rightPositions[CurlyBracket], 0,
3485 (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3487 System.arraycopy(rightDepths[CurlyBracket], 0,
3488 (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3491 rightPositions[CurlyBracket][index] = scanner.startPosition;
3492 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3497 int index = leftCount[RoundBracket]++;
3498 if (index == leftPositions[RoundBracket].length) {
3499 System.arraycopy(leftPositions[RoundBracket], 0,
3500 (leftPositions[RoundBracket] = new int[index * 2]), 0,
3503 .arraycopy(leftDepths[RoundBracket], 0,
3504 (leftDepths[RoundBracket] = new int[index * 2]), 0,
3507 leftPositions[RoundBracket][index] = scanner.startPosition;
3508 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3513 int index = rightCount[RoundBracket]++;
3514 if (index == rightPositions[RoundBracket].length) {
3515 System.arraycopy(rightPositions[RoundBracket], 0,
3516 (rightPositions[RoundBracket] = new int[index * 2]), 0,
3518 System.arraycopy(rightDepths[RoundBracket], 0,
3519 (rightDepths[RoundBracket] = new int[index * 2]), 0,
3522 rightPositions[RoundBracket][index] = scanner.startPosition;
3523 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3528 int index = leftCount[SquareBracket]++;
3529 if (index == leftPositions[SquareBracket].length) {
3530 System.arraycopy(leftPositions[SquareBracket], 0,
3531 (leftPositions[SquareBracket] = new int[index * 2]), 0,
3533 System.arraycopy(leftDepths[SquareBracket], 0,
3534 (leftDepths[SquareBracket] = new int[index * 2]), 0,
3537 leftPositions[SquareBracket][index] = scanner.startPosition;
3538 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3543 int index = rightCount[SquareBracket]++;
3544 if (index == rightPositions[SquareBracket].length) {
3545 System.arraycopy(rightPositions[SquareBracket], 0,
3546 (rightPositions[SquareBracket] = new int[index * 2]), 0,
3548 System.arraycopy(rightDepths[SquareBracket], 0,
3549 (rightDepths[SquareBracket] = new int[index * 2]), 0,
3552 rightPositions[SquareBracket][index] = scanner.startPosition;
3553 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3558 if (scanner.getNextChar('\\')) {
3559 scanner.scanEscapeCharacter();
3560 } else { // consume next character
3561 scanner.unicodeAsBackSlash = false;
3562 // if (((scanner.currentCharacter =
3563 // source[scanner.currentPosition++]) ==
3565 // (source[scanner.currentPosition] ==
3567 // scanner.getNextUnicodeChar();
3569 if (scanner.withoutUnicodePtr != 0) {
3570 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3574 scanner.getNextChar('\'');
3578 // consume next character
3579 scanner.unicodeAsBackSlash = false;
3580 // if (((scanner.currentCharacter =
3581 // source[scanner.currentPosition++]) == '\\') &&
3582 // (source[scanner.currentPosition] == 'u')) {
3583 // scanner.getNextUnicodeChar();
3585 if (scanner.withoutUnicodePtr != 0) {
3586 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3589 while (scanner.currentCharacter != '"') {
3590 if (scanner.currentCharacter == '\r') {
3591 if (source[scanner.currentPosition] == '\n')
3592 scanner.currentPosition++;
3593 break; // the string cannot go further that
3596 if (scanner.currentCharacter == '\n') {
3597 break; // the string cannot go further that
3600 if (scanner.currentCharacter == '\\') {
3601 scanner.scanEscapeCharacter();
3603 // consume next character
3604 scanner.unicodeAsBackSlash = false;
3605 // if (((scanner.currentCharacter =
3606 // source[scanner.currentPosition++]) == '\\')
3607 // && (source[scanner.currentPosition] == 'u'))
3609 // scanner.getNextUnicodeChar();
3611 if (scanner.withoutUnicodePtr != 0) {
3612 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3620 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3623 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3624 && (source[scanner.currentPosition] == 'u')) {
3625 //-------------unicode traitement
3627 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3628 scanner.currentPosition++;
3629 while (source[scanner.currentPosition] == 'u') {
3630 scanner.currentPosition++;
3633 .getNumericValue(source[scanner.currentPosition++])) > 15
3636 .getNumericValue(source[scanner.currentPosition++])) > 15
3639 .getNumericValue(source[scanner.currentPosition++])) > 15
3642 .getNumericValue(source[scanner.currentPosition++])) > 15
3643 || c4 < 0) { //error don't
3646 scanner.currentCharacter = 'A';
3647 } //something different from \n and \r
3649 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3652 while (scanner.currentCharacter != '\r'
3653 && scanner.currentCharacter != '\n') {
3655 scanner.startPosition = scanner.currentPosition;
3656 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3657 && (source[scanner.currentPosition] == 'u')) {
3658 //-------------unicode traitement
3660 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3661 scanner.currentPosition++;
3662 while (source[scanner.currentPosition] == 'u') {
3663 scanner.currentPosition++;
3666 .getNumericValue(source[scanner.currentPosition++])) > 15
3669 .getNumericValue(source[scanner.currentPosition++])) > 15
3672 .getNumericValue(source[scanner.currentPosition++])) > 15
3675 .getNumericValue(source[scanner.currentPosition++])) > 15
3676 || c4 < 0) { //error don't
3679 scanner.currentCharacter = 'A';
3680 } //something different from \n
3683 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3687 if (scanner.recordLineSeparator
3688 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3689 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3690 // only record line positions we
3691 // have not recorded yet
3692 scanner.pushLineSeparator();
3693 if (this.scanner.taskTags != null) {
3694 this.scanner.checkTaskTag(this.scanner
3695 .getCurrentTokenStartPosition(), this.scanner
3696 .getCurrentTokenEndPosition());
3702 if (test > 0) { //traditional and annotation
3704 boolean star = false;
3705 // consume next character
3706 scanner.unicodeAsBackSlash = false;
3707 // if (((scanner.currentCharacter =
3708 // source[scanner.currentPosition++]) ==
3710 // (source[scanner.currentPosition] ==
3712 // scanner.getNextUnicodeChar();
3714 if (scanner.withoutUnicodePtr != 0) {
3715 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3718 if (scanner.currentCharacter == '*') {
3722 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3723 && (source[scanner.currentPosition] == 'u')) {
3724 //-------------unicode traitement
3726 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3727 scanner.currentPosition++;
3728 while (source[scanner.currentPosition] == 'u') {
3729 scanner.currentPosition++;
3732 .getNumericValue(source[scanner.currentPosition++])) > 15
3735 .getNumericValue(source[scanner.currentPosition++])) > 15
3738 .getNumericValue(source[scanner.currentPosition++])) > 15
3741 .getNumericValue(source[scanner.currentPosition++])) > 15
3742 || c4 < 0) { //error don't
3745 scanner.currentCharacter = 'A';
3746 } //something different from * and /
3748 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3751 //loop until end of comment */
3752 while ((scanner.currentCharacter != '/') || (!star)) {
3753 star = scanner.currentCharacter == '*';
3755 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3756 && (source[scanner.currentPosition] == 'u')) {
3757 //-------------unicode traitement
3759 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3760 scanner.currentPosition++;
3761 while (source[scanner.currentPosition] == 'u') {
3762 scanner.currentPosition++;
3765 .getNumericValue(source[scanner.currentPosition++])) > 15
3768 .getNumericValue(source[scanner.currentPosition++])) > 15
3771 .getNumericValue(source[scanner.currentPosition++])) > 15
3774 .getNumericValue(source[scanner.currentPosition++])) > 15
3775 || c4 < 0) { //error don't
3778 scanner.currentCharacter = 'A';
3779 } //something different from * and
3782 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3786 if (this.scanner.taskTags != null) {
3787 this.scanner.checkTaskTag(this.scanner
3788 .getCurrentTokenStartPosition(), this.scanner
3789 .getCurrentTokenEndPosition());
3796 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3797 scanner.scanIdentifierOrKeyword(false);
3800 if (Character.isDigit(scanner.currentCharacter)) {
3801 scanner.scanNumber(false);
3805 //-----------------end switch while
3806 // try--------------------
3807 } catch (IndexOutOfBoundsException e) {
3808 break; // read until EOF
3809 } catch (InvalidInputException e) {
3810 return false; // no clue
3813 if (scanner.recordLineSeparator) {
3814 // compilationUnit.compilationResult.lineSeparatorPositions =
3815 // scanner.getLineEnds();
3817 // check placement anomalies against other kinds of brackets
3818 for (int kind = 0; kind < BracketKinds; kind++) {
3819 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3820 int start = leftPositions[kind][leftIndex]; // deepest
3822 // find matching closing bracket
3823 int depth = leftDepths[kind][leftIndex];
3825 for (int i = 0; i < rightCount[kind]; i++) {
3826 int pos = rightPositions[kind][i];
3827 // want matching bracket further in source with same
3829 if ((pos > start) && (depth == rightDepths[kind][i])) {
3834 if (end < 0) { // did not find a good closing match
3835 problemReporter.unmatchedBracket(start, referenceContext,
3836 compilationUnit.compilationResult);
3839 // check if even number of opening/closing other brackets
3840 // in between this pair of brackets
3842 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3843 for (int i = 0; i < leftCount[otherKind]; i++) {
3844 int pos = leftPositions[otherKind][i];
3845 if ((pos > start) && (pos < end))
3848 for (int i = 0; i < rightCount[otherKind]; i++) {
3849 int pos = rightPositions[otherKind][i];
3850 if ((pos > start) && (pos < end))
3854 problemReporter.unmatchedBracket(start, referenceContext,
3855 compilationUnit.compilationResult); //bracket
3861 // too many opening brackets ?
3862 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3863 anomaliesDetected = true;
3864 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3865 - i - 1], referenceContext, compilationUnit.compilationResult);
3867 // too many closing brackets ?
3868 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3869 anomaliesDetected = true;
3870 problemReporter.unmatchedBracket(rightPositions[kind][i],
3871 referenceContext, compilationUnit.compilationResult);
3873 if (anomaliesDetected)
3876 return anomaliesDetected;
3877 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3878 return anomaliesDetected;
3879 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3880 return anomaliesDetected;
3883 protected void pushOnAstLengthStack(int pos) {
3885 astLengthStack[++astLengthPtr] = pos;
3886 } catch (IndexOutOfBoundsException e) {
3887 int oldStackLength = astLengthStack.length;
3888 int[] oldPos = astLengthStack;
3889 astLengthStack = new int[oldStackLength + StackIncrement];
3890 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3891 astLengthStack[astLengthPtr] = pos;
3894 protected void pushOnAstStack(AstNode node) {
3896 * add a new obj on top of the ast stack
3899 astStack[++astPtr] = node;
3900 } catch (IndexOutOfBoundsException e) {
3901 int oldStackLength = astStack.length;
3902 AstNode[] oldStack = astStack;
3903 astStack = new AstNode[oldStackLength + AstStackIncrement];
3904 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3905 astPtr = oldStackLength;
3906 astStack[astPtr] = node;
3909 astLengthStack[++astLengthPtr] = 1;
3910 } catch (IndexOutOfBoundsException e) {
3911 int oldStackLength = astLengthStack.length;
3912 int[] oldPos = astLengthStack;
3913 astLengthStack = new int[oldStackLength + AstStackIncrement];
3914 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3915 astLengthStack[astLengthPtr] = 1;