new php icon
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPParser.java
index e2f1dce..98ce451 100644 (file)
@@ -1,8 +1,14 @@
 package net.sourceforge.phpeclipse.phpeditor;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Hashtable;
 
 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.ui.texteditor.MarkerUtilities;
 
 /**********************************************************************
 Copyright (c) 2000, 2002 IBM Corp. and others.
@@ -18,6 +24,15 @@ Contributors:
 
 public class PHPParser extends PHPKeywords {
 
+  public static final int ERROR = 2;
+  public static final int WARNING = 1;
+  public static final int INFO = 0;
+  private IFile fileToParse;
+  private ArrayList phpList;
+
+  private int currentPHPString;
+  private boolean phpEnd;
+
   private static HashMap keywordMap = null;
   private String str;
 
@@ -42,10 +57,11 @@ public class PHPParser extends PHPKeywords {
   final static int TT_EOF = 0;
   final static int TT_UNDEFINED = 1;
 
+  final static int TT_MOD = 30;
   final static int TT_NOT = 31;
   final static int TT_DOT = 32;
   final static int TT_POW = 33;
-  final static int TT_DIVIDE = 34;
+  final static int TT_DIV = 34;
   final static int TT_MULTIPLY = 35;
   final static int TT_SUBTRACT = 36;
   final static int TT_ADD = 37;
@@ -61,9 +77,20 @@ 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;
+  final static int TT_DOLLARLISTOPEN = 53;
+  final static int TT_TILDE = 54;
+  final static int TT_TILDEASSIGN = 55;
+  final static int TT_MODASSIGN = 56;
+  final static int TT_POWASSIGN = 57;
+  final static int TT_RSHIFTASSIGN = 58;
+  final static int TT_LSHIFTASSIGN = 59;
+  final static int TT_ANDASSIGN = 60;
+  final static int TT_QUESTIONMARK = 61;
+
   final static int TT_ARGOPEN = 128;
   final static int TT_ARGCLOSE = 129;
   final static int TT_LISTOPEN = 130;
@@ -71,7 +98,7 @@ public class PHPParser extends PHPKeywords {
   final static int TT_PARTOPEN = 132;
   final static int TT_PARTCLOSE = 133;
   final static int TT_COMMA = 134;
-  final static int TT_PERCENT = 135;
+
   final static int TT_STRING = 136;
   final static int TT_IDENTIFIER = 138;
   final static int TT_DIGIT = 139;
@@ -89,6 +116,12 @@ public class PHPParser extends PHPKeywords {
   final static int TT_DOUBLE_NUMBER = 152;
   final static int TT_INTERPOLATED_STRING = 153;
   final static int TT_STRING_CONSTANT = 154;
+
+  final static int TT_LSHIFT = 155;
+  final static int TT_RSHIFT = 156;
+  final static int TT_EX_EQUAL = 157;
+  final static int TT_EX_UNEQUAL = 158;
+  final static int TT_LINE = 159;
   //  final static int TT_AT = 153; // @
   /**
    *  Class Constructor.
@@ -97,20 +130,50 @@ public class PHPParser extends PHPKeywords {
    *@param  sess  Description of Parameter
    *@see
    */
