improved php parser for keywords do-while, null, false, true...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPParser.java
index 5848e7d..3bbd368 100644 (file)
@@ -62,7 +62,7 @@ public class PHPParser extends PHPKeywords {
   final static int TT_DDOT = 47;
   final static int TT_DOTASSIGN = 48;
 
-  final static int TT_SET = 49;
+  final static int TT_ASSIGN = 49;
   final static int TT_REF = 50;
   final static int TT_FOREACH = 51;
   final static int TT_AMPERSAND = 52;
@@ -197,7 +197,11 @@ public class PHPParser extends PHPKeywords {
                   chIndx += 2;
                   break;
                 }
-                chIndx++;
+                ch = str.charAt(chIndx++);
+                if (ch == '\n') {
+                  rowCount++;
+                  columnCount = chIndx;
+                }
               }
               continue;
             }
@@ -220,11 +224,9 @@ public class PHPParser extends PHPKeywords {
             } else if (ch == '"') {
               openString = false;
               break;
-            } else {
-              if (ch == '\n') {
-                rowCount++;
-                columnCount = chIndx;
-              }
+            } else if (ch == '\n') {
+              rowCount++;
+              columnCount = chIndx;
             }
           }
           if (openString) {
@@ -244,11 +246,9 @@ public class PHPParser extends PHPKeywords {
             } else if (ch == '\'') {
               openString = false;
               break;
-            } else {
-              if (ch == '\n') {
-                rowCount++;
-                columnCount = chIndx;
-              }
+            } else if (ch == '\n') {
+              rowCount++;
+              columnCount = chIndx;
             }
           }
           if (openString) {
@@ -393,7 +393,7 @@ public class PHPParser extends PHPKeywords {
 
             break;
           case '=' :
-            token = TT_SET;
+            token = TT_ASSIGN;
 
             if (str.length() > chIndx) {
               ch = str.charAt(chIndx);
@@ -652,8 +652,9 @@ public class PHPParser extends PHPKeywords {
     this.rowCount = rowCount;
     this.columnCount = 0;
     getNextToken();
-
-    statementList();
+    if (token != TT_EOF) {
+      statementList();
+    }
     if (token != TT_EOF) {
       if (token == TT_ARGCLOSE) {
         throwSyntaxError("too many closing ')'; end-of-file not reached");
@@ -724,7 +725,9 @@ public class PHPParser extends PHPKeywords {
         if (token == TT_SEMICOLON) {
           getNextToken();
         } else {
-          throwSyntaxError("';' character after 'include' or 'include_once' expected.");
+          if (token != TT_EOF) {
+            throwSyntaxError("';' character after 'include' or 'include_once' expected.");
+          }
         }
         return;
       } else if (token == TT_require || token == TT_require_once) {
@@ -734,7 +737,9 @@ public class PHPParser extends PHPKeywords {
         if (token == TT_SEMICOLON) {
           getNextToken();
         } else {
-          throwSyntaxError("';' character after 'require' or 'require_once' expected.");
+          if (token != TT_EOF) {
+            throwSyntaxError("';' character after 'require' or 'require_once' expected.");
+          }
         }
         return;
       } else if (token == TT_if) {
@@ -822,6 +827,45 @@ public class PHPParser extends PHPKeywords {
         }
         whileStatement();
         return;
+      } else if (token == TT_do) {
+        getNextToken();
+        if (token == TT_LISTOPEN) {
+          getNextToken();
+        } else {
+          throwSyntaxError("'{' expected after 'do' keyword.");
+        }
+        if (token != TT_LISTCLOSE) {
+          statementList();
+        }
+        if (token == TT_LISTCLOSE) {
+          getNextToken();
+        } else {
+          throwSyntaxError("'}' expected after 'do' keyword.");
+        }
+        if (token == TT_while) {
+          getNextToken();
+          if (token == TT_ARGOPEN) {
+            getNextToken();
+          } else {
+            throwSyntaxError("'(' expected after 'while' keyword.");
+          }
+          expression();
+          if (token == TT_ARGCLOSE) {
+            getNextToken();
+          } else {
+            throwSyntaxError("')' expected after 'while' condition.");
+          }
+        } else {
+          throwSyntaxError("'while' expected after 'do' keyword.");
+        }
+        if (token == TT_SEMICOLON) {
+          getNextToken();
+        } else {
+          if (token != TT_EOF) {
+            throwSyntaxError("';' expected after do-while statement.");
+          }
+        }
+        return;
       } else if (token == TT_foreach) {
         getNextToken();
         if (token == TT_ARGOPEN) {
@@ -856,7 +900,9 @@ public class PHPParser extends PHPKeywords {
         if (token == TT_SEMICOLON) {
           getNextToken();
         } else {
-          throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
+          if (token != TT_EOF) {
+            throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
+          }
         }
         return;
 
@@ -866,7 +912,9 @@ public class PHPParser extends PHPKeywords {
         if (token == TT_SEMICOLON) {
           getNextToken();
         } else {
-          throwSyntaxError("';' expected after 'echo' statement.");
+          if (token != TT_EOF) {
+            throwSyntaxError("';' expected after 'echo' statement.");
+          }
         }
         return;
 
@@ -876,7 +924,9 @@ public class PHPParser extends PHPKeywords {
         if (token == TT_SEMICOLON) {
           getNextToken();
         } else {
-          throwSyntaxError("';' expected after 'print' statement.");
+          if (token != TT_EOF) {
+            throwSyntaxError("';' expected after 'print' statement.");
+          }
         }
         return;
 
@@ -886,7 +936,9 @@ public class PHPParser extends PHPKeywords {
         if (token == TT_SEMICOLON) {
           getNextToken();
         } else {
-          throwSyntaxError("';' expected after 'global' or 'static' statement.");
+          if (token != TT_EOF) {
+            throwSyntaxError("';' expected after 'global' or 'static' statement.");
+          }
         }
         return;
 
@@ -906,7 +958,9 @@ public class PHPParser extends PHPKeywords {
         if (token == TT_SEMICOLON) {
           getNextToken();
         } else {
-          throwSyntaxError("';' expected after 'unset' statement.");
+          if (token != TT_EOF) {
+            throwSyntaxError("';' expected after 'unset' statement.");
+          }
         }
         return;
 
@@ -918,7 +972,9 @@ public class PHPParser extends PHPKeywords {
         if (token == TT_SEMICOLON) {
           getNextToken();
         } else {
-          throwSyntaxError("';' expected after 'exit' or 'die' statement.");
+          if (token != TT_EOF) {
+            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
+          }
         }
         return;
 
@@ -944,19 +1000,26 @@ public class PHPParser extends PHPKeywords {
         if (token == TT_SEMICOLON) {
           getNextToken();
         } else {
-          throwSyntaxError("';' expected after 'define' statement.");
+          if (token != TT_EOF) {
+            throwSyntaxError("';' expected after 'define' statement.");
+          }
         }
         return;
       } else if (token == TT_function) {
         getNextToken();
         functionDefinition();
         return;
+      } else if (token == TT_class) {
+        getNextToken();
+        classDeclarator();
+        classBody();
+        return;
       } else {
         throwSyntaxError("Unexpected keyword '" + keyword + "'");
       }
 
     } else if (token == TT_LISTOPEN) {
-      // compundStatement
+      // compoundStatement
       getNextToken();
       if (token != TT_LISTCLOSE) {
         statementList();
@@ -975,12 +1038,92 @@ public class PHPParser extends PHPKeywords {
         getNextToken();
         return;
       } else {
-        throwSyntaxError("';' expected after expression.");
+        if (token != TT_EOF) {
+          throwSyntaxError("';' expected after expression.");
+        }
       }
     }
 
   }
 
+  public void classDeclarator() {
+    //identifier
+    //identifier 'extends' identifier
+    if (token == TT_IDENTIFIER) {
+      getNextToken();
+      if (token == TT_extends) {
+        getNextToken();
+        if (token == TT_IDENTIFIER) {
+          getNextToken();
+        } else {
+          throwSyntaxError("Class name expected after keyword 'extends'.");
+        }
+      }
+    } else {
+      throwSyntaxError("Class name expected after keyword 'class'.");
+    }
+  }
+
+  public void classBody() {
+    //'{' [class-element-list] '}'
+    if (token == TT_LISTOPEN) {
+      getNextToken();
+      if (token != TT_LISTCLOSE) {
+        classElementList();
+      }
+      if (token == TT_LISTCLOSE) {
+        getNextToken();
+      } else {
+        throwSyntaxError("'}' expected at end of class body.");
+      }
+    } else {
+      throwSyntaxError("'{' expected at start of class body.");
+    }
+  }
+
+  public void classElementList() {
+    do {
+      classElement();
+    } while (token != TT_function || token != TT_var);
+  }
+
+  public void classElement() {
+    //class-property
+    //function-definition
+    if (token == TT_function) {
+      getNextToken();
+      functionDefinition();
+    } else if (token == TT_var) {
+      getNextToken();
+      classProperty();
+    } else {
+      throwSyntaxError("'function' or 'var' expected.");
+    }
+  }
+
+  public void classProperty() {
+    //'var' variable ';'
+    //'var' variable '=' constant ';'
+    if (token == TT_VARIABLE) {
+      getNextToken();
+      if (token == TT_ASSIGN) {
+        getNextToken();
+        constant();
+        if (token == TT_SEMICOLON) {
+          getNextToken();
+        } else {
+          throwSyntaxError("';' expected after variable declaration.");
+        }
+      } else if (token == TT_SEMICOLON) {
+        getNextToken();
+      } else {
+        throwSyntaxError("';' or '=' expected after variable declaration.");
+      }
+    } else {
+      throwSyntaxError("Variable expected after keyword 'var'.");
+    }
+  }
+
   public void functionDefinition() {
     functionDeclarator();
     compoundStatement();
@@ -1024,7 +1167,7 @@ public class PHPParser extends PHPKeywords {
     //variable '=' constant
     if (token == TT_VARIABLE) {
       getNextToken();
-      if (token == TT_SET) {
+      if (token == TT_ASSIGN) {
         getNextToken();
         constant();
       }
@@ -1335,6 +1478,19 @@ public class PHPParser extends PHPKeywords {
     String ident;
     boolean castFlag = false;
     switch (token) {
+      case TT_new :
+        getNextToken();
+        expression();
+        break;
+      case TT_null :
+        getNextToken();
+        break;
+      case TT_false :
+        getNextToken();
+        break;
+      case TT_true :
+        getNextToken();
+        break;
       case TT_STRING_CONSTANT :
         getNextToken();
         break;
@@ -1456,12 +1612,31 @@ public class PHPParser extends PHPKeywords {
           getNextToken();
           break;
         case TT_REF : // ->
+          getNextToken();
           switch (token) {
             case TT_VARIABLE :
+              ident = identifier;
               getNextToken();
+              //              if (token == TT_ARGOPEN) {
+              //                getNextToken();
+              //                expressionList();
+              //                if (token != TT_ARGCLOSE) {
+              //                  throwSyntaxError(") expected after variable '" + ident + "'.");
+              //                }
+              //                getNextToken();
+              //              }
               break;
             case TT_IDENTIFIER :
+              ident = identifier;
               getNextToken();
+              if (token == TT_ARGOPEN) {
+                getNextToken();
+                expressionList();
+                if (token != TT_ARGCLOSE) {
+                  throwSyntaxError(") expected after identifier '" + ident + "'.");
+                }
+                getNextToken();
+              }
               break;
             case TT_LISTOPEN :
               getNextToken();
@@ -1474,6 +1649,7 @@ public class PHPParser extends PHPKeywords {
             default :
               throwSyntaxError("Syntax error after '->' token.");
           }
+          break;
         case TT_INCREMENT :
           getNextToken();
           break;
@@ -1559,7 +1735,7 @@ public class PHPParser extends PHPKeywords {
 
   public void assignExpression() {
     castExpression();
-    if (token == TT_SET) { // =
+    if (token == TT_ASSIGN) { // =
       getNextToken();
       logicalinclusiveorExpression();
     } else if (token == TT_DOTASSIGN) { // .=
@@ -1568,6 +1744,18 @@ public class PHPParser extends PHPKeywords {
     } else if (token == TT_FOREACH) { // =>
       getNextToken();
       logicalinclusiveorExpression();
+    } else if (token == TT_ADDTO) { // +=
+      getNextToken();
+      logicalinclusiveorExpression();
+    } else if (token == TT_SUBTRACTFROM) { // -=
+      getNextToken();
+      logicalinclusiveorExpression();
+    } else if (token == TT_TIMESBY) { // *=
+      getNextToken();
+      logicalinclusiveorExpression();
+    } else if (token == TT_DIVIDEBY) { // *=
+      getNextToken();
+      logicalinclusiveorExpression();
     }
   }
 
@@ -1754,6 +1942,15 @@ public class PHPParser extends PHPKeywords {
 
   public void constant() {
     switch (token) {
+      case TT_null :
+        getNextToken();
+        break;
+      case TT_false :
+        getNextToken();
+        break;
+      case TT_true :
+        getNextToken();
+        break;
       case TT_STRING_CONSTANT :
         getNextToken();
         break;