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 &lt;?=
+   */
+  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 &lt;?=
+			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