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);
1434 if (token != TokenNameclass) {
1435 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1439 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1442 private void interface_extends_list() {
1444 // | T_EXTENDS interface_list
1445 if (token == TokenNameextends) {
1450 private void implements_list() {
1452 // | T_IMPLEMENTS interface_list
1453 if (token == TokenNameimplements) {
1458 private void interface_list() {
1460 // fully_qualified_class_name
1461 //| interface_list ',' fully_qualified_class_name
1463 if (token == TokenNameIdentifier) {
1466 throwSyntaxError("Interface name expected after keyword 'implements'.");
1468 if (token != TokenNameCOMMA) {
1474 // private void classBody(TypeDeclaration typeDecl) {
1475 // //'{' [class-element-list] '}'
1476 // if (token == TokenNameLBRACE) {
1478 // if (token != TokenNameRBRACE) {
1479 // class_statement_list();
1481 // if (token == TokenNameRBRACE) {
1482 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1485 // throwSyntaxError("'}' expected at end of class body.");
1488 // throwSyntaxError("'{' expected at start of class body.");
1491 private void class_statement_list() {
1494 } while (token == TokenNamefunction || token == TokenNamevar);
1496 private void class_statement() {
1498 // variable_modifiers class_variable_declaration ';'
1499 // | class_constant_declaration ';'
1500 // | method_modifiers T_FUNCTION is_reference T_STRING
1501 // '(' parameter_list ')' method_body
1502 initializeModifiers();
1503 if (token == TokenNamevar) {
1504 checkAndSetModifiers(AccPublic);
1506 "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected' modifier for field declarations.",
1507 scanner.getCurrentTokenStartPosition(), scanner
1508 .getCurrentTokenEndPosition());
1512 boolean hasModifiers = member_modifiers();
1513 if (token == TokenNamefunction) {
1514 if (!hasModifiers) {
1515 checkAndSetModifiers(AccPublic);
1517 MethodDeclaration methodDecl = new MethodDeclaration(
1518 this.compilationUnit.compilationResult);
1519 methodDecl.declarationSourceStart = scanner
1520 .getCurrentTokenStartPosition();
1521 methodDecl.modifiers = this.modifiers;
1523 functionDefinition(methodDecl);
1525 if (!hasModifiers) {
1526 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1531 // if (token == TokenNamefunction) {
1532 // MethodDeclaration methodDecl = new MethodDeclaration(
1533 // this.compilationUnit.compilationResult);
1534 // methodDecl.declarationSourceStart = scanner
1535 // .getCurrentTokenStartPosition();
1537 // functionDefinition(methodDecl);
1538 // } else if (token == TokenNamevar) {
1542 // throwSyntaxError("'function' or 'var' expected.");
1545 // private void variable_modifiers() {
1546 // // variable_modifiers:
1547 // // non_empty_member_modifiers
1549 // initializeModifiers();
1550 // if (token == TokenNamevar) {
1551 // checkAndSetModifiers(AccPublic);
1552 // reportSyntaxError(
1553 // "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
1554 // modifier for field declarations.",
1555 // scanner.getCurrentTokenStartPosition(), scanner
1556 // .getCurrentTokenEndPosition());
1559 // if (!member_modifiers()) {
1560 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1561 // field declarations.");
1565 // private void method_modifiers() {
1566 // //method_modifiers:
1568 // //| non_empty_member_modifiers
1569 // initializeModifiers();
1570 // if (!member_modifiers()) {
1571 // checkAndSetModifiers(AccPublic);
1574 private boolean member_modifiers() {
1581 boolean foundToken = false;
1583 if (token == TokenNamepublic) {
1584 checkAndSetModifiers(AccPublic);
1587 } else if (token == TokenNameprotected) {
1588 checkAndSetModifiers(AccProtected);
1591 } else if (token == TokenNameprivate) {
1592 checkAndSetModifiers(AccPrivate);
1595 } else if (token == TokenNamestatic) {
1596 checkAndSetModifiers(AccStatic);
1599 } else if (token == TokenNameabstract) {
1600 checkAndSetModifiers(AccAbstract);
1603 } else if (token == TokenNamefinal) {
1604 checkAndSetModifiers(AccFinal);
1613 private void classProperty() {
1614 //'var' variable ';'
1615 //'var' variable '=' constant ';'
1617 if (token == TokenNameVariable) {
1619 if (token == TokenNameEQUAL) {
1624 if (token == TokenNamethis) {
1625 throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1627 throwSyntaxError("Variable expected after keyword 'var'.");
1629 if (token != TokenNameCOMMA) {
1634 if (token == TokenNameSEMICOLON) {
1637 throwSyntaxError("';' expected after variable declaration.");
1640 private void functionDefinition(MethodDeclaration methodDecl) {
1642 compilationUnit.types.add(methodDecl);
1644 AstNode node = astStack[astPtr];
1645 if (node instanceof TypeDeclaration) {
1646 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1647 if (typeDecl.methods == null) {
1648 typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1650 AbstractMethodDeclaration[] newMethods;
1655 newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1656 1, typeDecl.methods.length);
1657 newMethods[0] = methodDecl;
1658 typeDecl.methods = newMethods;
1662 functionDeclarator(methodDecl);
1663 functionBody(methodDecl);
1665 private void functionDeclarator(MethodDeclaration methodDecl) {
1666 //identifier '(' [parameter-list] ')'
1667 if (token == TokenNameAND) {
1670 if (token == TokenNameIdentifier) {
1671 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1672 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1673 methodDecl.selector = scanner.getCurrentIdentifierSource();
1675 if (token == TokenNameLPAREN) {
1678 throwSyntaxError("'(' expected in function declaration.");
1680 if (token != TokenNameRPAREN) {
1683 if (token != TokenNameRPAREN) {
1684 throwSyntaxError("')' expected in function declaration.");
1686 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1690 if (token > TokenNameKEYWORD) {
1691 throwSyntaxError("Don't use keyword for function declaration [" + token
1694 throwSyntaxError("Function name expected after keyword 'function'.");
1698 private void parameterList() {
1699 //parameter-declaration
1700 //parameter-list ',' parameter-declaration
1702 parameterDeclaration();
1703 if (token != TokenNameCOMMA) {
1709 private void parameterDeclaration() {
1711 //variable-reference
1712 if (token == TokenNameAND) {
1717 throwSyntaxError("Variable expected after reference operator '&'.");
1720 //variable '=' constant
1721 if (token == TokenNameVariable) {
1723 if (token == TokenNameEQUAL) {
1729 if (token == TokenNamethis) {
1730 throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1733 private void labeledStatementList() {
1734 if (token != TokenNamecase && token != TokenNamedefault) {
1735 throwSyntaxError("'case' or 'default' expected.");
1738 if (token == TokenNamecase) {
1740 expr(); //constant();
1741 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1743 if (token == TokenNamecase || token == TokenNamedefault) { // empty
1751 // else if (token == TokenNameSEMICOLON) {
1753 // "':' expected after 'case' keyword (Found token: " +
1754 // scanner.toStringAction(token) + ")",
1755 // scanner.getCurrentTokenStartPosition(),
1756 // scanner.getCurrentTokenEndPosition(),
1759 // if (token == TokenNamecase) { // empty case statement ?
1765 throwSyntaxError("':' character after 'case' constant expected (Found token: "
1766 + scanner.toStringAction(token) + ")");
1768 } else { // TokenNamedefault
1770 if (token == TokenNameCOLON) {
1774 throwSyntaxError("':' character after 'default' expected.");
1777 } while (token == TokenNamecase || token == TokenNamedefault);
1779 // public void labeledStatement() {
1780 // if (token == TokenNamecase) {
1783 // if (token == TokenNameDDOT) {
1787 // throwSyntaxError("':' character after 'case' constant expected.");
1790 // } else if (token == TokenNamedefault) {
1792 // if (token == TokenNameDDOT) {
1796 // throwSyntaxError("':' character after 'default' expected.");
1801 // public void expressionStatement() {
1803 // private void inclusionStatement() {
1805 // public void compoundStatement() {
1807 // public void selectionStatement() {
1810 // public void iterationStatement() {
1813 // public void jumpStatement() {
1816 // public void outputStatement() {
1819 // public void scopeStatement() {
1822 // public void flowStatement() {
1825 // public void definitionStatement() {
1827 private void ifStatement() {
1828 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1829 if (token == TokenNameCOLON) {
1831 if (token != TokenNameendif) {
1834 case TokenNameelse :
1836 if (token == TokenNameCOLON) {
1838 if (token != TokenNameendif) {
1842 if (token == TokenNameif) { //'else if'
1844 elseifStatementList();
1846 throwSyntaxError("':' expected after 'else'.");
1850 case TokenNameelseif :
1852 elseifStatementList();
1856 if (token != TokenNameendif) {
1857 throwSyntaxError("'endif' expected.");
1860 if (token != TokenNameSEMICOLON) {
1861 throwSyntaxError("';' expected after if-statement.");
1865 // statement [else-statement]
1866 statement(TokenNameEOF);
1867 if (token == TokenNameelseif) {
1869 if (token == TokenNameLPAREN) {
1872 throwSyntaxError("'(' expected after 'elseif' keyword.");
1875 if (token == TokenNameRPAREN) {
1878 throwSyntaxError("')' expected after 'elseif' condition.");
1881 } else if (token == TokenNameelse) {
1883 statement(TokenNameEOF);
1887 private void elseifStatementList() {
1891 case TokenNameelse :
1893 if (token == TokenNameCOLON) {
1895 if (token != TokenNameendif) {
1900 if (token == TokenNameif) { //'else if'
1903 throwSyntaxError("':' expected after 'else'.");
1907 case TokenNameelseif :
1915 private void elseifStatement() {
1916 if (token == TokenNameLPAREN) {
1919 if (token != TokenNameRPAREN) {
1920 throwSyntaxError("')' expected in else-if-statement.");
1923 if (token != TokenNameCOLON) {
1924 throwSyntaxError("':' expected in else-if-statement.");
1927 if (token != TokenNameendif) {
1932 private void switchStatement() {
1933 if (token == TokenNameCOLON) {
1934 // ':' [labeled-statement-list] 'endswitch' ';'
1936 labeledStatementList();
1937 if (token != TokenNameendswitch) {
1938 throwSyntaxError("'endswitch' expected.");
1941 if (token != TokenNameSEMICOLON) {
1942 throwSyntaxError("';' expected after switch-statement.");
1946 // '{' [labeled-statement-list] '}'
1947 if (token != TokenNameLBRACE) {
1948 throwSyntaxError("'{' expected in switch statement.");
1951 if (token != TokenNameRBRACE) {
1952 labeledStatementList();
1954 if (token != TokenNameRBRACE) {
1955 throwSyntaxError("'}' expected in switch statement.");
1960 private void forStatement() {
1961 if (token == TokenNameCOLON) {
1964 if (token != TokenNameendfor) {
1965 throwSyntaxError("'endfor' expected.");
1968 if (token != TokenNameSEMICOLON) {
1969 throwSyntaxError("';' expected after for-statement.");
1973 statement(TokenNameEOF);
1976 private void whileStatement() {
1977 // ':' statement-list 'endwhile' ';'
1978 if (token == TokenNameCOLON) {
1981 if (token != TokenNameendwhile) {
1982 throwSyntaxError("'endwhile' expected.");
1985 if (token != TokenNameSEMICOLON) {
1986 throwSyntaxError("';' expected after while-statement.");
1990 statement(TokenNameEOF);
1993 private void foreachStatement() {
1994 if (token == TokenNameCOLON) {
1997 if (token != TokenNameendforeach) {
1998 throwSyntaxError("'endforeach' expected.");
2001 if (token != TokenNameSEMICOLON) {
2002 throwSyntaxError("';' expected after foreach-statement.");
2006 statement(TokenNameEOF);
2009 // private void exitStatus() {
2010 // if (token == TokenNameLPAREN) {
2013 // throwSyntaxError("'(' expected in 'exit-status'.");
2015 // if (token != TokenNameRPAREN) {
2018 // if (token == TokenNameRPAREN) {
2021 // throwSyntaxError("')' expected after 'exit-status'.");
2024 private void expressionList() {
2027 if (token == TokenNameCOMMA) {
2034 private void expr() {
2035 //todo: find a better way to get the expression
2036 // expression = new StringBuffer();
2037 // for (int i = chIndx; i < str.length(); i++) {
2038 // if (str.charAt(i) == ';') {
2041 // expression.append(str.charAt(i));
2043 // if (token == TokenNameSTRING_CONSTANT || token ==
2044 // TokenNameINTERPOLATED_STRING) {
2047 logicalinclusiveorExpression();
2048 // while (token != TokenNameSEMICOLON) {
2053 private void expr_without_variable() {
2056 boolean castFlag = false;
2057 boolean arrayFlag = false;
2059 case TokenNameisset :
2060 case TokenNameempty :
2061 case TokenNameeval :
2062 case TokenNameinclude :
2063 case TokenNameinclude_once :
2064 case TokenNamerequire :
2065 case TokenNamerequire_once :
2066 internal_functions_in_yacc();
2072 case TokenNamenull :
2075 case TokenNamefalse :
2078 case TokenNametrue :
2081 case TokenNameStringConstant :
2084 case TokenNameHEREDOC :
2085 case TokenNameStringInterpolated :
2086 case TokenNameStringLiteral :
2089 case TokenNameLPAREN :
2091 if (token == TokenNameIdentifier) {
2092 // check if identifier is a type:
2093 // ident = identifier;
2094 ident = scanner.getCurrentIdentifierSource();
2095 String str = new String(ident).toLowerCase();
2096 for (int i = 0; i < PHP_TYPES.length; i++) {
2097 if (PHP_TYPES[i].equals(str)) {
2099 if (PHP_TYPES[i].equals("array")) {
2108 if (arrayFlag && token == TokenNameLPAREN) {
2110 if (token == TokenNameRPAREN) {
2114 if (token != TokenNameRPAREN) {
2115 throwSyntaxError(") expected after 'array('.");
2119 if (token != TokenNameRPAREN) {
2120 throwSyntaxError(") expected after cast-type '" + str + "'.");
2128 if (token != TokenNameRPAREN) {
2129 throwSyntaxError(") expected in postfix-expression.");
2133 case TokenNameDoubleLiteral :
2136 case TokenNameIntegerLiteral :
2139 case TokenNameDOLLAR_LBRACE :
2142 if (token != TokenNameRBRACE) {
2143 throwSyntaxError("'}' expected after indirect variable token '${'.");
2147 case TokenNameVariable :
2148 case TokenNamethis :
2149 ident = scanner.getCurrentIdentifierSource();
2151 if (token == TokenNameLBRACE) {
2154 if (token != TokenNameRBRACE) {
2155 throwSyntaxError("'}' expected after variable '"
2156 + new String(ident) + "' in variable-expression.");
2159 } else if (token == TokenNameLPAREN) {
2161 if (token != TokenNameRPAREN) {
2163 if (token != TokenNameRPAREN) {
2164 throwSyntaxError("')' expected after variable '"
2165 + new String(ident) + "' in postfix-expression.");
2171 case TokenNameIdentifier :
2172 ident = scanner.getCurrentIdentifierSource();
2174 if (token == TokenNameLPAREN) {
2176 if (token != TokenNameRPAREN) {
2178 if (token != TokenNameRPAREN) {
2179 throwSyntaxError("')' expected after identifier '"
2180 + new String(ident) + "' in postfix-expression."
2181 + "(Found token: " + scanner.toStringAction(token) + ")");
2187 case TokenNameprint :
2191 case TokenNameexit :
2195 case TokenNamelist :
2197 if (token == TokenNameLPAREN) {
2199 if (token == TokenNameCOMMA) {
2203 if (token != TokenNameRPAREN) {
2204 throwSyntaxError("')' expected after 'list' keyword.");
2207 // if (token == TokenNameSET) {
2209 // logicalinclusiveorExpression();
2212 throwSyntaxError("'(' expected after 'list' keyword.");
2215 // case TokenNameexit :
2217 // if (token != TokenNameSEMICOLON) {
2220 // if (token == TokenNameSEMICOLON) {
2223 // if (token != TokenNameStopPHP) {
2224 // throwSyntaxError("';' expected after 'exit' expression.");
2229 // case TokenNamedie :
2231 // if (token != TokenNameSEMICOLON) {
2234 // if (token == TokenNameSEMICOLON) {
2237 // if (token != TokenNameStopPHP) {
2238 // throwSyntaxError("';' expected after 'die' expression.");
2242 // case TokenNamearray :
2244 // if (token == TokenNameARGOPEN) {
2246 // if (token == TokenNameCOMMA) {
2249 // expressionList();
2250 // if (token != TokenNameARGCLOSE) {
2251 // throwSyntaxError("')' expected after 'list' keyword.");
2254 // if (token == TokenNameSET) {
2256 // logicalinclusiveorExpression();
2259 // throwSyntaxError("'(' expected after 'list' keyword.");
2263 boolean while_flag = true;
2266 case TokenNameLBRACKET :
2269 if (token != TokenNameRBRACKET) {
2270 throwSyntaxError("] expected in postfix-expression.");
2274 case TokenNameCOLON_COLON :
2276 case TokenNameMINUS_GREATER :
2279 if (token > TokenNameKEYWORD) {
2280 ident = scanner.getCurrentIdentifierSource();
2282 // "Avoid using keyword '"
2283 // + new String(ident)
2284 // + "' as variable name.",
2288 // "Avoid using keyword '" + new String(ident) + "' as
2290 // scanner.getCurrentTokenStartPosition(),
2291 // scanner.getCurrentTokenEndPosition(),
2295 case TokenNameVariable :
2296 ident = scanner.getCurrentIdentifierSource();
2298 // if (token == TokenNameARGOPEN) {
2300 // expressionList();
2301 // if (token != TokenNameARGCLOSE) {
2302 // throwSyntaxError(") expected after variable '" +
2308 case TokenNameIdentifier :
2309 //ident = scanner.getCurrentIdentifierSource();
2312 case TokenNameLBRACE :
2315 if (token != TokenNameRBRACE) {
2316 throwSyntaxError("} expected in postfix-expression.");
2321 throwSyntaxError("Syntax error after '->' token.");
2323 while (token == TokenNameLBRACKET || token == TokenNameLPAREN
2324 || token == TokenNameLBRACE) {
2325 if (token == TokenNameLBRACKET) {
2328 if (token != TokenNameRBRACKET) {
2329 throwSyntaxError("] expected after '->'.");
2332 } else if (token == TokenNameLPAREN) {
2335 if (token != TokenNameRPAREN) {
2336 throwSyntaxError(") expected after '->'.");
2339 } else if (token == TokenNameLBRACE) {
2342 if (token != TokenNameRBRACE) {
2343 throwSyntaxError("} expected after '->'.");
2349 case TokenNamePLUS_PLUS :
2352 case TokenNameMINUS_MINUS :
2358 } while (while_flag);
2360 private void unaryExpression() {
2362 case TokenNamePLUS_PLUS :
2366 case TokenNameMINUS_MINUS :
2370 // '@' '&' '*' '+' '-' '~' '!'
2373 if (token == TokenNameinclude || token == TokenNameinclude_once
2374 || token == TokenNamerequire || token == TokenNamerequire_once) {
2375 statement(TokenNameAT);
2377 expr_without_variable(); // castExpression();
2384 case TokenNameMULTIPLY :
2388 case TokenNamePLUS :
2392 case TokenNameMINUS :
2396 case TokenNameTWIDDLE :
2405 expr_without_variable();
2408 private void castExpression() {
2409 // if (token == TokenNameARGOPEN) {
2412 // if (token != TokenNameARGCLOSE) {
2413 // throwSyntaxError(") expected after cast-expression.");
2419 private void assignExpression() {
2421 if (token == TokenNameEQUAL) { // =
2423 logicalinclusiveorExpression();
2424 } else if (token == TokenNameDOT_EQUAL) { // .=
2426 logicalinclusiveorExpression();
2427 } else if (token == TokenNameEQUAL_GREATER) { // =>
2429 logicalinclusiveorExpression();
2430 } else if (token == TokenNamePLUS_EQUAL) { // +=
2432 logicalinclusiveorExpression();
2433 } else if (token == TokenNameMINUS_EQUAL) { // -=
2435 logicalinclusiveorExpression();
2436 } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2438 logicalinclusiveorExpression();
2439 } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2441 logicalinclusiveorExpression();
2442 } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2444 logicalinclusiveorExpression();
2445 } else if (token == TokenNameAND_EQUAL) { // &=
2447 logicalinclusiveorExpression();
2448 } else if (token == TokenNameOR_EQUAL) { // |=
2450 logicalinclusiveorExpression();
2451 } else if (token == TokenNameXOR_EQUAL) { // ^=
2453 logicalinclusiveorExpression();
2454 } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2456 logicalinclusiveorExpression();
2457 } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2459 logicalinclusiveorExpression();
2460 } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2462 logicalinclusiveorExpression();
2465 private void multiplicativeExpression() {
2468 if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE
2469 && token != TokenNameREMAINDER) {
2475 private void concatenationExpression() {
2477 multiplicativeExpression();
2478 if (token != TokenNameDOT) {
2484 private void additiveExpression() {
2486 concatenationExpression();
2487 if (token != TokenNamePLUS && token != TokenNameMINUS) {
2493 private void shiftExpression() {
2495 additiveExpression();
2496 if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2502 private void relationalExpression() {
2505 if (token != TokenNameLESS && token != TokenNameGREATER
2506 && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2512 private void identicalExpression() {
2514 relationalExpression();
2515 if (token != TokenNameEQUAL_EQUAL_EQUAL
2516 && token != TokenNameNOT_EQUAL_EQUAL) {
2522 private void equalityExpression() {
2524 identicalExpression();
2525 if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2531 private void ternaryExpression() {
2532 equalityExpression();
2533 if (token == TokenNameQUESTION) {
2536 if (token == TokenNameCOLON) {
2540 throwSyntaxError("':' expected in ternary operator '? :'.");
2544 private void andExpression() {
2546 ternaryExpression();
2547 if (token != TokenNameAND) {
2553 private void exclusiveorExpression() {
2556 if (token != TokenNameXOR) {
2562 private void inclusiveorExpression() {
2564 exclusiveorExpression();
2565 if (token != TokenNameOR) {
2571 private void booleanandExpression() {
2573 inclusiveorExpression();
2574 if (token != TokenNameAND_AND) {
2580 private void booleanorExpression() {
2582 booleanandExpression();
2583 if (token != TokenNameOR_OR) {
2589 private void logicalandExpression() {
2591 booleanorExpression();
2592 if (token != TokenNameAND) {
2598 private void logicalexclusiveorExpression() {
2600 logicalandExpression();
2601 if (token != TokenNameXOR) {
2607 private void logicalinclusiveorExpression() {
2609 logicalexclusiveorExpression();
2610 if (token != TokenNameOR) {
2616 // public void assignmentExpression() {
2617 // if (token == TokenNameVARIABLE) {
2619 // if (token == TokenNameSET) {
2621 // logicalinclusiveorExpression();
2624 // logicalinclusiveorExpression();
2627 private void variableList() {
2630 if (token == TokenNameCOMMA) {
2637 private void variable() {
2638 if (token == TokenNameDOLLAR_LBRACE) {
2642 if (token != TokenNameRBRACE) {
2643 throwSyntaxError("'}' expected after indirect variable token '${'.");
2647 if (token == TokenNameVariable) {
2649 if (token == TokenNameLBRACKET) {
2652 if (token != TokenNameRBRACKET) {
2653 throwSyntaxError("']' expected in variable-list.");
2656 } else if (token == TokenNameEQUAL) {
2661 throwSyntaxError("$-variable expected in variable-list.");
2665 private void exit_expr() {
2669 if (token != TokenNameLPAREN) {
2673 if (token == TokenNameRPAREN) {
2678 if (token != TokenNameRPAREN) {
2679 throwSyntaxError("')' expected after keyword 'exit'");
2683 private void internal_functions_in_yacc() {
2685 case TokenNameisset :
2686 // T_ISSET '(' isset_variables ')'
2688 if (token != TokenNameLPAREN) {
2689 throwSyntaxError("'(' expected after keyword 'isset'");
2693 if (token != TokenNameRPAREN) {
2694 throwSyntaxError("')' expected after keyword 'isset'");
2698 case TokenNameempty :
2699 // T_EMPTY '(' variable ')'
2701 if (token != TokenNameLPAREN) {
2702 throwSyntaxError("'(' expected after keyword 'empty'");
2706 if (token != TokenNameRPAREN) {
2707 throwSyntaxError("')' expected after keyword 'empty'");
2711 case TokenNameinclude :
2716 case TokenNameinclude_once :
2717 // T_INCLUDE_ONCE expr
2721 case TokenNameeval :
2722 // T_EVAL '(' expr ')'
2724 if (token != TokenNameLPAREN) {
2725 throwSyntaxError("'(' expected after keyword 'eval'");
2729 if (token != TokenNameRPAREN) {
2730 throwSyntaxError("')' expected after keyword 'eval'");
2734 case TokenNamerequire :
2739 case TokenNamerequire_once :
2740 // T_REQUIRE_ONCE expr
2746 private void isset_variables() {
2748 // | isset_variables ','
2749 if (token == TokenNameRPAREN) {
2750 throwSyntaxError("Variable expected after keyword 'isset'");
2754 if (token == TokenNameCOMMA) {
2762 * It will look for a value (after a '=' for example) @
2764 private void constant() {
2767 case TokenNamePLUS :
2770 case TokenNameDoubleLiteral :
2773 case TokenNameIntegerLiteral :
2777 throwSyntaxError("Constant expected after '+' presign.");
2780 case TokenNameMINUS :
2783 case TokenNameDoubleLiteral :
2786 case TokenNameIntegerLiteral :
2790 throwSyntaxError("Constant expected after '-' presign.");
2793 case TokenNamenull :
2796 case TokenNamefalse :
2799 case TokenNametrue :
2802 case TokenNameIdentifier :
2803 // ident = identifier;
2804 char[] ident = scanner.getCurrentIdentifierSource();
2806 if (token == TokenNameLPAREN) {
2808 if (token != TokenNameRPAREN) {
2810 if (token != TokenNameRPAREN) {
2811 throwSyntaxError("')' expected after identifier '"
2812 + new String(ident) + "' in postfix-expression.");
2818 case TokenNameStringLiteral :
2821 case TokenNameStringConstant :
2824 case TokenNameStringInterpolated :
2827 case TokenNameDoubleLiteral :
2830 case TokenNameIntegerLiteral :
2834 throwSyntaxError("Constant expected.");
2837 public void reportSyntaxError() { //int act, int currentKind, int
2839 /* remember current scanner position */
2840 int startPos = scanner.startPosition;
2841 int currentPos = scanner.currentPosition;
2842 // String[] expectings;
2843 // String tokenName = name[symbol_index[currentKind]];
2844 //fetch all "accurate" possible terminals that could recover the error
2845 // int start, end = start = asi(stack[stateStackTop]);
2846 // while (asr[end] != 0)
2848 // int length = end - start;
2849 // expectings = new String[length];
2850 // if (length != 0) {
2851 // char[] indexes = new char[length];
2852 // System.arraycopy(asr, start, indexes, 0, length);
2853 // for (int i = 0; i < length; i++) {
2854 // expectings[i] = name[symbol_index[indexes[i]]];
2857 //if the pb is an EOF, try to tell the user that they are some
2858 // if (tokenName.equals(UNEXPECTED_EOF)) {
2859 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2860 // char[] tokenSource;
2862 // tokenSource = this.scanner.getCurrentTokenSource();
2863 // } catch (Exception e) {
2864 // tokenSource = new char[] {};
2866 // problemReporter().parseError(
2867 // this.scanner.startPosition,
2868 // this.scanner.currentPosition - 1,
2873 // } else { //the next test is HEAVILY grammar DEPENDENT.
2874 // if ((length == 14)
2875 // && (expectings[0] == "=") //$NON-NLS-1$
2876 // && (expectings[1] == "*=") //$NON-NLS-1$
2877 // && (expressionPtr > -1)) {
2878 // switch(currentKind) {
2879 // case TokenNameSEMICOLON:
2880 // case TokenNamePLUS:
2881 // case TokenNameMINUS:
2882 // case TokenNameDIVIDE:
2883 // case TokenNameREMAINDER:
2884 // case TokenNameMULTIPLY:
2885 // case TokenNameLEFT_SHIFT:
2886 // case TokenNameRIGHT_SHIFT:
2887 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
2888 // case TokenNameLESS:
2889 // case TokenNameGREATER:
2890 // case TokenNameLESS_EQUAL:
2891 // case TokenNameGREATER_EQUAL:
2892 // case TokenNameEQUAL_EQUAL:
2893 // case TokenNameNOT_EQUAL:
2894 // case TokenNameXOR:
2895 // case TokenNameAND:
2896 // case TokenNameOR:
2897 // case TokenNameOR_OR:
2898 // case TokenNameAND_AND:
2899 // // the ; is not the expected token ==> it ends a statement when an
2900 // expression is not ended
2901 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
2903 // case TokenNameRBRACE :
2904 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
2907 // char[] tokenSource;
2909 // tokenSource = this.scanner.getCurrentTokenSource();
2910 // } catch (Exception e) {
2911 // tokenSource = new char[] {};
2913 // problemReporter().parseError(
2914 // this.scanner.startPosition,
2915 // this.scanner.currentPosition - 1,
2919 // this.checkAndReportBracketAnomalies(problemReporter());
2924 tokenSource = this.scanner.getCurrentTokenSource();
2925 } catch (Exception e) {
2926 tokenSource = new char[]{};
2928 // problemReporter().parseError(
2929 // this.scanner.startPosition,
2930 // this.scanner.currentPosition - 1,
2934 this.checkAndReportBracketAnomalies(problemReporter());
2937 /* reset scanner where it was */
2938 scanner.startPosition = startPos;
2939 scanner.currentPosition = currentPos;
2941 public static final int RoundBracket = 0;
2942 public static final int SquareBracket = 1;
2943 public static final int CurlyBracket = 2;
2944 public static final int BracketKinds = 3;
2945 protected int[] nestedMethod; //the ptr is nestedType
2946 protected int nestedType, dimensions;
2948 final static int AstStackIncrement = 100;
2949 protected int astPtr;
2950 protected AstNode[] astStack = new AstNode[AstStackIncrement];
2951 protected int astLengthPtr;
2952 protected int[] astLengthStack;
2953 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
2954 public CompilationUnitDeclaration compilationUnit; /*
2955 * the result from parse()
2957 protected ReferenceContext referenceContext;
2958 protected ProblemReporter problemReporter;
2959 // protected CompilationResult compilationResult;
2961 * Returns this parser's problem reporter initialized with its reference
2962 * context. Also it is assumed that a problem is going to be reported, so
2963 * initializes the compilation result's line positions.
2965 public ProblemReporter problemReporter() {
2966 if (scanner.recordLineSeparator) {
2967 compilationUnit.compilationResult.lineSeparatorPositions = scanner
2970 problemReporter.referenceContext = referenceContext;
2971 return problemReporter;
2974 * Reconsider the entire source looking for inconsistencies in {} () []
2976 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
2977 scanner.wasAcr = false;
2978 boolean anomaliesDetected = false;
2980 char[] source = scanner.source;
2981 int[] leftCount = {0, 0, 0};
2982 int[] rightCount = {0, 0, 0};
2983 int[] depths = {0, 0, 0};
2984 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
2985 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
2986 int[][] rightPositions = new int[][]{new int[10], new int[10],
2988 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
2989 scanner.currentPosition = scanner.initialPosition; //starting
2991 // (first-zero-based
2993 while (scanner.currentPosition < scanner.eofPosition) { //loop for
2998 // ---------Consume white space and handles
2999 // startPosition---------
3000 boolean isWhiteSpace;
3002 scanner.startPosition = scanner.currentPosition;
3003 // if (((scanner.currentCharacter =
3004 // source[scanner.currentPosition++]) == '\\') &&
3005 // (source[scanner.currentPosition] == 'u')) {
3006 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3008 if (scanner.recordLineSeparator
3009 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3010 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3011 // only record line positions we have not
3013 scanner.pushLineSeparator();
3016 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3018 } while (isWhiteSpace
3019 && (scanner.currentPosition < scanner.eofPosition));
3020 // -------consume token until } is found---------
3021 switch (scanner.currentCharacter) {
3024 int index = leftCount[CurlyBracket]++;
3025 if (index == leftPositions[CurlyBracket].length) {
3026 System.arraycopy(leftPositions[CurlyBracket], 0,
3027 (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3030 .arraycopy(leftDepths[CurlyBracket], 0,
3031 (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3034 leftPositions[CurlyBracket][index] = scanner.startPosition;
3035 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3040 int index = rightCount[CurlyBracket]++;
3041 if (index == rightPositions[CurlyBracket].length) {
3042 System.arraycopy(rightPositions[CurlyBracket], 0,
3043 (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3045 System.arraycopy(rightDepths[CurlyBracket], 0,
3046 (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3049 rightPositions[CurlyBracket][index] = scanner.startPosition;
3050 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3055 int index = leftCount[RoundBracket]++;
3056 if (index == leftPositions[RoundBracket].length) {
3057 System.arraycopy(leftPositions[RoundBracket], 0,
3058 (leftPositions[RoundBracket] = new int[index * 2]), 0,
3061 .arraycopy(leftDepths[RoundBracket], 0,
3062 (leftDepths[RoundBracket] = new int[index * 2]), 0,
3065 leftPositions[RoundBracket][index] = scanner.startPosition;
3066 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3071 int index = rightCount[RoundBracket]++;
3072 if (index == rightPositions[RoundBracket].length) {
3073 System.arraycopy(rightPositions[RoundBracket], 0,
3074 (rightPositions[RoundBracket] = new int[index * 2]), 0,
3076 System.arraycopy(rightDepths[RoundBracket], 0,
3077 (rightDepths[RoundBracket] = new int[index * 2]), 0,
3080 rightPositions[RoundBracket][index] = scanner.startPosition;
3081 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3086 int index = leftCount[SquareBracket]++;
3087 if (index == leftPositions[SquareBracket].length) {
3088 System.arraycopy(leftPositions[SquareBracket], 0,
3089 (leftPositions[SquareBracket] = new int[index * 2]), 0,
3091 System.arraycopy(leftDepths[SquareBracket], 0,
3092 (leftDepths[SquareBracket] = new int[index * 2]), 0,
3095 leftPositions[SquareBracket][index] = scanner.startPosition;
3096 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3101 int index = rightCount[SquareBracket]++;
3102 if (index == rightPositions[SquareBracket].length) {
3103 System.arraycopy(rightPositions[SquareBracket], 0,
3104 (rightPositions[SquareBracket] = new int[index * 2]), 0,
3106 System.arraycopy(rightDepths[SquareBracket], 0,
3107 (rightDepths[SquareBracket] = new int[index * 2]), 0,
3110 rightPositions[SquareBracket][index] = scanner.startPosition;
3111 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3116 if (scanner.getNextChar('\\')) {
3117 scanner.scanEscapeCharacter();
3118 } else { // consume next character
3119 scanner.unicodeAsBackSlash = false;
3120 // if (((scanner.currentCharacter =
3121 // source[scanner.currentPosition++]) ==
3123 // (source[scanner.currentPosition] ==
3125 // scanner.getNextUnicodeChar();
3127 if (scanner.withoutUnicodePtr != 0) {
3128 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3132 scanner.getNextChar('\'');
3136 // consume next character
3137 scanner.unicodeAsBackSlash = false;
3138 // if (((scanner.currentCharacter =
3139 // source[scanner.currentPosition++]) == '\\') &&
3140 // (source[scanner.currentPosition] == 'u')) {
3141 // scanner.getNextUnicodeChar();
3143 if (scanner.withoutUnicodePtr != 0) {
3144 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3147 while (scanner.currentCharacter != '"') {
3148 if (scanner.currentCharacter == '\r') {
3149 if (source[scanner.currentPosition] == '\n')
3150 scanner.currentPosition++;
3151 break; // the string cannot go further that
3154 if (scanner.currentCharacter == '\n') {
3155 break; // the string cannot go further that
3158 if (scanner.currentCharacter == '\\') {
3159 scanner.scanEscapeCharacter();
3161 // consume next character
3162 scanner.unicodeAsBackSlash = false;
3163 // if (((scanner.currentCharacter =
3164 // source[scanner.currentPosition++]) == '\\')
3165 // && (source[scanner.currentPosition] == 'u'))
3167 // scanner.getNextUnicodeChar();
3169 if (scanner.withoutUnicodePtr != 0) {
3170 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3178 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3181 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3182 && (source[scanner.currentPosition] == 'u')) {
3183 //-------------unicode traitement
3185 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3186 scanner.currentPosition++;
3187 while (source[scanner.currentPosition] == 'u') {
3188 scanner.currentPosition++;
3191 .getNumericValue(source[scanner.currentPosition++])) > 15
3194 .getNumericValue(source[scanner.currentPosition++])) > 15
3197 .getNumericValue(source[scanner.currentPosition++])) > 15
3200 .getNumericValue(source[scanner.currentPosition++])) > 15
3201 || c4 < 0) { //error don't
3204 scanner.currentCharacter = 'A';
3205 } //something different from \n and \r
3207 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3210 while (scanner.currentCharacter != '\r'
3211 && scanner.currentCharacter != '\n') {
3213 scanner.startPosition = scanner.currentPosition;
3214 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3215 && (source[scanner.currentPosition] == 'u')) {
3216 //-------------unicode traitement
3218 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3219 scanner.currentPosition++;
3220 while (source[scanner.currentPosition] == 'u') {
3221 scanner.currentPosition++;
3224 .getNumericValue(source[scanner.currentPosition++])) > 15
3227 .getNumericValue(source[scanner.currentPosition++])) > 15
3230 .getNumericValue(source[scanner.currentPosition++])) > 15
3233 .getNumericValue(source[scanner.currentPosition++])) > 15
3234 || c4 < 0) { //error don't
3237 scanner.currentCharacter = 'A';
3238 } //something different from \n
3241 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3245 if (scanner.recordLineSeparator
3246 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3247 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3248 // only record line positions we
3249 // have not recorded yet
3250 scanner.pushLineSeparator();
3251 if (this.scanner.taskTags != null) {
3252 this.scanner.checkTaskTag(this.scanner
3253 .getCurrentTokenStartPosition(), this.scanner
3254 .getCurrentTokenEndPosition());
3260 if (test > 0) { //traditional and annotation
3262 boolean star = false;
3263 // consume next character
3264 scanner.unicodeAsBackSlash = false;
3265 // if (((scanner.currentCharacter =
3266 // source[scanner.currentPosition++]) ==
3268 // (source[scanner.currentPosition] ==
3270 // scanner.getNextUnicodeChar();
3272 if (scanner.withoutUnicodePtr != 0) {
3273 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3276 if (scanner.currentCharacter == '*') {
3280 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3281 && (source[scanner.currentPosition] == 'u')) {
3282 //-------------unicode traitement
3284 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3285 scanner.currentPosition++;
3286 while (source[scanner.currentPosition] == 'u') {
3287 scanner.currentPosition++;
3290 .getNumericValue(source[scanner.currentPosition++])) > 15
3293 .getNumericValue(source[scanner.currentPosition++])) > 15
3296 .getNumericValue(source[scanner.currentPosition++])) > 15
3299 .getNumericValue(source[scanner.currentPosition++])) > 15
3300 || c4 < 0) { //error don't
3303 scanner.currentCharacter = 'A';
3304 } //something different from * and /
3306 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3309 //loop until end of comment */
3310 while ((scanner.currentCharacter != '/') || (!star)) {
3311 star = scanner.currentCharacter == '*';
3313 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3314 && (source[scanner.currentPosition] == 'u')) {
3315 //-------------unicode traitement
3317 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3318 scanner.currentPosition++;
3319 while (source[scanner.currentPosition] == 'u') {
3320 scanner.currentPosition++;
3323 .getNumericValue(source[scanner.currentPosition++])) > 15
3326 .getNumericValue(source[scanner.currentPosition++])) > 15
3329 .getNumericValue(source[scanner.currentPosition++])) > 15
3332 .getNumericValue(source[scanner.currentPosition++])) > 15
3333 || c4 < 0) { //error don't
3336 scanner.currentCharacter = 'A';
3337 } //something different from * and
3340 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3344 if (this.scanner.taskTags != null) {
3345 this.scanner.checkTaskTag(this.scanner
3346 .getCurrentTokenStartPosition(), this.scanner
3347 .getCurrentTokenEndPosition());
3354 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3355 scanner.scanIdentifierOrKeyword(false);
3358 if (Character.isDigit(scanner.currentCharacter)) {
3359 scanner.scanNumber(false);
3363 //-----------------end switch while
3364 // try--------------------
3365 } catch (IndexOutOfBoundsException e) {
3366 break; // read until EOF
3367 } catch (InvalidInputException e) {
3368 return false; // no clue
3371 if (scanner.recordLineSeparator) {
3372 // compilationUnit.compilationResult.lineSeparatorPositions =
3373 // scanner.getLineEnds();
3375 // check placement anomalies against other kinds of brackets
3376 for (int kind = 0; kind < BracketKinds; kind++) {
3377 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3378 int start = leftPositions[kind][leftIndex]; // deepest
3380 // find matching closing bracket
3381 int depth = leftDepths[kind][leftIndex];
3383 for (int i = 0; i < rightCount[kind]; i++) {
3384 int pos = rightPositions[kind][i];
3385 // want matching bracket further in source with same
3387 if ((pos > start) && (depth == rightDepths[kind][i])) {
3392 if (end < 0) { // did not find a good closing match
3393 problemReporter.unmatchedBracket(start, referenceContext,
3394 compilationUnit.compilationResult);
3397 // check if even number of opening/closing other brackets
3398 // in between this pair of brackets
3400 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3401 for (int i = 0; i < leftCount[otherKind]; i++) {
3402 int pos = leftPositions[otherKind][i];
3403 if ((pos > start) && (pos < end))
3406 for (int i = 0; i < rightCount[otherKind]; i++) {
3407 int pos = rightPositions[otherKind][i];
3408 if ((pos > start) && (pos < end))
3412 problemReporter.unmatchedBracket(start, referenceContext,
3413 compilationUnit.compilationResult); //bracket
3419 // too many opening brackets ?
3420 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3421 anomaliesDetected = true;
3422 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3423 - i - 1], referenceContext, compilationUnit.compilationResult);
3425 // too many closing brackets ?
3426 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3427 anomaliesDetected = true;
3428 problemReporter.unmatchedBracket(rightPositions[kind][i],
3429 referenceContext, compilationUnit.compilationResult);
3431 if (anomaliesDetected)
3434 return anomaliesDetected;
3435 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3436 return anomaliesDetected;
3437 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3438 return anomaliesDetected;
3441 protected void pushOnAstLengthStack(int pos) {
3443 astLengthStack[++astLengthPtr] = pos;
3444 } catch (IndexOutOfBoundsException e) {
3445 int oldStackLength = astLengthStack.length;
3446 int[] oldPos = astLengthStack;
3447 astLengthStack = new int[oldStackLength + StackIncrement];
3448 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3449 astLengthStack[astLengthPtr] = pos;
3452 protected void pushOnAstStack(AstNode node) {
3454 * add a new obj on top of the ast stack
3457 astStack[++astPtr] = node;
3458 } catch (IndexOutOfBoundsException e) {
3459 int oldStackLength = astStack.length;
3460 AstNode[] oldStack = astStack;
3461 astStack = new AstNode[oldStackLength + AstStackIncrement];
3462 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3463 astPtr = oldStackLength;
3464 astStack[astPtr] = node;
3467 astLengthStack[++astLengthPtr] = 1;
3468 } catch (IndexOutOfBoundsException e) {
3469 int oldStackLength = astLengthStack.length;
3470 int[] oldPos = astLengthStack;
3471 astLengthStack = new int[oldStackLength + AstStackIncrement];
3472 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3473 astLengthStack[astLengthPtr] = 1;