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 || token > TokenNameKEYWORD) {
2942 if (token > TokenNameKEYWORD) {
2943 // TODO show a warning "Keyword used as variable" ?
2948 if (token != TokenNameLBRACE) {
2949 throwSyntaxError("'{' expected in variable name.");
2953 if (token != TokenNameRBRACE) {
2954 throwSyntaxError("'}' expected in variable name.");
2958 private void r_variable() {
2961 private void w_variable() {
2964 private void rw_variable() {
2967 private void variable() {
2969 // base_variable_with_function_calls T_OBJECT_OPERATOR
2970 // object_property method_or_not variable_properties
2971 // | base_variable_with_function_calls
2972 base_variable_with_function_calls();
2973 if (token == TokenNameMINUS_GREATER) {
2977 variable_properties();
2979 // if (token == TokenNameDOLLAR_LBRACE) {
2983 // if (token != TokenNameRBRACE) {
2984 // throwSyntaxError("'}' expected after indirect variable token '${'.");
2988 // if (token == TokenNameVariable) {
2990 // if (token == TokenNameLBRACKET) {
2993 // if (token != TokenNameRBRACKET) {
2994 // throwSyntaxError("']' expected in variable-list.");
2997 // } else if (token == TokenNameEQUAL) {
3002 // throwSyntaxError("$-variable expected in variable-list.");
3006 private void variable_properties() {
3007 // variable_properties:
3008 // variable_properties variable_property
3010 while (token == TokenNameMINUS_GREATER) {
3011 variable_property();
3014 private void variable_property() {
3015 // variable_property:
3016 // T_OBJECT_OPERATOR object_property method_or_not
3017 if (Scanner.TRACE) {
3018 System.out.println("TRACE: variable_property()");
3020 if (token == TokenNameMINUS_GREATER) {
3025 throwSyntaxError("'->' expected in variable_property.");
3028 private void method_or_not() {
3030 // '(' function_call_parameter_list ')'
3032 if (Scanner.TRACE) {
3033 System.out.println("TRACE: method_or_not()");
3035 if (token == TokenNameLPAREN) {
3037 if (token == TokenNameRPAREN) {
3041 non_empty_function_call_parameter_list();
3042 if (token != TokenNameRPAREN) {
3043 throwSyntaxError("')' expected in method_or_not.");
3048 private void exit_expr() {
3052 if (token != TokenNameLPAREN) {
3056 if (token == TokenNameRPAREN) {
3061 if (token != TokenNameRPAREN) {
3062 throwSyntaxError("')' expected after keyword 'exit'");
3066 private void internal_functions_in_yacc() {
3068 case TokenNameisset :
3069 // T_ISSET '(' isset_variables ')'
3071 if (token != TokenNameLPAREN) {
3072 throwSyntaxError("'(' expected after keyword 'isset'");
3076 if (token != TokenNameRPAREN) {
3077 throwSyntaxError("')' expected after keyword 'isset'");
3081 case TokenNameempty :
3082 // T_EMPTY '(' variable ')'
3084 if (token != TokenNameLPAREN) {
3085 throwSyntaxError("'(' expected after keyword 'empty'");
3089 if (token != TokenNameRPAREN) {
3090 throwSyntaxError("')' expected after keyword 'empty'");
3094 case TokenNameinclude :
3099 case TokenNameinclude_once :
3100 // T_INCLUDE_ONCE expr
3104 case TokenNameeval :
3105 // T_EVAL '(' expr ')'
3107 if (token != TokenNameLPAREN) {
3108 throwSyntaxError("'(' expected after keyword 'eval'");
3112 if (token != TokenNameRPAREN) {
3113 throwSyntaxError("')' expected after keyword 'eval'");
3117 case TokenNamerequire :
3122 case TokenNamerequire_once :
3123 // T_REQUIRE_ONCE expr
3129 private void isset_variables() {
3131 // | isset_variables ','
3132 if (token == TokenNameRPAREN) {
3133 throwSyntaxError("Variable expected after keyword 'isset'");
3137 if (token == TokenNameCOMMA) {
3144 private boolean common_scalar() {
3148 // | T_CONSTANT_ENCAPSED_STRING
3155 case TokenNameIntegerLiteral :
3158 case TokenNameDoubleLiteral :
3161 case TokenNameStringLiteral :
3164 case TokenNameStringConstant :
3167 case TokenNameStringInterpolated :
3170 case TokenNameFILE :
3173 case TokenNameLINE :
3176 case TokenNameCLASS_C :
3179 case TokenNameMETHOD_C :
3182 case TokenNameFUNC_C :
3188 private void scalar() {
3191 //| T_STRING_VARNAME
3194 //| '"' encaps_list '"'
3195 //| '\'' encaps_list '\''
3196 //| T_START_HEREDOC encaps_list T_END_HEREDOC
3197 throwSyntaxError("Not yet implemented (scalar).");
3199 private void static_scalar() {
3200 // static_scalar: /* compile-time evaluated scalars */
3203 // | '+' static_scalar
3204 // | '-' static_scalar
3205 // | T_ARRAY '(' static_array_pair_list ')'
3206 // | static_class_constant
3207 if (common_scalar()) {
3211 case TokenNameIdentifier :
3213 // static_class_constant:
3214 // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3215 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3217 if (token == TokenNameIdentifier) {
3220 throwSyntaxError("Identifier expected after '::' operator.");
3224 case TokenNamePLUS :
3228 case TokenNameMINUS :
3232 case TokenNamearray :
3234 if (token != TokenNameLPAREN) {
3235 throwSyntaxError("'(' expected after keyword 'array'");
3238 if (token == TokenNameRPAREN) {
3242 non_empty_static_array_pair_list();
3243 if (token != TokenNameRPAREN) {
3244 throwSyntaxError("')' expected after keyword 'array'");
3248 // case TokenNamenull :
3251 // case TokenNamefalse :
3254 // case TokenNametrue :
3258 throwSyntaxError("Static scalar/constant expected.");
3261 private void non_empty_static_array_pair_list() {
3262 // non_empty_static_array_pair_list:
3263 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3265 //| non_empty_static_array_pair_list ',' static_scalar
3266 //| static_scalar T_DOUBLE_ARROW static_scalar
3270 if (token == TokenNameEQUAL_GREATER) {
3274 if (token != TokenNameCOMMA) {
3278 if (token == TokenNameRPAREN) {
3283 public void reportSyntaxError() { //int act, int currentKind, int
3285 /* remember current scanner position */
3286 int startPos = scanner.startPosition;
3287 int currentPos = scanner.currentPosition;
3288 // String[] expectings;
3289 // String tokenName = name[symbol_index[currentKind]];
3290 //fetch all "accurate" possible terminals that could recover the error
3291 // int start, end = start = asi(stack[stateStackTop]);
3292 // while (asr[end] != 0)
3294 // int length = end - start;
3295 // expectings = new String[length];
3296 // if (length != 0) {
3297 // char[] indexes = new char[length];
3298 // System.arraycopy(asr, start, indexes, 0, length);
3299 // for (int i = 0; i < length; i++) {
3300 // expectings[i] = name[symbol_index[indexes[i]]];
3303 //if the pb is an EOF, try to tell the user that they are some
3304 // if (tokenName.equals(UNEXPECTED_EOF)) {
3305 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3306 // char[] tokenSource;
3308 // tokenSource = this.scanner.getCurrentTokenSource();
3309 // } catch (Exception e) {
3310 // tokenSource = new char[] {};
3312 // problemReporter().parseError(
3313 // this.scanner.startPosition,
3314 // this.scanner.currentPosition - 1,
3319 // } else { //the next test is HEAVILY grammar DEPENDENT.
3320 // if ((length == 14)
3321 // && (expectings[0] == "=") //$NON-NLS-1$
3322 // && (expectings[1] == "*=") //$NON-NLS-1$
3323 // && (expressionPtr > -1)) {
3324 // switch(currentKind) {
3325 // case TokenNameSEMICOLON:
3326 // case TokenNamePLUS:
3327 // case TokenNameMINUS:
3328 // case TokenNameDIVIDE:
3329 // case TokenNameREMAINDER:
3330 // case TokenNameMULTIPLY:
3331 // case TokenNameLEFT_SHIFT:
3332 // case TokenNameRIGHT_SHIFT:
3333 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3334 // case TokenNameLESS:
3335 // case TokenNameGREATER:
3336 // case TokenNameLESS_EQUAL:
3337 // case TokenNameGREATER_EQUAL:
3338 // case TokenNameEQUAL_EQUAL:
3339 // case TokenNameNOT_EQUAL:
3340 // case TokenNameXOR:
3341 // case TokenNameAND:
3342 // case TokenNameOR:
3343 // case TokenNameOR_OR:
3344 // case TokenNameAND_AND:
3345 // // the ; is not the expected token ==> it ends a statement when an
3346 // expression is not ended
3347 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3349 // case TokenNameRBRACE :
3350 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3353 // char[] tokenSource;
3355 // tokenSource = this.scanner.getCurrentTokenSource();
3356 // } catch (Exception e) {
3357 // tokenSource = new char[] {};
3359 // problemReporter().parseError(
3360 // this.scanner.startPosition,
3361 // this.scanner.currentPosition - 1,
3365 // this.checkAndReportBracketAnomalies(problemReporter());
3370 tokenSource = this.scanner.getCurrentTokenSource();
3371 } catch (Exception e) {
3372 tokenSource = new char[]{};
3374 // problemReporter().parseError(
3375 // this.scanner.startPosition,
3376 // this.scanner.currentPosition - 1,
3380 this.checkAndReportBracketAnomalies(problemReporter());
3383 /* reset scanner where it was */
3384 scanner.startPosition = startPos;
3385 scanner.currentPosition = currentPos;
3387 public static final int RoundBracket = 0;
3388 public static final int SquareBracket = 1;
3389 public static final int CurlyBracket = 2;
3390 public static final int BracketKinds = 3;
3391 protected int[] nestedMethod; //the ptr is nestedType
3392 protected int nestedType, dimensions;
3394 final static int AstStackIncrement = 100;
3395 protected int astPtr;
3396 protected AstNode[] astStack = new AstNode[AstStackIncrement];
3397 protected int astLengthPtr;
3398 protected int[] astLengthStack;
3399 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3400 public CompilationUnitDeclaration compilationUnit; /*
3401 * the result from parse()
3403 protected ReferenceContext referenceContext;
3404 protected ProblemReporter problemReporter;
3405 // protected CompilationResult compilationResult;
3407 * Returns this parser's problem reporter initialized with its reference
3408 * context. Also it is assumed that a problem is going to be reported, so
3409 * initializes the compilation result's line positions.
3411 public ProblemReporter problemReporter() {
3412 if (scanner.recordLineSeparator) {
3413 compilationUnit.compilationResult.lineSeparatorPositions = scanner
3416 problemReporter.referenceContext = referenceContext;
3417 return problemReporter;
3420 * Reconsider the entire source looking for inconsistencies in {} () []
3422 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3423 scanner.wasAcr = false;
3424 boolean anomaliesDetected = false;
3426 char[] source = scanner.source;
3427 int[] leftCount = {0, 0, 0};
3428 int[] rightCount = {0, 0, 0};
3429 int[] depths = {0, 0, 0};
3430 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3431 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3432 int[][] rightPositions = new int[][]{new int[10], new int[10],
3434 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3435 scanner.currentPosition = scanner.initialPosition; //starting
3437 // (first-zero-based
3439 while (scanner.currentPosition < scanner.eofPosition) { //loop for
3444 // ---------Consume white space and handles
3445 // startPosition---------
3446 boolean isWhiteSpace;
3448 scanner.startPosition = scanner.currentPosition;
3449 // if (((scanner.currentCharacter =
3450 // source[scanner.currentPosition++]) == '\\') &&
3451 // (source[scanner.currentPosition] == 'u')) {
3452 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3454 if (scanner.recordLineSeparator
3455 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3456 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3457 // only record line positions we have not
3459 scanner.pushLineSeparator();
3462 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3464 } while (isWhiteSpace
3465 && (scanner.currentPosition < scanner.eofPosition));
3466 // -------consume token until } is found---------
3467 switch (scanner.currentCharacter) {
3470 int index = leftCount[CurlyBracket]++;
3471 if (index == leftPositions[CurlyBracket].length) {
3472 System.arraycopy(leftPositions[CurlyBracket], 0,
3473 (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3476 .arraycopy(leftDepths[CurlyBracket], 0,
3477 (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3480 leftPositions[CurlyBracket][index] = scanner.startPosition;
3481 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3486 int index = rightCount[CurlyBracket]++;
3487 if (index == rightPositions[CurlyBracket].length) {
3488 System.arraycopy(rightPositions[CurlyBracket], 0,
3489 (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3491 System.arraycopy(rightDepths[CurlyBracket], 0,
3492 (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3495 rightPositions[CurlyBracket][index] = scanner.startPosition;
3496 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3501 int index = leftCount[RoundBracket]++;
3502 if (index == leftPositions[RoundBracket].length) {
3503 System.arraycopy(leftPositions[RoundBracket], 0,
3504 (leftPositions[RoundBracket] = new int[index * 2]), 0,
3507 .arraycopy(leftDepths[RoundBracket], 0,
3508 (leftDepths[RoundBracket] = new int[index * 2]), 0,
3511 leftPositions[RoundBracket][index] = scanner.startPosition;
3512 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3517 int index = rightCount[RoundBracket]++;
3518 if (index == rightPositions[RoundBracket].length) {
3519 System.arraycopy(rightPositions[RoundBracket], 0,
3520 (rightPositions[RoundBracket] = new int[index * 2]), 0,
3522 System.arraycopy(rightDepths[RoundBracket], 0,
3523 (rightDepths[RoundBracket] = new int[index * 2]), 0,
3526 rightPositions[RoundBracket][index] = scanner.startPosition;
3527 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3532 int index = leftCount[SquareBracket]++;
3533 if (index == leftPositions[SquareBracket].length) {
3534 System.arraycopy(leftPositions[SquareBracket], 0,
3535 (leftPositions[SquareBracket] = new int[index * 2]), 0,
3537 System.arraycopy(leftDepths[SquareBracket], 0,
3538 (leftDepths[SquareBracket] = new int[index * 2]), 0,
3541 leftPositions[SquareBracket][index] = scanner.startPosition;
3542 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3547 int index = rightCount[SquareBracket]++;
3548 if (index == rightPositions[SquareBracket].length) {
3549 System.arraycopy(rightPositions[SquareBracket], 0,
3550 (rightPositions[SquareBracket] = new int[index * 2]), 0,
3552 System.arraycopy(rightDepths[SquareBracket], 0,
3553 (rightDepths[SquareBracket] = new int[index * 2]), 0,
3556 rightPositions[SquareBracket][index] = scanner.startPosition;
3557 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3562 if (scanner.getNextChar('\\')) {
3563 scanner.scanEscapeCharacter();
3564 } else { // consume next character
3565 scanner.unicodeAsBackSlash = false;
3566 // if (((scanner.currentCharacter =
3567 // source[scanner.currentPosition++]) ==
3569 // (source[scanner.currentPosition] ==
3571 // scanner.getNextUnicodeChar();
3573 if (scanner.withoutUnicodePtr != 0) {
3574 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3578 scanner.getNextChar('\'');
3582 // consume next character
3583 scanner.unicodeAsBackSlash = false;
3584 // if (((scanner.currentCharacter =
3585 // source[scanner.currentPosition++]) == '\\') &&
3586 // (source[scanner.currentPosition] == 'u')) {
3587 // scanner.getNextUnicodeChar();
3589 if (scanner.withoutUnicodePtr != 0) {
3590 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3593 while (scanner.currentCharacter != '"') {
3594 if (scanner.currentCharacter == '\r') {
3595 if (source[scanner.currentPosition] == '\n')
3596 scanner.currentPosition++;
3597 break; // the string cannot go further that
3600 if (scanner.currentCharacter == '\n') {
3601 break; // the string cannot go further that
3604 if (scanner.currentCharacter == '\\') {
3605 scanner.scanEscapeCharacter();
3607 // consume next character
3608 scanner.unicodeAsBackSlash = false;
3609 // if (((scanner.currentCharacter =
3610 // source[scanner.currentPosition++]) == '\\')
3611 // && (source[scanner.currentPosition] == 'u'))
3613 // scanner.getNextUnicodeChar();
3615 if (scanner.withoutUnicodePtr != 0) {
3616 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3624 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3627 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3628 && (source[scanner.currentPosition] == 'u')) {
3629 //-------------unicode traitement
3631 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3632 scanner.currentPosition++;
3633 while (source[scanner.currentPosition] == 'u') {
3634 scanner.currentPosition++;
3637 .getNumericValue(source[scanner.currentPosition++])) > 15
3640 .getNumericValue(source[scanner.currentPosition++])) > 15
3643 .getNumericValue(source[scanner.currentPosition++])) > 15
3646 .getNumericValue(source[scanner.currentPosition++])) > 15
3647 || c4 < 0) { //error don't
3650 scanner.currentCharacter = 'A';
3651 } //something different from \n and \r
3653 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3656 while (scanner.currentCharacter != '\r'
3657 && scanner.currentCharacter != '\n') {
3659 scanner.startPosition = scanner.currentPosition;
3660 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3661 && (source[scanner.currentPosition] == 'u')) {
3662 //-------------unicode traitement
3664 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3665 scanner.currentPosition++;
3666 while (source[scanner.currentPosition] == 'u') {
3667 scanner.currentPosition++;
3670 .getNumericValue(source[scanner.currentPosition++])) > 15
3673 .getNumericValue(source[scanner.currentPosition++])) > 15
3676 .getNumericValue(source[scanner.currentPosition++])) > 15
3679 .getNumericValue(source[scanner.currentPosition++])) > 15
3680 || c4 < 0) { //error don't
3683 scanner.currentCharacter = 'A';
3684 } //something different from \n
3687 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3691 if (scanner.recordLineSeparator
3692 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3693 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3694 // only record line positions we
3695 // have not recorded yet
3696 scanner.pushLineSeparator();
3697 if (this.scanner.taskTags != null) {
3698 this.scanner.checkTaskTag(this.scanner
3699 .getCurrentTokenStartPosition(), this.scanner
3700 .getCurrentTokenEndPosition());
3706 if (test > 0) { //traditional and annotation
3708 boolean star = false;
3709 // consume next character
3710 scanner.unicodeAsBackSlash = false;
3711 // if (((scanner.currentCharacter =
3712 // source[scanner.currentPosition++]) ==
3714 // (source[scanner.currentPosition] ==
3716 // scanner.getNextUnicodeChar();
3718 if (scanner.withoutUnicodePtr != 0) {
3719 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3722 if (scanner.currentCharacter == '*') {
3726 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3727 && (source[scanner.currentPosition] == 'u')) {
3728 //-------------unicode traitement
3730 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3731 scanner.currentPosition++;
3732 while (source[scanner.currentPosition] == 'u') {
3733 scanner.currentPosition++;
3736 .getNumericValue(source[scanner.currentPosition++])) > 15
3739 .getNumericValue(source[scanner.currentPosition++])) > 15
3742 .getNumericValue(source[scanner.currentPosition++])) > 15
3745 .getNumericValue(source[scanner.currentPosition++])) > 15
3746 || c4 < 0) { //error don't
3749 scanner.currentCharacter = 'A';
3750 } //something different from * and /
3752 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3755 //loop until end of comment */
3756 while ((scanner.currentCharacter != '/') || (!star)) {
3757 star = scanner.currentCharacter == '*';
3759 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3760 && (source[scanner.currentPosition] == 'u')) {
3761 //-------------unicode traitement
3763 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3764 scanner.currentPosition++;
3765 while (source[scanner.currentPosition] == 'u') {
3766 scanner.currentPosition++;
3769 .getNumericValue(source[scanner.currentPosition++])) > 15
3772 .getNumericValue(source[scanner.currentPosition++])) > 15
3775 .getNumericValue(source[scanner.currentPosition++])) > 15
3778 .getNumericValue(source[scanner.currentPosition++])) > 15
3779 || c4 < 0) { //error don't
3782 scanner.currentCharacter = 'A';
3783 } //something different from * and
3786 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3790 if (this.scanner.taskTags != null) {
3791 this.scanner.checkTaskTag(this.scanner
3792 .getCurrentTokenStartPosition(), this.scanner
3793 .getCurrentTokenEndPosition());
3800 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3801 scanner.scanIdentifierOrKeyword(false);
3804 if (Character.isDigit(scanner.currentCharacter)) {
3805 scanner.scanNumber(false);
3809 //-----------------end switch while
3810 // try--------------------
3811 } catch (IndexOutOfBoundsException e) {
3812 break; // read until EOF
3813 } catch (InvalidInputException e) {
3814 return false; // no clue
3817 if (scanner.recordLineSeparator) {
3818 // compilationUnit.compilationResult.lineSeparatorPositions =
3819 // scanner.getLineEnds();
3821 // check placement anomalies against other kinds of brackets
3822 for (int kind = 0; kind < BracketKinds; kind++) {
3823 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3824 int start = leftPositions[kind][leftIndex]; // deepest
3826 // find matching closing bracket
3827 int depth = leftDepths[kind][leftIndex];
3829 for (int i = 0; i < rightCount[kind]; i++) {
3830 int pos = rightPositions[kind][i];
3831 // want matching bracket further in source with same
3833 if ((pos > start) && (depth == rightDepths[kind][i])) {
3838 if (end < 0) { // did not find a good closing match
3839 problemReporter.unmatchedBracket(start, referenceContext,
3840 compilationUnit.compilationResult);
3843 // check if even number of opening/closing other brackets
3844 // in between this pair of brackets
3846 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3847 for (int i = 0; i < leftCount[otherKind]; i++) {
3848 int pos = leftPositions[otherKind][i];
3849 if ((pos > start) && (pos < end))
3852 for (int i = 0; i < rightCount[otherKind]; i++) {
3853 int pos = rightPositions[otherKind][i];
3854 if ((pos > start) && (pos < end))
3858 problemReporter.unmatchedBracket(start, referenceContext,
3859 compilationUnit.compilationResult); //bracket
3865 // too many opening brackets ?
3866 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3867 anomaliesDetected = true;
3868 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3869 - i - 1], referenceContext, compilationUnit.compilationResult);
3871 // too many closing brackets ?
3872 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3873 anomaliesDetected = true;
3874 problemReporter.unmatchedBracket(rightPositions[kind][i],
3875 referenceContext, compilationUnit.compilationResult);
3877 if (anomaliesDetected)
3880 return anomaliesDetected;
3881 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3882 return anomaliesDetected;
3883 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3884 return anomaliesDetected;
3887 protected void pushOnAstLengthStack(int pos) {
3889 astLengthStack[++astLengthPtr] = pos;
3890 } catch (IndexOutOfBoundsException e) {
3891 int oldStackLength = astLengthStack.length;
3892 int[] oldPos = astLengthStack;
3893 astLengthStack = new int[oldStackLength + StackIncrement];
3894 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3895 astLengthStack[astLengthPtr] = pos;
3898 protected void pushOnAstStack(AstNode node) {
3900 * add a new obj on top of the ast stack
3903 astStack[++astPtr] = node;
3904 } catch (IndexOutOfBoundsException e) {
3905 int oldStackLength = astStack.length;
3906 AstNode[] oldStack = astStack;
3907 astStack = new AstNode[oldStackLength + AstStackIncrement];
3908 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3909 astPtr = oldStackLength;
3910 astStack[astPtr] = node;
3913 astLengthStack[++astLengthPtr] = 1;
3914 } catch (IndexOutOfBoundsException e) {
3915 int oldStackLength = astLengthStack.length;
3916 int[] oldPos = astLengthStack;
3917 astLengthStack = new int[oldStackLength + AstStackIncrement];
3918 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3919 astLengthStack[astLengthPtr] = 1;