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;
26 import net.sourceforge.phpeclipse.phpeditor.PHPString;
27 import org.eclipse.core.resources.IFile;
28 public class Parser //extends PHPParserSuperclass
29 implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
30 //internal data for the automat
31 protected final static int StackIncrement = 255;
32 protected int stateStackTop;
33 protected int[] stack = new int[StackIncrement];
34 public int firstToken; // handle for multiple parsing goals
35 public int lastAct; //handle for multiple parsing goals
36 protected RecoveredElement currentElement;
37 public static boolean VERBOSE_RECOVERY = false;
38 protected boolean diet = false; //tells the scanner to jump over some
39 // parts of the code/expressions like
42 public Scanner scanner;
43 private ArrayList phpList;
44 private int currentPHPString;
45 private boolean phpEnd;
46 // private static HashMap keywordMap = null;
52 // row counter for syntax errors:
54 // column counter for syntax errors:
58 // // current identifier
62 private String stringValue;
63 /** Contains the current expression. */
64 // private StringBuffer expression;
65 //private boolean phpMode;
66 protected int modifiers;
67 protected int modifiersSourceStart;
69 this.currentPHPString = 0;
70 // PHPParserSuperclass.fileToParse = fileToParse;
73 this.token = TokenNameEOF;
76 // this.columnCount = 0;
79 this.initializeScanner();
81 public void setFileToParse(IFile fileToParse) {
82 this.currentPHPString = 0;
83 // PHPParserSuperclass.fileToParse = fileToParse;
86 this.token = TokenNameEOF;
88 this.initializeScanner();
91 * ClassDeclaration Constructor.
95 * Description of Parameter
98 public Parser(IFile fileToParse) {
99 // if (keywordMap == null) {
100 // keywordMap = new HashMap();
101 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
102 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
105 this.currentPHPString = 0;
106 // PHPParserSuperclass.fileToParse = fileToParse;
109 this.token = TokenNameEOF;
111 // this.rowCount = 1;
112 // this.columnCount = 0;
115 this.initializeScanner();
117 public void initializeScanner() {
118 this.scanner = new Scanner(false, false, false, false);
121 * Create marker for the parse error
123 // private void setMarker(String message, int charStart, int charEnd, int
125 // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
128 * This method will throw the SyntaxError. It will add the good lines and
129 * columns to the Error
133 * @throws SyntaxError
136 private void throwSyntaxError(String error) {
137 int problemStartPosition = scanner.getCurrentTokenStartPosition();
138 int problemEndPosition = scanner.getCurrentTokenEndPosition();
139 throwSyntaxError(error, problemStartPosition, problemEndPosition);
142 * This method will throw the SyntaxError. It will add the good lines and
143 * columns to the Error
147 * @throws SyntaxError
150 // private void throwSyntaxError(String error, int startRow) {
151 // throw new SyntaxError(startRow, 0, " ", error);
153 private void throwSyntaxError(String error, int problemStartPosition,
154 int problemEndPosition) {
156 .phpParsingError(new String[]{error}, problemStartPosition,
157 problemEndPosition, referenceContext,
158 compilationUnit.compilationResult);
159 throw new SyntaxError(1, 0, " ", error);
161 private void reportSyntaxError(String error, int problemStartPosition,
162 int problemEndPosition) {
164 .phpParsingError(new String[]{error}, problemStartPosition,
165 problemEndPosition, referenceContext,
166 compilationUnit.compilationResult);
168 private void reportSyntaxWarning(String error, int problemStartPosition,
169 int problemEndPosition) {
170 problemReporter.phpParsingWarning(new String[]{error},
171 problemStartPosition, problemEndPosition, referenceContext,
172 compilationUnit.compilationResult);
175 * Method Declaration.
179 // private void getChar() {
180 // if (str.length() > chIndx) {
181 // ch = str.charAt(chIndx++);
186 // chIndx = str.length() + 1;
188 // // token = TokenNameEOF;
192 * gets the next token from input
194 private void getNextToken() {
196 token = scanner.getNextToken();
198 int currentEndPosition = scanner.getCurrentTokenEndPosition();
199 int currentStartPosition = scanner.getCurrentTokenStartPosition();
201 .print(currentStartPosition + "," + currentEndPosition + ": ");
202 System.out.println(scanner.toStringAction(token));
204 } catch (InvalidInputException e) {
205 token = TokenNameERROR;
210 * Get a number. if it's a <code>double</code> the number will be stored in
211 * <code>doubleNumber</code> and the token will have the value
212 * {@link Parser#TokenNameDOUBLE_NUMBER}<br />
213 * if it's a <code>double</code> the number will be stored in <code>longNumber</code>
214 * and the token will have the value {@link Parser#TokenNameINT_NUMBER}
216 // private void getNumber() {
217 // StringBuffer inum = new StringBuffer();
219 // int numFormat = 10;
221 // // save first digit
222 // char firstCh = ch;
226 // // determine number conversions:
227 // if (firstCh == '0') {
256 // if (numFormat == 16) {
257 // while ((ch >= '0' && ch <= '9')
258 // || (ch >= 'a' && ch <= 'f')
259 // || (ch >= 'A' && ch <= 'F')) {
264 // while ((ch >= '0' && ch <= '9')
268 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
269 // if (ch == '.' && dFlag != ' ') {
272 // if ((dFlag == 'E') || (dFlag == 'e')) {
278 // if ((ch == '-') || (ch == '+')) {
291 // if (dFlag != ' ') {
292 // doubleNumber = new Double(inum.toString());
293 // token = TokenNameDoubleLiteral;
296 // longNumber = Long.valueOf(inum.toString(), numFormat);
297 // token = TokenNameIntegerLiteral;
301 // } catch (Throwable e) {
302 // throwSyntaxError("Number format error: " + inum.toString());
308 // * @param openChar the opening char ('\'', '"', '`')
309 // * @param typeString the type of string {@link
310 // #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
311 // * @param errorMsg the error message in case of parse error in the string
313 // private void getString(
314 // final char openChar,
315 // final int typeString,
316 // final String errorMsg) {
317 // StringBuffer sBuffer = new StringBuffer();
318 // boolean openString = true;
319 // int startRow = rowCount;
320 // while (str.length() > chIndx) {
321 // ch = str.charAt(chIndx++);
323 // sBuffer.append(ch);
324 // if (str.length() > chIndx) {
325 // ch = str.charAt(chIndx++);
326 // sBuffer.append(ch);
328 // } else if (ch == openChar) {
329 // openString = false;
331 // } else if (ch == '\n') {
333 // columnCount = chIndx;
335 // sBuffer.append(ch);
339 // if (typeString == TokenNameStringConstant) {
340 // throwSyntaxError(errorMsg, startRow);
342 // throwSyntaxError(errorMsg);
345 // token = typeString;
346 // stringValue = sBuffer.toString();
348 // public void htmlParserTester(String input) {
349 // int lineNumber = 1;
350 // int startLineNumber = 1;
351 // int startIndex = 0;
354 // boolean phpMode = false;
355 // boolean phpFound = false;
357 // phpList = new ArrayList();
358 // currentPHPString = 0;
362 // while (i < input.length()) {
363 // ch = input.charAt(i++);
367 // if ((!phpMode) && ch == '<') {
368 // ch2 = input.charAt(i++);
370 // ch2 = input.charAt(i++);
371 // if (Character.isWhitespace(ch2)) {
376 // startLineNumber = lineNumber;
378 // } else if (ch2 == 'p') {
379 // ch2 = input.charAt(i++);
381 // ch2 = input.charAt(i++);
386 // startLineNumber = lineNumber;
392 // } else if (ch2 == 'P') {
393 // ch2 = input.charAt(i++);
395 // ch2 = input.charAt(i++);
400 // startLineNumber = lineNumber;
413 // if (ch == '/' && i < input.length()) {
414 // ch2 = input.charAt(i++);
416 // while (i < input.length()) {
417 // ch = input.charAt(i++);
418 // if (ch == '?' && i < input.length()) {
419 // ch2 = input.charAt(i++);
428 // startLineNumber));
432 // } else if (ch == '\n') {
438 // } else if (ch2 == '*') {
439 // // multi-line comment
440 // while (i < input.length()) {
441 // ch = input.charAt(i++);
444 // } else if (ch == '*' && i < input.length()) {
445 // ch2 = input.charAt(i++);
456 // } else if (ch == '#') {
457 // while (i < input.length()) {
458 // ch = input.charAt(i++);
459 // if (ch == '?' && i < input.length()) {
460 // ch2 = input.charAt(i++);
466 // input.substring(startIndex, i - 2),
467 // startLineNumber));
471 // } else if (ch == '\n') {
477 // } else if (ch == '"') {
479 // while (i < input.length()) {
480 // ch = input.charAt(i++);
484 // ch == '\\' && i < input.length()) { // escape
486 // } else if (ch == '"') {
491 // } else if (ch == '\'') {
493 // while (i < input.length()) {
494 // ch = input.charAt(i++);
498 // ch == '\\' && i < input.length()) { // escape
500 // } else if (ch == '\'') {
507 // if (ch == '?' && i < input.length()) {
508 // ch2 = input.charAt(i++);
514 // input.substring(startIndex, i - 2),
515 // startLineNumber));
525 // "No PHP source code found.",
531 // "Open PHP tag at end of file.",
536 // input.substring(startIndex, i - 2),
537 // startLineNumber));
539 // // for (int j=0;j<phpList.size();j++) {
540 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
541 // // int startIndx = temp.length()-10;
542 // // if (startIndx<0) {
545 // // System.out.println(temp.substring(startIndx)+"?>");
547 // phpParserTester(null, 1);
548 // // PHPString temp;
549 // // for(int j=0;j<phpList.size();j++) {
550 // // temp = (PHPString) phpList.get(j);
551 // // parser.start(temp.getPHPString(), temp.getLineNumber());
554 // } catch (CoreException e) {
557 // public void phpParserTester(String s, int rowCount) {
560 // if (phpList.size() != 0) {
561 // this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
564 // this.token = TokenNameEOF;
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 != TokenNameStopPHP) {
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 != TokenNameStopPHP) {
1155 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1160 } else if (token == TokenNameecho) {
1163 if (token == TokenNameSEMICOLON) {
1166 if (token != TokenNameStopPHP) {
1167 throwSyntaxError("';' expected after 'echo' statement.");
1172 // } else if (token == TokenNameprint) {
1175 // if (token == TokenNameSEMICOLON) {
1178 // if (token != TokenNameStopPHP) {
1179 // throwSyntaxError("';' expected after 'print' statement.");
1184 } else if (token == TokenNameglobal) {
1187 if (token == TokenNameSEMICOLON) {
1190 if (token != TokenNameStopPHP) {
1191 throwSyntaxError("';' expected after 'global' statement.");
1196 } else if (token == TokenNamestatic) {
1199 if (token == TokenNameSEMICOLON) {
1202 if (token != TokenNameStopPHP) {
1203 throwSyntaxError("';' expected after 'static' statement.");
1208 }else if (token == TokenNameunset) {
1210 if (token == TokenNameLPAREN) {
1213 throwSyntaxError("'(' expected after 'unset' statement.");
1216 if (token == TokenNameRPAREN) {
1219 throwSyntaxError("')' expected after 'unset' statement.");
1221 if (token == TokenNameSEMICOLON) {
1224 if (token != TokenNameStopPHP) {
1225 throwSyntaxError("';' expected after 'unset' statement.");
1230 // } else if (token == TokenNameexit || token == TokenNamedie) {
1232 // if (token != TokenNameSEMICOLON) {
1235 // if (token == TokenNameSEMICOLON) {
1238 // if (token != TokenNameStopPHP) {
1239 // throwSyntaxError("';' expected after 'exit' or 'die'
1245 // } else if (token == TokenNamedefine) {
1247 // if (token == TokenNameLPAREN) {
1250 // throwSyntaxError("'(' expected after 'define' keyword.");
1253 // if (token == TokenNameCOMMA) {
1256 // throwSyntaxError("',' expected after first 'define' constant.");
1259 // if (token == TokenNameCOMMA) {
1263 // if (token == TokenNameRPAREN) {
1266 // throwSyntaxError("')' expected after 'define' statement.");
1268 // if (token == TokenNameSEMICOLON) {
1271 // if (token != TokenNameStopPHP) {
1272 // throwSyntaxError("';' expected after 'define' statement.");
1277 } else if (token == TokenNamefunction) {
1278 MethodDeclaration methodDecl = new MethodDeclaration(
1279 this.compilationUnit.compilationResult);
1280 methodDecl.declarationSourceStart = scanner
1281 .getCurrentTokenStartPosition();
1283 functionDefinition(methodDecl);
1285 } else if (token == TokenNamefinal || token == TokenNameabstract
1286 || token == TokenNameclass || token == TokenNameinterface) {
1287 TypeDeclaration typeDecl = new TypeDeclaration(
1288 this.compilationUnit.compilationResult);
1289 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1290 // default super class
1291 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1292 compilationUnit.types.add(typeDecl);
1294 pushOnAstStack(typeDecl);
1295 unticked_class_declaration_statement(typeDecl);
1296 // classBody(typeDecl);
1303 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1304 } else if (token == TokenNameLBRACE) {
1306 if (token != TokenNameRBRACE) {
1309 if (token == TokenNameRBRACE) {
1313 throwSyntaxError("'}' expected.");
1316 if (token != TokenNameSEMICOLON) {
1319 if (token == TokenNameSEMICOLON) {
1323 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1324 throwSyntaxError("';' expected after expression (Found token: "
1325 + scanner.toStringAction(token) + ")");
1331 private void global_var_list() {
1333 // global_var_list ',' global_var
1337 if (token != TokenNameCOMMA) {
1343 private void global_var() {
1347 //| '$' '{' expr '}'
1348 if (token == TokenNameVariable) {
1350 } else if (token == TokenNameDOLLAR) {
1352 if (token == TokenNameLPAREN) {
1355 if (token != TokenNameLPAREN) {
1356 throwSyntaxError("')' expected in global variable.");
1364 private void static_var_list() {
1366 // static_var_list ',' T_VARIABLE
1367 //| static_var_list ',' T_VARIABLE '=' static_scalar
1369 //| T_VARIABLE '=' static_scalar
1371 if (token == TokenNameVariable) {
1373 if (token == TokenNameEQUAL) {
1377 if (token != TokenNameCOMMA) {
1386 private void unset_variables() {
1389 // | unset_variables ',' unset_variable
1394 if (token != TokenNameCOMMA) {
1400 private final void initializeModifiers() {
1402 this.modifiersSourceStart = -1;
1404 private final void checkAndSetModifiers(int flag) {
1405 this.modifiers |= flag;
1406 if (this.modifiersSourceStart < 0)
1407 this.modifiersSourceStart = this.scanner.startPosition;
1409 private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1410 initializeModifiers();
1411 if (token == TokenNameinterface) {
1412 // interface_entry T_STRING
1413 // interface_extends_list
1414 // '{' class_statement_list '}'
1415 checkAndSetModifiers(AccInterface);
1417 typeDecl.modifiers = this.modifiers;
1418 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1419 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1420 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1421 typeDecl.name = scanner.getCurrentIdentifierSource();
1422 if (token > TokenNameKEYWORD) {
1423 throwSyntaxError("Don't use a keyword for interface declaration ["
1424 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1425 typeDecl.sourceEnd);
1428 interface_extends_list();
1430 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1431 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1432 typeDecl.name = new char[]{' '};
1433 throwSyntaxError("Interface name expected after keyword 'interface'.",
1434 typeDecl.sourceStart, typeDecl.sourceEnd);
1438 // class_entry_type T_STRING extends_from
1440 // '{' class_statement_list'}'
1442 typeDecl.modifiers = this.modifiers;
1444 //identifier 'extends' identifier
1445 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1446 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1447 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1448 typeDecl.name = scanner.getCurrentIdentifierSource();
1449 if (token > TokenNameKEYWORD) {
1450 throwSyntaxError("Don't use a keyword for class declaration ["
1451 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1452 typeDecl.sourceEnd);
1457 // | T_EXTENDS fully_qualified_class_name
1458 if (token == TokenNameextends) {
1460 if (token == TokenNameIdentifier) {
1463 throwSyntaxError("Class name expected after keyword 'extends'.",
1464 scanner.getCurrentTokenStartPosition(), scanner
1465 .getCurrentTokenEndPosition());
1470 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1471 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1472 typeDecl.name = new char[]{' '};
1473 throwSyntaxError("Class name expected after keyword 'class'.",
1474 typeDecl.sourceStart, typeDecl.sourceEnd);
1478 // '{' class_statement_list '}'
1479 if (token == TokenNameLBRACE) {
1481 if (token != TokenNameRBRACE) {
1482 class_statement_list();
1484 if (token == TokenNameRBRACE) {
1485 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1488 throwSyntaxError("'}' expected at end of class body.");
1491 throwSyntaxError("'{' expected at start of class body.");
1494 private void class_entry_type() {
1496 // | T_ABSTRACT T_CLASS
1497 // | T_FINAL T_CLASS
1498 if (token == TokenNameclass) {
1500 } else if (token == TokenNameabstract) {
1501 checkAndSetModifiers(AccAbstract);
1503 if (token != TokenNameclass) {
1504 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1507 } else if (token == TokenNamefinal) {
1508 checkAndSetModifiers(AccFinal);
1510 if (token != TokenNameclass) {
1511 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1515 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1518 private void interface_extends_list() {
1520 // | T_EXTENDS interface_list
1521 if (token == TokenNameextends) {
1526 private void implements_list() {
1528 // | T_IMPLEMENTS interface_list
1529 if (token == TokenNameimplements) {
1534 private void interface_list() {
1536 // fully_qualified_class_name
1537 //| interface_list ',' fully_qualified_class_name
1539 if (token == TokenNameIdentifier) {
1542 throwSyntaxError("Interface name expected after keyword 'implements'.");
1544 if (token != TokenNameCOMMA) {
1550 // private void classBody(TypeDeclaration typeDecl) {
1551 // //'{' [class-element-list] '}'
1552 // if (token == TokenNameLBRACE) {
1554 // if (token != TokenNameRBRACE) {
1555 // class_statement_list();
1557 // if (token == TokenNameRBRACE) {
1558 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1561 // throwSyntaxError("'}' expected at end of class body.");
1564 // throwSyntaxError("'{' expected at start of class body.");
1567 private void class_statement_list() {
1570 } while (token == TokenNamepublic || token == TokenNameprotected
1571 || token == TokenNameprivate || token == TokenNamestatic
1572 || token == TokenNameabstract || token == TokenNamefinal
1573 || token == TokenNamefunction || token == TokenNamevar);
1575 private void class_statement() {
1577 // variable_modifiers class_variable_declaration ';'
1578 // | class_constant_declaration ';'
1579 // | method_modifiers T_FUNCTION is_reference T_STRING
1580 // '(' parameter_list ')' method_body
1581 initializeModifiers();
1582 if (token == TokenNamevar) {
1583 checkAndSetModifiers(AccPublic);
1584 problemReporter.phpVarDeprecatedWarning(scanner
1585 .getCurrentTokenStartPosition(),
1586 scanner.getCurrentTokenEndPosition(), referenceContext,
1587 compilationUnit.compilationResult);
1589 class_variable_declaration();
1591 boolean hasModifiers = member_modifiers();
1592 if (token == TokenNamefunction) {
1593 if (!hasModifiers) {
1594 checkAndSetModifiers(AccPublic);
1596 MethodDeclaration methodDecl = new MethodDeclaration(
1597 this.compilationUnit.compilationResult);
1598 methodDecl.declarationSourceStart = scanner
1599 .getCurrentTokenStartPosition();
1600 methodDecl.modifiers = this.modifiers;
1602 functionDefinition(methodDecl);
1604 if (!hasModifiers) {
1605 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1607 class_variable_declaration();
1610 // if (token == TokenNamefunction) {
1611 // MethodDeclaration methodDecl = new MethodDeclaration(
1612 // this.compilationUnit.compilationResult);
1613 // methodDecl.declarationSourceStart = scanner
1614 // .getCurrentTokenStartPosition();
1616 // functionDefinition(methodDecl);
1617 // } else if (token == TokenNamevar) {
1621 // throwSyntaxError("'function' or 'var' expected.");
1624 // private void variable_modifiers() {
1625 // // variable_modifiers:
1626 // // non_empty_member_modifiers
1628 // initializeModifiers();
1629 // if (token == TokenNamevar) {
1630 // checkAndSetModifiers(AccPublic);
1631 // reportSyntaxError(
1632 // "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
1633 // modifier for field declarations.",
1634 // scanner.getCurrentTokenStartPosition(), scanner
1635 // .getCurrentTokenEndPosition());
1638 // if (!member_modifiers()) {
1639 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1640 // field declarations.");
1644 // private void method_modifiers() {
1645 // //method_modifiers:
1647 // //| non_empty_member_modifiers
1648 // initializeModifiers();
1649 // if (!member_modifiers()) {
1650 // checkAndSetModifiers(AccPublic);
1653 private boolean member_modifiers() {
1660 boolean foundToken = false;
1662 if (token == TokenNamepublic) {
1663 checkAndSetModifiers(AccPublic);
1666 } else if (token == TokenNameprotected) {
1667 checkAndSetModifiers(AccProtected);
1670 } else if (token == TokenNameprivate) {
1671 checkAndSetModifiers(AccPrivate);
1674 } else if (token == TokenNamestatic) {
1675 checkAndSetModifiers(AccStatic);
1678 } else if (token == TokenNameabstract) {
1679 checkAndSetModifiers(AccAbstract);
1682 } else if (token == TokenNamefinal) {
1683 checkAndSetModifiers(AccFinal);
1692 private void class_variable_declaration() {
1693 // class_variable_declaration:
1694 // class_variable_declaration ',' T_VARIABLE
1695 // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1697 // | T_VARIABLE '=' static_scalar
1699 if (token == TokenNameVariable) {
1701 if (token == TokenNameEQUAL) {
1706 // if (token == TokenNamethis) {
1707 // throwSyntaxError("'$this' not allowed after keyword 'public'
1708 // 'protected' 'private' 'var'.");
1710 throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1712 if (token != TokenNameCOMMA) {
1717 if (token != TokenNameSEMICOLON) {
1718 throwSyntaxError("';' expected after field declaration.");
1722 private void functionDefinition(MethodDeclaration methodDecl) {
1724 compilationUnit.types.add(methodDecl);
1726 AstNode node = astStack[astPtr];
1727 if (node instanceof TypeDeclaration) {
1728 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1729 if (typeDecl.methods == null) {
1730 typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1732 AbstractMethodDeclaration[] newMethods;
1737 newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1738 1, typeDecl.methods.length);
1739 newMethods[0] = methodDecl;
1740 typeDecl.methods = newMethods;
1744 functionDeclarator(methodDecl);
1745 functionBody(methodDecl);
1747 private void functionDeclarator(MethodDeclaration methodDecl) {
1748 //identifier '(' [parameter-list] ')'
1749 if (token == TokenNameAND) {
1752 if (token == TokenNameIdentifier) {
1753 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1754 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1755 methodDecl.selector = scanner.getCurrentIdentifierSource();
1757 if (token == TokenNameLPAREN) {
1760 throwSyntaxError("'(' expected in function declaration.");
1762 if (token != TokenNameRPAREN) {
1765 if (token != TokenNameRPAREN) {
1766 throwSyntaxError("')' expected in function declaration.");
1768 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1772 if (token > TokenNameKEYWORD) {
1773 throwSyntaxError("Don't use keyword for function declaration [" + token
1776 throwSyntaxError("Function name expected after keyword 'function'.");
1780 private void parameterList() {
1781 //parameter-declaration
1782 //parameter-list ',' parameter-declaration
1784 parameterDeclaration();
1785 if (token != TokenNameCOMMA) {
1791 private void parameterDeclaration() {
1793 //variable-reference
1794 if (token == TokenNameAND) {
1799 throwSyntaxError("Variable expected after reference operator '&'.");
1802 //variable '=' constant
1803 if (token == TokenNameVariable) {
1805 if (token == TokenNameEQUAL) {
1811 // if (token == TokenNamethis) {
1812 // throwSyntaxError("Reserved word '$this' not allowed in parameter
1816 private void labeledStatementList() {
1817 if (token != TokenNamecase && token != TokenNamedefault) {
1818 throwSyntaxError("'case' or 'default' expected.");
1821 if (token == TokenNamecase) {
1823 expr(); //constant();
1824 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1826 if (token == TokenNamecase || token == TokenNamedefault) { // empty
1834 // else if (token == TokenNameSEMICOLON) {
1836 // "':' expected after 'case' keyword (Found token: " +
1837 // scanner.toStringAction(token) + ")",
1838 // scanner.getCurrentTokenStartPosition(),
1839 // scanner.getCurrentTokenEndPosition(),
1842 // if (token == TokenNamecase) { // empty case statement ?
1848 throwSyntaxError("':' character after 'case' constant expected (Found token: "
1849 + scanner.toStringAction(token) + ")");
1851 } else { // TokenNamedefault
1853 if (token == TokenNameCOLON) {
1857 throwSyntaxError("':' character after 'default' expected.");
1860 } while (token == TokenNamecase || token == TokenNamedefault);
1862 // public void labeledStatement() {
1863 // if (token == TokenNamecase) {
1866 // if (token == TokenNameDDOT) {
1870 // throwSyntaxError("':' character after 'case' constant expected.");
1873 // } else if (token == TokenNamedefault) {
1875 // if (token == TokenNameDDOT) {
1879 // throwSyntaxError("':' character after 'default' expected.");
1884 // public void expressionStatement() {
1886 // private void inclusionStatement() {
1888 // public void compoundStatement() {
1890 // public void selectionStatement() {
1893 // public void iterationStatement() {
1896 // public void jumpStatement() {
1899 // public void outputStatement() {
1902 // public void scopeStatement() {
1905 // public void flowStatement() {
1908 // public void definitionStatement() {
1910 private void ifStatement() {
1911 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1912 if (token == TokenNameCOLON) {
1914 if (token != TokenNameendif) {
1917 case TokenNameelse :
1919 if (token == TokenNameCOLON) {
1921 if (token != TokenNameendif) {
1925 if (token == TokenNameif) { //'else if'
1927 elseifStatementList();
1929 throwSyntaxError("':' expected after 'else'.");
1933 case TokenNameelseif :
1935 elseifStatementList();
1939 if (token != TokenNameendif) {
1940 throwSyntaxError("'endif' expected.");
1943 if (token != TokenNameSEMICOLON) {
1944 throwSyntaxError("';' expected after if-statement.");
1948 // statement [else-statement]
1949 statement(TokenNameEOF);
1950 if (token == TokenNameelseif) {
1952 if (token == TokenNameLPAREN) {
1955 throwSyntaxError("'(' expected after 'elseif' keyword.");
1958 if (token == TokenNameRPAREN) {
1961 throwSyntaxError("')' expected after 'elseif' condition.");
1964 } else if (token == TokenNameelse) {
1966 statement(TokenNameEOF);
1970 private void elseifStatementList() {
1974 case TokenNameelse :
1976 if (token == TokenNameCOLON) {
1978 if (token != TokenNameendif) {
1983 if (token == TokenNameif) { //'else if'
1986 throwSyntaxError("':' expected after 'else'.");
1990 case TokenNameelseif :
1998 private void elseifStatement() {
1999 if (token == TokenNameLPAREN) {
2002 if (token != TokenNameRPAREN) {
2003 throwSyntaxError("')' expected in else-if-statement.");
2006 if (token != TokenNameCOLON) {
2007 throwSyntaxError("':' expected in else-if-statement.");
2010 if (token != TokenNameendif) {
2015 private void switchStatement() {
2016 if (token == TokenNameCOLON) {
2017 // ':' [labeled-statement-list] 'endswitch' ';'
2019 labeledStatementList();
2020 if (token != TokenNameendswitch) {
2021 throwSyntaxError("'endswitch' expected.");
2024 if (token != TokenNameSEMICOLON) {
2025 throwSyntaxError("';' expected after switch-statement.");
2029 // '{' [labeled-statement-list] '}'
2030 if (token != TokenNameLBRACE) {
2031 throwSyntaxError("'{' expected in switch statement.");
2034 if (token != TokenNameRBRACE) {
2035 labeledStatementList();
2037 if (token != TokenNameRBRACE) {
2038 throwSyntaxError("'}' expected in switch statement.");
2043 private void forStatement() {
2044 if (token == TokenNameCOLON) {
2047 if (token != TokenNameendfor) {
2048 throwSyntaxError("'endfor' expected.");
2051 if (token != TokenNameSEMICOLON) {
2052 throwSyntaxError("';' expected after for-statement.");
2056 statement(TokenNameEOF);
2059 private void whileStatement() {
2060 // ':' statement-list 'endwhile' ';'
2061 if (token == TokenNameCOLON) {
2064 if (token != TokenNameendwhile) {
2065 throwSyntaxError("'endwhile' expected.");
2068 if (token != TokenNameSEMICOLON) {
2069 throwSyntaxError("';' expected after while-statement.");
2073 statement(TokenNameEOF);
2076 private void foreachStatement() {
2077 if (token == TokenNameCOLON) {
2080 if (token != TokenNameendforeach) {
2081 throwSyntaxError("'endforeach' expected.");
2084 if (token != TokenNameSEMICOLON) {
2085 throwSyntaxError("';' expected after foreach-statement.");
2089 statement(TokenNameEOF);
2092 // private void exitStatus() {
2093 // if (token == TokenNameLPAREN) {
2096 // throwSyntaxError("'(' expected in 'exit-status'.");
2098 // if (token != TokenNameRPAREN) {
2101 // if (token == TokenNameRPAREN) {
2104 // throwSyntaxError("')' expected after 'exit-status'.");
2107 private void expressionList() {
2110 if (token == TokenNameCOMMA) {
2117 private void expr() {
2119 // | expr_without_variable
2120 // if (token!=TokenNameEOF) {
2121 if (Scanner.TRACE) {
2122 System.out.println("TRACE: expr()");
2124 expr_without_variable(true);
2127 private void expr_without_variable(boolean only_variable) {
2128 // internal_functions_in_yacc
2137 // | T_INC rw_variable
2138 // | T_DEC rw_variable
2139 // | T_INT_CAST expr
2140 // | T_DOUBLE_CAST expr
2141 // | T_STRING_CAST expr
2142 // | T_ARRAY_CAST expr
2143 // | T_OBJECT_CAST expr
2144 // | T_BOOL_CAST expr
2145 // | T_UNSET_CAST expr
2146 // | T_EXIT exit_expr
2148 // | T_ARRAY '(' array_pair_list ')'
2149 // | '`' encaps_list '`'
2150 // | T_LIST '(' assignment_list ')' '=' expr
2151 // | T_NEW class_name_reference ctor_arguments
2152 // | variable '=' expr
2153 // | variable '=' '&' variable
2154 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2155 // | variable T_PLUS_EQUAL expr
2156 // | variable T_MINUS_EQUAL expr
2157 // | variable T_MUL_EQUAL expr
2158 // | variable T_DIV_EQUAL expr
2159 // | variable T_CONCAT_EQUAL expr
2160 // | variable T_MOD_EQUAL expr
2161 // | variable T_AND_EQUAL expr
2162 // | variable T_OR_EQUAL expr
2163 // | variable T_XOR_EQUAL expr
2164 // | variable T_SL_EQUAL expr
2165 // | variable T_SR_EQUAL expr
2166 // | rw_variable T_INC
2167 // | rw_variable T_DEC
2168 // | expr T_BOOLEAN_OR expr
2169 // | expr T_BOOLEAN_AND expr
2170 // | expr T_LOGICAL_OR expr
2171 // | expr T_LOGICAL_AND expr
2172 // | expr T_LOGICAL_XOR expr
2184 // | expr T_IS_IDENTICAL expr
2185 // | expr T_IS_NOT_IDENTICAL expr
2186 // | expr T_IS_EQUAL expr
2187 // | expr T_IS_NOT_EQUAL expr
2189 // | expr T_IS_SMALLER_OR_EQUAL expr
2191 // | expr T_IS_GREATER_OR_EQUAL expr
2192 // | expr T_INSTANCEOF class_name_reference
2193 // | expr '?' expr ':' expr
2194 if (Scanner.TRACE) {
2195 System.out.println("TRACE: expr_without_variable() PART 1");
2198 case TokenNameisset :
2199 case TokenNameempty :
2200 case TokenNameeval :
2201 case TokenNameinclude :
2202 case TokenNameinclude_once :
2203 case TokenNamerequire :
2204 case TokenNamerequire_once :
2205 internal_functions_in_yacc();
2208 case TokenNameLPAREN :
2211 if (token == TokenNameRPAREN) {
2214 throwSyntaxError("')' expected in expression.");
2224 // | T_INT_CAST expr
2225 // | T_DOUBLE_CAST expr
2226 // | T_STRING_CAST expr
2227 // | T_ARRAY_CAST expr
2228 // | T_OBJECT_CAST expr
2229 // | T_BOOL_CAST expr
2230 // | T_UNSET_CAST expr
2231 case TokenNameclone :
2232 case TokenNameprint :
2234 case TokenNamePLUS :
2235 case TokenNameMINUS :
2237 case TokenNameTWIDDLE :
2238 case TokenNameintCAST :
2239 case TokenNamedoubleCAST :
2240 case TokenNamestringCAST :
2241 case TokenNamearrayCAST :
2242 case TokenNameobjectCAST :
2243 case TokenNameboolCAST :
2244 case TokenNameunsetCAST :
2248 case TokenNameexit :
2254 //| T_STRING_VARNAME
2256 //| '"' encaps_list '"'
2257 //| '\'' encaps_list '\''
2258 //| T_START_HEREDOC encaps_list T_END_HEREDOC
2259 // | '`' encaps_list '`'
2261 case TokenNameIntegerLiteral :
2262 case TokenNameDoubleLiteral :
2263 case TokenNameStringLiteral :
2264 case TokenNameStringConstant :
2265 case TokenNameStringInterpolated :
2266 case TokenNameFILE :
2267 case TokenNameLINE :
2268 case TokenNameCLASS_C :
2269 case TokenNameMETHOD_C :
2270 case TokenNameFUNC_C :
2273 case TokenNameHEREDOC :
2276 case TokenNamearray :
2277 // T_ARRAY '(' array_pair_list ')'
2279 if (token == TokenNameLPAREN) {
2281 if (token == TokenNameRPAREN) {
2286 if (token != TokenNameRPAREN) {
2287 throwSyntaxError("')' expected after keyword 'array'"
2288 + "(Found token: " + scanner.toStringAction(token) + ")");
2292 throwSyntaxError("'(' expected after keyword 'array'"
2293 + "(Found token: " + scanner.toStringAction(token) + ")");
2296 case TokenNamelist :
2297 // | T_LIST '(' assignment_list ')' '=' expr
2299 if (token == TokenNameLPAREN) {
2302 if (token != TokenNameRPAREN) {
2303 throwSyntaxError("')' expected after 'list' keyword.");
2306 if (token != TokenNameEQUAL) {
2307 throwSyntaxError("'=' expected after 'list' keyword.");
2312 throwSyntaxError("'(' expected after 'list' keyword.");
2316 // | T_NEW class_name_reference ctor_arguments
2318 class_name_reference();
2321 // | T_INC rw_variable
2322 // | T_DEC rw_variable
2323 case TokenNamePLUS_PLUS :
2324 case TokenNameMINUS_MINUS :
2328 // | variable '=' expr
2329 // | variable '=' '&' variable
2330 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2331 // | variable T_PLUS_EQUAL expr
2332 // | variable T_MINUS_EQUAL expr
2333 // | variable T_MUL_EQUAL expr
2334 // | variable T_DIV_EQUAL expr
2335 // | variable T_CONCAT_EQUAL expr
2336 // | variable T_MOD_EQUAL expr
2337 // | variable T_AND_EQUAL expr
2338 // | variable T_OR_EQUAL expr
2339 // | variable T_XOR_EQUAL expr
2340 // | variable T_SL_EQUAL expr
2341 // | variable T_SR_EQUAL expr
2342 // | rw_variable T_INC
2343 // | rw_variable T_DEC
2344 case TokenNameIdentifier :
2345 case TokenNameVariable :
2346 case TokenNameDOLLAR :
2349 case TokenNameEQUAL :
2351 if (token == TokenNameAND) {
2353 if (token == TokenNamenew) {
2355 throwSyntaxError("not yet implemented (= & new)");
2356 // class_name_reference();
2357 // ctor_arguments();
2365 case TokenNamePLUS_EQUAL :
2366 case TokenNameMINUS_EQUAL :
2367 case TokenNameMULTIPLY_EQUAL :
2368 case TokenNameDIVIDE_EQUAL :
2369 case TokenNameDOT_EQUAL :
2370 case TokenNameREMAINDER_EQUAL :
2371 case TokenNameAND_EQUAL :
2372 case TokenNameOR_EQUAL :
2373 case TokenNameXOR_EQUAL :
2374 case TokenNameRIGHT_SHIFT_EQUAL :
2375 case TokenNameLEFT_SHIFT_EQUAL :
2379 case TokenNamePLUS_PLUS :
2380 case TokenNameMINUS_MINUS :
2384 if (!only_variable) {
2385 throwSyntaxError("Variable expression not allowed (found token '"
2386 + scanner.toStringAction(token) + "').");
2391 if (token != TokenNameStopPHP) {
2392 throwSyntaxError("Error in expression (found token '"
2393 + scanner.toStringAction(token) + "').");
2397 if (Scanner.TRACE) {
2398 System.out.println("TRACE: expr_without_variable() PART 2");
2400 // | expr T_BOOLEAN_OR expr
2401 // | expr T_BOOLEAN_AND expr
2402 // | expr T_LOGICAL_OR expr
2403 // | expr T_LOGICAL_AND expr
2404 // | expr T_LOGICAL_XOR expr
2416 // | expr T_IS_IDENTICAL expr
2417 // | expr T_IS_NOT_IDENTICAL expr
2418 // | expr T_IS_EQUAL expr
2419 // | expr T_IS_NOT_EQUAL expr
2421 // | expr T_IS_SMALLER_OR_EQUAL expr
2423 // | expr T_IS_GREATER_OR_EQUAL expr
2426 case TokenNameOR_OR :
2427 case TokenNameAND_AND :
2435 case TokenNamePLUS :
2436 case TokenNameMINUS :
2437 case TokenNameMULTIPLY :
2438 case TokenNameDIVIDE :
2439 case TokenNameREMAINDER :
2440 case TokenNameLEFT_SHIFT :
2441 case TokenNameRIGHT_SHIFT :
2442 case TokenNameEQUAL_EQUAL_EQUAL :
2443 case TokenNameNOT_EQUAL_EQUAL :
2444 case TokenNameEQUAL_EQUAL :
2445 case TokenNameNOT_EQUAL :
2446 case TokenNameLESS :
2447 case TokenNameLESS_EQUAL :
2448 case TokenNameGREATER :
2449 case TokenNameGREATER_EQUAL :
2453 // | expr T_INSTANCEOF class_name_reference
2454 // | expr '?' expr ':' expr
2455 case TokenNameinstanceof :
2457 throwSyntaxError("not yet implemented (class_name_reference)");
2458 // class_name_reference();
2460 case TokenNameQUESTION :
2463 if (token == TokenNameCOLON) {
2473 private void class_name_reference() {
2474 // class_name_reference:
2476 //| dynamic_class_name_reference
2477 if (Scanner.TRACE) {
2478 System.out.println("TRACE: class_name_reference()");
2480 if (token == TokenNameIdentifier) {
2483 dynamic_class_name_reference();
2486 private void dynamic_class_name_reference() {
2487 //dynamic_class_name_reference:
2488 // base_variable T_OBJECT_OPERATOR object_property
2489 // dynamic_class_name_variable_properties
2491 if (Scanner.TRACE) {
2492 System.out.println("TRACE: dynamic_class_name_reference()");
2495 if (token == TokenNameMINUS_GREATER) {
2498 dynamic_class_name_variable_properties();
2501 private void dynamic_class_name_variable_properties() {
2502 // dynamic_class_name_variable_properties:
2503 // dynamic_class_name_variable_properties
2504 // dynamic_class_name_variable_property
2506 if (Scanner.TRACE) {
2507 System.out.println("TRACE: dynamic_class_name_variable_properties()");
2509 while (token == TokenNameMINUS_GREATER) {
2510 dynamic_class_name_variable_property();
2513 private void dynamic_class_name_variable_property() {
2514 // dynamic_class_name_variable_property:
2515 // T_OBJECT_OPERATOR object_property
2516 if (Scanner.TRACE) {
2517 System.out.println("TRACE: dynamic_class_name_variable_property()");
2519 if (token == TokenNameMINUS_GREATER) {
2524 private void ctor_arguments() {
2527 //| '(' function_call_parameter_list ')'
2528 if (token == TokenNameLPAREN) {
2530 if (token == TokenNameRPAREN) {
2534 non_empty_function_call_parameter_list();
2535 if (token != TokenNameRPAREN) {
2536 throwSyntaxError("')' expected in ctor_arguments.");
2541 private void assignment_list() {
2543 // assignment_list ',' assignment_list_element
2544 //| assignment_list_element
2546 assignment_list_element();
2547 if (token != TokenNameCOMMA) {
2553 private void assignment_list_element() {
2554 //assignment_list_element:
2556 //| T_LIST '(' assignment_list ')'
2558 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2561 if (token == TokenNamelist) {
2563 if (token == TokenNameLPAREN) {
2566 if (token != TokenNameRPAREN) {
2567 throwSyntaxError("')' expected after 'list' keyword.");
2571 throwSyntaxError("'(' expected after 'list' keyword.");
2576 private void array_pair_list() {
2579 //| non_empty_array_pair_list possible_comma
2580 non_empty_array_pair_list();
2581 if (token == TokenNameCOMMA) {
2585 private void non_empty_array_pair_list() {
2586 //non_empty_array_pair_list:
2587 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2588 //| non_empty_array_pair_list ',' expr
2589 //| expr T_DOUBLE_ARROW expr
2591 //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2592 //| non_empty_array_pair_list ',' '&' w_variable
2593 //| expr T_DOUBLE_ARROW '&' w_variable
2597 if (token == TokenNameAND) {
2601 } else if (token == TokenNameEQUAL_GREATER) {
2603 if (token == TokenNameAND) {
2610 if (token != TokenNameCOMMA) {
2614 if (token == TokenNameRPAREN) {
2619 // private void variableList() {
2622 // if (token == TokenNameCOMMA) {
2629 private void variable_without_objects() {
2630 // variable_without_objects:
2631 // reference_variable
2632 // | simple_indirect_reference reference_variable
2633 if (Scanner.TRACE) {
2634 System.out.println("TRACE: variable_without_objects()");
2636 while (token == TokenNameDOLLAR) {
2639 reference_variable();
2641 private void function_call() {
2643 // T_STRING '(' function_call_parameter_list ')'
2644 //| class_constant '(' function_call_parameter_list ')'
2645 //| static_member '(' function_call_parameter_list ')'
2646 //| variable_without_objects '(' function_call_parameter_list ')'
2647 if (Scanner.TRACE) {
2648 System.out.println("TRACE: function_call()");
2650 if (token == TokenNameIdentifier) {
2653 case TokenNamePAAMAYIM_NEKUDOTAYIM :
2656 if (token == TokenNameIdentifier) {
2661 variable_without_objects();
2666 variable_without_objects();
2668 if (token != TokenNameLPAREN) {
2669 // TODO is this ok ?
2671 // throwSyntaxError("'(' expected in function call.");
2674 if (token == TokenNameRPAREN) {
2678 non_empty_function_call_parameter_list();
2679 if (token != TokenNameRPAREN) {
2680 throwSyntaxError("')' expected in function call.");
2684 // private void function_call_parameter_list() {
2685 // function_call_parameter_list:
2686 // non_empty_function_call_parameter_list { $$ = $1; }
2689 private void non_empty_function_call_parameter_list() {
2690 //non_empty_function_call_parameter_list:
2691 // expr_without_variable
2694 // | non_empty_function_call_parameter_list ',' expr_without_variable
2695 // | non_empty_function_call_parameter_list ',' variable
2696 // | non_empty_function_call_parameter_list ',' '&' w_variable
2697 if (Scanner.TRACE) {
2698 System.out.println("TRACE: non_empty_function_call_parameter_list()");
2701 if (token == TokenNameAND) {
2705 // if (token == TokenNameIdentifier || token == TokenNameVariable
2706 // || token == TokenNameDOLLAR) {
2709 expr_without_variable(true);
2712 if (token != TokenNameCOMMA) {
2718 private void fully_qualified_class_name() {
2719 if (token == TokenNameIdentifier) {
2722 throwSyntaxError("Class name expected.");
2725 private void static_member() {
2727 // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2728 // variable_without_objects
2729 if (Scanner.TRACE) {
2730 System.out.println("TRACE: static_member()");
2732 fully_qualified_class_name();
2733 if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2734 throwSyntaxError("'::' expected after class name (static_member).");
2737 variable_without_objects();
2739 private void base_variable_with_function_calls() {
2740 // base_variable_with_function_calls:
2743 boolean functionCall = false;
2744 if (Scanner.TRACE) {
2745 System.out.println("TRACE: base_variable_with_function_calls()");
2747 if (token == TokenNameIdentifier) {
2748 functionCall = true;
2749 } else if (token == TokenNameVariable) {
2750 int tempToken = token;
2751 int tempPosition = scanner.currentPosition;
2753 if (token == TokenNameLPAREN) {
2754 functionCall = true;
2757 scanner.currentPosition = tempPosition;
2758 scanner.phpMode = true;
2766 private void base_variable() {
2768 // reference_variable
2769 // | simple_indirect_reference reference_variable
2771 if (Scanner.TRACE) {
2772 System.out.println("TRACE: base_variable()");
2774 if (token == TokenNameIdentifier) {
2777 while (token == TokenNameDOLLAR) {
2780 reference_variable();
2783 // private void simple_indirect_reference() {
2784 // // simple_indirect_reference:
2786 // //| simple_indirect_reference '$'
2788 private void reference_variable() {
2789 // reference_variable:
2790 // reference_variable '[' dim_offset ']'
2791 // | reference_variable '{' expr '}'
2792 // | compound_variable
2793 if (Scanner.TRACE) {
2794 System.out.println("TRACE: reference_variable()");
2796 compound_variable();
2798 if (token == TokenNameLBRACE) {
2801 if (token != TokenNameRBRACE) {
2802 throwSyntaxError("'}' expected in reference variable.");
2805 } else if (token == TokenNameLBRACKET) {
2807 if (token != TokenNameRBRACKET) {
2810 if (token != TokenNameRBRACKET) {
2811 throwSyntaxError("']' expected in reference variable.");
2820 private void compound_variable() {
2821 // compound_variable:
2823 // | '$' '{' expr '}'
2824 if (Scanner.TRACE) {
2825 System.out.println("TRACE: compound_variable()");
2827 if (token == TokenNameVariable) {
2830 // because of simple_indirect_reference
2831 while (token == TokenNameDOLLAR) {
2834 if (token != TokenNameLBRACE) {
2835 throwSyntaxError("'{' expected after compound variable token '$'.");
2839 if (token != TokenNameRBRACE) {
2840 throwSyntaxError("'}' expected after compound variable token '$'.");
2845 // private void dim_offset() {
2851 private void object_property() {
2854 //| variable_without_objects
2855 if (Scanner.TRACE) {
2856 System.out.println("TRACE: object_property()");
2858 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2859 variable_without_objects();
2864 private void object_dim_list() {
2866 // object_dim_list '[' dim_offset ']'
2867 //| object_dim_list '{' expr '}'
2869 if (Scanner.TRACE) {
2870 System.out.println("TRACE: object_dim_list()");
2874 if (token == TokenNameLBRACE) {
2877 if (token != TokenNameRBRACE) {
2878 throwSyntaxError("'}' expected in object_dim_list.");
2881 } else if (token == TokenNameLBRACKET) {
2883 if (token == TokenNameRBRACKET) {
2888 if (token != TokenNameRBRACKET) {
2889 throwSyntaxError("']' expected in object_dim_list.");
2897 private void variable_name() {
2901 if (Scanner.TRACE) {
2902 System.out.println("TRACE: variable_name()");
2904 if (token == TokenNameIdentifier) {
2907 if (token != TokenNameLBRACE) {
2908 throwSyntaxError("'{' expected in variable name.");
2912 if (token != TokenNameRBRACE) {
2913 throwSyntaxError("'}' expected in variable name.");
2917 private void r_variable() {
2920 private void w_variable() {
2923 private void rw_variable() {
2926 private void variable() {
2928 // base_variable_with_function_calls T_OBJECT_OPERATOR
2929 // object_property method_or_not variable_properties
2930 // | base_variable_with_function_calls
2931 base_variable_with_function_calls();
2932 if (token == TokenNameMINUS_GREATER) {
2936 variable_properties();
2938 // if (token == TokenNameDOLLAR_LBRACE) {
2942 // if (token != TokenNameRBRACE) {
2943 // throwSyntaxError("'}' expected after indirect variable token '${'.");
2947 // if (token == TokenNameVariable) {
2949 // if (token == TokenNameLBRACKET) {
2952 // if (token != TokenNameRBRACKET) {
2953 // throwSyntaxError("']' expected in variable-list.");
2956 // } else if (token == TokenNameEQUAL) {
2961 // throwSyntaxError("$-variable expected in variable-list.");
2965 private void variable_properties() {
2966 // variable_properties:
2967 // variable_properties variable_property
2969 while (token == TokenNameMINUS_GREATER) {
2970 variable_property();
2973 private void variable_property() {
2974 // variable_property:
2975 // T_OBJECT_OPERATOR object_property method_or_not
2976 if (Scanner.TRACE) {
2977 System.out.println("TRACE: variable_property()");
2979 if (token == TokenNameMINUS_GREATER) {
2984 throwSyntaxError("'->' expected in variable_property.");
2987 private void method_or_not() {
2989 // '(' function_call_parameter_list ')'
2991 if (Scanner.TRACE) {
2992 System.out.println("TRACE: method_or_not()");
2994 if (token == TokenNameLPAREN) {
2996 if (token == TokenNameRPAREN) {
3000 non_empty_function_call_parameter_list();
3001 if (token != TokenNameRPAREN) {
3002 throwSyntaxError("')' expected in method_or_not.");
3007 private void exit_expr() {
3011 if (token != TokenNameLPAREN) {
3015 if (token == TokenNameRPAREN) {
3020 if (token != TokenNameRPAREN) {
3021 throwSyntaxError("')' expected after keyword 'exit'");
3025 private void internal_functions_in_yacc() {
3027 case TokenNameisset :
3028 // T_ISSET '(' isset_variables ')'
3030 if (token != TokenNameLPAREN) {
3031 throwSyntaxError("'(' expected after keyword 'isset'");
3035 if (token != TokenNameRPAREN) {
3036 throwSyntaxError("')' expected after keyword 'isset'");
3040 case TokenNameempty :
3041 // T_EMPTY '(' variable ')'
3043 if (token != TokenNameLPAREN) {
3044 throwSyntaxError("'(' expected after keyword 'empty'");
3048 if (token != TokenNameRPAREN) {
3049 throwSyntaxError("')' expected after keyword 'empty'");
3053 case TokenNameinclude :
3058 case TokenNameinclude_once :
3059 // T_INCLUDE_ONCE expr
3063 case TokenNameeval :
3064 // T_EVAL '(' expr ')'
3066 if (token != TokenNameLPAREN) {
3067 throwSyntaxError("'(' expected after keyword 'eval'");
3071 if (token != TokenNameRPAREN) {
3072 throwSyntaxError("')' expected after keyword 'eval'");
3076 case TokenNamerequire :
3081 case TokenNamerequire_once :
3082 // T_REQUIRE_ONCE expr
3088 private void isset_variables() {
3090 // | isset_variables ','
3091 if (token == TokenNameRPAREN) {
3092 throwSyntaxError("Variable expected after keyword 'isset'");
3096 if (token == TokenNameCOMMA) {
3103 private boolean common_scalar() {
3107 // | T_CONSTANT_ENCAPSED_STRING
3114 case TokenNameIntegerLiteral :
3117 case TokenNameDoubleLiteral :
3120 case TokenNameStringLiteral :
3123 case TokenNameStringConstant :
3126 case TokenNameStringInterpolated :
3129 case TokenNameFILE :
3132 case TokenNameLINE :
3135 case TokenNameCLASS_C :
3138 case TokenNameMETHOD_C :
3141 case TokenNameFUNC_C :
3147 private void scalar() {
3150 //| T_STRING_VARNAME
3153 //| '"' encaps_list '"'
3154 //| '\'' encaps_list '\''
3155 //| T_START_HEREDOC encaps_list T_END_HEREDOC
3156 throwSyntaxError("Not yet implemented (scalar).");
3158 private void static_scalar() {
3159 // static_scalar: /* compile-time evaluated scalars */
3162 // | '+' static_scalar
3163 // | '-' static_scalar
3164 // | T_ARRAY '(' static_array_pair_list ')'
3165 // | static_class_constant
3166 if (common_scalar()) {
3170 case TokenNameIdentifier :
3172 // static_class_constant:
3173 // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3174 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3176 if (token == TokenNameIdentifier) {
3179 throwSyntaxError("Identifier expected after '::' operator.");
3183 case TokenNamePLUS :
3187 case TokenNameMINUS :
3191 case TokenNamearray :
3193 if (token != TokenNameLPAREN) {
3194 throwSyntaxError("'(' expected after keyword 'array'");
3197 if (token == TokenNameRPAREN) {
3201 non_empty_static_array_pair_list();
3202 if (token != TokenNameRPAREN) {
3203 throwSyntaxError("')' expected after keyword 'array'");
3207 // case TokenNamenull :
3210 // case TokenNamefalse :
3213 // case TokenNametrue :
3217 throwSyntaxError("Static scalar/constant expected.");
3220 private void non_empty_static_array_pair_list() {
3221 // non_empty_static_array_pair_list:
3222 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3224 //| non_empty_static_array_pair_list ',' static_scalar
3225 //| static_scalar T_DOUBLE_ARROW static_scalar
3229 if (token == TokenNameEQUAL_GREATER) {
3233 if (token != TokenNameCOMMA) {
3237 if (token != TokenNameRPAREN) {
3242 public void reportSyntaxError() { //int act, int currentKind, int
3244 /* remember current scanner position */
3245 int startPos = scanner.startPosition;
3246 int currentPos = scanner.currentPosition;
3247 // String[] expectings;
3248 // String tokenName = name[symbol_index[currentKind]];
3249 //fetch all "accurate" possible terminals that could recover the error
3250 // int start, end = start = asi(stack[stateStackTop]);
3251 // while (asr[end] != 0)
3253 // int length = end - start;
3254 // expectings = new String[length];
3255 // if (length != 0) {
3256 // char[] indexes = new char[length];
3257 // System.arraycopy(asr, start, indexes, 0, length);
3258 // for (int i = 0; i < length; i++) {
3259 // expectings[i] = name[symbol_index[indexes[i]]];
3262 //if the pb is an EOF, try to tell the user that they are some
3263 // if (tokenName.equals(UNEXPECTED_EOF)) {
3264 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3265 // char[] tokenSource;
3267 // tokenSource = this.scanner.getCurrentTokenSource();
3268 // } catch (Exception e) {
3269 // tokenSource = new char[] {};
3271 // problemReporter().parseError(
3272 // this.scanner.startPosition,
3273 // this.scanner.currentPosition - 1,
3278 // } else { //the next test is HEAVILY grammar DEPENDENT.
3279 // if ((length == 14)
3280 // && (expectings[0] == "=") //$NON-NLS-1$
3281 // && (expectings[1] == "*=") //$NON-NLS-1$
3282 // && (expressionPtr > -1)) {
3283 // switch(currentKind) {
3284 // case TokenNameSEMICOLON:
3285 // case TokenNamePLUS:
3286 // case TokenNameMINUS:
3287 // case TokenNameDIVIDE:
3288 // case TokenNameREMAINDER:
3289 // case TokenNameMULTIPLY:
3290 // case TokenNameLEFT_SHIFT:
3291 // case TokenNameRIGHT_SHIFT:
3292 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3293 // case TokenNameLESS:
3294 // case TokenNameGREATER:
3295 // case TokenNameLESS_EQUAL:
3296 // case TokenNameGREATER_EQUAL:
3297 // case TokenNameEQUAL_EQUAL:
3298 // case TokenNameNOT_EQUAL:
3299 // case TokenNameXOR:
3300 // case TokenNameAND:
3301 // case TokenNameOR:
3302 // case TokenNameOR_OR:
3303 // case TokenNameAND_AND:
3304 // // the ; is not the expected token ==> it ends a statement when an
3305 // expression is not ended
3306 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3308 // case TokenNameRBRACE :
3309 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3312 // char[] tokenSource;
3314 // tokenSource = this.scanner.getCurrentTokenSource();
3315 // } catch (Exception e) {
3316 // tokenSource = new char[] {};
3318 // problemReporter().parseError(
3319 // this.scanner.startPosition,
3320 // this.scanner.currentPosition - 1,
3324 // this.checkAndReportBracketAnomalies(problemReporter());
3329 tokenSource = this.scanner.getCurrentTokenSource();
3330 } catch (Exception e) {
3331 tokenSource = new char[]{};
3333 // problemReporter().parseError(
3334 // this.scanner.startPosition,
3335 // this.scanner.currentPosition - 1,
3339 this.checkAndReportBracketAnomalies(problemReporter());
3342 /* reset scanner where it was */
3343 scanner.startPosition = startPos;
3344 scanner.currentPosition = currentPos;
3346 public static final int RoundBracket = 0;
3347 public static final int SquareBracket = 1;
3348 public static final int CurlyBracket = 2;
3349 public static final int BracketKinds = 3;
3350 protected int[] nestedMethod; //the ptr is nestedType
3351 protected int nestedType, dimensions;
3353 final static int AstStackIncrement = 100;
3354 protected int astPtr;
3355 protected AstNode[] astStack = new AstNode[AstStackIncrement];
3356 protected int astLengthPtr;
3357 protected int[] astLengthStack;
3358 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3359 public CompilationUnitDeclaration compilationUnit; /*
3360 * the result from parse()
3362 protected ReferenceContext referenceContext;
3363 protected ProblemReporter problemReporter;
3364 // protected CompilationResult compilationResult;
3366 * Returns this parser's problem reporter initialized with its reference
3367 * context. Also it is assumed that a problem is going to be reported, so
3368 * initializes the compilation result's line positions.
3370 public ProblemReporter problemReporter() {
3371 if (scanner.recordLineSeparator) {
3372 compilationUnit.compilationResult.lineSeparatorPositions = scanner
3375 problemReporter.referenceContext = referenceContext;
3376 return problemReporter;
3379 * Reconsider the entire source looking for inconsistencies in {} () []
3381 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3382 scanner.wasAcr = false;
3383 boolean anomaliesDetected = false;
3385 char[] source = scanner.source;
3386 int[] leftCount = {0, 0, 0};
3387 int[] rightCount = {0, 0, 0};
3388 int[] depths = {0, 0, 0};
3389 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3390 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3391 int[][] rightPositions = new int[][]{new int[10], new int[10],
3393 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3394 scanner.currentPosition = scanner.initialPosition; //starting
3396 // (first-zero-based
3398 while (scanner.currentPosition < scanner.eofPosition) { //loop for
3403 // ---------Consume white space and handles
3404 // startPosition---------
3405 boolean isWhiteSpace;
3407 scanner.startPosition = scanner.currentPosition;
3408 // if (((scanner.currentCharacter =
3409 // source[scanner.currentPosition++]) == '\\') &&
3410 // (source[scanner.currentPosition] == 'u')) {
3411 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3413 if (scanner.recordLineSeparator
3414 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3415 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3416 // only record line positions we have not
3418 scanner.pushLineSeparator();
3421 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3423 } while (isWhiteSpace
3424 && (scanner.currentPosition < scanner.eofPosition));
3425 // -------consume token until } is found---------
3426 switch (scanner.currentCharacter) {
3429 int index = leftCount[CurlyBracket]++;
3430 if (index == leftPositions[CurlyBracket].length) {
3431 System.arraycopy(leftPositions[CurlyBracket], 0,
3432 (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3435 .arraycopy(leftDepths[CurlyBracket], 0,
3436 (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3439 leftPositions[CurlyBracket][index] = scanner.startPosition;
3440 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3445 int index = rightCount[CurlyBracket]++;
3446 if (index == rightPositions[CurlyBracket].length) {
3447 System.arraycopy(rightPositions[CurlyBracket], 0,
3448 (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3450 System.arraycopy(rightDepths[CurlyBracket], 0,
3451 (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3454 rightPositions[CurlyBracket][index] = scanner.startPosition;
3455 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3460 int index = leftCount[RoundBracket]++;
3461 if (index == leftPositions[RoundBracket].length) {
3462 System.arraycopy(leftPositions[RoundBracket], 0,
3463 (leftPositions[RoundBracket] = new int[index * 2]), 0,
3466 .arraycopy(leftDepths[RoundBracket], 0,
3467 (leftDepths[RoundBracket] = new int[index * 2]), 0,
3470 leftPositions[RoundBracket][index] = scanner.startPosition;
3471 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3476 int index = rightCount[RoundBracket]++;
3477 if (index == rightPositions[RoundBracket].length) {
3478 System.arraycopy(rightPositions[RoundBracket], 0,
3479 (rightPositions[RoundBracket] = new int[index * 2]), 0,
3481 System.arraycopy(rightDepths[RoundBracket], 0,
3482 (rightDepths[RoundBracket] = new int[index * 2]), 0,
3485 rightPositions[RoundBracket][index] = scanner.startPosition;
3486 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3491 int index = leftCount[SquareBracket]++;
3492 if (index == leftPositions[SquareBracket].length) {
3493 System.arraycopy(leftPositions[SquareBracket], 0,
3494 (leftPositions[SquareBracket] = new int[index * 2]), 0,
3496 System.arraycopy(leftDepths[SquareBracket], 0,
3497 (leftDepths[SquareBracket] = new int[index * 2]), 0,
3500 leftPositions[SquareBracket][index] = scanner.startPosition;
3501 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3506 int index = rightCount[SquareBracket]++;
3507 if (index == rightPositions[SquareBracket].length) {
3508 System.arraycopy(rightPositions[SquareBracket], 0,
3509 (rightPositions[SquareBracket] = new int[index * 2]), 0,
3511 System.arraycopy(rightDepths[SquareBracket], 0,
3512 (rightDepths[SquareBracket] = new int[index * 2]), 0,
3515 rightPositions[SquareBracket][index] = scanner.startPosition;
3516 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3521 if (scanner.getNextChar('\\')) {
3522 scanner.scanEscapeCharacter();
3523 } else { // consume next character
3524 scanner.unicodeAsBackSlash = false;
3525 // if (((scanner.currentCharacter =
3526 // source[scanner.currentPosition++]) ==
3528 // (source[scanner.currentPosition] ==
3530 // scanner.getNextUnicodeChar();
3532 if (scanner.withoutUnicodePtr != 0) {
3533 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3537 scanner.getNextChar('\'');
3541 // consume next character
3542 scanner.unicodeAsBackSlash = false;
3543 // if (((scanner.currentCharacter =
3544 // source[scanner.currentPosition++]) == '\\') &&
3545 // (source[scanner.currentPosition] == 'u')) {
3546 // scanner.getNextUnicodeChar();
3548 if (scanner.withoutUnicodePtr != 0) {
3549 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3552 while (scanner.currentCharacter != '"') {
3553 if (scanner.currentCharacter == '\r') {
3554 if (source[scanner.currentPosition] == '\n')
3555 scanner.currentPosition++;
3556 break; // the string cannot go further that
3559 if (scanner.currentCharacter == '\n') {
3560 break; // the string cannot go further that
3563 if (scanner.currentCharacter == '\\') {
3564 scanner.scanEscapeCharacter();
3566 // consume next character
3567 scanner.unicodeAsBackSlash = false;
3568 // if (((scanner.currentCharacter =
3569 // source[scanner.currentPosition++]) == '\\')
3570 // && (source[scanner.currentPosition] == 'u'))
3572 // scanner.getNextUnicodeChar();
3574 if (scanner.withoutUnicodePtr != 0) {
3575 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3583 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3586 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3587 && (source[scanner.currentPosition] == 'u')) {
3588 //-------------unicode traitement
3590 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3591 scanner.currentPosition++;
3592 while (source[scanner.currentPosition] == 'u') {
3593 scanner.currentPosition++;
3596 .getNumericValue(source[scanner.currentPosition++])) > 15
3599 .getNumericValue(source[scanner.currentPosition++])) > 15
3602 .getNumericValue(source[scanner.currentPosition++])) > 15
3605 .getNumericValue(source[scanner.currentPosition++])) > 15
3606 || c4 < 0) { //error don't
3609 scanner.currentCharacter = 'A';
3610 } //something different from \n and \r
3612 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3615 while (scanner.currentCharacter != '\r'
3616 && scanner.currentCharacter != '\n') {
3618 scanner.startPosition = scanner.currentPosition;
3619 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3620 && (source[scanner.currentPosition] == 'u')) {
3621 //-------------unicode traitement
3623 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3624 scanner.currentPosition++;
3625 while (source[scanner.currentPosition] == 'u') {
3626 scanner.currentPosition++;
3629 .getNumericValue(source[scanner.currentPosition++])) > 15
3632 .getNumericValue(source[scanner.currentPosition++])) > 15
3635 .getNumericValue(source[scanner.currentPosition++])) > 15
3638 .getNumericValue(source[scanner.currentPosition++])) > 15
3639 || c4 < 0) { //error don't
3642 scanner.currentCharacter = 'A';
3643 } //something different from \n
3646 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3650 if (scanner.recordLineSeparator
3651 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3652 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3653 // only record line positions we
3654 // have not recorded yet
3655 scanner.pushLineSeparator();
3656 if (this.scanner.taskTags != null) {
3657 this.scanner.checkTaskTag(this.scanner
3658 .getCurrentTokenStartPosition(), this.scanner
3659 .getCurrentTokenEndPosition());
3665 if (test > 0) { //traditional and annotation
3667 boolean star = false;
3668 // consume next character
3669 scanner.unicodeAsBackSlash = false;
3670 // if (((scanner.currentCharacter =
3671 // source[scanner.currentPosition++]) ==
3673 // (source[scanner.currentPosition] ==
3675 // scanner.getNextUnicodeChar();
3677 if (scanner.withoutUnicodePtr != 0) {
3678 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3681 if (scanner.currentCharacter == '*') {
3685 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3686 && (source[scanner.currentPosition] == 'u')) {
3687 //-------------unicode traitement
3689 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3690 scanner.currentPosition++;
3691 while (source[scanner.currentPosition] == 'u') {
3692 scanner.currentPosition++;
3695 .getNumericValue(source[scanner.currentPosition++])) > 15
3698 .getNumericValue(source[scanner.currentPosition++])) > 15
3701 .getNumericValue(source[scanner.currentPosition++])) > 15
3704 .getNumericValue(source[scanner.currentPosition++])) > 15
3705 || c4 < 0) { //error don't
3708 scanner.currentCharacter = 'A';
3709 } //something different from * and /
3711 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3714 //loop until end of comment */
3715 while ((scanner.currentCharacter != '/') || (!star)) {
3716 star = scanner.currentCharacter == '*';
3718 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3719 && (source[scanner.currentPosition] == 'u')) {
3720 //-------------unicode traitement
3722 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3723 scanner.currentPosition++;
3724 while (source[scanner.currentPosition] == 'u') {
3725 scanner.currentPosition++;
3728 .getNumericValue(source[scanner.currentPosition++])) > 15
3731 .getNumericValue(source[scanner.currentPosition++])) > 15
3734 .getNumericValue(source[scanner.currentPosition++])) > 15
3737 .getNumericValue(source[scanner.currentPosition++])) > 15
3738 || c4 < 0) { //error don't
3741 scanner.currentCharacter = 'A';
3742 } //something different from * and
3745 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3749 if (this.scanner.taskTags != null) {
3750 this.scanner.checkTaskTag(this.scanner
3751 .getCurrentTokenStartPosition(), this.scanner
3752 .getCurrentTokenEndPosition());
3759 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3760 scanner.scanIdentifierOrKeyword(false);
3763 if (Character.isDigit(scanner.currentCharacter)) {
3764 scanner.scanNumber(false);
3768 //-----------------end switch while
3769 // try--------------------
3770 } catch (IndexOutOfBoundsException e) {
3771 break; // read until EOF
3772 } catch (InvalidInputException e) {
3773 return false; // no clue
3776 if (scanner.recordLineSeparator) {
3777 // compilationUnit.compilationResult.lineSeparatorPositions =
3778 // scanner.getLineEnds();
3780 // check placement anomalies against other kinds of brackets
3781 for (int kind = 0; kind < BracketKinds; kind++) {
3782 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3783 int start = leftPositions[kind][leftIndex]; // deepest
3785 // find matching closing bracket
3786 int depth = leftDepths[kind][leftIndex];
3788 for (int i = 0; i < rightCount[kind]; i++) {
3789 int pos = rightPositions[kind][i];
3790 // want matching bracket further in source with same
3792 if ((pos > start) && (depth == rightDepths[kind][i])) {
3797 if (end < 0) { // did not find a good closing match
3798 problemReporter.unmatchedBracket(start, referenceContext,
3799 compilationUnit.compilationResult);
3802 // check if even number of opening/closing other brackets
3803 // in between this pair of brackets
3805 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3806 for (int i = 0; i < leftCount[otherKind]; i++) {
3807 int pos = leftPositions[otherKind][i];
3808 if ((pos > start) && (pos < end))
3811 for (int i = 0; i < rightCount[otherKind]; i++) {
3812 int pos = rightPositions[otherKind][i];
3813 if ((pos > start) && (pos < end))
3817 problemReporter.unmatchedBracket(start, referenceContext,
3818 compilationUnit.compilationResult); //bracket
3824 // too many opening brackets ?
3825 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3826 anomaliesDetected = true;
3827 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3828 - i - 1], referenceContext, compilationUnit.compilationResult);
3830 // too many closing brackets ?
3831 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3832 anomaliesDetected = true;
3833 problemReporter.unmatchedBracket(rightPositions[kind][i],
3834 referenceContext, compilationUnit.compilationResult);
3836 if (anomaliesDetected)
3839 return anomaliesDetected;
3840 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3841 return anomaliesDetected;
3842 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3843 return anomaliesDetected;
3846 protected void pushOnAstLengthStack(int pos) {
3848 astLengthStack[++astLengthPtr] = pos;
3849 } catch (IndexOutOfBoundsException e) {
3850 int oldStackLength = astLengthStack.length;
3851 int[] oldPos = astLengthStack;
3852 astLengthStack = new int[oldStackLength + StackIncrement];
3853 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3854 astLengthStack[astLengthPtr] = pos;
3857 protected void pushOnAstStack(AstNode node) {
3859 * add a new obj on top of the ast stack
3862 astStack[++astPtr] = node;
3863 } catch (IndexOutOfBoundsException e) {
3864 int oldStackLength = astStack.length;
3865 AstNode[] oldStack = astStack;
3866 astStack = new AstNode[oldStackLength + AstStackIncrement];
3867 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3868 astPtr = oldStackLength;
3869 astStack[astPtr] = node;
3872 astLengthStack[++astLengthPtr] = 1;
3873 } catch (IndexOutOfBoundsException e) {
3874 int oldStackLength = astLengthStack.length;
3875 int[] oldPos = astLengthStack;
3876 astLengthStack = new int[oldStackLength + AstStackIncrement];
3877 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3878 astLengthStack[astLengthPtr] = 1;