Added PHPUnitEditor and corresponding PHPPreferencePage
[phpeclipse.git] / net.sourceforge.phpeclipse / src / test / PHPParser.jj
index 21cdb6f..bb3d533 100644 (file)
@@ -30,6 +30,7 @@ import org.eclipse.jface.preference.IPreferenceStore;
 
 import java.util.Hashtable;
 import java.io.StringReader;
+import java.io.*;
 import java.text.MessageFormat;
 
 import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
@@ -50,6 +51,7 @@ import net.sourceforge.phpdt.internal.compiler.parser.PHPReqIncDeclaration;
  */
 public final class PHPParser extends PHPParserSuperclass {
 
+  /** The file that is parsed. */
   private static IFile fileToParse;
 
   /** The current segment */
@@ -58,9 +60,15 @@ public final class PHPParser extends PHPParserSuperclass {
   private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
   private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
   PHPOutlineInfo outlineInfo;
+
+  /** The error level of the current ParseException. */
   private static int errorLevel = ERROR;
+  /** The message of the current ParseException. If it's null it's because the parse exception wasn't handled */
   private static String errorMessage;
 
+  private static int errorStart = -1;
+  private static int errorEnd = -1;
+
   public PHPParser() {
   }
 
@@ -83,6 +91,21 @@ public final class PHPParser extends PHPParserSuperclass {
     phpTest();
   }
 
+  public static final void htmlParserTester(final File fileName) throws CoreException, ParseException {
+    try {
+      final Reader stream = new FileReader(fileName);
+      if (jj_input_stream == null) {
+        jj_input_stream = new SimpleCharStream(stream, 1, 1);
+      }
+      ReInit(stream);
+      phpFile();
+    } catch (FileNotFoundException e) {
+      e.printStackTrace();  //To change body of catch statement use Options | File Templates.
+    } catch (ParseException e) {
+      e.printStackTrace();  //To change body of catch statement use Options | File Templates.
+    }
+  }
+
   public static final void htmlParserTester(final String strEval) throws CoreException, ParseException {
     final StringReader stream = new StringReader(strEval);
     if (jj_input_stream == null) {
@@ -117,6 +140,8 @@ public final class PHPParser extends PHPParserSuperclass {
     if (errorMessage == null) {
       PHPeclipsePlugin.log(e);
       errorMessage = "this exception wasn't handled by the parser please tell us how to reproduce it";
+      errorStart = jj_input_stream.getPosition();
+      errorEnd   = errorStart + 1;
     }
     setMarker(e);
     errorMessage = null;
@@ -128,12 +153,23 @@ public final class PHPParser extends PHPParserSuperclass {
    */
   private static void setMarker(final ParseException e) {
     try {
-      setMarker(fileToParse,
-                errorMessage,
-                jj_input_stream.tokenBegin,
-                jj_input_stream.tokenBegin + e.currentToken.image.length(),
-                errorLevel,
-                "Line " + e.currentToken.beginLine);
+      if (errorStart == -1) {
+        setMarker(fileToParse,
+                  errorMessage,
+                  jj_input_stream.tokenBegin,
+                  jj_input_stream.tokenBegin + e.currentToken.image.length(),
+                  errorLevel,
+                  "Line " + e.currentToken.beginLine);
+      } else {
+        setMarker(fileToParse,
+                  errorMessage,
+                  errorStart,
+                  errorEnd,
+                  errorLevel,
+                  "Line " + e.currentToken.beginLine);
+        errorStart = -1;
+        errorEnd = -1;
+      }
     } catch (CoreException e2) {
       PHPeclipsePlugin.log(e2);
     }
@@ -249,9 +285,9 @@ PARSER_END(PHPParser)
 
 <DEFAULT> TOKEN :
 {
-  <PHPSTARTSHORT : "<?"> : PHPPARSING
+  <PHPSTARTSHORT : "<?">   : PHPPARSING
 | <PHPSTARTLONG : "<?php"> : PHPPARSING
-| <PHPECHOSTART : "<?=">      : PHPPARSING
+| <PHPECHOSTART : "<?=">   : PHPPARSING
 }
 
 <PHPPARSING> TOKEN :
@@ -280,7 +316,9 @@ PARSER_END(PHPParser)
 
 <PHPPARSING> SPECIAL_TOKEN :
 {
-  "//" | "#" : IN_SINGLE_LINE_COMMENT
+  "//" : IN_SINGLE_LINE_COMMENT
+|
+  "#"  : IN_SINGLE_LINE_COMMENT
 |
   <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
 |
@@ -572,7 +610,7 @@ void phpFile() :
 
 void PhpBlock() :
 {
-  final int start = jj_input_stream.bufpos;
+  final int start = jj_input_stream.getPosition();
 }
 {
   <PHPECHOSTART> Expression() [ <SEMICOLON> ] <PHPEND>
@@ -583,7 +621,7 @@ void PhpBlock() :
       setMarker(fileToParse,
                 "You should use '<?php' instead of '<?' it will avoid some problems with XML",
                 start,
-                jj_input_stream.bufpos,
+                jj_input_stream.getPosition(),
                 INFO,
                 "Line " + token.beginLine);
     } catch (CoreException e) {
@@ -596,6 +634,8 @@ void PhpBlock() :
   } catch (ParseException e) {
     errorMessage = "'?>' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -610,10 +650,32 @@ void ClassDeclaration() :
 {
   final PHPClassDeclaration classDeclaration;
   final Token className;
-  final int pos = jj_input_stream.bufpos;
+  final int pos;
 }
 {
-  <CLASS> className = <IDENTIFIER> [ <EXTENDS> <IDENTIFIER> ]
+  <CLASS>
+  try {
+    {pos = jj_input_stream.getPosition();}
+    className = <IDENTIFIER>
+  } catch (ParseException e) {
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected";
+    errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
+    throw e;
+  }
+  [
+    <EXTENDS>
+    try {
+      <IDENTIFIER>
+    } catch (ParseException e) {
+      errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected";
+      errorLevel   = ERROR;
+      errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+      errorEnd   = jj_input_stream.getPosition() + 1;
+      throw e;
+    }
+  ]
   {
     if (currentSegment != null) {
       classDeclaration = new PHPClassDeclaration(currentSegment,className.image,pos);
@@ -635,16 +697,20 @@ void ClassBody() :
   try {
     <LBRACE>
   } catch (ParseException e) {
-    errorMessage = "'{' expected";
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image + "', '{' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   ( ClassBodyDeclaration() )*
   try {
     <RBRACE>
   } catch (ParseException e) {
-    errorMessage = "'var', 'function' or '}' expected";
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', 'var', 'function' or '}' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -681,6 +747,8 @@ void FieldDeclaration() :
   } catch (ParseException e) {
     errorMessage = "';' expected after variable declaration";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -688,8 +756,8 @@ void FieldDeclaration() :
 PHPVarDeclaration VariableDeclarator() :
 {
   final String varName;
-  String varValue;
-  final int pos = jj_input_stream.bufpos;
+  final String varValue;
+  final int pos = jj_input_stream.getPosition();
 }
 {
   varName = VariableDeclaratorId()
@@ -701,6 +769,8 @@ PHPVarDeclaration VariableDeclarator() :
     } catch (ParseException e) {
       errorMessage = "Literal expression expected in variable initializer";
       errorLevel   = ERROR;
+      errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+      errorEnd   = jj_input_stream.getPosition() + 1;
       throw e;
     }
   ]
@@ -723,6 +793,8 @@ String VariableDeclaratorId() :
   } catch (ParseException e) {
     errorMessage = "'$' expected for variable identifier";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -765,13 +837,16 @@ final Token token;
   <DOLLAR> expr = VariableName()
   {return "$" + expr;}
 |
+  token = <DOLLAR_ID>
+  {return token.image + expr;}
+/*|      pas besoin ?
   token = <DOLLAR_ID> [expr = VariableName()]
   {
   if (expr == null) {
     return token.image;
   }
   return token.image + expr;
-  }
+  }*/
 }
 
 String VariableInitializer() :
@@ -841,6 +916,8 @@ void MethodDeclaration() :
     }
     errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function identifier expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   {
@@ -857,12 +934,16 @@ void MethodDeclaration() :
   }
 }
 
+/**
+ * A MethodDeclarator contains [&] IDENTIFIER(parameters ...).
+ * @return a function description for the outline
+ */
 PHPFunctionDeclaration MethodDeclarator() :
 {
   final Token identifier;
   final StringBuffer methodDeclaration = new StringBuffer();
   final String formalParameters;
-  final int pos = jj_input_stream.bufpos;
+  final int pos = jj_input_stream.getPosition();
 }
 {
   [ <BIT_AND> {methodDeclaration.append("&");} ]
@@ -886,7 +967,9 @@ String FormalParameters() :
   } catch (ParseException e) {
     errorMessage = "Formal parameter expected after function identifier";
     errorLevel   = ERROR;
-    jj_consume_token(token.kind);
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
+    throw e;
   }
             [ expr = FormalParameter()
               {buff.append(expr);}
@@ -900,6 +983,8 @@ String FormalParameters() :
   } catch (ParseException e) {
     errorMessage = "')' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
  {
@@ -974,6 +1059,8 @@ String Expression() :
     } catch (ParseException e) {
       errorMessage = "expression expected";
       errorLevel   = ERROR;
+      errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+      errorEnd   = jj_input_stream.getPosition() + 1;
       throw e;
     }
   ]
@@ -1155,7 +1242,15 @@ String EqualityExpression() :
     | operator = <BANGDOUBLEEQUAL>
     | operator = <TRIPLEEQUAL>
   )
-  expr = RelationalExpression()
+  try {
+    expr = RelationalExpression()
+  } catch (ParseException e) {
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', expression expected after '"+operator.image+"'";
+    errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
+    throw e;
+  }
   {
     buff.append(operator.image);
     buff.append(expr);
@@ -1224,7 +1319,15 @@ String MultiplicativeExpression() :
   Token operator;
   final StringBuffer buff = new StringBuffer();}
 {
-  expr = UnaryExpression()
+  try {
+    expr = UnaryExpression()
+  } catch (ParseException e) {
+    errorMessage = "unexpected token '"+e.currentToken.next.image+"'";
+    errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
+    throw e;
+  }
   {buff.append(expr);}
   (
   ( operator = <STAR> | operator = <SLASH> | operator = <REM> ) expr = UnaryExpression()
@@ -1322,6 +1425,8 @@ String UnaryExpressionNotPlusMinus() :
   } catch (ParseException e) {
     errorMessage = "')' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   {return "("+expr+")";}
@@ -1397,11 +1502,26 @@ String PrimaryPrefix() :
   {
     return "new " + expr;
   }
-|  
+|
   expr = VariableDeclaratorId()
   {return expr;}
 }
 
+String classInstantiation() :
+{
+  String expr;
+  final StringBuffer buff = new StringBuffer("new ");
+}
+{
+  <NEW> expr = ClassIdentifier()
+  {buff.append(expr);}
+  [
+    expr = PrimaryExpression()
+    {buff.append(expr);}
+  ]
+  {return buff.toString();}
+}
+
 String ClassIdentifier():
 {
   final String expr;
@@ -1438,6 +1558,8 @@ String VariableSuffix() :
   } catch (ParseException e) {
     errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function call or field access expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   {return "->" + expr;}
@@ -1448,6 +1570,8 @@ String VariableSuffix() :
   } catch (ParseException e) {
     errorMessage = "']' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   {
@@ -1508,6 +1632,8 @@ String expr = null;
   } catch (ParseException e) {
     errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected to close the argument list";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   {
@@ -1532,6 +1658,8 @@ final StringBuffer buff = new StringBuffer();
       } catch (ParseException e) {
         errorMessage = "expression expected after a comma in argument list";
         errorLevel   = ERROR;
+        errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+        errorEnd   = jj_input_stream.getPosition() + 1;
         throw e;
       }
     {
@@ -1550,10 +1678,12 @@ void StatementNoBreak() :
   LOOKAHEAD(2)
   Expression()
   try {
-    (<SEMICOLON> | <PHPEND>)
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 |
@@ -1570,6 +1700,8 @@ void StatementNoBreak() :
   } catch (ParseException e) {
     errorMessage = "';' expected after expression";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 |
@@ -1612,7 +1744,7 @@ void Statement() :
 void IncludeStatement() :
 {
   final String expr;
-  final int pos = jj_input_stream.bufpos;
+  final int pos = jj_input_stream.getPosition();
 }
 {
   <REQUIRE>
@@ -1623,10 +1755,12 @@ void IncludeStatement() :
     }
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 |
@@ -1638,10 +1772,12 @@ void IncludeStatement() :
     }
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 |
@@ -1653,10 +1789,12 @@ void IncludeStatement() :
     }
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 |
@@ -1668,10 +1806,12 @@ void IncludeStatement() :
     }
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -1701,6 +1841,8 @@ String ListExpression() :
   } catch (ParseException e) {
     errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', '(' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   [
@@ -1713,6 +1855,8 @@ String ListExpression() :
     } catch (ParseException e) {
       errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ',' expected";
       errorLevel   = ERROR;
+      errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+      errorEnd   = jj_input_stream.getPosition() + 1;
       throw e;
     }
     expr = VariableDeclaratorId()
@@ -1724,6 +1868,8 @@ String ListExpression() :
   } catch (ParseException e) {
     errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   [ <ASSIGN> expr = Expression() {buff.append("(").append(expr);}]
@@ -1735,10 +1881,12 @@ void EchoStatement() :
 {
   <ECHO> Expression() (<COMMA> Expression())*
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected after 'echo' statement";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -1748,10 +1896,12 @@ void GlobalStatement() :
 {
   <GLOBAL> VariableDeclaratorId() (<COMMA> VariableDeclaratorId())*
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -1761,10 +1911,12 @@ void StaticStatement() :
 {
   <STATIC> VariableDeclarator() (<COMMA> VariableDeclarator())*
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -1783,6 +1935,8 @@ void Block() :
   } catch (ParseException e) {
     errorMessage = "'{' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   ( BlockStatement() )*
@@ -1791,6 +1945,8 @@ void Block() :
   } catch (ParseException e) {
     errorMessage = "unexpected token : '"+ e.currentToken.image +"', '}' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -1865,6 +2021,8 @@ void SwitchStatement() :
   } catch (ParseException e) {
     errorMessage = "'(' expected after 'switch'";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   Expression()
@@ -1873,6 +2031,8 @@ void SwitchStatement() :
   } catch (ParseException e) {
     errorMessage = "')' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   try {
@@ -1880,20 +2040,14 @@ void SwitchStatement() :
   } catch (ParseException e) {
     errorMessage = "'{' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
     (
       line = SwitchLabel()
       ( BlockStatementNoBreak() )*
-      [ breakToken = <BREAK>
-        try {
-          <SEMICOLON>
-        } catch (ParseException e) {
-          errorMessage = "';' expected after 'break' keyword";
-          errorLevel   = ERROR;
-          throw e;
-        }
-      ]
+      [ breakToken = BreakStatement() ]
       {
         try {
           if (breakToken == null) {
@@ -1913,10 +2067,30 @@ void SwitchStatement() :
   } catch (ParseException e) {
     errorMessage = "'}' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
 
+Token BreakStatement() :
+{
+  final Token token;
+}
+{
+  token = <BREAK> [ Expression() ]
+  try {
+    <SEMICOLON>
+  } catch (ParseException e) {
+    errorMessage = "';' expected after 'break' keyword";
+    errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
+    throw e;
+  }
+  {return token;}
+}
+
 int SwitchLabel() :
 {
   final Token token;
@@ -1929,6 +2103,8 @@ int SwitchLabel() :
     if (errorMessage != null) throw e;
     errorMessage = "expression expected after 'case' keyword";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   try {
@@ -1936,6 +2112,8 @@ int SwitchLabel() :
   } catch (ParseException e) {
     errorMessage = "':' expected after case expression";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   {return token.beginLine;}
@@ -1946,6 +2124,8 @@ int SwitchLabel() :
   } catch (ParseException e) {
     errorMessage = "':' expected after 'default' keyword";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   {return token.beginLine;}
@@ -1954,7 +2134,7 @@ int SwitchLabel() :
 void IfStatement() :
 {
   final Token token;
-  final int pos = jj_input_stream.bufpos;
+  final int pos = jj_input_stream.getPosition();
 }
 {
   token = <IF> Condition("if") IfStatement0(pos,pos+token.image.length())
@@ -1968,7 +2148,9 @@ void Condition(final String keyword) :
   } catch (ParseException e) {
     errorMessage = "'(' expected after " + keyword + " keyword";
     errorLevel   = ERROR;
-    throw e;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length();
+    errorEnd   = errorStart +1;
+    processParseException(e);
   }
   Expression()
   try {
@@ -1976,6 +2158,8 @@ void Condition(final String keyword) :
   } catch (ParseException e) {
     errorMessage = "')' expected after " + keyword + " keyword";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -2000,6 +2184,8 @@ void IfStatement0(final int start,final int end) :
   } catch (ParseException e) {
     errorMessage = "'endif' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   try {
@@ -2007,6 +2193,8 @@ void IfStatement0(final int start,final int end) :
   } catch (ParseException e) {
     errorMessage = "';' expected after 'endif' keyword";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 |
@@ -2034,7 +2222,7 @@ void ElseIfStatement() :
 void WhileStatement() :
 {
   final Token token;
-  final int pos = jj_input_stream.bufpos;
+  final int pos = jj_input_stream.getPosition();
 }
 {
   token = <WHILE> Condition("while") WhileStatement0(pos,pos + token.image.length())
@@ -2059,13 +2247,17 @@ void WhileStatement0(final int start, final int end) :
   } catch (ParseException e) {
     errorMessage = "'endwhile' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected after 'endwhile' keyword";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 |
@@ -2077,10 +2269,12 @@ void DoStatement() :
 {
   <DO> Statement() <WHILE> Condition("while")
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -2094,6 +2288,8 @@ void ForeachStatement() :
   } catch (ParseException e) {
     errorMessage = "'(' expected after 'foreach' keyword";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   try {
@@ -2101,6 +2297,8 @@ void ForeachStatement() :
   } catch (ParseException e) {
     errorMessage = "variable expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   [ VariableSuffix() ]
@@ -2109,6 +2307,8 @@ void ForeachStatement() :
   } catch (ParseException e) {
     errorMessage = "'as' expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   try {
@@ -2116,6 +2316,8 @@ void ForeachStatement() :
   } catch (ParseException e) {
     errorMessage = "variable expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   [ <ARRAYASSIGN> Expression() ]
@@ -2124,6 +2326,8 @@ void ForeachStatement() :
   } catch (ParseException e) {
     errorMessage = "')' expected after 'foreach' keyword";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
   try {
@@ -2132,6 +2336,8 @@ void ForeachStatement() :
     if (errorMessage != null) throw e;
     errorMessage = "statement expected";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -2139,7 +2345,7 @@ void ForeachStatement() :
 void ForStatement() :
 {
 final Token token;
-final int pos = jj_input_stream.bufpos;
+final int pos = jj_input_stream.getPosition();
 }
 {
   token = <FOR>
@@ -2148,6 +2354,8 @@ final int pos = jj_input_stream.bufpos;
   } catch (ParseException e) {
     errorMessage = "'(' expected after 'for' keyword";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
      [ ForInit() ] <SEMICOLON> [ Expression() ] <SEMICOLON> [ StatementExpressionList() ] <RPAREN>
@@ -2172,6 +2380,8 @@ final int pos = jj_input_stream.bufpos;
       } catch (ParseException e) {
         errorMessage = "'endfor' expected";
         errorLevel   = ERROR;
+        errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+        errorEnd   = jj_input_stream.getPosition() + 1;
         throw e;
       }
       try {
@@ -2179,6 +2389,8 @@ final int pos = jj_input_stream.bufpos;
       } catch (ParseException e) {
         errorMessage = "';' expected after 'endfor' keyword";
         errorLevel   = ERROR;
+        errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+        errorEnd   = jj_input_stream.getPosition() + 1;
         throw e;
       }
     )
@@ -2199,19 +2411,6 @@ void StatementExpressionList() :
   StatementExpression() ( <COMMA> StatementExpression() )*
 }
 
-void BreakStatement() :
-{}
-{
-  <BREAK> [ <IDENTIFIER> ]
-  try {
-    <SEMICOLON>
-  } catch (ParseException e) {
-    errorMessage = "';' expected after 'break' statement";
-    errorLevel   = ERROR;
-    throw e;
-  }
-}
-
 void ContinueStatement() :
 {}
 {
@@ -2221,6 +2420,8 @@ void ContinueStatement() :
   } catch (ParseException e) {
     errorMessage = "';' expected after 'continue' statement";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
@@ -2234,6 +2435,8 @@ void ReturnStatement() :
   } catch (ParseException e) {
     errorMessage = "';' expected after 'return' statement";
     errorLevel   = ERROR;
+    errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1;
+    errorEnd   = jj_input_stream.getPosition() + 1;
     throw e;
   }
 }
\ No newline at end of file