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 44568b9..1a484bc 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,25 +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.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 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 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 boolean VERBOSE_RECOVERY = false; + protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies //scanner token public Scanner scanner; - private IFile fileToParse; private ArrayList phpList; private int currentPHPString; @@ -139,12 +157,24 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // 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; @@ -152,7 +182,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { this.initializeScanner(); } /** - * Class Constructor. + * ClassDeclaration Constructor. * *@param s *@param sess Description of Parameter @@ -166,7 +196,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // } // } this.currentPHPString = 0; - this.fileToParse = fileToParse; + PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; this.str = ""; this.token = TokenNameEOF; @@ -185,12 +215,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { /** * 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); } @@ -232,6 +257,10 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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. * @@ -260,8 +289,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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) { @@ -269,616 +297,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } 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. @@ -1252,10 +671,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } if (token != TokenNameEOF) { if (token == TokenNameERROR) { - throwSyntaxError( - "Scanner error (Found unknown token: " - + scanner.toStringAction(token) - + ")"); + throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")"); } if (token == TokenNameRPAREN) { throwSyntaxError("Too many closing ')'; end-of-file not reached."); @@ -1285,11 +701,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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' @@ -1307,12 +719,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } 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; @@ -1323,6 +730,34 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { /* 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 { @@ -1331,10 +766,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } if (token != TokenNameEOF) { if (token == TokenNameERROR) { - throwSyntaxError( - "Scanner error (Found unknown token: " - + scanner.toStringAction(token) - + ")"); + throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")"); } if (token == TokenNameRPAREN) { throwSyntaxError("Too many closing ')'; end-of-file not reached."); @@ -1361,11 +793,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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' @@ -1381,11 +809,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } } 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; } } @@ -1416,10 +840,11 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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; @@ -1434,10 +859,10 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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) { @@ -1451,6 +876,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } else { switch (token) { case TokenNameVariable : + case TokenNamethis : current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); @@ -1461,10 +887,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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; @@ -1505,8 +928,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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), @@ -1518,8 +940,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } } 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), @@ -1530,15 +951,13 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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) { @@ -1547,11 +966,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { if (counter == 0 && goBack) { return; } - } else if ( - token == TokenNamerequire - || token == TokenNamerequire_once - || token == TokenNameinclude - || token == TokenNameinclude_once) { + } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) { ident = scanner.getCurrentTokenSource(); getNextToken(); @@ -1571,11 +986,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } 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) { } } @@ -1583,10 +994,11 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { private void statementList() throws CoreException { do { - statement(); + statement(TokenNameEOF); if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) + || (token == TokenNameelse) || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor) @@ -1600,7 +1012,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } while (true); } - private void compoundStatement() throws CoreException { + private void functionBody(MethodDeclaration methodDecl) throws CoreException { // '{' [statement-list] '}' if (token == TokenNameLBRACE) { getNextToken(); @@ -1611,39 +1023,49 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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 == 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) { @@ -1797,10 +1219,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { foreachStatement(); return; - } else if ( - token == TokenNamecontinue - || token == TokenNamebreak - || token == TokenNamereturn) { + } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) { getNextToken(); if (token != TokenNameSEMICOLON) { expression(); @@ -1924,18 +1343,30 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } 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(); @@ -1955,35 +1386,52 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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(); @@ -1991,6 +1439,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { classElementList(); } if (token == TokenNameRBRACE) { + typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); getNextToken(); } else { throwSyntaxError("'}' expected at end of class body."); @@ -2010,8 +1459,10 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { //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(); @@ -2031,6 +1482,9 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { constant(); } } else { + if (token == TokenNamethis) { + throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'."); + } throwSyntaxError("Variable expected after keyword 'var'."); } if (token != TokenNameCOMMA) { @@ -2045,17 +1499,36 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } } - 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(); @@ -2068,8 +1541,14 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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'."); } } // @@ -2090,7 +1569,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { //variable-reference if (token == TokenNameAND) { getNextToken(); - if (token == TokenNameVariable) { + if (isVariable()) { getNextToken(); } else { throwSyntaxError("Variable expected after reference operator '&'."); @@ -2105,6 +1584,9 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } return; } + if (token == TokenNamethis) { + throwSyntaxError("Reserved word '$this' not allowed in parameter declaration."); + } } private void labeledStatementList() throws CoreException { @@ -2114,11 +1596,10 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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(); @@ -2130,9 +1611,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // 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); @@ -2142,10 +1621,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } 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(); @@ -2216,26 +1692,30 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // ':' 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) { @@ -2248,7 +1728,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { getNextToken(); } else { // statement [else-statement] - statement(); + statement(TokenNameEOF); if (token == TokenNameelseif) { getNextToken(); if (token == TokenNameLPAREN) { @@ -2265,7 +1745,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { ifStatement(); } else if (token == TokenNameelse) { getNextToken(); - statement(); + statement(TokenNameEOF); } } } @@ -2278,7 +1758,9 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { getNextToken(); if (token == TokenNameCOLON) { getNextToken(); - statementList(); + if (token != TokenNameendif) { + statementList(); + } return; } else { if (token == TokenNameif) { //'else if' @@ -2301,7 +1783,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { if (token == TokenNameLPAREN) { getNextToken(); expression(); - if (token != TokenNameLPAREN) { + if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in else-if-statement."); } getNextToken(); @@ -2309,7 +1791,9 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { throwSyntaxError("':' expected in else-if-statement."); } getNextToken(); - statementList(); + if (token != TokenNameendif) { + statementList(); + } } } @@ -2356,7 +1840,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } getNextToken(); } else { - statement(); + statement(TokenNameEOF); } } @@ -2374,7 +1858,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } getNextToken(); } else { - statement(); + statement(TokenNameEOF); } } @@ -2391,7 +1875,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } getNextToken(); } else { - statement(); + statement(TokenNameEOF); } } @@ -2446,6 +1930,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // String ident; char[] ident; boolean castFlag = false; + boolean arrayFlag = false; switch (token) { case TokenNamenew : getNextToken(); @@ -2470,6 +1955,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { break; case TokenNameLPAREN : getNextToken(); + if (token == TokenNameIdentifier) { // check if identifier is a type: // ident = identifier; @@ -2478,20 +1964,34 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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) { @@ -2514,16 +2014,14 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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) { @@ -2531,10 +2029,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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(); @@ -2549,12 +2044,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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(); @@ -2664,9 +2154,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // 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); @@ -2698,10 +2186,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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(); @@ -2709,16 +2194,14 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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) { @@ -2755,7 +2238,11 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // '@' '&' '*' '+' '-' '~' '!' case TokenNameAT : getNextToken(); - castExpression(); + if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) { + statement(TokenNameAT); + } else { + postfixExpression(); // castExpression(); + } break; case TokenNameAND : getNextToken(); @@ -2798,27 +2285,6 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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) { // = @@ -2869,9 +2335,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { private void multiplicativeExpression() throws CoreException { do { assignExpression(); - if (token != TokenNameMULTIPLY - && token != TokenNameDIVIDE - && token != TokenNameREMAINDER) { + if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) { return; } getNextToken(); @@ -2911,10 +2375,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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(); @@ -2924,8 +2385,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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(); @@ -3139,10 +2599,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { 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(); @@ -3168,4 +2625,546 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } } + 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