X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java index dceae31..91197e9 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,54 +1,77 @@ -/********************************************************************** - Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de - All rights reserved. This program and the accompanying materials - 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 - **********************************************************************/ +/*********************************************************************************************************************************** + * 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 + * + * Contributors: Klaus Hartlage - www.eclipseproject.de + **********************************************************************************************************************************/ package net.sourceforge.phpdt.internal.compiler.parser; + import java.util.ArrayList; + import net.sourceforge.phpdt.core.compiler.CharOperation; import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; import net.sourceforge.phpdt.core.compiler.InvalidInputException; +import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions; import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext; import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers; 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.phpeclipse.builder.IdentifierIndexManager; +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.CompilationUnitDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.Expression; +import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.IfStatement; +import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference; import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration; import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference; +import net.sourceforge.phpeclipse.internal.compiler.ast.Statement; import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration; -import net.sourceforge.phpeclipse.phpeditor.PHPString; + import org.eclipse.core.resources.IFile; + public class Parser //extends PHPParserSuperclass implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation { //internal data for the automat protected final static int StackIncrement = 255; + protected int stateStackTop; + protected int[] stack = new int[StackIncrement]; + public int firstToken; // handle for multiple parsing goals + public int lastAct; //handle for multiple parsing goals + protected RecoveredElement currentElement; + public static boolean VERBOSE_RECOVERY = false; + protected boolean diet = false; //tells the scanner to jump over some + // parts of the code/expressions like // method bodies //scanner token public Scanner scanner; + private 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: @@ -58,17 +81,27 @@ public class Parser //extends PHPParserSuperclass // // current identifier // String identifier; Long longNumber; + Double doubleNumber; + private String stringValue; + /** Contains the current expression. */ // private StringBuffer expression; - private boolean phpMode; + //private boolean phpMode; protected int modifiers; + protected int modifiersSourceStart; - protected Parser() { + + // protected IdentifierIndexManager indexManager; + + protected Parser(ProblemReporter problemReporter) { + this.problemReporter = problemReporter; + this.options = problemReporter.options; this.currentPHPString = 0; // PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; + // this.indexManager = null; this.str = ""; this.token = TokenNameEOF; // this.chIndx = 0; @@ -78,21 +111,24 @@ public class Parser //extends PHPParserSuperclass // getNextToken(); this.initializeScanner(); } + public void setFileToParse(IFile fileToParse) { this.currentPHPString = 0; // PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; + // this.indexManager = null; this.str = ""; this.token = TokenNameEOF; this.phpEnd = false; this.initializeScanner(); } + /** * ClassDeclaration Constructor. * * @param s * @param sess - * Description of Parameter + * Description of Parameter * @see */ public Parser(IFile fileToParse) { @@ -105,6 +141,7 @@ public class Parser //extends PHPParserSuperclass this.currentPHPString = 0; // PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; + this.includesList = null; this.str = ""; this.token = TokenNameEOF; // this.chIndx = 0; @@ -114,9 +151,13 @@ public class Parser //extends PHPParserSuperclass // getNextToken(); this.initializeScanner(); } + public void initializeScanner() { - this.scanner = new Scanner(false, false, false, false); + 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 */); } + /** * Create marker for the parse error */ @@ -125,46 +166,46 @@ 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 + * the error message * @throws SyntaxError - * the error raised + * the error raised */ private void throwSyntaxError(String error) { int problemStartPosition = scanner.getCurrentTokenStartPosition(); int problemEndPosition = scanner.getCurrentTokenEndPosition(); - throwSyntaxError(error, problemStartPosition, problemEndPosition); + 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 + * the error message * @throws SyntaxError - * the error raised + * the error raised */ // private void throwSyntaxError(String error, int startRow) { // 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); + private void throwSyntaxError(String error, int problemStartPosition, int problemEndPosition) { + problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, + compilationUnit.compilationResult); throw new SyntaxError(1, 0, " ", error); } - private void reportSyntaxError(String error, int problemStartPosition, - int problemEndPosition) { - problemReporter - .phpParsingError(new String[]{error}, problemStartPosition, - problemEndPosition, referenceContext, - compilationUnit.compilationResult); + + private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) { + 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); } + /** * Method Declaration. * @@ -191,435 +232,22 @@ public class Parser //extends PHPParserSuperclass if (Scanner.DEBUG) { int currentEndPosition = scanner.getCurrentTokenEndPosition(); int currentStartPosition = scanner.getCurrentTokenStartPosition(); - System.out - .print(currentStartPosition + "," + currentEndPosition + ": "); + System.out.print(currentStartPosition + "," + currentEndPosition + ": "); System.out.println(scanner.toStringAction(token)); } } catch (InvalidInputException e) { token = TokenNameERROR; - } - return; - } - /** - * Get a number. if it's a double the number will be stored in - * doubleNumber and the token will have the value - * {@link Parser#TokenNameDOUBLE_NUMBER}
- * if it's a double the number will be stored in longNumber - * and the token will have the value {@link Parser#TokenNameINT_NUMBER} - */ - // private void getNumber() { - // StringBuffer inum = new StringBuffer(); - // char dFlag = ' '; - // int numFormat = 10; - // - // // save first digit - // char firstCh = ch; - // inum.append(ch); - // - // getChar(); - // // determine number conversions: - // if (firstCh == '0') { - // switch (ch) { - // case 'b' : - // numFormat = 2; - // getChar(); - // break; - // case 'B' : - // numFormat = 2; - // getChar(); - // break; - // case 'o' : - // numFormat = 8; - // getChar(); - // break; - // case 'O' : - // numFormat = 8; - // getChar(); - // break; - // case 'x' : - // numFormat = 16; - // getChar(); - // break; - // case 'X' : - // numFormat = 16; - // getChar(); - // break; - // } - // } - // - // if (numFormat == 16) { - // while ((ch >= '0' && ch <= '9') - // || (ch >= 'a' && ch <= 'f') - // || (ch >= 'A' && ch <= 'F')) { - // inum.append(ch); - // getChar(); - // } - // } else { - // while ((ch >= '0' && ch <= '9') - // || (ch == '.') - // || (ch == 'E') - // || (ch == 'e')) { - // if ((ch == '.') || (ch == 'E') || (ch == 'e')) { - // if (ch == '.' && dFlag != ' ') { - // break; - // } - // if ((dFlag == 'E') || (dFlag == 'e')) { - // break; - // } - // dFlag = ch; - // inum.append(ch); - // getChar(); - // if ((ch == '-') || (ch == '+')) { - // inum.append(ch); - // getChar(); - // } - // } else { - // inum.append(ch); - // getChar(); - // } - // } - // } - // chIndx--; - // - // try { - // if (dFlag != ' ') { - // doubleNumber = new Double(inum.toString()); - // token = TokenNameDoubleLiteral; - // return; - // } else { - // longNumber = Long.valueOf(inum.toString(), numFormat); - // token = TokenNameIntegerLiteral; - // return; - // } - // - // } catch (Throwable e) { - // throwSyntaxError("Number format error: " + inum.toString()); - // } - // } - // - // /** - // * Get a String. - // * @param openChar the opening char ('\'', '"', '`') - // * @param typeString the type of string {@link - // #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING} - // * @param errorMsg the error message in case of parse error in the string - // */ - // private void getString( - // final char openChar, - // final int typeString, - // final String errorMsg) { - // StringBuffer sBuffer = new StringBuffer(); - // boolean openString = true; - // int startRow = rowCount; - // while (str.length() > chIndx) { - // ch = str.charAt(chIndx++); - // if (ch == '\\') { - // sBuffer.append(ch); - // if (str.length() > chIndx) { - // ch = str.charAt(chIndx++); - // sBuffer.append(ch); - // } - // } else if (ch == openChar) { - // openString = false; - // break; - // } else if (ch == '\n') { - // rowCount++; - // columnCount = chIndx; - // } else { - // sBuffer.append(ch); - // } - // } - // if (openString) { - // if (typeString == TokenNameStringConstant) { - // throwSyntaxError(errorMsg, startRow); - // } else { - // throwSyntaxError(errorMsg); - // } - // } - // token = typeString; - // stringValue = sBuffer.toString(); - // } - // public void htmlParserTester(String input) { - // int lineNumber = 1; - // int startLineNumber = 1; - // int startIndex = 0; - // char ch; - // char ch2; - // boolean phpMode = false; - // boolean phpFound = false; - // - // phpList = new ArrayList(); - // currentPHPString = 0; - // - // try { - // int i = 0; - // while (i < input.length()) { - // ch = input.charAt(i++); - // if (ch == '\n') { - // lineNumber++; - // } - // if ((!phpMode) && ch == '<') { - // ch2 = input.charAt(i++); - // if (ch2 == '?') { - // ch2 = input.charAt(i++); - // if (Character.isWhitespace(ch2)) { - // // php start - // phpMode = true; - // phpFound = true; - // startIndex = i; - // startLineNumber = lineNumber; - // continue; - // } else if (ch2 == 'p') { - // ch2 = input.charAt(i++); - // if (ch2 == 'h') { - // ch2 = input.charAt(i++); - // if (ch2 == 'p') { - // phpMode = true; - // phpFound = true; - // startIndex = i; - // startLineNumber = lineNumber; - // continue; - // } - // i--; - // } - // i--; - // } else if (ch2 == 'P') { - // ch2 = input.charAt(i++); - // if (ch2 == 'H') { - // ch2 = input.charAt(i++); - // if (ch2 == 'P') { - // phpMode = true; - // phpFound = true; - // startIndex = i; - // startLineNumber = lineNumber; - // continue; - // } - // i--; - // } - // i--; - // } - // i--; - // } - // i--; - // } - // - // if (phpMode) { - // if (ch == '/' && i < input.length()) { - // ch2 = input.charAt(i++); - // if (ch2 == '/') { - // while (i < input.length()) { - // ch = input.charAt(i++); - // if (ch == '?' && i < input.length()) { - // ch2 = input.charAt(i++); - // if (ch2 == '>') { - // // php end - // phpMode = false; - // phpList.add( - // new PHPString( - // input.substring( - // startIndex, - // i - 2), - // startLineNumber)); - // continue; - // } - // i--; - // } else if (ch == '\n') { - // lineNumber++; - // break; - // } - // } - // continue; - // } else if (ch2 == '*') { - // // multi-line comment - // while (i < input.length()) { - // ch = input.charAt(i++); - // if (ch == '\n') { - // lineNumber++; - // } else if (ch == '*' && i < input.length()) { - // ch2 = input.charAt(i++); - // if (ch2 == '/') { - // break; - // } - // i--; - // } - // } - // continue; - // } else { - // i--; - // } - // } else if (ch == '#') { - // while (i < input.length()) { - // ch = input.charAt(i++); - // if (ch == '?' && i < input.length()) { - // ch2 = input.charAt(i++); - // if (ch2 == '>') { - // // php end - // phpMode = false; - // phpList.add( - // new PHPString( - // input.substring(startIndex, i - 2), - // startLineNumber)); - // continue; - // } - // i--; - // } else if (ch == '\n') { - // lineNumber++; - // break; - // } - // } - // continue; - // } else if (ch == '"') { - // ch = ' '; - // while (i < input.length()) { - // ch = input.charAt(i++); - // if (ch == '\n') { - // lineNumber++; - // } else if ( - // ch == '\\' && i < input.length()) { // escape - // i++; - // } else if (ch == '"') { - // break; - // } - // } - // continue; - // } else if (ch == '\'') { - // ch = ' '; - // while (i < input.length()) { - // ch = input.charAt(i++); - // if (ch == '\n') { - // lineNumber++; - // } else if ( - // ch == '\\' && i < input.length()) { // escape - // i++; - // } else if (ch == '\'') { - // break; - // } - // } - // continue; - // } - // - // if (ch == '?' && i < input.length()) { - // ch2 = input.charAt(i++); - // if (ch2 == '>') { - // // php end - // phpMode = false; - // phpList.add( - // new PHPString( - // input.substring(startIndex, i - 2), - // startLineNumber)); - // continue; - // } - // i--; - // } - // } - // } - // - // if (!phpFound) { - // setMarker( - // "No PHP source code found.", - // lineNumber, - // PHPParser.INFO); - // } else { - // if (phpMode) { - // setMarker( - // "Open PHP tag at end of file.", - // lineNumber, - // PHPParser.INFO); - // phpList.add( - // new PHPString( - // input.substring(startIndex, i - 2), - // startLineNumber)); - // } - // // for (int j=0;j"); - // // } - // phpParserTester(null, 1); - // // PHPString temp; - // // for(int j=0;j TokenNameKEYWORD && token != TokenNamelist && token != - // TokenNamenew) { - // char[] ident = scanner.getCurrentIdentifierSource(); - // String keyword = new String(ident); - if (token == TokenNameAT) { - getNextToken(); - if (token != TokenNamerequire && token != TokenNamerequire_once - && token != TokenNameinclude && token != TokenNameinclude_once - && token != TokenNameIdentifier && token != TokenNameVariable - && token != TokenNamethis && token != TokenNameStringInterpolated) { - throwSyntaxError("identifier expected after '@'."); - } - } - if (token == TokenNameinclude || token == TokenNameinclude_once) { - getNextToken(); - 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 if (token == TokenNameif) { + + private Statement statement(int previousToken) { + Statement statement = null; + Expression expression; + int sourceStart = scanner.getCurrentTokenStartPosition(); + if (token == TokenNameif) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } 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) { @@ -1014,7 +645,7 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("')' expected after 'switch' condition."); } switchStatement(); - return; + return statement; } else if (token == TokenNamefor) { getNextToken(); if (token == TokenNameLPAREN) { @@ -1053,7 +684,7 @@ public class Parser //extends PHPParserSuperclass } } forStatement(); - return; + return statement; } else if (token == TokenNamewhile) { getNextToken(); if (token == TokenNameLPAREN) { @@ -1068,21 +699,21 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("')' expected after 'while' condition."); } whileStatement(); - return; + return statement; } else if (token == TokenNamedo) { getNextToken(); if (token == TokenNameLBRACE) { getNextToken(); + if (token != TokenNameRBRACE) { + statementList(); + } + if (token == TokenNameRBRACE) { + getNextToken(); + } else { + throwSyntaxError("'}' expected after 'do' keyword."); + } } else { - throwSyntaxError("'{' expected after 'do' keyword."); - } - if (token != TokenNameRBRACE) { - statementList(); - } - if (token == TokenNameRBRACE) { - getNextToken(); - } else { - throwSyntaxError("'}' expected after 'do' keyword."); + statement(TokenNameEOF); } if (token == TokenNamewhile) { getNextToken(); @@ -1103,12 +734,12 @@ public class Parser //extends PHPParserSuperclass if (token == TokenNameSEMICOLON) { getNextToken(); } else { - if (token != TokenNameStopPHP) { + if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after do-while statement."); } getNextToken(); } - return; + return statement; } else if (token == TokenNameforeach) { getNextToken(); if (token == TokenNameLPAREN) { @@ -1122,7 +753,9 @@ public class Parser //extends PHPParserSuperclass } else { throwSyntaxError("'as' expected after 'foreach' exxpression."); } - variable(); + // variable(); + foreach_variable(); + foreach_optional_arg(); if (token == TokenNameEQUAL_GREATER) { getNextToken(); variable(); @@ -1133,9 +766,8 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("')' expected after 'foreach' expression."); } foreachStatement(); - return; - } else if (token == TokenNamecontinue || token == TokenNamebreak - || token == TokenNamereturn) { + return statement; + } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) { getNextToken(); if (token != TokenNameSEMICOLON) { expr(); @@ -1143,24 +775,27 @@ public class Parser //extends PHPParserSuperclass if (token == TokenNameSEMICOLON) { getNextToken(); } else { - if (token != TokenNameStopPHP) { + if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after 'continue', 'break' or 'return'."); } getNextToken(); } - return; + return statement; } else if (token == TokenNameecho) { getNextToken(); expressionList(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { - if (token != TokenNameStopPHP) { + if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after 'echo' statement."); } getNextToken(); } - return; + return statement; + } else if (token == TokenNameINLINE_HTML) { + getNextToken(); + return statement; // } else if (token == TokenNameprint) { // getNextToken(); // expression(); @@ -1173,18 +808,30 @@ public class Parser //extends PHPParserSuperclass // getNextToken(); // } // return; - } else if (token == TokenNameglobal || token == TokenNamestatic) { + } else if (token == TokenNameglobal) { getNextToken(); - variableList(); + global_var_list(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { - if (token != TokenNameStopPHP) { - throwSyntaxError("';' expected after 'global' or 'static' statement."); + if (token != TokenNameINLINE_HTML) { + throwSyntaxError("';' expected after 'global' statement."); } getNextToken(); } - return; + return statement; + } else if (token == TokenNamestatic) { + getNextToken(); + static_var_list(); + if (token == TokenNameSEMICOLON) { + getNextToken(); + } else { + if (token != TokenNameINLINE_HTML) { + throwSyntaxError("';' expected after 'static' statement."); + } + getNextToken(); + } + return statement; } else if (token == TokenNameunset) { getNextToken(); if (token == TokenNameLPAREN) { @@ -1201,72 +848,73 @@ public class Parser //extends PHPParserSuperclass if (token == TokenNameSEMICOLON) { getNextToken(); } else { - if (token != TokenNameStopPHP) { + if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after 'unset' statement."); } getNextToken(); } - return; - // } else if (token == TokenNameexit || token == TokenNamedie) { - // getNextToken(); - // if (token != TokenNameSEMICOLON) { - // exitStatus(); - // } - // if (token == TokenNameSEMICOLON) { - // getNextToken(); - // } else { - // if (token != TokenNameStopPHP) { - // throwSyntaxError("';' expected after 'exit' or 'die' - // statement."); - // } - // getNextToken(); - // } - // return; - } else if (token == TokenNamedefine) { + return statement; + } else if (token == TokenNamefunction) { + MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); + methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); + methodDecl.modifiers = AccDefault; getNextToken(); - if (token == TokenNameLPAREN) { - getNextToken(); - } else { - throwSyntaxError("'(' expected after 'define' keyword."); + functionDefinition(methodDecl); + return statement; + } else if (token == TokenNametry) { + getNextToken(); + if (token != TokenNameLBRACE) { + throwSyntaxError("'{' expected in 'try' statement."); } - expr(); - if (token == TokenNameCOMMA) { - getNextToken(); - } else { - throwSyntaxError("',' expected after first 'define' constant."); + getNextToken(); + statementList(); + if (token != TokenNameRBRACE) { + throwSyntaxError("'}' expected in 'try' statement."); } - expr(); - if (token == TokenNameCOMMA) { - getNextToken(); - expr(); + getNextToken(); + return statement; + } else if (token == TokenNamecatch) { + getNextToken(); + if (token != TokenNameLPAREN) { + throwSyntaxError("'(' expected in 'catch' statement."); } - if (token == TokenNameRPAREN) { - getNextToken(); - } else { - throwSyntaxError("')' expected after 'define' statement."); + getNextToken(); + fully_qualified_class_name(); + if (token != TokenNameVariable) { + throwSyntaxError("Variable expected in 'catch' statement."); + } + getNextToken(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected in 'catch' statement."); } + getNextToken(); + if (token != TokenNameLBRACE) { + throwSyntaxError("'{' expected in 'catch' statement."); + } + getNextToken(); + if (token != TokenNameRBRACE) { + statementList(); + if (token != TokenNameRBRACE) { + throwSyntaxError("'}' expected in 'catch' statement."); + } + } + getNextToken(); + additional_catches(); + return statement; + } else if (token == TokenNamethrow) { + getNextToken(); + expr(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { - if (token != TokenNameStopPHP) { - throwSyntaxError("';' expected after 'define' statement."); - } - getNextToken(); + throwSyntaxError("';' expected after 'throw' exxpression."); } - return; - } else if (token == TokenNamefunction) { - MethodDeclaration methodDecl = new MethodDeclaration( - this.compilationUnit.compilationResult); - methodDecl.declarationSourceStart = scanner - .getCurrentTokenStartPosition(); - getNextToken(); - functionDefinition(methodDecl); - return; - } else if (token == TokenNamefinal || token == TokenNameabstract - || token == TokenNameclass || token == TokenNameinterface) { - TypeDeclaration typeDecl = new TypeDeclaration( - this.compilationUnit.compilationResult); + return statement; + } else if (token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) { + 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); @@ -1278,7 +926,7 @@ public class Parser //extends PHPParserSuperclass astPtr--; astLengthPtr--; } - return; + return statement; // } else { // throwSyntaxError("Unexpected keyword '" + keyword + "'"); } else if (token == TokenNameLBRACE) { @@ -1288,7 +936,7 @@ public class Parser //extends PHPParserSuperclass } if (token == TokenNameRBRACE) { getNextToken(); - return; + return statement; } else { throwSyntaxError("'}' expected."); } @@ -1298,16 +946,122 @@ 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) + ")"); + } + getNextToken(); + } + } + // may be null + return statement; + } + + private void additional_catches() { + while (token == TokenNamecatch) { + getNextToken(); + if (token != TokenNameLPAREN) { + throwSyntaxError("'(' expected in 'catch' statement."); + } + getNextToken(); + fully_qualified_class_name(); + if (token != TokenNameVariable) { + throwSyntaxError("Variable expected in 'catch' statement."); + } + getNextToken(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected in 'catch' statement."); + } + getNextToken(); + if (token != TokenNameLBRACE) { + throwSyntaxError("'{' expected in 'catch' statement."); + } + getNextToken(); + statementList(); + if (token != TokenNameRBRACE) { + throwSyntaxError("'}' expected in 'catch' statement."); + } + getNextToken(); + } + } + + private void foreach_variable() { + // w_variable + //| '&' w_variable + if (token == TokenNameAND) { + getNextToken(); + } + w_variable(); + } + + private void foreach_optional_arg() { + // /* empty */ + //| T_DOUBLE_ARROW foreach_variable + if (token == TokenNameEQUAL_GREATER) { + getNextToken(); + foreach_variable(); + } + } + + private void global_var_list() { + // global_var_list: + // global_var_list ',' global_var + //| global_var + while (true) { + global_var(); + if (token != TokenNameCOMMA) { + break; + } + getNextToken(); + } + } + + private void global_var() { + //global_var: + // T_VARIABLE + //| '$' r_variable + //| '$' '{' expr '}' + if (token == TokenNameVariable) { + getNextToken(); + } else if (token == TokenNameDOLLAR) { + getNextToken(); + if (token == TokenNameLPAREN) { + getNextToken(); + expr(); + if (token != TokenNameLPAREN) { + throwSyntaxError("')' expected in global variable."); + } + getNextToken(); } else { - if (token != TokenNameStopPHP && token != TokenNameEOF) { - throwSyntaxError("';' expected after expression (Found token: " - + scanner.toStringAction(token) + ")"); + r_variable(); + } + } + } + + private void static_var_list() { + //static_var_list: + // static_var_list ',' T_VARIABLE + //| static_var_list ',' T_VARIABLE '=' static_scalar + //| T_VARIABLE + //| T_VARIABLE '=' static_scalar + while (true) { + if (token == TokenNameVariable) { + getNextToken(); + if (token == TokenNameEQUAL) { + getNextToken(); + static_scalar(); + } + if (token != TokenNameCOMMA) { + break; } getNextToken(); + } else { + break; } } } + private void unset_variables() { // unset_variables: // unset_variable @@ -1322,15 +1076,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) { @@ -1340,23 +1097,21 @@ 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(); } else { - typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); - typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); - typeDecl.name = new char[]{' '}; - throwSyntaxError("Interface name expected after keyword 'interface'.", - typeDecl.sourceStart, typeDecl.sourceEnd); + typeDecl.name = new char[] { ' ' }; + throwSyntaxError("Interface name expected after keyword 'interface'.", typeDecl.sourceStart, typeDecl.sourceEnd); return; } } else { @@ -1365,38 +1120,36 @@ 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) { - getNextToken(); - if (token == TokenNameIdentifier) { - getNextToken(); - } else { - throwSyntaxError("Class name expected after keyword 'extends'.", - scanner.getCurrentTokenStartPosition(), scanner - .getCurrentTokenEndPosition()); - } + interface_extends_list(); + // getNextToken(); + // if (token != TokenNameIdentifier) { + // throwSyntaxError("Class name expected after keyword + // 'extends'.", + // scanner.getCurrentTokenStartPosition(), scanner + // .getCurrentTokenEndPosition()); + // } } implements_list(); } else { - typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); - typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); - typeDecl.name = new char[]{' '}; - throwSyntaxError("Class name expected after keyword 'class'.", - typeDecl.sourceStart, typeDecl.sourceEnd); + typeDecl.name = new char[] { ' ' }; + throwSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd); return; } } @@ -1404,18 +1157,24 @@ public class Parser //extends PHPParserSuperclass if (token == TokenNameLBRACE) { getNextToken(); if (token != TokenNameRBRACE) { - class_statement_list(); + ArrayList list = new ArrayList(); + class_statement_list(list); + typeDecl.fields = new FieldDeclaration[list.size()]; + for (int i = 0; i < list.size(); i++) { + typeDecl.fields[i] = (FieldDeclaration) list.get(i); + } } if (token == TokenNameRBRACE) { typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); getNextToken(); } else { - throwSyntaxError("'}' expected at end of interface body."); + throwSyntaxError("'}' expected at end of class body."); } } else { - throwSyntaxError("'{' expected at start of interface body."); + throwSyntaxError("'{' expected at start of class body."); } } + private void class_entry_type() { // T_CLASS // | T_ABSTRACT T_CLASS @@ -1431,14 +1190,16 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } else if (token == TokenNamefinal) { checkAndSetModifiers(AccFinal); + getNextToken(); if (token != TokenNameclass) { throwSyntaxError("Keyword 'class' expected after keyword 'final'."); } getNextToken(); } else { - throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected"); + throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected"); } } + private void interface_extends_list() { // /* empty */ // | T_EXTENDS interface_list @@ -1447,6 +1208,7 @@ public class Parser //extends PHPParserSuperclass interface_list(); } } + private void implements_list() { // /* empty */ // | T_IMPLEMENTS interface_list @@ -1455,6 +1217,7 @@ public class Parser //extends PHPParserSuperclass interface_list(); } } + private void interface_list() { // interface_list: // fully_qualified_class_name @@ -1471,6 +1234,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } while (true); } + // private void classBody(TypeDeclaration typeDecl) { // //'{' [class-element-list] '}' // if (token == TokenNameLBRACE) { @@ -1488,36 +1252,44 @@ public class Parser //extends PHPParserSuperclass // throwSyntaxError("'{' expected at start of class body."); // } // } - private void class_statement_list() { + private void class_statement_list(ArrayList list) { do { - class_statement(); - } while (token == TokenNamefunction || token == TokenNamevar); + class_statement(list); + } while (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic + || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar + || token == TokenNameconst); } - private void class_statement() { + + private void class_statement(ArrayList list) { // class_statement: // variable_modifiers class_variable_declaration ';' // | class_constant_declaration ';' // | method_modifiers T_FUNCTION is_reference T_STRING // '(' parameter_list ')' method_body initializeModifiers(); + int declarationSourceStart = scanner.getCurrentTokenStartPosition(); + if (token == TokenNamevar) { checkAndSetModifiers(AccPublic); - reportSyntaxError( - "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected' modifier for field declarations.", - scanner.getCurrentTokenStartPosition(), scanner - .getCurrentTokenEndPosition()); + problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), + referenceContext, compilationUnit.compilationResult); + getNextToken(); + class_variable_declaration(declarationSourceStart, list); + } else if (token == TokenNameconst) { + checkAndSetModifiers(AccFinal | AccPublic); + class_constant_declaration(declarationSourceStart, list); + if (token != TokenNameSEMICOLON) { + throwSyntaxError("';' expected after class const declaration."); + } getNextToken(); - classProperty(); } else { boolean hasModifiers = member_modifiers(); if (token == TokenNamefunction) { if (!hasModifiers) { checkAndSetModifiers(AccPublic); } - MethodDeclaration methodDecl = new MethodDeclaration( - this.compilationUnit.compilationResult); - methodDecl.declarationSourceStart = scanner - .getCurrentTokenStartPosition(); + MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); + methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); methodDecl.modifiers = this.modifiers; getNextToken(); functionDefinition(methodDecl); @@ -1525,23 +1297,44 @@ public class Parser //extends PHPParserSuperclass if (!hasModifiers) { throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations."); } - classProperty(); + class_variable_declaration(declarationSourceStart, list); } } - // if (token == TokenNamefunction) { - // MethodDeclaration methodDecl = new MethodDeclaration( - // this.compilationUnit.compilationResult); - // methodDecl.declarationSourceStart = scanner - // .getCurrentTokenStartPosition(); - // getNextToken(); - // functionDefinition(methodDecl); - // } else if (token == TokenNamevar) { - // getNextToken(); - // classProperty(); - // } else { - // throwSyntaxError("'function' or 'var' expected."); - // } } + + private void class_constant_declaration(int declarationSourceStart, ArrayList list) { + // class_constant_declaration ',' T_STRING '=' static_scalar + // | T_CONST T_STRING '=' static_scalar + if (token != TokenNameconst) { + throwSyntaxError("'const' keyword expected in class declaration."); + } else { + getNextToken(); + } + while (true) { + if (token != TokenNameIdentifier) { + throwSyntaxError("Identifier expected in class const declaration."); + } + FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner.getCurrentIdentifierSource(), scanner + .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition()); + fieldDeclaration.modifiers = this.modifiers; + fieldDeclaration.declarationSourceStart = declarationSourceStart; + fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); + fieldDeclaration.modifiersSourceStart = declarationSourceStart; + // fieldDeclaration.type + list.add(fieldDeclaration); + getNextToken(); + if (token != TokenNameEQUAL) { + throwSyntaxError("'=' expected in class const declaration."); + } + getNextToken(); + static_scalar(); + if (token != TokenNameCOMMA) { + break; // while(true)-loop + } + getNextToken(); + } + } + // private void variable_modifiers() { // // variable_modifiers: // // non_empty_member_modifiers @@ -1550,7 +1343,8 @@ public class Parser //extends PHPParserSuperclass // if (token == TokenNamevar) { // checkAndSetModifiers(AccPublic); // reportSyntaxError( - // "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected' + // "Keyword 'var' is deprecated. Please use 'public' 'private' or + // 'protected' // modifier for field declarations.", // scanner.getCurrentTokenStartPosition(), scanner // .getCurrentTokenEndPosition()); @@ -1610,67 +1404,99 @@ public class Parser //extends PHPParserSuperclass } return foundToken; } - private void classProperty() { - //'var' variable ';' - //'var' variable '=' constant ';' + + private void class_variable_declaration(int declarationSourceStart, ArrayList list) { + // class_variable_declaration: + // class_variable_declaration ',' T_VARIABLE + // | class_variable_declaration ',' T_VARIABLE '=' static_scalar + // | T_VARIABLE + // | T_VARIABLE '=' static_scalar + char[] classVariable; do { if (token == TokenNameVariable) { + classVariable = scanner.getCurrentIdentifierSource(); + // 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); getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); - constant(); + static_scalar(); } } else { - if (token == TokenNamethis) { - throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'."); - } - throwSyntaxError("Variable expected after keyword 'var'."); + // if (token == TokenNamethis) { + // throwSyntaxError("'$this' not allowed after keyword 'public' + // 'protected' 'private' 'var'."); + // } + throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'."); } if (token != TokenNameCOMMA) { break; } getNextToken(); } while (true); - if (token == TokenNameSEMICOLON) { - getNextToken(); - } else { - throwSyntaxError("';' expected after variable declaration."); + if (token != TokenNameSEMICOLON) { + throwSyntaxError("';' expected after field declaration."); } + getNextToken(); } + private void functionDefinition(MethodDeclaration methodDecl) { + boolean isAbstract = false; if (astPtr == 0) { 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, typeDecl.methods.length); + System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, + typeDecl.methods.length); newMethods[0] = methodDecl; typeDecl.methods = newMethods; } + if ((typeDecl.modifiers & AccAbstract) == AccAbstract) { + isAbstract = true; + } else if ((typeDecl.modifiers & AccInterface) == AccInterface) { + isAbstract = true; + } } } functionDeclarator(methodDecl); + if (token == TokenNameSEMICOLON) { + if (!isAbstract) { + throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector)); + } + getNextToken(); + return; + } functionBody(methodDecl); } + private void functionDeclarator(MethodDeclaration methodDecl) { //identifier '(' [parameter-list] ')' if (token == TokenNameAND) { getNextToken(); } - if (token == TokenNameIdentifier) { - methodDecl.sourceStart = scanner.getCurrentTokenStartPosition(); - methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); + methodDecl.sourceStart = scanner.getCurrentTokenStartPosition(); + methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); + 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()); + } getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); @@ -1678,7 +1504,7 @@ public class Parser //extends PHPParserSuperclass throwSyntaxError("'(' expected in function declaration."); } if (token != TokenNameRPAREN) { - parameterList(); + parameter_list(); } if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in function declaration."); @@ -1687,25 +1513,63 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } else { - if (token > TokenNameKEYWORD) { - throwSyntaxError("Don't use keyword for function declaration [" + token - + "]."); - } + methodDecl.selector = "".toCharArray(); throwSyntaxError("Function name expected after keyword 'function'."); } } + // - private void parameterList() { - //parameter-declaration - //parameter-list ',' parameter-declaration - do { - parameterDeclaration(); - if (token != TokenNameCOMMA) { - break; + private void parameter_list() { + // non_empty_parameter_list + // | /* empty */ + non_empty_parameter_list(true); + } + + private void non_empty_parameter_list(boolean empty_allowed) { + // optional_class_type T_VARIABLE + // | optional_class_type '&' T_VARIABLE + // | optional_class_type '&' T_VARIABLE '=' static_scalar + // | optional_class_type T_VARIABLE '=' static_scalar + // | non_empty_parameter_list ',' optional_class_type T_VARIABLE + // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE + // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '=' + // static_scalar + // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' + // static_scalar + if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) { + while (true) { + if (token == TokenNameIdentifier) { + getNextToken(); + } + if (token == TokenNameAND) { + getNextToken(); + } + if (token == TokenNameVariable) { + getNextToken(); + if (token == TokenNameEQUAL) { + getNextToken(); + static_scalar(); + } + } else { + throwSyntaxError("Variable expected in parameter list."); + } + if (token != TokenNameCOMMA) { + break; + } + getNextToken(); } - getNextToken(); - } while (true); + return; + } + if (!empty_allowed) { + throwSyntaxError("Identifier expected in parameter list."); + } + } + + private void optional_class_type() { + // /* empty */ + //| T_STRING } + private void parameterDeclaration() { //variable //variable-reference @@ -1722,14 +1586,16 @@ public class Parser //extends PHPParserSuperclass getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); - constant(); + static_scalar(); } return; } - if (token == TokenNamethis) { - throwSyntaxError("Reserved word '$this' not allowed in parameter declaration."); - } + // 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."); @@ -1740,10 +1606,8 @@ public class Parser //extends PHPParserSuperclass expr(); //constant(); if (token == TokenNameCOLON || token == TokenNameSEMICOLON) { getNextToken(); - if (token == TokenNamecase || token == TokenNamedefault) { // empty - // case - // statement - // ? + if (token == TokenNamecase || token == TokenNamedefault) { + // empty case statement ? continue; } statementList(); @@ -1762,20 +1626,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) { getNextToken(); - statementList(); + if (token == TokenNameRBRACE) { + // empty default case + break; + } + 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(); @@ -1831,26 +1701,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) { @@ -1884,34 +1754,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(); @@ -1929,6 +1801,7 @@ public class Parser //extends PHPParserSuperclass } } } + private void switchStatement() { if (token == TokenNameCOLON) { // ':' [labeled-statement-list] 'endswitch' ';' @@ -1957,6 +1830,7 @@ public class Parser //extends PHPParserSuperclass getNextToken(); } } + private void forStatement() { if (token == TokenNameCOLON) { getNextToken(); @@ -1973,6 +1847,7 @@ public class Parser //extends PHPParserSuperclass statement(TokenNameEOF); } } + private void whileStatement() { // ':' statement-list 'endwhile' ';' if (token == TokenNameCOLON) { @@ -1990,6 +1865,7 @@ public class Parser //extends PHPParserSuperclass statement(TokenNameEOF); } } + private void foreachStatement() { if (token == TokenNameCOLON) { getNextToken(); @@ -2006,6 +1882,7 @@ public class Parser //extends PHPParserSuperclass statement(TokenNameEOF); } } + // private void exitStatus() { // if (token == TokenNameLPAREN) { // getNextToken(); @@ -2031,637 +1908,1031 @@ public class Parser //extends PHPParserSuperclass } } while (true); } - private void expr() { - //todo: find a better way to get the expression - // expression = new StringBuffer(); - // for (int i = chIndx; i < str.length(); i++) { - // if (str.charAt(i) == ';') { - // break; - // } - // expression.append(str.charAt(i)); - // } - // if (token == TokenNameSTRING_CONSTANT || token == - // TokenNameINTERPOLATED_STRING) { - // getNextToken(); - // } else { - logicalinclusiveorExpression(); - // while (token != TokenNameSEMICOLON) { - // getNextToken(); - // // } + + private Expression expr() { + // r_variable + // | expr_without_variable + // if (token!=TokenNameEOF) { + if (Scanner.TRACE) { + System.out.println("TRACE: expr()"); + } + return expr_without_variable(true); // } } - private void expr_without_variable() { - // String ident; - char[] ident; - boolean castFlag = false; - boolean arrayFlag = false; + + private Expression expr_without_variable(boolean only_variable) { + Expression expression = new Expression(); + expression.sourceStart = scanner.getCurrentTokenStartPosition(); + // default, may be overwritten + expression.sourceEnd = scanner.getCurrentTokenEndPosition(); + // 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; - case TokenNamenew : - getNextToken(); - expr(); - break; - case TokenNamenull : - getNextToken(); - break; - case TokenNamefalse : - getNextToken(); - break; - case TokenNametrue : - getNextToken(); - break; - case TokenNameStringConstant : - getNextToken(); - break; - case TokenNameHEREDOC : - case TokenNameStringInterpolated : - case TokenNameStringLiteral : - getNextToken(); - break; - case TokenNameLPAREN : + case TokenNameisset: + case TokenNameempty: + case TokenNameeval: + case TokenNameinclude: + case TokenNameinclude_once: + case TokenNamerequire: + case TokenNamerequire_once: + internal_functions_in_yacc(); + break; + // | '(' expr ')' + case TokenNameLPAREN: + getNextToken(); + expr(); + if (token == TokenNameRPAREN) { getNextToken(); - if (token == TokenNameIdentifier) { - // check if identifier is a type: - // ident = identifier; - ident = scanner.getCurrentIdentifierSource(); - String str = new String(ident).toLowerCase(); - for (int i = 0; i < PHP_TYPES.length; i++) { - if (PHP_TYPES[i].equals(str)) { - castFlag = true; - if (PHP_TYPES[i].equals("array")) { - arrayFlag = true; - } - break; - } + } else { + throwSyntaxError("')' expected in expression."); + } + break; + // | T_CLONE expr + // | T_PRINT expr + // | '@' expr + // | '+' expr + // | '-' expr + // | '!' expr + // | '~' expr + // | 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 + 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: + getNextToken(); + exit_expr(); + break; + // scalar: + // T_STRING + //| T_STRING_VARNAME + //| class_constant + //| T_START_HEREDOC encaps_list T_END_HEREDOC + // | '`' encaps_list '`' + // | common_scalar + // | '`' encaps_list '`' + case TokenNameEncapsedString0: + scanner.encapsedStringStack.push(new Character('`')); + getNextToken(); + try { + if (token == TokenNameEncapsedString0) { + } else { + encaps_list(); + if (token != TokenNameEncapsedString0) { + throwSyntaxError("\'`\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )"); } } - if (castFlag) { - getNextToken(); - if (arrayFlag && token == TokenNameLPAREN) { - getNextToken(); - if (token == TokenNameRPAREN) { - getNextToken(); - } else { - expr(); - if (token != TokenNameRPAREN) { - throwSyntaxError(") expected after 'array('."); - } - } + } finally { + scanner.encapsedStringStack.pop(); + getNextToken(); + } + break; + // | '\'' encaps_list '\'' + case TokenNameEncapsedString1: + scanner.encapsedStringStack.push(new Character('\'')); + getNextToken(); + try { + if (token == TokenNameEncapsedString1) { + } else { + encaps_list(); + if (token != TokenNameEncapsedString1) { + throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )"); } - if (token != TokenNameRPAREN) { - throwSyntaxError(") expected after cast-type '" + str + "'."); + } + } finally { + scanner.encapsedStringStack.pop(); + getNextToken(); + } + break; + //| '"' encaps_list '"' + case TokenNameEncapsedString2: + scanner.encapsedStringStack.push(new Character('"')); + getNextToken(); + try { + if (token == TokenNameEncapsedString2) { + } else { + encaps_list(); + if (token != TokenNameEncapsedString2) { + throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )"); } + } + } finally { + scanner.encapsedStringStack.pop(); + 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: + common_scalar(); + break; + case TokenNameHEREDOC: + getNextToken(); + break; + case TokenNamearray: + // T_ARRAY '(' array_pair_list ')' + getNextToken(); + if (token == TokenNameLPAREN) { + getNextToken(); + if (token == TokenNameRPAREN) { getNextToken(); - expr(); break; - } else { - expr(); } + array_pair_list(); if (token != TokenNameRPAREN) { - throwSyntaxError(") expected in postfix-expression."); + throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")"); } getNextToken(); - break; - case TokenNameDoubleLiteral : - getNextToken(); - break; - case TokenNameIntegerLiteral : - getNextToken(); - break; - case TokenNameDOLLAR_LBRACE : + } else { + throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")"); + } + break; + case TokenNamelist: + // | T_LIST '(' assignment_list ')' '=' expr + getNextToken(); + if (token == TokenNameLPAREN) { getNextToken(); - expr(); - if (token != TokenNameRBRACE) { - throwSyntaxError("'}' expected after indirect variable token '${'."); + assignment_list(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected after 'list' keyword."); } getNextToken(); - break; - case TokenNameVariable : - case TokenNamethis : - ident = scanner.getCurrentIdentifierSource(); - getNextToken(); - if (token == TokenNameLBRACE) { + if (token != TokenNameEQUAL) { + throwSyntaxError("'=' expected after 'list' keyword."); + } getNextToken(); expr(); - if (token != TokenNameRBRACE) { - throwSyntaxError("'}' expected after variable '" - + new String(ident) + "' in variable-expression."); - } - getNextToken(); - } else if (token == TokenNameLPAREN) { - getNextToken(); - if (token != TokenNameRPAREN) { - expressionList(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after variable '" - + new String(ident) + "' in postfix-expression."); - } - } - getNextToken(); - } - break; - case TokenNameIdentifier : - ident = scanner.getCurrentIdentifierSource(); + } else { + throwSyntaxError("'(' expected after 'list' keyword."); + } + break; + case TokenNamenew: + // | T_NEW class_name_reference ctor_arguments + getNextToken(); + class_name_reference(); + ctor_arguments(); + break; + // | T_INC rw_variable + // | T_DEC rw_variable + case TokenNamePLUS_PLUS: + case TokenNameMINUS_MINUS: + getNextToken(); + rw_variable(); + break; + // | 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 + case TokenNameIdentifier: + case TokenNameVariable: + case TokenNameDOLLAR: + variable(); + switch (token) { + case TokenNameEQUAL: getNextToken(); - if (token == TokenNameLPAREN) { + if (token == TokenNameAND) { getNextToken(); - if (token != TokenNameRPAREN) { - expressionList(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after identifier '" - + new String(ident) + "' in postfix-expression." - + "(Found token: " + scanner.toStringAction(token) + ")"); - } + if (token == TokenNamenew) { + // | variable '=' '&' T_NEW class_name_reference + // ctor_arguments + getNextToken(); + class_name_reference(); + ctor_arguments(); + } else { + variable(); } - getNextToken(); + } else { + expr(); } break; - case TokenNameprint : - getNextToken(); - expr(); + 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 TokenNameexit : + case TokenNamePLUS_PLUS: + case TokenNameMINUS_MINUS: getNextToken(); - exit_expr(); break; - case TokenNamelist : - getNextToken(); - if (token == TokenNameLPAREN) { - getNextToken(); - if (token == TokenNameCOMMA) { - getNextToken(); - } - expressionList(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after 'list' keyword."); - } + default: + if (!only_variable) { + throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "')."); + } + } + break; + default: + if (token != TokenNameINLINE_HTML) { + if (token > TokenNameKEYWORD) { getNextToken(); - // if (token == TokenNameSET) { - // getNextToken(); - // logicalinclusiveorExpression(); - // } + break; } else { - throwSyntaxError("'(' expected after 'list' keyword."); + throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "')."); } - break; - // case TokenNameexit : - // getNextToken(); - // if (token != TokenNameSEMICOLON) { - // exitStatus(); - // } - // if (token == TokenNameSEMICOLON) { - // getNextToken(); - // } else { - // if (token != TokenNameStopPHP) { - // throwSyntaxError("';' expected after 'exit' expression."); - // } - // getNextToken(); - // } - // break; - // case TokenNamedie : - // getNextToken(); - // if (token != TokenNameSEMICOLON) { - // exitStatus(); - // } - // if (token == TokenNameSEMICOLON) { - // getNextToken(); - // } else { - // if (token != TokenNameStopPHP) { - // throwSyntaxError("';' expected after 'die' expression."); - // } - // } - // break; - // case TokenNamearray : - // getNextToken(); - // if (token == TokenNameARGOPEN) { - // getNextToken(); - // if (token == TokenNameCOMMA) { - // getNextToken(); - // } - // expressionList(); - // if (token != TokenNameARGCLOSE) { - // throwSyntaxError("')' expected after 'list' keyword."); - // } - // getNextToken(); - // if (token == TokenNameSET) { - // getNextToken(); - // logicalinclusiveorExpression(); - // } - // } else { - // throwSyntaxError("'(' expected after 'list' keyword."); - // } - // break; + } + return expression; } - boolean while_flag = true; - do { + 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 TokenNameLBRACKET : + 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: getNextToken(); expr(); - if (token != TokenNameRBRACKET) { - throwSyntaxError("] expected in postfix-expression."); - } - getNextToken(); - break; - case TokenNameCOLON_COLON : - // :: - case TokenNameMINUS_GREATER : - // -> - getNextToken(); - if (token > TokenNameKEYWORD) { - ident = scanner.getCurrentIdentifierSource(); - // setMarker( - // "Avoid using keyword '" - // + new String(ident) - // + "' as variable name.", - // rowCount, - // PHPParser.INFO); - // setMarker( - // "Avoid using keyword '" + new String(ident) + "' as - // variable name.", - // scanner.getCurrentTokenStartPosition(), - // scanner.getCurrentTokenEndPosition(), - // INFO); - } - switch (token) { - case TokenNameVariable : - ident = scanner.getCurrentIdentifierSource(); - getNextToken(); - // if (token == TokenNameARGOPEN) { - // getNextToken(); - // expressionList(); - // if (token != TokenNameARGCLOSE) { - // throwSyntaxError(") expected after variable '" + - // ident + "'."); - // } - // getNextToken(); - // } - break; - case TokenNameIdentifier : - //ident = scanner.getCurrentIdentifierSource(); - getNextToken(); - break; - case TokenNameLBRACE : - getNextToken(); - expr(); - if (token != TokenNameRBRACE) { - throwSyntaxError("} expected in postfix-expression."); - } - getNextToken(); - break; - default : - throwSyntaxError("Syntax error after '->' token."); - } - while (token == TokenNameLBRACKET || token == TokenNameLPAREN - || token == TokenNameLBRACE) { - if (token == TokenNameLBRACKET) { - getNextToken(); - expressionList(); - if (token != TokenNameRBRACKET) { - throwSyntaxError("] expected after '->'."); - } - getNextToken(); - } else if (token == TokenNameLPAREN) { - getNextToken(); - expressionList(); - if (token != TokenNameRPAREN) { - throwSyntaxError(") expected after '->'."); - } - getNextToken(); - } else if (token == TokenNameLBRACE) { - getNextToken(); - expr(); - if (token != TokenNameRBRACE) { - throwSyntaxError("} expected after '->'."); - } - getNextToken(); - } - } - break; - case TokenNamePLUS_PLUS : - getNextToken(); - break; - case TokenNameMINUS_MINUS : - getNextToken(); - break; - default : - while_flag = false; - } - } while (while_flag); - } - private void unaryExpression() { - switch (token) { - case TokenNamePLUS_PLUS : - getNextToken(); - unaryExpression(); break; - case TokenNameMINUS_MINUS : + // | expr T_INSTANCEOF class_name_reference + // | expr '?' expr ':' expr + case TokenNameinstanceof: getNextToken(); - unaryExpression(); + class_name_reference(); break; - // '@' '&' '*' '+' '-' '~' '!' - case TokenNameAT : - getNextToken(); - if (token == TokenNameinclude || token == TokenNameinclude_once - || token == TokenNamerequire || token == TokenNamerequire_once) { - statement(TokenNameAT); - } else { - expr_without_variable(); // castExpression(); + case TokenNameQUESTION: + getNextToken(); + expr(); + if (token == TokenNameCOLON) { + getNextToken(); + expr(); } break; - case TokenNameAND : - getNextToken(); - castExpression(); - break; - case TokenNameMULTIPLY : - getNextToken(); - castExpression(); - break; - case TokenNamePLUS : - getNextToken(); - castExpression(); - break; - case TokenNameMINUS : - getNextToken(); - castExpression(); - break; - case TokenNameTWIDDLE : - getNextToken(); - castExpression(); - break; - case TokenNameNOT : - getNextToken(); - castExpression(); - break; - default : - expr_without_variable(); + default: + return expression; + } } } - private void castExpression() { - // if (token == TokenNameARGOPEN) { - // getNextToken(); - // typeName(); - // if (token != TokenNameARGCLOSE) { - // throwSyntaxError(") expected after cast-expression."); - // } - // getNextToken(); - // } - unaryExpression(); - } - private void assignExpression() { - castExpression(); - if (token == TokenNameEQUAL) { // = - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameDOT_EQUAL) { // .= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameEQUAL_GREATER) { // => - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNamePLUS_EQUAL) { // += - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameMINUS_EQUAL) { // -= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameMULTIPLY_EQUAL) { // *= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameDIVIDE_EQUAL) { // *= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameREMAINDER_EQUAL) { // %= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameAND_EQUAL) { // &= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameOR_EQUAL) { // |= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameXOR_EQUAL) { // ^= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>= - getNextToken(); - logicalinclusiveorExpression(); - } else if (token == TokenNameTWIDDLE_EQUAL) { // ~= + + private void class_name_reference() { + // class_name_reference: + // T_STRING + //| dynamic_class_name_reference + if (Scanner.TRACE) { + System.out.println("TRACE: class_name_reference()"); + } + if (token == TokenNameIdentifier) { getNextToken(); - logicalinclusiveorExpression(); + } else { + dynamic_class_name_reference(); } } - private void multiplicativeExpression() { - do { - assignExpression(); - if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE - && token != TokenNameREMAINDER) { - return; - } + + private void dynamic_class_name_reference() { + //dynamic_class_name_reference: + // base_variable T_OBJECT_OPERATOR object_property + // dynamic_class_name_variable_properties + //| base_variable + if (Scanner.TRACE) { + System.out.println("TRACE: dynamic_class_name_reference()"); + } + base_variable(); + if (token == TokenNameMINUS_GREATER) { getNextToken(); - } while (true); + object_property(); + dynamic_class_name_variable_properties(); + } } - private void concatenationExpression() { - do { - multiplicativeExpression(); - if (token != TokenNameDOT) { - return; - } + + private void dynamic_class_name_variable_properties() { + // dynamic_class_name_variable_properties: + // dynamic_class_name_variable_properties + // dynamic_class_name_variable_property + // | /* empty */ + if (Scanner.TRACE) { + System.out.println("TRACE: dynamic_class_name_variable_properties()"); + } + while (token == TokenNameMINUS_GREATER) { + dynamic_class_name_variable_property(); + } + } + + private void dynamic_class_name_variable_property() { + // dynamic_class_name_variable_property: + // T_OBJECT_OPERATOR object_property + if (Scanner.TRACE) { + System.out.println("TRACE: dynamic_class_name_variable_property()"); + } + if (token == TokenNameMINUS_GREATER) { getNextToken(); - } while (true); + object_property(); + } } - private void additiveExpression() { - do { - concatenationExpression(); - if (token != TokenNamePLUS && token != TokenNameMINUS) { + + private void ctor_arguments() { + // ctor_arguments: + // /* empty */ + //| '(' function_call_parameter_list ')' + if (token == TokenNameLPAREN) { + getNextToken(); + if (token == TokenNameRPAREN) { + getNextToken(); return; } + non_empty_function_call_parameter_list(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected in ctor_arguments."); + } getNextToken(); - } while (true); + } } - private void shiftExpression() { - do { - additiveExpression(); - if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) { - return; + + private void assignment_list() { + // assignment_list: + // assignment_list ',' assignment_list_element + //| assignment_list_element + while (true) { + assignment_list_element(); + if (token != TokenNameCOMMA) { + break; } getNextToken(); - } while (true); + } } - private void relationalExpression() { - do { - shiftExpression(); - if (token != TokenNameLESS && token != TokenNameGREATER - && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) { - return; + + private void assignment_list_element() { + //assignment_list_element: + // variable + //| T_LIST '(' assignment_list ')' + //| /* empty */ + if (token == TokenNameVariable || token == TokenNameDOLLAR) { + variable(); + } else { + if (token == TokenNamelist) { + getNextToken(); + if (token == TokenNameLPAREN) { + getNextToken(); + assignment_list(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected after 'list' keyword."); + } + getNextToken(); + } else { + throwSyntaxError("'(' expected after 'list' keyword."); + } } + } + } + + private void array_pair_list() { + // array_pair_list: + // /* empty */ + //| non_empty_array_pair_list possible_comma + non_empty_array_pair_list(); + if (token == TokenNameCOMMA) { getNextToken(); - } while (true); + } } - private void identicalExpression() { - do { - relationalExpression(); - if (token != TokenNameEQUAL_EQUAL_EQUAL - && token != TokenNameNOT_EQUAL_EQUAL) { + + private void non_empty_array_pair_list() { + //non_empty_array_pair_list: + // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr + //| non_empty_array_pair_list ',' expr + //| expr T_DOUBLE_ARROW expr + //| expr + //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable + //| non_empty_array_pair_list ',' '&' w_variable + //| expr T_DOUBLE_ARROW '&' w_variable + //| '&' w_variable + while (true) { + if (token == TokenNameAND) { + getNextToken(); + variable(); + } else { + expr(); + if (token == TokenNameAND) { + getNextToken(); + variable(); + } else if (token == TokenNameEQUAL_GREATER) { + getNextToken(); + if (token == TokenNameAND) { + getNextToken(); + variable(); + } else { + expr(); + } + } + } + if (token != TokenNameCOMMA) { return; } getNextToken(); - } while (true); - } - private void equalityExpression() { - do { - identicalExpression(); - if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) { + if (token == TokenNameRPAREN) { return; } + } + } + + // private void variableList() { + // do { + // variable(); + // if (token == TokenNameCOMMA) { + // getNextToken(); + // } else { + // break; + // } + // } while (true); + // } + private void variable_without_objects() { + // variable_without_objects: + // reference_variable + // | simple_indirect_reference reference_variable + if (Scanner.TRACE) { + System.out.println("TRACE: variable_without_objects()"); + } + while (token == TokenNameDOLLAR) { getNextToken(); - } while (true); + } + reference_variable(); } - private void ternaryExpression() { - equalityExpression(); - if (token == TokenNameQUESTION) { + + private void 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; + char[] ident = null; + int startPos = 0; + int endPos = 0; + if (Scanner.TRACE) { + System.out.println("TRACE: function_call()"); + } + if (token == TokenNameIdentifier) { + ident = scanner.getCurrentIdentifierSource(); + defineName = ident; + startPos = scanner.getCurrentTokenStartPosition(); + endPos = scanner.getCurrentTokenEndPosition(); getNextToken(); - expr(); - if (token == TokenNameCOLON) { + switch (token) { + case TokenNamePAAMAYIM_NEKUDOTAYIM: + // static member: + defineName = null; getNextToken(); - expr(); - } else { - throwSyntaxError("':' expected in ternary operator '? :'."); + if (token == TokenNameIdentifier) { + // class _constant + getNextToken(); + } else { + // static member: + variable_without_objects(); + } + break; } + } else { + variable_without_objects(); } - } - private void andExpression() { - do { - ternaryExpression(); - if (token != TokenNameAND) { - return; + if (token != TokenNameLPAREN) { + 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; + } + } 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 < defineName.length; i++) { + if (Character.isLowerCase(defineName[i])) { + problemReporter.phpUppercaseIdentifierWarning(startPos, endPos, referenceContext, compilationUnit.compilationResult); + break; + } + } + } } + // TODO is this ok ? + return; + // throwSyntaxError("'(' expected in function call."); + } + getNextToken(); + if (token == TokenNameRPAREN) { getNextToken(); - } while (true); - } - private void exclusiveorExpression() { - do { - andExpression(); - if (token != TokenNameXOR) { - return; + return; + } + non_empty_function_call_parameter_list(); + if (token != TokenNameRPAREN) { + String functionName; + if (ident == null) { + functionName = new String(" "); + } else { + functionName = new String(ident); } - getNextToken(); - } while (true); + throwSyntaxError("')' expected in function call (" + functionName + ")."); + } + getNextToken(); } - private void inclusiveorExpression() { - do { - exclusiveorExpression(); - if (token != TokenNameOR) { - return; + + // private void function_call_parameter_list() { + // function_call_parameter_list: + // non_empty_function_call_parameter_list { $$ = $1; } + // | /* empty */ + // } + private void non_empty_function_call_parameter_list() { + //non_empty_function_call_parameter_list: + // expr_without_variable + // | variable + // | '&' w_variable + // | non_empty_function_call_parameter_list ',' expr_without_variable + // | non_empty_function_call_parameter_list ',' variable + // | non_empty_function_call_parameter_list ',' '&' w_variable + if (Scanner.TRACE) { + System.out.println("TRACE: non_empty_function_call_parameter_list()"); + } + while (true) { + if (token == TokenNameAND) { + getNextToken(); + w_variable(); + } else { + // if (token == TokenNameIdentifier || token == + // TokenNameVariable + // || token == TokenNameDOLLAR) { + // variable(); + // } else { + expr_without_variable(true); + // } + } + if (token != TokenNameCOMMA) { + break; } getNextToken(); - } while (true); + } } - private void booleanandExpression() { - do { - inclusiveorExpression(); - if (token != TokenNameAND_AND) { - return; - } + + private void fully_qualified_class_name() { + if (token == TokenNameIdentifier) { getNextToken(); - } while (true); + } else { + throwSyntaxError("Class name expected."); + } } - private void booleanorExpression() { - do { - booleanandExpression(); - if (token != TokenNameOR_OR) { - return; + + private void static_member() { + // static_member: + // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM + // variable_without_objects + if (Scanner.TRACE) { + System.out.println("TRACE: static_member()"); + } + fully_qualified_class_name(); + if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) { + throwSyntaxError("'::' expected after class name (static_member)."); + } + getNextToken(); + variable_without_objects(); + } + + private void base_variable_with_function_calls() { + // base_variable_with_function_calls: + // base_variable + //| function_call + boolean functionCall = false; + if (Scanner.TRACE) { + System.out.println("TRACE: base_variable_with_function_calls()"); + } + // if (token == TokenNameIdentifier) { + // functionCall = true; + // } else if (token == TokenNameVariable) { + // int tempToken = token; + // int tempPosition = scanner.currentPosition; + // getNextToken(); + // if (token == TokenNameLPAREN) { + // functionCall = true; + // } + // token = tempToken; + // scanner.currentPosition = tempPosition; + // scanner.phpMode = true; + // } + // if (functionCall) { + function_call(); + // } else { + // base_variable(); + // } + } + + private void base_variable() { + // base_variable: + // reference_variable + // | simple_indirect_reference reference_variable + // | static_member + if (Scanner.TRACE) { + System.out.println("TRACE: base_variable()"); + } + if (token == TokenNameIdentifier) { + static_member(); + } else { + while (token == TokenNameDOLLAR) { + getNextToken(); } - getNextToken(); - } while (true); + reference_variable(); + } } - private void logicalandExpression() { - do { - booleanorExpression(); - if (token != TokenNameAND) { - return; + + // private void simple_indirect_reference() { + // // simple_indirect_reference: + // // '$' + // //| simple_indirect_reference '$' + // } + private void reference_variable() { + // reference_variable: + // reference_variable '[' dim_offset ']' + // | reference_variable '{' expr '}' + // | compound_variable + if (Scanner.TRACE) { + System.out.println("TRACE: reference_variable()"); + } + compound_variable(); + while (true) { + if (token == TokenNameLBRACE) { + getNextToken(); + expr(); + if (token != TokenNameRBRACE) { + throwSyntaxError("'}' expected in reference variable."); + } + getNextToken(); + } else if (token == TokenNameLBRACKET) { + getNextToken(); + if (token != TokenNameRBRACKET) { + expr(); + // dim_offset(); + if (token != TokenNameRBRACKET) { + throwSyntaxError("']' expected in reference variable."); + } + } + getNextToken(); + } else { + break; } - getNextToken(); - } while (true); + } } - private void logicalexclusiveorExpression() { - do { - logicalandExpression(); - if (token != TokenNameXOR) { - return; + + private void compound_variable() { + // compound_variable: + // T_VARIABLE + // | '$' '{' expr '}' + if (Scanner.TRACE) { + System.out.println("TRACE: compound_variable()"); + } + if (token == TokenNameVariable) { + getNextToken(); + } else { + // because of simple_indirect_reference + while (token == TokenNameDOLLAR) { + getNextToken(); + } + if (token != TokenNameLBRACE) { + throwSyntaxError("'{' expected after compound variable token '$'."); } getNextToken(); - } while (true); - } - private void logicalinclusiveorExpression() { - do { - logicalexclusiveorExpression(); - if (token != TokenNameOR) { - return; + expr(); + if (token != TokenNameRBRACE) { + throwSyntaxError("'}' expected after compound variable token '$'."); } getNextToken(); - } while (true); + } } - // public void assignmentExpression() { - // if (token == TokenNameVARIABLE) { - // getNextToken(); - // if (token == TokenNameSET) { - // getNextToken(); - // logicalinclusiveorExpression(); - // } - // } else { - // logicalinclusiveorExpression(); - // } + + // private void dim_offset() { + // // dim_offset: + // // /* empty */ + // // | expr + // expr(); // } - private void variableList() { - do { - variable(); - if (token == TokenNameCOMMA) { + private void object_property() { + // object_property: + // object_dim_list + //| variable_without_objects + if (Scanner.TRACE) { + System.out.println("TRACE: object_property()"); + } + if (token == TokenNameVariable || token == TokenNameDOLLAR) { + variable_without_objects(); + } else { + object_dim_list(); + } + } + + private void object_dim_list() { + //object_dim_list: + // object_dim_list '[' dim_offset ']' + //| object_dim_list '{' expr '}' + //| variable_name + if (Scanner.TRACE) { + System.out.println("TRACE: object_dim_list()"); + } + variable_name(); + while (true) { + if (token == TokenNameLBRACE) { + getNextToken(); + expr(); + if (token != TokenNameRBRACE) { + throwSyntaxError("'}' expected in object_dim_list."); + } + getNextToken(); + } else if (token == TokenNameLBRACKET) { + getNextToken(); + if (token == TokenNameRBRACKET) { + getNextToken(); + continue; + } + expr(); + if (token != TokenNameRBRACKET) { + throwSyntaxError("']' expected in object_dim_list."); + } getNextToken(); } else { break; } - } while (true); + } } - private void variable() { - if (token == TokenNameDOLLAR_LBRACE) { + + private void variable_name() { + //variable_name: + // T_STRING + //| '{' expr '}' + if (Scanner.TRACE) { + System.out.println("TRACE: variable_name()"); + } + if (token == TokenNameIdentifier || token > TokenNameKEYWORD) { + if (token > TokenNameKEYWORD) { + // TODO show a warning "Keyword used as variable" ? + } + getNextToken(); + } else { + if (token != TokenNameLBRACE) { + throwSyntaxError("'{' expected in variable name."); + } getNextToken(); expr(); - ; if (token != TokenNameRBRACE) { - throwSyntaxError("'}' expected after indirect variable token '${'."); + throwSyntaxError("'}' expected in variable name."); } getNextToken(); + } + } + + private void r_variable() { + variable(); + } + + private void w_variable() { + variable(); + } + + private void rw_variable() { + variable(); + } + + private void variable() { + // variable: + // base_variable_with_function_calls T_OBJECT_OPERATOR + // object_property method_or_not variable_properties + // | base_variable_with_function_calls + base_variable_with_function_calls(); + if (token == TokenNameMINUS_GREATER) { + getNextToken(); + object_property(); + method_or_not(); + variable_properties(); + } + // if (token == TokenNameDOLLAR_LBRACE) { + // getNextToken(); + // expr(); + // ; + // if (token != TokenNameRBRACE) { + // throwSyntaxError("'}' expected after indirect variable token '${'."); + // } + // getNextToken(); + // } else { + // if (token == TokenNameVariable) { + // getNextToken(); + // if (token == TokenNameLBRACKET) { + // getNextToken(); + // expr(); + // if (token != TokenNameRBRACKET) { + // throwSyntaxError("']' expected in variable-list."); + // } + // getNextToken(); + // } else if (token == TokenNameEQUAL) { + // getNextToken(); + // static_scalar(); + // } + // } else { + // throwSyntaxError("$-variable expected in variable-list."); + // } + // } + } + + private void variable_properties() { + // variable_properties: + // variable_properties variable_property + // | /* empty */ + while (token == TokenNameMINUS_GREATER) { + variable_property(); + } + } + + private void variable_property() { + // variable_property: + // T_OBJECT_OPERATOR object_property method_or_not + if (Scanner.TRACE) { + System.out.println("TRACE: variable_property()"); + } + if (token == TokenNameMINUS_GREATER) { + getNextToken(); + object_property(); + method_or_not(); } else { - if (token == TokenNameVariable) { + throwSyntaxError("'->' expected in variable_property."); + } + } + + private void method_or_not() { + // method_or_not: + // '(' function_call_parameter_list ')' + // | /* empty */ + if (Scanner.TRACE) { + System.out.println("TRACE: method_or_not()"); + } + if (token == TokenNameLPAREN) { + getNextToken(); + if (token == TokenNameRPAREN) { getNextToken(); - if (token == TokenNameLBRACKET) { - getNextToken(); - expr(); - if (token != TokenNameRBRACKET) { - throwSyntaxError("']' expected in variable-list."); - } - getNextToken(); - } else if (token == TokenNameEQUAL) { - getNextToken(); - constant(); - } - } else { - throwSyntaxError("$-variable expected in variable-list."); + return; + } + non_empty_function_call_parameter_list(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' expected in method_or_not."); } + getNextToken(); } } + private void exit_expr() { // /* empty */ // | '(' ')' @@ -2680,69 +2951,343 @@ public class Parser //extends PHPParserSuperclass } getNextToken(); } - private void internal_functions_in_yacc() { - 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'"); - } + + private void encaps_list() { + // encaps_list encaps_var + // | encaps_list T_STRING + // | encaps_list T_NUM_STRING + // | encaps_list T_ENCAPSED_AND_WHITESPACE + // | encaps_list T_CHARACTER + // | encaps_list T_BAD_CHARACTER + // | encaps_list '[' + // | encaps_list ']' + // | encaps_list '{' + // | encaps_list '}' + // | encaps_list T_OBJECT_OPERATOR + // | /* empty */ + while (true) { + switch (token) { + case TokenNameSTRING: getNextToken(); break; - case TokenNameempty : - // T_EMPTY '(' variable ')' - getNextToken(); - if (token != TokenNameLPAREN) { - throwSyntaxError("'(' expected after keyword 'empty'"); - } + case TokenNameLBRACE: + // scanner.encapsedStringStack.pop(); getNextToken(); - variable(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after keyword 'empty'"); - } + break; + case TokenNameRBRACE: + // scanner.encapsedStringStack.pop(); getNextToken(); break; - case TokenNameinclude : - //T_INCLUDE expr + case TokenNameLBRACKET: + // scanner.encapsedStringStack.pop(); getNextToken(); - expr(); break; - case TokenNameinclude_once : - // T_INCLUDE_ONCE expr + case TokenNameRBRACKET: + // scanner.encapsedStringStack.pop(); getNextToken(); - expr(); break; - case TokenNameeval : - // T_EVAL '(' expr ')' + case TokenNameMINUS_GREATER: + // scanner.encapsedStringStack.pop(); getNextToken(); - if (token != TokenNameLPAREN) { - throwSyntaxError("'(' expected after keyword 'eval'"); + 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; + } + } + } + + private void encaps_var() { + // T_VARIABLE + // | T_VARIABLE '[' encaps_var_offset ']' + // | T_VARIABLE T_OBJECT_OPERATOR T_STRING + // | T_DOLLAR_OPEN_CURLY_BRACES expr '}' + // | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' + // | T_CURLY_OPEN variable '}' + switch (token) { + case TokenNameVariable: + getNextToken(); + if (token == TokenNameLBRACKET) { getNextToken(); - expr(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after keyword 'eval'"); + expr(); //encaps_var_offset(); + if (token != TokenNameRBRACKET) { + throwSyntaxError("']' expected after variable."); } + // scanner.encapsedStringStack.pop(); getNextToken(); - break; - case TokenNamerequire : - //T_REQUIRE expr + // } + } 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(); + if (token != TokenNameRBRACKET) { + throwSyntaxError("']' expected after '${'."); + } + getNextToken(); + // } + } + } else { expr(); - break; - case TokenNamerequire_once : - // T_REQUIRE_ONCE 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 == TokenNameLBRACKET) { + getNextToken(); + // if (token == TokenNameRBRACKET) { + // getNextToken(); + // } else { + expr(); + if (token != TokenNameRBRACKET) { + throwSyntaxError("']' expected."); + } + getNextToken(); + // } + } else if (token == TokenNameMINUS_GREATER) { + getNextToken(); + if (token != TokenNameIdentifier && token != TokenNameVariable) { + throwSyntaxError("String or Variable token expected."); + } + 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(); + // getNextToken(); + } else { expr(); - break; + 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; + } + } + + private void internal_functions_in_yacc() { + int start = 0; + ImportReference impt = null; + 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(); + + 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 ')' + 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 + 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 ',' @@ -2758,82 +3303,192 @@ public class Parser //extends PHPParserSuperclass } } } - /** - * It will look for a value (after a '=' for example) @ - */ - private void constant() { - // String ident; + + private boolean common_scalar() { + // common_scalar: + // T_LNUMBER + // | T_DNUMBER + // | T_CONSTANT_ENCAPSED_STRING + // | T_LINE + // | T_FILE + // | T_CLASS_C + // | T_METHOD_C + // | T_FUNC_C switch (token) { - case TokenNamePLUS : + 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 + //| T_STRING_VARNAME + //| class_constant + //| common_scalar + //| '"' encaps_list '"' + //| '\'' encaps_list '\'' + //| 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 + // | T_STRING + // | '+' static_scalar + // | '-' static_scalar + // | T_ARRAY '(' static_array_pair_list ')' + // | static_class_constant + if (common_scalar()) { + return; + } + switch (token) { + case TokenNameIdentifier: + getNextToken(); + // static_class_constant: + // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING + if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) { getNextToken(); - switch (token) { - case TokenNameDoubleLiteral : - getNextToken(); - break; - case TokenNameIntegerLiteral : - getNextToken(); - break; - default : - throwSyntaxError("Constant expected after '+' presign."); + if (token == TokenNameIdentifier) { + getNextToken(); + } else { + throwSyntaxError("Identifier expected after '::' operator."); } - break; - case TokenNameMINUS : - getNextToken(); - switch (token) { - case TokenNameDoubleLiteral : - getNextToken(); - break; - case TokenNameIntegerLiteral : - getNextToken(); - break; - default : - throwSyntaxError("Constant expected after '-' presign."); + } + 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 TokenNamenull : - getNextToken(); - break; - case TokenNamefalse : - getNextToken(); - break; - case TokenNametrue : - getNextToken(); - break; - case TokenNameIdentifier : - // ident = identifier; - char[] ident = scanner.getCurrentIdentifierSource(); getNextToken(); - if (token == TokenNameLPAREN) { - getNextToken(); - if (token != TokenNameRPAREN) { - expressionList(); - if (token != TokenNameRPAREN) { - throwSyntaxError("')' expected after identifier '" - + new String(ident) + "' in postfix-expression."); - } + } 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(); + scanner.currentCharacter = scanner.source[scanner.currentPosition++]; } - break; - case TokenNameStringLiteral : getNextToken(); - break; - case TokenNameStringConstant : + } 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(); - break; - case TokenNameStringInterpolated : + } 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 TokenNameDoubleLiteral : + } + non_empty_static_array_pair_list(); + if (token != TokenNameRPAREN) { + throwSyntaxError("')' 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 + // static_scalar + //| non_empty_static_array_pair_list ',' static_scalar + //| static_scalar T_DOUBLE_ARROW static_scalar + //| static_scalar + while (true) { + static_scalar(); + if (token == TokenNameEQUAL_GREATER) { getNextToken(); + static_scalar(); + } + if (token != TokenNameCOMMA) { break; - case TokenNameIntegerLiteral : - getNextToken(); + } + getNextToken(); + if (token == TokenNameRPAREN) { break; - default : - throwSyntaxError("Constant expected."); + } } } + public void reportSyntaxError() { //int act, int currentKind, int // stateStackTop) { /* remember current scanner position */ @@ -2923,7 +3578,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, @@ -2938,38 +3593,57 @@ 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; + //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) { - compilationUnit.compilationResult.lineSeparatorPositions = scanner - .getLineEnds(); + compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); } problemReporter.referenceContext = referenceContext; return problemReporter; } + /* * Reconsider the entire source looking for inconsistencies in {} () [] */ @@ -2978,14 +3652,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 @@ -3005,8 +3678,7 @@ public class Parser //extends PHPParserSuperclass // (source[scanner.currentPosition] == 'u')) { // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace(); // } else { - if (scanner.recordLineSeparator - && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) { + 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 @@ -3015,350 +3687,282 @@ public class Parser //extends PHPParserSuperclass } isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter); // } - } while (isWhiteSpace - && (scanner.currentPosition < scanner.eofPosition)); + } 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); + } + leftPositions[CurlyBracket][index] = scanner.startPosition; + leftDepths[CurlyBracket][index] = depths[CurlyBracket]++; + } + break; + case '}': { + int index = rightCount[CurlyBracket]++; + if (index == rightPositions[CurlyBracket].length) { + System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index); + System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index); + } + rightPositions[CurlyBracket][index] = scanner.startPosition; + rightDepths[CurlyBracket][index] = --depths[CurlyBracket]; + } + break; + case '(': { + int index = leftCount[RoundBracket]++; + if (index == leftPositions[RoundBracket].length) { + System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index); + System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index); + } + leftPositions[RoundBracket][index] = scanner.startPosition; + leftDepths[RoundBracket][index] = depths[RoundBracket]++; + } + break; + case ')': { + int index = rightCount[RoundBracket]++; + if (index == rightPositions[RoundBracket].length) { + System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index); + System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index); + } + rightPositions[RoundBracket][index] = scanner.startPosition; + rightDepths[RoundBracket][index] = --depths[RoundBracket]; + } + break; + case '[': { + int index = leftCount[SquareBracket]++; + if (index == leftPositions[SquareBracket].length) { + System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index); + System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index); + } + leftPositions[SquareBracket][index] = scanner.startPosition; + leftDepths[SquareBracket][index] = depths[SquareBracket]++; + } + break; + case ']': { + int index = rightCount[SquareBracket]++; + if (index == rightPositions[SquareBracket].length) { + System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index); + System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index); + } + rightPositions[SquareBracket][index] = scanner.startPosition; + rightDepths[SquareBracket][index] = --depths[SquareBracket]; + } + break; + case '\'': { + if (scanner.getNextChar('\\')) { + scanner.scanEscapeCharacter(); + } else { // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = + // source[scanner.currentPosition++]) == + // '\\') && + // (source[scanner.currentPosition] == + // 'u')) { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; } - 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]; + // } + } + 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 } - 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]++; + if (scanner.currentCharacter == '\n') { + break; // the string cannot go further that + // the line } - 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]; + if (scanner.currentCharacter == '\\') { + scanner.scanEscapeCharacter(); } - 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); + // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = + // source[scanner.currentPosition++]) == '\\') + // && (source[scanner.currentPosition] == 'u')) + // { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; + } + // } + } + break; + case '/': { + int test; + if ((test = scanner.getNextChar('/', '*')) == 0) { //line + // comment + //get the next char + if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') + && (source[scanner.currentPosition] == 'u')) { + //-------------unicode traitement + // ------------ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + scanner.currentPosition++; + while (source[scanner.currentPosition] == 'u') { + scanner.currentPosition++; + } + if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0 + || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0 + || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0 + || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error + // don't + // care of the + // value + scanner.currentCharacter = 'A'; + } //something different from \n and \r + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); } - 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); + 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); + } } - 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; + 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()); } - // } } - scanner.getNextChar('\''); - break; } - case '"' : + 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.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(); + // } + 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++; } - // 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 * and / + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); } - // } } - 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; + //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++; - while (source[scanner.currentPosition] == 'u') { - scanner.currentPosition++; - } - if ((c1 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c1 < 0 - || (c2 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c2 < 0 - || (c3 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c3 < 0 - || (c4 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c4 < 0) { //error don't - // care of the - // value - scanner.currentCharacter = 'A'; - } //something different from \n and \r - else { - scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); - } - } - while (scanner.currentCharacter != '\r' - && scanner.currentCharacter != '\n') { - //get the next char - scanner.startPosition = scanner.currentPosition; - if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') - && (source[scanner.currentPosition] == 'u')) { - //-------------unicode traitement - // ------------ - int c1 = 0, c2 = 0, c3 = 0, c4 = 0; - scanner.currentPosition++; - while (source[scanner.currentPosition] == 'u') { - scanner.currentPosition++; - } - if ((c1 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c1 < 0 - || (c2 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c2 < 0 - || (c3 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c3 < 0 - || (c4 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c4 < 0) { //error don't - // care of the - // value - scanner.currentCharacter = 'A'; - } //something different from \n - // and \r - else { - scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); - } - } } - if (scanner.recordLineSeparator - && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) { - if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) { - // only record line positions we - // have not recorded yet - scanner.pushLineSeparator(); - if (this.scanner.taskTags != null) { - this.scanner.checkTaskTag(this.scanner - .getCurrentTokenStartPosition(), this.scanner - .getCurrentTokenEndPosition()); - } - } + 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); } - break; } - if (test > 0) { //traditional and annotation - // comment - boolean star = false; - // consume next character - scanner.unicodeAsBackSlash = false; - // if (((scanner.currentCharacter = - // source[scanner.currentPosition++]) == - // '\\') && - // (source[scanner.currentPosition] == - // 'u')) { - // scanner.getNextUnicodeChar(); - // } else { - if (scanner.withoutUnicodePtr != 0) { - scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; - } - // } - if (scanner.currentCharacter == '*') { - star = true; - } - //get the next char - if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') - && (source[scanner.currentPosition] == 'u')) { - //-------------unicode traitement - // ------------ - int c1 = 0, c2 = 0, c3 = 0, c4 = 0; - scanner.currentPosition++; - while (source[scanner.currentPosition] == 'u') { - scanner.currentPosition++; - } - if ((c1 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c1 < 0 - || (c2 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c2 < 0 - || (c3 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c3 < 0 - || (c4 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c4 < 0) { //error don't - // care of the - // value - scanner.currentCharacter = 'A'; - } //something different from * and / - else { - scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); - } - } - //loop until end of comment */ - while ((scanner.currentCharacter != '/') || (!star)) { - star = scanner.currentCharacter == '*'; - //get next char - if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') - && (source[scanner.currentPosition] == 'u')) { - //-------------unicode traitement - // ------------ - int c1 = 0, c2 = 0, c3 = 0, c4 = 0; - scanner.currentPosition++; - while (source[scanner.currentPosition] == 'u') { - scanner.currentPosition++; - } - if ((c1 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c1 < 0 - || (c2 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c2 < 0 - || (c3 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c3 < 0 - || (c4 = Character - .getNumericValue(source[scanner.currentPosition++])) > 15 - || c4 < 0) { //error don't - // care of the - // value - scanner.currentCharacter = 'A'; - } //something different from * and - // / - else { - scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); - } - } - } - if (this.scanner.taskTags != null) { - this.scanner.checkTaskTag(this.scanner - .getCurrentTokenStartPosition(), this.scanner - .getCurrentTokenEndPosition()); - } - break; - } - break; - } - default : - if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) { - scanner.scanIdentifierOrKeyword(false); - break; } - if (Character.isDigit(scanner.currentCharacter)) { - scanner.scanNumber(false); - break; + if (this.scanner.taskTags != null) { + this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); } + break; + } + break; + } + default: + if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) { + scanner.scanIdentifierOrKeyword(false); + break; + } + if (Character.isDigit(scanner.currentCharacter)) { + scanner.scanNumber(false); + break; + } } //-----------------end switch while // try-------------------- @@ -3390,8 +3994,7 @@ public class Parser //extends PHPParserSuperclass } } if (end < 0) { // did not find a good closing match - problemReporter.unmatchedBracket(start, referenceContext, - compilationUnit.compilationResult); + problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); return true; } // check if even number of opening/closing other brackets @@ -3409,8 +4012,7 @@ public class Parser //extends PHPParserSuperclass balance--; } if (balance != 0) { - problemReporter.unmatchedBracket(start, referenceContext, - compilationUnit.compilationResult); //bracket + problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket // anomaly return true; } @@ -3419,14 +4021,13 @@ public class Parser //extends PHPParserSuperclass // too many opening brackets ? for (int i = rightCount[kind]; i < leftCount[kind]; i++) { anomaliesDetected = true; - problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - - i - 1], referenceContext, compilationUnit.compilationResult); + problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, + compilationUnit.compilationResult); } // too many closing brackets ? for (int i = leftCount[kind]; i < rightCount[kind]; i++) { anomaliesDetected = true; - problemReporter.unmatchedBracket(rightPositions[kind][i], - referenceContext, compilationUnit.compilationResult); + problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult); } if (anomaliesDetected) return true; @@ -3438,6 +4039,7 @@ public class Parser //extends PHPParserSuperclass return anomaliesDetected; } } + protected void pushOnAstLengthStack(int pos) { try { astLengthStack[++astLengthPtr] = pos; @@ -3449,7 +4051,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 */ @@ -3457,8 +4060,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; @@ -3473,4 +4076,11 @@ public class Parser //extends PHPParserSuperclass astLengthStack[astLengthPtr] = 1; } } + + protected void resetModifiers() { + this.modifiers = AccDefault; + this.modifiersSourceStart = -1; // <-- see comment into + // modifiersFlag(int) + this.scanner.commentPtr = -1; + } } \ No newline at end of file