X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java index 99ead74..1a484bc 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java @@ -12,9 +12,19 @@ package net.sourceforge.phpdt.internal.compiler.parser; import java.util.ArrayList; +import net.sourceforge.phpdt.core.compiler.CharOperation; import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; import net.sourceforge.phpdt.core.compiler.InvalidInputException; +import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext; +import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants; +import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter; import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode; +import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration; +import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference; +import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration; import net.sourceforge.phpeclipse.phpeditor.PHPString; import org.eclipse.core.resources.IFile; @@ -23,7 +33,17 @@ import org.eclipse.jface.preference.IPreferenceStore; import test.PHPParserSuperclass; -public class Parser extends PHPParserSuperclass implements ITerminalSymbols { +public class Parser extends PHPParserSuperclass implements ITerminalSymbols, ParserBasicInformation { + //internal data for the automat + protected final static int StackIncrement = 255; + protected int stateStackTop; + protected int[] stack = new int[StackIncrement]; + public int firstToken; // handle for multiple parsing goals + public int lastAct; //handle for multiple parsing goals + protected RecoveredElement currentElement; + + public static boolean VERBOSE_RECOVERY = false; + protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies //scanner token public Scanner scanner; @@ -137,12 +157,24 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // final static int TokenNameOR = 159; // final static int TokenNameAT = 153; // @ - public Parser() { + protected Parser() { + this.currentPHPString = 0; + // PHPParserSuperclass.fileToParse = fileToParse; + this.phpList = null; + this.str = ""; + this.token = TokenNameEOF; + // this.chIndx = 0; + // this.rowCount = 1; + // this.columnCount = 0; + this.phpEnd = false; + // getNextToken(); + + this.initializeScanner(); } public void setFileToParse(IFile fileToParse) { this.currentPHPString = 0; - PHPParserSuperclass.fileToParse = fileToParse; + PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; this.str = ""; this.token = TokenNameEOF; @@ -164,7 +196,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // } // } this.currentPHPString = 0; - PHPParserSuperclass.fileToParse = fileToParse; + PHPParserSuperclass.fileToParse = fileToParse; this.phpList = null; this.str = ""; this.token = TokenNameEOF; @@ -225,6 +257,10 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { throw new SyntaxError(startRow, 0, " ", error); } + private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) { + problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext, compilationUnit.compilationResult); + throw new SyntaxError(1, 0, " ", error); + } /** * Method Declaration. * @@ -683,12 +719,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } while (true); } - - /** - * Parses a string with php tags - * i.e. '<body> <?php phpinfo() ?> </body>' - */ - public void parse(String s) throws CoreException { + public void init(String s) { this.str = s; this.token = TokenNameEOF; // this.chIndx = 0; @@ -699,6 +730,34 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { /* scanner initialization */ scanner.setSource(s.toCharArray()); scanner.setPHPMode(false); + } + + protected void initialize() { + compilationUnit = null; + referenceContext = null; + this.str = ""; + this.token = TokenNameEOF; + // this.chIndx = 0; + // this.rowCount = 1; + // this.columnCount = 0; + this.phpEnd = false; + this.phpMode = false; + scanner.setPHPMode(false); + } + /** + * Parses a string with php tags + * i.e. '<body> <?php phpinfo() ?> </body>' + */ + public void parse(String s) throws CoreException { + init(s); + parse(); + } + + /** + * Parses a string with php tags + * i.e. '<body> <?php phpinfo() ?> </body>' + */ + protected void parse() throws CoreException { getNextToken(); do { try { @@ -907,11 +966,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { if (counter == 0 && goBack) { return; } - } else if ( - token == TokenNamerequire - || token == TokenNamerequire_once - || token == TokenNameinclude - || token == TokenNameinclude_once) { + } else if (token == TokenNamerequire || token == TokenNamerequire_once || token == TokenNameinclude || token == TokenNameinclude_once) { ident = scanner.getCurrentTokenSource(); getNextToken(); @@ -957,7 +1012,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } while (true); } - private void compoundStatement() throws CoreException { + private void functionBody(MethodDeclaration methodDecl) throws CoreException { // '{' [statement-list] '}' if (token == TokenNameLBRACE) { getNextToken(); @@ -968,6 +1023,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { statementList(); } if (token == TokenNameRBRACE) { + methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); getNextToken(); } else { throwSyntaxError("'}' expected in compound-statement."); @@ -1287,18 +1343,30 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } return; } else if (token == TokenNamefunction) { + MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); + methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); getNextToken(); - functionDefinition(); + functionDefinition(methodDecl); return; } else if (token == TokenNameclass) { - getNextToken(); - classDeclarator(); - classBody(); + TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult); + typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); + // default super class + typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0); + compilationUnit.types.add(typeDecl); + try { + pushOnAstStack(typeDecl); + getNextToken(); + classDeclarator(typeDecl); + classBody(typeDecl); + } finally { + astPtr--; + astLengthPtr--; + } return; // } else { // throwSyntaxError("Unexpected keyword '" + keyword + "'"); } else if (token == TokenNameLBRACE) { - // compoundStatement getNextToken(); if (token != TokenNameRBRACE) { statementList(); @@ -1325,10 +1393,14 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } } - private void classDeclarator() throws CoreException { + private void classDeclarator(TypeDeclaration typeDecl) throws CoreException { //identifier //identifier 'extends' identifier + if (token == TokenNameIdentifier) { + typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); + typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); + typeDecl.name = scanner.getCurrentIdentifierSource(); getNextToken(); if (token == TokenNameextends) { do { @@ -1336,19 +1408,30 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { if (token == TokenNameIdentifier) { getNextToken(); } else { - throwSyntaxError("ClassDeclaration name expected after keyword 'extends'."); + reportSyntaxError("Class name expected after keyword 'extends'.", scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition()); + // throwSyntaxError("ClassDeclaration name expected after keyword 'extends'."); } } while (token == TokenNameCOMMA); - } + } } else { + typeDecl.sourceStart = scanner.getCurrentTokenStartPosition(); + typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); + if (token > TokenNameKEYWORD) { - throwSyntaxError("Don't use keyword for class declaration [" + token + "]."); - } - throwSyntaxError("ClassDeclaration name expected after keyword 'class'."); + typeDecl.name = scanner.getCurrentIdentifierSource(); + reportSyntaxError( + "Don't use keyword for class declaration [" + scanner.toStringAction(token) + "].", + typeDecl.sourceStart, + typeDecl.sourceEnd); + // throwSyntaxError("Don't use keyword for class declaration [" + token + "]."); + } + typeDecl.name = new char[] { ' ' }; + reportSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd); + // throwSyntaxError("ClassDeclaration name expected after keyword 'class'."); } } - private void classBody() throws CoreException { + private void classBody(TypeDeclaration typeDecl) throws CoreException { //'{' [class-element-list] '}' if (token == TokenNameLBRACE) { getNextToken(); @@ -1356,6 +1439,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { classElementList(); } if (token == TokenNameRBRACE) { + typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition(); getNextToken(); } else { throwSyntaxError("'}' expected at end of class body."); @@ -1375,8 +1459,10 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { //class-property //function-definition if (token == TokenNamefunction) { + MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult); + methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition(); getNextToken(); - functionDefinition(); + functionDefinition(methodDecl); } else if (token == TokenNamevar) { getNextToken(); classProperty(); @@ -1413,17 +1499,36 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } } - private void functionDefinition() throws CoreException { - functionDeclarator(); - compoundStatement(); + private void functionDefinition(MethodDeclaration methodDecl) throws CoreException { + if (astPtr == 0) { + compilationUnit.types.add(methodDecl); + } else { + AstNode node = astStack[astPtr]; + if (node instanceof TypeDeclaration) { + TypeDeclaration typeDecl = ((TypeDeclaration) node); + if (typeDecl.methods == null) { + typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl }; + } else { + AbstractMethodDeclaration[] newMethods; + System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1, typeDecl.methods.length); + newMethods[0] = methodDecl; + typeDecl.methods = newMethods; + } + } + } + functionDeclarator(methodDecl); + functionBody(methodDecl); } - private void functionDeclarator() throws CoreException { + private void functionDeclarator(MethodDeclaration methodDecl) throws CoreException { //identifier '(' [parameter-list] ')' if (token == TokenNameAND) { getNextToken(); } if (token == TokenNameIdentifier) { + methodDecl.sourceStart = scanner.getCurrentTokenStartPosition(); + methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition(); + methodDecl.selector = scanner.getCurrentIdentifierSource(); getNextToken(); if (token == TokenNameLPAREN) { getNextToken(); @@ -1436,6 +1541,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { if (token != TokenNameRPAREN) { throwSyntaxError("')' expected in function declaration."); } else { + methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1; getNextToken(); } } else { @@ -1938,12 +2044,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { expressionList(); if (token != TokenNameRPAREN) { throwSyntaxError( - "')' expected after identifier '" - + new String(ident) - + "' in postfix-expression." - + "(Found token: " - + scanner.toStringAction(token) - + ")"); + "')' expected after identifier '" + new String(ident) + "' in postfix-expression." + "(Found token: " + scanner.toStringAction(token) + ")"); } } getNextToken(); @@ -2137,10 +2238,7 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { // '@' '&' '*' '+' '-' '~' '!' case TokenNameAT : getNextToken(); - if (token == TokenNameinclude - || token == TokenNameinclude_once - || token == TokenNamerequire - || token == TokenNamerequire_once) { + if (token == TokenNameinclude || token == TokenNameinclude_once || token == TokenNamerequire || token == TokenNamerequire_once) { statement(TokenNameAT); } else { postfixExpression(); // castExpression(); @@ -2527,4 +2625,546 @@ public class Parser extends PHPParserSuperclass implements ITerminalSymbols { } } + public void reportSyntaxError() { //int act, int currentKind, int stateStackTop) { + + /* remember current scanner position */ + int startPos = scanner.startPosition; + int currentPos = scanner.currentPosition; + + // String[] expectings; + // String tokenName = name[symbol_index[currentKind]]; + + //fetch all "accurate" possible terminals that could recover the error + // int start, end = start = asi(stack[stateStackTop]); + // while (asr[end] != 0) + // end++; + // int length = end - start; + // expectings = new String[length]; + // if (length != 0) { + // char[] indexes = new char[length]; + // System.arraycopy(asr, start, indexes, 0, length); + // for (int i = 0; i < length; i++) { + // expectings[i] = name[symbol_index[indexes[i]]]; + // } + // } + + //if the pb is an EOF, try to tell the user that they are some + // if (tokenName.equals(UNEXPECTED_EOF)) { + // if (!this.checkAndReportBracketAnomalies(problemReporter())) { + // char[] tokenSource; + // try { + // tokenSource = this.scanner.getCurrentTokenSource(); + // } catch (Exception e) { + // tokenSource = new char[] {}; + // } + // problemReporter().parseError( + // this.scanner.startPosition, + // this.scanner.currentPosition - 1, + // tokenSource, + // tokenName, + // expectings); + // } + // } else { //the next test is HEAVILY grammar DEPENDENT. + // if ((length == 14) + // && (expectings[0] == "=") //$NON-NLS-1$ + // && (expectings[1] == "*=") //$NON-NLS-1$ + // && (expressionPtr > -1)) { + // switch(currentKind) { + // case TokenNameSEMICOLON: + // case TokenNamePLUS: + // case TokenNameMINUS: + // case TokenNameDIVIDE: + // case TokenNameREMAINDER: + // case TokenNameMULTIPLY: + // case TokenNameLEFT_SHIFT: + // case TokenNameRIGHT_SHIFT: + //// case TokenNameUNSIGNED_RIGHT_SHIFT: + // case TokenNameLESS: + // case TokenNameGREATER: + // case TokenNameLESS_EQUAL: + // case TokenNameGREATER_EQUAL: + // case TokenNameEQUAL_EQUAL: + // case TokenNameNOT_EQUAL: + // case TokenNameXOR: + // case TokenNameAND: + // case TokenNameOR: + // case TokenNameOR_OR: + // case TokenNameAND_AND: + // // the ; is not the expected token ==> it ends a statement when an expression is not ended + // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]); + // break; + // case TokenNameRBRACE : + // problemReporter().missingSemiColon(expressionStack[expressionPtr]); + // break; + // default: + // char[] tokenSource; + // try { + // tokenSource = this.scanner.getCurrentTokenSource(); + // } catch (Exception e) { + // tokenSource = new char[] {}; + // } + // problemReporter().parseError( + // this.scanner.startPosition, + // this.scanner.currentPosition - 1, + // tokenSource, + // tokenName, + // expectings); + // this.checkAndReportBracketAnomalies(problemReporter()); + // } + // } else { + char[] tokenSource; + try { + tokenSource = this.scanner.getCurrentTokenSource(); + } catch (Exception e) { + tokenSource = new char[] { + }; + } + // problemReporter().parseError( + // this.scanner.startPosition, + // this.scanner.currentPosition - 1, + // tokenSource, + // tokenName, + // expectings); + this.checkAndReportBracketAnomalies(problemReporter()); + // } + // } + /* reset scanner where it was */ + scanner.startPosition = startPos; + scanner.currentPosition = currentPos; + } + public static final int RoundBracket = 0; + public static final int SquareBracket = 1; + public static final int CurlyBracket = 2; + public static final int BracketKinds = 3; + + protected int[] nestedMethod; //the ptr is nestedType + protected int nestedType, dimensions; + //ast stack + final static int AstStackIncrement = 100; + protected int astPtr; + protected AstNode[] astStack = new AstNode[AstStackIncrement]; + protected int astLengthPtr; + protected int[] astLengthStack; + AstNode[] noAstNodes = new AstNode[AstStackIncrement]; + + public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/ + protected ReferenceContext referenceContext; + protected ProblemReporter problemReporter; + // protected CompilationResult compilationResult; + + /** + * Returns this parser's problem reporter initialized with its reference context. + * Also it is assumed that a problem is going to be reported, so initializes + * the compilation result's line positions. + */ + public ProblemReporter problemReporter() { + if (scanner.recordLineSeparator) { + compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); + } + problemReporter.referenceContext = referenceContext; + return problemReporter; + } + /* + * Reconsider the entire source looking for inconsistencies in {} () [] + */ + public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) { + + scanner.wasAcr = false; + boolean anomaliesDetected = false; + try { + char[] source = scanner.source; + int[] leftCount = { 0, 0, 0 }; + int[] rightCount = { 0, 0, 0 }; + int[] depths = { 0, 0, 0 }; + int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] }; + int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] }; + int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] }; + int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] }; + scanner.currentPosition = scanner.initialPosition; //starting point (first-zero-based char) + while (scanner.currentPosition < scanner.eofPosition) { //loop for jumping over comments + try { + // ---------Consume white space and handles startPosition--------- + boolean isWhiteSpace; + do { + scanner.startPosition = scanner.currentPosition; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace(); + // } else { + if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) { + if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) { + // only record line positions we have not recorded yet + scanner.pushLineSeparator(); + } + } + isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter); + // } + } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition)); + + // -------consume token until } is found--------- + + switch (scanner.currentCharacter) { + case '{' : + { + int index = leftCount[CurlyBracket]++; + if (index == leftPositions[CurlyBracket].length) { + System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index); + System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index); + } + leftPositions[CurlyBracket][index] = scanner.startPosition; + leftDepths[CurlyBracket][index] = depths[CurlyBracket]++; + } + break; + case '}' : + { + int index = rightCount[CurlyBracket]++; + if (index == rightPositions[CurlyBracket].length) { + System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index); + System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index); + } + rightPositions[CurlyBracket][index] = scanner.startPosition; + rightDepths[CurlyBracket][index] = --depths[CurlyBracket]; + } + break; + case '(' : + { + int index = leftCount[RoundBracket]++; + if (index == leftPositions[RoundBracket].length) { + System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index); + System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index); + } + leftPositions[RoundBracket][index] = scanner.startPosition; + leftDepths[RoundBracket][index] = depths[RoundBracket]++; + } + break; + case ')' : + { + int index = rightCount[RoundBracket]++; + if (index == rightPositions[RoundBracket].length) { + System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index); + System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index); + } + rightPositions[RoundBracket][index] = scanner.startPosition; + rightDepths[RoundBracket][index] = --depths[RoundBracket]; + } + break; + case '[' : + { + int index = leftCount[SquareBracket]++; + if (index == leftPositions[SquareBracket].length) { + System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index); + System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index); + } + leftPositions[SquareBracket][index] = scanner.startPosition; + leftDepths[SquareBracket][index] = depths[SquareBracket]++; + } + break; + case ']' : + { + int index = rightCount[SquareBracket]++; + if (index == rightPositions[SquareBracket].length) { + System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index); + System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index); + } + rightPositions[SquareBracket][index] = scanner.startPosition; + rightDepths[SquareBracket][index] = --depths[SquareBracket]; + } + break; + case '\'' : + { + if (scanner.getNextChar('\\')) { + scanner.scanEscapeCharacter(); + } else { // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; + } + // } + } + scanner.getNextChar('\''); + break; + } + case '"' : // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; + } + // } + while (scanner.currentCharacter != '"') { + if (scanner.currentCharacter == '\r') { + if (source[scanner.currentPosition] == '\n') + scanner.currentPosition++; + break; // the string cannot go further that the line + } + if (scanner.currentCharacter == '\n') { + break; // the string cannot go further that the line + } + if (scanner.currentCharacter == '\\') { + scanner.scanEscapeCharacter(); + } + // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; + } + // } + } + break; + case '/' : + { + int test; + if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment + //get the next char + if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + //-------------unicode traitement ------------ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + scanner.currentPosition++; + while (source[scanner.currentPosition] == 'u') { + scanner.currentPosition++; + } + if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c1 < 0 + || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c2 < 0 + || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c3 < 0 + || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c4 < 0) { //error don't care of the value + scanner.currentCharacter = 'A'; + } //something different from \n and \r + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); + } + } + while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') { + //get the next char + scanner.startPosition = scanner.currentPosition; + if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + //-------------unicode traitement ------------ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + scanner.currentPosition++; + while (source[scanner.currentPosition] == 'u') { + scanner.currentPosition++; + } + if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c1 < 0 + || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c2 < 0 + || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c3 < 0 + || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c4 < 0) { //error don't care of the value + scanner.currentCharacter = 'A'; + } //something different from \n and \r + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); + } + } + } + if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) { + if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) { + // only record line positions we have not recorded yet + scanner.pushLineSeparator(); + if (this.scanner.taskTags != null) { + this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); + } + } + } + break; + } + if (test > 0) { //traditional and annotation comment + boolean star = false; + // consume next character + scanner.unicodeAsBackSlash = false; + // if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + // scanner.getNextUnicodeChar(); + // } else { + if (scanner.withoutUnicodePtr != 0) { + scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter; + } + // } + if (scanner.currentCharacter == '*') { + star = true; + } + //get the next char + if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + //-------------unicode traitement ------------ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + scanner.currentPosition++; + while (source[scanner.currentPosition] == 'u') { + scanner.currentPosition++; + } + if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c1 < 0 + || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c2 < 0 + || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c3 < 0 + || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c4 < 0) { //error don't care of the value + scanner.currentCharacter = 'A'; + } //something different from * and / + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); + } + } + //loop until end of comment */ + while ((scanner.currentCharacter != '/') || (!star)) { + star = scanner.currentCharacter == '*'; + //get next char + if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) { + //-------------unicode traitement ------------ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + scanner.currentPosition++; + while (source[scanner.currentPosition] == 'u') { + scanner.currentPosition++; + } + if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c1 < 0 + || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c2 < 0 + || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c3 < 0 + || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 + || c4 < 0) { //error don't care of the value + scanner.currentCharacter = 'A'; + } //something different from * and / + else { + scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); + } + } + } + if (this.scanner.taskTags != null) { + this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()); + } + break; + } + break; + } + default : + if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) { + scanner.scanIdentifierOrKeyword(false); + break; + } + if (Character.isDigit(scanner.currentCharacter)) { + scanner.scanNumber(false); + break; + } + } + //-----------------end switch while try-------------------- + } catch (IndexOutOfBoundsException e) { + break; // read until EOF + } catch (InvalidInputException e) { + return false; // no clue + } + } + if (scanner.recordLineSeparator) { + // compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); + } + + // check placement anomalies against other kinds of brackets + for (int kind = 0; kind < BracketKinds; kind++) { + for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) { + int start = leftPositions[kind][leftIndex]; // deepest first + // find matching closing bracket + int depth = leftDepths[kind][leftIndex]; + int end = -1; + for (int i = 0; i < rightCount[kind]; i++) { + int pos = rightPositions[kind][i]; + // want matching bracket further in source with same depth + if ((pos > start) && (depth == rightDepths[kind][i])) { + end = pos; + break; + } + } + if (end < 0) { // did not find a good closing match + problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); + return true; + } + // check if even number of opening/closing other brackets in between this pair of brackets + int balance = 0; + for (int otherKind = 0;(balance == 0) && (otherKind < BracketKinds); otherKind++) { + for (int i = 0; i < leftCount[otherKind]; i++) { + int pos = leftPositions[otherKind][i]; + if ((pos > start) && (pos < end)) + balance++; + } + for (int i = 0; i < rightCount[otherKind]; i++) { + int pos = rightPositions[otherKind][i]; + if ((pos > start) && (pos < end)) + balance--; + } + if (balance != 0) { + problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly + return true; + } + } + } + // too many opening brackets ? + for (int i = rightCount[kind]; i < leftCount[kind]; i++) { + anomaliesDetected = true; + problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, compilationUnit.compilationResult); + } + // too many closing brackets ? + for (int i = leftCount[kind]; i < rightCount[kind]; i++) { + anomaliesDetected = true; + problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult); + } + if (anomaliesDetected) + return true; + } + + return anomaliesDetected; + } catch (ArrayStoreException e) { // jdk1.2.2 jit bug + return anomaliesDetected; + } catch (NullPointerException e) { // jdk1.2.2 jit bug + return anomaliesDetected; + } + } + + protected void pushOnAstLengthStack(int pos) { + try { + astLengthStack[++astLengthPtr] = pos; + } catch (IndexOutOfBoundsException e) { + int oldStackLength = astLengthStack.length; + int[] oldPos = astLengthStack; + astLengthStack = new int[oldStackLength + StackIncrement]; + System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength); + astLengthStack[astLengthPtr] = pos; + } + } + + protected void pushOnAstStack(AstNode node) { + /*add a new obj on top of the ast stack + astPtr points on the top*/ + + try { + astStack[++astPtr] = node; + } catch (IndexOutOfBoundsException e) { + int oldStackLength = astStack.length; + AstNode[] oldStack = astStack; + astStack = new AstNode[oldStackLength + AstStackIncrement]; + System.arraycopy(oldStack, 0, astStack, 0, oldStackLength); + astPtr = oldStackLength; + astStack[astPtr] = node; + } + + try { + astLengthStack[++astLengthPtr] = 1; + } catch (IndexOutOfBoundsException e) { + int oldStackLength = astLengthStack.length; + int[] oldPos = astLengthStack; + astLengthStack = new int[oldStackLength + AstStackIncrement]; + System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength); + astLengthStack[astLengthPtr] = 1; + } + } } \ No newline at end of file