/********************************************************************** 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 **********************************************************************/ 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.ReferenceContext; import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants; import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter; import net.sourceforge.phpeclipse.PHPeclipsePlugin; import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration; import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode; import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration; import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration; import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference; import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration; import net.sourceforge.phpeclipse.phpeditor.PHPString; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.preference.IPreferenceStore; import test.PHPParserSuperclass; public class Parser extends PHPParserSuperclass implements ITerminalSymbols, ParserBasicInformation { //internal data for the automat protected final static int StackIncrement = 255; protected int stateStackTop; protected int[] stack = new int[StackIncrement]; public int firstToken; // handle for multiple parsing goals public int lastAct; //handle for multiple parsing goals protected RecoveredElement currentElement; public static boolean VERBOSE_RECOVERY = false; protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies //scanner token public Scanner scanner; private 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: //int columnCount; //int chIndx; // // // current identifier // String identifier; Long longNumber; Double doubleNumber; private String stringValue; /** Contains the current expression. */ // private StringBuffer expression; private boolean phpMode; // final static int TokenNameEOF = 0; // final static int TokenNameERROR = 1; // final static int TokenNameHTML = 2; // // final static int TokenNameREMAINDER = 30; // final static int TokenNameNOT = 31; // final static int TokenNameDOT = 32; // final static int TokenNameXOR = 33; // final static int TokenNameDIVIDE = 34; // final static int TokenNameMULTIPLY = 35; // final static int TokenNameMINUS = 36; // final static int TokenNamePLUS = 37; // final static int TokenNameEQUAL_EQUAL = 38; // final static int TokenNameNOT_EQUAL = 39; // final static int TokenNameGREATER = 40; // final static int TokenNameGREATER_EQUAL = 41; // final static int TokenNameLESS = 42; // final static int TokenNameLESS_EQUAL = 43; // final static int TokenNameAND_AND = 44; // final static int TokenNameOR_OR = 45; // // final static int TokenNameHASH = 46; // final static int TokenNameCOLON = 47; // final static int TokenNameDOT_EQUAL = 48; // // final static int TokenNameEQUAL = 49; // final static int TokenNameMINUS_GREATER = 50; // -> // final static int TokenNameFOREACH = 51; // final static int TokenNameAND = 52; // //final static int TokenNameDOLLARLISTOPEN = 53; // final static int TokenNameTWIDDLE = 54; // final static int TokenNameTWIDDLE_EQUAL = 55; // final static int TokenNameREMAINDER_EQUAL = 56; // final static int TokenNameXOR_EQUAL = 57; // final static int TokenNameRIGHT_SHIFT_EQUAL = 58; // final static int TokenNameLEFT_SHIFT_EQUAL = 59; // final static int TokenNameAND_EQUAL = 60; // final static int TokenNameOR_EQUAL = 61; // final static int TokenNameQUESTION = 62; // final static int TokenNameCOLON_COLON = 63; // final static int TokenNameAT = 63; // // final static int TokenNameHEREDOC = 64; // // final static int TokenNameDOLLAROPEN = 127; // final static int TokenNameLPAREN = 128; // final static int TokenNameRPAREN = 129; // final static int TokenNameLBRACE = 130; // final static int TokenNameRBRACE = 131; // final static int TokenNameLBRACKET = 132; // final static int TokenNameRBRACKET = 133; // final static int TokenNameCOMMA = 134; // // final static int TokenNameStringLiteral = 136; // final static int TokenNameIdentifier = 138; // // final static int TokenNameDIGIT = 139; // final static int TokenNameSEMICOLON = 140; // // final static int TokenNameSLOT = 141; // // final static int TokenNameSLOTSEQUENCE = 142; // final static int TokenNameMINUS_MINUS = 144; // final static int TokenNamePLUS_PLUS = 145; // final static int TokenNamePLUS_EQUAL = 146; // final static int TokenNameDIVIDE_EQUAL = 147; // final static int TokenNameMINUS_EQUAL = 148; // final static int TokenNameMULTIPLY_EQUAL = 149; // final static int TokenNameVariable = 150; // final static int TokenNameIntegerLiteral = 151; // final static int TokenNameDoubleLiteral = 152; // final static int TokenNameStringInterpolated = 153; // final static int TokenNameStringConstant = 154; // // final static int TokenNameLEFT_SHIFT = 155; // final static int TokenNameRIGHT_SHIFT = 156; // final static int TokenNameEQUAL_EQUAL_EQUAL = 157; // final static int TokenNameNOT_EQUAL_EQUAL = 158; // final static int TokenNameOR = 159; // final static int TokenNameAT = 153; // @ protected Parser() { this.currentPHPString = 0; // PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; this.str = ""; this.token = TokenNameEOF; // this.chIndx = 0; // this.rowCount = 1; // this.columnCount = 0; this.phpEnd = false; // getNextToken(); this.initializeScanner(); } public void setFileToParse(IFile fileToParse) { this.currentPHPString = 0; PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; this.str = ""; this.token = TokenNameEOF; this.phpEnd = false; this.initializeScanner(); } /** * ClassDeclaration Constructor. * *@param s *@param sess Description of Parameter *@see */ public Parser(IFile fileToParse) { // if (keywordMap == null) { // keywordMap = new HashMap(); // for (int i = 0; i < PHP_KEYWORS.length; i++) { // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i])); // } // } this.currentPHPString = 0; PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; this.str = ""; this.token = TokenNameEOF; // this.chIndx = 0; // this.rowCount = 1; // this.columnCount = 0; this.phpEnd = false; // getNextToken(); this.initializeScanner(); } public void initializeScanner() { this.scanner = new Scanner(false, false, false, false); } /** * Create marker for the parse error */ private void setMarker(String message, int charStart, int charEnd, int errorLevel) throws CoreException { setMarker(fileToParse, message, charStart, charEnd, errorLevel); } /** * This method will throw the SyntaxError. * It will add the good lines and columns to the Error * @param error the error message * @throws SyntaxError the error raised */ private void throwSyntaxError(String error) { // if (str.length() < chIndx) { // chIndx--; // } // // read until end-of-line // int eol = chIndx; // while (str.length() > eol) { // ch = str.charAt(eol++); // if (ch == '\n') { // eol--; // break; // } // } // throw new SyntaxError( // rowCount, // chIndx - columnCount + 1, // str.substring(columnCount, eol), // error); throw new SyntaxError(1, 1, "", error); } /** * This method will throw the SyntaxError. * It will add the good lines and columns to the Error * @param error the error message * @throws SyntaxError the error raised */ private void throwSyntaxError(String error, int startRow) { throw new SyntaxError(startRow, 0, " ", error); } private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) { problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, compilationUnit.compilationResult); throw new SyntaxError(1, 0, " ", error); } /** * Method Declaration. * *@see */ // private void getChar() { // if (str.length() > chIndx) { // ch = str.charAt(chIndx++); // // return; // } // // chIndx = str.length() + 1; // ch = ' '; // // token = TokenNameEOF; // phpEnd = true; // } /** * gets the next token from input */ private void getNextToken() throws CoreException { try { token = scanner.getNextToken(); if (Scanner.DEBUG) { int currentEndPosition = scanner.getCurrentTokenEndPosition(); int currentStartPosition = scanner.getCurrentTokenStartPosition(); 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) { current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); } else { switch (token) { case TokenNameVariable : case TokenNamethis : current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); break; case TokenNameIdentifier : current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); break; case TokenNameDoubleLiteral : current.add(new PHPVarDeclaration(current, variableName + doubleNumber, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); break; case TokenNameIntegerLiteral : current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); break; case TokenNameStringInterpolated : case TokenNameStringLiteral : current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); break; case TokenNameStringConstant : current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length, scanner.getCurrentTokenStartPosition(), new String(ident))); break; default : current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length scanner.getCurrentTokenStartPosition())); break; } } } else { ident = scanner.getCurrentIdentifierSource(); current.add(new PHPVarDeclaration(current, variableName, // chIndx - ident.length scanner.getCurrentTokenStartPosition())); } } } else if (token == TokenNamefunction) { getNextToken(); if (token == TokenNameAND) { getNextToken(); } if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) { ident = scanner.getCurrentIdentifierSource(); outlineInfo.addVariable(new String(ident)); temp = new PHPFunctionDeclaration(current, new String(ident), // chIndx - ident.length scanner.getCurrentTokenStartPosition()); current.add(temp); getNextToken(); parseDeclarations(outlineInfo, temp, true); } } else if (token == TokenNameclass) { getNextToken(); if (token == TokenNameIdentifier && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) { ident = scanner.getCurrentIdentifierSource(); outlineInfo.addVariable(new String(ident)); temp = new PHPClassDeclaration(current, new String(ident), // chIndx - ident.len scanner.getCurrentTokenStartPosition()); current.add(temp); // stack.push(temp); getNextToken(); //skip tokens for classname, extends and others until we have the opening '{' while (token != TokenNameLBRACE && token != TokenNameEOF && token != TokenNameERROR) { getNextToken(); } parseDeclarations(outlineInfo, temp, true); // stack.pop(); } } else if ((token == TokenNameLBRACE) || (token == TokenNameDOLLAR_LBRACE)) { getNextToken(); counter++; } else if (token == TokenNameRBRACE) { getNextToken(); --counter; if (counter == 0 && goBack) { return; } } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) { ident = scanner.getCurrentTokenSource(); getNextToken(); int startPosition = scanner.getCurrentTokenStartPosition(); expression(); char[] expr = scanner.getCurrentTokenSource(startPosition); outlineInfo.addVariable(new String(ident)); current.add(new PHPReqIncDeclaration(current, new String(ident), // chIndx - ident.length, startPosition, new String(expr))); getNextToken(); } else { getNextToken(); } } } catch (CoreException e) { } catch (SyntaxError sytaxErr) { try { // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR); setMarker(sytaxErr.getMessage(), scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), ERROR); } catch (CoreException e) { } } } private void statementList() throws CoreException { do { statement(TokenNameEOF); if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse) || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor) || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch) || (token == TokenNameEOF) || (token == TokenNameERROR)) { return; } } while (true); } private void functionBody(MethodDeclaration methodDecl) throws CoreException { // '{' [statement-list] '}' if (token == TokenNameLBRACE) { getNextToken(); } else { throwSyntaxError("'{' expected in compound-statement."); } if (token != TokenNameRBRACE) { statementList(); } if (token == TokenNameRBRACE) { methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); getNextToken(); } else { throwSyntaxError("'}' expected in compound-statement."); } } private void statement(int previousToken) throws CoreException { // if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) { // char[] ident = scanner.getCurrentIdentifierSource(); // String keyword = new String(ident); if (token == TokenNameinclude || token == TokenNameinclude_once) { getNextToken(); if (token == TokenNameLPAREN) { expression(); 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) { expression(); 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) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'if' keyword."); } expression(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'if' condition."); } ifStatement(); return; } else if (token == TokenNameswitch) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'switch' keyword."); } expression(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'switch' condition."); } switchStatement(); return; } else if (token == TokenNamefor) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'for' keyword."); } if (token == TokenNameSEMICOLON) { getNextToken(); } else { expressionList(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { throwSyntaxError("';' expected after 'for'."); } } if (token == TokenNameSEMICOLON) { getNextToken(); } else { expressionList(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { throwSyntaxError("';' expected after 'for'."); } } if (token == TokenNameRPAREN) { getNextToken(); } else { expressionList(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'for'."); } } forStatement(); return; } else if (token == TokenNamewhile) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'while' keyword."); } expression(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'while' condition."); } whileStatement(); return; } else if (token == TokenNamedo) { getNextToken(); if (token == TokenNameLBRACE) { getNextToken(); } else { throwSyntaxError("'{' expected after 'do' keyword."); } if (token != TokenNameRBRACE) { statementList(); } if (token == TokenNameRBRACE) { getNextToken(); } else { throwSyntaxError("'}' expected after 'do' keyword."); } if (token == TokenNamewhile) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'while' keyword."); } expression(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'while' condition."); } } else { throwSyntaxError("'while' expected after 'do' keyword."); } if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameStopPHP) { throwSyntaxError("';' expected after do-while statement."); } getNextToken(); } return; } else if (token == TokenNameforeach) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'foreach' keyword."); } expression(); if (token == TokenNameas) { getNextToken(); } else { throwSyntaxError("'as' expected after 'foreach' exxpression."); } variable(); if (token == TokenNameEQUAL_GREATER) { getNextToken(); variable(); } if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'foreach' expression."); } foreachStatement(); return; } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) { getNextToken(); if (token != TokenNameSEMICOLON) { expression(); } if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameStopPHP) { throwSyntaxError("';' expected after 'continue', 'break' or 'return'."); } getNextToken(); } return; } else if (token == TokenNameecho) { getNextToken(); expressionList(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameStopPHP) { throwSyntaxError("';' expected after 'echo' statement."); } getNextToken(); } return; // } else if (token == TokenNameprint) { // getNextToken(); // expression(); // if (token == TokenNameSEMICOLON) { // getNextToken(); // } else { // if (token != TokenNameStopPHP) { // throwSyntaxError("';' expected after 'print' statement."); // } // getNextToken(); // } // return; } else if (token == TokenNameglobal || token == TokenNamestatic) { getNextToken(); variableList(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameStopPHP) { throwSyntaxError("';' expected after 'global' or 'static' statement."); } getNextToken(); } return; // } else if (token == TokenNameunset) { // getNextToken(); // if (token == TokenNameARGOPEN) { // getNextToken(); // } else { // throwSyntaxError("'(' expected after 'unset' keyword."); // } // variableList(); // if (token == TokenNameARGCLOSE) { // getNextToken(); // } else { // throwSyntaxError("')' expected after 'unset' statement."); // } // if (token == TokenNameSEMICOLON) { // getNextToken(); // } else { // if (token != TokenNameStopPHP) { // 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) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'define' keyword."); } expression(); if (token == TokenNameCOMMA) { getNextToken(); } else { throwSyntaxError("',' expected after first 'define' constant."); } expression(); if (token == TokenNameCOMMA) { getNextToken(); expression(); } if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'define' statement."); } if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameStopPHP) { throwSyntaxError("';' expected after 'define' statement."); } getNextToken(); } return; } else if (token == TokenNamefunction) { MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); getNextToken(); functionDefinition(methodDecl); return; } else if (token == TokenNameclass) { TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult); typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); // default super class typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0); compilationUnit.types.add(typeDecl); try { pushOnAstStack(typeDecl); getNextToken(); classDeclarator(typeDecl); classBody(typeDecl); } finally { astPtr--; astLengthPtr--; } return; // } else { // throwSyntaxError("Unexpected keyword '" + keyword + "'"); } else if (token == TokenNameLBRACE) { getNextToken(); if (token != TokenNameRBRACE) { statementList(); } if (token == TokenNameRBRACE) { getNextToken(); return; } else { throwSyntaxError("'}' expected."); } } else { if (token != TokenNameSEMICOLON) { expression(); } if (token == TokenNameSEMICOLON) { getNextToken(); return; } else { if (token != TokenNameStopPHP && token != TokenNameEOF) { throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")"); } getNextToken(); } } } private void classDeclarator(TypeDeclaration typeDecl) throws CoreException { //identifier //identifier 'extends' identifier if (token == TokenNameIdentifier) { typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); typeDecl.name = scanner.getCurrentIdentifierSource(); getNextToken(); if (token == TokenNameextends) { do { getNextToken(); if (token == TokenNameIdentifier) { getNextToken(); } else { reportSyntaxError("Class name expected after keyword 'extends'.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition()); // throwSyntaxError("ClassDeclaration name expected after keyword 'extends'."); } } while (token == TokenNameCOMMA); } } else { typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); if (token > TokenNameKEYWORD) { typeDecl.name = scanner.getCurrentIdentifierSource(); reportSyntaxError( "Don't use keyword for class declaration [" + scanner.toStringAction(token) + "].", typeDecl.sourceStart, typeDecl.sourceEnd); // throwSyntaxError("Don't use keyword for class declaration [" + token + "]."); } typeDecl.name = new char[] { ' ' }; reportSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd); // throwSyntaxError("ClassDeclaration name expected after keyword 'class'."); } } private void classBody(TypeDeclaration typeDecl) throws CoreException { //'{' [class-element-list] '}' if (token == TokenNameLBRACE) { getNextToken(); if (token != TokenNameRBRACE) { classElementList(); } if (token == TokenNameRBRACE) { typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); getNextToken(); } else { throwSyntaxError("'}' expected at end of class body."); } } else { throwSyntaxError("'{' expected at start of class body."); } } private void classElementList() throws CoreException { do { classElement(); } while (token == TokenNamefunction || token == TokenNamevar); } private void classElement() throws CoreException { //class-property //function-definition 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 classProperty() throws CoreException { //'var' variable ';' //'var' variable '=' constant ';' do { if (token == TokenNameVariable) { getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); constant(); } } else { if (token == TokenNamethis) { throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'."); } throwSyntaxError("Variable expected after keyword 'var'."); } if (token != TokenNameCOMMA) { break; } getNextToken(); } while (true); if (token == TokenNameSEMICOLON) { getNextToken(); } else { throwSyntaxError("';' expected after variable declaration."); } } private void functionDefinition(MethodDeclaration methodDecl) throws CoreException { if (astPtr == 0) { compilationUnit.types.add(methodDecl); } else { AstNode node = astStack[astPtr]; if (node instanceof TypeDeclaration) { TypeDeclaration typeDecl = ((TypeDeclaration) node); if (typeDecl.methods == null) { typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl }; } else { AbstractMethodDeclaration[] newMethods; System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, typeDecl.methods.length); newMethods[0] = methodDecl; typeDecl.methods = newMethods; } } } functionDeclarator(methodDecl); functionBody(methodDecl); } private void functionDeclarator(MethodDeclaration methodDecl) throws CoreException { //identifier '(' [parameter-list] ')' if (token == TokenNameAND) { getNextToken(); } if (token == TokenNameIdentifier) { methodDecl.sourceStart = scanner.getCurrentTokenStartPosition(); methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); methodDecl.selector = scanner.getCurrentIdentifierSource(); getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected in function declaration."); } if (token != TokenNameRPAREN) { parameterList(); } if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in function declaration."); } else { methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1; getNextToken(); } } else { if (token > TokenNameKEYWORD) { throwSyntaxError("Don't use keyword for function declaration [" + token + "]."); } throwSyntaxError("Function name expected after keyword 'function'."); } } // private void parameterList() throws CoreException { //parameter-declaration //parameter-list ',' parameter-declaration do { parameterDeclaration(); if (token != TokenNameCOMMA) { break; } getNextToken(); } while (true); } private void parameterDeclaration() throws CoreException { //variable //variable-reference if (token == TokenNameAND) { getNextToken(); if (isVariable()) { getNextToken(); } else { throwSyntaxError("Variable expected after reference operator '&'."); } } //variable '=' constant if (token == TokenNameVariable) { getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); constant(); } return; } if (token == TokenNamethis) { throwSyntaxError("Reserved word '$this' not allowed in parameter declaration."); } } private void labeledStatementList() throws CoreException { if (token != TokenNamecase && token != TokenNamedefault) { throwSyntaxError("'case' or 'default' expected."); } do { if (token == TokenNamecase) { getNextToken(); expression(); //constant(); if (token == TokenNameCOLON) { getNextToken(); if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ? continue; } statementList(); } else if (token == TokenNameSEMICOLON) { // setMarker( // "':' expected after 'case' keyword (Found token: " // + scanner.toStringAction(token) // + ")", // rowCount, // PHPParser.INFO); setMarker( "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), INFO); getNextToken(); if (token == TokenNamecase) { // empty case statement ? continue; } statementList(); } else { throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")"); } } else { // TokenNamedefault getNextToken(); if (token == TokenNameCOLON) { getNextToken(); statementList(); } else { throwSyntaxError("':' character after 'default' expected."); } } } while (token == TokenNamecase || token == TokenNamedefault); } // public void labeledStatement() { // if (token == TokenNamecase) { // getNextToken(); // constant(); // if (token == TokenNameDDOT) { // getNextToken(); // statement(); // } else { // throwSyntaxError("':' character after 'case' constant expected."); // } // return; // } else if (token == TokenNamedefault) { // getNextToken(); // if (token == TokenNameDDOT) { // getNextToken(); // statement(); // } else { // throwSyntaxError("':' character after 'default' expected."); // } // return; // } // } // public void expressionStatement() { // } // private void inclusionStatement() { // } // public void compoundStatement() { // } // public void selectionStatement() { // } // // public void iterationStatement() { // } // // public void jumpStatement() { // } // // public void outputStatement() { // } // // public void scopeStatement() { // } // // public void flowStatement() { // } // // public void definitionStatement() { // } private void ifStatement() throws CoreException { // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';' if (token == TokenNameCOLON) { getNextToken(); if (token != TokenNameendif) { statementList(); switch (token) { case TokenNameelse : getNextToken(); if (token == TokenNameCOLON) { getNextToken(); if (token != TokenNameendif) { statementList(); } } else { if (token == TokenNameif) { //'else if' getNextToken(); elseifStatementList(); } else { throwSyntaxError("':' expected after 'else'."); } } break; case TokenNameelseif : getNextToken(); elseifStatementList(); break; } } if (token != TokenNameendif) { throwSyntaxError("'endif' expected."); } getNextToken(); if (token != TokenNameSEMICOLON) { throwSyntaxError("';' expected after if-statement."); } getNextToken(); } else { // statement [else-statement] statement(TokenNameEOF); if (token == TokenNameelseif) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'elseif' keyword."); } expression(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'elseif' condition."); } ifStatement(); } else if (token == TokenNameelse) { getNextToken(); statement(TokenNameEOF); } } } private void elseifStatementList() throws CoreException { do { elseifStatement(); switch (token) { case TokenNameelse : getNextToken(); if (token == TokenNameCOLON) { getNextToken(); if (token != TokenNameendif) { statementList(); } return; } else { if (token == TokenNameif) { //'else if' getNextToken(); } else { throwSyntaxError("':' expected after 'else'."); } } break; case TokenNameelseif : getNextToken(); break; default : return; } } while (true); } private void elseifStatement() throws CoreException { if (token == TokenNameLPAREN) { getNextToken(); expression(); if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in else-if-statement."); } getNextToken(); if (token != TokenNameCOLON) { throwSyntaxError("':' expected in else-if-statement."); } getNextToken(); if (token != TokenNameendif) { statementList(); } } } private void switchStatement() throws CoreException { if (token == TokenNameCOLON) { // ':' [labeled-statement-list] 'endswitch' ';' getNextToken(); labeledStatementList(); if (token != TokenNameendswitch) { throwSyntaxError("'endswitch' expected."); } getNextToken(); if (token != TokenNameSEMICOLON) { throwSyntaxError("';' expected after switch-statement."); } getNextToken(); } else { // '{' [labeled-statement-list] '}' if (token != TokenNameLBRACE) { throwSyntaxError("'{' expected in switch statement."); } getNextToken(); if (token != TokenNameRBRACE) { labeledStatementList(); } if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected in switch statement."); } getNextToken(); } } private void forStatement() throws CoreException { if (token == TokenNameCOLON) { getNextToken(); statementList(); if (token != TokenNameendfor) { throwSyntaxError("'endfor' expected."); } getNextToken(); if (token != TokenNameSEMICOLON) { throwSyntaxError("';' expected after for-statement."); } getNextToken(); } else { statement(TokenNameEOF); } } private void whileStatement() throws CoreException { // ':' statement-list 'endwhile' ';' if (token == TokenNameCOLON) { getNextToken(); statementList(); if (token != TokenNameendwhile) { throwSyntaxError("'endwhile' expected."); } getNextToken(); if (token != TokenNameSEMICOLON) { throwSyntaxError("';' expected after while-statement."); } getNextToken(); } else { statement(TokenNameEOF); } } private void foreachStatement() throws CoreException { if (token == TokenNameCOLON) { getNextToken(); statementList(); if (token != TokenNameendforeach) { throwSyntaxError("'endforeach' expected."); } getNextToken(); if (token != TokenNameSEMICOLON) { throwSyntaxError("';' expected after foreach-statement."); } getNextToken(); } else { statement(TokenNameEOF); } } private void exitStatus() throws CoreException { if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected in 'exit-status'."); } if (token != TokenNameRPAREN) { expression(); } if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'exit-status'."); } } private void expressionList() throws CoreException { do { expression(); if (token == TokenNameCOMMA) { getNextToken(); } else { break; } } while (true); } private void expression() throws CoreException { //todo: find a better way to get the expression // expression = new StringBuffer(); // for (int i = chIndx; i < str.length(); i++) { // if (str.charAt(i) == ';') { // break; // } // expression.append(str.charAt(i)); // } // if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) { // getNextToken(); // } else { logicalinclusiveorExpression(); // while (token != TokenNameSEMICOLON) { // getNextToken(); // // } // } } private void postfixExpression() throws CoreException { // String ident; char[] ident; boolean castFlag = false; boolean arrayFlag = false; switch (token) { case TokenNamenew : getNextToken(); expression(); 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 : 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; } } } if (castFlag) { getNextToken(); if (arrayFlag && token == TokenNameLPAREN) { getNextToken(); if (token == TokenNameRPAREN) { getNextToken(); } else { expression(); if (token != TokenNameRPAREN) { throwSyntaxError(") expected after 'array('."); } } } if (token != TokenNameRPAREN) { throwSyntaxError(") expected after cast-type '" + str + "'."); } getNextToken(); expression(); break; } else { expression(); } if (token != TokenNameRPAREN) { throwSyntaxError(") expected in postfix-expression."); } getNextToken(); break; case TokenNameDoubleLiteral : getNextToken(); break; case TokenNameIntegerLiteral : getNextToken(); break; case TokenNameDOLLAR_LBRACE : getNextToken(); expression(); if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected after indirect variable token '${'."); } getNextToken(); break; case TokenNameVariable : case TokenNamethis : ident = scanner.getCurrentIdentifierSource(); getNextToken(); if (token == TokenNameLBRACE) { getNextToken(); expression(); if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression."); } 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(); getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); if (token != TokenNameRPAREN) { expressionList(); if (token != TokenNameRPAREN) { throwSyntaxError( "')' expected after identifier '" + new String(ident) + "' in postfix-expression." + "(Found token: " + scanner.toStringAction(token) + ")"); } } getNextToken(); } break; case TokenNameprint : getNextToken(); expression(); // if (token == TokenNameSEMICOLON) { // getNextToken(); // } else { // if (token != TokenNameStopPHP) { // throwSyntaxError("';' expected after 'print' statement."); // } // getNextToken(); // } break; case TokenNamelist : getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); if (token == TokenNameCOMMA) { getNextToken(); } expressionList(); if (token != TokenNameRPAREN) { throwSyntaxError("')' expected after 'list' keyword."); } getNextToken(); // if (token == TokenNameSET) { // getNextToken(); // logicalinclusiveorExpression(); // } } else { throwSyntaxError("'(' expected after 'list' keyword."); } 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; } boolean while_flag = true; do { switch (token) { case TokenNameLBRACKET : getNextToken(); expression(); 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(); expression(); 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(); expression(); 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() throws CoreException { switch (token) { case TokenNamePLUS_PLUS : getNextToken(); unaryExpression(); break; case TokenNameMINUS_MINUS : getNextToken(); unaryExpression(); break; // '@' '&' '*' '+' '-' '~' '!' case TokenNameAT : getNextToken(); if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) { statement(TokenNameAT); } else { postfixExpression(); // castExpression(); } 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 : postfixExpression(); } } private void castExpression() throws CoreException { // if (token == TokenNameARGOPEN) { // getNextToken(); // typeName(); // if (token != TokenNameARGCLOSE) { // throwSyntaxError(") expected after cast-expression."); // } // getNextToken(); // } unaryExpression(); } private void assignExpression() throws CoreException { 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) { // ~= getNextToken(); logicalinclusiveorExpression(); } } private void multiplicativeExpression() throws CoreException { do { assignExpression(); if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) { return; } getNextToken(); } while (true); } private void concatenationExpression() throws CoreException { do { multiplicativeExpression(); if (token != TokenNameDOT) { return; } getNextToken(); } while (true); } private void additiveExpression() throws CoreException { do { concatenationExpression(); if (token != TokenNamePLUS && token != TokenNameMINUS) { return; } getNextToken(); } while (true); } private void shiftExpression() throws CoreException { do { additiveExpression(); if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) { return; } getNextToken(); } while (true); } private void relationalExpression() throws CoreException { do { shiftExpression(); if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) { return; } getNextToken(); } while (true); } private void identicalExpression() throws CoreException { do { relationalExpression(); if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) { return; } getNextToken(); } while (true); } private void equalityExpression() throws CoreException { do { identicalExpression(); if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) { return; } getNextToken(); } while (true); } private void ternaryExpression() throws CoreException { equalityExpression(); if (token == TokenNameQUESTION) { getNextToken(); expression(); if (token == TokenNameCOLON) { getNextToken(); expression(); } else { throwSyntaxError("':' expected in ternary operator '? :'."); } } } private void andExpression() throws CoreException { do { ternaryExpression(); if (token != TokenNameAND) { return; } getNextToken(); } while (true); } private void exclusiveorExpression() throws CoreException { do { andExpression(); if (token != TokenNameXOR) { return; } getNextToken(); } while (true); } private void inclusiveorExpression() throws CoreException { do { exclusiveorExpression(); if (token != TokenNameOR) { return; } getNextToken(); } while (true); } private void booleanandExpression() throws CoreException { do { inclusiveorExpression(); if (token != TokenNameAND_AND) { return; } getNextToken(); } while (true); } private void booleanorExpression() throws CoreException { do { booleanandExpression(); if (token != TokenNameOR_OR) { return; } getNextToken(); } while (true); } private void logicalandExpression() throws CoreException { do { booleanorExpression(); if (token != TokenNameAND) { return; } getNextToken(); } while (true); } private void logicalexclusiveorExpression() throws CoreException { do { logicalandExpression(); if (token != TokenNameXOR) { return; } getNextToken(); } while (true); } private void logicalinclusiveorExpression() throws CoreException { do { logicalexclusiveorExpression(); if (token != TokenNameOR) { return; } getNextToken(); } while (true); } // public void assignmentExpression() { // if (token == TokenNameVARIABLE) { // getNextToken(); // if (token == TokenNameSET) { // getNextToken(); // logicalinclusiveorExpression(); // } // } else { // logicalinclusiveorExpression(); // } // } private void variableList() throws CoreException { do { variable(); if (token == TokenNameCOMMA) { getNextToken(); } else { break; } } while (true); } private void variable() throws CoreException { if (token == TokenNameDOLLAR_LBRACE) { getNextToken(); expression(); ; if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected after indirect variable token '${'."); } getNextToken(); } else { if (token == TokenNameVariable) { getNextToken(); if (token == TokenNameLBRACKET) { getNextToken(); expression(); if (token != TokenNameRBRACKET) { throwSyntaxError("']' expected in variable-list."); } getNextToken(); } else if (token == TokenNameEQUAL) { getNextToken(); constant(); } } else { throwSyntaxError("$-variable expected in variable-list."); } } } /** * It will look for a value (after a '=' for example) * @throws CoreException */ private void constant() throws CoreException { // String ident; switch (token) { case TokenNamePLUS : getNextToken(); switch (token) { case TokenNameDoubleLiteral : getNextToken(); break; case TokenNameIntegerLiteral : getNextToken(); break; default : throwSyntaxError("Constant expected after '+' presign."); } break; case TokenNameMINUS : getNextToken(); switch (token) { case TokenNameDoubleLiteral : getNextToken(); break; case TokenNameIntegerLiteral : getNextToken(); break; default : throwSyntaxError("Constant expected after '-' presign."); } 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."); } } getNextToken(); } break; case TokenNameStringLiteral : getNextToken(); break; case TokenNameStringConstant : getNextToken(); break; case TokenNameStringInterpolated : getNextToken(); break; case TokenNameDoubleLiteral : getNextToken(); break; case TokenNameIntegerLiteral : getNextToken(); break; default : throwSyntaxError("Constant expected."); } } public void reportSyntaxError() { //int act, int currentKind, int stateStackTop) { /* remember current scanner position */ int startPos = scanner.startPosition; int currentPos = scanner.currentPosition; // String[] expectings; // String tokenName = name[symbol_index[currentKind]]; //fetch all "accurate" possible terminals that could recover the error // int start, end = start = asi(stack[stateStackTop]); // while (asr[end] != 0) // end++; // int length = end - start; // expectings = new String[length]; // if (length != 0) { // char[] indexes = new char[length]; // System.arraycopy(asr, start, indexes, 0, length); // for (int i = 0; i < length; i++) { // expectings[i] = name[symbol_index[indexes[i]]]; // } // } //if the pb is an EOF, try to tell the user that they are some // if (tokenName.equals(UNEXPECTED_EOF)) { // if (!this.checkAndReportBracketAnomalies(problemReporter())) { // char[] tokenSource; // try { // tokenSource = this.scanner.getCurrentTokenSource(); // } catch (Exception e) { // tokenSource = new char[] {}; // } // problemReporter().parseError( // this.scanner.startPosition, // this.scanner.currentPosition - 1, // tokenSource, // tokenName, // expectings); // } // } else { //the next test is HEAVILY grammar DEPENDENT. // if ((length == 14) // && (expectings[0] == "=") //$NON-NLS-1$ // && (expectings[1] == "*=") //$NON-NLS-1$ // && (expressionPtr > -1)) { // switch(currentKind) { // case TokenNameSEMICOLON: // case TokenNamePLUS: // case TokenNameMINUS: // case TokenNameDIVIDE: // case TokenNameREMAINDER: // case TokenNameMULTIPLY: // case TokenNameLEFT_SHIFT: // case TokenNameRIGHT_SHIFT: //// case TokenNameUNSIGNED_RIGHT_SHIFT: // case TokenNameLESS: // case TokenNameGREATER: // case TokenNameLESS_EQUAL: // case TokenNameGREATER_EQUAL: // case TokenNameEQUAL_EQUAL: // case TokenNameNOT_EQUAL: // case TokenNameXOR: // case TokenNameAND: // case TokenNameOR: // case TokenNameOR_OR: // case TokenNameAND_AND: // // the ; is not the expected token ==> it ends a statement when an expression is not ended // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]); // break; // case TokenNameRBRACE : // problemReporter().missingSemiColon(expressionStack[expressionPtr]); // break; // default: // char[] tokenSource; // try { // tokenSource = this.scanner.getCurrentTokenSource(); // } catch (Exception e) { // tokenSource = new char[] {}; // } // problemReporter().parseError( // this.scanner.startPosition, // this.scanner.currentPosition - 1, // tokenSource, // tokenName, // expectings); // this.checkAndReportBracketAnomalies(problemReporter()); // } // } else { char[] tokenSource; try { tokenSource = this.scanner.getCurrentTokenSource(); } catch (Exception e) { tokenSource = new char[] { }; } // problemReporter().parseError( // this.scanner.startPosition, // this.scanner.currentPosition - 1, // tokenSource, // tokenName, // expectings); this.checkAndReportBracketAnomalies(problemReporter()); // } // } /* reset scanner where it was */ scanner.startPosition = startPos; scanner.currentPosition = currentPos; } public static final int RoundBracket = 0; public static final int SquareBracket = 1; public static final int CurlyBracket = 2; public static final int BracketKinds = 3; protected int[] nestedMethod; //the ptr is nestedType protected int nestedType, dimensions; //ast stack final static int AstStackIncrement = 100; protected int astPtr; protected AstNode[] astStack = new AstNode[AstStackIncrement]; protected int astLengthPtr; protected int[] astLengthStack; AstNode[] noAstNodes = new AstNode[AstStackIncrement]; public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/ protected ReferenceContext referenceContext; protected ProblemReporter problemReporter; // protected CompilationResult compilationResult; /** * Returns this parser's problem reporter initialized with its reference context. * Also it is assumed that a problem is going to be reported, so initializes * the compilation result's line positions. */ public ProblemReporter problemReporter() { if (scanner.recordLineSeparator) { compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); } problemReporter.referenceContext = referenceContext; return problemReporter; } /* * Reconsider the entire source looking for inconsistencies in {} () [] */ public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) { scanner.wasAcr = false; boolean anomaliesDetected = false; try { char[] source = scanner.source; int[] leftCount = { 0, 0, 0 }; int[] rightCount = { 0, 0, 0 }; int[] depths = { 0, 0, 0 }; int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] }; int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] }; int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] }; int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] }; scanner.currentPosition = scanner.initialPosition; //starting point (first-zero-based char) while (scanner.currentPosition < scanner.eofPosition) { //loop for jumping over comments try { // ---------Consume white space and handles startPosition--------- boolean isWhiteSpace; do { scanner.startPosition = scanner.currentPosition; // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace(); // } else { if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) { if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) { // only record line positions we have not recorded yet scanner.pushLineSeparator(); } } isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter); // } } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition)); // -------consume token until } is found--------- switch (scanner.currentCharacter) { case '{' : { int index = leftCount[CurlyBracket]++; if (index == leftPositions[CurlyBracket].length) { System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index); System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index); } leftPositions[CurlyBracket][index] = scanner.startPosition; leftDepths[CurlyBracket][index] = depths[CurlyBracket]++; } break; case '}' : { int index = rightCount[CurlyBracket]++; if (index == rightPositions[CurlyBracket].length) { System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index); System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index); } rightPositions[CurlyBracket][index] = scanner.startPosition; rightDepths[CurlyBracket][index] = --depths[CurlyBracket]; } break; case '(' : { int index = leftCount[RoundBracket]++; if (index == leftPositions[RoundBracket].length) { System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index); System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index); } leftPositions[RoundBracket][index] = scanner.startPosition; leftDepths[RoundBracket][index] = depths[RoundBracket]++; } break; case ')' : { int index = rightCount[RoundBracket]++; if (index == rightPositions[RoundBracket].length) { System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index); System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index); } rightPositions[RoundBracket][index] = scanner.startPosition; rightDepths[RoundBracket][index] = --depths[RoundBracket]; } break; case '[' : { int index = leftCount[SquareBracket]++; if (index == leftPositions[SquareBracket].length) { System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index); System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index); } leftPositions[SquareBracket][index] = scanner.startPosition; leftDepths[SquareBracket][index] = depths[SquareBracket]++; } break; case ']' : { int index = rightCount[SquareBracket]++; if (index == rightPositions[SquareBracket].length) { System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index); System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index); } rightPositions[SquareBracket][index] = scanner.startPosition; rightDepths[SquareBracket][index] = --depths[SquareBracket]; } break; case '\'' : { if (scanner.getNextChar('\\')) { scanner.scanEscapeCharacter(); } else { // consume next character scanner.unicodeAsBackSlash = false; // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { // scanner.getNextUnicodeChar(); // } else { if (scanner.withoutUnicodePtr != 0) { scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; } // } } scanner.getNextChar('\''); break; } case '"' : // consume next character scanner.unicodeAsBackSlash = false; // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { // scanner.getNextUnicodeChar(); // } else { if (scanner.withoutUnicodePtr != 0) { scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; } // } while (scanner.currentCharacter != '"') { if (scanner.currentCharacter == '\r') { if (source[scanner.currentPosition] == '\n') scanner.currentPosition++; break; // the string cannot go further that the line } if (scanner.currentCharacter == '\n') { break; // the string cannot go further that the line } if (scanner.currentCharacter == '\\') { scanner.scanEscapeCharacter(); } // consume next character scanner.unicodeAsBackSlash = false; // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { // scanner.getNextUnicodeChar(); // } else { if (scanner.withoutUnicodePtr != 0) { scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; } // } } break; case '/' : { int test; if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment //get the next char if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { //-------------unicode traitement ------------ int c1 = 0, c2 = 0, c3 = 0, c4 = 0; scanner.currentPosition++; while (source[scanner.currentPosition] == 'u') { scanner.currentPosition++; } if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error don't care of the value scanner.currentCharacter = 'A'; } //something different from \n and \r else { scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); } } while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') { //get the next char scanner.startPosition = scanner.currentPosition; if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { //-------------unicode traitement ------------ int c1 = 0, c2 = 0, c3 = 0, c4 = 0; scanner.currentPosition++; while (source[scanner.currentPosition] == 'u') { scanner.currentPosition++; } if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error don't care of the value scanner.currentCharacter = 'A'; } //something different from \n and \r else { scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); } } } if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) { if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) { // only record line positions we have not recorded yet scanner.pushLineSeparator(); if (this.scanner.taskTags != null) { this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); } } } break; } if (test > 0) { //traditional and annotation comment boolean star = false; // consume next character scanner.unicodeAsBackSlash = false; // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { // scanner.getNextUnicodeChar(); // } else { if (scanner.withoutUnicodePtr != 0) { scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; } // } if (scanner.currentCharacter == '*') { star = true; } //get the next char if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { //-------------unicode traitement ------------ int c1 = 0, c2 = 0, c3 = 0, c4 = 0; scanner.currentPosition++; while (source[scanner.currentPosition] == 'u') { scanner.currentPosition++; } if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error don't care of the value scanner.currentCharacter = 'A'; } //something different from * and / else { scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); } } //loop until end of comment */ while ((scanner.currentCharacter != '/') || (!star)) { star = scanner.currentCharacter == '*'; //get next char if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { //-------------unicode traitement ------------ int c1 = 0, c2 = 0, c3 = 0, c4 = 0; scanner.currentPosition++; while (source[scanner.currentPosition] == 'u') { scanner.currentPosition++; } if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error don't care of the value scanner.currentCharacter = 'A'; } //something different from * and / else { scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); } } } if (this.scanner.taskTags != null) { this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); } break; } break; } default : if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) { scanner.scanIdentifierOrKeyword(false); break; } if (Character.isDigit(scanner.currentCharacter)) { scanner.scanNumber(false); break; } } //-----------------end switch while try-------------------- } catch (IndexOutOfBoundsException e) { break; // read until EOF } catch (InvalidInputException e) { return false; // no clue } } if (scanner.recordLineSeparator) { // compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); } // check placement anomalies against other kinds of brackets for (int kind = 0; kind < BracketKinds; kind++) { for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) { int start = leftPositions[kind][leftIndex]; // deepest first // find matching closing bracket int depth = leftDepths[kind][leftIndex]; int end = -1; for (int i = 0; i < rightCount[kind]; i++) { int pos = rightPositions[kind][i]; // want matching bracket further in source with same depth if ((pos > start) && (depth == rightDepths[kind][i])) { end = pos; break; } } if (end < 0) { // did not find a good closing match problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); return true; } // check if even number of opening/closing other brackets in between this pair of brackets int balance = 0; for (int otherKind = 0;(balance == 0) && (otherKind < BracketKinds); otherKind++) { for (int i = 0; i < leftCount[otherKind]; i++) { int pos = leftPositions[otherKind][i]; if ((pos > start) && (pos < end)) balance++; } for (int i = 0; i < rightCount[otherKind]; i++) { int pos = rightPositions[otherKind][i]; if ((pos > start) && (pos < end)) balance--; } if (balance != 0) { problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly return true; } } } // too many opening brackets ? for (int i = rightCount[kind]; i < leftCount[kind]; i++) { anomaliesDetected = true; problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, compilationUnit.compilationResult); } // too many closing brackets ? for (int i = leftCount[kind]; i < rightCount[kind]; i++) { anomaliesDetected = true; problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult); } if (anomaliesDetected) return true; } return anomaliesDetected; } catch (ArrayStoreException e) { // jdk1.2.2 jit bug return anomaliesDetected; } catch (NullPointerException e) { // jdk1.2.2 jit bug return anomaliesDetected; } } protected void pushOnAstLengthStack(int pos) { try { astLengthStack[++astLengthPtr] = pos; } catch (IndexOutOfBoundsException e) { int oldStackLength = astLengthStack.length; int[] oldPos = astLengthStack; astLengthStack = new int[oldStackLength + StackIncrement]; System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength); astLengthStack[astLengthPtr] = pos; } } protected void pushOnAstStack(AstNode node) { /*add a new obj on top of the ast stack astPtr points on the top*/ try { astStack[++astPtr] = node; } catch (IndexOutOfBoundsException e) { int oldStackLength = astStack.length; AstNode[] oldStack = astStack; astStack = new AstNode[oldStackLength + AstStackIncrement]; System.arraycopy(oldStack, 0, astStack, 0, oldStackLength); astPtr = oldStackLength; astStack[astPtr] = node; } try { astLengthStack[++astLengthPtr] = 1; } catch (IndexOutOfBoundsException e) { int oldStackLength = astLengthStack.length; int[] oldPos = astLengthStack; astLengthStack = new int[oldStackLength + AstStackIncrement]; System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength); astLengthStack[astLengthPtr] = 1; } } }