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 == TokenNamefinal) {
1426 checkAndSetModifiers(AccAbstract);
1428 if (token != TokenNameclass) {
1429 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1432 } else if (token == TokenNamefinal) {
1433 checkAndSetModifiers(AccFinal);
1434 if (token != TokenNameclass) {
1435 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1440 private void interface_extends_list() {
1442 // | T_EXTENDS interface_list
1443 if (token == TokenNameextends) {
1448 private void implements_list() {
1450 // | T_IMPLEMENTS interface_list
1451 if (token == TokenNameimplements) {
1456 private void interface_list() {
1458 // fully_qualified_class_name
1459 //| interface_list ',' fully_qualified_class_name
1461 if (token == TokenNameIdentifier) {
1464 throwSyntaxError("Interface name expected after keyword 'implements'.");
1466 if (token != TokenNameCOMMA) {
1472 // private void classBody(TypeDeclaration typeDecl) {
1473 // //'{' [class-element-list] '}'
1474 // if (token == TokenNameLBRACE) {
1476 // if (token != TokenNameRBRACE) {
1477 // class_statement_list();
1479 // if (token == TokenNameRBRACE) {
1480 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1483 // throwSyntaxError("'}' expected at end of class body.");
1486 // throwSyntaxError("'{' expected at start of class body.");
1489 private void class_statement_list() {
1492 } while (token == TokenNamefunction || token == TokenNamevar);
1494 private void class_statement() {
1496 // variable_modifiers class_variable_declaration ';'
1497 // | class_constant_declaration ';'
1498 // | method_modifiers T_FUNCTION is_reference T_STRING
1499 // '(' parameter_list ')' method_body
1500 initializeModifiers();
1501 if (token == TokenNamevar) {
1502 checkAndSetModifiers(AccPublic);
1504 "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected' modifier for field declarations.",
1505 scanner.getCurrentTokenStartPosition(), scanner
1506 .getCurrentTokenEndPosition());
1510 boolean hasModifiers = member_modifiers();
1511 if (token == TokenNamefunction) {
1512 if (!hasModifiers) {
1513 checkAndSetModifiers(AccPublic);
1515 MethodDeclaration methodDecl = new MethodDeclaration(
1516 this.compilationUnit.compilationResult);
1517 methodDecl.declarationSourceStart = scanner
1518 .getCurrentTokenStartPosition();
1519 methodDecl.modifiers = this.modifiers;
1521 functionDefinition(methodDecl);
1523 if (!hasModifiers) {
1524 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1529 // if (token == TokenNamefunction) {
1530 // MethodDeclaration methodDecl = new MethodDeclaration(
1531 // this.compilationUnit.compilationResult);
1532 // methodDecl.declarationSourceStart = scanner
1533 // .getCurrentTokenStartPosition();
1535 // functionDefinition(methodDecl);
1536 // } else if (token == TokenNamevar) {
1540 // throwSyntaxError("'function' or 'var' expected.");
1543 // private void variable_modifiers() {
1544 // // variable_modifiers:
1545 // // non_empty_member_modifiers
1547 // initializeModifiers();
1548 // if (token == TokenNamevar) {
1549 // checkAndSetModifiers(AccPublic);
1550 // reportSyntaxError(
1551 // "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
1552 // modifier for field declarations.",
1553 // scanner.getCurrentTokenStartPosition(), scanner
1554 // .getCurrentTokenEndPosition());
1557 // if (!member_modifiers()) {
1558 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1559 // field declarations.");
1563 // private void method_modifiers() {
1564 // //method_modifiers:
1566 // //| non_empty_member_modifiers
1567 // initializeModifiers();
1568 // if (!member_modifiers()) {
1569 // checkAndSetModifiers(AccPublic);
1572 private boolean member_modifiers() {
1579 boolean foundToken = false;
1581 if (token == TokenNamepublic) {
1582 checkAndSetModifiers(AccPublic);
1585 } else if (token == TokenNameprotected) {
1586 checkAndSetModifiers(AccProtected);
1589 } else if (token == TokenNameprivate) {
1590 checkAndSetModifiers(AccPrivate);
1593 } else if (token == TokenNamestatic) {
1594 checkAndSetModifiers(AccStatic);
1597 } else if (token == TokenNameabstract) {
1598 checkAndSetModifiers(AccAbstract);
1601 } else if (token == TokenNamefinal) {
1602 checkAndSetModifiers(AccFinal);
1611 private void classProperty() {
1612 //'var' variable ';'
1613 //'var' variable '=' constant ';'
1615 if (token == TokenNameVariable) {
1617 if (token == TokenNameEQUAL) {
1622 if (token == TokenNamethis) {
1623 throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1625 throwSyntaxError("Variable expected after keyword 'var'.");
1627 if (token != TokenNameCOMMA) {
1632 if (token == TokenNameSEMICOLON) {
1635 throwSyntaxError("';' expected after variable declaration.");
1638 private void functionDefinition(MethodDeclaration methodDecl) {
1640 compilationUnit.types.add(methodDecl);
1642 AstNode node = astStack[astPtr];
1643 if (node instanceof TypeDeclaration) {
1644 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1645 if (typeDecl.methods == null) {
1646 typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1648 AbstractMethodDeclaration[] newMethods;
1653 newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1654 1, typeDecl.methods.length);
1655 newMethods[0] = methodDecl;
1656 typeDecl.methods = newMethods;
1660 functionDeclarator(methodDecl);
1661 functionBody(methodDecl);
1663 private void functionDeclarator(MethodDeclaration methodDecl) {
1664 //identifier '(' [parameter-list] ')'
1665 if (token == TokenNameAND) {
1668 if (token == TokenNameIdentifier) {
1669 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1670 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1671 methodDecl.selector = scanner.getCurrentIdentifierSource();
1673 if (token == TokenNameLPAREN) {
1676 throwSyntaxError("'(' expected in function declaration.");
1678 if (token != TokenNameRPAREN) {
1681 if (token != TokenNameRPAREN) {
1682 throwSyntaxError("')' expected in function declaration.");
1684 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1688 if (token > TokenNameKEYWORD) {
1689 throwSyntaxError("Don't use keyword for function declaration [" + token
1692 throwSyntaxError("Function name expected after keyword 'function'.");
1696 private void parameterList() {
1697 //parameter-declaration
1698 //parameter-list ',' parameter-declaration
1700 parameterDeclaration();
1701 if (token != TokenNameCOMMA) {
1707 private void parameterDeclaration() {
1709 //variable-reference
1710 if (token == TokenNameAND) {
1715 throwSyntaxError("Variable expected after reference operator '&'.");
1718 //variable '=' constant
1719 if (token == TokenNameVariable) {
1721 if (token == TokenNameEQUAL) {
1727 if (token == TokenNamethis) {
1728 throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1731 private void labeledStatementList() {
1732 if (token != TokenNamecase && token != TokenNamedefault) {
1733 throwSyntaxError("'case' or 'default' expected.");
1736 if (token == TokenNamecase) {
1738 expr(); //constant();
1739 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1741 if (token == TokenNamecase || token == TokenNamedefault) { // empty
1749 // else if (token == TokenNameSEMICOLON) {
1751 // "':' expected after 'case' keyword (Found token: " +
1752 // scanner.toStringAction(token) + ")",
1753 // scanner.getCurrentTokenStartPosition(),
1754 // scanner.getCurrentTokenEndPosition(),
1757 // if (token == TokenNamecase) { // empty case statement ?
1763 throwSyntaxError("':' character after 'case' constant expected (Found token: "
1764 + scanner.toStringAction(token) + ")");
1766 } else { // TokenNamedefault
1768 if (token == TokenNameCOLON) {
1772 throwSyntaxError("':' character after 'default' expected.");
1775 } while (token == TokenNamecase || token == TokenNamedefault);
1777 // public void labeledStatement() {
1778 // if (token == TokenNamecase) {
1781 // if (token == TokenNameDDOT) {
1785 // throwSyntaxError("':' character after 'case' constant expected.");
1788 // } else if (token == TokenNamedefault) {
1790 // if (token == TokenNameDDOT) {
1794 // throwSyntaxError("':' character after 'default' expected.");
1799 // public void expressionStatement() {
1801 // private void inclusionStatement() {
1803 // public void compoundStatement() {
1805 // public void selectionStatement() {
1808 // public void iterationStatement() {
1811 // public void jumpStatement() {
1814 // public void outputStatement() {
1817 // public void scopeStatement() {
1820 // public void flowStatement() {
1823 // public void definitionStatement() {
1825 private void ifStatement() {
1826 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1827 if (token == TokenNameCOLON) {
1829 if (token != TokenNameendif) {
1832 case TokenNameelse :
1834 if (token == TokenNameCOLON) {
1836 if (token != TokenNameendif) {
1840 if (token == TokenNameif) { //'else if'
1842 elseifStatementList();
1844 throwSyntaxError("':' expected after 'else'.");
1848 case TokenNameelseif :
1850 elseifStatementList();
1854 if (token != TokenNameendif) {
1855 throwSyntaxError("'endif' expected.");
1858 if (token != TokenNameSEMICOLON) {
1859 throwSyntaxError("';' expected after if-statement.");
1863 // statement [else-statement]
1864 statement(TokenNameEOF);
1865 if (token == TokenNameelseif) {
1867 if (token == TokenNameLPAREN) {
1870 throwSyntaxError("'(' expected after 'elseif' keyword.");
1873 if (token == TokenNameRPAREN) {
1876 throwSyntaxError("')' expected after 'elseif' condition.");
1879 } else if (token == TokenNameelse) {
1881 statement(TokenNameEOF);
1885 private void elseifStatementList() {
1889 case TokenNameelse :
1891 if (token == TokenNameCOLON) {
1893 if (token != TokenNameendif) {
1898 if (token == TokenNameif) { //'else if'
1901 throwSyntaxError("':' expected after 'else'.");
1905 case TokenNameelseif :
1913 private void elseifStatement() {
1914 if (token == TokenNameLPAREN) {
1917 if (token != TokenNameRPAREN) {
1918 throwSyntaxError("')' expected in else-if-statement.");
1921 if (token != TokenNameCOLON) {
1922 throwSyntaxError("':' expected in else-if-statement.");
1925 if (token != TokenNameendif) {
1930 private void switchStatement() {
1931 if (token == TokenNameCOLON) {
1932 // ':' [labeled-statement-list] 'endswitch' ';'
1934 labeledStatementList();
1935 if (token != TokenNameendswitch) {
1936 throwSyntaxError("'endswitch' expected.");
1939 if (token != TokenNameSEMICOLON) {
1940 throwSyntaxError("';' expected after switch-statement.");
1944 // '{' [labeled-statement-list] '}'
1945 if (token != TokenNameLBRACE) {
1946 throwSyntaxError("'{' expected in switch statement.");
1949 if (token != TokenNameRBRACE) {
1950 labeledStatementList();
1952 if (token != TokenNameRBRACE) {
1953 throwSyntaxError("'}' expected in switch statement.");
1958 private void forStatement() {
1959 if (token == TokenNameCOLON) {
1962 if (token != TokenNameendfor) {
1963 throwSyntaxError("'endfor' expected.");
1966 if (token != TokenNameSEMICOLON) {
1967 throwSyntaxError("';' expected after for-statement.");
1971 statement(TokenNameEOF);
1974 private void whileStatement() {
1975 // ':' statement-list 'endwhile' ';'
1976 if (token == TokenNameCOLON) {
1979 if (token != TokenNameendwhile) {
1980 throwSyntaxError("'endwhile' expected.");
1983 if (token != TokenNameSEMICOLON) {
1984 throwSyntaxError("';' expected after while-statement.");
1988 statement(TokenNameEOF);
1991 private void foreachStatement() {
1992 if (token == TokenNameCOLON) {
1995 if (token != TokenNameendforeach) {
1996 throwSyntaxError("'endforeach' expected.");
1999 if (token != TokenNameSEMICOLON) {
2000 throwSyntaxError("';' expected after foreach-statement.");
2004 statement(TokenNameEOF);
2007 // private void exitStatus() {
2008 // if (token == TokenNameLPAREN) {
2011 // throwSyntaxError("'(' expected in 'exit-status'.");
2013 // if (token != TokenNameRPAREN) {
2016 // if (token == TokenNameRPAREN) {
2019 // throwSyntaxError("')' expected after 'exit-status'.");
2022 private void expressionList() {
2025 if (token == TokenNameCOMMA) {
2032 private void expr() {
2033 //todo: find a better way to get the expression
2034 // expression = new StringBuffer();
2035 // for (int i = chIndx; i < str.length(); i++) {
2036 // if (str.charAt(i) == ';') {
2039 // expression.append(str.charAt(i));
2041 // if (token == TokenNameSTRING_CONSTANT || token ==
2042 // TokenNameINTERPOLATED_STRING) {
2045 logicalinclusiveorExpression();
2046 // while (token != TokenNameSEMICOLON) {
2051 private void expr_without_variable() {
2054 boolean castFlag = false;
2055 boolean arrayFlag = false;
2057 case TokenNameisset :
2058 case TokenNameempty :
2059 case TokenNameeval :
2060 case TokenNameinclude :
2061 case TokenNameinclude_once :
2062 case TokenNamerequire :
2063 case TokenNamerequire_once :
2064 internal_functions_in_yacc();
2070 case TokenNamenull :
2073 case TokenNamefalse :
2076 case TokenNametrue :
2079 case TokenNameStringConstant :
2082 case TokenNameHEREDOC :
2083 case TokenNameStringInterpolated :
2084 case TokenNameStringLiteral :
2087 case TokenNameLPAREN :
2089 if (token == TokenNameIdentifier) {
2090 // check if identifier is a type:
2091 // ident = identifier;
2092 ident = scanner.getCurrentIdentifierSource();
2093 String str = new String(ident).toLowerCase();
2094 for (int i = 0; i < PHP_TYPES.length; i++) {
2095 if (PHP_TYPES[i].equals(str)) {
2097 if (PHP_TYPES[i].equals("array")) {
2106 if (arrayFlag && token == TokenNameLPAREN) {
2108 if (token == TokenNameRPAREN) {
2112 if (token != TokenNameRPAREN) {
2113 throwSyntaxError(") expected after 'array('.");
2117 if (token != TokenNameRPAREN) {
2118 throwSyntaxError(") expected after cast-type '" + str + "'.");
2126 if (token != TokenNameRPAREN) {
2127 throwSyntaxError(") expected in postfix-expression.");
2131 case TokenNameDoubleLiteral :
2134 case TokenNameIntegerLiteral :
2137 case TokenNameDOLLAR_LBRACE :
2140 if (token != TokenNameRBRACE) {
2141 throwSyntaxError("'}' expected after indirect variable token '${'.");
2145 case TokenNameVariable :
2146 case TokenNamethis :
2147 ident = scanner.getCurrentIdentifierSource();
2149 if (token == TokenNameLBRACE) {
2152 if (token != TokenNameRBRACE) {
2153 throwSyntaxError("'}' expected after variable '"
2154 + new String(ident) + "' in variable-expression.");
2157 } else if (token == TokenNameLPAREN) {
2159 if (token != TokenNameRPAREN) {
2161 if (token != TokenNameRPAREN) {
2162 throwSyntaxError("')' expected after variable '"
2163 + new String(ident) + "' in postfix-expression.");
2169 case TokenNameIdentifier :
2170 ident = scanner.getCurrentIdentifierSource();
2172 if (token == TokenNameLPAREN) {
2174 if (token != TokenNameRPAREN) {
2176 if (token != TokenNameRPAREN) {
2177 throwSyntaxError("')' expected after identifier '"
2178 + new String(ident) + "' in postfix-expression."
2179 + "(Found token: " + scanner.toStringAction(token) + ")");
2185 case TokenNameprint :
2189 case TokenNameexit :
2193 case TokenNamelist :
2195 if (token == TokenNameLPAREN) {
2197 if (token == TokenNameCOMMA) {
2201 if (token != TokenNameRPAREN) {
2202 throwSyntaxError("')' expected after 'list' keyword.");
2205 // if (token == TokenNameSET) {
2207 // logicalinclusiveorExpression();
2210 throwSyntaxError("'(' expected after 'list' keyword.");
2213 // case TokenNameexit :
2215 // if (token != TokenNameSEMICOLON) {
2218 // if (token == TokenNameSEMICOLON) {
2221 // if (token != TokenNameStopPHP) {
2222 // throwSyntaxError("';' expected after 'exit' expression.");
2227 // case TokenNamedie :
2229 // if (token != TokenNameSEMICOLON) {
2232 // if (token == TokenNameSEMICOLON) {
2235 // if (token != TokenNameStopPHP) {
2236 // throwSyntaxError("';' expected after 'die' expression.");
2240 // case TokenNamearray :
2242 // if (token == TokenNameARGOPEN) {
2244 // if (token == TokenNameCOMMA) {
2247 // expressionList();
2248 // if (token != TokenNameARGCLOSE) {
2249 // throwSyntaxError("')' expected after 'list' keyword.");
2252 // if (token == TokenNameSET) {
2254 // logicalinclusiveorExpression();
2257 // throwSyntaxError("'(' expected after 'list' keyword.");
2261 boolean while_flag = true;
2264 case TokenNameLBRACKET :
2267 if (token != TokenNameRBRACKET) {
2268 throwSyntaxError("] expected in postfix-expression.");
2272 case TokenNameCOLON_COLON :
2274 case TokenNameMINUS_GREATER :
2277 if (token > TokenNameKEYWORD) {
2278 ident = scanner.getCurrentIdentifierSource();
2280 // "Avoid using keyword '"
2281 // + new String(ident)
2282 // + "' as variable name.",
2286 // "Avoid using keyword '" + new String(ident) + "' as
2288 // scanner.getCurrentTokenStartPosition(),
2289 // scanner.getCurrentTokenEndPosition(),
2293 case TokenNameVariable :
2294 ident = scanner.getCurrentIdentifierSource();
2296 // if (token == TokenNameARGOPEN) {
2298 // expressionList();
2299 // if (token != TokenNameARGCLOSE) {
2300 // throwSyntaxError(") expected after variable '" +
2306 case TokenNameIdentifier :
2307 //ident = scanner.getCurrentIdentifierSource();
2310 case TokenNameLBRACE :
2313 if (token != TokenNameRBRACE) {
2314 throwSyntaxError("} expected in postfix-expression.");
2319 throwSyntaxError("Syntax error after '->' token.");
2321 while (token == TokenNameLBRACKET || token == TokenNameLPAREN
2322 || token == TokenNameLBRACE) {
2323 if (token == TokenNameLBRACKET) {
2326 if (token != TokenNameRBRACKET) {
2327 throwSyntaxError("] expected after '->'.");
2330 } else if (token == TokenNameLPAREN) {
2333 if (token != TokenNameRPAREN) {
2334 throwSyntaxError(") expected after '->'.");
2337 } else if (token == TokenNameLBRACE) {
2340 if (token != TokenNameRBRACE) {
2341 throwSyntaxError("} expected after '->'.");
2347 case TokenNamePLUS_PLUS :
2350 case TokenNameMINUS_MINUS :
2356 } while (while_flag);
2358 private void unaryExpression() {
2360 case TokenNamePLUS_PLUS :
2364 case TokenNameMINUS_MINUS :
2368 // '@' '&' '*' '+' '-' '~' '!'
2371 if (token == TokenNameinclude || token == TokenNameinclude_once
2372 || token == TokenNamerequire || token == TokenNamerequire_once) {
2373 statement(TokenNameAT);
2375 expr_without_variable(); // castExpression();
2382 case TokenNameMULTIPLY :
2386 case TokenNamePLUS :
2390 case TokenNameMINUS :
2394 case TokenNameTWIDDLE :
2403 expr_without_variable();
2406 private void castExpression() {
2407 // if (token == TokenNameARGOPEN) {
2410 // if (token != TokenNameARGCLOSE) {
2411 // throwSyntaxError(") expected after cast-expression.");
2417 private void assignExpression() {
2419 if (token == TokenNameEQUAL) { // =
2421 logicalinclusiveorExpression();
2422 } else if (token == TokenNameDOT_EQUAL) { // .=
2424 logicalinclusiveorExpression();
2425 } else if (token == TokenNameEQUAL_GREATER) { // =>
2427 logicalinclusiveorExpression();
2428 } else if (token == TokenNamePLUS_EQUAL) { // +=
2430 logicalinclusiveorExpression();
2431 } else if (token == TokenNameMINUS_EQUAL) { // -=
2433 logicalinclusiveorExpression();
2434 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2436 logicalinclusiveorExpression();
2437 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2439 logicalinclusiveorExpression();
2440 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2442 logicalinclusiveorExpression();
2443 } else if (token == TokenNameAND_EQUAL) { // &=
2445 logicalinclusiveorExpression();
2446 } else if (token == TokenNameOR_EQUAL) { // |=
2448 logicalinclusiveorExpression();
2449 } else if (token == TokenNameXOR_EQUAL) { // ^=
2451 logicalinclusiveorExpression();
2452 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2454 logicalinclusiveorExpression();
2455 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2457 logicalinclusiveorExpression();
2458 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2460 logicalinclusiveorExpression();
2463 private void multiplicativeExpression() {
2466 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE
2467 && token != TokenNameREMAINDER) {
2473 private void concatenationExpression() {
2475 multiplicativeExpression();
2476 if (token != TokenNameDOT) {
2482 private void additiveExpression() {
2484 concatenationExpression();
2485 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2491 private void shiftExpression() {
2493 additiveExpression();
2494 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2500 private void relationalExpression() {
2503 if (token != TokenNameLESS && token != TokenNameGREATER
2504 && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2510 private void identicalExpression() {
2512 relationalExpression();
2513 if (token != TokenNameEQUAL_EQUAL_EQUAL
2514 && token != TokenNameNOT_EQUAL_EQUAL) {
2520 private void equalityExpression() {
2522 identicalExpression();
2523 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2529 private void ternaryExpression() {
2530 equalityExpression();
2531 if (token == TokenNameQUESTION) {
2534 if (token == TokenNameCOLON) {
2538 throwSyntaxError("':' expected in ternary operator '? :'.");
2542 private void andExpression() {
2544 ternaryExpression();
2545 if (token != TokenNameAND) {
2551 private void exclusiveorExpression() {
2554 if (token != TokenNameXOR) {
2560 private void inclusiveorExpression() {
2562 exclusiveorExpression();
2563 if (token != TokenNameOR) {
2569 private void booleanandExpression() {
2571 inclusiveorExpression();
2572 if (token != TokenNameAND_AND) {
2578 private void booleanorExpression() {
2580 booleanandExpression();
2581 if (token != TokenNameOR_OR) {
2587 private void logicalandExpression() {
2589 booleanorExpression();
2590 if (token != TokenNameAND) {
2596 private void logicalexclusiveorExpression() {
2598 logicalandExpression();
2599 if (token != TokenNameXOR) {
2605 private void logicalinclusiveorExpression() {
2607 logicalexclusiveorExpression();
2608 if (token != TokenNameOR) {
2614 // public void assignmentExpression() {
2615 // if (token == TokenNameVARIABLE) {
2617 // if (token == TokenNameSET) {
2619 // logicalinclusiveorExpression();
2622 // logicalinclusiveorExpression();
2625 private void variableList() {
2628 if (token == TokenNameCOMMA) {
2635 private void variable() {
2636 if (token == TokenNameDOLLAR_LBRACE) {
2640 if (token != TokenNameRBRACE) {
2641 throwSyntaxError("'}' expected after indirect variable token '${'.");
2645 if (token == TokenNameVariable) {
2647 if (token == TokenNameLBRACKET) {
2650 if (token != TokenNameRBRACKET) {
2651 throwSyntaxError("']' expected in variable-list.");
2654 } else if (token == TokenNameEQUAL) {
2659 throwSyntaxError("$-variable expected in variable-list.");
2663 private void exit_expr() {
2667 if (token != TokenNameLPAREN) {
2671 if (token == TokenNameRPAREN) {
2676 if (token != TokenNameRPAREN) {
2677 throwSyntaxError("')' expected after keyword 'exit'");
2681 private void internal_functions_in_yacc() {
2683 case TokenNameisset :
2684 // T_ISSET '(' isset_variables ')'
2686 if (token != TokenNameLPAREN) {
2687 throwSyntaxError("'(' expected after keyword 'isset'");
2691 if (token != TokenNameRPAREN) {
2692 throwSyntaxError("')' expected after keyword 'isset'");
2696 case TokenNameempty :
2697 // T_EMPTY '(' variable ')'
2699 if (token != TokenNameLPAREN) {
2700 throwSyntaxError("'(' expected after keyword 'empty'");
2704 if (token != TokenNameRPAREN) {
2705 throwSyntaxError("')' expected after keyword 'empty'");
2709 case TokenNameinclude :
2714 case TokenNameinclude_once :
2715 // T_INCLUDE_ONCE expr
2719 case TokenNameeval :
2720 // T_EVAL '(' expr ')'
2722 if (token != TokenNameLPAREN) {
2723 throwSyntaxError("'(' expected after keyword 'eval'");
2727 if (token != TokenNameRPAREN) {
2728 throwSyntaxError("')' expected after keyword 'eval'");
2732 case TokenNamerequire :
2737 case TokenNamerequire_once :
2738 // T_REQUIRE_ONCE expr
2744 private void isset_variables() {
2746 // | isset_variables ','
2747 if (token == TokenNameRPAREN) {
2748 throwSyntaxError("Variable expected after keyword 'isset'");
2752 if (token == TokenNameCOMMA) {
2760 * It will look for a value (after a '=' for example) @
2762 private void constant() {
2765 case TokenNamePLUS :
2768 case TokenNameDoubleLiteral :
2771 case TokenNameIntegerLiteral :
2775 throwSyntaxError("Constant expected after '+' presign.");
2778 case TokenNameMINUS :
2781 case TokenNameDoubleLiteral :
2784 case TokenNameIntegerLiteral :
2788 throwSyntaxError("Constant expected after '-' presign.");
2791 case TokenNamenull :
2794 case TokenNamefalse :
2797 case TokenNametrue :
2800 case TokenNameIdentifier :
2801 // ident = identifier;
2802 char[] ident = scanner.getCurrentIdentifierSource();
2804 if (token == TokenNameLPAREN) {
2806 if (token != TokenNameRPAREN) {
2808 if (token != TokenNameRPAREN) {
2809 throwSyntaxError("')' expected after identifier '"
2810 + new String(ident) + "' in postfix-expression.");
2816 case TokenNameStringLiteral :
2819 case TokenNameStringConstant :
2822 case TokenNameStringInterpolated :
2825 case TokenNameDoubleLiteral :
2828 case TokenNameIntegerLiteral :
2832 throwSyntaxError("Constant expected.");
2835 public void reportSyntaxError() { //int act, int currentKind, int
2837 /* remember current scanner position */
2838 int startPos = scanner.startPosition;
2839 int currentPos = scanner.currentPosition;
2840 // String[] expectings;
2841 // String tokenName = name[symbol_index[currentKind]];
2842 //fetch all "accurate" possible terminals that could recover the error
2843 // int start, end = start = asi(stack[stateStackTop]);
2844 // while (asr[end] != 0)
2846 // int length = end - start;
2847 // expectings = new String[length];
2848 // if (length != 0) {
2849 // char[] indexes = new char[length];
2850 // System.arraycopy(asr, start, indexes, 0, length);
2851 // for (int i = 0; i < length; i++) {
2852 // expectings[i] = name[symbol_index[indexes[i]]];
2855 //if the pb is an EOF, try to tell the user that they are some
2856 // if (tokenName.equals(UNEXPECTED_EOF)) {
2857 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2858 // char[] tokenSource;
2860 // tokenSource = this.scanner.getCurrentTokenSource();
2861 // } catch (Exception e) {
2862 // tokenSource = new char[] {};
2864 // problemReporter().parseError(
2865 // this.scanner.startPosition,
2866 // this.scanner.currentPosition - 1,
2871 // } else { //the next test is HEAVILY grammar DEPENDENT.
2872 // if ((length == 14)
2873 // && (expectings[0] == "=") //$NON-NLS-1$
2874 // && (expectings[1] == "*=") //$NON-NLS-1$
2875 // && (expressionPtr > -1)) {
2876 // switch(currentKind) {
2877 // case TokenNameSEMICOLON:
2878 // case TokenNamePLUS:
2879 // case TokenNameMINUS:
2880 // case TokenNameDIVIDE:
2881 // case TokenNameREMAINDER:
2882 // case TokenNameMULTIPLY:
2883 // case TokenNameLEFT_SHIFT:
2884 // case TokenNameRIGHT_SHIFT:
2885 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
2886 // case TokenNameLESS:
2887 // case TokenNameGREATER:
2888 // case TokenNameLESS_EQUAL:
2889 // case TokenNameGREATER_EQUAL:
2890 // case TokenNameEQUAL_EQUAL:
2891 // case TokenNameNOT_EQUAL:
2892 // case TokenNameXOR:
2893 // case TokenNameAND:
2894 // case TokenNameOR:
2895 // case TokenNameOR_OR:
2896 // case TokenNameAND_AND:
2897 // // the ; is not the expected token ==> it ends a statement when an
2898 // expression is not ended
2899 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
2901 // case TokenNameRBRACE :
2902 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
2905 // char[] tokenSource;
2907 // tokenSource = this.scanner.getCurrentTokenSource();
2908 // } catch (Exception e) {
2909 // tokenSource = new char[] {};
2911 // problemReporter().parseError(
2912 // this.scanner.startPosition,
2913 // this.scanner.currentPosition - 1,
2917 // this.checkAndReportBracketAnomalies(problemReporter());
2922 tokenSource = this.scanner.getCurrentTokenSource();
2923 } catch (Exception e) {
2924 tokenSource = new char[]{};
2926 // problemReporter().parseError(
2927 // this.scanner.startPosition,
2928 // this.scanner.currentPosition - 1,
2932 this.checkAndReportBracketAnomalies(problemReporter());
2935 /* reset scanner where it was */
2936 scanner.startPosition = startPos;
2937 scanner.currentPosition = currentPos;
2939 public static final int RoundBracket = 0;
2940 public static final int SquareBracket = 1;
2941 public static final int CurlyBracket = 2;
2942 public static final int BracketKinds = 3;
2943 protected int[] nestedMethod; //the ptr is nestedType
2944 protected int nestedType, dimensions;
2946 final static int AstStackIncrement = 100;
2947 protected int astPtr;
2948 protected AstNode[] astStack = new AstNode[AstStackIncrement];
2949 protected int astLengthPtr;
2950 protected int[] astLengthStack;
2951 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
2952 public CompilationUnitDeclaration compilationUnit; /*
2953 * the result from parse()
2955 protected ReferenceContext referenceContext;
2956 protected ProblemReporter problemReporter;
2957 // protected CompilationResult compilationResult;
2959 * Returns this parser's problem reporter initialized with its reference
2960 * context. Also it is assumed that a problem is going to be reported, so
2961 * initializes the compilation result's line positions.
2963 public ProblemReporter problemReporter() {
2964 if (scanner.recordLineSeparator) {
2965 compilationUnit.compilationResult.lineSeparatorPositions = scanner
2968 problemReporter.referenceContext = referenceContext;
2969 return problemReporter;
2972 * Reconsider the entire source looking for inconsistencies in {} () []
2974 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
2975 scanner.wasAcr = false;
2976 boolean anomaliesDetected = false;
2978 char[] source = scanner.source;
2979 int[] leftCount = {0, 0, 0};
2980 int[] rightCount = {0, 0, 0};
2981 int[] depths = {0, 0, 0};
2982 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
2983 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
2984 int[][] rightPositions = new int[][]{new int[10], new int[10],
2986 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
2987 scanner.currentPosition = scanner.initialPosition; //starting
2989 // (first-zero-based
2991 while (scanner.currentPosition < scanner.eofPosition) { //loop for
2996 // ---------Consume white space and handles
2997 // startPosition---------
2998 boolean isWhiteSpace;
3000 scanner.startPosition = scanner.currentPosition;
3001 // if (((scanner.currentCharacter =
3002 // source[scanner.currentPosition++]) == '\\') &&
3003 // (source[scanner.currentPosition] == 'u')) {
3004 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3006 if (scanner.recordLineSeparator
3007 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3008 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3009 // only record line positions we have not
3011 scanner.pushLineSeparator();
3014 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3016 } while (isWhiteSpace
3017 && (scanner.currentPosition < scanner.eofPosition));
3018 // -------consume token until } is found---------
3019 switch (scanner.currentCharacter) {
3022 int index = leftCount[CurlyBracket]++;
3023 if (index == leftPositions[CurlyBracket].length) {
3024 System.arraycopy(leftPositions[CurlyBracket], 0,
3025 (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3028 .arraycopy(leftDepths[CurlyBracket], 0,
3029 (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3032 leftPositions[CurlyBracket][index] = scanner.startPosition;
3033 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3038 int index = rightCount[CurlyBracket]++;
3039 if (index == rightPositions[CurlyBracket].length) {
3040 System.arraycopy(rightPositions[CurlyBracket], 0,
3041 (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3043 System.arraycopy(rightDepths[CurlyBracket], 0,
3044 (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3047 rightPositions[CurlyBracket][index] = scanner.startPosition;
3048 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3053 int index = leftCount[RoundBracket]++;
3054 if (index == leftPositions[RoundBracket].length) {
3055 System.arraycopy(leftPositions[RoundBracket], 0,
3056 (leftPositions[RoundBracket] = new int[index * 2]), 0,
3059 .arraycopy(leftDepths[RoundBracket], 0,
3060 (leftDepths[RoundBracket] = new int[index * 2]), 0,
3063 leftPositions[RoundBracket][index] = scanner.startPosition;
3064 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3069 int index = rightCount[RoundBracket]++;
3070 if (index == rightPositions[RoundBracket].length) {
3071 System.arraycopy(rightPositions[RoundBracket], 0,
3072 (rightPositions[RoundBracket] = new int[index * 2]), 0,
3074 System.arraycopy(rightDepths[RoundBracket], 0,
3075 (rightDepths[RoundBracket] = new int[index * 2]), 0,
3078 rightPositions[RoundBracket][index] = scanner.startPosition;
3079 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3084 int index = leftCount[SquareBracket]++;
3085 if (index == leftPositions[SquareBracket].length) {
3086 System.arraycopy(leftPositions[SquareBracket], 0,
3087 (leftPositions[SquareBracket] = new int[index * 2]), 0,
3089 System.arraycopy(leftDepths[SquareBracket], 0,
3090 (leftDepths[SquareBracket] = new int[index * 2]), 0,
3093 leftPositions[SquareBracket][index] = scanner.startPosition;
3094 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3099 int index = rightCount[SquareBracket]++;
3100 if (index == rightPositions[SquareBracket].length) {
3101 System.arraycopy(rightPositions[SquareBracket], 0,
3102 (rightPositions[SquareBracket] = new int[index * 2]), 0,
3104 System.arraycopy(rightDepths[SquareBracket], 0,
3105 (rightDepths[SquareBracket] = new int[index * 2]), 0,
3108 rightPositions[SquareBracket][index] = scanner.startPosition;
3109 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3114 if (scanner.getNextChar('\\')) {
3115 scanner.scanEscapeCharacter();
3116 } else { // consume next character
3117 scanner.unicodeAsBackSlash = false;
3118 // if (((scanner.currentCharacter =
3119 // source[scanner.currentPosition++]) ==
3121 // (source[scanner.currentPosition] ==
3123 // scanner.getNextUnicodeChar();
3125 if (scanner.withoutUnicodePtr != 0) {
3126 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3130 scanner.getNextChar('\'');
3134 // consume next character
3135 scanner.unicodeAsBackSlash = false;
3136 // if (((scanner.currentCharacter =
3137 // source[scanner.currentPosition++]) == '\\') &&
3138 // (source[scanner.currentPosition] == 'u')) {
3139 // scanner.getNextUnicodeChar();
3141 if (scanner.withoutUnicodePtr != 0) {
3142 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3145 while (scanner.currentCharacter != '"') {
3146 if (scanner.currentCharacter == '\r') {
3147 if (source[scanner.currentPosition] == '\n')
3148 scanner.currentPosition++;
3149 break; // the string cannot go further that
3152 if (scanner.currentCharacter == '\n') {
3153 break; // the string cannot go further that
3156 if (scanner.currentCharacter == '\\') {
3157 scanner.scanEscapeCharacter();
3159 // consume next character
3160 scanner.unicodeAsBackSlash = false;
3161 // if (((scanner.currentCharacter =
3162 // source[scanner.currentPosition++]) == '\\')
3163 // && (source[scanner.currentPosition] == 'u'))
3165 // scanner.getNextUnicodeChar();
3167 if (scanner.withoutUnicodePtr != 0) {
3168 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3176 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3179 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3180 && (source[scanner.currentPosition] == 'u')) {
3181 //-------------unicode traitement
3183 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3184 scanner.currentPosition++;
3185 while (source[scanner.currentPosition] == 'u') {
3186 scanner.currentPosition++;
3189 .getNumericValue(source[scanner.currentPosition++])) > 15
3192 .getNumericValue(source[scanner.currentPosition++])) > 15
3195 .getNumericValue(source[scanner.currentPosition++])) > 15
3198 .getNumericValue(source[scanner.currentPosition++])) > 15
3199 || c4 < 0) { //error don't
3202 scanner.currentCharacter = 'A';
3203 } //something different from \n and \r
3205 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3208 while (scanner.currentCharacter != '\r'
3209 && scanner.currentCharacter != '\n') {
3211 scanner.startPosition = scanner.currentPosition;
3212 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3213 && (source[scanner.currentPosition] == 'u')) {
3214 //-------------unicode traitement
3216 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3217 scanner.currentPosition++;
3218 while (source[scanner.currentPosition] == 'u') {
3219 scanner.currentPosition++;
3222 .getNumericValue(source[scanner.currentPosition++])) > 15
3225 .getNumericValue(source[scanner.currentPosition++])) > 15
3228 .getNumericValue(source[scanner.currentPosition++])) > 15
3231 .getNumericValue(source[scanner.currentPosition++])) > 15
3232 || c4 < 0) { //error don't
3235 scanner.currentCharacter = 'A';
3236 } //something different from \n
3239 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3243 if (scanner.recordLineSeparator
3244 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3245 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3246 // only record line positions we
3247 // have not recorded yet
3248 scanner.pushLineSeparator();
3249 if (this.scanner.taskTags != null) {
3250 this.scanner.checkTaskTag(this.scanner
3251 .getCurrentTokenStartPosition(), this.scanner
3252 .getCurrentTokenEndPosition());
3258 if (test > 0) { //traditional and annotation
3260 boolean star = false;
3261 // consume next character
3262 scanner.unicodeAsBackSlash = false;
3263 // if (((scanner.currentCharacter =
3264 // source[scanner.currentPosition++]) ==
3266 // (source[scanner.currentPosition] ==
3268 // scanner.getNextUnicodeChar();
3270 if (scanner.withoutUnicodePtr != 0) {
3271 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3274 if (scanner.currentCharacter == '*') {
3278 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3279 && (source[scanner.currentPosition] == 'u')) {
3280 //-------------unicode traitement
3282 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3283 scanner.currentPosition++;
3284 while (source[scanner.currentPosition] == 'u') {
3285 scanner.currentPosition++;
3288 .getNumericValue(source[scanner.currentPosition++])) > 15
3291 .getNumericValue(source[scanner.currentPosition++])) > 15
3294 .getNumericValue(source[scanner.currentPosition++])) > 15
3297 .getNumericValue(source[scanner.currentPosition++])) > 15
3298 || c4 < 0) { //error don't
3301 scanner.currentCharacter = 'A';
3302 } //something different from * and /
3304 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3307 //loop until end of comment */
3308 while ((scanner.currentCharacter != '/') || (!star)) {
3309 star = scanner.currentCharacter == '*';
3311 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3312 && (source[scanner.currentPosition] == 'u')) {
3313 //-------------unicode traitement
3315 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3316 scanner.currentPosition++;
3317 while (source[scanner.currentPosition] == 'u') {
3318 scanner.currentPosition++;
3321 .getNumericValue(source[scanner.currentPosition++])) > 15
3324 .getNumericValue(source[scanner.currentPosition++])) > 15
3327 .getNumericValue(source[scanner.currentPosition++])) > 15
3330 .getNumericValue(source[scanner.currentPosition++])) > 15
3331 || c4 < 0) { //error don't
3334 scanner.currentCharacter = 'A';
3335 } //something different from * and
3338 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3342 if (this.scanner.taskTags != null) {
3343 this.scanner.checkTaskTag(this.scanner
3344 .getCurrentTokenStartPosition(), this.scanner
3345 .getCurrentTokenEndPosition());
3352 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3353 scanner.scanIdentifierOrKeyword(false);
3356 if (Character.isDigit(scanner.currentCharacter)) {
3357 scanner.scanNumber(false);
3361 //-----------------end switch while
3362 // try--------------------
3363 } catch (IndexOutOfBoundsException e) {
3364 break; // read until EOF
3365 } catch (InvalidInputException e) {
3366 return false; // no clue
3369 if (scanner.recordLineSeparator) {
3370 // compilationUnit.compilationResult.lineSeparatorPositions =
3371 // scanner.getLineEnds();
3373 // check placement anomalies against other kinds of brackets
3374 for (int kind = 0; kind < BracketKinds; kind++) {
3375 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3376 int start = leftPositions[kind][leftIndex]; // deepest
3378 // find matching closing bracket
3379 int depth = leftDepths[kind][leftIndex];
3381 for (int i = 0; i < rightCount[kind]; i++) {
3382 int pos = rightPositions[kind][i];
3383 // want matching bracket further in source with same
3385 if ((pos > start) && (depth == rightDepths[kind][i])) {
3390 if (end < 0) { // did not find a good closing match
3391 problemReporter.unmatchedBracket(start, referenceContext,
3392 compilationUnit.compilationResult);
3395 // check if even number of opening/closing other brackets
3396 // in between this pair of brackets
3398 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3399 for (int i = 0; i < leftCount[otherKind]; i++) {
3400 int pos = leftPositions[otherKind][i];
3401 if ((pos > start) && (pos < end))
3404 for (int i = 0; i < rightCount[otherKind]; i++) {
3405 int pos = rightPositions[otherKind][i];
3406 if ((pos > start) && (pos < end))
3410 problemReporter.unmatchedBracket(start, referenceContext,
3411 compilationUnit.compilationResult); //bracket
3417 // too many opening brackets ?
3418 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3419 anomaliesDetected = true;
3420 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3421 - i - 1], referenceContext, compilationUnit.compilationResult);
3423 // too many closing brackets ?
3424 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3425 anomaliesDetected = true;
3426 problemReporter.unmatchedBracket(rightPositions[kind][i],
3427 referenceContext, compilationUnit.compilationResult);
3429 if (anomaliesDetected)
3432 return anomaliesDetected;
3433 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3434 return anomaliesDetected;
3435 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3436 return anomaliesDetected;
3439 protected void pushOnAstLengthStack(int pos) {
3441 astLengthStack[++astLengthPtr] = pos;
3442 } catch (IndexOutOfBoundsException e) {
3443 int oldStackLength = astLengthStack.length;
3444 int[] oldPos = astLengthStack;
3445 astLengthStack = new int[oldStackLength + StackIncrement];
3446 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3447 astLengthStack[astLengthPtr] = pos;
3450 protected void pushOnAstStack(AstNode node) {
3452 * add a new obj on top of the ast stack
3455 astStack[++astPtr] = node;
3456 } catch (IndexOutOfBoundsException e) {
3457 int oldStackLength = astStack.length;
3458 AstNode[] oldStack = astStack;
3459 astStack = new AstNode[oldStackLength + AstStackIncrement];
3460 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3461 astPtr = oldStackLength;
3462 astStack[astPtr] = node;
3465 astLengthStack[++astLengthPtr] = 1;
3466 } catch (IndexOutOfBoundsException e) {
3467 int oldStackLength = astLengthStack.length;
3468 int[] oldPos = astLengthStack;
3469 astLengthStack = new int[oldStackLength + AstStackIncrement];
3470 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3471 astLengthStack[astLengthPtr] = 1;