-  public PHPParser(String s, int rowCount) {
+  public PHPParser(IFile fileToParse) {
     if (keywordMap == null) {
       keywordMap = new HashMap();
       for (int i = 0; i < PHP_KEYWORS.length; i++) {
         keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
       }
     }
-    this.str = s;
+    this.currentPHPString = 0;
+    this.fileToParse = fileToParse;
+    this.phpList = null;
+    this.str = "";
     this.token = TT_EOF;
     this.chIndx = 0;
-    this.rowCount = rowCount;
+    this.rowCount = 1;
     this.columnCount = 0;
+    this.phpEnd = false;
+
+    //   getNextToken();
+  }
 
-    getNextToken();
+  /**
+   * Create marker for the parse error
+   */
+  protected void setMarker(String message, int lineNumber, int errorLevel) throws CoreException {
+    setMarker(fileToParse, message, lineNumber, errorLevel);
+  }
+
+  public static void setMarker(IFile file, String message, int lineNumber, int errorLevel) throws CoreException {
+
+    Hashtable attributes = new Hashtable();
+    MarkerUtilities.setMessage(attributes, message);
+    switch (errorLevel) {
+      case ERROR :
+        attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
+        break;
+      case WARNING :
+        attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
+        break;
+      case INFO :
+        attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
+        break;
+    }
+    MarkerUtilities.setLineNumber(attributes, lineNumber);
+    MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
   }
 
   private void throwSyntaxError(String error) {
@@ -127,7 +190,7 @@ public class PHPParser extends PHPKeywords {
         break;
       }
     }
-    throw new SyntaxError(rowCount, chIndx - columnCount, str.substring(columnCount + 1, eol), error);
+    throw new SyntaxError(rowCount, chIndx - columnCount + 1, str.substring(columnCount, eol), error);
   }
 
   /**
@@ -144,13 +207,16 @@ public class PHPParser extends PHPKeywords {
 
     chIndx = str.length() + 1;
     ch = ' ';
-    token = TT_EOF;
+    //  token = TT_EOF;
+    phpEnd = true;
   }
 
   /**
    * gets the next token from input
    */
   void getNextToken() {
+    phpEnd = false;
+
     while (str.length() > chIndx) {
       ch = str.charAt(chIndx++);
       token = TT_UNDEFINED;
@@ -159,7 +225,9 @@ public class PHPParser extends PHPKeywords {
         columnCount = chIndx;
         continue; // while loop
       }
-
+      if (str.length() == chIndx) {
+        phpEnd = true;
+      }
       if (!Character.isWhitespace(ch)) {
         if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$') || (ch == '@')) {
           getIdentifier();
@@ -182,13 +250,15 @@ public class PHPParser extends PHPKeywords {
               chIndx++;
               // multi line comment:
               while (str.length() > chIndx) {
-                if  (str.charAt(chIndx) == '*' &&
-                      (str.length() > (chIndx+1) ) && 
-                      str.charAt(chIndx+1) == '/') {
+                if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
                   chIndx += 2;
                   break;
                 }
-                chIndx++;
+                ch = str.charAt(chIndx++);
+                if (ch == '\n') {
+                  rowCount++;
+                  columnCount = chIndx;
+                }
               }
               continue;
             }
@@ -201,40 +271,45 @@ public class PHPParser extends PHPKeywords {
           continue;
         } else if (ch == '"') {
           // read string until end
-          while ((str.length() > chIndx) && (str.charAt(chIndx++) != '"')) {
-            if (str.charAt(chIndx) == '\\') {
-              if (str.length() > chIndx) {
-                chIndx++;
-              }
+          boolean openString = true;
+          while (str.length() > chIndx) {
+            ch = str.charAt(chIndx++);
+            if (ch == '\\') {
               if (str.length() > chIndx) {
-                chIndx++;
-              }
-            } else {
-              if (str.charAt(chIndx) == '\n') {
-                rowCount++;
-                columnCount = chIndx;
+                ch = str.charAt(chIndx++);
               }
+            } else if (ch == '"') {
+              openString = false;
+              break;
+            } else if (ch == '\n') {
+              rowCount++;
+              columnCount = chIndx;
             }
           }
-          if (str.length() > chIndx) {
-            chIndx++;
+          if (openString) {
+            throwSyntaxError("Open string character '\"' at end of file.");
           }
           token = TT_INTERPOLATED_STRING;
           return;
         } else if (ch == '\'') {
           // read string until end
-          while ((str.length() > chIndx) && (str.charAt(chIndx++) != '\'')) {
-            if (str.charAt(chIndx) == '\\') {
-              if (str.length() > chIndx) {
-                chIndx++;
-              }
+          boolean openString = true;
+          while (str.length() > chIndx) {
+            ch = str.charAt(chIndx++);
+            if (ch == '\\') {
               if (str.length() > chIndx) {
-                chIndx++;
+                ch = str.charAt(chIndx++);
               }
+            } else if (ch == '\'') {
+              openString = false;
+              break;
+            } else if (ch == '\n') {
+              rowCount++;
+              columnCount = chIndx;
             }
           }
-          if (str.length() > chIndx) {
-            chIndx++;
+          if (openString) {
+            throwSyntaxError("Open string character \"'\" at end of file.");
           }
           token = TT_STRING_CONSTANT;
           return;
@@ -270,7 +345,20 @@ public class PHPParser extends PHPKeywords {
             token = TT_COMMA;
 
             break;
+          case '?' :
+            token = TT_QUESTIONMARK;
+            break;
+          case '~' :
+            token = TT_TILDE;
+            if (str.length() > chIndx) {
+              if (str.charAt(chIndx) == '=') {
+                chIndx++;
+                token = TT_TILDEASSIGN;
 
+                break;
+              }
+            }
+            break;
           case '.' :
             token = TT_DOT;
             if (str.length() > chIndx) {
@@ -288,8 +376,15 @@ public class PHPParser extends PHPKeywords {
 
             break;
           case '%' :
-            token = TT_PERCENT;
+            token = TT_MOD;
+            if (str.length() > chIndx) {
+              if (str.charAt(chIndx) == '=') {
+                chIndx++;
+                token = TT_MODASSIGN;
 
+                break;
+              }
+            }
             break;
           case ';' :
             token = TT_SEMICOLON;
@@ -297,10 +392,17 @@ public class PHPParser extends PHPKeywords {
             break;
           case '^' :
             token = TT_POW;
+            if (str.length() > chIndx) {
+              if (str.charAt(chIndx) == '=') {
+                chIndx++;
+                token = TT_POWASSIGN;
 
+                break;
+              }
+            }
             break;
           case '/' :
-            token = TT_DIVIDE;
+            token = TT_DIV;
 
             if (str.length() > chIndx) {
               if (str.charAt(chIndx) == '=') {
@@ -362,11 +464,17 @@ public class PHPParser extends PHPKeywords {
 
                 break;
               }
+              if (str.charAt(chIndx) == '>') {
+                chIndx++;
+                token = TT_REF;
+
+                break;
+              }
             }
 
             break;
           case '=' :
-            token = TT_SET;
+            token = TT_ASSIGN;
 
             if (str.length() > chIndx) {
               ch = str.charAt(chIndx);
@@ -374,7 +482,14 @@ public class PHPParser extends PHPKeywords {
               if (ch == '=') {
                 chIndx++;
                 token = TT_EQUAL;
+                if (str.length() > chIndx) {
+                  ch = str.charAt(chIndx);
 
+                  if (ch == '=') {
+                    chIndx++;
+                    token = TT_EX_EQUAL;
+                  }
+                }
                 break;
               }
               if (ch == '>') {
@@ -393,7 +508,14 @@ public class PHPParser extends PHPKeywords {
               if (str.charAt(chIndx) == '=') {
                 chIndx++;
                 token = TT_UNEQUAL;
+                if (str.length() > chIndx) {
+                  ch = str.charAt(chIndx);
 
+                  if (ch == '=') {
+                    chIndx++;
+                    token = TT_EX_UNEQUAL;
+                  }
+                }
                 break;
               }
             }
@@ -406,7 +528,18 @@ public class PHPParser extends PHPKeywords {
               if (str.charAt(chIndx) == '=') {
                 chIndx++;
                 token = TT_GREATEREQUAL;
-
+                break;
+              }
+              if (str.charAt(chIndx) == '>') {
+                chIndx++;
+                token = TT_RSHIFT;
+                if (str.length() > chIndx) {
+                  if (str.charAt(chIndx) == '=') {
+                    chIndx++;
+                    token = TT_RSHIFTASSIGN;
+                    break;
+                  }
+                }
                 break;
               }
             }
@@ -422,13 +555,28 @@ public class PHPParser extends PHPKeywords {
 
                 break;
               }
+              if (str.charAt(chIndx) == '<') {
+                chIndx++;
+                token = TT_LSHIFT;
+                if (str.length() > chIndx) {
+                  if (str.charAt(chIndx) == '=') {
+                    chIndx++;
+                    token = TT_LSHIFTASSIGN;
+                    break;
+                  }
+                }
+                break;
+              }
             }
 
             break;
 
           case '|' :
+            token = TT_LINE;
+
             if (str.length() > chIndx) {
-              if (str.charAt(chIndx++) == '|') {
+              if (str.charAt(chIndx) == '|') {
+                chIndx++;
                 token = TT_OR;
 
                 break;
@@ -437,12 +585,19 @@ public class PHPParser extends PHPKeywords {
 
             break;
           case '&' :
+            token = TT_AMPERSAND;
             if (str.length() > chIndx) {
-              if (str.charAt(chIndx++) == '&') {
+              if (str.charAt(chIndx) == '&') {
+                chIndx++;
                 token = TT_AND;
-
                 break;
               }
+              if (str.charAt(chIndx) == '=') {
+                chIndx++;
+                token = TT_ANDASSIGN;
+                break;
+              }
+              break;
             }
 
             break;
@@ -473,11 +628,28 @@ public class PHPParser extends PHPKeywords {
     chIndx = str.length() + 1;
     ch = ' ';
     token = TT_EOF;
+    phpEnd = true;
+    PHPString temp;
+    if (phpList != null) {
+      if (currentPHPString < phpList.size()) {
+        token = TT_UNDEFINED;
+        temp = (PHPString) phpList.get(currentPHPString++);
+        this.str = temp.getPHPString();
+        this.token = TT_EOF;
+        this.chIndx = 0;
+        this.rowCount = temp.getLineNumber();
+        this.columnCount = 0;
+        getNextToken();
+        phpEnd = true;
+      } else {
+        token = TT_UNDEFINED;
+        return;
+      }
+    }
   }
 
   void getIdentifier() {
     StringBuffer ident = new StringBuffer();
-    ident.append(ch);
 
     ident.append(ch);
     if (ch == '$') {
@@ -486,13 +658,14 @@ public class PHPParser extends PHPKeywords {
       token = TT_IDENTIFIER;
     }
     getChar();
-    while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch >= '_')) {
+    while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
       ident.append(ch);
       getChar();
     }
     identifier = ident.toString();
+    chIndx--;
 
-    Integer i = (Integer) keywordMap.get(identifier);
+    Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
     if (i != null) {
       token = i.intValue();
     }
@@ -565,8 +738,7 @@ public class PHPParser extends PHPKeywords {
         }
       }
     }
-
-    // token = TT_INT_NUMBER;
+    chIndx--;
 
     try {
       if (dFlag != ' ') {
@@ -584,139 +756,370 @@ public class PHPParser extends PHPKeywords {
     }
   }
 
-  public void start() throws SyntaxError {
-    statementList();
-    if (token != TT_EOF) {
-      if (token == TT_ARGCLOSE) {
-        throwSyntaxError("too many closing ')'; end-of-file not reached");
+  public void htmlParse(String input) {
+    boolean lineCommentMode = false;
+    boolean multiLineCommentMode = false;
+    boolean stringMode = false;
+
+    StringBuffer buf = new StringBuffer();
+    int lineNumber = 1;
+    int startLineNumber = 1;
+    int startIndex = 0;
+    char ch;
+    char ch2;
+    boolean phpMode = false;
+    boolean phpFound = false;
+
+    phpList = new ArrayList();
+    currentPHPString = 0;
+
+    try {
+      int i = 0;
+      while (i < input.length()) {
+        ch = input.charAt(i++);
+        if (ch == '\n') {
+          lineNumber++;
+        }
+        if ((!phpMode) && ch == '<') {
+          ch2 = input.charAt(i++);
+          if (ch2 == '?') {
+            ch2 = input.charAt(i++);
+            if (Character.isWhitespace(ch2)) {
+              // php start 
+              phpMode = true;
+              phpFound = true;
+              startIndex = i;
+              startLineNumber = lineNumber;
+              continue;
+            } else if (ch2 == 'p') {
+              ch2 = input.charAt(i++);
+              if (ch2 == 'h') {
+                ch2 = input.charAt(i++);
+                if (ch2 == 'p') {
+                  phpMode = true;
+                  phpFound = true;
+                  startIndex = i;
+                  startLineNumber = lineNumber;
+                  continue;
+                }
+                i--;
+              }
+              i--;
+            } else if (ch2 == 'P') {
+              ch2 = input.charAt(i++);
+              if (ch2 == 'H') {
+                ch2 = input.charAt(i++);
+                if (ch2 == 'P') {
+                  phpMode = true;
+                  phpFound = true;
+                  startIndex = i;
+                  startLineNumber = lineNumber;
+                  continue;
+                }
+                i--;
+              }
+              i--;
+            }
+            i--;
+          }
+          i--;
+        }
+
+        if (phpMode) {
+          buf.append(ch);
+          if (lineCommentMode && (ch == '\n')) {
+            lineCommentMode = false;
+            // read until end of line
+          } else if ((!stringMode) && (ch == '#')) {
+            // read until end of line
+            lineCommentMode = true;
+            continue;
+          } else if ((!stringMode) && (!multiLineCommentMode) && (ch == '/')) {
+            ch2 = input.charAt(i++);
+            if (ch2 == '/') {
+              lineCommentMode = true;
+              continue;
+            } else if (ch2 == '*') {
+              multiLineCommentMode = true;
+              continue;
+            } else {
+              i--;
+            }
+          } else if (ch == '*' && multiLineCommentMode) {
+            ch2 = input.charAt(i++);
+            if (ch2 == '/') {
+              multiLineCommentMode = false;
+              continue;
+            } else {
+              i--;
+            }
+          } else if (ch == '\\' && stringMode) {
+            ch2 = input.charAt(i++);
+            if (ch2 == '"') {
+              continue;
+            } else {
+              i--;
+            }
+          } else if ((!lineCommentMode) && (!multiLineCommentMode) && (ch == '"')) {
+            if (stringMode) {
+              stringMode = false;
+            } else {
+              stringMode = true;
+            }
+            continue;
+          }
+          if (lineCommentMode || multiLineCommentMode || stringMode) {
+            continue;
+          }
+
+          if (ch == '?') {
+            ch2 = input.charAt(i++);
+            if (ch2 == '>') {
+              // php end
+              phpMode = false;
+              phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
+              continue;
+            }
+            i--;
+          }
+        } else {
+        }
       }
-      if (token == TT_LISTCLOSE) {
-        throwSyntaxError("too many closing '}'; end-of-file not reached");
+      if (!phpFound) {
+        setMarker("No PHP source code found.", lineNumber, PHPParser.INFO);
+      } else {
+        //        for (int j=0;j<phpList.size();j++) {
+        //          String temp = ((PHPString)phpList.get(j)).getPHPString();
+        //          int startIndx = temp.length()-10;
+        //          if (startIndx<0) {
+        //            startIndx = 0; 
+        //          }
+        //          System.out.println(temp.substring(startIndx)+"?>");
+        //        }
+        phpParse(null, 1);
+        //        PHPString temp;
+        //        for(int j=0;j<phpList.size();j++) {
+        //          temp = (PHPString) phpList.get(j);
+        //          parser.start(temp.getPHPString(), temp.getLineNumber());
+        //        } 
       }
-      if (token == TT_PARTCLOSE) {
-        throwSyntaxError("too many closing ']'; end-of-file not reached");
+    } catch (CoreException e) {
+    }
+  }
+
+  public void phpParse(String s, int rowCount) throws CoreException {
+    // start up
+    try {
+      this.str = s;
+      if (s == null) {
+        if (phpList.size() != 0) {
+          this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
+        }
       }
+      this.token = TT_EOF;
+      this.chIndx = 0;
+      this.rowCount = rowCount;
+      this.columnCount = 0;
+      this.phpEnd = false;
+      getNextToken();
+      if (token != TT_EOF && token != TT_UNDEFINED) {
+        statementList();
+      }
+      if (token != TT_EOF && token != TT_UNDEFINED) {
+        if (token == TT_ARGCLOSE) {
+          throwSyntaxError("too many closing ')'; end-of-file not reached");
+        }
+        if (token == TT_LISTCLOSE) {
+          throwSyntaxError("too many closing '}'; end-of-file not reached");
+        }
+        if (token == TT_PARTCLOSE) {
+          throwSyntaxError("too many closing ']'; end-of-file not reached");
+        }
 
-      throwSyntaxError("end-of-file not reached");
+        if (token == TT_ARGOPEN) {
+          throwSyntaxError("read character '('; end-of-file not reached");
+        }
+        if (token == TT_LISTOPEN) {
+          throwSyntaxError("read character '{';  end-of-file not reached");
+        }
+        if (token == TT_PARTOPEN) {
+          throwSyntaxError("read character '[';  end-of-file not reached");
+        }
+
+        throwSyntaxError("end-of-file not reached");
+      }
+    } catch (SyntaxError err) {
+      if (s != null) {
+        throw err;
+      } else {
+        setMarker(err.getMessage(), err.getLine(), ERROR);
+      }
     }
+  }
 
+  public void statementList() throws CoreException {
+    do {
+      statement();
+      if ((token == TT_LISTCLOSE)
+        || (token == TT_case)
+        || (token == TT_default)
+        || (token == TT_elseif)
+        || (token == TT_endif)
+        || (token == TT_endfor)
+        || (token == TT_endforeach)
+        || (token == TT_endwhile)
+        || (token == TT_endswitch)
+        || (token == TT_EOF)
+        || (token == TT_UNDEFINED)) {
+        return;
+      }
+    } while (true);
   }
 
-  public void statementList() {
-    statement();
+  public void compoundStatement() throws CoreException {
+    // '{' [statement-list] '}'
+    if (token == TT_LISTOPEN) {
+      getNextToken();
+    } else {
+      throwSyntaxError("'{' expected in compound-statement.");
+    }
+    if (token != TT_LISTCLOSE) {
+      statementList();
+    }
+    if (token == TT_LISTCLOSE) {
+      getNextToken();
+    } else {
+      throwSyntaxError("'}' expected in compound-statement.");
+    }
   }
 
-  public void statement() {
-    while (token != TT_UNDEFINED) {
-      if (token > TT_KEYWORD) {
-        if (token == TT_case) {
+  public void statement() throws CoreException {
+    if (token > TT_KEYWORD && token != TT_list) {
+      String keyword = identifier;
+      if (token == TT_include || token == TT_include_once) {
+        getNextToken();
+        expression();
+        if (token == TT_SEMICOLON) {
           getNextToken();
-          constant();
-          if (token == TT_DDOT) {
-            getNextToken();
-            statement();
-          } else {
-            throwSyntaxError("':' character after 'case' constant expected.");
+        } else {
+          if (!phpEnd) {
+            throwSyntaxError("';' character after 'include' or 'include_once' expected.");
           }
-          return;
-        } else if (token == TT_default) {
+        }
+        return;
+      } else if (token == TT_require || token == TT_require_once) {
+        getNextToken();
+        //constant();
+        expression();
+        if (token == TT_SEMICOLON) {
           getNextToken();
-          if (token == TT_DDOT) {
-            getNextToken();
-            statement();
-          } else {
-            throwSyntaxError("':' character after 'default' expected.");
+        } else {
+          if (!phpEnd) {
+            throwSyntaxError("';' character after 'require' or 'require_once' expected.");
           }
-          return;
-        } else if (token == TT_include || token == TT_include_once) {
+        }
+        return;
+      } else if (token == TT_if) {
+        getNextToken();
+        if (token == TT_ARGOPEN) {
           getNextToken();
+        } else {
+          throwSyntaxError("'(' expected after 'if' keyword.");
+        }
+        expression();
+        if (token == TT_ARGCLOSE) {
+          getNextToken();
+        } else {
+          throwSyntaxError("')' expected after 'if' condition.");
+        }
+        ifStatement();
+        return;
+
+      } else if (token == TT_switch) {
+        getNextToken();
+        if (token == TT_ARGOPEN) {
+          getNextToken();
+        } else {
+          throwSyntaxError("'(' expected after 'switch' keyword.");
+        }
+        expression();
+        if (token == TT_ARGCLOSE) {
+          getNextToken();
+        } else {
+          throwSyntaxError("')' expected after 'switch' condition.");
+        }
+        switchStatement();
+        return;
+      } else if (token == TT_for) {
+        getNextToken();
+        if (token == TT_ARGOPEN) {
+          getNextToken();
+        } else {
+          throwSyntaxError("'(' expected after 'for' keyword.");
+        }
+        if (token == TT_SEMICOLON) {
+          getNextToken();
+        } else {
           expression();
           if (token == TT_SEMICOLON) {
             getNextToken();
           } else {
-            throwSyntaxError("';' character after 'include' or 'include_once' expected.");
+            throwSyntaxError("';' character after 'for' expected.");
           }
-          return;
-        } else if (token == TT_require || token == TT_require_once) {
+        }
+        if (token == TT_SEMICOLON) {
           getNextToken();
-          constant();
+        } else {
+          expression();
           if (token == TT_SEMICOLON) {
             getNextToken();
           } else {
-            throwSyntaxError("';' character after 'require' or 'require_once' expected.");
+            throwSyntaxError("';' character after 'for' expected.");
           }
-          return;
-        } else if (token == TT_if) {
+        }
+        if (token == TT_ARGCLOSE) {
           getNextToken();
-          if (token == TT_ARGOPEN) {
-            getNextToken();
-          } else {
-            throwSyntaxError("'(' expected after 'if' keyword.");
-          }
+        } else {
           expression();
           if (token == TT_ARGCLOSE) {
             getNextToken();
           } else {
-            throwSyntaxError("')' expected after 'if' condition.");
+            throwSyntaxError("')' expected after 'for' condition.");
           }
-          ifStatement();
-          return;
-
-        } else if (token == TT_switch) {
+        }
+        forStatement();
+        return;
+      } else if (token == TT_while) {
+        getNextToken();
+        if (token == TT_ARGOPEN) {
           getNextToken();
-          if (token == TT_ARGOPEN) {
-            getNextToken();
-          } else {
-            throwSyntaxError("'(' expected after 'switch' keyword.");
-          }
-          expression();
-          if (token == TT_ARGCLOSE) {
-            getNextToken();
-          } else {
-            throwSyntaxError("')' expected after 'switch' condition.");
-          }
-          switchStatement();
-          return;
-        } else if (token == TT_for) {
+        } else {
+          throwSyntaxError("'(' expected after 'while' keyword.");
+        }
+        expression();
+        if (token == TT_ARGCLOSE) {
           getNextToken();
-          if (token == TT_ARGOPEN) {
-            getNextToken();
-          } else {
-            throwSyntaxError("'(' expected after 'for' keyword.");
-          }
-          if (token == TT_SEMICOLON) {
-            getNextToken();
-          } else {
-            expression();
-            if (token == TT_SEMICOLON) {
-              getNextToken();
-            } else {
-              throwSyntaxError("';' character after 'for' expected.");
-            }
-          }
-          if (token == TT_SEMICOLON) {
-            getNextToken();
-          } else {
-            expression();
-            if (token == TT_SEMICOLON) {
-              getNextToken();
-            } else {
-              throwSyntaxError("';' character after 'for' expected.");
-            }
-          }
-          if (token == TT_ARGCLOSE) {
-            getNextToken();
-          } else {
-            expression();
-            if (token == TT_ARGCLOSE) {
-              getNextToken();
-            } else {
-              throwSyntaxError("')' expected after 'for' condition.");
-            }
-          }
-          forStatement();
-          return;
-        } else if (token == TT_while) {
+        } else {
+          throwSyntaxError("')' expected after 'while' condition.");
+        }
+        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();
@@ -729,202 +1132,588 @@ public class PHPParser extends PHPKeywords {
           } else {
             throwSyntaxError("')' expected after 'while' condition.");
           }
-          whileStatement();
-          return;
-        } else if (token == TT_foreach) {
+        } else {
+          throwSyntaxError("'while' expected after 'do' keyword.");
+        }
+        if (token == TT_SEMICOLON) {
           getNextToken();
-          if (token == TT_ARGOPEN) {
-            getNextToken();
-          } else {
-            throwSyntaxError("'(' expected after 'foreach' keyword.");
-          }
-          expression();
-          if (token == TT_as) {
-            getNextToken();
-          } else {
-            throwSyntaxError("'as' expected after 'foreach' exxpression.");
+        } else {
+          if (!phpEnd) {
+            throwSyntaxError("';' expected after do-while statement.");
           }
+        }
+        return;
+      } else if (token == TT_foreach) {
+        getNextToken();
+        if (token == TT_ARGOPEN) {
+          getNextToken();
+        } else {
+          throwSyntaxError("'(' expected after 'foreach' keyword.");
+        }
+        expression();
+        if (token == TT_as) {
+          getNextToken();
+        } else {
+          throwSyntaxError("'as' expected after 'foreach' exxpression.");
+        }
+        variable();
+        if (token == TT_FOREACH) {
+          getNextToken();
           variable();
-          if (token == TT_FOREACH) {
-            getNextToken();
-            variable();
-          }
-          if (token == TT_ARGCLOSE) {
-            getNextToken();
-          } else {
-            throwSyntaxError("')' expected after 'foreach' expression.");
-          }
-          foreachStatement();
-          return;
+        }
+        if (token == TT_ARGCLOSE) {
+          getNextToken();
+        } else {
+          throwSyntaxError("')' expected after 'foreach' expression.");
+        }
+        foreachStatement();
+        return;
 
-        } else if (token == TT_continue || token == TT_break || token == TT_return) {
+      } else if (token == TT_continue || token == TT_break || token == TT_return) {
+        getNextToken();
+        if (token != TT_SEMICOLON) {
+          expression();
+        }
+        if (token == TT_SEMICOLON) {
           getNextToken();
-          if (token != TT_SEMICOLON) {
-            expression();
-          }
-          if (token == TT_SEMICOLON) {
-            getNextToken();
-          } else {
+        } else {
+          if (!phpEnd) {
             throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
           }
-          return;
+        }
+        return;
 
-        } else if (token == TT_echo) {
+      } else if (token == TT_echo) {
+        getNextToken();
+        expressionList();
+        if (token == TT_SEMICOLON) {
           getNextToken();
-          expressionList();
-          if (token == TT_SEMICOLON) {
-            getNextToken();
-          } else {
+        } else {
+          if (!phpEnd) {
             throwSyntaxError("';' expected after 'echo' statement.");
           }
-          return;
-
-        } else if (token == TT_print) {
+        }
+        return;
+      } else if (token == TT_print) {
+        getNextToken();
+        expression();
+        if (token == TT_SEMICOLON) {
           getNextToken();
-          expression();
-          if (token == TT_SEMICOLON) {
-            getNextToken();
-          } else {
+        } else {
+          if (!phpEnd) {
             throwSyntaxError("';' expected after 'print' statement.");
           }
-          return;
+        }
+        return;
 
-        } else if (token == TT_global || token == TT_static) {
+      } else if (token == TT_global || token == TT_static) {
+        getNextToken();
+        variableList();
+        if (token == TT_SEMICOLON) {
           getNextToken();
-          variableList();
-          if (token == TT_SEMICOLON) {
-            getNextToken();
-          } else {
+        } else {
+          if (!phpEnd) {
             throwSyntaxError("';' expected after 'global' or 'static' statement.");
           }
-          return;
+        }
+        return;
 
-        } else if (token == TT_unset) {
+      } else if (token == TT_unset) {
+        getNextToken();
+        if (token == TT_ARGOPEN) {
           getNextToken();
-          if (token == TT_ARGOPEN) {
-            getNextToken();
-          } else {
-            throwSyntaxError("'(' expected after 'unset' keyword.");
-          }
-          variableList();
-          if (token == TT_ARGCLOSE) {
-            getNextToken();
-          } else {
-            throwSyntaxError("')' expected after 'unset' statement.");
-          }
-          if (token == TT_SEMICOLON) {
-            getNextToken();
-          } else {
+        } else {
+          throwSyntaxError("'(' expected after 'unset' keyword.");
+        }
+        variableList();
+        if (token == TT_ARGCLOSE) {
+          getNextToken();
+        } else {
+          throwSyntaxError("')' expected after 'unset' statement.");
+        }
+        if (token == TT_SEMICOLON) {
+          getNextToken();
+        } else {
+          if (!phpEnd) {
             throwSyntaxError("';' expected after 'unset' statement.");
           }
-          return;
+        }
+        return;
 
-        } else if (token == TT_exit || token == TT_die) {
+        //      } else if (token == TT_exit || token == TT_die) {
+        //        getNextToken();
+        //        if (token != TT_SEMICOLON) {
+        //          exitStatus();
+        //        }
+        //        if (token == TT_SEMICOLON) {
+        //          getNextToken();
+        //        } else {
+        //          if (!phpEnd) {
+        //            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
+        //          }
+        //        }
+        //        return;
+
+      } else if (token == TT_define) {
+        getNextToken();
+        if (token == TT_ARGOPEN) {
           getNextToken();
-          if (token != TT_SEMICOLON) {
-            exitStatus();
-          }
-          if (token == TT_SEMICOLON) {
-            getNextToken();
-          } else {
-            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
-          }
-          return;
-
-        } else if (token == TT_define) {
+        } else {
+          throwSyntaxError("'(' expected after 'define' keyword.");
+        }
+        constant();
+        if (token == TT_COMMA) {
           getNextToken();
-          if (token == TT_ARGOPEN) {
-            getNextToken();
-          } else {
-            throwSyntaxError("'(' expected after 'define' keyword.");
-          }
-          constant();
-          if (token == TT_COMMA) {
-            getNextToken();
-          } else {
-            throwSyntaxError("',' expected after first 'define' constant.");
-          }
-          constant();
-          if (token == TT_ARGCLOSE) {
-            getNextToken();
-          } else {
-            throwSyntaxError("')' expected after 'define' statement.");
-          }
-          if (token == TT_SEMICOLON) {
-            getNextToken();
-          } else {
+        } else {
+          throwSyntaxError("',' expected after first 'define' constant.");
+        }
+        constant();
+        if (token == TT_ARGCLOSE) {
+          getNextToken();
+        } else {
+          throwSyntaxError("')' expected after 'define' statement.");
+        }
+        if (token == TT_SEMICOLON) {
+          getNextToken();
+        } else {
+          if (!phpEnd) {
             throwSyntaxError("';' expected after 'define' statement.");
           }
-          return;
-
         }
+        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) {
+      // compoundStatement
+      getNextToken();
+      if (token != TT_LISTCLOSE) {
+        statementList();
+      }
+      if (token == TT_LISTCLOSE) {
+        getNextToken();
+        return;
       } else {
-        if (token == TT_LISTOPEN) {
-          getNextToken();
-          statementList();
-          if (token == TT_LISTCLOSE) {
-            getNextToken();
-          } else {
-            throwSyntaxError("'}' expected.");
-          }
-        }
+        throwSyntaxError("'}' expected.");
+      }
+    } else {
+      if (token != TT_SEMICOLON) {
+        expression();
       }
-      expression();
       if (token == TT_SEMICOLON) {
         getNextToken();
+        return;
       } else {
-        throwSyntaxError("';' expected after expression.");
+        if (!phpEnd) {
+          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 labeledStatement() {
+  public void classBody() throws CoreException {
+    //'{' [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 expressionStatement() {
+  public void classElementList() throws CoreException {
+    do {
+      classElement();
+    } while (token == TT_function || token == TT_var);
   }
 
-  public void inclusionStatement() {
+  public void classElement() throws CoreException {
+    //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 compoundStatement() {
+  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 selectionStatement() {
+  public void functionDefinition() throws CoreException {
+    functionDeclarator();
+    compoundStatement();
   }
 
-  public void iterationStatement() {
+  public void functionDeclarator() {
+    //identifier '(' [parameter-list] ')'
+    if (token == TT_IDENTIFIER) {
+      getNextToken();
+      if (token == TT_ARGOPEN) {
+        getNextToken();
+      } else {
+        throwSyntaxError("'(' expected in function declaration.");
+      }
+      if (token != TT_ARGCLOSE) {
+        parameterList();
+      }
+      if (token != TT_ARGCLOSE) {
+        throwSyntaxError("')' expected in function declaration.");
+      } else {
+        getNextToken();
+      }
+    }
+  }
+  //
+  public void parameterList() {
+    //parameter-declaration
+    //parameter-list ',' parameter-declaration
+    do {
+      parameterDeclaration();
+      if (token != TT_COMMA) {
+        break;
+      }
+      getNextToken();
+    } while (true);
   }
 
-  public void jumpStatement() {
+  public void parameterDeclaration() {
+    //variable
+    //variable-reference
+    //variable '=' constant
+    if (token == TT_VARIABLE) {
+      getNextToken();
+      if (token == TT_ASSIGN) {
+        getNextToken();
+        constant();
+      }
+      return;
+    }
   }
 
-  public void outputStatement() {
+  public void labeledStatementList() throws CoreException {
+    if (token != TT_case && token != TT_default) {
+      throwSyntaxError("'case' or 'default' expected.");
+    }
+    do {
+      if (token == TT_case) {
+        getNextToken();
+        constant();
+        if (token == TT_DDOT) {
+          getNextToken();
+          statementList();
+        } else if (token == TT_SEMICOLON) {
+          setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO);
+          getNextToken();
+          statementList();
+        } else {
+          throwSyntaxError("':' character after 'case' constant expected.");
+        }
+      } else { // TT_default 
+        getNextToken();
+        if (token == TT_DDOT) {
+          getNextToken();
+          statementList();
+        } else {
+          throwSyntaxError("':' character after 'default' expected.");
+        }
+      }
+    } while (token == TT_case || token == TT_default);
   }
 
-  public void scopeStatement() {
+  //  public void labeledStatement() {
+  //    if (token == TT_case) {
+  //      getNextToken();
+  //      constant();
+  //      if (token == TT_DDOT) {
+  //        getNextToken();
+  //        statement();
+  //      } else {
+  //        throwSyntaxError("':' character after 'case' constant expected.");
+  //      }
+  //      return;
+  //    } else if (token == TT_default) {
+  //      getNextToken();
+  //      if (token == TT_DDOT) {
+  //        getNextToken();
+  //        statement();
+  //      } else {
+  //        throwSyntaxError("':' character after 'default' expected.");
+  //      }
+  //      return;
+  //    }
+  //  }
+
+  public void expressionStatement() {
   }
 
-  public void flowStatement() {
+  public void inclusionStatement() {
   }
 
-  public void definitionStatement() {
+  //  public void compoundStatement() {
+  //  }
+
+  //  public void selectionStatement() {
+  //  }
+  //
+  //  public void iterationStatement() {
+  //  }
+  //
+  //  public void jumpStatement() {
+  //  }
+  //
+  //  public void outputStatement() {
+  //  }
+  //
+  //  public void scopeStatement() {
+  //  }
+  //
+  //  public void flowStatement() {
+  //  }
+  //
+  //  public void definitionStatement() {
+  //  }
+
+  public void ifStatement() throws CoreException {
+    // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
+    if (token == TT_DDOT) {
+      getNextToken();
+      statementList();
+      switch (token) {
+        case TT_else :
+          getNextToken();
+          if (token == TT_DDOT) {
+            getNextToken();
+            statementList();
+          } else {
+            if (token == TT_if) { //'else if'
+              getNextToken();
+              elseifStatementList();
+            } else {
+              throwSyntaxError("':' expected after 'else'.");
+            }
+          }
+          break;
+        case TT_elseif :
+          getNextToken();
+          elseifStatementList();
+          break;
+      }
+
+      if (token != TT_endif) {
+        throwSyntaxError("'endif' expected.");
+      }
+      getNextToken();
+      if (token != TT_SEMICOLON) {
+        throwSyntaxError("';' expected after if-statement.");
+      }
+      getNextToken();
+    } else {
+      // statement [else-statement]
+      statement();
+      if (token == TT_elseif) {
+        getNextToken();
+        if (token == TT_ARGOPEN) {
+          getNextToken();
+        } else {
+          throwSyntaxError("'(' expected after 'elseif' keyword.");
+        }
+        expression();
+        if (token == TT_ARGCLOSE) {
+          getNextToken();
+        } else {
+          throwSyntaxError("')' expected after 'elseif' condition.");
+        }
+        ifStatement();
+      } else if (token == TT_else) {
+        getNextToken();
+        statement();
+      }
+    }
+  }
+  public void elseifStatementList() throws CoreException {
+    do {
+      elseifStatement();
+      switch (token) {
+        case TT_else :
+          getNextToken();
+          if (token == TT_DDOT) {
+            getNextToken();
+            statementList();
+            return;
+          } else {
+            if (token == TT_if) { //'else if'
+              getNextToken();
+            } else {
+              throwSyntaxError("':' expected after 'else'.");
+            }
+          }
+          break;
+        case TT_elseif :
+          getNextToken();
+          break;
+        default :
+          return;
+      }
+    } while (true);
   }
 
-  public void ifStatement() {
+  public void elseifStatement() throws CoreException {
+    if (token == TT_ARGOPEN) {
+      getNextToken();
+      expression();
+      if (token != TT_ARGOPEN) {
+        throwSyntaxError("')' expected in else-if-statement.");
+      }
+      getNextToken();
+      if (token != TT_DDOT) {
+        throwSyntaxError("':' expected in else-if-statement.");
+      }
+      getNextToken();
+      statementList();
+    }
   }
 
-  public void switchStatement() {
+  public void switchStatement() throws CoreException {
+    if (token == TT_DDOT) {
+      // ':' [labeled-statement-list] 'endswitch' ';'
+      getNextToken();
+      labeledStatementList();
+      if (token != TT_endswitch) {
+        throwSyntaxError("'endswitch' expected.");
+      }
+      getNextToken();
+      if (token != TT_SEMICOLON) {
+        throwSyntaxError("';' expected after switch-statement.");
+      }
+      getNextToken();
+    } else {
+      // '{' [labeled-statement-list] '}'
+      if (token != TT_LISTOPEN) {
+        throwSyntaxError("'{' expected in switch statement.");
+      }
+      getNextToken();
+      if (token != TT_LISTCLOSE) {
+        labeledStatementList();
+      }
+      if (token != TT_LISTCLOSE) {
+        throwSyntaxError("'}' expected in switch statement.");
+      }
+      getNextToken();
+
+    }
   }
 
-  public void forStatement() {
+  public void forStatement() throws CoreException {
+    if (token == TT_DDOT) {
+      getNextToken();
+      statementList();
+      if (token != TT_endfor) {
+        throwSyntaxError("'endfor' expected.");
+      }
+      getNextToken();
+      if (token != TT_SEMICOLON) {
+        throwSyntaxError("';' expected after for-statement.");
+      }
+      getNextToken();
+    } else {
+      statement();
+    }
   }
 
-  public void whileStatement() {
+  public void whileStatement() throws CoreException {
+    // ':' statement-list 'endwhile' ';'
+    if (token == TT_DDOT) {
+      getNextToken();
+      statementList();
+      if (token != TT_endwhile) {
+        throwSyntaxError("'endwhile' expected.");
+      }
+      getNextToken();
+      if (token != TT_SEMICOLON) {
+        throwSyntaxError("';' expected after while-statement.");
+      }
+      getNextToken();
+    } else {
+      statement();
+    }
   }
 
-  public void foreachStatement() {
+  public void foreachStatement() throws CoreException {
+    if (token == TT_DDOT) {
+      getNextToken();
+      statementList();
+      if (token != TT_endforeach) {
+        throwSyntaxError("'endforeach' expected.");
+      }
+      getNextToken();
+      if (token != TT_SEMICOLON) {
+        throwSyntaxError("';' expected after foreach-statement.");
+      }
+      getNextToken();
+    } else {
+      statement();
+    }
   }
 
   public void exitStatus() {
@@ -955,20 +1744,522 @@ public class PHPParser extends PHPKeywords {
   }
 
   public void expression() {
-    if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) {
+    //    if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) {
+    //      getNextToken();
+    //    } else {
+    logicalinclusiveorExpression();
+    //      while (token != TT_SEMICOLON) {
+    //        getNextToken();
+    //      //      }
+    //    }
+  }
+
+  public void postfixExpression() {
+    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;
+      case TT_INTERPOLATED_STRING :
+        getNextToken();
+        break;
+      case TT_ARGOPEN :
+        getNextToken();
+        if (token == TT_IDENTIFIER) {
+          // check if identifier is a type:
+          ident = identifier;
+          String str = identifier.toLowerCase();
+          for (int i = 0; i < PHP_TYPES.length; i++) {
+            if (PHP_TYPES[i].equals(str)) {
+              castFlag = true;
+              break;
+            }
+          }
+          if (castFlag) {
+            getNextToken();
+            if (token != TT_ARGCLOSE) {
+              throwSyntaxError(") expected after cast-type '" + ident + "'.");
+            }
+            getNextToken();
+            expression();
+            break;
+          }
+        }
+        if (!castFlag) {
+          expression();
+        }
+        if (token != TT_ARGCLOSE) {
+          throwSyntaxError(") expected in postfix-expression.");
+        }
+        getNextToken();
+        break;
+      case TT_DOUBLE_NUMBER :
+        getNextToken();
+        break;
+      case TT_INT_NUMBER :
+        getNextToken();
+        break;
+      case TT_VARIABLE :
+        ident = identifier;
+        getNextToken();
+        if (token == TT_LISTOPEN) {
+          getNextToken();
+          expression();
+          if (token != TT_LISTCLOSE) {
+            throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression.");
+          }
+          getNextToken();
+        }
+        break;
+      case TT_IDENTIFIER :
+        ident = identifier;
+        getNextToken();
+        if (token == TT_ARGOPEN) {
+          getNextToken();
+          if (token != TT_ARGCLOSE) {
+            expressionList();
+            if (token != TT_ARGCLOSE) {
+              throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
+            }
+          }
+          getNextToken();
+        }
+        break;
+      case TT_list :
+        getNextToken();
+        if (token == TT_ARGOPEN) {
+          getNextToken();
+          if (token == TT_COMMA) {
+            getNextToken();
+          }
+          expressionList();
+          if (token != TT_ARGCLOSE) {
+            throwSyntaxError("')' expected after 'list' keyword.");
+          }
+          getNextToken();
+          //          if (token == TT_SET) {
+          //            getNextToken();
+          //            logicalinclusiveorExpression();
+          //          }
+        } else {
+          throwSyntaxError("'(' expected after 'list' keyword.");
+        }
+        break;
+        //      case TT_exit :
+        //        getNextToken();
+        //        if (token != TT_SEMICOLON) {
+        //          exitStatus();
+        //        }
+        //        if (token == TT_SEMICOLON) {
+        //          getNextToken();
+        //        } else {
+        //          if (!phpEnd) {
+        //            throwSyntaxError("';' expected after 'exit' expression.");
+        //          }
+        //        }
+        //        break;
+        //      case TT_die :
+        //        getNextToken();
+        //        if (token != TT_SEMICOLON) {
+        //          exitStatus();
+        //        }
+        //        if (token == TT_SEMICOLON) {
+        //          getNextToken();
+        //        } else {
+        //          if (!phpEnd) {
+        //            throwSyntaxError("';' expected after 'die' expression.");
+        //          }
+        //        }
+        //        break;
+
+        //      case TT_array :
+        //        getNextToken();
+        //        if (token == TT_ARGOPEN) {
+        //          getNextToken();
+        //          if (token == TT_COMMA) {
+        //            getNextToken();
+        //          }
+        //          expressionList();
+        //          if (token != TT_ARGCLOSE) {
+        //            throwSyntaxError("')' expected after 'list' keyword.");
+        //          }
+        //          getNextToken();
+        //          if (token == TT_SET) {
+        //            getNextToken();
+        //            logicalinclusiveorExpression();
+        //          }
+        //        } else {
+        //          throwSyntaxError("'(' expected after 'list' keyword.");
+        //        }
+        //        break;
+    }
+    boolean while_flag = true;
+    do {
+      switch (token) {
+        case TT_PARTOPEN :
+          getNextToken();
+          expression();
+          if (token != TT_PARTCLOSE) {
+            throwSyntaxError("] expected in postfix-expression.");
+          }
+          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();
+              expression();
+              if (token != TT_LISTCLOSE) {
+                throwSyntaxError("} expected in postfix-expression.");
+              }
+              getNextToken();
+              break;
+            default :
+              throwSyntaxError("Syntax error after '->' token.");
+          }
+          break;
+        case TT_INCREMENT :
+          getNextToken();
+          break;
+        case TT_DECREMENT :
+          getNextToken();
+          break;
+        default :
+          while_flag = false;
+      }
+    } while (while_flag);
+  }
+
+  public void unaryExpression() {
+    switch (token) {
+      case TT_INCREMENT :
+        getNextToken();
+        unaryExpression();
+        break;
+      case TT_DECREMENT :
+        getNextToken();
+        unaryExpression();
+        break;
+        //'&' '*' '+' '-' '~' '!' 
+      case TT_AMPERSAND :
+        getNextToken();
+        castExpression();
+        break;
+      case TT_MULTIPLY :
+        getNextToken();
+        castExpression();
+        break;
+      case TT_ADD :
+        getNextToken();
+        castExpression();
+        break;
+      case TT_SUBTRACT :
+        getNextToken();
+        castExpression();
+        break;
+      case TT_TILDE :
+        getNextToken();
+        castExpression();
+        break;
+      case TT_NOT :
+        getNextToken();
+        castExpression();
+        break;
+      default :
+        postfixExpression();
+    }
+  }
+
+  public void castExpression() {
+    //    if (token == TT_ARGOPEN) {
+    //      getNextToken();
+    //      typeName();
+    //      if (token != TT_ARGCLOSE) {
+    //        throwSyntaxError(") expected after cast-expression.");
+    //      }
+    //      getNextToken();
+    //    }
+    unaryExpression();
+  }
+
+  public void typeName() {
+    //'string' 'unset' 'array' 'object'
+    //'bool' 'boolean'
+    //'real' 'double' 'float'
+    //'int' 'integer'
+    String ident = "";
+    if (token == TT_IDENTIFIER) {
+      ident = identifier;
+      String str = identifier.toLowerCase();
       getNextToken();
-    } else {
-      postfixExpression();
-      //      while (token != TT_SEMICOLON) {
-      //        getNextToken();
-      //      }
+      for (int i = 0; i < PHP_TYPES.length; i++) {
+        if (PHP_TYPES[i].equals(str)) {
+          return;
+        }
+      }
     }
+    throwSyntaxError("Expected type cast '( <type-name> )'; Got '" + ident + "'.");
   }
 
-  public void postfixExpression() {
+  public void assignExpression() {
+    castExpression();
+    if (token == TT_ASSIGN) { // =
+      getNextToken();
+      logicalinclusiveorExpression();
+    } else if (token == TT_DOTASSIGN) { // .=
+      getNextToken();
+      logicalinclusiveorExpression();
+    } 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();
+    } else if (token == TT_MODASSIGN) { // %=
+      getNextToken();
+      logicalinclusiveorExpression();
+    } else if (token == TT_ANDASSIGN) { // &=
+      getNextToken();
+      logicalinclusiveorExpression();
+    } else if (token == TT_POWASSIGN) { // ^=
+      getNextToken();
+      logicalinclusiveorExpression();
+    } else if (token == TT_LSHIFTASSIGN) { // <<=
+      getNextToken();
+      logicalinclusiveorExpression();
+    } else if (token == TT_RSHIFTASSIGN) { // >>=
+      getNextToken();
+      logicalinclusiveorExpression();
+    } else if (token == TT_TILDEASSIGN) { // ~=
+      getNextToken();
+      logicalinclusiveorExpression();
+    }
+  }
+
+  public void multiplicativeExpression() {
+    do {
+      assignExpression();
+      if (token != TT_MULTIPLY && token != TT_DIV && token != TT_MOD) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void concatenationExpression() {
+    do {
+      multiplicativeExpression();
+      if (token != TT_DOT) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void additiveExpression() {
+    do {
+      concatenationExpression();
+      if (token != TT_ADD && token != TT_SUBTRACT) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void shiftExpression() {
+    do {
+      additiveExpression();
+      if (token != TT_LSHIFT && token != TT_RSHIFT) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void relationalExpression() {
+    do {
+      shiftExpression();
+      if (token != TT_LESS && token != TT_GREATER && token != TT_LESSEQUAL && token != TT_GREATEREQUAL) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void identicalExpression() {
+    do {
+      relationalExpression();
+      if (token != TT_EX_EQUAL && token != TT_EX_UNEQUAL) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void equalityExpression() {
+    do {
+      identicalExpression();
+      if (token != TT_EQUAL && token != TT_UNEQUAL) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void ternaryExpression() {
+    equalityExpression();
+    if (token == TT_QUESTIONMARK) {
+      getNextToken();
+      expression();
+      if (token == TT_DDOT) {
+        getNextToken();
+        expression();
+      } else {
+        throwSyntaxError("':' expected in ternary operator '? :'.");
+      }
+    }
+  }
+
+  public void andExpression() {
+    do {
+      ternaryExpression();
+      if (token != TT_AMPERSAND) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void exclusiveorExpression() {
+    do {
+      andExpression();
+      if (token != TT_POW) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void inclusiveorExpression() {
+    do {
+      exclusiveorExpression();
+      if (token != TT_LINE) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void booleanandExpression() {
+    do {
+      inclusiveorExpression();
+      if (token != TT_AND) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void booleanorExpression() {
+    do {
+      booleanandExpression();
+      if (token != TT_OR) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
 
+  public void logicalandExpression() {
+    do {
+      booleanorExpression();
+      if (token != TT_and) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  public void logicalexclusiveorExpression() {
+    do {
+      logicalandExpression();
+      if (token != TT_xor) {
+        return;
+      }
+      getNextToken();
+    } while (true);
   }
 
+  public void logicalinclusiveorExpression() {
+    do {
+      logicalexclusiveorExpression();
+      if (token != TT_or) {
+        return;
+      }
+      getNextToken();
+    } while (true);
+  }
+
+  //  public void assignmentExpression() {
+  //    if (token == TT_VARIABLE) {
+  //      getNextToken();
+  //      if (token == TT_SET) {
+  //        getNextToken();
+  //        logicalinclusiveorExpression();
+  //      }
+  //    } else {
+  //      logicalinclusiveorExpression();
+  //    }
+  //  }
+
   public void variableList() {
     do {
       variable();
@@ -989,6 +2280,57 @@ public class PHPParser extends PHPKeywords {
   }
 
   public void constant() {
-
+    switch (token) {
+      case TT_ADD :
+        getNextToken();
+        switch (token) {
+          case TT_DOUBLE_NUMBER :
+            getNextToken();
+            break;
+          case TT_INT_NUMBER :
+            getNextToken();
+            break;
+          default :
+            throwSyntaxError("Constant expected after '+' presign.");
+        }
+        break;
+      case TT_SUBTRACT :
+        getNextToken();
+        switch (token) {
+          case TT_DOUBLE_NUMBER :
+            getNextToken();
+            break;
+          case TT_INT_NUMBER :
+            getNextToken();
+            break;
+          default :
+            throwSyntaxError("Constant expected after '-' presign.");
+        }
+        break;
+      case TT_null :
+        getNextToken();
+        break;
+      case TT_false :
+        getNextToken();
+        break;
+      case TT_true :
+        getNextToken();
+        break;
+      case TT_STRING_CONSTANT :
+        getNextToken();
+        break;
+      case TT_INTERPOLATED_STRING :
+        getNextToken();
+        break;
+      case TT_DOUBLE_NUMBER :
+        getNextToken();
+        break;
+      case TT_INT_NUMBER :
+        getNextToken();
+        break;
+      default :
+        throwSyntaxError("Constant expected.");
+    }
   }
+
 }
\ No newline at end of file