added new error messages for keywords function, class
[phpeclipse.git] / net.sourceforge.phpeclipse / src / test / PHPParser.jj
index 34ee7b7..b49b15a 100644 (file)
@@ -50,6 +50,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 +59,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() {
   }
 
@@ -128,12 +135,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 +267,9 @@ PARSER_END(PHPParser)
 
 <DEFAULT> TOKEN :
 {
-  <PHPSTARTSHORT : "<?"> : PHPPARSING
+  <PHPSTARTSHORT : "<?">   : PHPPARSING
 | <PHPSTARTLONG : "<?php"> : PHPPARSING
-| <PHPECHOSTART : "<?=">      : PHPPARSING
+| <PHPECHOSTART : "<?=">   : PHPPARSING
 }
 
 <PHPPARSING> TOKEN :
@@ -282,6 +300,8 @@ PARSER_END(PHPParser)
 {
   "//" : IN_SINGLE_LINE_COMMENT
 |
+  "#"  : IN_SINGLE_LINE_COMMENT
+|
   <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
 |
   "/*" : IN_MULTI_LINE_COMMENT
@@ -344,6 +364,10 @@ MORE :
 | <ARRAYASSIGN        : "=>">
 }
 
+<PHPPARSING> TOKEN :
+{
+  <LIST   : "list">
+}
 /* RESERVED WORDS AND LITERALS */
 
 <PHPPARSING> TOKEN :
