X-Git-Url: http://secure.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 e7491b1..b1ddd61 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 @@ -1,13 +1,14 @@ -/******************************************************************************* - * Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de All rights - * reserved. This program and the accompanying material are made available under - * the terms of the Common Public License v1.0 which accompanies this - * distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html +/*********************************************************************************************************************************** + * Copyright (c) 2002 www.phpeclipse.de All rights reserved. This program and the accompanying material are made available under the + * terms of the Common Public License v1.0 which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html * - * Contributors: Klaus Hartlage - www.eclipseproject.de - ******************************************************************************/ + * Contributors: www.phpeclipse.de + **********************************************************************************************************************************/ package net.sourceforge.phpdt.internal.compiler.parser; + import java.util.ArrayList; +import java.util.HashMap; import net.sourceforge.phpdt.core.compiler.CharOperation; import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; @@ -19,41 +20,75 @@ import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants; import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter; import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities; import net.sourceforge.phpdt.internal.compiler.util.Util; +import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil; import net.sourceforge.phpeclipse.builder.IdentifierIndexManager; +import net.sourceforge.phpeclipse.internal.compiler.ast.AND_AND_Expression; +import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode; import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration; -import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode; +import net.sourceforge.phpeclipse.internal.compiler.ast.BinaryExpression; import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.ConditionalExpression; +import net.sourceforge.phpeclipse.internal.compiler.ast.EmptyStatement; +import net.sourceforge.phpeclipse.internal.compiler.ast.EqualExpression; +import net.sourceforge.phpeclipse.internal.compiler.ast.Expression; import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.FieldReference; +import net.sourceforge.phpeclipse.internal.compiler.ast.IfStatement; import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference; +import net.sourceforge.phpeclipse.internal.compiler.ast.InstanceOfExpression; import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.OR_OR_Expression; +import net.sourceforge.phpeclipse.internal.compiler.ast.OperatorIds; import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference; +import net.sourceforge.phpeclipse.internal.compiler.ast.Statement; +import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteral; +import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralDQ; +import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralSQ; import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference; +import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil; import org.eclipse.core.resources.IFile; -public class Parser //extends PHPParserSuperclass - implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation { - //internal data for the automat +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; + +public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation { protected final static int StackIncrement = 255; + protected int stateStackTop; - protected int[] stack = new int[StackIncrement]; + + // 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; + + // 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 ArrayList phpList; - private int currentPHPString; - private boolean phpEnd; + + // private ArrayList phpList; + + // private int currentPHPString; + + // private boolean phpEnd; + // private static HashMap keywordMap = null; private String str; + // current character // char ch; // current token int token; + // row counter for syntax errors: //int rowCount; // column counter for syntax errors: @@ -62,42 +97,47 @@ public class Parser //extends PHPParserSuperclass // // // current identifier // String identifier; - Long longNumber; - Double doubleNumber; - private String stringValue; + // Long longNumber; + + // Double doubleNumber; + + // private String stringValue; + /** Contains the current expression. */ // private StringBuffer expression; //private boolean phpMode; protected int modifiers; + protected int modifiersSourceStart; -// protected IdentifierIndexManager indexManager; - + protected Parser(ProblemReporter problemReporter) { this.problemReporter = problemReporter; this.options = problemReporter.options; - this.currentPHPString = 0; + // this.currentPHPString = 0; // PHPParserSuperclass.fileToParse = fileToParse; - this.phpList = null; -// this.indexManager = null; + // this.phpList = null; + // this.indexManager = null; this.str = ""; this.token = TokenNameEOF; // this.chIndx = 0; // this.rowCount = 1; // this.columnCount = 0; - this.phpEnd = false; + // this.phpEnd = false; // getNextToken(); this.initializeScanner(); } + public void setFileToParse(IFile fileToParse) { - this.currentPHPString = 0; + // this.currentPHPString = 0; // PHPParserSuperclass.fileToParse = fileToParse; - this.phpList = null; -// this.indexManager = null; + // this.phpList = null; + // this.indexManager = null; this.str = ""; this.token = TokenNameEOF; - this.phpEnd = false; + // this.phpEnd = false; this.initializeScanner(); } + /** * ClassDeclaration Constructor. * @@ -113,24 +153,26 @@ public class Parser //extends PHPParserSuperclass // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i])); // } // } - this.currentPHPString = 0; + // this.currentPHPString = 0; // PHPParserSuperclass.fileToParse = fileToParse; - this.phpList = null; + // this.phpList = null; this.includesList = null; this.str = ""; this.token = TokenNameEOF; // this.chIndx = 0; // this.rowCount = 1; // this.columnCount = 0; - this.phpEnd = false; + // this.phpEnd = false; // getNextToken(); this.initializeScanner(); } + public void initializeScanner() { this.scanner = new Scanner(false /* comment */, false /* whitespace */, this.options .getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */, false, false, - this.options.taskTags/* taskTags */, this.options.taskPriorites/* taskPriorities */); + this.options.taskTags/* taskTags */, this.options.taskPriorites/* taskPriorities */, true/* isTaskCaseSensitive */); } + /** * Create marker for the parse error */ @@ -139,8 +181,7 @@ public class Parser //extends PHPParserSuperclass // setMarker(fileToParse, message, charStart, charEnd, errorLevel); // } /** - * This method will throw the SyntaxError. It will add the good lines and - * columns to the Error + * This method will throw the SyntaxError. It will add the good lines and columns to the Error * * @param error * the error message @@ -152,9 +193,9 @@ public class Parser //extends PHPParserSuperclass int problemEndPosition = scanner.getCurrentTokenEndPosition(); throwSyntaxError(error, problemStartPosition, problemEndPosition + 1); } + /** - * This method will throw the SyntaxError. It will add the good lines and - * columns to the Error + * This method will throw the SyntaxError. It will add the good lines and columns to the Error * * @param error * the error message @@ -165,35 +206,33 @@ public class Parser //extends PHPParserSuperclass // throw new SyntaxError(startRow, 0, " ", error); // } private void throwSyntaxError(String error, int problemStartPosition, int problemEndPosition) { - problemReporter.phpParsingError(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext, - compilationUnit.compilationResult); + if (referenceContext != null) { + problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, + compilationUnit.compilationResult); + } throw new SyntaxError(1, 0, " ", error); } + + private void reportSyntaxError(String error) { + int problemStartPosition = scanner.getCurrentTokenStartPosition(); + int problemEndPosition = scanner.getCurrentTokenEndPosition(); + reportSyntaxError(error, problemStartPosition, problemEndPosition + 1); + } + private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) { - problemReporter.phpParsingError(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext, - compilationUnit.compilationResult); + if (referenceContext != null) { + problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, + compilationUnit.compilationResult); + } } + private void reportSyntaxWarning(String error, int problemStartPosition, int problemEndPosition) { - problemReporter.phpParsingWarning(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext, - compilationUnit.compilationResult); + if (referenceContext != null) { + problemReporter.phpParsingWarning(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, + compilationUnit.compilationResult); + } } - /** - * Method Declaration. - * - * @see - */ - // 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 */ @@ -209,57 +248,78 @@ public class Parser //extends PHPParserSuperclass } catch (InvalidInputException e) { token = TokenNameERROR; String detailedMessage = e.getMessage(); - - if (detailedMessage==Scanner.UNTERMINATED_STRING) { + + if (detailedMessage == Scanner.UNTERMINATED_STRING) { throwSyntaxError("Unterminated string."); - } else if (detailedMessage==Scanner.UNTERMINATED_COMMENT) { + } else if (detailedMessage == Scanner.UNTERMINATED_COMMENT) { throwSyntaxError("Unterminated commment."); } } return; } + public void init(String s) { this.str = s; this.token = TokenNameEOF; + this.includesList = new ArrayList(); // this.chIndx = 0; // this.rowCount = 1; // this.columnCount = 0; - this.phpEnd = false; + // this.phpEnd = false; // this.phpMode = false; /* scanner initialization */ scanner.setSource(s.toCharArray()); scanner.setPHPMode(false); + astPtr = 0; } + protected void initialize(boolean phpMode) { initialize(phpMode, null); } + protected void initialize(boolean phpMode, IdentifierIndexManager indexManager) { compilationUnit = null; referenceContext = null; - includesList = new ArrayList(); -// this.indexManager = indexManager; + this.includesList = new ArrayList(); + // this.indexManager = indexManager; this.str = ""; this.token = TokenNameEOF; // this.chIndx = 0; // this.rowCount = 1; // this.columnCount = 0; - this.phpEnd = false; + // this.phpEnd = false; // this.phpMode = phpMode; scanner.setPHPMode(phpMode); + astPtr = 0; } + /** - * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> - * </body>' + * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>' */ public void parse(String s) { + parse(s, null); + } + + /** + * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>' + */ + public void parse(String s, HashMap variables) { + fMethodVariables = variables; init(s); parse(); } + /** - * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> - * </body>' + * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>' */ protected void parse() { + if (scanner.compilationUnit != null) { + IResource resource = scanner.compilationUnit.getResource(); + if (resource != null && resource instanceof IFile) { + // set the package name + consumePackageDeclarationName((IFile) resource); + } + } getNextToken(); do { try { @@ -292,58 +352,95 @@ public class Parser //extends PHPParserSuperclass } break; } catch (SyntaxError sytaxErr1) { - // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), - // ERROR); - // setMarker(sytaxErr1.getMessage(), - // scanner.getCurrentTokenStartPosition(), - // scanner.getCurrentTokenEndPosition(), ERROR); - try { - // if an error occured, - // try to find keywords 'class' or 'function' - // to parse the rest of the string - while (token != TokenNameEOF && token != TokenNameERROR) { - if (token == TokenNameabstract || token == TokenNamefinal || token == TokenNameclass || token == TokenNamefunction) { - break; - } - getNextToken(); - } - if (token == TokenNameEOF || token == TokenNameERROR) { - break; - } - } catch (SyntaxError sytaxErr2) { - // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), - // ERROR); - // setMarker(sytaxErr2.getMessage(), - // scanner.getCurrentTokenStartPosition(), - // scanner.getCurrentTokenEndPosition(), ERROR); - break; - } + break; + // // if an error occured, + // // try to find keywords 'abstract' 'final' 'class' or 'function' + // // to parse the rest of the string + // boolean tokenize = scanner.tokenizeStrings; + // if (!tokenize) { + // scanner.tokenizeStrings = true; + // } + // try { + // while (token != TokenNameEOF) { + // if (token == TokenNameabstract || token == TokenNamefinal || token == TokenNameclass || token == TokenNamefunction) { + // break; + // } + // getNextToken(); + // } + // if (token == TokenNameEOF) { + // break; + // } + // } catch (SyntaxError sytaxErr2) { + // break; + // } finally { + // scanner.tokenizeStrings = tokenize; + // } } } while (true); endParse(0); } + /** + * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>' + */ + public void parseFunction(String s, HashMap variables) { + init(s); + scanner.phpMode = true; + parseFunction(variables); + } + + /** + * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>' + */ + protected void parseFunction(HashMap variables) { + getNextToken(); + boolean hasModifiers = member_modifiers(); + if (token == TokenNamefunction) { + if (!hasModifiers) { + checkAndSetModifiers(AccPublic); + } + this.fMethodVariables = variables; + + MethodDeclaration methodDecl = new MethodDeclaration(null); + methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); + methodDecl.modifiers = this.modifiers; + methodDecl.type = MethodDeclaration.METHOD_DEFINITION; + try { + getNextToken(); + functionDefinition(methodDecl); + } catch (SyntaxError sytaxErr1) { + return; + } finally { + int sourceEnd = scanner.getCurrentTokenStartPosition(); + if (sourceEnd <= 0 || methodDecl.declarationSourceStart > sourceEnd) { + sourceEnd = methodDecl.declarationSourceStart + 1; + } + methodDecl.declarationSourceEnd = sourceEnd; + } + } + } + protected CompilationUnitDeclaration endParse(int act) { this.lastAct = act; - if (currentElement != null) { - currentElement.topElement().updateParseTree(); - if (VERBOSE_RECOVERY) { - System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$ - System.out.println("--------------------------"); //$NON-NLS-1$ - System.out.println(compilationUnit); - System.out.println("----------------------------------"); //$NON-NLS-1$ - } - } else { - if (diet & VERBOSE_RECOVERY) { - System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$ - System.out.println("--------------------------"); //$NON-NLS-1$ - System.out.println(compilationUnit); - System.out.println("----------------------------------"); //$NON-NLS-1$ - } + // if (currentElement != null) { + // currentElement.topElement().updateParseTree(); + // if (VERBOSE_RECOVERY) { + // System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$ + // System.out.println("--------------------------"); //$NON-NLS-1$ + // System.out.println(compilationUnit); + // System.out.println("----------------------------------"); //$NON-NLS-1$ + // } + // } else { + if (diet & VERBOSE_RECOVERY) { + System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$ + System.out.println("--------------------------"); //$NON-NLS-1$ + System.out.println(compilationUnit); + System.out.println("----------------------------------"); //$NON-NLS-1$ } + // } if (scanner.recordLineSeparator) { compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); } @@ -360,205 +457,59 @@ public class Parser //extends PHPParserSuperclass } return compilationUnit; } - // public PHPOutlineInfo parseInfo(Object parent, String s) { - // PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent); - // // Stack stack = new Stack(); - // // stack.push(outlineInfo.getDeclarations()); - // this.str = s; - // this.token = TokenNameEOF; - // // this.chIndx = 0; - // // this.rowCount = 1; - // // this.columnCount = 0; - // this.phpEnd = false; - // this.phpMode = false; - // scanner.setSource(s.toCharArray()); - // scanner.setPHPMode(false); - // - // getNextToken(); - // parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false); - // - // return outlineInfo; - // } + 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) { - // if (token == TokenNameVariable) { - // ident = scanner.getCurrentIdentifierSource(); - // outlineInfo.addVariable(new String(ident)); - // getNextToken(); - // } else if (token == TokenNamevar) { - // getNextToken(); - // if (token == TokenNameVariable - // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) { - // ident = scanner.getCurrentIdentifierSource(); - // //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) { - // current.add(new PHPVarDeclaration(current, variableName, - // // chIndx - ident.length, - // scanner.getCurrentTokenStartPosition(), new String(ident))); - // } else { - // switch (token) { - // case TokenNameVariable : - // case TokenNamethis : - // current.add(new PHPVarDeclaration(current, variableName, - // // chIndx - - // // ident.length, - // scanner.getCurrentTokenStartPosition(), new String( - // ident))); - // break; - // case TokenNameIdentifier : - // current.add(new PHPVarDeclaration(current, variableName, - // // chIndx - - // // ident.length, - // scanner.getCurrentTokenStartPosition(), new String( - // ident))); - // break; - // case TokenNameDoubleLiteral : - // current.add(new PHPVarDeclaration(current, variableName - // + doubleNumber, - // // chIndx - - // // ident.length, - // scanner.getCurrentTokenStartPosition(), new String( - // ident))); - // break; - // case TokenNameIntegerLiteral : - // current.add(new PHPVarDeclaration(current, variableName, - // // chIndx - - // // ident.length, - // scanner.getCurrentTokenStartPosition(), new String( - // ident))); - // break; - // case TokenNameStringInterpolated : - // case TokenNameStringLiteral : - // current.add(new PHPVarDeclaration(current, variableName, - // // chIndx - - // // ident.length, - // scanner.getCurrentTokenStartPosition(), new String( - // ident))); - // break; - // case TokenNameStringConstant : - // current.add(new PHPVarDeclaration(current, variableName, - // // chIndx - - // // ident.length, - // scanner.getCurrentTokenStartPosition(), new String( - // ident))); - // break; - // default : - // current.add(new PHPVarDeclaration(current, variableName, - // // chIndx - - // // ident.length - // scanner.getCurrentTokenStartPosition())); - // break; - // } - // } - // } else { - // ident = scanner.getCurrentIdentifierSource(); - // current.add(new PHPVarDeclaration(current, variableName, - // // chIndx - ident.length - // scanner.getCurrentTokenStartPosition())); - // } - // } - // } else if (token == TokenNamefunction) { - // getNextToken(); - // if (token == TokenNameAND) { - // getNextToken(); - // } - // if (token == TokenNameIdentifier - // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) { - // ident = scanner.getCurrentIdentifierSource(); - // outlineInfo.addVariable(new String(ident)); - // temp = new PHPFunctionDeclaration(current, new String(ident), - // // chIndx - ident.length - // scanner.getCurrentTokenStartPosition()); - // current.add(temp); - // getNextToken(); - // parseDeclarations(outlineInfo, temp, true); - // } - // } else if (token == TokenNameclass) { - // getNextToken(); - // if (token == TokenNameIdentifier - // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) { - // ident = scanner.getCurrentIdentifierSource(); - // outlineInfo.addVariable(new String(ident)); - // temp = new PHPClassDeclaration(current, new String(ident), - // // chIndx - ident.len - // scanner.getCurrentTokenStartPosition()); - // current.add(temp); - // // stack.push(temp); - // getNextToken(); - // //skip tokens for classname, extends and others until - // // we have the opening '{' - // while (token != TokenNameLBRACE && token != TokenNameEOF - // && token != TokenNameERROR) { - // getNextToken(); - // } - // parseDeclarations(outlineInfo, temp, true); - // // stack.pop(); - // } - // } else if ((token == TokenNameLBRACE) - // || (token == TokenNameDOLLAR_LBRACE)) { - // getNextToken(); - // counter++; - // } else if (token == TokenNameRBRACE) { - // getNextToken(); - // --counter; - // if (counter == 0 && goBack) { - // return; - // } - // } else if (token == TokenNamerequire || token == TokenNamerequire_once - // || token == TokenNameinclude || token == TokenNameinclude_once) { - // ident = scanner.getCurrentTokenSource(); - // getNextToken(); - // int startPosition = scanner.getCurrentTokenStartPosition(); - // expr(); - // char[] expr = scanner.getCurrentTokenSource(startPosition); - // outlineInfo.addVariable(new String(ident)); - // current.add(new PHPReqIncDeclaration(current, new String(ident), - // // chIndx - ident.length, - // startPosition, new String(expr))); - // getNextToken(); - // } else { - // getNextToken(); - // } - // } - // } catch (SyntaxError sytaxErr) { - // // try { - // // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR); - // // setMarker(sytaxErr.getMessage(), - // // scanner.getCurrentTokenStartPosition(), - // // scanner.getCurrentTokenEndPosition(), ERROR); - // // } catch (CoreException e) { - // // } - // } - // } + private void statementList() { do { - statement(TokenNameEOF); - if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse) - || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor) - || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch) - || (token == TokenNameEOF) || (token == TokenNameERROR)) { - return; + try { + statement(TokenNameEOF); + if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse) + || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor) + || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch) + || (token == TokenNameenddeclare) || (token == TokenNameEOF) || (token == TokenNameERROR)) { + return; + } + } catch (SyntaxError sytaxErr1) { + // if an error occured, + // try to find keywords + // to parse the rest of the string + boolean tokenize = scanner.tokenizeStrings; + if (!tokenize) { + scanner.tokenizeStrings = true; + } + try { + while (token != TokenNameEOF) { + if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse) + || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor) + || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch) + || (token == TokenNameenddeclare) || (token == TokenNameEOF) || (token == TokenNameERROR)) { + return; + } + if (token == TokenNameif || token == TokenNameswitch || token == TokenNamefor || token == TokenNamewhile + || token == TokenNamedo || token == TokenNameforeach || token == TokenNamecontinue || token == TokenNamebreak + || token == TokenNamereturn || token == TokenNameexit || token == TokenNameecho || token == TokenNameglobal + || token == TokenNamestatic || token == TokenNameunset || token == TokenNamefunction || token == TokenNamedeclare + || token == TokenNametry || token == TokenNamecatch || token == TokenNamethrow || token == TokenNamefinal + || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) { + break; + } + // System.out.println(scanner.toStringAction(token)); + getNextToken(); + // System.out.println(scanner.toStringAction(token)); + } + if (token == TokenNameEOF) { + throw sytaxErr1; + } + } finally { + scanner.tokenizeStrings = tokenize; + } } } while (true); } + private void functionBody(MethodDeclaration methodDecl) { // '{' [statement-list] '}' if (token == TokenNameLBRACE) { @@ -570,62 +521,17 @@ public class Parser //extends PHPParserSuperclass statementList(); } if (token == TokenNameRBRACE) { - methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); + // methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); getNextToken(); } else { throwSyntaxError("'}' expected in compound-statement."); } } - private void statement(int previousToken) { - // 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 != TokenNameStringInterpolated) { - // throwSyntaxError("identifier expected after '@'."); - // } - // } - // if (token == TokenNameinclude || token == TokenNameinclude_once) { - // getNextToken(); - // if (token == TokenNameLPAREN) { - // expr(); - // if (token == TokenNameSEMICOLON) { - // getNextToken(); - // } else { - // if (previousToken != TokenNameAT && token != TokenNameStopPHP) { - // throwSyntaxError("';' expected after 'include' or 'include_once'."); - // } - // // getNextToken(); - // } - // } else { - // concatenationExpression(); - // } - // return; - // } else if (token == TokenNamerequire || token == - // TokenNamerequire_once) - // { - // getNextToken(); - // //constant(); - // if (token == TokenNameLPAREN) { - // expr(); - // if (token == TokenNameSEMICOLON) { - // getNextToken(); - // } else { - // if (previousToken != TokenNameAT && token != TokenNameStopPHP) { - // throwSyntaxError("';' expected after 'require' or 'require_once'."); - // } - // // getNextToken(); - // } - // } else { - // concatenationExpression(); - // } - // return; - // } else + + private Statement statement(int previousToken) { + Statement statement = null; + Expression expression; + int sourceStart = scanner.getCurrentTokenStartPosition(); if (token == TokenNameif) { getNextToken(); if (token == TokenNameLPAREN) { @@ -633,14 +539,14 @@ public class Parser //extends PHPParserSuperclass } else { throwSyntaxError("'(' expected after 'if' keyword."); } - expr(); + expression = expr(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'if' condition."); } ifStatement(); - return; + return new IfStatement(expression, statement, sourceStart, scanner.getCurrentTokenEndPosition()); } else if (token == TokenNameswitch) { getNextToken(); if (token == TokenNameLPAREN) { @@ -655,7 +561,7 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("')' expected after 'switch' condition."); } switchStatement(); - return; + return statement; } else if (token == TokenNamefor) { getNextToken(); if (token == TokenNameLPAREN) { @@ -694,7 +600,7 @@ public class Parser //extends PHPParserSuperclass } } forStatement(); - return; + return statement; } else if (token == TokenNamewhile) { getNextToken(); if (token == TokenNameLPAREN) { @@ -709,7 +615,7 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("')' expected after 'while' condition."); } whileStatement(); - return; + return statement; } else if (token == TokenNamedo) { getNextToken(); if (token == TokenNameLBRACE) { @@ -749,7 +655,7 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); } - return; + return statement; } else if (token == TokenNameforeach) { getNextToken(); if (token == TokenNameLPAREN) { @@ -776,7 +682,7 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("')' expected after 'foreach' expression."); } foreachStatement(); - return; + return statement; } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) { getNextToken(); if (token != TokenNameSEMICOLON) { @@ -790,7 +696,7 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); } - return; + return statement; } else if (token == TokenNameecho) { getNextToken(); expressionList(); @@ -802,10 +708,10 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); } - return; + return statement; } else if (token == TokenNameINLINE_HTML) { getNextToken(); - return; + return statement; // } else if (token == TokenNameprint) { // getNextToken(); // expression(); @@ -829,7 +735,7 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); } - return; + return statement; } else if (token == TokenNamestatic) { getNextToken(); static_var_list(); @@ -841,7 +747,7 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); } - return; + return statement; } else if (token == TokenNameunset) { getNextToken(); if (token == TokenNameLPAREN) { @@ -863,14 +769,37 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); } - return; + return statement; } else if (token == TokenNamefunction) { MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); methodDecl.modifiers = AccDefault; + methodDecl.type = MethodDeclaration.FUNCTION_DEFINITION; + try { + getNextToken(); + functionDefinition(methodDecl); + } finally { + int sourceEnd = scanner.getCurrentTokenStartPosition(); + if (sourceEnd <= 0 || methodDecl.declarationSourceStart > sourceEnd) { + sourceEnd = methodDecl.declarationSourceStart + 1; + } + methodDecl.declarationSourceEnd = sourceEnd; + } + return statement; + } else if (token == TokenNamedeclare) { + //T_DECLARE '(' declare_list ')' declare_statement getNextToken(); - functionDefinition(methodDecl); - return; + if (token != TokenNameLPAREN) { + throwSyntaxError("'(' expected in 'declare' statement."); + } + getNextToken(); + declare_list(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected in 'declare' statement."); + } + getNextToken(); + declare_statement(); + return statement; } else if (token == TokenNametry) { getNextToken(); if (token != TokenNameLBRACE) { @@ -882,7 +811,7 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("'}' expected in 'try' statement."); } getNextToken(); - return; + return statement; } else if (token == TokenNamecatch) { getNextToken(); if (token != TokenNameLPAREN) { @@ -910,7 +839,7 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); additional_catches(); - return; + return statement; } else if (token == TokenNamethrow) { getNextToken(); expr(); @@ -919,22 +848,24 @@ public class Parser //extends PHPParserSuperclass } else { throwSyntaxError("';' expected after 'throw' exxpression."); } - return; + return statement; } else if (token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) { - 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 { + TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult); + typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); + typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); + typeDecl.name = new char[] { ' ' }; + // default super class + typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0); + compilationUnit.types.add(typeDecl); pushOnAstStack(typeDecl); unticked_class_declaration_statement(typeDecl); - // classBody(typeDecl); } finally { + // reduce stack: astPtr--; astLengthPtr--; } - return; + return statement; // } else { // throwSyntaxError("Unexpected keyword '" + keyword + "'"); } else if (token == TokenNameLBRACE) { @@ -944,7 +875,7 @@ public class Parser //extends PHPParserSuperclass } if (token == TokenNameRBRACE) { getNextToken(); - return; + return statement; } else { throwSyntaxError("'}' expected."); } @@ -954,15 +885,63 @@ public class Parser //extends PHPParserSuperclass } if (token == TokenNameSEMICOLON) { getNextToken(); - return; + return statement; } else { - if (token != TokenNameINLINE_HTML && token != TokenNameEOF) { - throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")"); + if (token == TokenNameRBRACE) { + reportSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")"); + } else { + if (token != TokenNameINLINE_HTML && token != TokenNameEOF) { + throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")"); + } + getNextToken(); } - getNextToken(); } } + // may be null + return statement; } + + private void declare_statement() { + // statement + //| ':' inner_statement_list T_ENDDECLARE ';' + //; + if (token == TokenNameCOLON) { + getNextToken(); + // TODO: implement inner_statement_list(); + statementList(); + if (token != TokenNameenddeclare) { + throwSyntaxError("'enddeclare' expected in 'declare' statement."); + } + getNextToken(); + if (token != TokenNameSEMICOLON) { + throwSyntaxError("';' expected after 'enddeclare' keyword."); + } + getNextToken(); + } else { + statement(TokenNameRPAREN); + } + } + + private void declare_list() { + // T_STRING '=' static_scalar + //| declare_list ',' T_STRING '=' static_scalar + while (true) { + if (token != TokenNameIdentifier) { + throwSyntaxError("Identifier expected in 'declare' list."); + } + getNextToken(); + if (token != TokenNameEQUAL) { + throwSyntaxError("'=' expected in 'declare' list."); + } + getNextToken(); + static_scalar(); + if (token != TokenNameCOMMA) { + break; + } + getNextToken(); + } + } + private void additional_catches() { while (token == TokenNamecatch) { getNextToken(); @@ -983,13 +962,16 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("'{' expected in 'catch' statement."); } getNextToken(); - statementList(); + if (token != TokenNameRBRACE) { + statementList(); + } if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected in 'catch' statement."); } getNextToken(); } } + private void foreach_variable() { // w_variable //| '&' w_variable @@ -998,6 +980,7 @@ public class Parser //extends PHPParserSuperclass } w_variable(); } + private void foreach_optional_arg() { // /* empty */ //| T_DOUBLE_ARROW foreach_variable @@ -1006,6 +989,7 @@ public class Parser //extends PHPParserSuperclass foreach_variable(); } } + private void global_var_list() { // global_var_list: // global_var_list ',' global_var @@ -1018,20 +1002,25 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } + private void global_var() { //global_var: // T_VARIABLE //| '$' r_variable //| '$' '{' expr '}' if (token == TokenNameVariable) { + VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_GLOBAL_VAR); + if (fMethodVariables != null) { + fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info); + } getNextToken(); } else if (token == TokenNameDOLLAR) { getNextToken(); - if (token == TokenNameLPAREN) { + if (token == TokenNameLBRACE) { getNextToken(); expr(); - if (token != TokenNameLPAREN) { - throwSyntaxError("')' expected in global variable."); + if (token != TokenNameRBRACE) { + throwSyntaxError("'}' expected in global variable."); } getNextToken(); } else { @@ -1039,6 +1028,7 @@ public class Parser //extends PHPParserSuperclass } } } + private void static_var_list() { //static_var_list: // static_var_list ',' T_VARIABLE @@ -1047,6 +1037,10 @@ public class Parser //extends PHPParserSuperclass //| T_VARIABLE '=' static_scalar while (true) { if (token == TokenNameVariable) { + VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_STATIC_VAR); + if (fMethodVariables != null) { + fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info); + } getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); @@ -1061,6 +1055,7 @@ public class Parser //extends PHPParserSuperclass } } } + private void unset_variables() { // unset_variables: // unset_variable @@ -1075,15 +1070,18 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } + private final void initializeModifiers() { this.modifiers = 0; this.modifiersSourceStart = -1; } + private final void checkAndSetModifiers(int flag) { this.modifiers |= flag; if (this.modifiersSourceStart < 0) this.modifiersSourceStart = this.scanner.startPosition; } + private void unticked_class_declaration_statement(TypeDeclaration typeDecl) { initializeModifiers(); if (token == TokenNameinterface) { @@ -1093,20 +1091,20 @@ public class Parser //extends PHPParserSuperclass checkAndSetModifiers(AccInterface); getNextToken(); typeDecl.modifiers = this.modifiers; + typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); + typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); if (token == TokenNameIdentifier || token > TokenNameKEYWORD) { - typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); - typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); typeDecl.name = scanner.getCurrentIdentifierSource(); if (token > TokenNameKEYWORD) { - throwSyntaxError("Don't use a keyword for interface declaration [" + scanner.toStringAction(token) + "].", - typeDecl.sourceStart, typeDecl.sourceEnd); + problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(), + scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult); + // throwSyntaxError("Don't use a keyword for interface declaration [" + scanner.toStringAction(token) + "].", + // typeDecl.sourceStart, typeDecl.sourceEnd); } getNextToken(); - interface_extends_list(); + interface_extends_list(typeDecl); } else { - typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); - typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); - typeDecl.name = new char[]{' '}; + typeDecl.name = new char[] { ' ' }; throwSyntaxError("Interface name expected after keyword 'interface'.", typeDecl.sourceStart, typeDecl.sourceEnd); return; } @@ -1116,22 +1114,24 @@ public class Parser //extends PHPParserSuperclass // '{' class_statement_list'}' class_entry_type(); typeDecl.modifiers = this.modifiers; + typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); + typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); //identifier //identifier 'extends' identifier if (token == TokenNameIdentifier || token > TokenNameKEYWORD) { - typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); - typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); typeDecl.name = scanner.getCurrentIdentifierSource(); if (token > TokenNameKEYWORD) { - throwSyntaxError("Don't use a keyword for class declaration [" + scanner.toStringAction(token) + "].", - typeDecl.sourceStart, typeDecl.sourceEnd); + problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(), + scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult); + // throwSyntaxError("Don't use a keyword for class declaration [" + scanner.toStringAction(token) + "].", + // typeDecl.sourceStart, typeDecl.sourceEnd); } getNextToken(); // extends_from: // /* empty */ // | T_EXTENDS fully_qualified_class_name if (token == TokenNameextends) { - interface_extends_list(); + interface_extends_list(typeDecl); // getNextToken(); // if (token != TokenNameIdentifier) { // throwSyntaxError("Class name expected after keyword @@ -1140,11 +1140,9 @@ public class Parser //extends PHPParserSuperclass // .getCurrentTokenEndPosition()); // } } - implements_list(); + implements_list(typeDecl); } else { - typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); - typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); - typeDecl.name = new char[]{' '}; + typeDecl.name = new char[] { ' ' }; throwSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd); return; } @@ -1170,6 +1168,7 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("'{' expected at start of class body."); } } + private void class_entry_type() { // T_CLASS // | T_ABSTRACT T_CLASS @@ -1194,7 +1193,22 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected"); } } - private void interface_extends_list() { + + private void class_extends(TypeDeclaration typeDecl) { + // /* empty */ + // | T_EXTENDS interface_list + if (token == TokenNameextends) { + getNextToken(); + + if (token == TokenNameIdentifier) { + getNextToken(); + } else { + throwSyntaxError("Class name expected after keyword 'extends'."); + } + } + } + + private void interface_extends_list(TypeDeclaration typeDecl) { // /* empty */ // | T_EXTENDS interface_list if (token == TokenNameextends) { @@ -1202,7 +1216,8 @@ public class Parser //extends PHPParserSuperclass interface_list(); } } - private void implements_list() { + + private void implements_list(TypeDeclaration typeDecl) { // /* empty */ // | T_IMPLEMENTS interface_list if (token == TokenNameimplements) { @@ -1210,6 +1225,7 @@ public class Parser //extends PHPParserSuperclass interface_list(); } } + private void interface_list() { // interface_list: // fully_qualified_class_name @@ -1226,6 +1242,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } while (true); } + // private void classBody(TypeDeclaration typeDecl) { // //'{' [class-element-list] '}' // if (token == TokenNameLBRACE) { @@ -1245,11 +1262,45 @@ public class Parser //extends PHPParserSuperclass // } private void class_statement_list(ArrayList list) { do { - class_statement(list); - } while (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic - || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar - || token == TokenNameconst); + try { + class_statement(list); + if (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic + || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar + || token == TokenNameconst) { + continue; + } + if (token == TokenNameRBRACE) { + break; + } + throwSyntaxError("'}' at end of class statement."); + } catch (SyntaxError sytaxErr1) { + boolean tokenize = scanner.tokenizeStrings; + if (!tokenize) { + scanner.tokenizeStrings = true; + } + try { + // if an error occured, + // try to find keywords + // to parse the rest of the string + while (token != TokenNameEOF) { + if (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic + || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar + || token == TokenNameconst) { + break; + } + // System.out.println(scanner.toStringAction(token)); + getNextToken(); + } + if (token == TokenNameEOF) { + throw sytaxErr1; + } + } finally { + scanner.tokenizeStrings = tokenize; + } + } + } while (true); } + private void class_statement(ArrayList list) { // class_statement: // variable_modifiers class_variable_declaration ';' @@ -1258,7 +1309,7 @@ public class Parser //extends PHPParserSuperclass // '(' parameter_list ')' method_body initializeModifiers(); int declarationSourceStart = scanner.getCurrentTokenStartPosition(); - + if (token == TokenNamevar) { checkAndSetModifiers(AccPublic); problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), @@ -1266,7 +1317,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); class_variable_declaration(declarationSourceStart, list); } else if (token == TokenNameconst) { - checkAndSetModifiers(AccFinal|AccPublic); + checkAndSetModifiers(AccFinal | AccPublic); class_constant_declaration(declarationSourceStart, list); if (token != TokenNameSEMICOLON) { throwSyntaxError("';' expected after class const declaration."); @@ -1281,8 +1332,17 @@ public class Parser //extends PHPParserSuperclass MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); methodDecl.modifiers = this.modifiers; - getNextToken(); - functionDefinition(methodDecl); + methodDecl.type = MethodDeclaration.METHOD_DEFINITION; + try { + getNextToken(); + functionDefinition(methodDecl); + } finally { + int sourceEnd = scanner.getCurrentTokenStartPosition(); + if (sourceEnd <= 0 || methodDecl.declarationSourceStart > sourceEnd) { + sourceEnd = methodDecl.declarationSourceStart + 1; + } + methodDecl.declarationSourceEnd = sourceEnd; + } } else { if (!hasModifiers) { throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations."); @@ -1291,6 +1351,7 @@ public class Parser //extends PHPParserSuperclass } } } + private void class_constant_declaration(int declarationSourceStart, ArrayList list) { // class_constant_declaration ',' T_STRING '=' static_scalar // | T_CONST T_STRING '=' static_scalar @@ -1323,6 +1384,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } + // private void variable_modifiers() { // // variable_modifiers: // // non_empty_member_modifiers @@ -1392,6 +1454,7 @@ public class Parser //extends PHPParserSuperclass } return foundToken; } + private void class_variable_declaration(int declarationSourceStart, ArrayList list) { // class_variable_declaration: // class_variable_declaration ',' T_VARIABLE @@ -1402,15 +1465,18 @@ public class Parser //extends PHPParserSuperclass do { if (token == TokenNameVariable) { classVariable = scanner.getCurrentIdentifierSource(); - // indexManager.addIdentifierInformation('v', classVariable, buf, -1, -1); - FieldDeclaration fieldDeclaration = new FieldDeclaration(classVariable, scanner - .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition()); + // indexManager.addIdentifierInformation('v', classVariable, buf, -1, -1); + FieldDeclaration fieldDeclaration = new FieldDeclaration(classVariable, scanner.getCurrentTokenStartPosition(), scanner + .getCurrentTokenEndPosition()); fieldDeclaration.modifiers = this.modifiers; fieldDeclaration.declarationSourceStart = declarationSourceStart; fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); fieldDeclaration.modifiersSourceStart = declarationSourceStart; - // fieldDeclaration.type list.add(fieldDeclaration); + if (fTypeVariables != null) { + VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_CLASS_UNIT); + fTypeVariables.put(new String(scanner.getCurrentIdentifierSource()), info); + } getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); @@ -1433,21 +1499,24 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); } + private void functionDefinition(MethodDeclaration methodDecl) { boolean isAbstract = false; if (astPtr == 0) { - compilationUnit.types.add(methodDecl); + if (compilationUnit != null) { + compilationUnit.types.add(methodDecl); + } } else { - AstNode node = astStack[astPtr]; + ASTNode node = astStack[astPtr]; if (node instanceof TypeDeclaration) { TypeDeclaration typeDecl = ((TypeDeclaration) node); if (typeDecl.methods == null) { - typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl}; + typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl }; } else { AbstractMethodDeclaration[] newMethods; - System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, + System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 0, typeDecl.methods.length); - newMethods[0] = methodDecl; + newMethods[typeDecl.methods.length] = methodDecl; typeDecl.methods = newMethods; } if ((typeDecl.modifiers & AccAbstract) == AccAbstract) { @@ -1467,6 +1536,7 @@ public class Parser //extends PHPParserSuperclass } functionBody(methodDecl); } + private void functionDeclarator(MethodDeclaration methodDecl) { //identifier '(' [parameter-list] ')' if (token == TokenNameAND) { @@ -1477,10 +1547,8 @@ public class Parser //extends PHPParserSuperclass if (Scanner.isIdentifierOrKeyword(token)) { methodDecl.selector = scanner.getCurrentIdentifierSource(); if (token > TokenNameKEYWORD) { - problemReporter.phpKeywordWarning(new String[]{scanner.toStringAction(token)}, scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), - referenceContext, compilationUnit.compilationResult); -// reportSyntaxWarning("Don't use keyword for function declaration [" + scanner.toStringAction(token) + "].", -// scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition()); + problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(), + scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult); } getNextToken(); if (token == TokenNameLPAREN) { @@ -1489,7 +1557,7 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("'(' expected in function declaration."); } if (token != TokenNameRPAREN) { - parameter_list(); + parameter_list(methodDecl); } if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in function declaration."); @@ -1502,13 +1570,15 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("Function name expected after keyword 'function'."); } } + // - private void parameter_list() { + private void parameter_list(MethodDeclaration methodDecl) { // non_empty_parameter_list // | /* empty */ - non_empty_parameter_list(true); + non_empty_parameter_list(methodDecl, true); } - private void non_empty_parameter_list(boolean empty_allowed) { + + private void non_empty_parameter_list(MethodDeclaration methodDecl, boolean empty_allowed) { // optional_class_type T_VARIABLE // | optional_class_type '&' T_VARIABLE // | optional_class_type '&' T_VARIABLE '=' static_scalar @@ -1519,15 +1589,27 @@ public class Parser //extends PHPParserSuperclass // static_scalar // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' // static_scalar + char[] typeIdentifier = null; if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) { while (true) { if (token == TokenNameIdentifier) { + typeIdentifier = scanner.getCurrentIdentifierSource(); getNextToken(); } if (token == TokenNameAND) { getNextToken(); } if (token == TokenNameVariable) { + if (fMethodVariables != null) { + VariableInfo info; + if (methodDecl.type == MethodDeclaration.FUNCTION_DEFINITION) { + info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_FUNCTION_DEFINITION); + } else { + info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_METHOD_DEFINITION); + } + info.typeIdentifier = typeIdentifier; + fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info); + } getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); @@ -1547,35 +1629,38 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("Identifier expected in parameter list."); } } + private void optional_class_type() { // /* empty */ //| T_STRING } - private void parameterDeclaration() { - //variable - //variable-reference - if (token == TokenNameAND) { - getNextToken(); - if (isVariable()) { - getNextToken(); - } else { - throwSyntaxError("Variable expected after reference operator '&'."); - } - } - //variable '=' constant - if (token == TokenNameVariable) { - getNextToken(); - if (token == TokenNameEQUAL) { - getNextToken(); - static_scalar(); - } - return; - } - // if (token == TokenNamethis) { - // throwSyntaxError("Reserved word '$this' not allowed in parameter - // declaration."); - // } - } + + // private void parameterDeclaration() { + // //variable + // //variable-reference + // if (token == TokenNameAND) { + // getNextToken(); + // if (isVariable()) { + // getNextToken(); + // } else { + // throwSyntaxError("Variable expected after reference operator '&'."); + // } + // } + // //variable '=' constant + // if (token == TokenNameVariable) { + // getNextToken(); + // if (token == TokenNameEQUAL) { + // getNextToken(); + // static_scalar(); + // } + // return; + // } + // // if (token == TokenNamethis) { + // // throwSyntaxError("Reserved word '$this' not allowed in parameter + // // declaration."); + // // } + // } + private void labeledStatementList() { if (token != TokenNamecase && token != TokenNamedefault) { throwSyntaxError("'case' or 'default' expected."); @@ -1606,23 +1691,26 @@ public class Parser //extends PHPParserSuperclass // statementList(); // } else { - throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")"); + throwSyntaxError("':' character expected after 'case' constant (Found token: " + scanner.toStringAction(token) + ")"); } } else { // TokenNamedefault getNextToken(); - if (token == TokenNameCOLON) { + if (token == TokenNameCOLON || token == TokenNameSEMICOLON) { getNextToken(); if (token == TokenNameRBRACE) { // empty default case break; } - statementList(); + if (token != TokenNamecase) { + statementList(); + } } else { - throwSyntaxError("':' character after 'default' expected."); + throwSyntaxError("':' character expected after 'default'."); } } } while (token == TokenNamecase || token == TokenNamedefault); } + // public void labeledStatement() { // if (token == TokenNamecase) { // getNextToken(); @@ -1678,26 +1766,26 @@ public class Parser //extends PHPParserSuperclass if (token != TokenNameendif) { statementList(); switch (token) { - case TokenNameelse : + case TokenNameelse: + getNextToken(); + if (token == TokenNameCOLON) { getNextToken(); - if (token == TokenNameCOLON) { + if (token != TokenNameendif) { + statementList(); + } + } else { + if (token == TokenNameif) { //'else if' getNextToken(); - if (token != TokenNameendif) { - statementList(); - } + elseifStatementList(); } else { - if (token == TokenNameif) { //'else if' - getNextToken(); - elseifStatementList(); - } else { - throwSyntaxError("':' expected after 'else'."); - } + throwSyntaxError("':' expected after 'else'."); } - break; - case TokenNameelseif : - getNextToken(); - elseifStatementList(); - break; + } + break; + case TokenNameelseif: + getNextToken(); + elseifStatementList(); + break; } } if (token != TokenNameendif) { @@ -1731,34 +1819,36 @@ public class Parser //extends PHPParserSuperclass } } } + private void elseifStatementList() { do { elseifStatement(); switch (token) { - case TokenNameelse : + case TokenNameelse: + getNextToken(); + if (token == TokenNameCOLON) { getNextToken(); - if (token == TokenNameCOLON) { + if (token != TokenNameendif) { + statementList(); + } + return; + } else { + if (token == TokenNameif) { //'else if' getNextToken(); - if (token != TokenNameendif) { - statementList(); - } - return; } else { - if (token == TokenNameif) { //'else if' - getNextToken(); - } else { - throwSyntaxError("':' expected after 'else'."); - } + throwSyntaxError("':' expected after 'else'."); } - break; - case TokenNameelseif : - getNextToken(); - break; - default : - return; + } + break; + case TokenNameelseif: + getNextToken(); + break; + default: + return; } } while (true); } + private void elseifStatement() { if (token == TokenNameLPAREN) { getNextToken(); @@ -1776,6 +1866,7 @@ public class Parser //extends PHPParserSuperclass } } } + private void switchStatement() { if (token == TokenNameCOLON) { // ':' [labeled-statement-list] 'endswitch' ';' @@ -1804,6 +1895,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } + private void forStatement() { if (token == TokenNameCOLON) { getNextToken(); @@ -1820,6 +1912,7 @@ public class Parser //extends PHPParserSuperclass statement(TokenNameEOF); } } + private void whileStatement() { // ':' statement-list 'endwhile' ';' if (token == TokenNameCOLON) { @@ -1837,6 +1930,7 @@ public class Parser //extends PHPParserSuperclass statement(TokenNameEOF); } } + private void foreachStatement() { if (token == TokenNameCOLON) { getNextToken(); @@ -1853,6 +1947,7 @@ public class Parser //extends PHPParserSuperclass statement(TokenNameEOF); } } + // private void exitStatus() { // if (token == TokenNameLPAREN) { // getNextToken(); @@ -1878,98 +1973,107 @@ public class Parser //extends PHPParserSuperclass } } while (true); } - private void expr() { + + private Expression expr() { // r_variable // | expr_without_variable // if (token!=TokenNameEOF) { if (Scanner.TRACE) { System.out.println("TRACE: expr()"); } - expr_without_variable(true); + return expr_without_variable(true); // } } - private void expr_without_variable(boolean only_variable) { - // internal_functions_in_yacc - // | T_CLONE expr - // | T_PRINT expr - // | '(' expr ')' - // | '@' expr - // | '+' expr - // | '-' expr - // | '!' expr - // | '~' expr - // | T_INC rw_variable - // | T_DEC rw_variable - // | T_INT_CAST expr - // | T_DOUBLE_CAST expr - // | T_STRING_CAST expr - // | T_ARRAY_CAST expr - // | T_OBJECT_CAST expr - // | T_BOOL_CAST expr - // | T_UNSET_CAST expr - // | T_EXIT exit_expr - // | scalar - // | T_ARRAY '(' array_pair_list ')' - // | '`' encaps_list '`' - // | T_LIST '(' assignment_list ')' '=' expr - // | T_NEW class_name_reference ctor_arguments - // | variable '=' expr - // | variable '=' '&' variable - // | variable '=' '&' T_NEW class_name_reference ctor_arguments - // | variable T_PLUS_EQUAL expr - // | variable T_MINUS_EQUAL expr - // | variable T_MUL_EQUAL expr - // | variable T_DIV_EQUAL expr - // | variable T_CONCAT_EQUAL expr - // | variable T_MOD_EQUAL expr - // | variable T_AND_EQUAL expr - // | variable T_OR_EQUAL expr - // | variable T_XOR_EQUAL expr - // | variable T_SL_EQUAL expr - // | variable T_SR_EQUAL expr - // | rw_variable T_INC - // | rw_variable T_DEC - // | expr T_BOOLEAN_OR expr - // | expr T_BOOLEAN_AND expr - // | expr T_LOGICAL_OR expr - // | expr T_LOGICAL_AND expr - // | expr T_LOGICAL_XOR expr - // | expr '|' expr - // | expr '&' expr - // | expr '^' expr - // | expr '.' expr - // | expr '+' expr - // | expr '-' expr - // | expr '*' expr - // | expr '/' expr - // | expr '%' expr - // | expr T_SL expr - // | expr T_SR expr - // | expr T_IS_IDENTICAL expr - // | expr T_IS_NOT_IDENTICAL expr - // | expr T_IS_EQUAL expr - // | expr T_IS_NOT_EQUAL expr - // | expr '<' expr - // | expr T_IS_SMALLER_OR_EQUAL expr - // | expr '>' expr - // | expr T_IS_GREATER_OR_EQUAL expr - // | expr T_INSTANCEOF class_name_reference - // | expr '?' expr ':' expr - if (Scanner.TRACE) { - System.out.println("TRACE: expr_without_variable() PART 1"); - } - switch (token) { - case TokenNameisset : - case TokenNameempty : - case TokenNameeval : - case TokenNameinclude : - case TokenNameinclude_once : - case TokenNamerequire : - case TokenNamerequire_once : + + private Expression expr_without_variable(boolean only_variable) { + int exprSourceStart = scanner.getCurrentTokenStartPosition(); + int exprSourceEnd = scanner.getCurrentTokenEndPosition(); + Expression expression = new Expression(); + expression.sourceStart = exprSourceStart; + // default, may be overwritten + expression.sourceEnd = exprSourceEnd; + try { + // internal_functions_in_yacc + // | T_CLONE expr + // | T_PRINT expr + // | '(' expr ')' + // | '@' expr + // | '+' expr + // | '-' expr + // | '!' expr + // | '~' expr + // | T_INC rw_variable + // | T_DEC rw_variable + // | T_INT_CAST expr + // | T_DOUBLE_CAST expr + // | T_STRING_CAST expr + // | T_ARRAY_CAST expr + // | T_OBJECT_CAST expr + // | T_BOOL_CAST expr + // | T_UNSET_CAST expr + // | T_EXIT exit_expr + // | scalar + // | T_ARRAY '(' array_pair_list ')' + // | '`' encaps_list '`' + // | T_LIST '(' assignment_list ')' '=' expr + // | T_NEW class_name_reference ctor_arguments + // | variable '=' expr + // | variable '=' '&' variable + // | variable '=' '&' T_NEW class_name_reference ctor_arguments + // | variable T_PLUS_EQUAL expr + // | variable T_MINUS_EQUAL expr + // | variable T_MUL_EQUAL expr + // | variable T_DIV_EQUAL expr + // | variable T_CONCAT_EQUAL expr + // | variable T_MOD_EQUAL expr + // | variable T_AND_EQUAL expr + // | variable T_OR_EQUAL expr + // | variable T_XOR_EQUAL expr + // | variable T_SL_EQUAL expr + // | variable T_SR_EQUAL expr + // | rw_variable T_INC + // | rw_variable T_DEC + // | expr T_BOOLEAN_OR expr + // | expr T_BOOLEAN_AND expr + // | expr T_LOGICAL_OR expr + // | expr T_LOGICAL_AND expr + // | expr T_LOGICAL_XOR expr + // | expr '|' expr + // | expr '&' expr + // | expr '^' expr + // | expr '.' expr + // | expr '+' expr + // | expr '-' expr + // | expr '*' expr + // | expr '/' expr + // | expr '%' expr + // | expr T_SL expr + // | expr T_SR expr + // | expr T_IS_IDENTICAL expr + // | expr T_IS_NOT_IDENTICAL expr + // | expr T_IS_EQUAL expr + // | expr T_IS_NOT_EQUAL expr + // | expr '<' expr + // | expr T_IS_SMALLER_OR_EQUAL expr + // | expr '>' expr + // | expr T_IS_GREATER_OR_EQUAL expr + // | expr T_INSTANCEOF class_name_reference + // | expr '?' expr ':' expr + if (Scanner.TRACE) { + System.out.println("TRACE: expr_without_variable() PART 1"); + } + switch (token) { + case TokenNameisset: + case TokenNameempty: + case TokenNameeval: + case TokenNameinclude: + case TokenNameinclude_once: + case TokenNamerequire: + case TokenNamerequire_once: internal_functions_in_yacc(); break; // | '(' expr ')' - case TokenNameLPAREN : + case TokenNameLPAREN: getNextToken(); expr(); if (token == TokenNameRPAREN) { @@ -1992,24 +2096,24 @@ public class Parser //extends PHPParserSuperclass // | T_OBJECT_CAST expr // | T_BOOL_CAST expr // | T_UNSET_CAST expr - case TokenNameclone : - case TokenNameprint : - case TokenNameAT : - case TokenNamePLUS : - case TokenNameMINUS : - case TokenNameNOT : - case TokenNameTWIDDLE : - case TokenNameintCAST : - case TokenNamedoubleCAST : - case TokenNamestringCAST : - case TokenNamearrayCAST : - case TokenNameobjectCAST : - case TokenNameboolCAST : - case TokenNameunsetCAST : + case TokenNameclone: + case TokenNameprint: + case TokenNameAT: + case TokenNamePLUS: + case TokenNameMINUS: + case TokenNameNOT: + case TokenNameTWIDDLE: + case TokenNameintCAST: + case TokenNamedoubleCAST: + case TokenNamestringCAST: + case TokenNamearrayCAST: + case TokenNameobjectCAST: + case TokenNameboolCAST: + case TokenNameunsetCAST: getNextToken(); expr(); break; - case TokenNameexit : + case TokenNameexit: getNextToken(); exit_expr(); break; @@ -2021,7 +2125,7 @@ public class Parser //extends PHPParserSuperclass // | '`' encaps_list '`' // | common_scalar // | '`' encaps_list '`' - case TokenNameEncapsedString0 : + case TokenNameEncapsedString0: scanner.encapsedStringStack.push(new Character('`')); getNextToken(); try { @@ -2038,15 +2142,21 @@ public class Parser //extends PHPParserSuperclass } break; // | '\'' encaps_list '\'' - case TokenNameEncapsedString1 : + case TokenNameEncapsedString1: scanner.encapsedStringStack.push(new Character('\'')); getNextToken(); try { + exprSourceStart = scanner.getCurrentTokenStartPosition(); if (token == TokenNameEncapsedString1) { + expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner + .getCurrentTokenEndPosition()); } else { encaps_list(); if (token != TokenNameEncapsedString1) { throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )"); + } else { + expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner + .getCurrentTokenEndPosition()); } } } finally { @@ -2055,15 +2165,21 @@ public class Parser //extends PHPParserSuperclass } break; //| '"' encaps_list '"' - case TokenNameEncapsedString2 : + case TokenNameEncapsedString2: scanner.encapsedStringStack.push(new Character('"')); getNextToken(); try { + exprSourceStart = scanner.getCurrentTokenStartPosition(); if (token == TokenNameEncapsedString2) { + expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner + .getCurrentTokenEndPosition()); } else { encaps_list(); if (token != TokenNameEncapsedString2) { throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )"); + } else { + expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner + .getCurrentTokenEndPosition()); } } } finally { @@ -2071,22 +2187,30 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } break; - case TokenNameIntegerLiteral : - case TokenNameDoubleLiteral : - case TokenNameStringDoubleQuote : - case TokenNameStringSingleQuote : - case TokenNameStringInterpolated : - case TokenNameFILE : - case TokenNameLINE : - case TokenNameCLASS_C : - case TokenNameMETHOD_C : - case TokenNameFUNC_C : + case TokenNameStringDoubleQuote: + expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner + .getCurrentTokenEndPosition()); + common_scalar(); + break; + case TokenNameStringSingleQuote: + expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner + .getCurrentTokenEndPosition()); common_scalar(); break; - case TokenNameHEREDOC : + case TokenNameIntegerLiteral: + case TokenNameDoubleLiteral: + case TokenNameStringInterpolated: + case TokenNameFILE: + case TokenNameLINE: + case TokenNameCLASS_C: + case TokenNameMETHOD_C: + case TokenNameFUNC_C: + common_scalar(); + break; + case TokenNameHEREDOC: getNextToken(); break; - case TokenNamearray : + case TokenNamearray: // T_ARRAY '(' array_pair_list ')' getNextToken(); if (token == TokenNameLPAREN) { @@ -2097,14 +2221,14 @@ public class Parser //extends PHPParserSuperclass } array_pair_list(); if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")"); + throwSyntaxError("')' or ',' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")"); } getNextToken(); } else { throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")"); } break; - case TokenNamelist : + case TokenNamelist: // | T_LIST '(' assignment_list ')' '=' expr getNextToken(); if (token == TokenNameLPAREN) { @@ -2123,16 +2247,19 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("'(' expected after 'list' keyword."); } break; - case TokenNamenew : + case TokenNamenew: // | T_NEW class_name_reference ctor_arguments getNextToken(); - class_name_reference(); + Expression typeRef = class_name_reference(); ctor_arguments(); + if (typeRef != null) { + expression = typeRef; + } break; // | T_INC rw_variable // | T_DEC rw_variable - case TokenNamePLUS_PLUS : - case TokenNameMINUS_MINUS : + case TokenNamePLUS_PLUS: + case TokenNameMINUS_MINUS: getNextToken(); rw_variable(); break; @@ -2152,53 +2279,116 @@ public class Parser //extends PHPParserSuperclass // | variable T_SR_EQUAL expr // | rw_variable T_INC // | rw_variable T_DEC - case TokenNameIdentifier : - case TokenNameVariable : - case TokenNameDOLLAR : - variable(); + case TokenNameIdentifier: + case TokenNameVariable: + case TokenNameDOLLAR: + boolean rememberedVar = false; + Expression lhs = variable(); switch (token) { - case TokenNameEQUAL : + case TokenNameEQUAL: + getNextToken(); + if (token == TokenNameAND) { getNextToken(); - if (token == TokenNameAND) { + if (token == TokenNamenew) { + // | variable '=' '&' T_NEW class_name_reference + // ctor_arguments getNextToken(); - if (token == TokenNamenew) { - // | variable '=' '&' T_NEW class_name_reference - // ctor_arguments - getNextToken(); - class_name_reference(); - ctor_arguments(); - } else { - variable(); + SingleTypeReference classRef = class_name_reference(); + ctor_arguments(); + if (classRef != null) { + if (lhs != null && lhs instanceof FieldReference) { + // example: + // $var = & new Object(); + if (fMethodVariables != null) { + VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart()); + lhsInfo.reference = classRef; + lhsInfo.typeIdentifier = classRef.token; + fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo); + rememberedVar = true; + } + } } } else { - expr(); + Expression rhs = variable(); + if (rhs != null && rhs instanceof FieldReference && lhs != null && lhs instanceof FieldReference) { + // example: + // $var = &$ref; + if (fMethodVariables != null) { + VariableInfo rhsInfo = (VariableInfo) fMethodVariables.get(((FieldReference) rhs).token); + if (rhsInfo != null && rhsInfo.reference != null) { + VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart()); + lhsInfo.reference = rhsInfo.reference; + lhsInfo.typeIdentifier = rhsInfo.typeIdentifier; + fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo); + rememberedVar = true; + } + } + } } - break; - case TokenNamePLUS_EQUAL : - case TokenNameMINUS_EQUAL : - case TokenNameMULTIPLY_EQUAL : - case TokenNameDIVIDE_EQUAL : - case TokenNameDOT_EQUAL : - case TokenNameREMAINDER_EQUAL : - case TokenNameAND_EQUAL : - case TokenNameOR_EQUAL : - case TokenNameXOR_EQUAL : - case TokenNameRIGHT_SHIFT_EQUAL : - case TokenNameLEFT_SHIFT_EQUAL : - getNextToken(); - expr(); - break; - case TokenNamePLUS_PLUS : - case TokenNameMINUS_MINUS : - getNextToken(); - break; - default : - if (!only_variable) { - throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "')."); + } else { + Expression rhs = expr(); + if (lhs != null && lhs instanceof FieldReference) { + if (rhs != null && rhs instanceof FieldReference) { + // example: + // $var = $ref; + if (fMethodVariables != null) { + VariableInfo rhsInfo = (VariableInfo) fMethodVariables.get(((FieldReference) rhs).token); + if (rhsInfo != null && rhsInfo.reference != null) { + VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart()); + lhsInfo.reference = rhsInfo.reference; + lhsInfo.typeIdentifier = rhsInfo.typeIdentifier; + fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo); + rememberedVar = true; + } + } + } else if (rhs != null && rhs instanceof SingleTypeReference) { + // example: + // $var = new Object(); + if (fMethodVariables != null) { + VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart()); + lhsInfo.reference = (SingleTypeReference) rhs; + lhsInfo.typeIdentifier = ((SingleTypeReference) rhs).token; + fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo); + rememberedVar = true; + } + } } + } + if (rememberedVar == false && lhs != null && lhs instanceof FieldReference) { + if (fMethodVariables != null) { + VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart()); + fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo); + } + } + break; + case TokenNamePLUS_EQUAL: + case TokenNameMINUS_EQUAL: + case TokenNameMULTIPLY_EQUAL: + case TokenNameDIVIDE_EQUAL: + case TokenNameDOT_EQUAL: + case TokenNameREMAINDER_EQUAL: + case TokenNameAND_EQUAL: + case TokenNameOR_EQUAL: + case TokenNameXOR_EQUAL: + case TokenNameRIGHT_SHIFT_EQUAL: + case TokenNameLEFT_SHIFT_EQUAL: + getNextToken(); + expr(); + break; + case TokenNamePLUS_PLUS: + case TokenNameMINUS_MINUS: + getNextToken(); + break; + default: + if (!only_variable) { + throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "')."); + } + if (lhs != null) { + expression = lhs; + } } break; - default : + default: if (token != TokenNameINLINE_HTML) { if (token > TokenNameKEYWORD) { getNextToken(); @@ -2207,96 +2397,129 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "')."); } } - return; - } - if (Scanner.TRACE) { - System.out.println("TRACE: expr_without_variable() PART 2"); - } - // | expr T_BOOLEAN_OR expr - // | expr T_BOOLEAN_AND expr - // | expr T_LOGICAL_OR expr - // | expr T_LOGICAL_AND expr - // | expr T_LOGICAL_XOR expr - // | expr '|' expr - // | expr '&' expr - // | expr '^' expr - // | expr '.' expr - // | expr '+' expr - // | expr '-' expr - // | expr '*' expr - // | expr '/' expr - // | expr '%' expr - // | expr T_SL expr - // | expr T_SR expr - // | expr T_IS_IDENTICAL expr - // | expr T_IS_NOT_IDENTICAL expr - // | expr T_IS_EQUAL expr - // | expr T_IS_NOT_EQUAL expr - // | expr '<' expr - // | expr T_IS_SMALLER_OR_EQUAL expr - // | expr '>' expr - // | expr T_IS_GREATER_OR_EQUAL expr - while (true) { - switch (token) { - case TokenNameOR_OR : - case TokenNameAND_AND : - case TokenNameand : - case TokenNameor : - case TokenNamexor : - case TokenNameAND : - case TokenNameOR : - case TokenNameXOR : - case TokenNameDOT : - case TokenNamePLUS : - case TokenNameMINUS : - case TokenNameMULTIPLY : - case TokenNameDIVIDE : - case TokenNameREMAINDER : - case TokenNameLEFT_SHIFT : - case TokenNameRIGHT_SHIFT : - case TokenNameEQUAL_EQUAL_EQUAL : - case TokenNameNOT_EQUAL_EQUAL : - case TokenNameEQUAL_EQUAL : - case TokenNameNOT_EQUAL : - case TokenNameLESS : - case TokenNameLESS_EQUAL : - case TokenNameGREATER : - case TokenNameGREATER_EQUAL : + return expression; + } + if (Scanner.TRACE) { + System.out.println("TRACE: expr_without_variable() PART 2"); + } + // | expr T_BOOLEAN_OR expr + // | expr T_BOOLEAN_AND expr + // | expr T_LOGICAL_OR expr + // | expr T_LOGICAL_AND expr + // | expr T_LOGICAL_XOR expr + // | expr '|' expr + // | expr '&' expr + // | expr '^' expr + // | expr '.' expr + // | expr '+' expr + // | expr '-' expr + // | expr '*' expr + // | expr '/' expr + // | expr '%' expr + // | expr T_SL expr + // | expr T_SR expr + // | expr T_IS_IDENTICAL expr + // | expr T_IS_NOT_IDENTICAL expr + // | expr T_IS_EQUAL expr + // | expr T_IS_NOT_EQUAL expr + // | expr '<' expr + // | expr T_IS_SMALLER_OR_EQUAL expr + // | expr '>' expr + // | expr T_IS_GREATER_OR_EQUAL expr + while (true) { + switch (token) { + case TokenNameOR_OR: getNextToken(); - expr(); + expression = new OR_OR_Expression(expression, expr(), token); + break; + case TokenNameAND_AND: + getNextToken(); + expression = new AND_AND_Expression(expression, expr(), token); + break; + case TokenNameEQUAL_EQUAL: + getNextToken(); + expression = new EqualExpression(expression, expr(), token); + break; + case TokenNameand: + case TokenNameor: + case TokenNamexor: + case TokenNameAND: + case TokenNameOR: + case TokenNameXOR: + case TokenNameDOT: + case TokenNamePLUS: + case TokenNameMINUS: + case TokenNameMULTIPLY: + case TokenNameDIVIDE: + case TokenNameREMAINDER: + case TokenNameLEFT_SHIFT: + case TokenNameRIGHT_SHIFT: + case TokenNameEQUAL_EQUAL_EQUAL: + case TokenNameNOT_EQUAL_EQUAL: + case TokenNameNOT_EQUAL: + case TokenNameLESS: + case TokenNameLESS_EQUAL: + case TokenNameGREATER: + case TokenNameGREATER_EQUAL: + getNextToken(); + expression = new BinaryExpression(expression, expr(), token); break; // | expr T_INSTANCEOF class_name_reference // | expr '?' expr ':' expr - case TokenNameinstanceof : + case TokenNameinstanceof: getNextToken(); - class_name_reference(); + TypeReference classRef = class_name_reference(); + expression = new InstanceOfExpression(expression, classRef, OperatorIds.INSTANCEOF); + expression.sourceStart = exprSourceStart; + expression.sourceEnd = scanner.getCurrentTokenEndPosition(); break; - case TokenNameQUESTION : + case TokenNameQUESTION: getNextToken(); - expr(); - if (token == TokenNameCOLON) { - getNextToken(); - expr(); + Expression valueIfTrue = expr(); + if (token != TokenNameCOLON) { + throwSyntaxError("':' expected in conditional expression."); } + getNextToken(); + Expression valueIfFalse = expr(); + + expression = new ConditionalExpression(expression, valueIfTrue, valueIfFalse); break; - default : - return; + default: + return expression; + } + } + } catch (SyntaxError e) { + // try to find next token after expression with errors: + if (token == TokenNameSEMICOLON) { + getNextToken(); + return expression; + } + if (token == TokenNameRBRACE || token == TokenNameRPAREN || token == TokenNameRBRACKET) { + getNextToken(); + return expression; } + throw e; } } - private void class_name_reference() { + + private SingleTypeReference class_name_reference() { // class_name_reference: // T_STRING //| dynamic_class_name_reference + SingleTypeReference ref = null; if (Scanner.TRACE) { System.out.println("TRACE: class_name_reference()"); } if (token == TokenNameIdentifier) { + ref = new SingleTypeReference(scanner.getCurrentIdentifierSource(), scanner.getCurrentTokenStartPosition()); getNextToken(); } else { + ref = null; dynamic_class_name_reference(); } + return ref; } + private void dynamic_class_name_reference() { //dynamic_class_name_reference: // base_variable T_OBJECT_OPERATOR object_property @@ -2312,6 +2535,7 @@ public class Parser //extends PHPParserSuperclass dynamic_class_name_variable_properties(); } } + private void dynamic_class_name_variable_properties() { // dynamic_class_name_variable_properties: // dynamic_class_name_variable_properties @@ -2324,6 +2548,7 @@ public class Parser //extends PHPParserSuperclass dynamic_class_name_variable_property(); } } + private void dynamic_class_name_variable_property() { // dynamic_class_name_variable_property: // T_OBJECT_OPERATOR object_property @@ -2335,6 +2560,7 @@ public class Parser //extends PHPParserSuperclass object_property(); } } + private void ctor_arguments() { // ctor_arguments: // /* empty */ @@ -2352,6 +2578,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } + private void assignment_list() { // assignment_list: // assignment_list ',' assignment_list_element @@ -2364,6 +2591,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } + private void assignment_list_element() { //assignment_list_element: // variable @@ -2387,6 +2615,7 @@ public class Parser //extends PHPParserSuperclass } } } + private void array_pair_list() { // array_pair_list: // /* empty */ @@ -2396,6 +2625,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } + private void non_empty_array_pair_list() { //non_empty_array_pair_list: // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr @@ -2434,6 +2664,7 @@ public class Parser //extends PHPParserSuperclass } } } + // private void variableList() { // do { // variable(); @@ -2444,7 +2675,7 @@ public class Parser //extends PHPParserSuperclass // } // } while (true); // } - private void variable_without_objects() { + private Expression variable_without_objects() { // variable_without_objects: // reference_variable // | simple_indirect_reference reference_variable @@ -2454,97 +2685,96 @@ public class Parser //extends PHPParserSuperclass while (token == TokenNameDOLLAR) { getNextToken(); } - reference_variable(); + return reference_variable(); } - private void function_call() { + + private Expression function_call() { // function_call: // T_STRING '(' function_call_parameter_list ')' //| class_constant '(' function_call_parameter_list ')' //| static_member '(' function_call_parameter_list ')' //| variable_without_objects '(' function_call_parameter_list ')' char[] defineName = null; - int startPos=0; - int endPos=0; + char[] ident = null; + int startPos = 0; + int endPos = 0; + Expression ref = null; if (Scanner.TRACE) { System.out.println("TRACE: function_call()"); } if (token == TokenNameIdentifier) { - defineName = scanner.getCurrentIdentifierSource(); + ident = scanner.getCurrentIdentifierSource(); + defineName = ident; startPos = scanner.getCurrentTokenStartPosition(); endPos = scanner.getCurrentTokenEndPosition(); getNextToken(); switch (token) { - case TokenNamePAAMAYIM_NEKUDOTAYIM : - // static member: - defineName = null; + case TokenNamePAAMAYIM_NEKUDOTAYIM: + // static member: + defineName = null; + getNextToken(); + if (token == TokenNameIdentifier) { + // class _constant getNextToken(); - if (token == TokenNameIdentifier) { - // class _constant - getNextToken(); - } else { - // static member: - variable_without_objects(); - } - break; + } else { + // static member: + variable_without_objects(); + } + break; } } else { - variable_without_objects(); + ref = variable_without_objects(); } if (token != TokenNameLPAREN) { - if (defineName!=null) { + if (defineName != null) { // does this identifier contain only uppercase characters? - if (defineName.length==3) { - if (defineName[0]=='d' && - defineName[1]=='i' && - defineName[2]=='e' ) { - defineName=null; - } - } else if (defineName.length==4) { - if (defineName[0]=='t' && - defineName[1]=='r' && - defineName[2]=='u' && - defineName[3]=='e' ) { - defineName=null; - } else if (defineName[0]=='n' && - defineName[1]=='u' && - defineName[2]=='l' && - defineName[3]=='l' ) { - defineName=null; + if (defineName.length == 3) { + if (defineName[0] == 'd' && defineName[1] == 'i' && defineName[2] == 'e') { + defineName = null; + } + } else if (defineName.length == 4) { + if (defineName[0] == 't' && defineName[1] == 'r' && defineName[2] == 'u' && defineName[3] == 'e') { + defineName = null; + } else if (defineName[0] == 'n' && defineName[1] == 'u' && defineName[2] == 'l' && defineName[3] == 'l') { + defineName = null; } - } else if (defineName.length==5) { - if (defineName[0]=='f' && - defineName[1]=='a' && - defineName[2]=='l' && - defineName[3]=='s' && - defineName[4]=='e' ) { - defineName=null; + } else if (defineName.length == 5) { + if (defineName[0] == 'f' && defineName[1] == 'a' && defineName[2] == 'l' && defineName[3] == 's' && defineName[4] == 'e') { + defineName = null; } } - if (defineName!=null) { - for (int i=0; i' expected in variable_property."); } } + private void method_or_not() { // method_or_not: // '(' function_call_parameter_list ')' @@ -2873,6 +3105,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } + private void exit_expr() { // /* empty */ // | '(' ')' @@ -2891,6 +3124,7 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); } + private void encaps_list() { // encaps_list encaps_var // | encaps_list T_STRING @@ -2906,71 +3140,65 @@ public class Parser //extends PHPParserSuperclass // | /* empty */ while (true) { switch (token) { - case TokenNameSTRING : - getNextToken(); - break; - case TokenNameLBRACE : - // scanner.encapsedStringStack.pop(); - getNextToken(); - break; - case TokenNameRBRACE : - // scanner.encapsedStringStack.pop(); - getNextToken(); - break; - case TokenNameLBRACKET : - // scanner.encapsedStringStack.pop(); - getNextToken(); - break; - case TokenNameRBRACKET : - // scanner.encapsedStringStack.pop(); - getNextToken(); - break; - case TokenNameMINUS_GREATER : - // scanner.encapsedStringStack.pop(); - getNextToken(); - break; - case TokenNameVariable : - case TokenNameDOLLAR_LBRACE : - case TokenNameCURLY_OPEN : - encaps_var(); - break; - // case TokenNameDOLLAR : - // getNextToken(); - // if (token == TokenNameLBRACE) { - // token = TokenNameDOLLAR_LBRACE; - // encaps_var(); - // } - // break; - default : - char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue(); - if (encapsedChar == '$') { - scanner.encapsedStringStack.pop(); - encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue(); - switch (encapsedChar) { - case '`' : - if (token == TokenNameEncapsedString0) { - return; - } - token = TokenNameSTRING; - continue; - case '\'' : - if (token == TokenNameEncapsedString1) { - return; - } - token = TokenNameSTRING; - continue; - case '"' : - if (token == TokenNameEncapsedString2) { - return; - } - token = TokenNameSTRING; - continue; + case TokenNameSTRING: + getNextToken(); + break; + case TokenNameLBRACE: + // scanner.encapsedStringStack.pop(); + getNextToken(); + break; + case TokenNameRBRACE: + // scanner.encapsedStringStack.pop(); + getNextToken(); + break; + case TokenNameLBRACKET: + // scanner.encapsedStringStack.pop(); + getNextToken(); + break; + case TokenNameRBRACKET: + // scanner.encapsedStringStack.pop(); + getNextToken(); + break; + case TokenNameMINUS_GREATER: + // scanner.encapsedStringStack.pop(); + getNextToken(); + break; + case TokenNameVariable: + case TokenNameDOLLAR_LBRACE: + case TokenNameLBRACE_DOLLAR: + encaps_var(); + break; + default: + char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue(); + if (encapsedChar == '$') { + scanner.encapsedStringStack.pop(); + encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue(); + switch (encapsedChar) { + case '`': + if (token == TokenNameEncapsedString0) { + return; + } + token = TokenNameSTRING; + continue; + case '\'': + if (token == TokenNameEncapsedString1) { + return; } + token = TokenNameSTRING; + continue; + case '"': + if (token == TokenNameEncapsedString2) { + return; + } + token = TokenNameSTRING; + continue; } - return; + } + return; } } } + private void encaps_var() { // T_VARIABLE // | T_VARIABLE '[' encaps_var_offset ']' @@ -2979,99 +3207,111 @@ public class Parser //extends PHPParserSuperclass // | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' // | T_CURLY_OPEN variable '}' switch (token) { - case TokenNameVariable : + case TokenNameVariable: + getNextToken(); + if (token == TokenNameLBRACKET) { + getNextToken(); + expr(); //encaps_var_offset(); + if (token != TokenNameRBRACKET) { + throwSyntaxError("']' expected after variable."); + } + // scanner.encapsedStringStack.pop(); + getNextToken(); + // } + } else if (token == TokenNameMINUS_GREATER) { + getNextToken(); + if (token != TokenNameIdentifier) { + throwSyntaxError("Identifier expected after '->'."); + } + // scanner.encapsedStringStack.pop(); + getNextToken(); + } + // else { + // // scanner.encapsedStringStack.pop(); + // int tempToken = TokenNameSTRING; + // if (!scanner.encapsedStringStack.isEmpty() + // && (token == TokenNameEncapsedString0 + // || token == TokenNameEncapsedString1 + // || token == TokenNameEncapsedString2 || token == + // TokenNameERROR)) { + // char encapsedChar = ((Character) + // scanner.encapsedStringStack.peek()) + // .charValue(); + // switch (token) { + // case TokenNameEncapsedString0 : + // if (encapsedChar == '`') { + // tempToken = TokenNameEncapsedString0; + // } + // break; + // case TokenNameEncapsedString1 : + // if (encapsedChar == '\'') { + // tempToken = TokenNameEncapsedString1; + // } + // break; + // case TokenNameEncapsedString2 : + // if (encapsedChar == '"') { + // tempToken = TokenNameEncapsedString2; + // } + // break; + // case TokenNameERROR : + // if (scanner.source[scanner.currentPosition - 1] == '\\') { + // scanner.currentPosition--; + // getNextToken(); + // } + // break; + // } + // } + // token = tempToken; + // } + break; + case TokenNameDOLLAR_LBRACE: + getNextToken(); + if (token == TokenNameDOLLAR_LBRACE) { + encaps_var(); + } else if (token == TokenNameIdentifier) { getNextToken(); if (token == TokenNameLBRACKET) { getNextToken(); - // if (token == TokenNameRBRACKET) { - // getNextToken(); - // } else { - expr(); //encaps_var_offset(); + // if (token == TokenNameRBRACKET) { + // getNextToken(); + // } else { + expr(); if (token != TokenNameRBRACKET) { - throwSyntaxError("']' expected after variable."); - } - // scanner.encapsedStringStack.pop(); - getNextToken(); - // } - } else if (token == TokenNameMINUS_GREATER) { - getNextToken(); - if (token != TokenNameIdentifier) { - throwSyntaxError("Identifier expected after '->'."); + throwSyntaxError("']' expected after '${'."); } - // scanner.encapsedStringStack.pop(); getNextToken(); + // } } - // else { - // // scanner.encapsedStringStack.pop(); - // int tempToken = TokenNameSTRING; - // if (!scanner.encapsedStringStack.isEmpty() - // && (token == TokenNameEncapsedString0 - // || token == TokenNameEncapsedString1 - // || token == TokenNameEncapsedString2 || token == - // TokenNameERROR)) { - // char encapsedChar = ((Character) - // scanner.encapsedStringStack.peek()) - // .charValue(); - // switch (token) { - // case TokenNameEncapsedString0 : - // if (encapsedChar == '`') { - // tempToken = TokenNameEncapsedString0; - // } - // break; - // case TokenNameEncapsedString1 : - // if (encapsedChar == '\'') { - // tempToken = TokenNameEncapsedString1; - // } - // break; - // case TokenNameEncapsedString2 : - // if (encapsedChar == '"') { - // tempToken = TokenNameEncapsedString2; - // } - // break; - // case TokenNameERROR : - // if (scanner.source[scanner.currentPosition - 1] == '\\') { - // scanner.currentPosition--; - // getNextToken(); - // } - // break; - // } - // } - // token = tempToken; - // } - break; - case TokenNameDOLLAR_LBRACE : + } else { + expr(); + } + if (token != TokenNameRBRACE) { + throwSyntaxError("'}' expected."); + } + getNextToken(); + break; + case TokenNameLBRACE_DOLLAR: + getNextToken(); + if (token == TokenNameLBRACE_DOLLAR) { + encaps_var(); + } else if (token == TokenNameIdentifier || token > TokenNameKEYWORD) { getNextToken(); - if (token == TokenNameIdentifier) { - getNextToken(); - if (token == TokenNameLBRACKET) { - getNextToken(); - // if (token == TokenNameRBRACKET) { - // getNextToken(); - // } else { - expr(); - if (token != TokenNameRBRACKET) { - throwSyntaxError("']' expected after '${'."); - } - getNextToken(); - // } - } - if (token != TokenNameRBRACE) { - throwSyntaxError("'}' expected after '${'."); - } - // scanner.encapsedStringStack.pop(); + if (token == TokenNameLBRACKET) { getNextToken(); - } else { + // if (token == TokenNameRBRACKET) { + // getNextToken(); + // } else { expr(); - if (token != TokenNameRBRACE) { - throwSyntaxError("'}' expected."); + if (token != TokenNameRBRACKET) { + throwSyntaxError("']' expected."); } - // scanner.encapsedStringStack.pop(); getNextToken(); - } - break; - case TokenNameCURLY_OPEN : - getNextToken(); - if (token == TokenNameIdentifier || token > TokenNameKEYWORD) { + // } + } else if (token == TokenNameMINUS_GREATER) { + getNextToken(); + if (token != TokenNameIdentifier && token != TokenNameVariable) { + throwSyntaxError("String or Variable token expected."); + } getNextToken(); if (token == TokenNameLBRACKET) { getNextToken(); @@ -3080,149 +3320,200 @@ public class Parser //extends PHPParserSuperclass // } else { expr(); if (token != TokenNameRBRACKET) { - throwSyntaxError("']' expected after '{$'."); + throwSyntaxError("']' expected after '${'."); } getNextToken(); // } - } else if (token == TokenNameMINUS_GREATER) { - getNextToken(); - if (token != TokenNameIdentifier) { - throwSyntaxError("String token expected."); - } - getNextToken(); - } - // if (token != TokenNameRBRACE) { - // throwSyntaxError("'}' expected after '{$'."); - // } - // // scanner.encapsedStringStack.pop(); - // getNextToken(); - } else { - expr(); - if (token != TokenNameRBRACE) { - throwSyntaxError("'}' expected."); } - // scanner.encapsedStringStack.pop(); - getNextToken(); } - break; + // if (token != TokenNameRBRACE) { + // throwSyntaxError("'}' expected after '{$'."); + // } + // // scanner.encapsedStringStack.pop(); + // getNextToken(); + } else { + expr(); + if (token != TokenNameRBRACE) { + throwSyntaxError("'}' expected."); + } + // scanner.encapsedStringStack.pop(); + getNextToken(); + } + break; } } + private void encaps_var_offset() { // T_STRING // | T_NUM_STRING // | T_VARIABLE switch (token) { - case TokenNameSTRING : - getNextToken(); - break; - case TokenNameIntegerLiteral : - getNextToken(); - break; - case TokenNameVariable : - getNextToken(); - break; - case TokenNameIdentifier : - getNextToken(); - break; - default : - throwSyntaxError("Variable or String token expected."); - break; + case TokenNameSTRING: + getNextToken(); + break; + case TokenNameIntegerLiteral: + getNextToken(); + break; + case TokenNameVariable: + getNextToken(); + break; + case TokenNameIdentifier: + getNextToken(); + break; + default: + throwSyntaxError("Variable or String token expected."); + break; } } + private void internal_functions_in_yacc() { - int start = 0; - ImportReference impt = null; + // int start = 0; switch (token) { - case TokenNameisset : - // T_ISSET '(' isset_variables ')' - getNextToken(); - if (token != TokenNameLPAREN) { - throwSyntaxError("'(' expected after keyword 'isset'"); - } - getNextToken(); - isset_variables(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after keyword 'isset'"); - } - getNextToken(); - break; - case TokenNameempty : - // T_EMPTY '(' variable ')' - getNextToken(); - if (token != TokenNameLPAREN) { - throwSyntaxError("'(' expected after keyword 'empty'"); - } - getNextToken(); - variable(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after keyword 'empty'"); - } - getNextToken(); - break; - case TokenNameinclude : - //T_INCLUDE expr - start = scanner.getCurrentTokenStartPosition(); - getNextToken(); - expr(); + case TokenNameisset: + // T_ISSET '(' isset_variables ')' + getNextToken(); + if (token != TokenNameLPAREN) { + throwSyntaxError("'(' expected after keyword 'isset'"); + } + getNextToken(); + isset_variables(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected after keyword 'isset'"); + } + getNextToken(); + break; + case TokenNameempty: + // T_EMPTY '(' variable ')' + getNextToken(); + if (token != TokenNameLPAREN) { + throwSyntaxError("'(' expected after keyword 'empty'"); + } + getNextToken(); + variable(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected after keyword 'empty'"); + } + getNextToken(); + break; + case TokenNameinclude: + //T_INCLUDE expr + checkFileName(token); + break; + case TokenNameinclude_once: + // T_INCLUDE_ONCE expr + checkFileName(token); + break; + case TokenNameeval: + // T_EVAL '(' expr ')' + getNextToken(); + if (token != TokenNameLPAREN) { + throwSyntaxError("'(' expected after keyword 'eval'"); + } + getNextToken(); + expr(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected after keyword 'eval'"); + } + getNextToken(); + break; + case TokenNamerequire: + //T_REQUIRE expr + checkFileName(token); + break; + case TokenNamerequire_once: + // T_REQUIRE_ONCE expr + checkFileName(token); + break; + } + } - impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false); - impt.declarationSourceEnd = impt.sourceEnd; - impt.declarationEnd = impt.declarationSourceEnd; - //endPosition is just before the ; - impt.declarationSourceStart = start; - includesList.add(impt); - break; - case TokenNameinclude_once : - // T_INCLUDE_ONCE expr - start = scanner.getCurrentTokenStartPosition(); - getNextToken(); - expr(); - impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false); - impt.declarationSourceEnd = impt.sourceEnd; - impt.declarationEnd = impt.declarationSourceEnd; - //endPosition is just before the ; - impt.declarationSourceStart = start; - includesList.add(impt); - break; - case TokenNameeval : - // T_EVAL '(' expr ')' + private void checkFileName(int includeToken) { + // expr + int start = scanner.getCurrentTokenStartPosition(); + boolean hasLPAREN = false; + getNextToken(); + if (token == TokenNameLPAREN) { + hasLPAREN = true; + getNextToken(); + } + Expression expression = expr(); + if (hasLPAREN) { + if (token == TokenNameRPAREN) { getNextToken(); - if (token != TokenNameLPAREN) { - throwSyntaxError("'(' expected after keyword 'eval'"); + } else { + throwSyntaxError("')' expected for keyword '" + scanner.toStringAction(includeToken) + "'"); + } + } + char[] currTokenSource = scanner.getCurrentTokenSource(start); + IFile file = null; + if (scanner.compilationUnit != null) { + IResource resource = scanner.compilationUnit.getResource(); + if (resource != null && resource instanceof IFile) { + file = (IFile) resource; + } + } + char[][] tokens; + tokens = new char[1][]; + tokens[0] = currTokenSource; + + ImportReference impt = new ImportReference(tokens, currTokenSource, start, scanner.getCurrentTokenEndPosition(), false); + impt.declarationSourceEnd = impt.sourceEnd; + impt.declarationEnd = impt.declarationSourceEnd; + //endPosition is just before the ; + impt.declarationSourceStart = start; + includesList.add(impt); + + if (expression instanceof StringLiteral) { + StringLiteral literal = (StringLiteral) expression; + char[] includeName = literal.source(); + if (includeName.length == 0) { + reportSyntaxError("Empty filename after keyword '" + scanner.toStringAction(includeToken) + "'", literal.sourceStart, + literal.sourceStart + 1); + } + String includeNameString = new String(includeName); + if (literal instanceof StringLiteralDQ) { + if (includeNameString.indexOf('$') >= 0) { + // assuming that the filename contains a variable => no filename check + return; } - getNextToken(); - expr(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after keyword 'eval'"); + } + if (includeNameString.startsWith("http://")) { + // assuming external include location + return; + } + if (file != null) { + // check the filename: + // System.out.println(new String(compilationUnit.getFileName())+" - "+ expression.toStringExpression()); + IProject project = file.getProject(); + if (project != null) { + IPath path = PHPFileUtil.determineFilePath(includeNameString, file, project); + + if (path == null) { + // reportSyntaxError("File: " + expression.toStringExpression() + " doesn't exist in project: " + // + project.getLocation().toString(), literal.sourceStart, literal.sourceEnd); + String[] args = { expression.toStringExpression(), project.getLocation().toString() }; + problemReporter.phpIncludeNotExistWarning(args, literal.sourceStart, literal.sourceEnd, referenceContext, + compilationUnit.compilationResult); + } else { + try { + // String projectPath = ProjectPrefUtil.getDocumentRoot(file.getProject()).toString(); + // String filePath = file.getRawLocation().toString(); + String filePath = path.toString(); + String ext = file.getRawLocation().getFileExtension(); + int fileExtensionLength = ext == null ? 0 : ext.length() + 1; + int length; + + impt.tokens = CharOperation.splitOn('/', filePath.toCharArray(), 0, filePath.length() - fileExtensionLength); + impt.setFile(PHPFileUtil.createFile(path, project)); + } catch (Exception e) { + // the file is outside of the workspace + } + } } - getNextToken(); - break; - case TokenNamerequire : - //T_REQUIRE expr - start = scanner.getCurrentTokenStartPosition(); - getNextToken(); - expr(); - impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false); - impt.declarationSourceEnd = impt.sourceEnd; - impt.declarationEnd = impt.declarationSourceEnd; - //endPosition is just before the ; - impt.declarationSourceStart = start; - includesList.add(impt); - break; - case TokenNamerequire_once : - // T_REQUIRE_ONCE expr - start = scanner.getCurrentTokenStartPosition(); - getNextToken(); - expr(); - impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false); - impt.declarationSourceEnd = impt.sourceEnd; - impt.declarationEnd = impt.declarationSourceEnd; - //endPosition is just before the ; - impt.declarationSourceStart = start; - includesList.add(impt); - break; + } } } + private void isset_variables() { // variable // | isset_variables ',' @@ -3238,6 +3529,7 @@ public class Parser //extends PHPParserSuperclass } } } + private boolean common_scalar() { // common_scalar: // T_LNUMBER @@ -3249,39 +3541,40 @@ public class Parser //extends PHPParserSuperclass // | T_METHOD_C // | T_FUNC_C switch (token) { - case TokenNameIntegerLiteral : - getNextToken(); - return true; - case TokenNameDoubleLiteral : - getNextToken(); - return true; - case TokenNameStringDoubleQuote : - getNextToken(); - return true; - case TokenNameStringSingleQuote : - getNextToken(); - return true; - case TokenNameStringInterpolated : - getNextToken(); - return true; - case TokenNameFILE : - getNextToken(); - return true; - case TokenNameLINE : - getNextToken(); - return true; - case TokenNameCLASS_C : - getNextToken(); - return true; - case TokenNameMETHOD_C : - getNextToken(); - return true; - case TokenNameFUNC_C : - getNextToken(); - return true; + case TokenNameIntegerLiteral: + getNextToken(); + return true; + case TokenNameDoubleLiteral: + getNextToken(); + return true; + case TokenNameStringDoubleQuote: + getNextToken(); + return true; + case TokenNameStringSingleQuote: + getNextToken(); + return true; + case TokenNameStringInterpolated: + getNextToken(); + return true; + case TokenNameFILE: + getNextToken(); + return true; + case TokenNameLINE: + getNextToken(); + return true; + case TokenNameCLASS_C: + getNextToken(); + return true; + case TokenNameMETHOD_C: + getNextToken(); + return true; + case TokenNameFUNC_C: + getNextToken(); + return true; } return false; } + private void scalar() { // scalar: // T_STRING @@ -3293,6 +3586,7 @@ public class Parser //extends PHPParserSuperclass //| T_START_HEREDOC encaps_list T_END_HEREDOC throwSyntaxError("Not yet implemented (scalar)."); } + private void static_scalar() { // static_scalar: /* compile-time evaluated scalars */ // common_scalar @@ -3305,98 +3599,99 @@ public class Parser //extends PHPParserSuperclass return; } switch (token) { - case TokenNameIdentifier : + case TokenNameIdentifier: + getNextToken(); + // static_class_constant: + // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING + if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) { getNextToken(); - // static_class_constant: - // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING - if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) { + if (token == TokenNameIdentifier) { getNextToken(); - if (token == TokenNameIdentifier) { - getNextToken(); - } else { - throwSyntaxError("Identifier expected after '::' operator."); - } + } else { + throwSyntaxError("Identifier expected after '::' operator."); } - break; - case TokenNameEncapsedString0 : - try { - scanner.currentCharacter = scanner.source[scanner.currentPosition++]; - while (scanner.currentCharacter != '`') { - if (scanner.currentCharacter == '\\') { - scanner.currentPosition++; - } - scanner.currentCharacter = scanner.source[scanner.currentPosition++]; + } + break; + case TokenNameEncapsedString0: + try { + scanner.currentCharacter = scanner.source[scanner.currentPosition++]; + while (scanner.currentCharacter != '`') { + if (scanner.currentCharacter == '\\') { + scanner.currentPosition++; } - getNextToken(); - } catch (IndexOutOfBoundsException e) { - throwSyntaxError("'`' expected at end of static string."); - } - break; - case TokenNameEncapsedString1 : - try { scanner.currentCharacter = scanner.source[scanner.currentPosition++]; - while (scanner.currentCharacter != '\'') { - if (scanner.currentCharacter == '\\') { - scanner.currentPosition++; - } - scanner.currentCharacter = scanner.source[scanner.currentPosition++]; - } - getNextToken(); - } catch (IndexOutOfBoundsException e) { - throwSyntaxError("'\'' expected at end of static string."); } - break; - case TokenNameEncapsedString2 : - try { - scanner.currentCharacter = scanner.source[scanner.currentPosition++]; - while (scanner.currentCharacter != '"') { - if (scanner.currentCharacter == '\\') { - scanner.currentPosition++; - } - scanner.currentCharacter = scanner.source[scanner.currentPosition++]; + getNextToken(); + } catch (IndexOutOfBoundsException e) { + throwSyntaxError("'`' expected at end of static string."); + } + break; + case TokenNameEncapsedString1: + try { + scanner.currentCharacter = scanner.source[scanner.currentPosition++]; + while (scanner.currentCharacter != '\'') { + if (scanner.currentCharacter == '\\') { + scanner.currentPosition++; } - getNextToken(); - } catch (IndexOutOfBoundsException e) { - throwSyntaxError("'\"' expected at end of static string."); + scanner.currentCharacter = scanner.source[scanner.currentPosition++]; } - break; - case TokenNamePLUS : - getNextToken(); - static_scalar(); - break; - case TokenNameMINUS : - getNextToken(); - static_scalar(); - break; - case TokenNamearray : getNextToken(); - if (token != TokenNameLPAREN) { - throwSyntaxError("'(' expected after keyword 'array'"); + } catch (IndexOutOfBoundsException e) { + throwSyntaxError("'\'' expected at end of static string."); + } + break; + case TokenNameEncapsedString2: + try { + scanner.currentCharacter = scanner.source[scanner.currentPosition++]; + while (scanner.currentCharacter != '"') { + if (scanner.currentCharacter == '\\') { + scanner.currentPosition++; + } + scanner.currentCharacter = scanner.source[scanner.currentPosition++]; } getNextToken(); - if (token == TokenNameRPAREN) { - getNextToken(); - break; - } - non_empty_static_array_pair_list(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after keyword 'array'"); - } + } catch (IndexOutOfBoundsException e) { + throwSyntaxError("'\"' expected at end of static string."); + } + break; + case TokenNamePLUS: + getNextToken(); + static_scalar(); + break; + case TokenNameMINUS: + getNextToken(); + static_scalar(); + break; + case TokenNamearray: + getNextToken(); + if (token != TokenNameLPAREN) { + throwSyntaxError("'(' expected after keyword 'array'"); + } + getNextToken(); + if (token == TokenNameRPAREN) { getNextToken(); break; - // case TokenNamenull : - // getNextToken(); - // break; - // case TokenNamefalse : - // getNextToken(); - // break; - // case TokenNametrue : - // getNextToken(); - // break; - default : - throwSyntaxError("Static scalar/constant expected."); + } + non_empty_static_array_pair_list(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' or ',' expected after keyword 'array'"); + } + getNextToken(); + break; + // case TokenNamenull : + // getNextToken(); + // break; + // case TokenNamefalse : + // getNextToken(); + // break; + // case TokenNametrue : + // getNextToken(); + // break; + default: + throwSyntaxError("Static scalar/constant expected."); } } + private void non_empty_static_array_pair_list() { // non_empty_static_array_pair_list: // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW @@ -3419,6 +3714,7 @@ public class Parser //extends PHPParserSuperclass } } } + public void reportSyntaxError() { //int act, int currentKind, int // stateStackTop) { /* remember current scanner position */ @@ -3508,7 +3804,7 @@ public class Parser //extends PHPParserSuperclass try { tokenSource = this.scanner.getCurrentTokenSource(); } catch (Exception e) { - tokenSource = new char[]{}; + tokenSource = new char[] {}; } // problemReporter().parseError( // this.scanner.startPosition, @@ -3523,31 +3819,55 @@ public class Parser //extends PHPParserSuperclass 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; + + //variable set stack + final static int VariableStackIncrement = 10; + + HashMap fTypeVariables = null; + + HashMap fMethodVariables = null; + //ast stack final static int AstStackIncrement = 100; + protected int astPtr; - protected AstNode[] astStack = new AstNode[AstStackIncrement]; + + protected ASTNode[] astStack = new ASTNode[AstStackIncrement]; + protected int astLengthPtr; + protected int[] astLengthStack; - AstNode[] noAstNodes = new AstNode[AstStackIncrement]; + + ASTNode[] noAstNodes = new ASTNode[AstStackIncrement]; + public CompilationUnitDeclaration compilationUnit; /* * the result from parse() */ + protected ReferenceContext referenceContext; + protected ProblemReporter problemReporter; + protected CompilerOptions options; + private ArrayList includesList; + // 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. + * 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) { @@ -3556,6 +3876,7 @@ public class Parser //extends PHPParserSuperclass problemReporter.referenceContext = referenceContext; return problemReporter; } + /* * Reconsider the entire source looking for inconsistencies in {} () [] */ @@ -3564,13 +3885,13 @@ public class Parser //extends PHPParserSuperclass 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]}; + 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 @@ -3602,131 +3923,156 @@ public class Parser //extends PHPParserSuperclass } 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]++; + 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); } - 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]; + 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); } - 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]++; + 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); } - 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]; + 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); } - 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]++; + 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); } - 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); + 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; } - rightPositions[SquareBracket][index] = scanner.startPosition; - rightDepths[SquareBracket][index] = --depths[SquareBracket]; + // } } - break; - case '\'' : { - if (scanner.getNextChar('\\')) { + 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(); - } 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.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(); + // } + } + 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++; } - // 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 ((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); } - // } } - break; - case '/' : { - int test; - if ((test = scanner.getNextChar('/', '*')) == 0) { //line - // comment + 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 @@ -3740,75 +4086,76 @@ public class Parser //extends PHPParserSuperclass || (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 + // don't // care of the // value scanner.currentCharacter = 'A'; - } //something different from \n and \r + } //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()); - } + } + 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; + 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 (scanner.currentCharacter == '*') { - star = true; + 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); } - //get the next char + } + //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 @@ -3822,59 +4169,33 @@ public class Parser //extends PHPParserSuperclass || (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 + // don't // care of the // value scanner.currentCharacter = 'A'; - } //something different from * and / + } //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; + } + if (this.scanner.taskTags != null) { + this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); } break; } - default : - if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) { - scanner.scanIdentifierOrKeyword(false); - break; - } - if (Character.isDigit(scanner.currentCharacter)) { - scanner.scanNumber(false); - 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-------------------- @@ -3951,6 +4272,7 @@ public class Parser //extends PHPParserSuperclass return anomaliesDetected; } } + protected void pushOnAstLengthStack(int pos) { try { astLengthStack[++astLengthPtr] = pos; @@ -3962,7 +4284,8 @@ public class Parser //extends PHPParserSuperclass astLengthStack[astLengthPtr] = pos; } } - protected void pushOnAstStack(AstNode node) { + + protected void pushOnAstStack(ASTNode node) { /* * add a new obj on top of the ast stack */ @@ -3970,8 +4293,8 @@ public class Parser //extends PHPParserSuperclass astStack[++astPtr] = node; } catch (IndexOutOfBoundsException e) { int oldStackLength = astStack.length; - AstNode[] oldStack = astStack; - astStack = new AstNode[oldStackLength + AstStackIncrement]; + ASTNode[] oldStack = astStack; + astStack = new ASTNode[oldStackLength + AstStackIncrement]; System.arraycopy(oldStack, 0, astStack, 0, oldStackLength); astPtr = oldStackLength; astStack[astPtr] = node; @@ -3993,4 +4316,31 @@ public class Parser //extends PHPParserSuperclass // modifiersFlag(int) this.scanner.commentPtr = -1; } + + protected void consumePackageDeclarationName(IFile file) { + // create a package name similar to java package names + String projectPath = ProjectPrefUtil.getDocumentRoot(file.getProject()).toString(); + String filePath = file.getRawLocation().toString(); + String ext = file.getRawLocation().getFileExtension(); + int fileExtensionLength = ext == null ? 0 : ext.length() + 1; + ImportReference impt; + int length; + char[][] tokens; + if (filePath.startsWith(projectPath)) { + tokens = CharOperation + .splitOn('/', filePath.toCharArray(), projectPath.length() + 1, filePath.length() - fileExtensionLength); + } else { + String name = file.getName(); + tokens = new char[1][]; + tokens[0] = name.substring(0, ext.length() - fileExtensionLength).toCharArray(); + } + + this.compilationUnit.currentPackage = impt = new ImportReference(tokens, new char[0], 0, 0, true); + + impt.declarationSourceStart = 0; + impt.declarationSourceEnd = 0; + impt.declarationEnd = 0; + //endPosition is just before the ; + + } } \ No newline at end of file