/******************************************************************************* * 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.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.FieldDeclaration; 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.TypeDeclaration; 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: //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; protected int modifiers; protected int modifiersSourceStart; protected Parser(ProblemReporter problemReporter) { this.problemReporter = problemReporter; this.options = problemReporter.options; 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.includesList = 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 /* 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 */ // private void setMarker(String message, int charStart, int charEnd, int // errorLevel) { // 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) { int problemStartPosition = scanner.getCurrentTokenStartPosition(); int problemEndPosition = scanner.getCurrentTokenEndPosition(); throwSyntaxError(error, problemStartPosition, problemEndPosition + 1); } /** * This method will throw the SyntaxError. It will add the good lines and * columns to the Error * * @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 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 reportSyntaxWarning(String error, int problemStartPosition, int problemEndPosition) { problemReporter.phpParsingWarning(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext, compilationUnit.compilationResult); } /** * Method Declaration. * * @see */ // private void getChar() { // if (str.length() > chIndx) { // ch = str.charAt(chIndx++); // // return; // } // // chIndx = str.length() + 1; // ch = ' '; // // token = TokenNameEOF; // phpEnd = true; // } /** * gets the next token from input */ private void getNextToken() { 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; } public void init(String s) { this.str = s; this.token = TokenNameEOF; // this.chIndx = 0; // this.rowCount = 1; // this.columnCount = 0; this.phpEnd = false; // this.phpMode = false; /* scanner initialization */ scanner.setSource(s.toCharArray()); scanner.setPHPMode(false); } protected void initialize(boolean phpMode) { compilationUnit = null; referenceContext = null; includesList = new ArrayList(); this.str = ""; this.token = TokenNameEOF; // this.chIndx = 0; // this.rowCount = 1; // this.columnCount = 0; this.phpEnd = false; // this.phpMode = phpMode; scanner.setPHPMode(phpMode); } /** * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> * </body>' */ public void parse(String s) { init(s); parse(); } /** * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> * </body>' */ protected void parse() { getNextToken(); do { try { if (token != TokenNameEOF && token != TokenNameERROR) { statementList(); } if (token != TokenNameEOF) { if (token == TokenNameERROR) { throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")"); } if (token == TokenNameRPAREN) { throwSyntaxError("Too many closing ')'; end-of-file not reached."); } if (token == TokenNameRBRACE) { throwSyntaxError("Too many closing '}'; end-of-file not reached."); } if (token == TokenNameRBRACKET) { throwSyntaxError("Too many closing ']'; end-of-file not reached."); } if (token == TokenNameLPAREN) { throwSyntaxError("Read character '('; end-of-file not reached."); } if (token == TokenNameLBRACE) { throwSyntaxError("Read character '{'; end-of-file not reached."); } if (token == TokenNameLBRACKET) { throwSyntaxError("Read character '['; end-of-file not reached."); } throwSyntaxError("End-of-file not reached."); } break; } catch (SyntaxError sytaxErr1) { // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), // ERROR); // setMarker(sytaxErr1.getMessage(), // scanner.getCurrentTokenStartPosition(), // scanner.getCurrentTokenEndPosition(), ERROR); try { // if an error occured, // try to find keywords 'class' or 'function' // to parse the rest of the string while (token != TokenNameEOF && token != TokenNameERROR) { if (token == TokenNameabstract || token == TokenNamefinal || token == TokenNameclass || token == TokenNamefunction) { break; } getNextToken(); } if (token == TokenNameEOF || token == TokenNameERROR) { break; } } catch (SyntaxError sytaxErr2) { // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), // ERROR); // setMarker(sytaxErr2.getMessage(), // scanner.getCurrentTokenStartPosition(), // scanner.getCurrentTokenEndPosition(), ERROR); break; } } } while (true); endParse(0); } protected CompilationUnitDeclaration endParse(int act) { this.lastAct = act; if (currentElement != null) { currentElement.topElement().updateParseTree(); if (VERBOSE_RECOVERY) { System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$ System.out.println("--------------------------"); //$NON-NLS-1$ System.out.println(compilationUnit); System.out.println("----------------------------------"); //$NON-NLS-1$ } } else { if (diet & VERBOSE_RECOVERY) { System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$ System.out.println("--------------------------"); //$NON-NLS-1$ System.out.println(compilationUnit); System.out.println("----------------------------------"); //$NON-NLS-1$ } } if (scanner.recordLineSeparator) { compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); } if (scanner.taskTags != null) { for (int i = 0; i < scanner.foundTaskCount; i++) { problemReporter().task(new String(scanner.foundTaskTags[i]), new String(scanner.foundTaskMessages[i]), scanner.foundTaskPriorities[i] == null ? null : new String(scanner.foundTaskPriorities[i]), scanner.foundTaskPositions[i][0], scanner.foundTaskPositions[i][1]); } } compilationUnit.imports = new ImportReference[includesList.size()]; for (int i = 0; i < includesList.size(); i++) { compilationUnit.imports[i] = (ImportReference) includesList.get(i); } return compilationUnit; } // public PHPOutlineInfo parseInfo(Object parent, String s) { // PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent); // // Stack stack = new Stack(); // // stack.push(outlineInfo.getDeclarations()); // this.str = s; // this.token = TokenNameEOF; // // this.chIndx = 0; // // this.rowCount = 1; // // this.columnCount = 0; // this.phpEnd = false; // this.phpMode = false; // scanner.setSource(s.toCharArray()); // scanner.setPHPMode(false); // // getNextToken(); // parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false); // // return outlineInfo; // } private boolean isVariable() { return token == TokenNameVariable; // || token == TokenNamethis; } // private void parseDeclarations(PHPOutlineInfo outlineInfo, // OutlineableWithChildren current, boolean goBack) { // char[] ident; // // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek(); // PHPSegmentWithChildren temp; // int counter = 0; // IPreferenceStore store = // PHPeclipsePlugin.getDefault().getPreferenceStore(); // try { // while (token != TokenNameEOF && token != TokenNameERROR) { // if (token == TokenNameVariable) { // ident = scanner.getCurrentIdentifierSource(); // outlineInfo.addVariable(new String(ident)); // getNextToken(); // } else if (token == TokenNamevar) { // getNextToken(); // if (token == TokenNameVariable // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) { // ident = scanner.getCurrentIdentifierSource(); // //substring(1) added because PHPVarDeclaration doesn't // // need the $ anymore // String variableName = new String(ident).substring(1); // outlineInfo.addVariable(variableName); // getNextToken(); // if (token != TokenNameSEMICOLON) { // getNextToken(); // ident = scanner.getCurrentTokenSource(); // if (token > TokenNameKEYWORD) { // current.add(new PHPVarDeclaration(current, variableName, // // chIndx - ident.length, // scanner.getCurrentTokenStartPosition(), new String(ident))); // } else { // switch (token) { // case TokenNameVariable : // case TokenNamethis : // current.add(new PHPVarDeclaration(current, variableName, // // chIndx - // // ident.length, // scanner.getCurrentTokenStartPosition(), new String( // ident))); // break; // case TokenNameIdentifier : // current.add(new PHPVarDeclaration(current, variableName, // // chIndx - // // ident.length, // scanner.getCurrentTokenStartPosition(), new String( // ident))); // break; // case TokenNameDoubleLiteral : // current.add(new PHPVarDeclaration(current, variableName // + doubleNumber, // // chIndx - // // ident.length, // scanner.getCurrentTokenStartPosition(), new String( // ident))); // break; // case TokenNameIntegerLiteral : // current.add(new PHPVarDeclaration(current, variableName, // // chIndx - // // ident.length, // scanner.getCurrentTokenStartPosition(), new String( // ident))); // break; // case TokenNameStringInterpolated : // case TokenNameStringLiteral : // current.add(new PHPVarDeclaration(current, variableName, // // chIndx - // // ident.length, // scanner.getCurrentTokenStartPosition(), new String( // ident))); // break; // case TokenNameStringConstant : // current.add(new PHPVarDeclaration(current, variableName, // // chIndx - // // ident.length, // scanner.getCurrentTokenStartPosition(), new String( // ident))); // break; // default : // current.add(new PHPVarDeclaration(current, variableName, // // chIndx - // // ident.length // scanner.getCurrentTokenStartPosition())); // break; // } // } // } else { // ident = scanner.getCurrentIdentifierSource(); // current.add(new PHPVarDeclaration(current, variableName, // // chIndx - ident.length // scanner.getCurrentTokenStartPosition())); // } // } // } else if (token == TokenNamefunction) { // getNextToken(); // if (token == TokenNameAND) { // getNextToken(); // } // if (token == TokenNameIdentifier // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) { // ident = scanner.getCurrentIdentifierSource(); // outlineInfo.addVariable(new String(ident)); // temp = new PHPFunctionDeclaration(current, new String(ident), // // chIndx - ident.length // scanner.getCurrentTokenStartPosition()); // current.add(temp); // getNextToken(); // parseDeclarations(outlineInfo, temp, true); // } // } else if (token == TokenNameclass) { // getNextToken(); // if (token == TokenNameIdentifier // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) { // ident = scanner.getCurrentIdentifierSource(); // outlineInfo.addVariable(new String(ident)); // temp = new PHPClassDeclaration(current, new String(ident), // // chIndx - ident.len // scanner.getCurrentTokenStartPosition()); // current.add(temp); // // stack.push(temp); // getNextToken(); // //skip tokens for classname, extends and others until // // we have the opening '{' // while (token != TokenNameLBRACE && token != TokenNameEOF // && token != TokenNameERROR) { // getNextToken(); // } // parseDeclarations(outlineInfo, temp, true); // // stack.pop(); // } // } else if ((token == TokenNameLBRACE) // || (token == TokenNameDOLLAR_LBRACE)) { // getNextToken(); // counter++; // } else if (token == TokenNameRBRACE) { // getNextToken(); // --counter; // if (counter == 0 && goBack) { // return; // } // } else if (token == TokenNamerequire || token == TokenNamerequire_once // || token == TokenNameinclude || token == TokenNameinclude_once) { // ident = scanner.getCurrentTokenSource(); // getNextToken(); // int startPosition = scanner.getCurrentTokenStartPosition(); // expr(); // char[] expr = scanner.getCurrentTokenSource(startPosition); // outlineInfo.addVariable(new String(ident)); // current.add(new PHPReqIncDeclaration(current, new String(ident), // // chIndx - ident.length, // startPosition, new String(expr))); // getNextToken(); // } else { // getNextToken(); // } // } // } catch (SyntaxError sytaxErr) { // // try { // // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR); // // setMarker(sytaxErr.getMessage(), // // scanner.getCurrentTokenStartPosition(), // // scanner.getCurrentTokenEndPosition(), ERROR); // // } catch (CoreException e) { // // } // } // } private void statementList() { do { statement(TokenNameEOF); if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse) || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor) || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch) || (token == TokenNameEOF) || (token == TokenNameERROR)) { return; } } while (true); } private void functionBody(MethodDeclaration methodDecl) { // '{' [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) { // if (token > TokenNameKEYWORD && token != TokenNamelist && token != // TokenNamenew) { // char[] ident = scanner.getCurrentIdentifierSource(); // String keyword = new String(ident); // if (token == TokenNameAT) { // getNextToken(); // if (token != TokenNamerequire && token != TokenNamerequire_once // && token != TokenNameinclude && token != TokenNameinclude_once // && token != TokenNameIdentifier && token != TokenNameVariable // && token != TokenNameStringInterpolated) { // throwSyntaxError("identifier expected after '@'."); // } // } // if (token == TokenNameinclude || token == TokenNameinclude_once) { // getNextToken(); // if (token == TokenNameLPAREN) { // expr(); // if (token == TokenNameSEMICOLON) { // getNextToken(); // } else { // if (previousToken != TokenNameAT && token != TokenNameStopPHP) { // throwSyntaxError("';' expected after 'include' or 'include_once'."); // } // // getNextToken(); // } // } else { // concatenationExpression(); // } // return; // } else if (token == TokenNamerequire || token == // TokenNamerequire_once) // { // getNextToken(); // //constant(); // if (token == TokenNameLPAREN) { // expr(); // if (token == TokenNameSEMICOLON) { // getNextToken(); // } else { // if (previousToken != TokenNameAT && token != TokenNameStopPHP) { // throwSyntaxError("';' expected after 'require' or 'require_once'."); // } // // getNextToken(); // } // } else { // concatenationExpression(); // } // return; // } else if (token == TokenNameif) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'if' keyword."); } expr(); 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."); } expr(); 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."); } expr(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'while' condition."); } whileStatement(); return; } else if (token == TokenNamedo) { getNextToken(); if (token == TokenNameLBRACE) { getNextToken(); if (token != TokenNameRBRACE) { statementList(); } if (token == TokenNameRBRACE) { getNextToken(); } else { throwSyntaxError("'}' expected after 'do' keyword."); } } else { statement(TokenNameEOF); } if (token == TokenNamewhile) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'while' keyword."); } expr(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'while' condition."); } } else { throwSyntaxError("'while' expected after 'do' keyword."); } if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after do-while statement."); } getNextToken(); } return; } else if (token == TokenNameforeach) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'foreach' keyword."); } expr(); if (token == TokenNameas) { getNextToken(); } else { throwSyntaxError("'as' expected after 'foreach' exxpression."); } // variable(); foreach_variable(); foreach_optional_arg(); 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) { expr(); } if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after 'continue', 'break' or 'return'."); } getNextToken(); } return; } else if (token == TokenNameecho) { getNextToken(); expressionList(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after 'echo' statement."); } getNextToken(); } return; } else if (token == TokenNameINLINE_HTML) { 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) { getNextToken(); global_var_list(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after 'global' statement."); } getNextToken(); } return; } else if (token == TokenNamestatic) { getNextToken(); static_var_list(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after 'static' statement."); } getNextToken(); } return; } else if (token == TokenNameunset) { getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'unset' statement."); } unset_variables(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'unset' statement."); } if (token == TokenNameSEMICOLON) { getNextToken(); } else { if (token != TokenNameINLINE_HTML) { throwSyntaxError("';' expected after 'unset' 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 == TokenNametry) { getNextToken(); if (token != TokenNameLBRACE) { throwSyntaxError("'{' expected in 'try' statement."); } getNextToken(); statementList(); if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected in 'try' statement."); } getNextToken(); return; } else if (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(); if (token != TokenNameRBRACE) { statementList(); if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected in 'catch' statement."); } } getNextToken(); additional_catches(); return; } else if (token == TokenNamethrow) { getNextToken(); expr(); if (token == TokenNameSEMICOLON) { getNextToken(); } else { throwSyntaxError("';' expected after 'throw' exxpression."); } return; } else if (token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) { TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult); typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); // default super class typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0); compilationUnit.types.add(typeDecl); try { pushOnAstStack(typeDecl); unticked_class_declaration_statement(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) { expr(); } if (token == TokenNameSEMICOLON) { getNextToken(); return; } else { if (token != TokenNameINLINE_HTML && token != TokenNameEOF) { throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")"); } getNextToken(); } } } 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 { 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 // | unset_variables ',' unset_variable // unset_variable: // variable while (true) { variable(); if (token != TokenNameCOMMA) { break; } 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) { // interface_entry T_STRING // interface_extends_list // '{' class_statement_list '}' checkAndSetModifiers(AccInterface); getNextToken(); typeDecl.modifiers = this.modifiers; 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); } 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); return; } } else { // class_entry_type T_STRING extends_from // implements_list // '{' class_statement_list'}' class_entry_type(); typeDecl.modifiers = this.modifiers; //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); } getNextToken(); // extends_from: // /* empty */ // | T_EXTENDS fully_qualified_class_name if (token == TokenNameextends) { 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); return; } } // '{' class_statement_list '}' if (token == TokenNameLBRACE) { getNextToken(); if (token != TokenNameRBRACE) { 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 class body."); } } else { throwSyntaxError("'{' expected at start of class body."); } } private void class_entry_type() { // T_CLASS // | T_ABSTRACT T_CLASS // | T_FINAL T_CLASS if (token == TokenNameclass) { getNextToken(); } else if (token == TokenNameabstract) { checkAndSetModifiers(AccAbstract); getNextToken(); if (token != TokenNameclass) { throwSyntaxError("Keyword 'class' expected after keyword 'abstract'."); } 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"); } } private void interface_extends_list() { // /* empty */ // | T_EXTENDS interface_list if (token == TokenNameextends) { getNextToken(); interface_list(); } } private void implements_list() { // /* empty */ // | T_IMPLEMENTS interface_list if (token == TokenNameimplements) { getNextToken(); interface_list(); } } private void interface_list() { // interface_list: // fully_qualified_class_name //| interface_list ',' fully_qualified_class_name do { if (token == TokenNameIdentifier) { getNextToken(); } else { throwSyntaxError("Interface name expected after keyword 'implements'."); } if (token != TokenNameCOMMA) { return; } getNextToken(); } while (true); } // private void classBody(TypeDeclaration typeDecl) { // //'{' [class-element-list] '}' // if (token == TokenNameLBRACE) { // getNextToken(); // if (token != TokenNameRBRACE) { // class_statement_list(); // } // 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 class_statement_list(ArrayList list) { do { class_statement(list); } while (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar || token == TokenNameconst); } 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); problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult); getNextToken(); class_variable_declaration(declarationSourceStart, list); } else if (token == TokenNameconst) { class_constant_declaration(); if (token != TokenNameSEMICOLON) { throwSyntaxError("';' expected after class const declaration."); } getNextToken(); } else { boolean hasModifiers = member_modifiers(); if (token == TokenNamefunction) { if (!hasModifiers) { checkAndSetModifiers(AccPublic); } MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); methodDecl.modifiers = this.modifiers; getNextToken(); functionDefinition(methodDecl); } else { if (!hasModifiers) { throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations."); } 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() { // 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."); } 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 // //| T_VAR // initializeModifiers(); // if (token == TokenNamevar) { // checkAndSetModifiers(AccPublic); // reportSyntaxError( // "Keyword 'var' is deprecated. Please use 'public' 'private' or // 'protected' // modifier for field declarations.", // scanner.getCurrentTokenStartPosition(), scanner // .getCurrentTokenEndPosition()); // getNextToken(); // } else { // if (!member_modifiers()) { // throwSyntaxError("'public' 'private' or 'protected' modifier expected for // field declarations."); // } // } // } // private void method_modifiers() { // //method_modifiers: // // /* empty */ // //| non_empty_member_modifiers // initializeModifiers(); // if (!member_modifiers()) { // checkAndSetModifiers(AccPublic); // } // } private boolean member_modifiers() { // T_PUBLIC //| T_PROTECTED //| T_PRIVATE //| T_STATIC //| T_ABSTRACT //| T_FINAL boolean foundToken = false; while (true) { if (token == TokenNamepublic) { checkAndSetModifiers(AccPublic); getNextToken(); foundToken = true; } else if (token == TokenNameprotected) { checkAndSetModifiers(AccProtected); getNextToken(); foundToken = true; } else if (token == TokenNameprivate) { checkAndSetModifiers(AccPrivate); getNextToken(); foundToken = true; } else if (token == TokenNamestatic) { checkAndSetModifiers(AccStatic); getNextToken(); foundToken = true; } else if (token == TokenNameabstract) { checkAndSetModifiers(AccAbstract); getNextToken(); foundToken = true; } else if (token == TokenNamefinal) { checkAndSetModifiers(AccFinal); getNextToken(); foundToken = true; } else { break; } } return foundToken; } 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 do { if (token == TokenNameVariable) { 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) { getNextToken(); static_scalar(); } } else { // 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) { 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]; 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; } 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.selector = scanner.getCurrentIdentifierSource(); getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); } else { throwSyntaxError("'(' expected in function declaration."); } if (token != TokenNameRPAREN) { parameter_list(); } 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 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(); } return; } if (!empty_allowed) { throwSyntaxError("Identifier expected in parameter list."); } } private void optional_class_type() { // /* empty */ //| T_STRING } private void parameterDeclaration() { //variable //variable-reference if (token == TokenNameAND) { getNextToken(); if (isVariable()) { getNextToken(); } else { throwSyntaxError("Variable expected after reference operator '&'."); } } //variable '=' constant if (token == TokenNameVariable) { getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); static_scalar(); } return; } // if (token == TokenNamethis) { // throwSyntaxError("Reserved word '$this' not allowed in parameter // declaration."); // } } private void labeledStatementList() { if (token != TokenNamecase && token != TokenNamedefault) { throwSyntaxError("'case' or 'default' expected."); } do { if (token == TokenNamecase) { getNextToken(); expr(); //constant(); if (token == TokenNameCOLON || token == TokenNameSEMICOLON) { 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) + ")", // 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(); if (token == TokenNameRBRACE) { // empty default case break; } 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() { // ':' 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."); } expr(); if (token == TokenNameRPAREN) { getNextToken(); } else { throwSyntaxError("')' expected after 'elseif' condition."); } ifStatement(); } else if (token == TokenNameelse) { getNextToken(); statement(TokenNameEOF); } } } private void elseifStatementList() { 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() { if (token == TokenNameLPAREN) { getNextToken(); expr(); 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() { 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() { 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() { // ':' 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() { 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() { // 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() { do { expr(); if (token == TokenNameCOMMA) { getNextToken(); } else { break; } } while (true); } private void expr() { // r_variable // | expr_without_variable // if (token!=TokenNameEOF) { if (Scanner.TRACE) { System.out.println("TRACE: expr()"); } expr_without_variable(true); // } } private void expr_without_variable(boolean only_variable) { // internal_functions_in_yacc // | T_CLONE expr // | T_PRINT expr // | '(' expr ')' // | '@' expr // | '+' expr // | '-' expr // | '!' expr // | '~' expr // | T_INC rw_variable // | T_DEC rw_variable // | T_INT_CAST expr // | T_DOUBLE_CAST expr // | T_STRING_CAST expr // | T_ARRAY_CAST expr // | T_OBJECT_CAST expr // | T_BOOL_CAST expr // | T_UNSET_CAST expr // | T_EXIT exit_expr // | scalar // | T_ARRAY '(' array_pair_list ')' // | '`' encaps_list '`' // | T_LIST '(' assignment_list ')' '=' expr // | T_NEW class_name_reference ctor_arguments // | variable '=' expr // | variable '=' '&' variable // | variable '=' '&' T_NEW class_name_reference ctor_arguments // | variable T_PLUS_EQUAL expr // | variable T_MINUS_EQUAL expr // | variable T_MUL_EQUAL expr // | variable T_DIV_EQUAL expr // | variable T_CONCAT_EQUAL expr // | variable T_MOD_EQUAL expr // | variable T_AND_EQUAL expr // | variable T_OR_EQUAL expr // | variable T_XOR_EQUAL expr // | variable T_SL_EQUAL expr // | variable T_SR_EQUAL expr // | rw_variable T_INC // | rw_variable T_DEC // | expr T_BOOLEAN_OR expr // | expr T_BOOLEAN_AND expr // | expr T_LOGICAL_OR expr // | expr T_LOGICAL_AND expr // | expr T_LOGICAL_XOR expr // | expr '|' expr // | expr '&' expr // | expr '^' expr // | expr '.' expr // | expr '+' expr // | expr '-' expr // | expr '*' expr // | expr '/' expr // | expr '%' expr // | expr T_SL expr // | expr T_SR expr // | expr T_IS_IDENTICAL expr // | expr T_IS_NOT_IDENTICAL expr // | expr T_IS_EQUAL expr // | expr T_IS_NOT_EQUAL expr // | expr '<' expr // | expr T_IS_SMALLER_OR_EQUAL expr // | expr '>' expr // | expr T_IS_GREATER_OR_EQUAL expr // | expr T_INSTANCEOF class_name_reference // | expr '?' expr ':' expr if (Scanner.TRACE) { System.out.println("TRACE: expr_without_variable() PART 1"); } switch (token) { case TokenNameisset : case TokenNameempty : case TokenNameeval : case TokenNameinclude : case TokenNameinclude_once : case TokenNamerequire : case TokenNamerequire_once : internal_functions_in_yacc(); break; // | '(' expr ')' case TokenNameLPAREN : getNextToken(); expr(); if (token == TokenNameRPAREN) { getNextToken(); } 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) + " )"); } } } 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) + " )"); } } } 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(); break; } array_pair_list(); if (token != TokenNameRPAREN) { throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")"); } getNextToken(); } else { throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")"); } break; case TokenNamelist : // | T_LIST '(' assignment_list ')' '=' expr getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); assignment_list(); if (token != TokenNameRPAREN) { throwSyntaxError("')' expected after 'list' keyword."); } getNextToken(); if (token != TokenNameEQUAL) { throwSyntaxError("'=' expected after 'list' keyword."); } getNextToken(); expr(); } 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 == TokenNameAND) { getNextToken(); if (token == TokenNamenew) { // | variable '=' '&' T_NEW class_name_reference // ctor_arguments getNextToken(); class_name_reference(); ctor_arguments(); } else { variable(); } } else { expr(); } break; case TokenNamePLUS_EQUAL : case TokenNameMINUS_EQUAL : case TokenNameMULTIPLY_EQUAL : case TokenNameDIVIDE_EQUAL : case TokenNameDOT_EQUAL : case TokenNameREMAINDER_EQUAL : case TokenNameAND_EQUAL : case TokenNameOR_EQUAL : case TokenNameXOR_EQUAL : case TokenNameRIGHT_SHIFT_EQUAL : case TokenNameLEFT_SHIFT_EQUAL : getNextToken(); expr(); break; case TokenNamePLUS_PLUS : case TokenNameMINUS_MINUS : getNextToken(); break; default : if (!only_variable) { throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "')."); } } break; default : if (token != TokenNameINLINE_HTML) { if (token > TokenNameKEYWORD) { getNextToken(); break; } else { throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "')."); } } return; } if (Scanner.TRACE) { System.out.println("TRACE: expr_without_variable() PART 2"); } // | expr T_BOOLEAN_OR expr // | expr T_BOOLEAN_AND expr // | expr T_LOGICAL_OR expr // | expr T_LOGICAL_AND expr // | expr T_LOGICAL_XOR expr // | expr '|' expr // | expr '&' expr // | expr '^' expr // | expr '.' expr // | expr '+' expr // | expr '-' expr // | expr '*' expr // | expr '/' expr // | expr '%' expr // | expr T_SL expr // | expr T_SR expr // | expr T_IS_IDENTICAL expr // | expr T_IS_NOT_IDENTICAL expr // | expr T_IS_EQUAL expr // | expr T_IS_NOT_EQUAL expr // | expr '<' expr // | expr T_IS_SMALLER_OR_EQUAL expr // | expr '>' expr // | expr T_IS_GREATER_OR_EQUAL expr while (true) { switch (token) { case TokenNameOR_OR : case TokenNameAND_AND : case TokenNameand : case TokenNameor : case TokenNamexor : case TokenNameAND : case TokenNameOR : case TokenNameXOR : case TokenNameDOT : case TokenNamePLUS : case TokenNameMINUS : case TokenNameMULTIPLY : case TokenNameDIVIDE : case TokenNameREMAINDER : case TokenNameLEFT_SHIFT : case TokenNameRIGHT_SHIFT : case TokenNameEQUAL_EQUAL_EQUAL : case TokenNameNOT_EQUAL_EQUAL : case TokenNameEQUAL_EQUAL : case TokenNameNOT_EQUAL : case TokenNameLESS : case TokenNameLESS_EQUAL : case TokenNameGREATER : case TokenNameGREATER_EQUAL : getNextToken(); expr(); break; // | expr T_INSTANCEOF class_name_reference // | expr '?' expr ':' expr case TokenNameinstanceof : getNextToken(); class_name_reference(); break; case TokenNameQUESTION : getNextToken(); expr(); if (token == TokenNameCOLON) { getNextToken(); expr(); } break; default : return; } } } 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(); } else { dynamic_class_name_reference(); } } 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(); object_property(); dynamic_class_name_variable_properties(); } } 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(); object_property(); } } 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(); } } private void assignment_list() { // assignment_list: // assignment_list ',' assignment_list_element //| assignment_list_element while (true) { assignment_list_element(); if (token != TokenNameCOMMA) { break; } getNextToken(); } } 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(); } } 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(); 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(); } reference_variable(); } 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 ')' if (Scanner.TRACE) { System.out.println("TRACE: function_call()"); } if (token == TokenNameIdentifier) { getNextToken(); switch (token) { case TokenNamePAAMAYIM_NEKUDOTAYIM : // static member: getNextToken(); if (token == TokenNameIdentifier) { // class _constant getNextToken(); } else { // static member: variable_without_objects(); } break; } } else { variable_without_objects(); } if (token != TokenNameLPAREN) { // TODO is this ok ? return; // throwSyntaxError("'(' expected in function call."); } getNextToken(); if (token == TokenNameRPAREN) { getNextToken(); return; } non_empty_function_call_parameter_list(); if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in function call."); } getNextToken(); } // 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(); } } private void fully_qualified_class_name() { if (token == TokenNameIdentifier) { getNextToken(); } else { throwSyntaxError("Class name expected."); } } 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(); } reference_variable(); } } // 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; } } } 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(); expr(); if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected after compound variable token '$'."); } getNextToken(); } } // private void dim_offset() { // // dim_offset: // // /* empty */ // // | expr // expr(); // } 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; } } } 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 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 { 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(); return; } non_empty_function_call_parameter_list(); if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in method_or_not."); } getNextToken(); } } private void exit_expr() { // /* empty */ // | '(' ')' // | '(' expr ')' if (token != TokenNameLPAREN) { return; } getNextToken(); if (token == TokenNameRPAREN) { getNextToken(); return; } expr(); if (token != TokenNameRPAREN) { throwSyntaxError("')' expected after keyword 'exit'"); } getNextToken(); } 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 TokenNameLBRACE : // scanner.encapsedStringStack.pop(); getNextToken(); break; case TokenNameRBRACE : // scanner.encapsedStringStack.pop(); getNextToken(); break; case TokenNameLBRACKET : // scanner.encapsedStringStack.pop(); getNextToken(); break; case TokenNameRBRACKET : // scanner.encapsedStringStack.pop(); getNextToken(); break; case TokenNameMINUS_GREATER : // scanner.encapsedStringStack.pop(); getNextToken(); break; case TokenNameVariable : case TokenNameDOLLAR_LBRACE : case TokenNameCURLY_OPEN : encaps_var(); break; // case TokenNameDOLLAR : // getNextToken(); // if (token == TokenNameLBRACE) { // token = TokenNameDOLLAR_LBRACE; // encaps_var(); // } // break; default : char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue(); if (encapsedChar == '$') { scanner.encapsedStringStack.pop(); encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue(); switch (encapsedChar) { case '`' : if (token == TokenNameEncapsedString0) { return; } token = TokenNameSTRING; continue; case '\'' : if (token == TokenNameEncapsedString1) { return; } token = TokenNameSTRING; continue; case '"' : if (token == TokenNameEncapsedString2) { return; } token = TokenNameSTRING; continue; } } 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(); // if (token == TokenNameRBRACKET) { // getNextToken(); // } else { expr(); //encaps_var_offset(); if (token != TokenNameRBRACKET) { throwSyntaxError("']' expected after variable."); } // scanner.encapsedStringStack.pop(); getNextToken(); // } } else if (token == TokenNameMINUS_GREATER) { getNextToken(); if (token != TokenNameIdentifier) { throwSyntaxError("Identifier expected after '->'."); } // scanner.encapsedStringStack.pop(); getNextToken(); } // else { // // scanner.encapsedStringStack.pop(); // int tempToken = TokenNameSTRING; // if (!scanner.encapsedStringStack.isEmpty() // && (token == TokenNameEncapsedString0 // || token == TokenNameEncapsedString1 // || token == TokenNameEncapsedString2 || token == // TokenNameERROR)) { // char encapsedChar = ((Character) // scanner.encapsedStringStack.peek()) // .charValue(); // switch (token) { // case TokenNameEncapsedString0 : // if (encapsedChar == '`') { // tempToken = TokenNameEncapsedString0; // } // break; // case TokenNameEncapsedString1 : // if (encapsedChar == '\'') { // tempToken = TokenNameEncapsedString1; // } // break; // case TokenNameEncapsedString2 : // if (encapsedChar == '"') { // tempToken = TokenNameEncapsedString2; // } // break; // case TokenNameERROR : // if (scanner.source[scanner.currentPosition - 1] == '\\') { // scanner.currentPosition--; // getNextToken(); // } // break; // } // } // token = tempToken; // } break; case TokenNameDOLLAR_LBRACE : getNextToken(); if (token == TokenNameIdentifier) { getNextToken(); if (token == TokenNameLBRACKET) { getNextToken(); // if (token == TokenNameRBRACKET) { // getNextToken(); // } else { expr(); if (token != TokenNameRBRACKET) { throwSyntaxError("']' expected after '${'."); } getNextToken(); // } } if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected after '${'."); } // scanner.encapsedStringStack.pop(); getNextToken(); } else { expr(); if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected."); } // scanner.encapsedStringStack.pop(); getNextToken(); } break; case TokenNameCURLY_OPEN : getNextToken(); if (token == TokenNameIdentifier || token > TokenNameKEYWORD) { getNextToken(); if (token == TokenNameLBRACKET) { getNextToken(); // if (token == TokenNameRBRACKET) { // getNextToken(); // } else { expr(); if (token != TokenNameRBRACKET) { throwSyntaxError("']' expected after '{$'."); } getNextToken(); // } } else if (token == TokenNameMINUS_GREATER) { getNextToken(); if (token != TokenNameIdentifier) { throwSyntaxError("String token expected."); } getNextToken(); } // if (token != TokenNameRBRACE) { // throwSyntaxError("'}' expected after '{$'."); // } // // scanner.encapsedStringStack.pop(); // getNextToken(); } else { expr(); if (token != TokenNameRBRACE) { throwSyntaxError("'}' expected."); } // scanner.encapsedStringStack.pop(); getNextToken(); } break; } } 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 ',' if (token == TokenNameRPAREN) { throwSyntaxError("Variable expected after keyword 'isset'"); } while (true) { variable(); if (token == TokenNameCOMMA) { getNextToken(); } else { break; } } } 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 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(); if (token == TokenNameIdentifier) { getNextToken(); } else { throwSyntaxError("Identifier expected after '::' operator."); } } break; case TokenNameEncapsedString0 : try { scanner.currentCharacter = scanner.source[scanner.currentPosition++]; while (scanner.currentCharacter != '`') { if (scanner.currentCharacter == '\\') { scanner.currentPosition++; } scanner.currentCharacter = scanner.source[scanner.currentPosition++]; } getNextToken(); } catch (IndexOutOfBoundsException e) { throwSyntaxError("'`' expected at end of static string."); } break; case TokenNameEncapsedString1 : try { scanner.currentCharacter = scanner.source[scanner.currentPosition++]; while (scanner.currentCharacter != '\'') { if (scanner.currentCharacter == '\\') { scanner.currentPosition++; } scanner.currentCharacter = scanner.source[scanner.currentPosition++]; } getNextToken(); } catch (IndexOutOfBoundsException e) { throwSyntaxError("'\'' expected at end of static string."); } break; case TokenNameEncapsedString2 : try { scanner.currentCharacter = scanner.source[scanner.currentPosition++]; while (scanner.currentCharacter != '"') { if (scanner.currentCharacter == '\\') { scanner.currentPosition++; } scanner.currentCharacter = scanner.source[scanner.currentPosition++]; } getNextToken(); } catch (IndexOutOfBoundsException e) { throwSyntaxError("'\"' expected at end of static string."); } break; case 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; } 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; } getNextToken(); if (token == TokenNameRPAREN) { break; } } } 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 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. */ 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 */ 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; } } protected void resetModifiers() { this.modifiers = AccDefault; this.modifiersSourceStart = -1; // <-- see comment into // modifiersFlag(int) this.scanner.commentPtr = -1; } }