From d85f520265d454d8f8b97563f2352f2fd869aecb Mon Sep 17 00:00:00 2001 From: axelcl <axelcl> Date: Tue, 20 Dec 2005 06:41:20 +0000 Subject: [PATCH 1/1] Fix bug #1385272: Improved version for "Parsing of short open tags not fully compatible to PHP parse" --- .../phpdt/core/compiler/ITerminalSymbols.java | 7 + .../phpdt/internal/compiler/parser/Parser.java | 34 ++++- .../phpdt/internal/compiler/parser/Scanner.java | 151 +------------------- 3 files changed, 40 insertions(+), 152 deletions(-) diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/ITerminalSymbols.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/ITerminalSymbols.java index df10d9f..6440ffd 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/ITerminalSymbols.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/ITerminalSymbols.java @@ -122,6 +122,13 @@ public interface ITerminalSymbols { public final static int TokenNameSQLset = 907; public final static int TokenNameSQLvalues = 908; // stop SQL token + + /** + * Special 0-length token for php short tag syntax; + * Detected directly after <?= + */ + public final static int TokenNameECHO_INVISIBLE = 990; + public final static int TokenNameKEYWORD = 1000; public final static int TokenNameif = 1001; public final static int TokenNameelseif = 1002; 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 2d17647..f79075c 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 @@ -456,10 +456,10 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI } if (token == TokenNameif || token == TokenNameswitch || token == TokenNamefor || token == TokenNamewhile || token == TokenNamedo || token == TokenNameforeach || token == TokenNamecontinue || token == TokenNamebreak - || token == TokenNamereturn || token == TokenNameexit || token == TokenNameecho || token == TokenNameglobal - || token == TokenNamestatic || token == TokenNameunset || token == TokenNamefunction || token == TokenNamedeclare - || token == TokenNametry || token == TokenNamecatch || token == TokenNamethrow || token == TokenNamefinal - || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) { + || token == TokenNamereturn || token == TokenNameexit || token == TokenNameecho || token == TokenNameECHO_INVISIBLE + || token == TokenNameglobal || token == TokenNamestatic || token == TokenNameunset || token == TokenNamefunction + || token == TokenNamedeclare || token == TokenNametry || token == TokenNamecatch || token == TokenNamethrow + || token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) { break; } // System.out.println(scanner.toStringAction(token)); @@ -751,6 +751,23 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI getNextToken(); } return statement; + } else if (token == TokenNameECHO_INVISIBLE) { + // 0-length token directly after PHP short tag <?= + getNextToken(); + expressionList(); + if (token == TokenNameSEMICOLON) { + getNextToken(); + if (token != TokenNameINLINE_HTML) { + // TODO should this become a configurable warning? + reportSyntaxError("Probably '?>' expected after PHP short tag expression (only the first expression will be echoed)."); + } + } else { + if (token != TokenNameINLINE_HTML) { + throwSyntaxError("';' expected after PHP short tag '<?=' expression."); + } + getNextToken(); + } + return statement; } else if (token == TokenNameINLINE_HTML) { getNextToken(); return statement; @@ -1726,7 +1743,8 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI if (token == TokenNameCOLON || token == TokenNameSEMICOLON) { getNextToken(); if (token == TokenNameRBRACE) { - // empty case; assumes that the '}' token belongs to the wrapping switch statement - #1371992 + // empty case; assumes that the '}' token belongs to the wrapping + // switch statement - #1371992 break; } if (token == TokenNamecase || token == TokenNamedefault) { @@ -1756,7 +1774,8 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI if (token == TokenNameCOLON || token == TokenNameSEMICOLON) { getNextToken(); if (token == TokenNameRBRACE) { - // empty default case; ; assumes that the '}' token belongs to the wrapping switch statement - #1371992 + // empty default case; ; assumes that the '}' token belongs to the + // wrapping switch statement - #1371992 break; } if (token != TokenNamecase) { @@ -3128,7 +3147,8 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI } getNextToken(); } else if (token == TokenNameLBRACKET) { - // To remove "ref = null;" here, is probably better than the patch commented in #1368081 - axelcl + // To remove "ref = null;" here, is probably better than the patch + // commented in #1368081 - axelcl getNextToken(); if (token != TokenNameRBRACKET) { expr(); diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java index a1e5351..803f878 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java @@ -1297,6 +1297,7 @@ public class Scanner implements IScanner, ITerminalSymbols { } else { if (fFillerToken != TokenNameEOF) { int tempToken; + startPosition = currentPosition; tempToken = fFillerToken; fFillerToken = TokenNameEOF; return tempToken; @@ -1310,154 +1311,14 @@ public class Scanner implements IScanner, ITerminalSymbols { try { while (true) { withoutUnicodePtr = 0; - // start with a new token - char encapsedChar = ' '; - // if (!encapsedStringStack.isEmpty()) { - // encapsedChar = ((Character) - // encapsedStringStack.peek()).charValue(); - // } - // if (encapsedChar != '$' && encapsedChar != ' ') { - // currentCharacter = source[currentPosition++]; - // if (currentCharacter == encapsedChar) { - // switch (currentCharacter) { - // case '`': - // return TokenNameEncapsedString0; - // case '\'': - // return TokenNameEncapsedString1; - // case '"': - // return TokenNameEncapsedString2; - // } - // } - // while (currentCharacter != encapsedChar) { - // /** ** in PHP \r and \n are valid in string literals *** */ - // switch (currentCharacter) { - // case '\\': - // int escapeSize = currentPosition; - // boolean backSlashAsUnicodeInString = unicodeAsBackSlash; - // //scanEscapeCharacter make a side effect on this value and - // // we need the previous value few lines down this one - // scanDoubleQuotedEscapeCharacter(); - // escapeSize = currentPosition - escapeSize; - // if (withoutUnicodePtr == 0) { - // //buffer all the entries that have been left aside.... - // withoutUnicodePtr = currentPosition - escapeSize - 1 - - // startPosition; - // System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, - // withoutUnicodePtr); - // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter; - // } else { //overwrite the / in the buffer - // withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter; - // if (backSlashAsUnicodeInString) { //there are TWO \ in - // withoutUnicodePtr--; - // } - // } - // break; - // case '\r': - // case '\n': - // if (recordLineSeparator) { - // pushLineSeparator(); - // } - // break; - // case '$': - // if (isPHPIdentifierStart(source[currentPosition]) || - // source[currentPosition] == '{') { - // currentPosition--; - // encapsedStringStack.push(new Character('$')); - // return TokenNameSTRING; - // } - // break; - // case '{': - // if (source[currentPosition] == '$') { // CURLY_OPEN - // currentPosition--; - // encapsedStringStack.push(new Character('$')); - // return TokenNameSTRING; - // } - // } - // // consume next character - // unicodeAsBackSlash = false; - // currentCharacter = source[currentPosition++]; - // if (withoutUnicodePtr != 0) { - // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter; - // } - // // } - // } // end while - // currentPosition--; - // return TokenNameSTRING; - // } // ---------Consume white space and handles startPosition--------- int whiteStart = currentPosition; startPosition = currentPosition; currentCharacter = source[currentPosition++]; - // if (encapsedChar == '$') { - // switch (currentCharacter) { - // case '\\': - // currentCharacter = source[currentPosition++]; - // return TokenNameSTRING; - // case '{': - // if (encapsedChar == '$') { - // if (getNextChar('$')) - // return TokenNameLBRACE_DOLLAR; - // } - // return TokenNameLBRACE; - // case '}': - // return TokenNameRBRACE; - // case '[': - // return TokenNameLBRACKET; - // case ']': - // return TokenNameRBRACKET; - // case '\'': - // if (tokenizeStrings) { - // consumeStringConstant(); - // return TokenNameStringSingleQuote; - // } - // return TokenNameEncapsedString1; - // case '"': - // return TokenNameEncapsedString2; - // case '`': - // if (tokenizeStrings) { - // consumeStringInterpolated(); - // return TokenNameStringInterpolated; - // } - // return TokenNameEncapsedString0; - // case '-': - // if (getNextChar('>')) - // return TokenNameMINUS_GREATER; - // return TokenNameSTRING; - // default: - // if (currentCharacter == '$') { - // int oldPosition = currentPosition; - // try { - // currentCharacter = source[currentPosition++]; - // if (currentCharacter == '{') { - // return TokenNameDOLLAR_LBRACE; - // } - // if (isPHPIdentifierStart(currentCharacter)) { - // return scanIdentifierOrKeyword(true); - // } else { - // currentPosition = oldPosition; - // return TokenNameSTRING; - // } - // } catch (IndexOutOfBoundsException e) { - // currentPosition = oldPosition; - // return TokenNameSTRING; - // } - // } - // if (isPHPIdentifierStart(currentCharacter)) - // return scanIdentifierOrKeyword(false); - // if (Character.isDigit(currentCharacter)) - // return scanNumber(false); - // return TokenNameERROR; - // } - // } - // boolean isWhiteSpace; while ((currentCharacter == ' ') || Character.isWhitespace(currentCharacter)) { startPosition = currentPosition; currentCharacter = source[currentPosition++]; - // if (((currentCharacter = source[currentPosition++]) == '\\') - // && (source[currentPosition] == 'u')) { - // isWhiteSpace = jumpOverUnicodeWhiteSpace(); - // } else { if ((currentCharacter == '\r') || (currentCharacter == '\n')) { checkNonExternalizeString(); if (recordLineSeparator) { @@ -1466,9 +1327,6 @@ public class Scanner implements IScanner, ITerminalSymbols { currentLine = null; } } - // isWhiteSpace = (currentCharacter == ' ') - // || Character.isWhitespace(currentCharacter); - // } } if (tokenizeWhiteSpace && (whiteStart != currentPosition - 1)) { // reposition scanner in case we are interested by spaces as tokens @@ -1983,14 +1841,14 @@ public class Scanner implements IScanner, ITerminalSymbols { if (lookAheadLinePHPTag() == TokenNameINLINE_HTML) { phpMode = true; if (phpShortTag) { - fFillerToken = TokenNameecho; + fFillerToken = TokenNameECHO_INVISIBLE; } return TokenNameINLINE_HTML; } } else { phpMode = true; if (phpShortTag) { - fFillerToken = TokenNameecho; + fFillerToken = TokenNameECHO_INVISIBLE; } return TokenNameINLINE_HTML; } @@ -3880,6 +3738,9 @@ public class Scanner implements IScanner, ITerminalSymbols { // //$NON-NLS-1$ case TokenNameINLINE_HTML: return "Inline-HTML(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + case TokenNameECHO_INVISIBLE: + //0-length token + return ""; case TokenNameIdentifier: return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ case TokenNameVariable: -- 1.7.1