1 /**********************************************************************
2 Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Common Public License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/legal/cpl-v10.html
9 Klaus Hartlage - www.eclipseproject.de
10 **********************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.parser;
12 import java.util.ArrayList;
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
15 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
16 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
17 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
18 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
19 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
20 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
21 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
22 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
23 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
26 import net.sourceforge.phpeclipse.phpeditor.PHPString;
27 import org.eclipse.core.resources.IFile;
28 public class Parser //extends PHPParserSuperclass
29 implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
30 //internal data for the automat
31 protected final static int StackIncrement = 255;
32 protected int stateStackTop;
33 protected int[] stack = new int[StackIncrement];
34 public int firstToken; // handle for multiple parsing goals
35 public int lastAct; //handle for multiple parsing goals
36 protected RecoveredElement currentElement;
37 public static boolean VERBOSE_RECOVERY = false;
38 protected boolean diet = false; //tells the scanner to jump over some
39 // parts of the code/expressions like
42 public Scanner scanner;
43 private ArrayList phpList;
44 private int currentPHPString;
45 private boolean phpEnd;
46 // private static HashMap keywordMap = null;
52 // row counter for syntax errors:
54 // column counter for syntax errors:
58 // // current identifier
62 private String stringValue;
63 /** Contains the current expression. */
64 // private StringBuffer expression;
65 private boolean phpMode;
66 protected int modifiers;
67 protected int modifiersSourceStart;
69 this.currentPHPString = 0;
70 // PHPParserSuperclass.fileToParse = fileToParse;
73 this.token = TokenNameEOF;
76 // this.columnCount = 0;
79 this.initializeScanner();
81 public void setFileToParse(IFile fileToParse) {
82 this.currentPHPString = 0;
83 // PHPParserSuperclass.fileToParse = fileToParse;
86 this.token = TokenNameEOF;
88 this.initializeScanner();
91 * ClassDeclaration Constructor.
95 * Description of Parameter
98 public Parser(IFile fileToParse) {
99 // if (keywordMap == null) {
100 // keywordMap = new HashMap();
101 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
102 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
105 this.currentPHPString = 0;
106 // PHPParserSuperclass.fileToParse = fileToParse;
109 this.token = TokenNameEOF;
111 // this.rowCount = 1;
112 // this.columnCount = 0;
115 this.initializeScanner();
117 public void initializeScanner() {
118 this.scanner = new Scanner(false, false, false, false);
121 * Create marker for the parse error
123 // private void setMarker(String message, int charStart, int charEnd, int
125 // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
128 * This method will throw the SyntaxError. It will add the good lines and
129 * columns to the Error
133 * @throws SyntaxError
136 private void throwSyntaxError(String error) {
137 int problemStartPosition = scanner.getCurrentTokenStartPosition();
138 int problemEndPosition = scanner.getCurrentTokenEndPosition();
139 throwSyntaxError(error, problemStartPosition, problemEndPosition);
142 * This method will throw the SyntaxError. It will add the good lines and
143 * columns to the Error
147 * @throws SyntaxError
150 // private void throwSyntaxError(String error, int startRow) {
151 // throw new SyntaxError(startRow, 0, " ", error);
153 private void throwSyntaxError(String error, int problemStartPosition,
154 int problemEndPosition) {
156 .phpParsingError(new String[]{error}, problemStartPosition,
157 problemEndPosition, referenceContext,
158 compilationUnit.compilationResult);
159 throw new SyntaxError(1, 0, " ", error);
161 private void reportSyntaxError(String error, int problemStartPosition,
162 int problemEndPosition) {
164 .phpParsingError(new String[]{error}, problemStartPosition,
165 problemEndPosition, referenceContext,
166 compilationUnit.compilationResult);
169 * Method Declaration.
173 // private void getChar() {
174 // if (str.length() > chIndx) {
175 // ch = str.charAt(chIndx++);
180 // chIndx = str.length() + 1;
182 // // token = TokenNameEOF;
186 * gets the next token from input
188 private void getNextToken() {
190 token = scanner.getNextToken();
192 int currentEndPosition = scanner.getCurrentTokenEndPosition();
193 int currentStartPosition = scanner.getCurrentTokenStartPosition();
195 .print(currentStartPosition + "," + currentEndPosition + ": ");
196 System.out.println(scanner.toStringAction(token));
198 } catch (InvalidInputException e) {
199 token = TokenNameERROR;
204 * Get a number. if it's a <code>double</code> the number will be stored in
205 * <code>doubleNumber</code> and the token will have the value
206 * {@link Parser#TokenNameDOUBLE_NUMBER}<br />
207 * if it's a <code>double</code> the number will be stored in <code>longNumber</code>
208 * and the token will have the value {@link Parser#TokenNameINT_NUMBER}
210 // private void getNumber() {
211 // StringBuffer inum = new StringBuffer();
213 // int numFormat = 10;
215 // // save first digit
216 // char firstCh = ch;
220 // // determine number conversions:
221 // if (firstCh == '0') {
250 // if (numFormat == 16) {
251 // while ((ch >= '0' && ch <= '9')
252 // || (ch >= 'a' && ch <= 'f')
253 // || (ch >= 'A' && ch <= 'F')) {
258 // while ((ch >= '0' && ch <= '9')
262 // if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
263 // if (ch == '.' && dFlag != ' ') {
266 // if ((dFlag == 'E') || (dFlag == 'e')) {
272 // if ((ch == '-') || (ch == '+')) {
285 // if (dFlag != ' ') {
286 // doubleNumber = new Double(inum.toString());
287 // token = TokenNameDoubleLiteral;
290 // longNumber = Long.valueOf(inum.toString(), numFormat);
291 // token = TokenNameIntegerLiteral;
295 // } catch (Throwable e) {
296 // throwSyntaxError("Number format error: " + inum.toString());
302 // * @param openChar the opening char ('\'', '"', '`')
303 // * @param typeString the type of string {@link
304 // #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
305 // * @param errorMsg the error message in case of parse error in the string
307 // private void getString(
308 // final char openChar,
309 // final int typeString,
310 // final String errorMsg) {
311 // StringBuffer sBuffer = new StringBuffer();
312 // boolean openString = true;
313 // int startRow = rowCount;
314 // while (str.length() > chIndx) {
315 // ch = str.charAt(chIndx++);
317 // sBuffer.append(ch);
318 // if (str.length() > chIndx) {
319 // ch = str.charAt(chIndx++);
320 // sBuffer.append(ch);
322 // } else if (ch == openChar) {
323 // openString = false;
325 // } else if (ch == '\n') {
327 // columnCount = chIndx;
329 // sBuffer.append(ch);
333 // if (typeString == TokenNameStringConstant) {
334 // throwSyntaxError(errorMsg, startRow);
336 // throwSyntaxError(errorMsg);
339 // token = typeString;
340 // stringValue = sBuffer.toString();
342 // public void htmlParserTester(String input) {
343 // int lineNumber = 1;
344 // int startLineNumber = 1;
345 // int startIndex = 0;
348 // boolean phpMode = false;
349 // boolean phpFound = false;
351 // phpList = new ArrayList();
352 // currentPHPString = 0;
356 // while (i < input.length()) {
357 // ch = input.charAt(i++);
361 // if ((!phpMode) && ch == '<') {
362 // ch2 = input.charAt(i++);
364 // ch2 = input.charAt(i++);
365 // if (Character.isWhitespace(ch2)) {
370 // startLineNumber = lineNumber;
372 // } else if (ch2 == 'p') {
373 // ch2 = input.charAt(i++);
375 // ch2 = input.charAt(i++);
380 // startLineNumber = lineNumber;
386 // } else if (ch2 == 'P') {
387 // ch2 = input.charAt(i++);
389 // ch2 = input.charAt(i++);
394 // startLineNumber = lineNumber;
407 // if (ch == '/' && i < input.length()) {
408 // ch2 = input.charAt(i++);
410 // while (i < input.length()) {
411 // ch = input.charAt(i++);
412 // if (ch == '?' && i < input.length()) {
413 // ch2 = input.charAt(i++);
422 // startLineNumber));
426 // } else if (ch == '\n') {
432 // } else if (ch2 == '*') {
433 // // multi-line comment
434 // while (i < input.length()) {
435 // ch = input.charAt(i++);
438 // } else if (ch == '*' && i < input.length()) {
439 // ch2 = input.charAt(i++);
450 // } else if (ch == '#') {
451 // while (i < input.length()) {
452 // ch = input.charAt(i++);
453 // if (ch == '?' && i < input.length()) {
454 // ch2 = input.charAt(i++);
460 // input.substring(startIndex, i - 2),
461 // startLineNumber));
465 // } else if (ch == '\n') {
471 // } else if (ch == '"') {
473 // while (i < input.length()) {
474 // ch = input.charAt(i++);
478 // ch == '\\' && i < input.length()) { // escape
480 // } else if (ch == '"') {
485 // } else if (ch == '\'') {
487 // while (i < input.length()) {
488 // ch = input.charAt(i++);
492 // ch == '\\' && i < input.length()) { // escape
494 // } else if (ch == '\'') {
501 // if (ch == '?' && i < input.length()) {
502 // ch2 = input.charAt(i++);
508 // input.substring(startIndex, i - 2),
509 // startLineNumber));
519 // "No PHP source code found.",
525 // "Open PHP tag at end of file.",
530 // input.substring(startIndex, i - 2),
531 // startLineNumber));
533 // // for (int j=0;j<phpList.size();j++) {
534 // // String temp = ((PHPString)phpList.get(j)).getPHPString();
535 // // int startIndx = temp.length()-10;
536 // // if (startIndx<0) {
539 // // System.out.println(temp.substring(startIndx)+"?>");
541 // phpParserTester(null, 1);
542 // // PHPString temp;
543 // // for(int j=0;j<phpList.size();j++) {
544 // // temp = (PHPString) phpList.get(j);
545 // // parser.start(temp.getPHPString(), temp.getLineNumber());
548 // } catch (CoreException e) {
551 public void phpParserTester(String s, int rowCount) {
554 if (phpList.size() != 0) {
555 this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
558 this.token = TokenNameEOF;
560 // this.rowCount = rowCount;
561 // this.columnCount = 0;
564 scanner.setSource(s.toCharArray());
565 scanner.setPHPMode(true);
569 if (token != TokenNameEOF && token != TokenNameERROR) {
572 if (token != TokenNameEOF) {
573 if (token == TokenNameERROR) {
574 throwSyntaxError("Scanner error (Found unknown token: "
575 + scanner.toStringAction(token) + ")");
577 if (token == TokenNameRPAREN) {
578 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
580 if (token == TokenNameRBRACE) {
581 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
583 if (token == TokenNameRBRACKET) {
584 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
586 if (token == TokenNameLPAREN) {
587 throwSyntaxError("Read character '('; end-of-file not reached.");
589 if (token == TokenNameLBRACE) {
590 throwSyntaxError("Read character '{'; end-of-file not reached.");
592 if (token == TokenNameLBRACKET) {
593 throwSyntaxError("Read character '['; end-of-file not reached.");
595 throwSyntaxError("End-of-file not reached.");
598 } catch (SyntaxError err) {
602 // setMarker(err.getMessage(), err.getLine(), ERROR);
603 // setMarker(err.getMessage(),
604 // scanner.getCurrentTokenStartPosition(),
605 // scanner.getCurrentTokenEndPosition(), ERROR);
607 // if an error occured,
608 // try to find keywords 'class' or 'function'
609 // to parse the rest of the string
610 while (token != TokenNameEOF && token != TokenNameERROR) {
611 if (token == TokenNameabstract || token == TokenNamefinal
612 || token == TokenNameclass || token == TokenNamefunction) {
617 if (token == TokenNameEOF || token == TokenNameERROR) {
623 public void init(String s) {
625 this.token = TokenNameEOF;
627 // this.rowCount = 1;
628 // this.columnCount = 0;
630 this.phpMode = false;
631 /* scanner initialization */
632 scanner.setSource(s.toCharArray());
633 scanner.setPHPMode(false);
635 protected void initialize(boolean phpMode) {
636 compilationUnit = null;
637 referenceContext = null;
639 this.token = TokenNameEOF;
641 // this.rowCount = 1;
642 // this.columnCount = 0;
644 this.phpMode = phpMode;
645 scanner.setPHPMode(phpMode);
648 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
651 public void parse(String s) {
656 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
659 protected void parse() {
663 if (token != TokenNameEOF && token != TokenNameERROR) {
666 if (token != TokenNameEOF) {
667 if (token == TokenNameERROR) {
668 throwSyntaxError("Scanner error (Found unknown token: "
669 + scanner.toStringAction(token) + ")");
671 if (token == TokenNameRPAREN) {
672 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
674 if (token == TokenNameRBRACE) {
675 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
677 if (token == TokenNameRBRACKET) {
678 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
680 if (token == TokenNameLPAREN) {
681 throwSyntaxError("Read character '('; end-of-file not reached.");
683 if (token == TokenNameLBRACE) {
684 throwSyntaxError("Read character '{'; end-of-file not reached.");
686 if (token == TokenNameLBRACKET) {
687 throwSyntaxError("Read character '['; end-of-file not reached.");
689 throwSyntaxError("End-of-file not reached.");
692 } catch (SyntaxError sytaxErr1) {
693 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
695 // setMarker(sytaxErr1.getMessage(),
696 // scanner.getCurrentTokenStartPosition(),
697 // scanner.getCurrentTokenEndPosition(), ERROR);
699 // if an error occured,
700 // try to find keywords 'class' or 'function'
701 // to parse the rest of the string
702 while (token != TokenNameEOF && token != TokenNameERROR) {
703 if (token == TokenNameabstract || token == TokenNamefinal
704 || token == TokenNameclass || token == TokenNamefunction) {
709 if (token == TokenNameEOF || token == TokenNameERROR) {
712 } catch (SyntaxError sytaxErr2) {
713 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
715 // setMarker(sytaxErr2.getMessage(),
716 // scanner.getCurrentTokenStartPosition(),
717 // scanner.getCurrentTokenEndPosition(), ERROR);
723 // public PHPOutlineInfo parseInfo(Object parent, String s) {
724 // PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
725 // // Stack stack = new Stack();
726 // // stack.push(outlineInfo.getDeclarations());
728 // this.token = TokenNameEOF;
729 // // this.chIndx = 0;
730 // // this.rowCount = 1;
731 // // this.columnCount = 0;
732 // this.phpEnd = false;
733 // this.phpMode = false;
734 // scanner.setSource(s.toCharArray());
735 // scanner.setPHPMode(false);
738 // parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
740 // return outlineInfo;
742 private boolean isVariable() {
743 return token == TokenNameVariable || token == TokenNamethis;
745 // private void parseDeclarations(PHPOutlineInfo outlineInfo,
746 // OutlineableWithChildren current, boolean goBack) {
748 // // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
749 // PHPSegmentWithChildren temp;
751 // IPreferenceStore store =
752 // PHPeclipsePlugin.getDefault().getPreferenceStore();
754 // while (token != TokenNameEOF && token != TokenNameERROR) {
755 // if (token == TokenNameVariable) {
756 // ident = scanner.getCurrentIdentifierSource();
757 // outlineInfo.addVariable(new String(ident));
759 // } else if (token == TokenNamevar) {
761 // if (token == TokenNameVariable
762 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
763 // ident = scanner.getCurrentIdentifierSource();
764 // //substring(1) added because PHPVarDeclaration doesn't
765 // // need the $ anymore
766 // String variableName = new String(ident).substring(1);
767 // outlineInfo.addVariable(variableName);
769 // if (token != TokenNameSEMICOLON) {
771 // ident = scanner.getCurrentTokenSource();
772 // if (token > TokenNameKEYWORD) {
773 // current.add(new PHPVarDeclaration(current, variableName,
774 // // chIndx - ident.length,
775 // scanner.getCurrentTokenStartPosition(), new String(ident)));
778 // case TokenNameVariable :
779 // case TokenNamethis :
780 // current.add(new PHPVarDeclaration(current, variableName,
783 // scanner.getCurrentTokenStartPosition(), new String(
786 // case TokenNameIdentifier :
787 // current.add(new PHPVarDeclaration(current, variableName,
790 // scanner.getCurrentTokenStartPosition(), new String(
793 // case TokenNameDoubleLiteral :
794 // current.add(new PHPVarDeclaration(current, variableName
798 // scanner.getCurrentTokenStartPosition(), new String(
801 // case TokenNameIntegerLiteral :
802 // current.add(new PHPVarDeclaration(current, variableName,
805 // scanner.getCurrentTokenStartPosition(), new String(
808 // case TokenNameStringInterpolated :
809 // case TokenNameStringLiteral :
810 // current.add(new PHPVarDeclaration(current, variableName,
813 // scanner.getCurrentTokenStartPosition(), new String(
816 // case TokenNameStringConstant :
817 // current.add(new PHPVarDeclaration(current, variableName,
820 // scanner.getCurrentTokenStartPosition(), new String(
824 // current.add(new PHPVarDeclaration(current, variableName,
827 // scanner.getCurrentTokenStartPosition()));
832 // ident = scanner.getCurrentIdentifierSource();
833 // current.add(new PHPVarDeclaration(current, variableName,
834 // // chIndx - ident.length
835 // scanner.getCurrentTokenStartPosition()));
838 // } else if (token == TokenNamefunction) {
840 // if (token == TokenNameAND) {
843 // if (token == TokenNameIdentifier
844 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
845 // ident = scanner.getCurrentIdentifierSource();
846 // outlineInfo.addVariable(new String(ident));
847 // temp = new PHPFunctionDeclaration(current, new String(ident),
848 // // chIndx - ident.length
849 // scanner.getCurrentTokenStartPosition());
850 // current.add(temp);
852 // parseDeclarations(outlineInfo, temp, true);
854 // } else if (token == TokenNameclass) {
856 // if (token == TokenNameIdentifier
857 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
858 // ident = scanner.getCurrentIdentifierSource();
859 // outlineInfo.addVariable(new String(ident));
860 // temp = new PHPClassDeclaration(current, new String(ident),
861 // // chIndx - ident.len
862 // scanner.getCurrentTokenStartPosition());
863 // current.add(temp);
864 // // stack.push(temp);
866 // //skip tokens for classname, extends and others until
867 // // we have the opening '{'
868 // while (token != TokenNameLBRACE && token != TokenNameEOF
869 // && token != TokenNameERROR) {
872 // parseDeclarations(outlineInfo, temp, true);
875 // } else if ((token == TokenNameLBRACE)
876 // || (token == TokenNameDOLLAR_LBRACE)) {
879 // } else if (token == TokenNameRBRACE) {
882 // if (counter == 0 && goBack) {
885 // } else if (token == TokenNamerequire || token == TokenNamerequire_once
886 // || token == TokenNameinclude || token == TokenNameinclude_once) {
887 // ident = scanner.getCurrentTokenSource();
889 // int startPosition = scanner.getCurrentTokenStartPosition();
891 // char[] expr = scanner.getCurrentTokenSource(startPosition);
892 // outlineInfo.addVariable(new String(ident));
893 // current.add(new PHPReqIncDeclaration(current, new String(ident),
894 // // chIndx - ident.length,
895 // startPosition, new String(expr)));
901 // } catch (SyntaxError sytaxErr) {
903 // // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
904 // // setMarker(sytaxErr.getMessage(),
905 // // scanner.getCurrentTokenStartPosition(),
906 // // scanner.getCurrentTokenEndPosition(), ERROR);
907 // // } catch (CoreException e) {
911 private void statementList() {
913 statement(TokenNameEOF);
914 if ((token == TokenNameRBRACE) || (token == TokenNamecase)
915 || (token == TokenNamedefault) || (token == TokenNameelse)
916 || (token == TokenNameelseif) || (token == TokenNameendif)
917 || (token == TokenNameendfor) || (token == TokenNameendforeach)
918 || (token == TokenNameendwhile) || (token == TokenNameendswitch)
919 || (token == TokenNameEOF) || (token == TokenNameERROR)) {
924 private void functionBody(MethodDeclaration methodDecl) {
925 // '{' [statement-list] '}'
926 if (token == TokenNameLBRACE) {
929 throwSyntaxError("'{' expected in compound-statement.");
931 if (token != TokenNameRBRACE) {
934 if (token == TokenNameRBRACE) {
935 methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
938 throwSyntaxError("'}' expected in compound-statement.");
941 private void statement(int previousToken) {
942 // if (token > TokenNameKEYWORD && token != TokenNamelist && token !=
944 // char[] ident = scanner.getCurrentIdentifierSource();
945 // String keyword = new String(ident);
946 if (token == TokenNameAT) {
948 if (token != TokenNamerequire && token != TokenNamerequire_once
949 && token != TokenNameinclude && token != TokenNameinclude_once
950 && token != TokenNameIdentifier && token != TokenNameVariable
951 && token != TokenNamethis && token != TokenNameStringInterpolated) {
952 throwSyntaxError("identifier expected after '@'.");
955 if (token == TokenNameinclude || token == TokenNameinclude_once) {
957 if (token == TokenNameLPAREN) {
959 if (token == TokenNameSEMICOLON) {
962 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
963 throwSyntaxError("';' expected after 'include' or 'include_once'.");
968 concatenationExpression();
971 } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
974 if (token == TokenNameLPAREN) {
976 if (token == TokenNameSEMICOLON) {
979 if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
980 throwSyntaxError("';' expected after 'require' or 'require_once'.");
985 concatenationExpression();
988 } else if (token == TokenNameif) {
990 if (token == TokenNameLPAREN) {
993 throwSyntaxError("'(' expected after 'if' keyword.");
996 if (token == TokenNameRPAREN) {
999 throwSyntaxError("')' expected after 'if' condition.");
1003 } else if (token == TokenNameswitch) {
1005 if (token == TokenNameLPAREN) {
1008 throwSyntaxError("'(' expected after 'switch' keyword.");
1011 if (token == TokenNameRPAREN) {
1014 throwSyntaxError("')' expected after 'switch' condition.");
1018 } else if (token == TokenNamefor) {
1020 if (token == TokenNameLPAREN) {
1023 throwSyntaxError("'(' expected after 'for' keyword.");
1025 if (token == TokenNameSEMICOLON) {
1029 if (token == TokenNameSEMICOLON) {
1032 throwSyntaxError("';' expected after 'for'.");
1035 if (token == TokenNameSEMICOLON) {
1039 if (token == TokenNameSEMICOLON) {
1042 throwSyntaxError("';' expected after 'for'.");
1045 if (token == TokenNameRPAREN) {
1049 if (token == TokenNameRPAREN) {
1052 throwSyntaxError("')' expected after 'for'.");
1057 } else if (token == TokenNamewhile) {
1059 if (token == TokenNameLPAREN) {
1062 throwSyntaxError("'(' expected after 'while' keyword.");
1065 if (token == TokenNameRPAREN) {
1068 throwSyntaxError("')' expected after 'while' condition.");
1072 } else if (token == TokenNamedo) {
1074 if (token == TokenNameLBRACE) {
1077 throwSyntaxError("'{' expected after 'do' keyword.");
1079 if (token != TokenNameRBRACE) {
1082 if (token == TokenNameRBRACE) {
1085 throwSyntaxError("'}' expected after 'do' keyword.");
1087 if (token == TokenNamewhile) {
1089 if (token == TokenNameLPAREN) {
1092 throwSyntaxError("'(' expected after 'while' keyword.");
1095 if (token == TokenNameRPAREN) {
1098 throwSyntaxError("')' expected after 'while' condition.");
1101 throwSyntaxError("'while' expected after 'do' keyword.");
1103 if (token == TokenNameSEMICOLON) {
1106 if (token != TokenNameStopPHP) {
1107 throwSyntaxError("';' expected after do-while statement.");
1112 } else if (token == TokenNameforeach) {
1114 if (token == TokenNameLPAREN) {
1117 throwSyntaxError("'(' expected after 'foreach' keyword.");
1120 if (token == TokenNameas) {
1123 throwSyntaxError("'as' expected after 'foreach' exxpression.");
1126 if (token == TokenNameEQUAL_GREATER) {
1130 if (token == TokenNameRPAREN) {
1133 throwSyntaxError("')' expected after 'foreach' expression.");
1137 } else if (token == TokenNamecontinue || token == TokenNamebreak
1138 || token == TokenNamereturn) {
1140 if (token != TokenNameSEMICOLON) {
1143 if (token == TokenNameSEMICOLON) {
1146 if (token != TokenNameStopPHP) {
1147 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1152 } else if (token == TokenNameecho) {
1155 if (token == TokenNameSEMICOLON) {
1158 if (token != TokenNameStopPHP) {
1159 throwSyntaxError("';' expected after 'echo' statement.");
1164 // } else if (token == TokenNameprint) {
1167 // if (token == TokenNameSEMICOLON) {
1170 // if (token != TokenNameStopPHP) {
1171 // throwSyntaxError("';' expected after 'print' statement.");
1176 } else if (token == TokenNameglobal || token == TokenNamestatic) {
1179 if (token == TokenNameSEMICOLON) {
1182 if (token != TokenNameStopPHP) {
1183 throwSyntaxError("';' expected after 'global' or 'static' statement.");
1188 } else if (token == TokenNameunset) {
1190 if (token == TokenNameLPAREN) {
1193 throwSyntaxError("'(' expected after 'unset' statement.");
1196 if (token == TokenNameRPAREN) {
1199 throwSyntaxError("')' expected after 'unset' statement.");
1201 if (token == TokenNameSEMICOLON) {
1204 if (token != TokenNameStopPHP) {
1205 throwSyntaxError("';' expected after 'unset' statement.");
1210 // } else if (token == TokenNameexit || token == TokenNamedie) {
1212 // if (token != TokenNameSEMICOLON) {
1215 // if (token == TokenNameSEMICOLON) {
1218 // if (token != TokenNameStopPHP) {
1219 // throwSyntaxError("';' expected after 'exit' or 'die'
1225 // } else if (token == TokenNamedefine) {
1227 // if (token == TokenNameLPAREN) {
1230 // throwSyntaxError("'(' expected after 'define' keyword.");
1233 // if (token == TokenNameCOMMA) {
1236 // throwSyntaxError("',' expected after first 'define' constant.");
1239 // if (token == TokenNameCOMMA) {
1243 // if (token == TokenNameRPAREN) {
1246 // throwSyntaxError("')' expected after 'define' statement.");
1248 // if (token == TokenNameSEMICOLON) {
1251 // if (token != TokenNameStopPHP) {
1252 // throwSyntaxError("';' expected after 'define' statement.");
1257 } else if (token == TokenNamefunction) {
1258 MethodDeclaration methodDecl = new MethodDeclaration(
1259 this.compilationUnit.compilationResult);
1260 methodDecl.declarationSourceStart = scanner
1261 .getCurrentTokenStartPosition();
1263 functionDefinition(methodDecl);
1265 } else if (token == TokenNamefinal || token == TokenNameabstract
1266 || token == TokenNameclass || token == TokenNameinterface) {
1267 TypeDeclaration typeDecl = new TypeDeclaration(
1268 this.compilationUnit.compilationResult);
1269 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1270 // default super class
1271 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
1272 compilationUnit.types.add(typeDecl);
1274 pushOnAstStack(typeDecl);
1275 unticked_class_declaration_statement(typeDecl);
1276 // classBody(typeDecl);
1283 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1284 } else if (token == TokenNameLBRACE) {
1286 if (token != TokenNameRBRACE) {
1289 if (token == TokenNameRBRACE) {
1293 throwSyntaxError("'}' expected.");
1296 if (token != TokenNameSEMICOLON) {
1299 if (token == TokenNameSEMICOLON) {
1303 if (token != TokenNameStopPHP && token != TokenNameEOF) {
1304 throwSyntaxError("';' expected after expression (Found token: "
1305 + scanner.toStringAction(token) + ")");
1311 private void unset_variables() {
1314 // | unset_variables ',' unset_variable
1319 if (token != TokenNameCOMMA) {
1325 private final void initializeModifiers() {
1327 this.modifiersSourceStart = -1;
1329 private final void checkAndSetModifiers(int flag) {
1330 this.modifiers |= flag;
1331 if (this.modifiersSourceStart < 0)
1332 this.modifiersSourceStart = this.scanner.startPosition;
1334 private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1335 initializeModifiers();
1336 if (token == TokenNameinterface) {
1337 // interface_entry T_STRING
1338 // interface_extends_list
1339 // '{' class_statement_list '}'
1340 checkAndSetModifiers(AccInterface);
1342 typeDecl.modifiers = this.modifiers;
1343 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1344 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1345 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1346 typeDecl.name = scanner.getCurrentIdentifierSource();
1347 if (token > TokenNameKEYWORD) {
1348 throwSyntaxError("Don't use a keyword for interface declaration ["
1349 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1350 typeDecl.sourceEnd);
1353 interface_extends_list();
1355 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1356 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1357 typeDecl.name = new char[]{' '};
1358 throwSyntaxError("Interface name expected after keyword 'interface'.",
1359 typeDecl.sourceStart, typeDecl.sourceEnd);
1363 // class_entry_type T_STRING extends_from
1365 // '{' class_statement_list'}'
1367 typeDecl.modifiers = this.modifiers;
1369 //identifier 'extends' identifier
1370 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1371 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1372 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1373 typeDecl.name = scanner.getCurrentIdentifierSource();
1374 if (token > TokenNameKEYWORD) {
1375 throwSyntaxError("Don't use a keyword for class declaration ["
1376 + scanner.toStringAction(token) + "].", typeDecl.sourceStart,
1377 typeDecl.sourceEnd);
1382 // | T_EXTENDS fully_qualified_class_name
1383 if (token == TokenNameextends) {
1385 if (token == TokenNameIdentifier) {
1388 throwSyntaxError("Class name expected after keyword 'extends'.",
1389 scanner.getCurrentTokenStartPosition(), scanner
1390 .getCurrentTokenEndPosition());
1395 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1396 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1397 typeDecl.name = new char[]{' '};
1398 throwSyntaxError("Class name expected after keyword 'class'.",
1399 typeDecl.sourceStart, typeDecl.sourceEnd);
1403 // '{' class_statement_list '}'
1404 if (token == TokenNameLBRACE) {
1406 if (token != TokenNameRBRACE) {
1407 class_statement_list();
1409 if (token == TokenNameRBRACE) {
1410 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1413 throwSyntaxError("'}' expected at end of interface body.");
1416 throwSyntaxError("'{' expected at start of interface body.");
1419 private void class_entry_type() {
1421 // | T_ABSTRACT T_CLASS
1422 // | T_FINAL T_CLASS
1423 if (token == TokenNameclass) {
1425 } else if (token == TokenNameabstract) {
1426 checkAndSetModifiers(AccAbstract);
1428 if (token != TokenNameclass) {
1429 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1432 } else if (token == TokenNamefinal) {
1433 checkAndSetModifiers(AccFinal);
1435 if (token != TokenNameclass) {
1436 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1440 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1443 private void interface_extends_list() {
1445 // | T_EXTENDS interface_list
1446 if (token == TokenNameextends) {
1451 private void implements_list() {
1453 // | T_IMPLEMENTS interface_list
1454 if (token == TokenNameimplements) {
1459 private void interface_list() {
1461 // fully_qualified_class_name
1462 //| interface_list ',' fully_qualified_class_name
1464 if (token == TokenNameIdentifier) {
1467 throwSyntaxError("Interface name expected after keyword 'implements'.");
1469 if (token != TokenNameCOMMA) {
1475 // private void classBody(TypeDeclaration typeDecl) {
1476 // //'{' [class-element-list] '}'
1477 // if (token == TokenNameLBRACE) {
1479 // if (token != TokenNameRBRACE) {
1480 // class_statement_list();
1482 // if (token == TokenNameRBRACE) {
1483 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1486 // throwSyntaxError("'}' expected at end of class body.");
1489 // throwSyntaxError("'{' expected at start of class body.");
1492 private void class_statement_list() {
1495 } while (token == TokenNamefunction || token == TokenNamevar);
1497 private void class_statement() {
1499 // variable_modifiers class_variable_declaration ';'
1500 // | class_constant_declaration ';'
1501 // | method_modifiers T_FUNCTION is_reference T_STRING
1502 // '(' parameter_list ')' method_body
1503 initializeModifiers();
1504 if (token == TokenNamevar) {
1505 checkAndSetModifiers(AccPublic);
1507 "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected' modifier for field declarations.",
1508 scanner.getCurrentTokenStartPosition(), scanner
1509 .getCurrentTokenEndPosition());
1513 boolean hasModifiers = member_modifiers();
1514 if (token == TokenNamefunction) {
1515 if (!hasModifiers) {
1516 checkAndSetModifiers(AccPublic);
1518 MethodDeclaration methodDecl = new MethodDeclaration(
1519 this.compilationUnit.compilationResult);
1520 methodDecl.declarationSourceStart = scanner
1521 .getCurrentTokenStartPosition();
1522 methodDecl.modifiers = this.modifiers;
1524 functionDefinition(methodDecl);
1526 if (!hasModifiers) {
1527 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1532 // if (token == TokenNamefunction) {
1533 // MethodDeclaration methodDecl = new MethodDeclaration(
1534 // this.compilationUnit.compilationResult);
1535 // methodDecl.declarationSourceStart = scanner
1536 // .getCurrentTokenStartPosition();
1538 // functionDefinition(methodDecl);
1539 // } else if (token == TokenNamevar) {
1543 // throwSyntaxError("'function' or 'var' expected.");
1546 // private void variable_modifiers() {
1547 // // variable_modifiers:
1548 // // non_empty_member_modifiers
1550 // initializeModifiers();
1551 // if (token == TokenNamevar) {
1552 // checkAndSetModifiers(AccPublic);
1553 // reportSyntaxError(
1554 // "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
1555 // modifier for field declarations.",
1556 // scanner.getCurrentTokenStartPosition(), scanner
1557 // .getCurrentTokenEndPosition());
1560 // if (!member_modifiers()) {
1561 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1562 // field declarations.");
1566 // private void method_modifiers() {
1567 // //method_modifiers:
1569 // //| non_empty_member_modifiers
1570 // initializeModifiers();
1571 // if (!member_modifiers()) {
1572 // checkAndSetModifiers(AccPublic);
1575 private boolean member_modifiers() {
1582 boolean foundToken = false;
1584 if (token == TokenNamepublic) {
1585 checkAndSetModifiers(AccPublic);
1588 } else if (token == TokenNameprotected) {
1589 checkAndSetModifiers(AccProtected);
1592 } else if (token == TokenNameprivate) {
1593 checkAndSetModifiers(AccPrivate);
1596 } else if (token == TokenNamestatic) {
1597 checkAndSetModifiers(AccStatic);
1600 } else if (token == TokenNameabstract) {
1601 checkAndSetModifiers(AccAbstract);
1604 } else if (token == TokenNamefinal) {
1605 checkAndSetModifiers(AccFinal);
1614 private void classProperty() {
1615 //'var' variable ';'
1616 //'var' variable '=' constant ';'
1618 if (token == TokenNameVariable) {
1620 if (token == TokenNameEQUAL) {
1625 if (token == TokenNamethis) {
1626 throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1628 throwSyntaxError("Variable expected after keyword 'var'.");
1630 if (token != TokenNameCOMMA) {
1635 if (token == TokenNameSEMICOLON) {
1638 throwSyntaxError("';' expected after variable declaration.");
1641 private void functionDefinition(MethodDeclaration methodDecl) {
1643 compilationUnit.types.add(methodDecl);
1645 AstNode node = astStack[astPtr];
1646 if (node instanceof TypeDeclaration) {
1647 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1648 if (typeDecl.methods == null) {
1649 typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1651 AbstractMethodDeclaration[] newMethods;
1656 newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1657 1, typeDecl.methods.length);
1658 newMethods[0] = methodDecl;
1659 typeDecl.methods = newMethods;
1663 functionDeclarator(methodDecl);
1664 functionBody(methodDecl);
1666 private void functionDeclarator(MethodDeclaration methodDecl) {
1667 //identifier '(' [parameter-list] ')'
1668 if (token == TokenNameAND) {
1671 if (token == TokenNameIdentifier) {
1672 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1673 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1674 methodDecl.selector = scanner.getCurrentIdentifierSource();
1676 if (token == TokenNameLPAREN) {
1679 throwSyntaxError("'(' expected in function declaration.");
1681 if (token != TokenNameRPAREN) {
1684 if (token != TokenNameRPAREN) {
1685 throwSyntaxError("')' expected in function declaration.");
1687 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1691 if (token > TokenNameKEYWORD) {
1692 throwSyntaxError("Don't use keyword for function declaration [" + token
1695 throwSyntaxError("Function name expected after keyword 'function'.");
1699 private void parameterList() {
1700 //parameter-declaration
1701 //parameter-list ',' parameter-declaration
1703 parameterDeclaration();
1704 if (token != TokenNameCOMMA) {
1710 private void parameterDeclaration() {
1712 //variable-reference
1713 if (token == TokenNameAND) {
1718 throwSyntaxError("Variable expected after reference operator '&'.");
1721 //variable '=' constant
1722 if (token == TokenNameVariable) {
1724 if (token == TokenNameEQUAL) {
1730 if (token == TokenNamethis) {
1731 throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1734 private void labeledStatementList() {
1735 if (token != TokenNamecase && token != TokenNamedefault) {
1736 throwSyntaxError("'case' or 'default' expected.");
1739 if (token == TokenNamecase) {
1741 expr(); //constant();
1742 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1744 if (token == TokenNamecase || token == TokenNamedefault) { // empty
1752 // else if (token == TokenNameSEMICOLON) {
1754 // "':' expected after 'case' keyword (Found token: " +
1755 // scanner.toStringAction(token) + ")",
1756 // scanner.getCurrentTokenStartPosition(),
1757 // scanner.getCurrentTokenEndPosition(),
1760 // if (token == TokenNamecase) { // empty case statement ?
1766 throwSyntaxError("':' character after 'case' constant expected (Found token: "
1767 + scanner.toStringAction(token) + ")");
1769 } else { // TokenNamedefault
1771 if (token == TokenNameCOLON) {
1775 throwSyntaxError("':' character after 'default' expected.");
1778 } while (token == TokenNamecase || token == TokenNamedefault);
1780 // public void labeledStatement() {
1781 // if (token == TokenNamecase) {
1784 // if (token == TokenNameDDOT) {
1788 // throwSyntaxError("':' character after 'case' constant expected.");
1791 // } else if (token == TokenNamedefault) {
1793 // if (token == TokenNameDDOT) {
1797 // throwSyntaxError("':' character after 'default' expected.");
1802 // public void expressionStatement() {
1804 // private void inclusionStatement() {
1806 // public void compoundStatement() {
1808 // public void selectionStatement() {
1811 // public void iterationStatement() {
1814 // public void jumpStatement() {
1817 // public void outputStatement() {
1820 // public void scopeStatement() {
1823 // public void flowStatement() {
1826 // public void definitionStatement() {
1828 private void ifStatement() {
1829 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1830 if (token == TokenNameCOLON) {
1832 if (token != TokenNameendif) {
1835 case TokenNameelse :
1837 if (token == TokenNameCOLON) {
1839 if (token != TokenNameendif) {
1843 if (token == TokenNameif) { //'else if'
1845 elseifStatementList();
1847 throwSyntaxError("':' expected after 'else'.");
1851 case TokenNameelseif :
1853 elseifStatementList();
1857 if (token != TokenNameendif) {
1858 throwSyntaxError("'endif' expected.");
1861 if (token != TokenNameSEMICOLON) {
1862 throwSyntaxError("';' expected after if-statement.");
1866 // statement [else-statement]
1867 statement(TokenNameEOF);
1868 if (token == TokenNameelseif) {
1870 if (token == TokenNameLPAREN) {
1873 throwSyntaxError("'(' expected after 'elseif' keyword.");
1876 if (token == TokenNameRPAREN) {
1879 throwSyntaxError("')' expected after 'elseif' condition.");
1882 } else if (token == TokenNameelse) {
1884 statement(TokenNameEOF);
1888 private void elseifStatementList() {
1892 case TokenNameelse :
1894 if (token == TokenNameCOLON) {
1896 if (token != TokenNameendif) {
1901 if (token == TokenNameif) { //'else if'
1904 throwSyntaxError("':' expected after 'else'.");
1908 case TokenNameelseif :
1916 private void elseifStatement() {
1917 if (token == TokenNameLPAREN) {
1920 if (token != TokenNameRPAREN) {
1921 throwSyntaxError("')' expected in else-if-statement.");
1924 if (token != TokenNameCOLON) {
1925 throwSyntaxError("':' expected in else-if-statement.");
1928 if (token != TokenNameendif) {
1933 private void switchStatement() {
1934 if (token == TokenNameCOLON) {
1935 // ':' [labeled-statement-list] 'endswitch' ';'
1937 labeledStatementList();
1938 if (token != TokenNameendswitch) {
1939 throwSyntaxError("'endswitch' expected.");
1942 if (token != TokenNameSEMICOLON) {
1943 throwSyntaxError("';' expected after switch-statement.");
1947 // '{' [labeled-statement-list] '}'
1948 if (token != TokenNameLBRACE) {
1949 throwSyntaxError("'{' expected in switch statement.");
1952 if (token != TokenNameRBRACE) {
1953 labeledStatementList();
1955 if (token != TokenNameRBRACE) {
1956 throwSyntaxError("'}' expected in switch statement.");
1961 private void forStatement() {
1962 if (token == TokenNameCOLON) {
1965 if (token != TokenNameendfor) {
1966 throwSyntaxError("'endfor' expected.");
1969 if (token != TokenNameSEMICOLON) {
1970 throwSyntaxError("';' expected after for-statement.");
1974 statement(TokenNameEOF);
1977 private void whileStatement() {
1978 // ':' statement-list 'endwhile' ';'
1979 if (token == TokenNameCOLON) {
1982 if (token != TokenNameendwhile) {
1983 throwSyntaxError("'endwhile' expected.");
1986 if (token != TokenNameSEMICOLON) {
1987 throwSyntaxError("';' expected after while-statement.");
1991 statement(TokenNameEOF);
1994 private void foreachStatement() {
1995 if (token == TokenNameCOLON) {
1998 if (token != TokenNameendforeach) {
1999 throwSyntaxError("'endforeach' expected.");
2002 if (token != TokenNameSEMICOLON) {
2003 throwSyntaxError("';' expected after foreach-statement.");
2007 statement(TokenNameEOF);
2010 // private void exitStatus() {
2011 // if (token == TokenNameLPAREN) {
2014 // throwSyntaxError("'(' expected in 'exit-status'.");
2016 // if (token != TokenNameRPAREN) {
2019 // if (token == TokenNameRPAREN) {
2022 // throwSyntaxError("')' expected after 'exit-status'.");
2025 private void expressionList() {
2028 if (token == TokenNameCOMMA) {
2035 private void expr() {
2036 //todo: find a better way to get the expression
2037 // expression = new StringBuffer();
2038 // for (int i = chIndx; i < str.length(); i++) {
2039 // if (str.charAt(i) == ';') {
2042 // expression.append(str.charAt(i));
2044 // if (token == TokenNameSTRING_CONSTANT || token ==
2045 // TokenNameINTERPOLATED_STRING) {
2048 logicalinclusiveorExpression();
2049 // while (token != TokenNameSEMICOLON) {
2054 private void expr_without_variable() {
2057 boolean castFlag = false;
2058 boolean arrayFlag = false;
2060 case TokenNameisset :
2061 case TokenNameempty :
2062 case TokenNameeval :
2063 case TokenNameinclude :
2064 case TokenNameinclude_once :
2065 case TokenNamerequire :
2066 case TokenNamerequire_once :
2067 internal_functions_in_yacc();
2073 case TokenNamenull :
2076 case TokenNamefalse :
2079 case TokenNametrue :
2082 case TokenNameStringConstant :
2085 case TokenNameHEREDOC :
2086 case TokenNameStringInterpolated :
2087 case TokenNameStringLiteral :
2090 case TokenNameLPAREN :
2092 if (token == TokenNameIdentifier) {
2093 // check if identifier is a type:
2094 // ident = identifier;
2095 ident = scanner.getCurrentIdentifierSource();
2096 String str = new String(ident).toLowerCase();
2097 for (int i = 0; i < PHP_TYPES.length; i++) {
2098 if (PHP_TYPES[i].equals(str)) {
2100 if (PHP_TYPES[i].equals("array")) {
2109 if (arrayFlag && token == TokenNameLPAREN) {
2111 if (token == TokenNameRPAREN) {
2115 if (token != TokenNameRPAREN) {
2116 throwSyntaxError(") expected after 'array('.");
2120 if (token != TokenNameRPAREN) {
2121 throwSyntaxError(") expected after cast-type '" + str + "'.");
2129 if (token != TokenNameRPAREN) {
2130 throwSyntaxError(") expected in postfix-expression.");
2134 case TokenNameDoubleLiteral :
2137 case TokenNameIntegerLiteral :
2140 case TokenNameDOLLAR_LBRACE :
2143 if (token != TokenNameRBRACE) {
2144 throwSyntaxError("'}' expected after indirect variable token '${'.");
2148 case TokenNameVariable :
2149 case TokenNamethis :
2150 ident = scanner.getCurrentIdentifierSource();
2152 if (token == TokenNameLBRACE) {
2155 if (token != TokenNameRBRACE) {
2156 throwSyntaxError("'}' expected after variable '"
2157 + new String(ident) + "' in variable-expression.");
2160 } else if (token == TokenNameLPAREN) {
2162 if (token != TokenNameRPAREN) {
2164 if (token != TokenNameRPAREN) {
2165 throwSyntaxError("')' expected after variable '"
2166 + new String(ident) + "' in postfix-expression.");
2172 case TokenNameIdentifier :
2173 ident = scanner.getCurrentIdentifierSource();
2175 if (token == TokenNameLPAREN) {
2177 if (token != TokenNameRPAREN) {
2179 if (token != TokenNameRPAREN) {
2180 throwSyntaxError("')' expected after identifier '"
2181 + new String(ident) + "' in postfix-expression."
2182 + "(Found token: " + scanner.toStringAction(token) + ")");
2188 case TokenNameprint :
2192 case TokenNameexit :
2196 case TokenNamelist :
2198 if (token == TokenNameLPAREN) {
2200 if (token == TokenNameCOMMA) {
2204 if (token != TokenNameRPAREN) {
2205 throwSyntaxError("')' expected after 'list' keyword.");
2208 // if (token == TokenNameSET) {
2210 // logicalinclusiveorExpression();
2213 throwSyntaxError("'(' expected after 'list' keyword.");
2216 // case TokenNameexit :
2218 // if (token != TokenNameSEMICOLON) {
2221 // if (token == TokenNameSEMICOLON) {
2224 // if (token != TokenNameStopPHP) {
2225 // throwSyntaxError("';' expected after 'exit' expression.");
2230 // case TokenNamedie :
2232 // if (token != TokenNameSEMICOLON) {
2235 // if (token == TokenNameSEMICOLON) {
2238 // if (token != TokenNameStopPHP) {
2239 // throwSyntaxError("';' expected after 'die' expression.");
2243 // case TokenNamearray :
2245 // if (token == TokenNameARGOPEN) {
2247 // if (token == TokenNameCOMMA) {
2250 // expressionList();
2251 // if (token != TokenNameARGCLOSE) {
2252 // throwSyntaxError("')' expected after 'list' keyword.");
2255 // if (token == TokenNameSET) {
2257 // logicalinclusiveorExpression();
2260 // throwSyntaxError("'(' expected after 'list' keyword.");
2264 boolean while_flag = true;
2267 case TokenNameLBRACKET :
2270 if (token != TokenNameRBRACKET) {
2271 throwSyntaxError("] expected in postfix-expression.");
2275 case TokenNameCOLON_COLON :
2277 case TokenNameMINUS_GREATER :
2280 if (token > TokenNameKEYWORD) {
2281 ident = scanner.getCurrentIdentifierSource();
2283 // "Avoid using keyword '"
2284 // + new String(ident)
2285 // + "' as variable name.",
2289 // "Avoid using keyword '" + new String(ident) + "' as
2291 // scanner.getCurrentTokenStartPosition(),
2292 // scanner.getCurrentTokenEndPosition(),
2296 case TokenNameVariable :
2297 ident = scanner.getCurrentIdentifierSource();
2299 // if (token == TokenNameARGOPEN) {
2301 // expressionList();
2302 // if (token != TokenNameARGCLOSE) {
2303 // throwSyntaxError(") expected after variable '" +
2309 case TokenNameIdentifier :
2310 //ident = scanner.getCurrentIdentifierSource();
2313 case TokenNameLBRACE :
2316 if (token != TokenNameRBRACE) {
2317 throwSyntaxError("} expected in postfix-expression.");
2322 throwSyntaxError("Syntax error after '->' token.");
2324 while (token == TokenNameLBRACKET || token == TokenNameLPAREN
2325 || token == TokenNameLBRACE) {
2326 if (token == TokenNameLBRACKET) {
2329 if (token != TokenNameRBRACKET) {
2330 throwSyntaxError("] expected after '->'.");
2333 } else if (token == TokenNameLPAREN) {
2336 if (token != TokenNameRPAREN) {
2337 throwSyntaxError(") expected after '->'.");
2340 } else if (token == TokenNameLBRACE) {
2343 if (token != TokenNameRBRACE) {
2344 throwSyntaxError("} expected after '->'.");
2350 case TokenNamePLUS_PLUS :
2353 case TokenNameMINUS_MINUS :
2359 } while (while_flag);
2361 private void unaryExpression() {
2363 case TokenNamePLUS_PLUS :
2367 case TokenNameMINUS_MINUS :
2371 // '@' '&' '*' '+' '-' '~' '!'
2374 if (token == TokenNameinclude || token == TokenNameinclude_once
2375 || token == TokenNamerequire || token == TokenNamerequire_once) {
2376 statement(TokenNameAT);
2378 expr_without_variable(); // castExpression();
2385 case TokenNameMULTIPLY :
2389 case TokenNamePLUS :
2393 case TokenNameMINUS :
2397 case TokenNameTWIDDLE :
2406 expr_without_variable();
2409 private void castExpression() {
2410 // if (token == TokenNameARGOPEN) {
2413 // if (token != TokenNameARGCLOSE) {
2414 // throwSyntaxError(") expected after cast-expression.");
2420 private void assignExpression() {
2422 if (token == TokenNameEQUAL) { // =
2424 logicalinclusiveorExpression();
2425 } else if (token == TokenNameDOT_EQUAL) { // .=
2427 logicalinclusiveorExpression();
2428 } else if (token == TokenNameEQUAL_GREATER) { // =>
2430 logicalinclusiveorExpression();
2431 } else if (token == TokenNamePLUS_EQUAL) { // +=
2433 logicalinclusiveorExpression();
2434 } else if (token == TokenNameMINUS_EQUAL) { // -=
2436 logicalinclusiveorExpression();
2437 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2439 logicalinclusiveorExpression();
2440 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2442 logicalinclusiveorExpression();
2443 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2445 logicalinclusiveorExpression();
2446 } else if (token == TokenNameAND_EQUAL) { // &=
2448 logicalinclusiveorExpression();
2449 } else if (token == TokenNameOR_EQUAL) { // |=
2451 logicalinclusiveorExpression();
2452 } else if (token == TokenNameXOR_EQUAL) { // ^=
2454 logicalinclusiveorExpression();
2455 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2457 logicalinclusiveorExpression();
2458 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2460 logicalinclusiveorExpression();
2461 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2463 logicalinclusiveorExpression();
2466 private void multiplicativeExpression() {
2469 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE
2470 && token != TokenNameREMAINDER) {
2476 private void concatenationExpression() {
2478 multiplicativeExpression();
2479 if (token != TokenNameDOT) {
2485 private void additiveExpression() {
2487 concatenationExpression();
2488 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2494 private void shiftExpression() {
2496 additiveExpression();
2497 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2503 private void relationalExpression() {
2506 if (token != TokenNameLESS && token != TokenNameGREATER
2507 && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2513 private void identicalExpression() {
2515 relationalExpression();
2516 if (token != TokenNameEQUAL_EQUAL_EQUAL
2517 && token != TokenNameNOT_EQUAL_EQUAL) {
2523 private void equalityExpression() {
2525 identicalExpression();
2526 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2532 private void ternaryExpression() {
2533 equalityExpression();
2534 if (token == TokenNameQUESTION) {
2537 if (token == TokenNameCOLON) {
2541 throwSyntaxError("':' expected in ternary operator '? :'.");
2545 private void andExpression() {
2547 ternaryExpression();
2548 if (token != TokenNameAND) {
2554 private void exclusiveorExpression() {
2557 if (token != TokenNameXOR) {
2563 private void inclusiveorExpression() {
2565 exclusiveorExpression();
2566 if (token != TokenNameOR) {
2572 private void booleanandExpression() {
2574 inclusiveorExpression();
2575 if (token != TokenNameAND_AND) {
2581 private void booleanorExpression() {
2583 booleanandExpression();
2584 if (token != TokenNameOR_OR) {
2590 private void logicalandExpression() {
2592 booleanorExpression();
2593 if (token != TokenNameAND) {
2599 private void logicalexclusiveorExpression() {
2601 logicalandExpression();
2602 if (token != TokenNameXOR) {
2608 private void logicalinclusiveorExpression() {
2610 logicalexclusiveorExpression();
2611 if (token != TokenNameOR) {
2617 // public void assignmentExpression() {
2618 // if (token == TokenNameVARIABLE) {
2620 // if (token == TokenNameSET) {
2622 // logicalinclusiveorExpression();
2625 // logicalinclusiveorExpression();
2628 private void variableList() {
2631 if (token == TokenNameCOMMA) {
2638 private void variable() {
2639 if (token == TokenNameDOLLAR_LBRACE) {
2643 if (token != TokenNameRBRACE) {
2644 throwSyntaxError("'}' expected after indirect variable token '${'.");
2648 if (token == TokenNameVariable) {
2650 if (token == TokenNameLBRACKET) {
2653 if (token != TokenNameRBRACKET) {
2654 throwSyntaxError("']' expected in variable-list.");
2657 } else if (token == TokenNameEQUAL) {
2662 throwSyntaxError("$-variable expected in variable-list.");
2666 private void exit_expr() {
2670 if (token != TokenNameLPAREN) {
2674 if (token == TokenNameRPAREN) {
2679 if (token != TokenNameRPAREN) {
2680 throwSyntaxError("')' expected after keyword 'exit'");
2684 private void internal_functions_in_yacc() {
2686 case TokenNameisset :
2687 // T_ISSET '(' isset_variables ')'
2689 if (token != TokenNameLPAREN) {
2690 throwSyntaxError("'(' expected after keyword 'isset'");
2694 if (token != TokenNameRPAREN) {
2695 throwSyntaxError("')' expected after keyword 'isset'");
2699 case TokenNameempty :
2700 // T_EMPTY '(' variable ')'
2702 if (token != TokenNameLPAREN) {
2703 throwSyntaxError("'(' expected after keyword 'empty'");
2707 if (token != TokenNameRPAREN) {
2708 throwSyntaxError("')' expected after keyword 'empty'");
2712 case TokenNameinclude :
2717 case TokenNameinclude_once :
2718 // T_INCLUDE_ONCE expr
2722 case TokenNameeval :
2723 // T_EVAL '(' expr ')'
2725 if (token != TokenNameLPAREN) {
2726 throwSyntaxError("'(' expected after keyword 'eval'");
2730 if (token != TokenNameRPAREN) {
2731 throwSyntaxError("')' expected after keyword 'eval'");
2735 case TokenNamerequire :
2740 case TokenNamerequire_once :
2741 // T_REQUIRE_ONCE expr
2747 private void isset_variables() {
2749 // | isset_variables ','
2750 if (token == TokenNameRPAREN) {
2751 throwSyntaxError("Variable expected after keyword 'isset'");
2755 if (token == TokenNameCOMMA) {
2763 * It will look for a value (after a '=' for example) @
2765 private void constant() {
2768 case TokenNamePLUS :
2771 case TokenNameDoubleLiteral :
2774 case TokenNameIntegerLiteral :
2778 throwSyntaxError("Constant expected after '+' presign.");
2781 case TokenNameMINUS :
2784 case TokenNameDoubleLiteral :
2787 case TokenNameIntegerLiteral :
2791 throwSyntaxError("Constant expected after '-' presign.");
2794 case TokenNamenull :
2797 case TokenNamefalse :
2800 case TokenNametrue :
2803 case TokenNameIdentifier :
2804 // ident = identifier;
2805 char[] ident = scanner.getCurrentIdentifierSource();
2807 if (token == TokenNameLPAREN) {
2809 if (token != TokenNameRPAREN) {
2811 if (token != TokenNameRPAREN) {
2812 throwSyntaxError("')' expected after identifier '"
2813 + new String(ident) + "' in postfix-expression.");
2819 case TokenNameStringLiteral :
2822 case TokenNameStringConstant :
2825 case TokenNameStringInterpolated :
2828 case TokenNameDoubleLiteral :
2831 case TokenNameIntegerLiteral :
2835 throwSyntaxError("Constant expected.");
2838 public void reportSyntaxError() { //int act, int currentKind, int
2840 /* remember current scanner position */
2841 int startPos = scanner.startPosition;
2842 int currentPos = scanner.currentPosition;
2843 // String[] expectings;
2844 // String tokenName = name[symbol_index[currentKind]];
2845 //fetch all "accurate" possible terminals that could recover the error
2846 // int start, end = start = asi(stack[stateStackTop]);
2847 // while (asr[end] != 0)
2849 // int length = end - start;
2850 // expectings = new String[length];
2851 // if (length != 0) {
2852 // char[] indexes = new char[length];
2853 // System.arraycopy(asr, start, indexes, 0, length);
2854 // for (int i = 0; i < length; i++) {
2855 // expectings[i] = name[symbol_index[indexes[i]]];
2858 //if the pb is an EOF, try to tell the user that they are some
2859 // if (tokenName.equals(UNEXPECTED_EOF)) {
2860 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2861 // char[] tokenSource;
2863 // tokenSource = this.scanner.getCurrentTokenSource();
2864 // } catch (Exception e) {
2865 // tokenSource = new char[] {};
2867 // problemReporter().parseError(
2868 // this.scanner.startPosition,
2869 // this.scanner.currentPosition - 1,
2874 // } else { //the next test is HEAVILY grammar DEPENDENT.
2875 // if ((length == 14)
2876 // && (expectings[0] == "=") //$NON-NLS-1$
2877 // && (expectings[1] == "*=") //$NON-NLS-1$
2878 // && (expressionPtr > -1)) {
2879 // switch(currentKind) {
2880 // case TokenNameSEMICOLON:
2881 // case TokenNamePLUS:
2882 // case TokenNameMINUS:
2883 // case TokenNameDIVIDE:
2884 // case TokenNameREMAINDER:
2885 // case TokenNameMULTIPLY:
2886 // case TokenNameLEFT_SHIFT:
2887 // case TokenNameRIGHT_SHIFT:
2888 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
2889 // case TokenNameLESS:
2890 // case TokenNameGREATER:
2891 // case TokenNameLESS_EQUAL:
2892 // case TokenNameGREATER_EQUAL:
2893 // case TokenNameEQUAL_EQUAL:
2894 // case TokenNameNOT_EQUAL:
2895 // case TokenNameXOR:
2896 // case TokenNameAND:
2897 // case TokenNameOR:
2898 // case TokenNameOR_OR:
2899 // case TokenNameAND_AND:
2900 // // the ; is not the expected token ==> it ends a statement when an
2901 // expression is not ended
2902 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
2904 // case TokenNameRBRACE :
2905 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
2908 // char[] tokenSource;
2910 // tokenSource = this.scanner.getCurrentTokenSource();
2911 // } catch (Exception e) {
2912 // tokenSource = new char[] {};
2914 // problemReporter().parseError(
2915 // this.scanner.startPosition,
2916 // this.scanner.currentPosition - 1,
2920 // this.checkAndReportBracketAnomalies(problemReporter());
2925 tokenSource = this.scanner.getCurrentTokenSource();
2926 } catch (Exception e) {
2927 tokenSource = new char[]{};
2929 // problemReporter().parseError(
2930 // this.scanner.startPosition,
2931 // this.scanner.currentPosition - 1,
2935 this.checkAndReportBracketAnomalies(problemReporter());
2938 /* reset scanner where it was */
2939 scanner.startPosition = startPos;
2940 scanner.currentPosition = currentPos;
2942 public static final int RoundBracket = 0;
2943 public static final int SquareBracket = 1;
2944 public static final int CurlyBracket = 2;
2945 public static final int BracketKinds = 3;
2946 protected int[] nestedMethod; //the ptr is nestedType
2947 protected int nestedType, dimensions;
2949 final static int AstStackIncrement = 100;
2950 protected int astPtr;
2951 protected AstNode[] astStack = new AstNode[AstStackIncrement];
2952 protected int astLengthPtr;
2953 protected int[] astLengthStack;
2954 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
2955 public CompilationUnitDeclaration compilationUnit; /*
2956 * the result from parse()
2958 protected ReferenceContext referenceContext;
2959 protected ProblemReporter problemReporter;
2960 // protected CompilationResult compilationResult;
2962 * Returns this parser's problem reporter initialized with its reference
2963 * context. Also it is assumed that a problem is going to be reported, so
2964 * initializes the compilation result's line positions.
2966 public ProblemReporter problemReporter() {
2967 if (scanner.recordLineSeparator) {
2968 compilationUnit.compilationResult.lineSeparatorPositions = scanner
2971 problemReporter.referenceContext = referenceContext;
2972 return problemReporter;
2975 * Reconsider the entire source looking for inconsistencies in {} () []
2977 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
2978 scanner.wasAcr = false;
2979 boolean anomaliesDetected = false;
2981 char[] source = scanner.source;
2982 int[] leftCount = {0, 0, 0};
2983 int[] rightCount = {0, 0, 0};
2984 int[] depths = {0, 0, 0};
2985 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
2986 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
2987 int[][] rightPositions = new int[][]{new int[10], new int[10],
2989 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
2990 scanner.currentPosition = scanner.initialPosition; //starting
2992 // (first-zero-based
2994 while (scanner.currentPosition < scanner.eofPosition) { //loop for
2999 // ---------Consume white space and handles
3000 // startPosition---------
3001 boolean isWhiteSpace;
3003 scanner.startPosition = scanner.currentPosition;
3004 // if (((scanner.currentCharacter =
3005 // source[scanner.currentPosition++]) == '\\') &&
3006 // (source[scanner.currentPosition] == 'u')) {
3007 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3009 if (scanner.recordLineSeparator
3010 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3011 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3012 // only record line positions we have not
3014 scanner.pushLineSeparator();
3017 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3019 } while (isWhiteSpace
3020 && (scanner.currentPosition < scanner.eofPosition));
3021 // -------consume token until } is found---------
3022 switch (scanner.currentCharacter) {
3025 int index = leftCount[CurlyBracket]++;
3026 if (index == leftPositions[CurlyBracket].length) {
3027 System.arraycopy(leftPositions[CurlyBracket], 0,
3028 (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3031 .arraycopy(leftDepths[CurlyBracket], 0,
3032 (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3035 leftPositions[CurlyBracket][index] = scanner.startPosition;
3036 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3041 int index = rightCount[CurlyBracket]++;
3042 if (index == rightPositions[CurlyBracket].length) {
3043 System.arraycopy(rightPositions[CurlyBracket], 0,
3044 (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3046 System.arraycopy(rightDepths[CurlyBracket], 0,
3047 (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3050 rightPositions[CurlyBracket][index] = scanner.startPosition;
3051 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3056 int index = leftCount[RoundBracket]++;
3057 if (index == leftPositions[RoundBracket].length) {
3058 System.arraycopy(leftPositions[RoundBracket], 0,
3059 (leftPositions[RoundBracket] = new int[index * 2]), 0,
3062 .arraycopy(leftDepths[RoundBracket], 0,
3063 (leftDepths[RoundBracket] = new int[index * 2]), 0,
3066 leftPositions[RoundBracket][index] = scanner.startPosition;
3067 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3072 int index = rightCount[RoundBracket]++;
3073 if (index == rightPositions[RoundBracket].length) {
3074 System.arraycopy(rightPositions[RoundBracket], 0,
3075 (rightPositions[RoundBracket] = new int[index * 2]), 0,
3077 System.arraycopy(rightDepths[RoundBracket], 0,
3078 (rightDepths[RoundBracket] = new int[index * 2]), 0,
3081 rightPositions[RoundBracket][index] = scanner.startPosition;
3082 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3087 int index = leftCount[SquareBracket]++;
3088 if (index == leftPositions[SquareBracket].length) {
3089 System.arraycopy(leftPositions[SquareBracket], 0,
3090 (leftPositions[SquareBracket] = new int[index * 2]), 0,
3092 System.arraycopy(leftDepths[SquareBracket], 0,
3093 (leftDepths[SquareBracket] = new int[index * 2]), 0,
3096 leftPositions[SquareBracket][index] = scanner.startPosition;
3097 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3102 int index = rightCount[SquareBracket]++;
3103 if (index == rightPositions[SquareBracket].length) {
3104 System.arraycopy(rightPositions[SquareBracket], 0,
3105 (rightPositions[SquareBracket] = new int[index * 2]), 0,
3107 System.arraycopy(rightDepths[SquareBracket], 0,
3108 (rightDepths[SquareBracket] = new int[index * 2]), 0,
3111 rightPositions[SquareBracket][index] = scanner.startPosition;
3112 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3117 if (scanner.getNextChar('\\')) {
3118 scanner.scanEscapeCharacter();
3119 } else { // consume next character
3120 scanner.unicodeAsBackSlash = false;
3121 // if (((scanner.currentCharacter =
3122 // source[scanner.currentPosition++]) ==
3124 // (source[scanner.currentPosition] ==
3126 // scanner.getNextUnicodeChar();
3128 if (scanner.withoutUnicodePtr != 0) {
3129 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3133 scanner.getNextChar('\'');
3137 // consume next character
3138 scanner.unicodeAsBackSlash = false;
3139 // if (((scanner.currentCharacter =
3140 // source[scanner.currentPosition++]) == '\\') &&
3141 // (source[scanner.currentPosition] == 'u')) {
3142 // scanner.getNextUnicodeChar();
3144 if (scanner.withoutUnicodePtr != 0) {
3145 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3148 while (scanner.currentCharacter != '"') {
3149 if (scanner.currentCharacter == '\r') {
3150 if (source[scanner.currentPosition] == '\n')
3151 scanner.currentPosition++;
3152 break; // the string cannot go further that
3155 if (scanner.currentCharacter == '\n') {
3156 break; // the string cannot go further that
3159 if (scanner.currentCharacter == '\\') {
3160 scanner.scanEscapeCharacter();
3162 // consume next character
3163 scanner.unicodeAsBackSlash = false;
3164 // if (((scanner.currentCharacter =
3165 // source[scanner.currentPosition++]) == '\\')
3166 // && (source[scanner.currentPosition] == 'u'))
3168 // scanner.getNextUnicodeChar();
3170 if (scanner.withoutUnicodePtr != 0) {
3171 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3179 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3182 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3183 && (source[scanner.currentPosition] == 'u')) {
3184 //-------------unicode traitement
3186 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3187 scanner.currentPosition++;
3188 while (source[scanner.currentPosition] == 'u') {
3189 scanner.currentPosition++;
3192 .getNumericValue(source[scanner.currentPosition++])) > 15
3195 .getNumericValue(source[scanner.currentPosition++])) > 15
3198 .getNumericValue(source[scanner.currentPosition++])) > 15
3201 .getNumericValue(source[scanner.currentPosition++])) > 15
3202 || c4 < 0) { //error don't
3205 scanner.currentCharacter = 'A';
3206 } //something different from \n and \r
3208 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3211 while (scanner.currentCharacter != '\r'
3212 && scanner.currentCharacter != '\n') {
3214 scanner.startPosition = scanner.currentPosition;
3215 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3216 && (source[scanner.currentPosition] == 'u')) {
3217 //-------------unicode traitement
3219 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3220 scanner.currentPosition++;
3221 while (source[scanner.currentPosition] == 'u') {
3222 scanner.currentPosition++;
3225 .getNumericValue(source[scanner.currentPosition++])) > 15
3228 .getNumericValue(source[scanner.currentPosition++])) > 15
3231 .getNumericValue(source[scanner.currentPosition++])) > 15
3234 .getNumericValue(source[scanner.currentPosition++])) > 15
3235 || c4 < 0) { //error don't
3238 scanner.currentCharacter = 'A';
3239 } //something different from \n
3242 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3246 if (scanner.recordLineSeparator
3247 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3248 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3249 // only record line positions we
3250 // have not recorded yet
3251 scanner.pushLineSeparator();
3252 if (this.scanner.taskTags != null) {
3253 this.scanner.checkTaskTag(this.scanner
3254 .getCurrentTokenStartPosition(), this.scanner
3255 .getCurrentTokenEndPosition());
3261 if (test > 0) { //traditional and annotation
3263 boolean star = false;
3264 // consume next character
3265 scanner.unicodeAsBackSlash = false;
3266 // if (((scanner.currentCharacter =
3267 // source[scanner.currentPosition++]) ==
3269 // (source[scanner.currentPosition] ==
3271 // scanner.getNextUnicodeChar();
3273 if (scanner.withoutUnicodePtr != 0) {
3274 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3277 if (scanner.currentCharacter == '*') {
3281 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3282 && (source[scanner.currentPosition] == 'u')) {
3283 //-------------unicode traitement
3285 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3286 scanner.currentPosition++;
3287 while (source[scanner.currentPosition] == 'u') {
3288 scanner.currentPosition++;
3291 .getNumericValue(source[scanner.currentPosition++])) > 15
3294 .getNumericValue(source[scanner.currentPosition++])) > 15
3297 .getNumericValue(source[scanner.currentPosition++])) > 15
3300 .getNumericValue(source[scanner.currentPosition++])) > 15
3301 || c4 < 0) { //error don't
3304 scanner.currentCharacter = 'A';
3305 } //something different from * and /
3307 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3310 //loop until end of comment */
3311 while ((scanner.currentCharacter != '/') || (!star)) {
3312 star = scanner.currentCharacter == '*';
3314 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3315 && (source[scanner.currentPosition] == 'u')) {
3316 //-------------unicode traitement
3318 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3319 scanner.currentPosition++;
3320 while (source[scanner.currentPosition] == 'u') {
3321 scanner.currentPosition++;
3324 .getNumericValue(source[scanner.currentPosition++])) > 15
3327 .getNumericValue(source[scanner.currentPosition++])) > 15
3330 .getNumericValue(source[scanner.currentPosition++])) > 15
3333 .getNumericValue(source[scanner.currentPosition++])) > 15
3334 || c4 < 0) { //error don't
3337 scanner.currentCharacter = 'A';
3338 } //something different from * and
3341 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3345 if (this.scanner.taskTags != null) {
3346 this.scanner.checkTaskTag(this.scanner
3347 .getCurrentTokenStartPosition(), this.scanner
3348 .getCurrentTokenEndPosition());
3355 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3356 scanner.scanIdentifierOrKeyword(false);
3359 if (Character.isDigit(scanner.currentCharacter)) {
3360 scanner.scanNumber(false);
3364 //-----------------end switch while
3365 // try--------------------
3366 } catch (IndexOutOfBoundsException e) {
3367 break; // read until EOF
3368 } catch (InvalidInputException e) {
3369 return false; // no clue
3372 if (scanner.recordLineSeparator) {
3373 // compilationUnit.compilationResult.lineSeparatorPositions =
3374 // scanner.getLineEnds();
3376 // check placement anomalies against other kinds of brackets
3377 for (int kind = 0; kind < BracketKinds; kind++) {
3378 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3379 int start = leftPositions[kind][leftIndex]; // deepest
3381 // find matching closing bracket
3382 int depth = leftDepths[kind][leftIndex];
3384 for (int i = 0; i < rightCount[kind]; i++) {
3385 int pos = rightPositions[kind][i];
3386 // want matching bracket further in source with same
3388 if ((pos > start) && (depth == rightDepths[kind][i])) {
3393 if (end < 0) { // did not find a good closing match
3394 problemReporter.unmatchedBracket(start, referenceContext,
3395 compilationUnit.compilationResult);
3398 // check if even number of opening/closing other brackets
3399 // in between this pair of brackets
3401 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3402 for (int i = 0; i < leftCount[otherKind]; i++) {
3403 int pos = leftPositions[otherKind][i];
3404 if ((pos > start) && (pos < end))
3407 for (int i = 0; i < rightCount[otherKind]; i++) {
3408 int pos = rightPositions[otherKind][i];
3409 if ((pos > start) && (pos < end))
3413 problemReporter.unmatchedBracket(start, referenceContext,
3414 compilationUnit.compilationResult); //bracket
3420 // too many opening brackets ?
3421 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3422 anomaliesDetected = true;
3423 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3424 - i - 1], referenceContext, compilationUnit.compilationResult);
3426 // too many closing brackets ?
3427 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3428 anomaliesDetected = true;
3429 problemReporter.unmatchedBracket(rightPositions[kind][i],
3430 referenceContext, compilationUnit.compilationResult);
3432 if (anomaliesDetected)
3435 return anomaliesDetected;
3436 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3437 return anomaliesDetected;
3438 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3439 return anomaliesDetected;
3442 protected void pushOnAstLengthStack(int pos) {
3444 astLengthStack[++astLengthPtr] = pos;
3445 } catch (IndexOutOfBoundsException e) {
3446 int oldStackLength = astLengthStack.length;
3447 int[] oldPos = astLengthStack;
3448 astLengthStack = new int[oldStackLength + StackIncrement];
3449 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3450 astLengthStack[astLengthPtr] = pos;
3453 protected void pushOnAstStack(AstNode node) {
3455 * add a new obj on top of the ast stack
3458 astStack[++astPtr] = node;
3459 } catch (IndexOutOfBoundsException e) {
3460 int oldStackLength = astStack.length;
3461 AstNode[] oldStack = astStack;
3462 astStack = new AstNode[oldStackLength + AstStackIncrement];
3463 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3464 astPtr = oldStackLength;
3465 astStack[astPtr] = node;
3468 astLengthStack[++astLengthPtr] = 1;
3469 } catch (IndexOutOfBoundsException e) {
3470 int oldStackLength = astLengthStack.length;
3471 int[] oldPos = astLengthStack;
3472 astLengthStack = new int[oldStackLength + AstStackIncrement];
3473 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3474 astLengthStack[astLengthPtr] = 1;