@@ -574,18 +598,19 @@ void PhpBlock() :
   <PHPECHOSTART> Expression() [ <SEMICOLON> ] <PHPEND>
 |
   [ <PHPSTARTLONG>
-  | <PHPSTARTSHORT>
-  {try {
-    setMarker(fileToParse,
-              "You should use '<?php' instead of '<?' it will avoid some problems with XML",
-              start,
-              jj_input_stream.bufpos,
-              INFO,
-              "Line " + token.beginLine);
-  } catch (CoreException e) {
-    PHPeclipsePlugin.log(e);
-  }}
-  ]Php()
+    | <PHPSTARTSHORT>
+    {try {
+      setMarker(fileToParse,
+                "You should use '<?php' instead of '<?' it will avoid some problems with XML",
+                start,
+                jj_input_stream.bufpos,
+                INFO,
+                "Line " + token.beginLine);
+    } catch (CoreException e) {
+      PHPeclipsePlugin.log(e);
+    }}
+  ]
+  Php()
   try {
     <PHPEND>
   } catch (ParseException e) {
@@ -605,10 +630,28 @@ 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.bufpos;}
+    className = <IDENTIFIER>
+  } catch (ParseException e) {
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
+  [
+    <EXTENDS>
+    try {
+      <IDENTIFIER>
+    } catch (ParseException e) {
+      errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected";
+      errorLevel   = ERROR;
+      throw e;
+    }
+  ]
   {
     if (currentSegment != null) {
       classDeclaration = new PHPClassDeclaration(currentSegment,className.image,pos);
@@ -683,7 +726,7 @@ void FieldDeclaration() :
 PHPVarDeclaration VariableDeclarator() :
 {
   final String varName;
-  String varValue = null;
+  String varValue;
   final int pos = jj_input_stream.bufpos;
 }
 {
@@ -827,7 +870,17 @@ void MethodDeclaration() :
   final PHPFunctionDeclaration functionDeclaration;
 }
 {
-  <FUNCTION> functionDeclaration = MethodDeclarator()
+  <FUNCTION>
+  try {
+    functionDeclaration = MethodDeclarator()
+  } catch (ParseException e) {
+    if (errorMessage != null) {
+      throw e;
+    }
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function identifier expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
   {
     if (currentSegment != null) {
       currentSegment.add(functionDeclaration);
@@ -947,6 +1000,9 @@ String Expression() :
   expr = PrintExpression()
   {return expr;}
 |
+  expr = ListExpression()
+  {return expr;}
+|
   expr = ConditionalExpression()
   [
     assignOperator = AssignmentOperator()
@@ -1137,7 +1193,13 @@ 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;
+    throw e;
+  }
   {
     buff.append(operator.image);
     buff.append(expr);
@@ -1298,7 +1360,14 @@ String UnaryExpressionNotPlusMinus() :
   expr = Literal()
   {return expr;}
 |
-  <LPAREN> expr = Expression()<RPAREN>
+  <LPAREN> expr = Expression()
+  try {
+    <RPAREN>
+  } catch (ParseException e) {
+    errorMessage = "')' expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
   {return "("+expr+")";}
 }
 
@@ -1407,7 +1476,14 @@ String VariableSuffix() :
   String expr = null;
 }
 {
-  <CLASSACCESS> expr = VariableName()
+  <CLASSACCESS>
+  try {
+    expr = VariableName()
+  } catch (ParseException e) {
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function call or field access expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
   {return "->" + expr;}
 | 
   <LBRACKET> [ expr = Expression() ]
@@ -1474,7 +1550,7 @@ String expr = null;
   try {
     <RPAREN>
   } catch (ParseException e) {
-    errorMessage = "')' expected to close the argument list";
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected to close the argument list";
     errorLevel   = ERROR;
     throw e;
   }
@@ -1509,17 +1585,16 @@ final StringBuffer buff = new StringBuffer();
    {return buff.toString();}
 }
 
-/*
- * Statement syntax follows.
+/**
+ * A Statement without break
  */
-
-void Statement() :
+void StatementNoBreak() :
 {}
 {
   LOOKAHEAD(2)
   Expression()
   try {
-    (<SEMICOLON> | <PHPEND>)
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
@@ -1554,8 +1629,6 @@ void Statement() :
 |
   ForeachStatement()
 |
-  BreakStatement()
-|
   ContinueStatement()
 |
   ReturnStatement()
@@ -1569,6 +1642,17 @@ void Statement() :
   GlobalStatement()
 }
 
+/**
+ * A Normal statement
+ */
+void Statement() :
+{}
+{
+  StatementNoBreak()
+|
+  BreakStatement()
+}
+
 void IncludeStatement() :
 {
   final String expr;
@@ -1583,7 +1667,7 @@ void IncludeStatement() :
     }
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
@@ -1598,7 +1682,7 @@ void IncludeStatement() :
     }
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
@@ -1613,7 +1697,7 @@ void IncludeStatement() :
     }
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
@@ -1628,7 +1712,7 @@ void IncludeStatement() :
     }
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
@@ -1649,12 +1733,53 @@ String PrintExpression() :
   }
 }
 
+String ListExpression() :
+{
+  final StringBuffer buff = new StringBuffer("list(");
+  String expr;
+}
+{
+  <LIST>
+  try {
+    <LPAREN>
+  } catch (ParseException e) {
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', '(' expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
+  [
+    expr = VariableDeclaratorId()
+    {buff.append(expr);}
+  ]
+  [
+    try {
+      <COMMA>
+    } catch (ParseException e) {
+      errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ',' expected";
+      errorLevel   = ERROR;
+      throw e;
+    }
+    expr = VariableDeclaratorId()
+    {buff.append(",").append(expr);}
+  ]
+  {buff.append(")");}
+  try {
+    <RPAREN>
+  } catch (ParseException e) {
+    errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
+  [ <ASSIGN> expr = Expression() {buff.append("(").append(expr);}]
+  {return buff.toString();}
+}
+
 void EchoStatement() :
 {}
 {
   <ECHO> Expression() (<COMMA> Expression())*
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected after 'echo' statement";
     errorLevel   = ERROR;
@@ -1667,7 +1792,7 @@ void GlobalStatement() :
 {
   <GLOBAL> VariableDeclaratorId() (<COMMA> VariableDeclaratorId())*
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
@@ -1680,7 +1805,7 @@ void StaticStatement() :
 {
   <STATIC> VariableDeclarator() (<COMMA> VariableDeclarator())*
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
@@ -1705,7 +1830,13 @@ void Block() :
     throw e;
   }
   ( BlockStatement() )*
-  <RBRACE>
+  try {
+    <RBRACE>
+  } catch (ParseException e) {
+    errorMessage = "unexpected token : '"+ e.currentToken.image +"', '}' expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
 }
 
 void BlockStatement() :
@@ -1718,6 +1849,19 @@ void BlockStatement() :
   MethodDeclaration()
 }
 
+/**
+ * A Block statement that will not contain any 'break'
+ */
+void BlockStatementNoBreak() :
+{}
+{
+  StatementNoBreak()
+|
+  ClassDeclaration()
+|
+  MethodDeclaration()
+}
+
 void LocalVariableDeclaration() :
 {}
 {
@@ -1754,19 +1898,109 @@ void StatementExpression() :
 }
 
 void SwitchStatement() :
-{}
 {
-  <SWITCH> <LPAREN> Expression() <RPAREN> <LBRACE>
-    ( SwitchLabel() ( BlockStatement() )* )*
-  <RBRACE>
+  Token breakToken = null;
+  int line;
+}
+{
+  <SWITCH>
+  try {
+    <LPAREN>
+  } catch (ParseException e) {
+    errorMessage = "'(' expected after 'switch'";
+    errorLevel   = ERROR;
+    throw e;
+  }
+  Expression()
+  try {
+    <RPAREN>
+  } catch (ParseException e) {
+    errorMessage = "')' expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
+  try {
+  <LBRACE>
+  } catch (ParseException e) {
+    errorMessage = "'{' expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
+    (
+      line = SwitchLabel()
+      ( BlockStatementNoBreak() )*
+      [ breakToken = BreakStatement() ]
+      {
+        try {
+          if (breakToken == null) {
+            setMarker(fileToParse,
+                      "You should use put a 'break' at the end of your statement",
+                      line,
+                      INFO,
+                      "Line " + line);
+          }
+        } catch (CoreException e) {
+          PHPeclipsePlugin.log(e);
+        }
+      }
+    )*
+  try {
+    <RBRACE>
+  } catch (ParseException e) {
+    errorMessage = "'}' expected";
+    errorLevel   = ERROR;
+    throw e;
+  }
 }
 
-void SwitchLabel() :
-{}
+Token BreakStatement() :
+{
+  final Token token;
+}
+{
+  token = <BREAK> [ Expression() ]
+  try {
+    <SEMICOLON>
+  } catch (ParseException e) {
+    errorMessage = "';' expected after 'break' keyword";
+    errorLevel   = ERROR;
+    throw e;
+  }
+  {return token;}
+}
+
+int SwitchLabel() :
 {
-  <CASE> Expression() <COLON>
+  final Token token;
+}
+{
+  token = <CASE>
+  try {
+    Expression()
+  } catch (ParseException e) {
+    if (errorMessage != null) throw e;
+    errorMessage = "expression expected after 'case' keyword";
+    errorLevel   = ERROR;
+    throw e;
+  }
+  try {
+    <COLON>
+  } catch (ParseException e) {
+    errorMessage = "':' expected after case expression";
+    errorLevel   = ERROR;
+    throw e;
+  }
+  {return token.beginLine;}
 |
-  <_DEFAULT> <COLON>
+  token = <_DEFAULT>
+  try {
+    <COLON>
+  } catch (ParseException e) {
+    errorMessage = "':' expected after 'default' keyword";
+    errorLevel   = ERROR;
+    throw e;
+  }
+  {return token.beginLine;}
 }
 
 void IfStatement() :
@@ -1799,8 +2033,7 @@ void Condition(final String keyword) :
 }
 
 void IfStatement0(final int start,final int end) :
-{
-}
+{}
 {
   <COLON> (Statement())* (ElseIfStatementColon())* [ElseStatementColon()]
 
@@ -1824,7 +2057,7 @@ void IfStatement0(final int start,final int end) :
   try {
     <SEMICOLON>
   } catch (ParseException e) {
-    errorMessage = "';' expected 'endif' keyword";
+    errorMessage = "';' expected after 'endif' keyword";
     errorLevel   = ERROR;
     throw e;
   }
@@ -1881,7 +2114,7 @@ void WhileStatement0(final int start, final int end) :
     throw e;
   }
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected after 'endwhile' keyword";
     errorLevel   = ERROR;
@@ -1896,7 +2129,7 @@ void DoStatement() :
 {
   <DO> Statement() <WHILE> Condition("while")
   try {
-    (<SEMICOLON> | "?>")
+    (<SEMICOLON> | <PHPEND> {PHPParserTokenManager.SwitchTo(PHPParserTokenManager.DEFAULT);})
   } catch (ParseException e) {
     errorMessage = "';' expected";
     errorLevel   = ERROR;
@@ -1969,7 +2202,7 @@ final int pos = jj_input_stream.bufpos;
     errorLevel   = ERROR;
     throw e;
   }
-     [ ForInit() ] <SEMICOLON> [ Expression() ] <SEMICOLON> [ ForUpdate() ] <RPAREN>
+     [ ForInit() ] <SEMICOLON> [ Expression() ] <SEMICOLON> [ StatementExpressionList() ] <RPAREN>
     (
       Statement()
     |
@@ -1996,7 +2229,7 @@ final int pos = jj_input_stream.bufpos;
       try {
         <SEMICOLON>
       } catch (ParseException e) {
-        errorMessage = "';' expected 'endfor' keyword";
+        errorMessage = "';' expected after 'endfor' keyword";
         errorLevel   = ERROR;
         throw e;
       }
@@ -2018,26 +2251,28 @@ void StatementExpressionList() :
   StatementExpression() ( <COMMA> StatementExpression() )*
 }
 
-void ForUpdate() :
-{}
-{
-  StatementExpressionList()
-}
-
-void BreakStatement() :
-{}
-{
-  <BREAK> [ <IDENTIFIER> ] <SEMICOLON>
-}
-
 void ContinueStatement() :
 {}
 {
-  <CONTINUE> [ <IDENTIFIER> ] <SEMICOLON>
+  <CONTINUE> [ <IDENTIFIER> ]
+  try {
+    <SEMICOLON>
+  } catch (ParseException e) {
+    errorMessage = "';' expected after 'continue' statement";
+    errorLevel   = ERROR;
+    throw e;
+  }
 }
 
 void ReturnStatement() :
 {}
 {
-  <RETURN> [ Expression() ] <SEMICOLON>
+  <RETURN> [ Expression() ]
+  try {
+    <SEMICOLON>
+  } catch (ParseException e) {
+    errorMessage = "';' expected after 'return' statement";
+    errorLevel   = ERROR;
+    throw e;
+  }
 }
\ No newline at end of file