X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java index e3bea19..8d65f5b 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java @@ -11,32 +11,43 @@ Contributors: package net.sourceforge.phpdt.internal.compiler.parser; import java.util.ArrayList; -import java.util.Hashtable; -import net.sourceforge.phpdt.core.compiler.*; -import net.sourceforge.phpdt.internal.compiler.parser.*; +import net.sourceforge.phpdt.core.compiler.CharOperation; +import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; +import net.sourceforge.phpdt.core.compiler.InvalidInputException; +import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext; +import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants; +import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter; import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode; +import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference; +import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration; import net.sourceforge.phpeclipse.phpeditor.PHPString; -import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords; import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.ui.texteditor.MarkerUtilities; + import test.PHPParserSuperclass; -public class Parser extends PHPParserSuperclass implements PHPKeywords, ITerminalSymbols { +public class Parser extends PHPParserSuperclass implements ITerminalSymbols, ParserBasicInformation { + //internal data for the automat + protected final static int StackIncrement = 255; + protected int stateStackTop; + protected int[] stack = new int[StackIncrement]; + public int firstToken; // handle for multiple parsing goals + public int lastAct; //handle for multiple parsing goals + protected RecoveredElement currentElement; - public static final int ERROR = 2; - public static final int WARNING = 1; - public static final int INFO = 0; + public static boolean VERBOSE_RECOVERY = false; + protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies - public static final boolean DEBUG = false; - //scanner token + //scanner token public Scanner scanner; - private IFile fileToParse; private ArrayList phpList; private int currentPHPString; @@ -46,7 +57,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina private String str; // current character -// char ch; + // char ch; // current token int token; @@ -66,7 +77,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina private String stringValue; /** Contains the current expression. */ - // private StringBuffer expression; + // private StringBuffer expression; private boolean phpMode; @@ -146,12 +157,24 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina // final static int TokenNameOR = 159; // final static int TokenNameAT = 153; // @ - public Parser() { + protected Parser() { + this.currentPHPString = 0; + // PHPParserSuperclass.fileToParse = fileToParse; + this.phpList = null; + this.str = ""; + this.token = TokenNameEOF; + // this.chIndx = 0; + // this.rowCount = 1; + // this.columnCount = 0; + this.phpEnd = false; + // getNextToken(); + + this.initializeScanner(); } public void setFileToParse(IFile fileToParse) { this.currentPHPString = 0; - this.fileToParse = fileToParse; + PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; this.str = ""; this.token = TokenNameEOF; @@ -159,27 +182,27 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina this.initializeScanner(); } /** - * Class Constructor. + * ClassDeclaration Constructor. * *@param s *@param sess Description of Parameter *@see */ public Parser(IFile fileToParse) { -// if (keywordMap == null) { -// keywordMap = new HashMap(); -// for (int i = 0; i < PHP_KEYWORS.length; i++) { -// keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i])); -// } -// } + // if (keywordMap == null) { + // keywordMap = new HashMap(); + // for (int i = 0; i < PHP_KEYWORS.length; i++) { + // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i])); + // } + // } this.currentPHPString = 0; - this.fileToParse = fileToParse; + PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; this.str = ""; this.token = TokenNameEOF; -// this.chIndx = 0; -// this.rowCount = 1; -// this.columnCount = 0; + // this.chIndx = 0; + // this.rowCount = 1; + // this.columnCount = 0; this.phpEnd = false; // getNextToken(); @@ -192,45 +215,10 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina /** * Create marker for the parse error */ - private void setMarker( - String message, - int charStart, - int charEnd, - int errorLevel) - throws CoreException { + private void setMarker(String message, int charStart, int charEnd, int errorLevel) throws CoreException { setMarker(fileToParse, message, charStart, charEnd, errorLevel); } - public static void setMarker( - IFile file, - String message, - int charStart, - int charEnd, - int errorLevel) - throws CoreException { - if (file != null) { - Hashtable attributes = new Hashtable(); - MarkerUtilities.setMessage(attributes, message); - switch (errorLevel) { - case ERROR : - attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR)); - break; - case WARNING : - attributes.put( - IMarker.SEVERITY, - new Integer(IMarker.SEVERITY_WARNING)); - break; - case INFO : - attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO)); - break; - } - MarkerUtilities.setCharStart(attributes, charStart); - MarkerUtilities.setCharEnd(attributes, charEnd); - // setLineNumber(attributes, lineNumber); - MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM); - } - } - /** * This method will throw the SyntaxError. * It will add the good lines and columns to the Error @@ -239,28 +227,24 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina */ private void throwSyntaxError(String error) { -// if (str.length() < chIndx) { -// chIndx--; -// } -// // read until end-of-line -// int eol = chIndx; -// while (str.length() > eol) { -// ch = str.charAt(eol++); -// if (ch == '\n') { -// eol--; -// break; -// } -// } -// throw new SyntaxError( -// rowCount, -// chIndx - columnCount + 1, -// str.substring(columnCount, eol), -// error); - throw new SyntaxError( - 1, - 1, - "", - error); + // if (str.length() < chIndx) { + // chIndx--; + // } + // // read until end-of-line + // int eol = chIndx; + // while (str.length() > eol) { + // ch = str.charAt(eol++); + // if (ch == '\n') { + // eol--; + // break; + // } + // } + // throw new SyntaxError( + // rowCount, + // chIndx - columnCount + 1, + // str.substring(columnCount, eol), + // error); + throw new SyntaxError(1, 1, "", error); } /** @@ -273,23 +257,27 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina throw new SyntaxError(startRow, 0, " ", error); } + private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) { + problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, compilationUnit.compilationResult); + throw new SyntaxError(1, 0, " ", error); + } /** * Method Declaration. * *@see */ -// private void getChar() { -// if (str.length() > chIndx) { -// ch = str.charAt(chIndx++); -// -// return; -// } -// -// chIndx = str.length() + 1; -// ch = ' '; -// // token = TokenNameEOF; -// phpEnd = true; -// } + // private void getChar() { + // if (str.length() > chIndx) { + // ch = str.charAt(chIndx++); + // + // return; + // } + // + // chIndx = str.length() + 1; + // ch = ' '; + // // token = TokenNameEOF; + // phpEnd = true; + // } /** * gets the next token from input @@ -297,12 +285,11 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina private void getNextToken() throws CoreException { try { token = scanner.getNextToken(); - if (DEBUG) { + if (Scanner.DEBUG) { int currentEndPosition = scanner.getCurrentTokenEndPosition(); int currentStartPosition = scanner.getCurrentTokenStartPosition(); - System.out.print( - currentStartPosition + "," + currentEndPosition + ": "); + System.out.print(currentStartPosition + "," + currentEndPosition + ": "); System.out.println(scanner.toStringAction(token)); } } catch (InvalidInputException e) { @@ -310,616 +297,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } return; - // boolean phpFound = false; - // char ch2; - // - // phpEnd = false; - // try { - // if (!phpMode) { - // - // while (str.length() > chIndx) { - // token = TokenNameERROR; - // ch = str.charAt(chIndx++); - // - // if (ch == '\n') { - // rowCount++; - // } - // if (ch == '<') { - // ch2 = str.charAt(chIndx++); - // if (ch2 == '?') { - // ch2 = str.charAt(chIndx++); - // if (Character.isWhitespace(ch2)) { - // // php start - // phpMode = true; - // phpFound = true; - // break; - // } else if (ch2 == 'p' || ch2 == 'P') { - // ch2 = str.charAt(chIndx++); - // if (ch2 == 'h' || ch2 == 'H') { - // ch2 = str.charAt(chIndx++); - // if (ch2 == 'p' || ch2 == 'P') { - // phpMode = true; - // phpFound = true; - // break; - // } - // chIndx--; - // } - // chIndx--; - // } - // chIndx--; - // } - // chIndx--; - // } - // } - // - // } - // - // if (phpMode) { - // while (str.length() > chIndx) { - // ch = str.charAt(chIndx++); - // token = TokenNameERROR; - // if (ch == '\n') { - // rowCount++; - // columnCount = chIndx; - // continue; // while loop - // } - // if (str.length() == chIndx) { - // phpEnd = true; - // } - // if (!Character.isWhitespace(ch)) { - // if (ch == '$') { - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '{') { - // chIndx++; - // token = TokenNameDOLLAROPEN; - // return; - // } - // } - // getIdentifier(); - // return; - // } - // if ((ch >= 'a' && ch <= 'z') - // || (ch >= 'A' && ch <= 'Z') - // || (ch == '_') - // || (ch == '$')) { - // getIdentifier(); - // return; - // } - // if (ch >= '0' && ch <= '9') { - // getNumber(); - // return; - // } - // if (ch == '/') { - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '/') { - // ch = '/'; - // chIndx++; - // // read comment until end of line: - // while ((str.length() > chIndx) - // && (ch != '\n')) { - // ch = str.charAt(chIndx++); - // if (ch == '?') { - // ch2 = str.charAt(chIndx); - // if (ch2 == '>') { - // chIndx++; - // token = TokenNameHTML; - // // php end - // phpMode = false; - // phpEnd = true; - // return; - // } - // } - // } - // rowCount++; - // continue; - // - // } else if (str.charAt(chIndx) == '*') { - // chIndx++; - // // multi line comment: - // while (str.length() > chIndx) { - // if (str.charAt(chIndx) == '*' - // && (str.length() > (chIndx + 1)) - // && str.charAt(chIndx + 1) == '/') { - // chIndx += 2; - // break; - // } - // ch = str.charAt(chIndx++); - // if (ch == '\n') { - // rowCount++; - // columnCount = chIndx; - // } - // } - // continue; - // } - // } - // } else if (ch == '#') { - // // read comment until end of line: - // while ((str.length() > chIndx) && (ch != '\n')) { - // ch = str.charAt(chIndx++); - // if (ch == '?') { - // ch2 = str.charAt(chIndx); - // if (ch2 == '>') { - // chIndx++; - // token = TokenNameHTML; - // // php end - // phpMode = false; - // phpEnd = true; - // return; - // } - // } - // } - // rowCount++; - // continue; - // - // } else if (ch == '"') { - // getString( - // '"', - // TokenNameStringInterpolated, - // "Open string character '\"' at end of file."); - // return; - // } else if (ch == '\'') { - // getString( - // '\'', - // TokenNameStringConstant, - // "Open string character \"'\" at end of file."); - // return; - // } else if (ch == '`') { - // getString( - // '`', - // TokenNameStringConstant, - // "Open string character \"`\" at end of file."); - // setMarker( - // "Other string delimiters prefered (found \"`\").", - // rowCount, - // PHPParser.INFO); - // return; - // } - // - // switch (ch) { - // - // case '(' : - // token = TokenNameLPAREN; - // - // break; - // case ')' : - // token = TokenNameRPAREN; - // - // break; - // case '{' : - // token = TokenNameLBRACE; - // - // break; - // case '}' : - // token = TokenNameRBRACE; - // - // break; - // case '[' : - // token = TokenNameLBRACKET; - // - // break; - // case ']' : - // token = TokenNameRBRACKET; - // - // break; - // case ',' : - // token = TokenNameCOMMA; - // - // break; - // case '?' : - // token = TokenNameQUESTION; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '>') { - // chIndx++; - // token = TokenNameHTML; - // // php end - // phpMode = false; - // phpEnd = true; - // break; - // } - // } - // - // break; - // case '@' : - // token = TokenNameAT; - // break; - // case '~' : - // token = TokenNameTWIDDLE; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameTWIDDLE_EQUAL; - // - // break; - // } - // } - // break; - // case '.' : - // token = TokenNameDOT; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameDOT_EQUAL; - // - // break; - // } - // } - // - // break; - // case '"' : - // token = TokenNameStringLiteral; - // - // break; - // case '%' : - // token = TokenNameREMAINDER; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameREMAINDER_EQUAL; - // - // break; - // } - // } - // break; - // case ';' : - // token = TokenNameSEMICOLON; - // - // break; - // case '^' : - // token = TokenNameXOR; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameXOR_EQUAL; - // - // break; - // } - // } - // break; - // case '/' : - // token = TokenNameDIVIDE; - // - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameDIVIDE_EQUAL; - // - // break; - // } - // } - // - // break; - // case '*' : - // token = TokenNameMULTIPLY; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '*') { - // chIndx++; - // token = TokenNameXOR; - // - // break; - // } - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameMULTIPLY_EQUAL; - // - // break; - // } - // } - // - // break; - // case '+' : - // token = TokenNamePLUS; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '+') { - // chIndx++; - // token = TokenNamePLUS_PLUS; - // - // break; - // } - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNamePLUS_EQUAL; - // - // break; - // } - // } - // break; - // case '-' : - // token = TokenNameMINUS; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '-') { - // chIndx++; - // token = TokenNameMINUS_MINUS; - // - // break; - // } - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameMINUS_EQUAL; - // - // break; - // } - // if (str.charAt(chIndx) == '>') { - // chIndx++; - // token = TokenNameMINUS_GREATER; - // - // break; - // } - // } - // - // break; - // case '=' : - // token = TokenNameEQUAL; - // - // if (str.length() > chIndx) { - // ch = str.charAt(chIndx); - // - // if (ch == '=') { - // chIndx++; - // token = TokenNameEQUAL_EQUAL; - // if (str.length() > chIndx) { - // ch = str.charAt(chIndx); - // - // if (ch == '=') { - // chIndx++; - // token = - // TokenNameEQUAL_EQUAL_EQUAL; - // } - // } - // break; - // } - // if (ch == '>') { - // chIndx++; - // token = TokenNameEQUAL_GREATER; - // - // break; - // } - // } - // - // break; - // case '!' : - // token = TokenNameNOT; - // - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameNOT_EQUAL; - // if (str.length() > chIndx) { - // ch = str.charAt(chIndx); - // - // if (ch == '=') { - // chIndx++; - // token = - // TokenNameNOT_EQUAL_EQUAL; - // } - // } - // break; - // } - // } - // - // break; - // case '>' : - // token = TokenNameGREATER; - // - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameGREATER_EQUAL; - // break; - // } - // if (str.charAt(chIndx) == '>') { - // chIndx++; - // token = TokenNameRIGHT_SHIFT; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = - // TokenNameRIGHT_SHIFT_EQUAL; - // break; - // } - // } - // break; - // } - // } - // - // break; - // case '<' : - // token = TokenNameLESS; - // - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameLESS_EQUAL; - // - // break; - // } - // if (str.charAt(chIndx) == '<') { - // chIndx++; - // token = TokenNameLEFT_SHIFT; - // if (str.charAt(chIndx) == '<') { - // // heredoc - // int startRow = rowCount; - // if (str.length() > chIndx) { - // - // ch = str.charAt(++chIndx); - // if ((ch >= 'a' && ch <= 'z') - // || (ch >= 'A' && ch <= 'Z') - // || (ch == '_')) { - // chIndx++; - // getIdentifier(); - // token = - // TokenNameStringConstant; - // while (str.length() - // > chIndx) { - // ch = - // str.charAt( - // chIndx++); - // if (ch == '\n') { - // if (str.length() - // >= chIndx - // + identifier - // .length()) { - // if (str - // .substring( - // chIndx, - // chIndx - // + identifier - // .length()) - // .equals(identifier)) { - // chIndx - // += identifier - // .length(); - // return; - // } - // } - // } - // } - // } - // } - // throwSyntaxError( - // "Open heredoc syntax after operator '<<<'.", - // startRow); - // } else if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameLEFT_SHIFT_EQUAL; - // break; - // } - // break; - // } - // } - // - // break; - // - // case '|' : - // token = TokenNameOR; - // - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '|') { - // chIndx++; - // token = TokenNameOR_OR; - // break; - // } - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameOR_EQUAL; - // break; - // } - // } - // - // break; - // case '&' : - // token = TokenNameAND; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == '&') { - // chIndx++; - // token = TokenNameAND_AND; - // break; - // } - // if (str.charAt(chIndx) == '=') { - // chIndx++; - // token = TokenNameAND_EQUAL; - // break; - // } - // break; - // } - // - // break; - // case ':' : - // token = TokenNameCOLON; - // if (str.length() > chIndx) { - // if (str.charAt(chIndx) == ':') { - // chIndx++; - // token = TokenNameCOLON_COLON; - // } - // } - // break; - // // case '#' : - // // token = TokenNameHASH; - // // - // // break; - // // case '@' : - // // token = TokenNameAT; - // // - // // break; - // default : - // throwSyntaxError( - // "unexpected character: '" + ch + "'"); - // } - // - // if (token == TokenNameERROR) { - // throwSyntaxError("token not found"); - // } - // - // return; - // } - // } - // } - // } catch (StringIndexOutOfBoundsException e) { - // // catched from charAt - // } - // - // chIndx = str.length() + 1; - // ch = ' '; - // token = TokenNameEOF; - // phpEnd = true; - // //PHPString temp; - // // if (phpList != null) { - // // if (currentPHPString < phpList.size()) { - // // token = TokenNameUNDEFINED; - // // temp = (PHPString) phpList.get(currentPHPString++); - // // this.str = temp.getPHPString(); - // // this.token = TokenNameEOF; - // // this.chIndx = 0; - // // this.rowCount = temp.getLineNumber(); - // // this.columnCount = 0; - // // getNextToken(); - // // phpEnd = true; - // // } else { - // // token = TokenNameUNDEFINED; - // // return; - // // } - // // } - } - - // /** - // * Get an identifier. - // */ - // private void getIdentifier() { - // // StringBuffer ident = new StringBuffer(); - // int startPosition = chIndx - 1; - // // ident.append(ch); - // if (ch == '$') { - // getChar(); - // // attention recursive call: - // getIdentifier(); - // token = TokenNameVariable; - // return; - // } else { - // token = TokenNameIdentifier; - // } - // - // getChar(); - // - // //this will read the buffer until the next character is a forbidden character for identifier - // while ((ch >= 'a' && ch <= 'z') - // || (ch >= 'A' && ch <= 'Z') - // || (ch >= '0' && ch <= '9') - // || (ch == '_')) { - // // ident.append(ch); - // getChar(); - // } - // int endPosition = chIndx--; - // int length = (--endPosition) - startPosition; - // - // identifier = str.substring(startPosition, endPosition); - // // System.out.println(identifier); - // - // // determine if this identitfer is a keyword - // // @todo improve this in future version - // Integer i = (Integer) keywordMap.get(identifier.toLowerCase()); - // if (i != null) { - // token = i.intValue(); - // } - // } + } /** * Get a number. @@ -928,137 +306,137 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina * if it's a double the number will be stored in longNumber and the token will have the * value {@link Parser#TokenNameINT_NUMBER} */ -// private void getNumber() { -// StringBuffer inum = new StringBuffer(); -// char dFlag = ' '; -// int numFormat = 10; -// -// // save first digit -// char firstCh = ch; -// inum.append(ch); -// -// getChar(); -// // determine number conversions: -// if (firstCh == '0') { -// switch (ch) { -// case 'b' : -// numFormat = 2; -// getChar(); -// break; -// case 'B' : -// numFormat = 2; -// getChar(); -// break; -// case 'o' : -// numFormat = 8; -// getChar(); -// break; -// case 'O' : -// numFormat = 8; -// getChar(); -// break; -// case 'x' : -// numFormat = 16; -// getChar(); -// break; -// case 'X' : -// numFormat = 16; -// getChar(); -// break; -// } -// } -// -// if (numFormat == 16) { -// while ((ch >= '0' && ch <= '9') -// || (ch >= 'a' && ch <= 'f') -// || (ch >= 'A' && ch <= 'F')) { -// inum.append(ch); -// getChar(); -// } -// } else { -// while ((ch >= '0' && ch <= '9') -// || (ch == '.') -// || (ch == 'E') -// || (ch == 'e')) { -// if ((ch == '.') || (ch == 'E') || (ch == 'e')) { -// if (ch == '.' && dFlag != ' ') { -// break; -// } -// if ((dFlag == 'E') || (dFlag == 'e')) { -// break; -// } -// dFlag = ch; -// inum.append(ch); -// getChar(); -// if ((ch == '-') || (ch == '+')) { -// inum.append(ch); -// getChar(); -// } -// } else { -// inum.append(ch); -// getChar(); -// } -// } -// } -// chIndx--; -// -// try { -// if (dFlag != ' ') { -// doubleNumber = new Double(inum.toString()); -// token = TokenNameDoubleLiteral; -// return; -// } else { -// longNumber = Long.valueOf(inum.toString(), numFormat); -// token = TokenNameIntegerLiteral; -// return; -// } -// -// } catch (Throwable e) { -// throwSyntaxError("Number format error: " + inum.toString()); -// } -// } -// -// /** -// * Get a String. -// * @param openChar the opening char ('\'', '"', '`') -// * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING} -// * @param errorMsg the error message in case of parse error in the string -// */ -// private void getString( -// final char openChar, -// final int typeString, -// final String errorMsg) { -// StringBuffer sBuffer = new StringBuffer(); -// boolean openString = true; -// int startRow = rowCount; -// while (str.length() > chIndx) { -// ch = str.charAt(chIndx++); -// if (ch == '\\') { -// sBuffer.append(ch); -// if (str.length() > chIndx) { -// ch = str.charAt(chIndx++); -// sBuffer.append(ch); -// } -// } else if (ch == openChar) { -// openString = false; -// break; -// } else if (ch == '\n') { -// rowCount++; -// columnCount = chIndx; -// } else { -// sBuffer.append(ch); -// } -// } -// if (openString) { -// if (typeString == TokenNameStringConstant) { -// throwSyntaxError(errorMsg, startRow); -// } else { -// throwSyntaxError(errorMsg); -// } -// } -// token = typeString; -// stringValue = sBuffer.toString(); -// } + // private void getNumber() { + // StringBuffer inum = new StringBuffer(); + // char dFlag = ' '; + // int numFormat = 10; + // + // // save first digit + // char firstCh = ch; + // inum.append(ch); + // + // getChar(); + // // determine number conversions: + // if (firstCh == '0') { + // switch (ch) { + // case 'b' : + // numFormat = 2; + // getChar(); + // break; + // case 'B' : + // numFormat = 2; + // getChar(); + // break; + // case 'o' : + // numFormat = 8; + // getChar(); + // break; + // case 'O' : + // numFormat = 8; + // getChar(); + // break; + // case 'x' : + // numFormat = 16; + // getChar(); + // break; + // case 'X' : + // numFormat = 16; + // getChar(); + // break; + // } + // } + // + // if (numFormat == 16) { + // while ((ch >= '0' && ch <= '9') + // || (ch >= 'a' && ch <= 'f') + // || (ch >= 'A' && ch <= 'F')) { + // inum.append(ch); + // getChar(); + // } + // } else { + // while ((ch >= '0' && ch <= '9') + // || (ch == '.') + // || (ch == 'E') + // || (ch == 'e')) { + // if ((ch == '.') || (ch == 'E') || (ch == 'e')) { + // if (ch == '.' && dFlag != ' ') { + // break; + // } + // if ((dFlag == 'E') || (dFlag == 'e')) { + // break; + // } + // dFlag = ch; + // inum.append(ch); + // getChar(); + // if ((ch == '-') || (ch == '+')) { + // inum.append(ch); + // getChar(); + // } + // } else { + // inum.append(ch); + // getChar(); + // } + // } + // } + // chIndx--; + // + // try { + // if (dFlag != ' ') { + // doubleNumber = new Double(inum.toString()); + // token = TokenNameDoubleLiteral; + // return; + // } else { + // longNumber = Long.valueOf(inum.toString(), numFormat); + // token = TokenNameIntegerLiteral; + // return; + // } + // + // } catch (Throwable e) { + // throwSyntaxError("Number format error: " + inum.toString()); + // } + // } + // + // /** + // * Get a String. + // * @param openChar the opening char ('\'', '"', '`') + // * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING} + // * @param errorMsg the error message in case of parse error in the string + // */ + // private void getString( + // final char openChar, + // final int typeString, + // final String errorMsg) { + // StringBuffer sBuffer = new StringBuffer(); + // boolean openString = true; + // int startRow = rowCount; + // while (str.length() > chIndx) { + // ch = str.charAt(chIndx++); + // if (ch == '\\') { + // sBuffer.append(ch); + // if (str.length() > chIndx) { + // ch = str.charAt(chIndx++); + // sBuffer.append(ch); + // } + // } else if (ch == openChar) { + // openString = false; + // break; + // } else if (ch == '\n') { + // rowCount++; + // columnCount = chIndx; + // } else { + // sBuffer.append(ch); + // } + // } + // if (openString) { + // if (typeString == TokenNameStringConstant) { + // throwSyntaxError(errorMsg, startRow); + // } else { + // throwSyntaxError(errorMsg); + // } + // } + // token = typeString; + // stringValue = sBuffer.toString(); + // } // public void htmlParserTester(String input) { // int lineNumber = 1; @@ -1278,9 +656,9 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } } this.token = TokenNameEOF; -// this.chIndx = 0; -// this.rowCount = rowCount; -// this.columnCount = 0; + // this.chIndx = 0; + // this.rowCount = rowCount; + // this.columnCount = 0; this.phpEnd = false; this.phpMode = true; scanner.setSource(s.toCharArray()); @@ -1291,7 +669,10 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina if (token != TokenNameEOF && token != TokenNameERROR) { statementList(); } - if (token != TokenNameEOF && token != TokenNameERROR) { + if (token != TokenNameEOF) { + if (token == TokenNameERROR) { + throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")"); + } if (token == TokenNameRPAREN) { throwSyntaxError("Too many closing ')'; end-of-file not reached."); } @@ -1320,11 +701,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina throw err; } else { // setMarker(err.getMessage(), err.getLine(), ERROR); - setMarker( - err.getMessage(), - scanner.getCurrentTokenStartPosition(), - scanner.getCurrentTokenEndPosition(), - ERROR); + setMarker(err.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR); } // if an error occured, // try to find keywords 'class' or 'function' @@ -1342,29 +719,55 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } while (true); } - - /** - * Parses a string with php tags - * i.e. '<body> <?php phpinfo() ?> </body>' - */ - public void parse(String s) throws CoreException { + public void init(String s) { this.str = s; this.token = TokenNameEOF; -// this.chIndx = 0; -// this.rowCount = 1; -// this.columnCount = 0; + // this.chIndx = 0; + // this.rowCount = 1; + // this.columnCount = 0; this.phpEnd = false; this.phpMode = false; /* scanner initialization */ scanner.setSource(s.toCharArray()); scanner.setPHPMode(false); + } + + protected void initialize() { + compilationUnit = null; + referenceContext = null; + this.str = ""; + this.token = TokenNameEOF; + // this.chIndx = 0; + // this.rowCount = 1; + // this.columnCount = 0; + this.phpEnd = false; + this.phpMode = false; + scanner.setPHPMode(false); + } + /** + * Parses a string with php tags + * i.e. '<body> <?php phpinfo() ?> </body>' + */ + public void parse(String s) throws CoreException { + init(s); + parse(); + } + + /** + * Parses a string with php tags + * i.e. '<body> <?php phpinfo() ?> </body>' + */ + protected void parse() throws CoreException { getNextToken(); do { try { if (token != TokenNameEOF && token != TokenNameERROR) { statementList(); } - if (token != TokenNameEOF && token != TokenNameERROR) { + if (token != TokenNameEOF) { + if (token == TokenNameERROR) { + throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")"); + } if (token == TokenNameRPAREN) { throwSyntaxError("Too many closing ')'; end-of-file not reached."); } @@ -1390,11 +793,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina return; } catch (SyntaxError sytaxErr1) { // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR); - setMarker( - sytaxErr1.getMessage(), - scanner.getCurrentTokenStartPosition(), - scanner.getCurrentTokenEndPosition(), - ERROR); + setMarker(sytaxErr1.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR); try { // if an error occured, // try to find keywords 'class' or 'function' @@ -1410,11 +809,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } } catch (SyntaxError sytaxErr2) { // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR); - setMarker( - sytaxErr2.getMessage(), - scanner.getCurrentTokenStartPosition(), - scanner.getCurrentTokenEndPosition(), - ERROR); + setMarker(sytaxErr2.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR); return; } } @@ -1429,9 +824,9 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina this.str = s; this.token = TokenNameEOF; -// this.chIndx = 0; -// this.rowCount = 1; -// this.columnCount = 0; + // this.chIndx = 0; + // this.rowCount = 1; + // this.columnCount = 0; this.phpEnd = false; this.phpMode = false; scanner.setSource(s.toCharArray()); @@ -1445,15 +840,16 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina return outlineInfo; } - private void parseDeclarations( - PHPOutlineInfo outlineInfo, - PHPSegmentWithChildren current, - boolean goBack) { + private boolean isVariable() { + return token == TokenNameVariable || token == TokenNamethis; + } + + private void parseDeclarations(PHPOutlineInfo outlineInfo, OutlineableWithChildren current, boolean goBack) { char[] ident; // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek(); PHPSegmentWithChildren temp; int counter = 0; - + IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); try { while (token != TokenNameEOF && token != TokenNameERROR) { @@ -1463,14 +859,14 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina getNextToken(); } else if (token == TokenNamevar) { getNextToken(); - if (token == TokenNameVariable - && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) { + if (token == TokenNameVariable && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) { ident = scanner.getCurrentIdentifierSource(); - String variableName = new String(ident); + //substring(1) added because PHPVarDeclaration doesn't need the $ anymore + String variableName = new String(ident).substring(1); outlineInfo.addVariable(variableName); getNextToken(); if (token != TokenNameSEMICOLON) { - + getNextToken(); ident = scanner.getCurrentTokenSource(); if (token > TokenNameKEYWORD) { @@ -1480,6 +876,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } else { switch (token) { case TokenNameVariable : + case TokenNamethis : current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); @@ -1490,10 +887,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina scanner.getCurrentTokenStartPosition(), new String(ident))); break; case TokenNameDoubleLiteral : - current - .add(new PHPVarDeclaration( - current, - variableName + doubleNumber, + current.add(new PHPVarDeclaration(current, variableName + doubleNumber, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); break; @@ -1534,8 +928,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina if (token == TokenNameAND) { getNextToken(); } - if (token == TokenNameIdentifier - && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) { + if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) { ident = scanner.getCurrentIdentifierSource(); outlineInfo.addVariable(new String(ident)); temp = new PHPFunctionDeclaration(current, new String(ident), @@ -1547,8 +940,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } } else if (token == TokenNameclass) { getNextToken(); - if (token == TokenNameIdentifier - && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) { + if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) { ident = scanner.getCurrentIdentifierSource(); outlineInfo.addVariable(new String(ident)); temp = new PHPClassDeclaration(current, new String(ident), @@ -1559,15 +951,13 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina getNextToken(); //skip tokens for classname, extends and others until we have the opening '{' - while (token != TokenNameLBRACE - && token != TokenNameEOF - && token != TokenNameERROR) { + while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) { getNextToken(); } parseDeclarations(outlineInfo, temp, true); // stack.pop(); } - } else if (token == TokenNameLBRACE) { + } else if ((token == TokenNameLBRACE) || (token == TokenNameDOLLAR_LBRACE)) { getNextToken(); counter++; } else if (token == TokenNameRBRACE) { @@ -1576,17 +966,13 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina if (counter == 0 && goBack) { return; } - } else if ( - token == TokenNamerequire - || token == TokenNamerequire_once - || token == TokenNameinclude - || token == TokenNameinclude_once) { - ident = scanner.getCurrentTokenSource(); - + } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) { + ident = scanner.getCurrentTokenSource(); + getNextToken(); int startPosition = scanner.getCurrentTokenStartPosition(); expression(); - char[] expr = scanner.getCurrentTokenSource(startPosition); + char[] expr = scanner.getCurrentTokenSource(startPosition); outlineInfo.addVariable(new String(ident)); current.add(new PHPReqIncDeclaration(current, new String(ident), // chIndx - ident.length, @@ -1600,11 +986,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } catch (SyntaxError sytaxErr) { try { // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR); - setMarker( - sytaxErr.getMessage(), - scanner.getCurrentTokenStartPosition(), - scanner.getCurrentTokenEndPosition(), - ERROR); + setMarker(sytaxErr.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR); } catch (CoreException e) { } } @@ -1612,10 +994,11 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina private void statementList() throws CoreException { do { - statement(); + statement(TokenNameEOF); if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) + || (token == TokenNameelse) || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor) @@ -1629,7 +1012,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } while (true); } - private void compoundStatement() throws CoreException { + private void functionBody(MethodDeclaration methodDecl) throws CoreException { // '{' [statement-list] '}' if (token == TokenNameLBRACE) { getNextToken(); @@ -1640,39 +1023,62 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina statementList(); } if (token == TokenNameRBRACE) { + methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); getNextToken(); } else { throwSyntaxError("'}' expected in compound-statement."); } } - private void statement() throws CoreException { + private void statement(int previousToken) throws CoreException { // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) { // char[] ident = scanner.getCurrentIdentifierSource(); // String keyword = new String(ident); + if (token == TokenNameAT) { + getNextToken(); + if (token != TokenNamerequire + && token != TokenNamerequire_once + && token != TokenNameinclude + && token != TokenNameinclude_once + && token != TokenNameIdentifier + && token != TokenNameVariable + && token != TokenNamethis + && token != TokenNameStringInterpolated) { + throwSyntaxError("identifier expected after '@'."); + } + } if (token == TokenNameinclude || token == TokenNameinclude_once) { getNextToken(); - expression(); - if (token == TokenNameSEMICOLON) { - getNextToken(); - } else { - if (token != TokenNameStopPHP) { - throwSyntaxError("';' character after 'include' or 'include_once' expected."); + if (token == TokenNameLPAREN) { + expression(); + if (token == TokenNameSEMICOLON) { + getNextToken(); + } else { + if (previousToken != TokenNameAT && token != TokenNameStopPHP) { + throwSyntaxError("';' expected after 'include' or 'include_once'."); + } + // getNextToken(); } - getNextToken(); + } else { + concatenationExpression(); } + return; } else if (token == TokenNamerequire || token == TokenNamerequire_once) { getNextToken(); //constant(); - expression(); - if (token == TokenNameSEMICOLON) { - getNextToken(); - } else { - if (token != TokenNameStopPHP) { - throwSyntaxError("';' character after 'require' or 'require_once' expected."); + if (token == TokenNameLPAREN) { + expression(); + if (token == TokenNameSEMICOLON) { + getNextToken(); + } else { + if (previousToken != TokenNameAT && token != TokenNameStopPHP) { + throwSyntaxError("';' expected after 'require' or 'require_once'."); + } + // getNextToken(); } - getNextToken(); + } else { + concatenationExpression(); } return; } else if (token == TokenNameif) { @@ -1826,10 +1232,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina foreachStatement(); return; - } else if ( - token == TokenNamecontinue - || token == TokenNamebreak - || token == TokenNamereturn) { + } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) { getNextToken(); if (token != TokenNameSEMICOLON) { expression(); @@ -1953,18 +1356,30 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } return; } else if (token == TokenNamefunction) { + MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); + methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); getNextToken(); - functionDefinition(); + functionDefinition(methodDecl); return; } else if (token == TokenNameclass) { - getNextToken(); - classDeclarator(); - classBody(); + TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult); + typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); + // default super class + typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0); + compilationUnit.types.add(typeDecl); + try { + pushOnAstStack(typeDecl); + getNextToken(); + classDeclarator(typeDecl); + classBody(typeDecl); + } finally { + astPtr--; + astLengthPtr--; + } return; // } else { // throwSyntaxError("Unexpected keyword '" + keyword + "'"); } else if (token == TokenNameLBRACE) { - // compoundStatement getNextToken(); if (token != TokenNameRBRACE) { statementList(); @@ -1984,35 +1399,52 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina return; } else { if (token != TokenNameStopPHP && token != TokenNameEOF) { - throwSyntaxError( - "';' expected after expression (Found token: " - + scanner.toStringAction(token) - + ")"); + throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")"); } getNextToken(); } } } - private void classDeclarator() throws CoreException { + private void classDeclarator(TypeDeclaration typeDecl) throws CoreException { //identifier //identifier 'extends' identifier + if (token == TokenNameIdentifier) { + typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); + typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); + typeDecl.name = scanner.getCurrentIdentifierSource(); getNextToken(); if (token == TokenNameextends) { - getNextToken(); - if (token == TokenNameIdentifier) { + do { getNextToken(); - } else { - throwSyntaxError("Class name expected after keyword 'extends'."); - } - } + if (token == TokenNameIdentifier) { + getNextToken(); + } else { + reportSyntaxError("Class name expected after keyword 'extends'.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition()); + // throwSyntaxError("ClassDeclaration name expected after keyword 'extends'."); + } + } while (token == TokenNameCOMMA); + } } else { - throwSyntaxError("Class name expected after keyword 'class'."); + typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); + typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); + + if (token > TokenNameKEYWORD) { + typeDecl.name = scanner.getCurrentIdentifierSource(); + reportSyntaxError( + "Don't use keyword for class declaration [" + scanner.toStringAction(token) + "].", + typeDecl.sourceStart, + typeDecl.sourceEnd); + // throwSyntaxError("Don't use keyword for class declaration [" + token + "]."); + } + typeDecl.name = new char[] { ' ' }; + reportSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd); + // throwSyntaxError("ClassDeclaration name expected after keyword 'class'."); } } - private void classBody() throws CoreException { + private void classBody(TypeDeclaration typeDecl) throws CoreException { //'{' [class-element-list] '}' if (token == TokenNameLBRACE) { getNextToken(); @@ -2020,6 +1452,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina classElementList(); } if (token == TokenNameRBRACE) { + typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); getNextToken(); } else { throwSyntaxError("'}' expected at end of class body."); @@ -2039,8 +1472,10 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina //class-property //function-definition if (token == TokenNamefunction) { + MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); + methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); getNextToken(); - functionDefinition(); + functionDefinition(methodDecl); } else if (token == TokenNamevar) { getNextToken(); classProperty(); @@ -2060,6 +1495,9 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina constant(); } } else { + if (token == TokenNamethis) { + throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'."); + } throwSyntaxError("Variable expected after keyword 'var'."); } if (token != TokenNameCOMMA) { @@ -2074,17 +1512,36 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } } - private void functionDefinition() throws CoreException { - functionDeclarator(); - compoundStatement(); + private void functionDefinition(MethodDeclaration methodDecl) throws CoreException { + if (astPtr == 0) { + compilationUnit.types.add(methodDecl); + } else { + AstNode node = astStack[astPtr]; + if (node instanceof TypeDeclaration) { + TypeDeclaration typeDecl = ((TypeDeclaration) node); + if (typeDecl.methods == null) { + typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl }; + } else { + AbstractMethodDeclaration[] newMethods; + System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, typeDecl.methods.length); + newMethods[0] = methodDecl; + typeDecl.methods = newMethods; + } + } + } + functionDeclarator(methodDecl); + functionBody(methodDecl); } - private void functionDeclarator() throws CoreException { + private void functionDeclarator(MethodDeclaration methodDecl) throws CoreException { //identifier '(' [parameter-list] ')' if (token == TokenNameAND) { getNextToken(); } if (token == TokenNameIdentifier) { + methodDecl.sourceStart = scanner.getCurrentTokenStartPosition(); + methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); + methodDecl.selector = scanner.getCurrentIdentifierSource(); getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); @@ -2097,8 +1554,14 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in function declaration."); } else { + methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1; getNextToken(); } + } else { + if (token > TokenNameKEYWORD) { + throwSyntaxError("Don't use keyword for function declaration [" + token + "]."); + } + throwSyntaxError("Function name expected after keyword 'function'."); } } // @@ -2119,7 +1582,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina //variable-reference if (token == TokenNameAND) { getNextToken(); - if (token == TokenNameVariable) { + if (isVariable()) { getNextToken(); } else { throwSyntaxError("Variable expected after reference operator '&'."); @@ -2134,6 +1597,9 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } return; } + if (token == TokenNamethis) { + throwSyntaxError("Reserved word '$this' not allowed in parameter declaration."); + } } private void labeledStatementList() throws CoreException { @@ -2143,11 +1609,10 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina do { if (token == TokenNamecase) { getNextToken(); - constant(); + expression(); //constant(); if (token == TokenNameCOLON) { getNextToken(); - if (token == TokenNamecase - || token == TokenNamedefault) { // empty case statement ? + if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ? continue; } statementList(); @@ -2159,9 +1624,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina // rowCount, // PHPParser.INFO); setMarker( - "':' expected after 'case' keyword (Found token: " - + scanner.toStringAction(token) - + ")", + "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), INFO); @@ -2171,10 +1634,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } statementList(); } else { - throwSyntaxError( - "':' character after 'case' constant expected (Found token: " - + scanner.toStringAction(token) - + ")"); + throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")"); } } else { // TokenNamedefault getNextToken(); @@ -2245,26 +1705,30 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';' if (token == TokenNameCOLON) { getNextToken(); - statementList(); - switch (token) { - case TokenNameelse : - getNextToken(); - if (token == TokenNameCOLON) { + if (token != TokenNameendif) { + statementList(); + switch (token) { + case TokenNameelse : getNextToken(); - statementList(); - } else { - if (token == TokenNameif) { //'else if' + if (token == TokenNameCOLON) { getNextToken(); - elseifStatementList(); + if (token != TokenNameendif) { + statementList(); + } } else { - throwSyntaxError("':' expected after 'else'."); + if (token == TokenNameif) { //'else if' + getNextToken(); + elseifStatementList(); + } else { + throwSyntaxError("':' expected after 'else'."); + } } - } - break; - case TokenNameelseif : - getNextToken(); - elseifStatementList(); - break; + break; + case TokenNameelseif : + getNextToken(); + elseifStatementList(); + break; + } } if (token != TokenNameendif) { @@ -2277,7 +1741,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina getNextToken(); } else { // statement [else-statement] - statement(); + statement(TokenNameEOF); if (token == TokenNameelseif) { getNextToken(); if (token == TokenNameLPAREN) { @@ -2294,7 +1758,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina ifStatement(); } else if (token == TokenNameelse) { getNextToken(); - statement(); + statement(TokenNameEOF); } } } @@ -2307,7 +1771,9 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina getNextToken(); if (token == TokenNameCOLON) { getNextToken(); - statementList(); + if (token != TokenNameendif) { + statementList(); + } return; } else { if (token == TokenNameif) { //'else if' @@ -2330,7 +1796,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina if (token == TokenNameLPAREN) { getNextToken(); expression(); - if (token != TokenNameLPAREN) { + if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in else-if-statement."); } getNextToken(); @@ -2338,7 +1804,9 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina throwSyntaxError("':' expected in else-if-statement."); } getNextToken(); - statementList(); + if (token != TokenNameendif) { + statementList(); + } } } @@ -2385,7 +1853,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } getNextToken(); } else { - statement(); + statement(TokenNameEOF); } } @@ -2403,7 +1871,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } getNextToken(); } else { - statement(); + statement(TokenNameEOF); } } @@ -2420,7 +1888,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } getNextToken(); } else { - statement(); + statement(TokenNameEOF); } } @@ -2453,14 +1921,14 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina private void expression() throws CoreException { //todo: find a better way to get the expression -// expression = new StringBuffer(); -// for (int i = chIndx; i < str.length(); i++) { -// if (str.charAt(i) == ';') { -// break; -// } -// expression.append(str.charAt(i)); -// } - + // expression = new StringBuffer(); + // for (int i = chIndx; i < str.length(); i++) { + // if (str.charAt(i) == ';') { + // break; + // } + // expression.append(str.charAt(i)); + // } + // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) { // getNextToken(); // } else { @@ -2475,6 +1943,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina // String ident; char[] ident; boolean castFlag = false; + boolean arrayFlag = false; switch (token) { case TokenNamenew : getNextToken(); @@ -2499,6 +1968,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina break; case TokenNameLPAREN : getNextToken(); + if (token == TokenNameIdentifier) { // check if identifier is a type: // ident = identifier; @@ -2507,20 +1977,34 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina for (int i = 0; i < PHP_TYPES.length; i++) { if (PHP_TYPES[i].equals(str)) { castFlag = true; + if (PHP_TYPES[i].equals("array")) { + arrayFlag = true; + } break; } } - if (castFlag) { + } + + if (castFlag) { + getNextToken(); + if (arrayFlag && token == TokenNameLPAREN) { getNextToken(); - if (token != TokenNameRPAREN) { - throwSyntaxError(") expected after cast-type '" + str + "'."); + if (token == TokenNameRPAREN) { + getNextToken(); + } else { + expression(); + if (token != TokenNameRPAREN) { + throwSyntaxError(") expected after 'array('."); + } } - getNextToken(); - expression(); - break; } - } - if (!castFlag) { + if (token != TokenNameRPAREN) { + throwSyntaxError(") expected after cast-type '" + str + "'."); + } + getNextToken(); + expression(); + break; + } else { expression(); } if (token != TokenNameRPAREN) { @@ -2543,16 +2027,14 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina getNextToken(); break; case TokenNameVariable : + case TokenNamethis : ident = scanner.getCurrentIdentifierSource(); getNextToken(); if (token == TokenNameLBRACE) { getNextToken(); expression(); if (token != TokenNameRBRACE) { - throwSyntaxError( - "'}' expected after variable '" - + new String(ident) - + "' in variable-expression."); + throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression."); } getNextToken(); } else if (token == TokenNameLPAREN) { @@ -2560,10 +2042,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina if (token != TokenNameRPAREN) { expressionList(); if (token != TokenNameRPAREN) { - throwSyntaxError( - "')' expected after variable '" - + new String(ident) - + "' in postfix-expression."); + throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression."); } } getNextToken(); @@ -2578,12 +2057,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina expressionList(); if (token != TokenNameRPAREN) { throwSyntaxError( - "')' expected after identifier '" - + new String(ident) - + "' in postfix-expression." - + "(Found token: " - + scanner.toStringAction(token) - + ")"); + "')' expected after identifier '" + new String(ident) + "' in postfix-expression." + "(Found token: " + scanner.toStringAction(token) + ")"); } } getNextToken(); @@ -2693,9 +2167,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina // rowCount, // PHPParser.INFO); setMarker( - "Avoid using keyword '" - + new String(ident) - + "' as variable name.", + "Avoid using keyword '" + new String(ident) + "' as variable name.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), INFO); @@ -2727,10 +2199,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina break; default : throwSyntaxError("Syntax error after '->' token."); - } while ( - token == TokenNameLBRACKET - || token == TokenNameLPAREN - || token == TokenNameLBRACE) { + } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) { if (token == TokenNameLBRACKET) { getNextToken(); expressionList(); @@ -2738,16 +2207,14 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina throwSyntaxError("] expected after '->'."); } getNextToken(); - } - if (token == TokenNameLPAREN) { + } else if (token == TokenNameLPAREN) { getNextToken(); expressionList(); if (token != TokenNameRPAREN) { throwSyntaxError(") expected after '->'."); } getNextToken(); - } - if (token == TokenNameLBRACE) { + } else if (token == TokenNameLBRACE) { getNextToken(); expression(); if (token != TokenNameRBRACE) { @@ -2784,7 +2251,11 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina // '@' '&' '*' '+' '-' '~' '!' case TokenNameAT : getNextToken(); - castExpression(); + if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) { + statement(TokenNameAT); + } else { + postfixExpression(); // castExpression(); + } break; case TokenNameAND : getNextToken(); @@ -2827,27 +2298,6 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina unaryExpression(); } - private void typeName() throws CoreException { - //'string' 'unset' 'array' 'object' - //'bool' 'boolean' - //'real' 'double' 'float' - //'int' 'integer' - String identifier = ""; - if (token == TokenNameIdentifier) { - char[] ident = scanner.getCurrentIdentifierSource(); - identifier = new String(ident); - String str = identifier.toLowerCase(); - getNextToken(); - for (int i = 0; i < PHP_TYPES.length; i++) { - if (PHP_TYPES[i].equals(str)) { - return; - } - } - } - throwSyntaxError( - "Expected type cast '( )'; Got '" + identifier + "'."); - } - private void assignExpression() throws CoreException { castExpression(); if (token == TokenNameEQUAL) { // = @@ -2898,9 +2348,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina private void multiplicativeExpression() throws CoreException { do { assignExpression(); - if (token != TokenNameMULTIPLY - && token != TokenNameDIVIDE - && token != TokenNameREMAINDER) { + if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) { return; } getNextToken(); @@ -2940,10 +2388,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina private void relationalExpression() throws CoreException { do { shiftExpression(); - if (token != TokenNameLESS - && token != TokenNameGREATER - && token != TokenNameLESS_EQUAL - && token != TokenNameGREATER_EQUAL) { + if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) { return; } getNextToken(); @@ -2953,8 +2398,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina private void identicalExpression() throws CoreException { do { relationalExpression(); - if (token != TokenNameEQUAL_EQUAL_EQUAL - && token != TokenNameNOT_EQUAL_EQUAL) { + if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) { return; } getNextToken(); @@ -3168,10 +2612,7 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina if (token != TokenNameRPAREN) { expressionList(); if (token != TokenNameRPAREN) { - throwSyntaxError( - "')' expected after identifier '" - + new String(ident) - + "' in postfix-expression."); + throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression."); } } getNextToken(); @@ -3197,4 +2638,546 @@ public class Parser extends PHPParserSuperclass implements PHPKeywords, ITermina } } + public void reportSyntaxError() { //int act, int currentKind, int stateStackTop) { + + /* remember current scanner position */ + int startPos = scanner.startPosition; + int currentPos = scanner.currentPosition; + + // String[] expectings; + // String tokenName = name[symbol_index[currentKind]]; + + //fetch all "accurate" possible terminals that could recover the error + // int start, end = start = asi(stack[stateStackTop]); + // while (asr[end] != 0) + // end++; + // int length = end - start; + // expectings = new String[length]; + // if (length != 0) { + // char[] indexes = new char[length]; + // System.arraycopy(asr, start, indexes, 0, length); + // for (int i = 0; i < length; i++) { + // expectings[i] = name[symbol_index[indexes[i]]]; + // } + // } + + //if the pb is an EOF, try to tell the user that they are some + // if (tokenName.equals(UNEXPECTED_EOF)) { + // if (!this.checkAndReportBracketAnomalies(problemReporter())) { + // char[] tokenSource; + // try { + // tokenSource = this.scanner.getCurrentTokenSource(); + // } catch (Exception e) { + // tokenSource = new char[] {}; + // } + // problemReporter().parseError( + // this.scanner.startPosition, + // this.scanner.currentPosition - 1, + // tokenSource, + // tokenName, + // expectings); + // } + // } else { //the next test is HEAVILY grammar DEPENDENT. + // if ((length == 14) + // && (expectings[0] == "=") //$NON-NLS-1$ + // && (expectings[1] == "*=") //$NON-NLS-1$ + // && (expressionPtr > -1)) { + // switch(currentKind) { + // case TokenNameSEMICOLON: + // case TokenNamePLUS: + // case TokenNameMINUS: + // case TokenNameDIVIDE: + // case TokenNameREMAINDER: + // case TokenNameMULTIPLY: + // case TokenNameLEFT_SHIFT: + // case TokenNameRIGHT_SHIFT: + //// case TokenNameUNSIGNED_RIGHT_SHIFT: + // case TokenNameLESS: + // case TokenNameGREATER: + // case TokenNameLESS_EQUAL: + // case TokenNameGREATER_EQUAL: + // case TokenNameEQUAL_EQUAL: + // case TokenNameNOT_EQUAL: + // case TokenNameXOR: + // case TokenNameAND: + // case TokenNameOR: + // case TokenNameOR_OR: + // case TokenNameAND_AND: + // // the ; is not the expected token ==> it ends a statement when an expression is not ended + // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]); + // break; + // case TokenNameRBRACE : + // problemReporter().missingSemiColon(expressionStack[expressionPtr]); + // break; + // default: + // char[] tokenSource; + // try { + // tokenSource = this.scanner.getCurrentTokenSource(); + // } catch (Exception e) { + // tokenSource = new char[] {}; + // } + // problemReporter().parseError( + // this.scanner.startPosition, + // this.scanner.currentPosition - 1, + // tokenSource, + // tokenName, + // expectings); + // this.checkAndReportBracketAnomalies(problemReporter()); + // } + // } else { + char[] tokenSource; + try { + tokenSource = this.scanner.getCurrentTokenSource(); + } catch (Exception e) { + tokenSource = new char[] { + }; + } + // problemReporter().parseError( + // this.scanner.startPosition, + // this.scanner.currentPosition - 1, + // tokenSource, + // tokenName, + // expectings); + this.checkAndReportBracketAnomalies(problemReporter()); + // } + // } + /* reset scanner where it was */ + scanner.startPosition = startPos; + scanner.currentPosition = currentPos; + } + public static final int RoundBracket = 0; + public static final int SquareBracket = 1; + public static final int CurlyBracket = 2; + public static final int BracketKinds = 3; + + protected int[] nestedMethod; //the ptr is nestedType + protected int nestedType, dimensions; + //ast stack + final static int AstStackIncrement = 100; + protected int astPtr; + protected AstNode[] astStack = new AstNode[AstStackIncrement]; + protected int astLengthPtr; + protected int[] astLengthStack; + AstNode[] noAstNodes = new AstNode[AstStackIncrement]; + + public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/ + protected ReferenceContext referenceContext; + protected ProblemReporter problemReporter; + // protected CompilationResult compilationResult; + + /** + * Returns this parser's problem reporter initialized with its reference context. + * Also it is assumed that a problem is going to be reported, so initializes + * the compilation result's line positions. + */ + public ProblemReporter problemReporter() { + if (scanner.recordLineSeparator) { + compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); + } + problemReporter.referenceContext = referenceContext; + return problemReporter; + } + /* + * Reconsider the entire source looking for inconsistencies in {} () [] + */ + public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) { + + scanner.wasAcr = false; + boolean anomaliesDetected = false; + try { + char[] source = scanner.source; + int[] leftCount = { 0, 0, 0 }; + int[] rightCount = { 0, 0, 0 }; + int[] depths = { 0, 0, 0 }; + int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] }; + int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] }; + int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] }; + int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] }; + scanner.currentPosition = scanner.initialPosition; //starting point (first-zero-based char) + while (scanner.currentPosition < scanner.eofPosition) { //loop for jumping over comments + try { + // ---------Consume white space and handles startPosition--------- + boolean isWhiteSpace; + do { + scanner.startPosition = scanner.currentPosition; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace(); + // } else { + if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) { + if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) { + // only record line positions we have not recorded yet + scanner.pushLineSeparator(); + } + } + isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter); + // } + } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition)); + + // -------consume token until } is found--------- + + switch (scanner.currentCharacter) { + case '{' : + { + int index = leftCount[CurlyBracket]++; + if (index == leftPositions[CurlyBracket].length) { + System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index); + System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index); + } + leftPositions[CurlyBracket][index] = scanner.startPosition; + leftDepths[CurlyBracket][index] = depths[CurlyBracket]++; + } + break; + case '}' : + { + int index = rightCount[CurlyBracket]++; + if (index == rightPositions[CurlyBracket].length) { + System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index); + System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index); + } + rightPositions[CurlyBracket][index] = scanner.startPosition; + rightDepths[CurlyBracket][index] = --depths[CurlyBracket]; + } + break; + case '(' : + { + int index = leftCount[RoundBracket]++; + if (index == leftPositions[RoundBracket].length) { + System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index); + System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index); + } + leftPositions[RoundBracket][index] = scanner.startPosition; + leftDepths[RoundBracket][index] = depths[RoundBracket]++; + } + break; + case ')' : + { + int index = rightCount[RoundBracket]++; + if (index == rightPositions[RoundBracket].length) { + System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index); + System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index); + } + rightPositions[RoundBracket][index] = scanner.startPosition; + rightDepths[RoundBracket][index] = --depths[RoundBracket]; + } + break; + case '[' : + { + int index = leftCount[SquareBracket]++; + if (index == leftPositions[SquareBracket].length) { + System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index); + System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index); + } + leftPositions[SquareBracket][index] = scanner.startPosition; + leftDepths[SquareBracket][index] = depths[SquareBracket]++; + } + break; + case ']' : + { + int index = rightCount[SquareBracket]++; + if (index == rightPositions[SquareBracket].length) { + System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index); + System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index); + } + rightPositions[SquareBracket][index] = scanner.startPosition; + rightDepths[SquareBracket][index] = --depths[SquareBracket]; + } + break; + case '\'' : + { + if (scanner.getNextChar('\\')) { + scanner.scanEscapeCharacter(); + } else { // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; + } + // } + } + scanner.getNextChar('\''); + break; + } + case '"' : // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; + } + // } + while (scanner.currentCharacter != '"') { + if (scanner.currentCharacter == '\r') { + if (source[scanner.currentPosition] == '\n') + scanner.currentPosition++; + break; // the string cannot go further that the line + } + if (scanner.currentCharacter == '\n') { + break; // the string cannot go further that the line + } + if (scanner.currentCharacter == '\\') { + scanner.scanEscapeCharacter(); + } + // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; + } + // } + } + break; + case '/' : + { + int test; + if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment + //get the next char + if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + //-------------unicode traitement ------------ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + scanner.currentPosition++; + while (source[scanner.currentPosition] == 'u') { + scanner.currentPosition++; + } + if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c1 < 0 + || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c2 < 0 + || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c3 < 0 + || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c4 < 0) { //error don't care of the value + scanner.currentCharacter = 'A'; + } //something different from \n and \r + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); + } + } + while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') { + //get the next char + scanner.startPosition = scanner.currentPosition; + if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + //-------------unicode traitement ------------ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + scanner.currentPosition++; + while (source[scanner.currentPosition] == 'u') { + scanner.currentPosition++; + } + if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c1 < 0 + || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c2 < 0 + || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c3 < 0 + || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c4 < 0) { //error don't care of the value + scanner.currentCharacter = 'A'; + } //something different from \n and \r + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); + } + } + } + if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) { + if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) { + // only record line positions we have not recorded yet + scanner.pushLineSeparator(); + if (this.scanner.taskTags != null) { + this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); + } + } + } + break; + } + if (test > 0) { //traditional and annotation comment + boolean star = false; + // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; + } + // } + if (scanner.currentCharacter == '*') { + star = true; + } + //get the next char + if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + //-------------unicode traitement ------------ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + scanner.currentPosition++; + while (source[scanner.currentPosition] == 'u') { + scanner.currentPosition++; + } + if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c1 < 0 + || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c2 < 0 + || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c3 < 0 + || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c4 < 0) { //error don't care of the value + scanner.currentCharacter = 'A'; + } //something different from * and / + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); + } + } + //loop until end of comment */ + while ((scanner.currentCharacter != '/') || (!star)) { + star = scanner.currentCharacter == '*'; + //get next char + if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + //-------------unicode traitement ------------ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + scanner.currentPosition++; + while (source[scanner.currentPosition] == 'u') { + scanner.currentPosition++; + } + if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c1 < 0 + || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c2 < 0 + || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c3 < 0 + || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c4 < 0) { //error don't care of the value + scanner.currentCharacter = 'A'; + } //something different from * and / + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); + } + } + } + if (this.scanner.taskTags != null) { + this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); + } + break; + } + break; + } + default : + if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) { + scanner.scanIdentifierOrKeyword(false); + break; + } + if (Character.isDigit(scanner.currentCharacter)) { + scanner.scanNumber(false); + break; + } + } + //-----------------end switch while try-------------------- + } catch (IndexOutOfBoundsException e) { + break; // read until EOF + } catch (InvalidInputException e) { + return false; // no clue + } + } + if (scanner.recordLineSeparator) { + // compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); + } + + // check placement anomalies against other kinds of brackets + for (int kind = 0; kind < BracketKinds; kind++) { + for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) { + int start = leftPositions[kind][leftIndex]; // deepest first + // find matching closing bracket + int depth = leftDepths[kind][leftIndex]; + int end = -1; + for (int i = 0; i < rightCount[kind]; i++) { + int pos = rightPositions[kind][i]; + // want matching bracket further in source with same depth + if ((pos > start) && (depth == rightDepths[kind][i])) { + end = pos; + break; + } + } + if (end < 0) { // did not find a good closing match + problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); + return true; + } + // check if even number of opening/closing other brackets in between this pair of brackets + int balance = 0; + for (int otherKind = 0;(balance == 0) && (otherKind < BracketKinds); otherKind++) { + for (int i = 0; i < leftCount[otherKind]; i++) { + int pos = leftPositions[otherKind][i]; + if ((pos > start) && (pos < end)) + balance++; + } + for (int i = 0; i < rightCount[otherKind]; i++) { + int pos = rightPositions[otherKind][i]; + if ((pos > start) && (pos < end)) + balance--; + } + if (balance != 0) { + problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly + return true; + } + } + } + // too many opening brackets ? + for (int i = rightCount[kind]; i < leftCount[kind]; i++) { + anomaliesDetected = true; + problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, compilationUnit.compilationResult); + } + // too many closing brackets ? + for (int i = leftCount[kind]; i < rightCount[kind]; i++) { + anomaliesDetected = true; + problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult); + } + if (anomaliesDetected) + return true; + } + + return anomaliesDetected; + } catch (ArrayStoreException e) { // jdk1.2.2 jit bug + return anomaliesDetected; + } catch (NullPointerException e) { // jdk1.2.2 jit bug + return anomaliesDetected; + } + } + + protected void pushOnAstLengthStack(int pos) { + try { + astLengthStack[++astLengthPtr] = pos; + } catch (IndexOutOfBoundsException e) { + int oldStackLength = astLengthStack.length; + int[] oldPos = astLengthStack; + astLengthStack = new int[oldStackLength + StackIncrement]; + System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength); + astLengthStack[astLengthPtr] = pos; + } + } + + protected void pushOnAstStack(AstNode node) { + /*add a new obj on top of the ast stack + astPtr points on the top*/ + + try { + astStack[++astPtr] = node; + } catch (IndexOutOfBoundsException e) { + int oldStackLength = astStack.length; + AstNode[] oldStack = astStack; + astStack = new AstNode[oldStackLength + AstStackIncrement]; + System.arraycopy(oldStack, 0, astStack, 0, oldStackLength); + astPtr = oldStackLength; + astStack[astPtr] = node; + } + + try { + astLengthStack[++astLengthPtr] = 1; + } catch (IndexOutOfBoundsException e) { + int oldStackLength = astLengthStack.length; + int[] oldPos = astLengthStack; + astLengthStack = new int[oldStackLength + AstStackIncrement]; + System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength); + astLengthStack[astLengthPtr] = 1; + } + } } \ No newline at end of file