misc changes
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Parser.java
index f389faa..ab95c81 100644 (file)
@@ -1,6 +1,6 @@
 /**********************************************************************
  Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de
- All rights reserved. This program and the accompanying materials
+ All rights reserved. This program and the accompanying material
  are made available under the terms of the Common Public License v1.0
  which accompanies this distribution, and is available at
  http://www.eclipse.org/legal/cpl-v10.html
@@ -23,7 +23,6 @@ import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclarati
 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
-import net.sourceforge.phpeclipse.phpeditor.PHPString;
 import org.eclipse.core.resources.IFile;
 public class Parser //extends PHPParserSuperclass
     implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
@@ -62,7 +61,7 @@ public class Parser //extends PHPParserSuperclass
   private String stringValue;
   /** Contains the current expression. */
   // private StringBuffer expression;
-  private boolean phpMode;
+  //private boolean phpMode;
   protected int modifiers;
   protected int modifiersSourceStart;
   protected Parser() {
@@ -136,7 +135,7 @@ public class Parser //extends PHPParserSuperclass
   private void throwSyntaxError(String error) {
     int problemStartPosition = scanner.getCurrentTokenStartPosition();
     int problemEndPosition = scanner.getCurrentTokenEndPosition();
-    throwSyntaxError(error, problemStartPosition, problemEndPosition);
+    throwSyntaxError(error, problemStartPosition, problemEndPosition+1);
   }
   /**
    * This method will throw the SyntaxError. It will add the good lines and
@@ -206,426 +205,6 @@ public class Parser //extends PHPParserSuperclass
     }
     return;
   }
-  /**
-   * Get a number. if it's a <code>double</code> the number will be stored in
-   * <code>doubleNumber</code> and the token will have the value
-   * {@link Parser#TokenNameDOUBLE_NUMBER}<br />
-   * if it's a <code>double</code> the number will be stored in <code>longNumber</code>
-   * and the token will have the value {@link Parser#TokenNameINT_NUMBER}
-   */
-  //  private void getNumber() {
-  //    StringBuffer inum = new StringBuffer();
-  //    char dFlag = ' ';
-  //    int numFormat = 10;
-  //
-  //    // save first digit
-  //    char firstCh = ch;
-  //    inum.append(ch);
-  //
-  //    getChar();
-  //    // determine number conversions:
-  //    if (firstCh == '0') {
-  //      switch (ch) {
-  //        case 'b' :
-  //          numFormat = 2;
-  //          getChar();
-  //          break;
-  //        case 'B' :
-  //          numFormat = 2;
-  //          getChar();
-  //          break;
-  //        case 'o' :
-  //          numFormat = 8;
-  //          getChar();
-  //          break;
-  //        case 'O' :
-  //          numFormat = 8;
-  //          getChar();
-  //          break;
-  //        case 'x' :
-  //          numFormat = 16;
-  //          getChar();
-  //          break;
-  //        case 'X' :
-  //          numFormat = 16;
-  //          getChar();
-  //          break;
-  //      }
-  //    }
-  //
-  //    if (numFormat == 16) {
-  //      while ((ch >= '0' && ch <= '9')
-  //        || (ch >= 'a' && ch <= 'f')
-  //        || (ch >= 'A' && ch <= 'F')) {
-  //        inum.append(ch);
-  //        getChar();
-  //      }
-  //    } else {
-  //      while ((ch >= '0' && ch <= '9')
-  //        || (ch == '.')
-  //        || (ch == 'E')
-  //        || (ch == 'e')) {
-  //        if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
-  //          if (ch == '.' && dFlag != ' ') {
-  //            break;
-  //          }
-  //          if ((dFlag == 'E') || (dFlag == 'e')) {
-  //            break;
-  //          }
-  //          dFlag = ch;
-  //          inum.append(ch);
-  //          getChar();
-  //          if ((ch == '-') || (ch == '+')) {
-  //            inum.append(ch);
-  //            getChar();
-  //          }
-  //        } else {
-  //          inum.append(ch);
-  //          getChar();
-  //        }
-  //      }
-  //    }
-  //    chIndx--;
-  //
-  //    try {
-  //      if (dFlag != ' ') {
-  //        doubleNumber = new Double(inum.toString());
-  //        token = TokenNameDoubleLiteral;
-  //        return;
-  //      } else {
-  //        longNumber = Long.valueOf(inum.toString(), numFormat);
-  //        token = TokenNameIntegerLiteral;
-  //        return;
-  //      }
-  //
-  //    } catch (Throwable e) {
-  //      throwSyntaxError("Number format error: " + inum.toString());
-  //    }
-  //  }
-  //
-  //  /**
-  //   * Get a String.
-  //   * @param openChar the opening char ('\'', '"', '`')
-  //   * @param typeString the type of string {@link
-  // #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
-  //   * @param errorMsg the error message in case of parse error in the string
-  //   */
-  //  private void getString(
-  //    final char openChar,
-  //    final int typeString,
-  //    final String errorMsg) {
-  //    StringBuffer sBuffer = new StringBuffer();
-  //    boolean openString = true;
-  //    int startRow = rowCount;
-  //    while (str.length() > chIndx) {
-  //      ch = str.charAt(chIndx++);
-  //      if (ch == '\\') {
-  //        sBuffer.append(ch);
-  //        if (str.length() > chIndx) {
-  //          ch = str.charAt(chIndx++);
-  //          sBuffer.append(ch);
-  //        }
-  //      } else if (ch == openChar) {
-  //        openString = false;
-  //        break;
-  //      } else if (ch == '\n') {
-  //        rowCount++;
-  //        columnCount = chIndx;
-  //      } else {
-  //        sBuffer.append(ch);
-  //      }
-  //    }
-  //    if (openString) {
-  //      if (typeString == TokenNameStringConstant) {
-  //        throwSyntaxError(errorMsg, startRow);
-  //      } else {
-  //        throwSyntaxError(errorMsg);
-  //      }
-  //    }
-  //    token = typeString;
-  //    stringValue = sBuffer.toString();
-  //  }
-  //   public void htmlParserTester(String input) {
-  //           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) {
-  //                                   if (ch == '/' && i < input.length()) {
-  //                                           ch2 = input.charAt(i++);
-  //                                           if (ch2 == '/') {
-  //                                                   while (i < input.length()) {
-  //                                                           ch = input.charAt(i++);
-  //                                                           if (ch == '?' && i < input.length()) {
-  //                                                                   ch2 = input.charAt(i++);
-  //                                                                   if (ch2 == '>') {
-  //                                                                           // php end
-  //                                                                           phpMode = false;
-  //                                                                           phpList.add(
-  //                                                                                   new PHPString(
-  //                                                                                           input.substring(
-  //                                                                                                   startIndex,
-  //                                                                                                   i - 2),
-  //                                                                                           startLineNumber));
-  //                                                                           continue;
-  //                                                                   }
-  //                                                                   i--;
-  //                                                           } else if (ch == '\n') {
-  //                                                                   lineNumber++;
-  //                                                                   break;
-  //                                                           }
-  //                                                   }
-  //                                                   continue;
-  //                                           } else if (ch2 == '*') {
-  //                                                   // multi-line comment
-  //                                                   while (i < input.length()) {
-  //                                                           ch = input.charAt(i++);
-  //                                                           if (ch == '\n') {
-  //                                                                   lineNumber++;
-  //                                                           } else if (ch == '*' && i < input.length()) {
-  //                                                                   ch2 = input.charAt(i++);
-  //                                                                   if (ch2 == '/') {
-  //                                                                           break;
-  //                                                                   }
-  //                                                                   i--;
-  //                                                           }
-  //                                                   }
-  //                                                   continue;
-  //                                           } else {
-  //                                                   i--;
-  //                                           }
-  //                                   } else if (ch == '#') {
-  //                                           while (i < input.length()) {
-  //                                                   ch = input.charAt(i++);
-  //                                                   if (ch == '?' && i < input.length()) {
-  //                                                           ch2 = input.charAt(i++);
-  //                                                           if (ch2 == '>') {
-  //                                                                   // php end
-  //                                                                   phpMode = false;
-  //                                                                   phpList.add(
-  //                                                                           new PHPString(
-  //                                                                                   input.substring(startIndex, i - 2),
-  //                                                                                   startLineNumber));
-  //                                                                   continue;
-  //                                                           }
-  //                                                           i--;
-  //                                                   } else if (ch == '\n') {
-  //                                                           lineNumber++;
-  //                                                           break;
-  //                                                   }
-  //                                           }
-  //                                           continue;
-  //                                   } else if (ch == '"') {
-  //                                           ch = ' ';
-  //                                           while (i < input.length()) {
-  //                                                   ch = input.charAt(i++);
-  //                                                   if (ch == '\n') {
-  //                                                           lineNumber++;
-  //                                                   } else if (
-  //                                                           ch == '\\' && i < input.length()) { // escape
-  //                                                           i++;
-  //                                                   } else if (ch == '"') {
-  //                                                           break;
-  //                                                   }
-  //                                           }
-  //                                           continue;
-  //                                   } else if (ch == '\'') {
-  //                                           ch = ' ';
-  //                                           while (i < input.length()) {
-  //                                                   ch = input.charAt(i++);
-  //                                                   if (ch == '\n') {
-  //                                                           lineNumber++;
-  //                                                   } else if (
-  //                                                           ch == '\\' && i < input.length()) { // escape
-  //                                                           i++;
-  //                                                   } else if (ch == '\'') {
-  //                                                           break;
-  //                                                   }
-  //                                           }
-  //                                           continue;
-  //                                   }
-  //
-  //                                   if (ch == '?' && i < input.length()) {
-  //                                           ch2 = input.charAt(i++);
-  //                                           if (ch2 == '>') {
-  //                                                   // php end
-  //                                                   phpMode = false;
-  //                                                   phpList.add(
-  //                                                           new PHPString(
-  //                                                                   input.substring(startIndex, i - 2),
-  //                                                                   startLineNumber));
-  //                                                   continue;
-  //                                           }
-  //                                           i--;
-  //                                   }
-  //                           }
-  //                   }
-  //
-  //                   if (!phpFound) {
-  //                           setMarker(
-  //                                   "No PHP source code found.",
-  //                                   lineNumber,
-  //                                   PHPParser.INFO);
-  //                   } else {
-  //                           if (phpMode) {
-  //                                   setMarker(
-  //                                           "Open PHP tag at end of file.",
-  //                                           lineNumber,
-  //                                           PHPParser.INFO);
-  //                                   phpList.add(
-  //                                           new PHPString(
-  //                                                   input.substring(startIndex, i - 2),
-  //                                                   startLineNumber));
-  //                           }
-  //                           // 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)+"?>");
-  //                           // }
-  //                           phpParserTester(null, 1);
-  //                           // PHPString temp;
-  //                           // for(int j=0;j<phpList.size();j++) {
-  //                           // temp = (PHPString) phpList.get(j);
-  //                           // parser.start(temp.getPHPString(), temp.getLineNumber());
-  //                           // }
-  //                   }
-  //           } catch (CoreException e) {
-  //           }
-  //   }
-  public void phpParserTester(String s, int rowCount) {
-    this.str = s;
-    if (s == null) {
-      if (phpList.size() != 0) {
-        this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
-      }
-    }
-    this.token = TokenNameEOF;
-    //    this.chIndx = 0;
-    //    this.rowCount = rowCount;
-    //    this.columnCount = 0;
-    this.phpEnd = false;
-    this.phpMode = true;
-    scanner.setSource(s.toCharArray());
-    scanner.setPHPMode(true);
-    getNextToken();
-    do {
-      try {
-        if (token != TokenNameEOF && token != TokenNameERROR) {
-          statementList();
-        }
-        if (token != TokenNameEOF) {
-          if (token == TokenNameERROR) {
-            throwSyntaxError("Scanner error (Found unknown token: "
-                + scanner.toStringAction(token) + ")");
-          }
-          if (token == TokenNameRPAREN) {
-            throwSyntaxError("Too many closing ')'; end-of-file not reached.");
-          }
-          if (token == TokenNameRBRACE) {
-            throwSyntaxError("Too many closing '}'; end-of-file not reached.");
-          }
-          if (token == TokenNameRBRACKET) {
-            throwSyntaxError("Too many closing ']'; end-of-file not reached.");
-          }
-          if (token == TokenNameLPAREN) {
-            throwSyntaxError("Read character '('; end-of-file not reached.");
-          }
-          if (token == TokenNameLBRACE) {
-            throwSyntaxError("Read character '{';  end-of-file not reached.");
-          }
-          if (token == TokenNameLBRACKET) {
-            throwSyntaxError("Read character '[';  end-of-file not reached.");
-          }
-          throwSyntaxError("End-of-file not reached.");
-        }
-        return;
-      } catch (SyntaxError err) {
-        if (s != null) {
-          throw err;
-        } else {
-          //   setMarker(err.getMessage(), err.getLine(), ERROR);
-          //          setMarker(err.getMessage(),
-          // scanner.getCurrentTokenStartPosition(),
-          // scanner.getCurrentTokenEndPosition(), ERROR);
-        }
-        // if an error occured,
-        // try to find keywords 'class' or 'function'
-        // to parse the rest of the string
-        while (token != TokenNameEOF && token != TokenNameERROR) {
-          if (token == TokenNameabstract || token == TokenNamefinal
-              || token == TokenNameclass || token == TokenNamefunction) {
-            break;
-          }
-          getNextToken();
-        }
-        if (token == TokenNameEOF || token == TokenNameERROR) {
-          return;
-        }
-      }
-    } while (true);
-  }
   public void init(String s) {
     this.str = s;
     this.token = TokenNameEOF;
@@ -633,7 +212,7 @@ public class Parser //extends PHPParserSuperclass
     //    this.rowCount = 1;
     //    this.columnCount = 0;
     this.phpEnd = false;
-    this.phpMode = false;
+    //    this.phpMode = false;
     /* scanner initialization */
     scanner.setSource(s.toCharArray());
     scanner.setPHPMode(false);
@@ -647,7 +226,7 @@ public class Parser //extends PHPParserSuperclass
     //    this.rowCount = 1;
     //    this.columnCount = 0;
     this.phpEnd = false;
-    this.phpMode = phpMode;
+    //    this.phpMode = phpMode;
     scanner.setPHPMode(phpMode);
   }
   /**
@@ -746,7 +325,7 @@ public class Parser //extends PHPParserSuperclass
   //    return outlineInfo;
   //  }
   private boolean isVariable() {
-    return token == TokenNameVariable || token == TokenNamethis;
+    return token == TokenNameVariable; //  || token == TokenNamethis;
   }
   //  private void parseDeclarations(PHPOutlineInfo outlineInfo,
   //      OutlineableWithChildren current, boolean goBack) {
@@ -949,49 +528,51 @@ public class Parser //extends PHPParserSuperclass
     // TokenNamenew) {
     //  char[] ident = scanner.getCurrentIdentifierSource();
     //  String keyword = new String(ident);
-    if (token == TokenNameAT) {
-      getNextToken();
-      if (token != TokenNamerequire && token != TokenNamerequire_once
-          && token != TokenNameinclude && token != TokenNameinclude_once
-          && token != TokenNameIdentifier && token != TokenNameVariable
-          && token != TokenNamethis && token != TokenNameStringInterpolated) {
-        throwSyntaxError("identifier expected after '@'.");
-      }
-    }
-    if (token == TokenNameinclude || token == TokenNameinclude_once) {
-      getNextToken();
-      if (token == TokenNameLPAREN) {
-        expr();
-        if (token == TokenNameSEMICOLON) {
-          getNextToken();
-        } else {
-          if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
-            throwSyntaxError("';' expected after 'include' or 'include_once'.");
-          }
-          //        getNextToken();
-        }
-      } else {
-        concatenationExpression();
-      }
-      return;
-    } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
-      getNextToken();
-      //constant();
-      if (token == TokenNameLPAREN) {
-        expr();
-        if (token == TokenNameSEMICOLON) {
-          getNextToken();
-        } else {
-          if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
-            throwSyntaxError("';' expected after 'require' or 'require_once'.");
-          }
-          //        getNextToken();
-        }
-      } else {
-        concatenationExpression();
-      }
-      return;
-    } else if (token == TokenNameif) {
+    //    if (token == TokenNameAT) {
+    //      getNextToken();
+    //      if (token != TokenNamerequire && token != TokenNamerequire_once
+    //          && token != TokenNameinclude && token != TokenNameinclude_once
+    //          && token != TokenNameIdentifier && token != TokenNameVariable
+    //          && token != TokenNameStringInterpolated) {
+    //        throwSyntaxError("identifier expected after '@'.");
+    //      }
+    //    }
+    //    if (token == TokenNameinclude || token == TokenNameinclude_once) {
+    //      getNextToken();
+    //      if (token == TokenNameLPAREN) {
+    //        expr();
+    //        if (token == TokenNameSEMICOLON) {
+    //          getNextToken();
+    //        } else {
+    //          if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
+    //            throwSyntaxError("';' expected after 'include' or 'include_once'.");
+    //          }
+    //          // getNextToken();
+    //        }
+    //      } else {
+    //        concatenationExpression();
+    //      }
+    //      return;
+    //    } else if (token == TokenNamerequire || token == TokenNamerequire_once)
+    // {
+    //      getNextToken();
+    //      //constant();
+    //      if (token == TokenNameLPAREN) {
+    //        expr();
+    //        if (token == TokenNameSEMICOLON) {
+    //          getNextToken();
+    //        } else {
+    //          if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
+    //            throwSyntaxError("';' expected after 'require' or 'require_once'.");
+    //          }
+    //          // getNextToken();
+    //        }
+    //      } else {
+    //        concatenationExpression();
+    //      }
+    //      return;
+    //    } else
+    if (token == TokenNameif) {
       getNextToken();
       if (token == TokenNameLPAREN) {
         getNextToken();
@@ -1109,7 +690,7 @@ public class Parser //extends PHPParserSuperclass
       if (token == TokenNameSEMICOLON) {
         getNextToken();
       } else {
-        if (token != TokenNameStopPHP) {
+        if (token != TokenNameINLINE_HTML) {
           throwSyntaxError("';' expected after do-while statement.");
         }
         getNextToken();
@@ -1128,7 +709,9 @@ public class Parser //extends PHPParserSuperclass
       } else {
         throwSyntaxError("'as' expected after 'foreach' exxpression.");
       }
-      variable();
+      //      variable();
+      foreach_variable();
+      foreach_optional_arg();
       if (token == TokenNameEQUAL_GREATER) {
         getNextToken();
         variable();
@@ -1149,7 +732,7 @@ public class Parser //extends PHPParserSuperclass
       if (token == TokenNameSEMICOLON) {
         getNextToken();
       } else {
-        if (token != TokenNameStopPHP) {
+        if (token != TokenNameINLINE_HTML) {
           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
         }
         getNextToken();
@@ -1161,12 +744,15 @@ public class Parser //extends PHPParserSuperclass
       if (token == TokenNameSEMICOLON) {
         getNextToken();
       } else {
-        if (token != TokenNameStopPHP) {
+        if (token != TokenNameINLINE_HTML) {
           throwSyntaxError("';' expected after 'echo' statement.");
         }
         getNextToken();
       }
       return;
+    } else if (token == TokenNameINLINE_HTML) {
+      getNextToken();
+      return;
       //    } else if (token == TokenNameprint) {
       //      getNextToken();
       //      expression();
@@ -1179,14 +765,26 @@ public class Parser //extends PHPParserSuperclass
       //        getNextToken();
       //      }
       //      return;
-    } else if (token == TokenNameglobal || token == TokenNamestatic) {
+    } else if (token == TokenNameglobal) {
       getNextToken();
-      variableList();
+      global_var_list();
       if (token == TokenNameSEMICOLON) {
         getNextToken();
       } else {
-        if (token != TokenNameStopPHP) {
-          throwSyntaxError("';' expected after 'global' or 'static' statement.");
+        if (token != TokenNameINLINE_HTML) {
+          throwSyntaxError("';' expected after 'global' statement.");
+        }
+        getNextToken();
+      }
+      return;
+    } else if (token == TokenNamestatic) {
+      getNextToken();
+      static_var_list();
+      if (token == TokenNameSEMICOLON) {
+        getNextToken();
+      } else {
+        if (token != TokenNameINLINE_HTML) {
+          throwSyntaxError("';' expected after 'static' statement.");
         }
         getNextToken();
       }
@@ -1207,59 +805,12 @@ public class Parser //extends PHPParserSuperclass
       if (token == TokenNameSEMICOLON) {
         getNextToken();
       } else {
-        if (token != TokenNameStopPHP) {
+        if (token != TokenNameINLINE_HTML) {
           throwSyntaxError("';' expected after 'unset' statement.");
         }
         getNextToken();
       }
       return;
-      //      } else if (token == TokenNameexit || token == TokenNamedie) {
-      //        getNextToken();
-      //        if (token != TokenNameSEMICOLON) {
-      //          exitStatus();
-      //        }
-      //        if (token == TokenNameSEMICOLON) {
-      //          getNextToken();
-      //        } else {
-      //          if (token != TokenNameStopPHP) {
-      //            throwSyntaxError("';' expected after 'exit' or 'die'
-      // statement.");
-      //          }
-      //          getNextToken();
-      //        }
-      //        return;
-      //    } else if (token == TokenNamedefine) {
-      //      getNextToken();
-      //      if (token == TokenNameLPAREN) {
-      //        getNextToken();
-      //      } else {
-      //        throwSyntaxError("'(' expected after 'define' keyword.");
-      //      }
-      //      expr();
-      //      if (token == TokenNameCOMMA) {
-      //        getNextToken();
-      //      } else {
-      //        throwSyntaxError("',' expected after first 'define' constant.");
-      //      }
-      //      expr();
-      //      if (token == TokenNameCOMMA) {
-      //        getNextToken();
-      //        expr();
-      //      }
-      //      if (token == TokenNameRPAREN) {
-      //        getNextToken();
-      //      } else {
-      //        throwSyntaxError("')' expected after 'define' statement.");
-      //      }
-      //      if (token == TokenNameSEMICOLON) {
-      //        getNextToken();
-      //      } else {
-      //        if (token != TokenNameStopPHP) {
-      //          throwSyntaxError("';' expected after 'define' statement.");
-      //        }
-      //        getNextToken();
-      //      }
-      //      return;
     } else if (token == TokenNamefunction) {
       MethodDeclaration methodDecl = new MethodDeclaration(
           this.compilationUnit.compilationResult);
@@ -1268,6 +819,53 @@ public class Parser //extends PHPParserSuperclass
       getNextToken();
       functionDefinition(methodDecl);
       return;
+    } else if (token == TokenNametry) {
+      getNextToken();
+      if (token != TokenNameLBRACE) {
+        throwSyntaxError("'{' expected in 'try' statement.");
+      }
+      getNextToken();
+      statementList();
+      if (token != TokenNameRBRACE) {
+        throwSyntaxError("'}' expected in 'try' statement.");
+      }
+      getNextToken();
+      return;
+    } else if (token == TokenNamecatch) {
+      getNextToken();
+      if (token != TokenNameLPAREN) {
+        throwSyntaxError("'(' expected in 'catch' statement.");
+      }
+      getNextToken();
+      fully_qualified_class_name();
+      if (token != TokenNameVariable) {
+        throwSyntaxError("Variable expected in 'catch' statement.");
+      }
+      getNextToken();
+      if (token != TokenNameRPAREN) {
+        throwSyntaxError("')' expected in 'catch' statement.");
+      }
+      getNextToken();
+      if (token != TokenNameLBRACE) {
+        throwSyntaxError("'{' expected in 'catch' statement.");
+      }
+      getNextToken();
+      statementList();
+      if (token != TokenNameRBRACE) {
+        throwSyntaxError("'}' expected in 'catch' statement.");
+      }
+      getNextToken();
+      additional_catches();
+      return;
+    } else if (token == TokenNamethrow) {
+      getNextToken();
+      expr();
+      if (token == TokenNameSEMICOLON) {
+        getNextToken();
+      } else {
+        throwSyntaxError("';' expected after 'throw' exxpression.");
+      }
+      return;
     } else if (token == TokenNamefinal || token == TokenNameabstract
         || token == TokenNameclass || token == TokenNameinterface) {
       TypeDeclaration typeDecl = new TypeDeclaration(
@@ -1306,7 +904,7 @@ public class Parser //extends PHPParserSuperclass
         getNextToken();
         return;
       } else {
-        if (token != TokenNameStopPHP && token != TokenNameEOF) {
+        if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
           throwSyntaxError("';' expected after expression (Found token: "
               + scanner.toStringAction(token) + ")");
         }
@@ -1314,6 +912,104 @@ public class Parser //extends PHPParserSuperclass
       }
     }
   }
+  private void additional_catches() {
+    while (token == TokenNamecatch) {
+      getNextToken();
+      if (token != TokenNameLPAREN) {
+        throwSyntaxError("'(' expected in 'catch' statement.");
+      }
+      getNextToken();
+      fully_qualified_class_name();
+      if (token != TokenNameVariable) {
+        throwSyntaxError("Variable expected in 'catch' statement.");
+      }
+      getNextToken();
+      if (token != TokenNameRPAREN) {
+        throwSyntaxError("')' expected in 'catch' statement.");
+      }
+      getNextToken();
+      if (token != TokenNameLBRACE) {
+        throwSyntaxError("'{' expected in 'catch' statement.");
+      }
+      getNextToken();
+      statementList();
+      if (token != TokenNameRBRACE) {
+        throwSyntaxError("'}' expected in 'catch' statement.");
+      }
+      getNextToken();
+    }
+  }
+  private void foreach_variable() {
+    // w_variable
+    //| '&' w_variable
+    if (token == TokenNameAND) {
+      getNextToken();
+    }
+    w_variable();
+  }
+  private void foreach_optional_arg() {
+    // /* empty */
+    //| T_DOUBLE_ARROW foreach_variable
+    if (token == TokenNameEQUAL_GREATER) {
+      getNextToken();
+      foreach_variable();
+    }
+  }
+  private void global_var_list() {
+    //  global_var_list:
+    // global_var_list ',' global_var
+    //| global_var
+    while (true) {
+      global_var();
+      if (token != TokenNameCOMMA) {
+        break;
+      }
+      getNextToken();
+    }
+  }
+  private void global_var() {
+    //global_var:
+    // T_VARIABLE
+    //| '$' r_variable
+    //| '$' '{' expr '}'
+    if (token == TokenNameVariable) {
+      getNextToken();
+    } else if (token == TokenNameDOLLAR) {
+      getNextToken();
+      if (token == TokenNameLPAREN) {
+        getNextToken();
+        expr();
+        if (token != TokenNameLPAREN) {
+          throwSyntaxError("')' expected in global variable.");
+        }
+        getNextToken();
+      } else {
+        r_variable();
+      }
+    }
+  }
+  private void static_var_list() {
+    //static_var_list:
+    // static_var_list ',' T_VARIABLE
+    //| static_var_list ',' T_VARIABLE '=' static_scalar
+    //| T_VARIABLE
+    //| T_VARIABLE '=' static_scalar
+    while (true) {
+      if (token == TokenNameVariable) {
+        getNextToken();
+        if (token == TokenNameEQUAL) {
+          getNextToken();
+          static_scalar();
+        }
+        if (token != TokenNameCOMMA) {
+          break;
+        }
+        getNextToken();
+      } else {
+        break;
+      }
+    }
+  }
   private void unset_variables() {
     //    unset_variables:
     //                 unset_variable
@@ -1387,14 +1083,13 @@ public class Parser //extends PHPParserSuperclass
         //             /* empty */
         //     | T_EXTENDS fully_qualified_class_name
         if (token == TokenNameextends) {
-          getNextToken();
-          if (token == TokenNameIdentifier) {
-            getNextToken();
-          } else {
-            throwSyntaxError("Class name expected after keyword 'extends'.",
-                scanner.getCurrentTokenStartPosition(), scanner
-                    .getCurrentTokenEndPosition());
-          }
+          interface_extends_list();
+          //          getNextToken();
+          //          if (token != TokenNameIdentifier) {
+          //            throwSyntaxError("Class name expected after keyword 'extends'.",
+          //                scanner.getCurrentTokenStartPosition(), scanner
+          //                    .getCurrentTokenEndPosition());
+          //          }
         }
         implements_list();
       } else {
@@ -1501,7 +1196,8 @@ public class Parser //extends PHPParserSuperclass
     } while (token == TokenNamepublic || token == TokenNameprotected
         || token == TokenNameprivate || token == TokenNamestatic
         || token == TokenNameabstract || token == TokenNamefinal
-        || token == TokenNamefunction || token == TokenNamevar);
+        || token == TokenNamefunction || token == TokenNamevar
+        || token == TokenNameconst);
   }
   private void class_statement() {
     //    class_statement:
@@ -1518,6 +1214,12 @@ public class Parser //extends PHPParserSuperclass
           compilationUnit.compilationResult);
       getNextToken();
       class_variable_declaration();
+    } else if (token == TokenNameconst) {
+      class_constant_declaration();
+      if (token != TokenNameSEMICOLON) {
+        throwSyntaxError("';' expected after class const declaration.");
+      }
+      getNextToken();
     } else {
       boolean hasModifiers = member_modifiers();
       if (token == TokenNamefunction) {
@@ -1552,6 +1254,30 @@ public class Parser //extends PHPParserSuperclass
     //      throwSyntaxError("'function' or 'var' expected.");
     //    }
   }
+  private void class_constant_declaration() {
+    // class_constant_declaration ',' T_STRING '=' static_scalar
+    // | T_CONST T_STRING '=' static_scalar
+    if (token != TokenNameconst) {
+      throwSyntaxError("'const' keyword expected in class declaration.");
+    } else {
+      getNextToken();
+    }
+    while (true) {
+      if (token != TokenNameIdentifier) {
+        throwSyntaxError("Identifier expected in class const declaration.");
+      }
+      getNextToken();
+      if (token != TokenNameEQUAL) {
+        throwSyntaxError("'=' expected in class const declaration.");
+      }
+      getNextToken();
+      static_scalar();
+      if (token != TokenNameCOMMA) {
+        break; // while(true)-loop
+      }
+      getNextToken();
+    }
+  }
   //  private void variable_modifiers() {
   //    // variable_modifiers:
   //    // non_empty_member_modifiers
@@ -1634,10 +1360,11 @@ public class Parser //extends PHPParserSuperclass
           static_scalar();
         }
       } else {
-        if (token == TokenNamethis) {
-          throwSyntaxError("'$this' not allowed after keyword 'public' 'protected' 'private' 'var'.");
-        }
-        throwSyntaxError("Variable expected keyword 'public' 'protected' 'private' 'var'.");
+        //        if (token == TokenNamethis) {
+        //          throwSyntaxError("'$this' not allowed after keyword 'public'
+        // 'protected' 'private' 'var'.");
+        //        }
+        throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
       }
       if (token != TokenNameCOMMA) {
         break;
@@ -1650,6 +1377,7 @@ public class Parser //extends PHPParserSuperclass
     getNextToken();
   }
   private void functionDefinition(MethodDeclaration methodDecl) {
+    boolean isAbstract = false;
     if (astPtr == 0) {
       compilationUnit.types.add(methodDecl);
     } else {
@@ -1669,9 +1397,22 @@ public class Parser //extends PHPParserSuperclass
           newMethods[0] = methodDecl;
           typeDecl.methods = newMethods;
         }
+        if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
+          isAbstract = true;
+        } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
+          isAbstract = true;
+        }
       }
     }
     functionDeclarator(methodDecl);
+    if (token == TokenNameSEMICOLON) {
+      if (!isAbstract) {
+        throwSyntaxError("Body declaration expected for method: "
+            + new String(methodDecl.selector));
+      }
+      getNextToken();
+      return;
+    }
     functionBody(methodDecl);
   }
   private void functionDeclarator(MethodDeclaration methodDecl) {
@@ -1690,7 +1431,7 @@ public class Parser //extends PHPParserSuperclass
         throwSyntaxError("'(' expected in function declaration.");
       }
       if (token != TokenNameRPAREN) {
-        parameterList();
+        parameter_list();
       }
       if (token != TokenNameRPAREN) {
         throwSyntaxError("')' expected in function declaration.");
@@ -1707,16 +1448,54 @@ public class Parser //extends PHPParserSuperclass
     }
   }
   //
-  private void parameterList() {
-    //parameter-declaration
-    //parameter-list ',' parameter-declaration
-    do {
-      parameterDeclaration();
-      if (token != TokenNameCOMMA) {
-        break;
+  private void parameter_list() {
+    // non_empty_parameter_list
+    // | /* empty */
+    non_empty_parameter_list(true);
+  }
+  private void non_empty_parameter_list(boolean empty_allowed) {
+    // optional_class_type T_VARIABLE
+    // | optional_class_type '&' T_VARIABLE
+    // | optional_class_type '&' T_VARIABLE '=' static_scalar
+    // | optional_class_type T_VARIABLE '=' static_scalar
+    // | non_empty_parameter_list ',' optional_class_type T_VARIABLE
+    // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
+    // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
+    // static_scalar
+    // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
+    // static_scalar
+    if (token == TokenNameIdentifier || token == TokenNameVariable
+        || token == TokenNameAND) {
+      while (true) {
+        if (token == TokenNameIdentifier) {
+          getNextToken();
+        }
+        if (token == TokenNameAND) {
+          getNextToken();
+        }
+        if (token == TokenNameVariable) {
+          getNextToken();
+          if (token == TokenNameEQUAL) {
+            getNextToken();
+            static_scalar();
+          }
+        } else {
+          throwSyntaxError("Variable expected in parameter list.");
+        }
+        if (token != TokenNameCOMMA) {
+          break;
+        }
+        getNextToken();
       }
-      getNextToken();
-    } while (true);
+      return;
+    }
+    if (!empty_allowed) {
+      throwSyntaxError("Identifier expected in parameter list.");
+    }
+  }
+  private void optional_class_type() {
+    // /* empty */
+    //| T_STRING
   }
   private void parameterDeclaration() {
     //variable
@@ -1738,9 +1517,10 @@ public class Parser //extends PHPParserSuperclass
       }
       return;
     }
-    if (token == TokenNamethis) {
-      throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
-    }
+    //    if (token == TokenNamethis) {
+    //      throwSyntaxError("Reserved word '$this' not allowed in parameter
+    // declaration.");
+    //    }
   }
   private void labeledStatementList() {
     if (token != TokenNamecase && token != TokenNamedefault) {
@@ -2044,29 +1824,85 @@ public class Parser //extends PHPParserSuperclass
     } while (true);
   }
   private void expr() {
-    //todo: find a better way to get the expression
-    //    expression = new StringBuffer();
-    //    for (int i = chIndx; i < str.length(); i++) {
-    //      if (str.charAt(i) == ';') {
-    //        break;
-    //      }
-    //      expression.append(str.charAt(i));
-    //    }
-    //    if (token == TokenNameSTRING_CONSTANT || token ==
-    // TokenNameINTERPOLATED_STRING) {
-    //      getNextToken();
-    //    } else {
-    logicalinclusiveorExpression();
-    //      while (token != TokenNameSEMICOLON) {
-    //        getNextToken();
-    //      // }
+    // r_variable
+    // | expr_without_variable
+    //    if (token!=TokenNameEOF) {
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: expr()");
+    }
+    expr_without_variable(true);
     //    }
   }
-  private void expr_without_variable() {
-    // String ident;
-    char[] ident;
-    boolean castFlag = false;
-    boolean arrayFlag = false;
+  private void expr_without_variable(boolean only_variable) {
+    //         internal_functions_in_yacc
+    // | T_CLONE expr
+    // | T_PRINT expr
+    // | '(' expr ')'
+    // | '@' expr
+    // | '+' expr
+    // | '-' expr
+    // | '!' expr
+    // | '~' expr
+    // | T_INC rw_variable
+    // | T_DEC rw_variable
+    // | T_INT_CAST expr
+    // | T_DOUBLE_CAST expr
+    // | T_STRING_CAST expr
+    // | T_ARRAY_CAST expr
+    // | T_OBJECT_CAST expr
+    // | T_BOOL_CAST expr
+    // | T_UNSET_CAST expr
+    // | T_EXIT exit_expr
+    // | scalar
+    // | T_ARRAY '(' array_pair_list ')'
+    // | '`' encaps_list '`'
+    // | T_LIST '(' assignment_list ')' '=' expr
+    // | T_NEW class_name_reference ctor_arguments
+    // | variable '=' expr
+    // | variable '=' '&' variable
+    // | variable '=' '&' T_NEW class_name_reference ctor_arguments
+    // | variable T_PLUS_EQUAL expr
+    // | variable T_MINUS_EQUAL expr
+    // | variable T_MUL_EQUAL expr
+    // | variable T_DIV_EQUAL expr
+    // | variable T_CONCAT_EQUAL expr
+    // | variable T_MOD_EQUAL expr
+    // | variable T_AND_EQUAL expr
+    // | variable T_OR_EQUAL expr
+    // | variable T_XOR_EQUAL expr
+    // | variable T_SL_EQUAL expr
+    // | variable T_SR_EQUAL expr
+    // | rw_variable T_INC
+    // | rw_variable T_DEC
+    // | expr T_BOOLEAN_OR expr
+    // | expr T_BOOLEAN_AND expr
+    // | expr T_LOGICAL_OR expr
+    // | expr T_LOGICAL_AND expr
+    // | expr T_LOGICAL_XOR expr
+    // | expr '|' expr
+    // | expr '&' expr
+    // | expr '^' expr
+    // | expr '.' expr
+    // | expr '+' expr
+    // | expr '-' expr
+    // | expr '*' expr
+    // | expr '/' expr
+    // | expr '%' expr
+    // | expr T_SL expr
+    // | expr T_SR expr
+    // | expr T_IS_IDENTICAL expr
+    // | expr T_IS_NOT_IDENTICAL expr
+    // | expr T_IS_EQUAL expr
+    // | expr T_IS_NOT_EQUAL expr
+    // | expr '<' expr
+    // | expr T_IS_SMALLER_OR_EQUAL expr
+    // | expr '>' expr
+    // | expr T_IS_GREATER_OR_EQUAL expr
+    // | expr T_INSTANCEOF class_name_reference
+    // | expr '?' expr ':' expr
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: expr_without_variable() PART 1");
+    }
     switch (token) {
       case TokenNameisset :
       case TokenNameempty :
@@ -2077,126 +1913,127 @@ public class Parser //extends PHPParserSuperclass
       case TokenNamerequire_once :
         internal_functions_in_yacc();
         break;
-      case TokenNamenew :
-        getNextToken();
-        expr();
-        break;
-      //        
-      //      case TokenNamenull :
-      //        getNextToken();
-      //        break;
-      //      case TokenNamefalse :
-      //        getNextToken();
-      //        break;
-      //      case TokenNametrue :
-      //        getNextToken();
-      //        break;
-      case TokenNameStringConstant :
-        getNextToken();
-        break;
-      case TokenNameHEREDOC :
-      case TokenNameStringInterpolated :
-      case TokenNameStringLiteral :
-        getNextToken();
-        break;
+      //       | '(' expr ')'
       case TokenNameLPAREN :
         getNextToken();
-        if (token == TokenNameIdentifier) {
-          // check if identifier is a type:
-          //   ident = identifier;
-          ident = scanner.getCurrentIdentifierSource();
-          String str = new String(ident).toLowerCase();
-          for (int i = 0; i < PHP_TYPES.length; i++) {
-            if (PHP_TYPES[i].equals(str)) {
-              castFlag = true;
-              if (PHP_TYPES[i].equals("array")) {
-                arrayFlag = true;
-              }
-              break;
-            }
-          }
-        }
-        if (castFlag) {
-          getNextToken();
-          if (arrayFlag && token == TokenNameLPAREN) {
-            getNextToken();
-            if (token == TokenNameRPAREN) {
-              getNextToken();
-            } else {
-              expr();
-              if (token != TokenNameRPAREN) {
-                throwSyntaxError(") expected after 'array('.");
-              }
-            }
-          }
-          if (token != TokenNameRPAREN) {
-            throwSyntaxError(") expected after cast-type '" + str + "'.");
-          }
+        expr();
+        if (token == TokenNameRPAREN) {
           getNextToken();
-          expr();
-          break;
         } else {
-          expr();
+          throwSyntaxError("')' expected in expression.");
         }
-        if (token != TokenNameRPAREN) {
-          throwSyntaxError(") expected in postfix-expression.");
-        }
-        getNextToken();
         break;
-      case TokenNameDoubleLiteral :
+      //    | T_CLONE expr
+      //    | T_PRINT expr
+      //    | '@' expr
+      //    | '+' expr
+      //    | '-' expr
+      //    | '!' expr
+      //    | '~' expr
+      //    | T_INT_CAST expr
+      //       | T_DOUBLE_CAST expr
+      //       | T_STRING_CAST expr
+      //       | T_ARRAY_CAST expr
+      //       | T_OBJECT_CAST expr
+      //       | T_BOOL_CAST expr
+      //       | T_UNSET_CAST expr
+      case TokenNameclone :
+      case TokenNameprint :
+      case TokenNameAT :
+      case TokenNamePLUS :
+      case TokenNameMINUS :
+      case TokenNameNOT :
+      case TokenNameTWIDDLE :
+      case TokenNameintCAST :
+      case TokenNamedoubleCAST :
+      case TokenNamestringCAST :
+      case TokenNamearrayCAST :
+      case TokenNameobjectCAST :
+      case TokenNameboolCAST :
+      case TokenNameunsetCAST :
         getNextToken();
+        expr();
         break;
-      case TokenNameIntegerLiteral :
+      case TokenNameexit :
         getNextToken();
+        exit_expr();
         break;
-      case TokenNameDOLLAR_LBRACE :
+      //  scalar:
+      //       T_STRING
+      //| T_STRING_VARNAME
+      //| class_constant
+      //| T_START_HEREDOC encaps_list T_END_HEREDOC
+      //       | '`' encaps_list '`'
+      //  | common_scalar
+      //       | '`' encaps_list '`'
+      case TokenNameEncapsedString0 :
+        scanner.encapsedStringStack.push(new Character('`'));
         getNextToken();
-        expr();
-        if (token != TokenNameRBRACE) {
-          throwSyntaxError("'}' expected after indirect variable token '${'.");
+        try {
+          if (token == TokenNameEncapsedString0) {
+          } else {
+            encaps_list();
+            if (token != TokenNameEncapsedString0) {
+              throwSyntaxError("\'`\' expected at end of string"
+                  + "(Found token: " + scanner.toStringAction(token) + " )");
+            }
+          }
+        } finally {
+          scanner.encapsedStringStack.pop();
+          getNextToken();
         }
-        getNextToken();
         break;
-      case TokenNameVariable :
-      case TokenNamethis :
-        ident = scanner.getCurrentIdentifierSource();
+      //      | '\'' encaps_list '\''
+      case TokenNameEncapsedString1 :
+        scanner.encapsedStringStack.push(new Character('\''));
         getNextToken();
-        if (token == TokenNameLBRACE) {
-          getNextToken();
-          expr();
-          if (token != TokenNameRBRACE) {
-            throwSyntaxError("'}' expected after variable '"
-                + new String(ident) + "' in variable-expression.");
-          }
-          getNextToken();
-        } else if (token == TokenNameLPAREN) {
-          getNextToken();
-          if (token != TokenNameRPAREN) {
-            expressionList();
-            if (token != TokenNameRPAREN) {
-              throwSyntaxError("')' expected after variable '"
-                  + new String(ident) + "' in postfix-expression.");
+        try {
+          if (token == TokenNameEncapsedString1) {
+          } else {
+            encaps_list();
+            if (token != TokenNameEncapsedString1) {
+              throwSyntaxError("\'\'\' expected at end of string"
+                  + "(Found token: " + scanner.toStringAction(token) + " )");
             }
           }
+        } finally {
+          scanner.encapsedStringStack.pop();
           getNextToken();
         }
         break;
-      case TokenNameIdentifier :
-        ident = scanner.getCurrentIdentifierSource();
+      //| '"' encaps_list '"'
+      case TokenNameEncapsedString2 :
+        scanner.encapsedStringStack.push(new Character('"'));
         getNextToken();
-        if (token == TokenNameLPAREN) {
-          getNextToken();
-          if (token != TokenNameRPAREN) {
-            expressionList();
-            if (token != TokenNameRPAREN) {
-              throwSyntaxError("')' expected after identifier '"
-                  + new String(ident) + "' in postfix-expression."
-                  + "(Found token: " + scanner.toStringAction(token) + ")");
+        try {
+          if (token == TokenNameEncapsedString2) {
+          } else {
+            encaps_list();
+            if (token != TokenNameEncapsedString2) {
+              throwSyntaxError("'\"' expected at end of string"
+                  + "(Found token: " + scanner.toStringAction(token) + " )");
             }
           }
+        } finally {
+          scanner.encapsedStringStack.pop();
           getNextToken();
         }
         break;
+      case TokenNameIntegerLiteral :
+      case TokenNameDoubleLiteral :
+      case TokenNameStringLiteral :
+      case TokenNameStringConstant :
+      case TokenNameStringInterpolated :
+      case TokenNameFILE :
+      case TokenNameLINE :
+      case TokenNameCLASS_C :
+      case TokenNameMETHOD_C :
+      case TokenNameFUNC_C :
+        common_scalar();
+        break;
+      case TokenNameHEREDOC :
+        getNextToken();
+        break;
       case TokenNamearray :
         //    T_ARRAY '(' array_pair_list ')'
         getNextToken();
@@ -2217,178 +2054,284 @@ public class Parser //extends PHPParserSuperclass
               + "(Found token: " + scanner.toStringAction(token) + ")");
         }
         break;
-      case TokenNameprint :
-        getNextToken();
-        expr();
-        break;
-      case TokenNameexit :
-        getNextToken();
-        exit_expr();
-        break;
       case TokenNamelist :
+        //    | T_LIST '(' assignment_list ')' '=' expr
         getNextToken();
         if (token == TokenNameLPAREN) {
           getNextToken();
-          if (token == TokenNameCOMMA) {
-            getNextToken();
-          }
-          expressionList();
+          assignment_list();
           if (token != TokenNameRPAREN) {
             throwSyntaxError("')' expected after 'list' keyword.");
           }
           getNextToken();
-          //          if (token == TokenNameSET) {
-          //            getNextToken();
-          //            logicalinclusiveorExpression();
-          //          }
+          if (token != TokenNameEQUAL) {
+            throwSyntaxError("'=' expected after 'list' keyword.");
+          }
+          getNextToken();
+          expr();
         } else {
           throwSyntaxError("'(' expected after 'list' keyword.");
         }
         break;
-    //      case TokenNameexit :
-    //        getNextToken();
-    //        if (token != TokenNameSEMICOLON) {
-    //          exitStatus();
-    //        }
-    //        if (token == TokenNameSEMICOLON) {
-    //          getNextToken();
-    //        } else {
-    //          if (token != TokenNameStopPHP) {
-    //            throwSyntaxError("';' expected after 'exit' expression.");
-    //          }
-    //          getNextToken();
-    //        }
-    //        break;
-    //      case TokenNamedie :
-    //        getNextToken();
-    //        if (token != TokenNameSEMICOLON) {
-    //          exitStatus();
-    //        }
-    //        if (token == TokenNameSEMICOLON) {
-    //          getNextToken();
-    //        } else {
-    //          if (token != TokenNameStopPHP) {
-    //            throwSyntaxError("';' expected after 'die' expression.");
-    //          }
-    //        }
-    //        break;
-    //      case TokenNamearray :
-    //        getNextToken();
-    //        if (token == TokenNameARGOPEN) {
-    //          getNextToken();
-    //          if (token == TokenNameCOMMA) {
-    //            getNextToken();
-    //          }
-    //          expressionList();
-    //          if (token != TokenNameARGCLOSE) {
-    //            throwSyntaxError("')' expected after 'list' keyword.");
-    //          }
-    //          getNextToken();
-    //          if (token == TokenNameSET) {
-    //            getNextToken();
-    //            logicalinclusiveorExpression();
-    //          }
-    //        } else {
-    //          throwSyntaxError("'(' expected after 'list' keyword.");
-    //        }
-    //        break;
+      case TokenNamenew :
+        //     | T_NEW class_name_reference ctor_arguments
+        getNextToken();
+        class_name_reference();
+        ctor_arguments();
+        break;
+      //       | T_INC rw_variable
+      //       | T_DEC rw_variable
+      case TokenNamePLUS_PLUS :
+      case TokenNameMINUS_MINUS :
+        getNextToken();
+        rw_variable();
+        break;
+      //       | variable '=' expr
+      //       | variable '=' '&' variable
+      //       | variable '=' '&' T_NEW class_name_reference ctor_arguments
+      //       | variable T_PLUS_EQUAL expr
+      //       | variable T_MINUS_EQUAL expr
+      //       | variable T_MUL_EQUAL expr
+      //       | variable T_DIV_EQUAL expr
+      //       | variable T_CONCAT_EQUAL expr
+      //       | variable T_MOD_EQUAL expr
+      //       | variable T_AND_EQUAL expr
+      //       | variable T_OR_EQUAL expr
+      //       | variable T_XOR_EQUAL expr
+      //       | variable T_SL_EQUAL expr
+      //       | variable T_SR_EQUAL expr
+      //       | rw_variable T_INC
+      //       | rw_variable T_DEC
+      case TokenNameIdentifier :
+      case TokenNameVariable :
+      case TokenNameDOLLAR :
+        variable();
+        switch (token) {
+          case TokenNameEQUAL :
+            getNextToken();
+            if (token == TokenNameAND) {
+              getNextToken();
+              if (token == TokenNamenew) {
+                // | variable '=' '&' T_NEW class_name_reference ctor_arguments
+                getNextToken();
+                class_name_reference();
+                ctor_arguments();
+              } else {
+                variable();
+              }
+            } else {
+              expr();
+            }
+            break;
+          case TokenNamePLUS_EQUAL :
+          case TokenNameMINUS_EQUAL :
+          case TokenNameMULTIPLY_EQUAL :
+          case TokenNameDIVIDE_EQUAL :
+          case TokenNameDOT_EQUAL :
+          case TokenNameREMAINDER_EQUAL :
+          case TokenNameAND_EQUAL :
+          case TokenNameOR_EQUAL :
+          case TokenNameXOR_EQUAL :
+          case TokenNameRIGHT_SHIFT_EQUAL :
+          case TokenNameLEFT_SHIFT_EQUAL :
+            getNextToken();
+            expr();
+            break;
+          case TokenNamePLUS_PLUS :
+          case TokenNameMINUS_MINUS :
+            getNextToken();
+            break;
+          default :
+            if (!only_variable) {
+              throwSyntaxError("Variable expression not allowed (found token '"
+                  + scanner.toStringAction(token) + "').");
+            }
+        }
+        break;
+      default :
+        if (token != TokenNameINLINE_HTML) {
+          throwSyntaxError("Error in expression (found token '"
+              + scanner.toStringAction(token) + "').");
+        }
+        return;
     }
-    boolean while_flag = true;
-    do {
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: expr_without_variable() PART 2");
+    }
+    // | expr T_BOOLEAN_OR expr
+    // | expr T_BOOLEAN_AND expr
+    // | expr T_LOGICAL_OR expr
+    // | expr T_LOGICAL_AND expr
+    // | expr T_LOGICAL_XOR expr
+    // | expr '|' expr
+    // | expr '&' expr
+    // | expr '^' expr
+    // | expr '.' expr
+    // | expr '+' expr
+    // | expr '-' expr
+    // | expr '*' expr
+    // | expr '/' expr
+    // | expr '%' expr
+    // | expr T_SL expr
+    // | expr T_SR expr
+    // | expr T_IS_IDENTICAL expr
+    // | expr T_IS_NOT_IDENTICAL expr
+    // | expr T_IS_EQUAL expr
+    // | expr T_IS_NOT_EQUAL expr
+    // | expr '<' expr
+    // | expr T_IS_SMALLER_OR_EQUAL expr
+    // | expr '>' expr
+    // | expr T_IS_GREATER_OR_EQUAL expr
+    while (true) {
       switch (token) {
-        case TokenNameLBRACKET :
+        case TokenNameOR_OR :
+        case TokenNameAND_AND :
+        case TokenNameand :
+        case TokenNameor :
+        case TokenNamexor :
+        case TokenNameAND :
+        case TokenNameOR :
+        case TokenNameXOR :
+        case TokenNameDOT :
+        case TokenNamePLUS :
+        case TokenNameMINUS :
+        case TokenNameMULTIPLY :
+        case TokenNameDIVIDE :
+        case TokenNameREMAINDER :
+        case TokenNameLEFT_SHIFT :
+        case TokenNameRIGHT_SHIFT :
+        case TokenNameEQUAL_EQUAL_EQUAL :
+        case TokenNameNOT_EQUAL_EQUAL :
+        case TokenNameEQUAL_EQUAL :
+        case TokenNameNOT_EQUAL :
+        case TokenNameLESS :
+        case TokenNameLESS_EQUAL :
+        case TokenNameGREATER :
+        case TokenNameGREATER_EQUAL :
           getNextToken();
           expr();
-          if (token != TokenNameRBRACKET) {
-            throwSyntaxError("] expected in postfix-expression.");
-          }
+          break;
+        //  | expr T_INSTANCEOF class_name_reference
+        //     | expr '?' expr ':' expr
+        case TokenNameinstanceof :
           getNextToken();
+          class_name_reference();
           break;
-        case TokenNamePAAMAYIM_NEKUDOTAYIM :
-        // ::
-        case TokenNameMINUS_GREATER :
-          // ->
+        case TokenNameQUESTION :
           getNextToken();
-          if (token > TokenNameKEYWORD) {
-            ident = scanner.getCurrentIdentifierSource();
-            //            setMarker(
-            //              "Avoid using keyword '"
-            //                + new String(ident)
-            //                + "' as variable name.",
-            //              rowCount,
-            //              PHPParser.INFO);
-            //            setMarker(
-            //              "Avoid using keyword '" + new String(ident) + "' as
-            // variable name.",
-            //              scanner.getCurrentTokenStartPosition(),
-            //              scanner.getCurrentTokenEndPosition(),
-            //              INFO);
-          }
-          switch (token) {
-            case TokenNameVariable :
-              ident = scanner.getCurrentIdentifierSource();
-              getNextToken();
-              //              if (token == TokenNameARGOPEN) {
-              //                getNextToken();
-              //                expressionList();
-              //                if (token != TokenNameARGCLOSE) {
-              //                  throwSyntaxError(") expected after variable '" +
-              // ident + "'.");
-              //                }
-              //                getNextToken();
-              //              }
-              break;
-            case TokenNameIdentifier :
-              //ident = scanner.getCurrentIdentifierSource();
-              getNextToken();
-              break;
-            case TokenNameLBRACE :
-              getNextToken();
-              expr();
-              if (token != TokenNameRBRACE) {
-                throwSyntaxError("} expected in postfix-expression.");
-              }
-              getNextToken();
-              break;
-            default :
-              throwSyntaxError("Syntax error after '->' token.");
-          }
-          while (token == TokenNameLBRACKET || token == TokenNameLPAREN
-              || token == TokenNameLBRACE) {
-            if (token == TokenNameLBRACKET) {
-              getNextToken();
-              expressionList();
-              if (token != TokenNameRBRACKET) {
-                throwSyntaxError("] expected after '->'.");
-              }
-              getNextToken();
-            } else if (token == TokenNameLPAREN) {
-              getNextToken();
-              expressionList();
-              if (token != TokenNameRPAREN) {
-                throwSyntaxError(") expected after '->'.");
-              }
-              getNextToken();
-            } else if (token == TokenNameLBRACE) {
-              getNextToken();
-              expr();
-              if (token != TokenNameRBRACE) {
-                throwSyntaxError("} expected after '->'.");
-              }
-              getNextToken();
-            }
+          expr();
+          if (token == TokenNameCOLON) {
+            getNextToken();
+            expr();
           }
           break;
-        case TokenNamePLUS_PLUS :
+        default :
+          return;
+      }
+    }
+  }
+  private void class_name_reference() {
+    //  class_name_reference:
+    // T_STRING
+    //| dynamic_class_name_reference
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: class_name_reference()");
+    }
+    if (token == TokenNameIdentifier) {
+      getNextToken();
+    } else {
+      dynamic_class_name_reference();
+    }
+  }
+  private void dynamic_class_name_reference() {
+    //dynamic_class_name_reference:
+    // base_variable T_OBJECT_OPERATOR object_property
+    // dynamic_class_name_variable_properties
+    //| base_variable
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: dynamic_class_name_reference()");
+    }
+    base_variable();
+    if (token == TokenNameMINUS_GREATER) {
+      getNextToken();
+      object_property();
+      dynamic_class_name_variable_properties();
+    }
+  }
+  private void dynamic_class_name_variable_properties() {
+    //  dynamic_class_name_variable_properties:
+    //                 dynamic_class_name_variable_properties
+    // dynamic_class_name_variable_property
+    //         | /* empty */
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: dynamic_class_name_variable_properties()");
+    }
+    while (token == TokenNameMINUS_GREATER) {
+      dynamic_class_name_variable_property();
+    }
+  }
+  private void dynamic_class_name_variable_property() {
+    //  dynamic_class_name_variable_property:
+    // T_OBJECT_OPERATOR object_property
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: dynamic_class_name_variable_property()");
+    }
+    if (token == TokenNameMINUS_GREATER) {
+      getNextToken();
+      object_property();
+    }
+  }
+  private void ctor_arguments() {
+    //  ctor_arguments:
+    // /* empty */
+    //| '(' function_call_parameter_list ')'
+    if (token == TokenNameLPAREN) {
+      getNextToken();
+      if (token == TokenNameRPAREN) {
+        getNextToken();
+        return;
+      }
+      non_empty_function_call_parameter_list();
+      if (token != TokenNameRPAREN) {
+        throwSyntaxError("')' expected in ctor_arguments.");
+      }
+      getNextToken();
+    }
+  }
+  private void assignment_list() {
+    //  assignment_list:
+    // assignment_list ',' assignment_list_element
+    //| assignment_list_element
+    while (true) {
+      assignment_list_element();
+      if (token != TokenNameCOMMA) {
+        break;
+      }
+      getNextToken();
+    }
+  }
+  private void assignment_list_element() {
+    //assignment_list_element:
+    // variable
+    //| T_LIST '(' assignment_list ')'
+    //| /* empty */
+    if (token == TokenNameVariable || token == TokenNameDOLLAR) {
+      variable();
+    } else {
+      if (token == TokenNamelist) {
+        getNextToken();
+        if (token == TokenNameLPAREN) {
           getNextToken();
-          break;
-        case TokenNameMINUS_MINUS :
+          assignment_list();
+          if (token != TokenNameRPAREN) {
+            throwSyntaxError("')' expected after 'list' keyword.");
+          }
           getNextToken();
-          break;
-        default :
-          while_flag = false;
+        } else {
+          throwSyntaxError("'(' expected after 'list' keyword.");
+        }
       }
-    } while (while_flag);
+    }
   }
   private void array_pair_list() {
     //  array_pair_list:
@@ -2410,18 +2353,22 @@ public class Parser //extends PHPParserSuperclass
     //| expr T_DOUBLE_ARROW '&' w_variable
     //| '&' w_variable
     while (true) {
-      expr();
       if (token == TokenNameAND) {
         getNextToken();
         variable();
-        return;
-      } else if (token == TokenNameEQUAL_GREATER) {
-        getNextToken();
+      } else {
+        expr();
         if (token == TokenNameAND) {
           getNextToken();
           variable();
-        } else {
-          expr();
+        } else if (token == TokenNameEQUAL_GREATER) {
+          getNextToken();
+          if (token == TokenNameAND) {
+            getNextToken();
+            variable();
+          } else {
+            expr();
+          }
         }
       }
       if (token != TokenNameCOMMA) {
@@ -2433,309 +2380,396 @@ public class Parser //extends PHPParserSuperclass
       }
     }
   }
-  private void unaryExpression() {
-    switch (token) {
-      case TokenNamePLUS_PLUS :
-        getNextToken();
-        unaryExpression();
-        break;
-      case TokenNameMINUS_MINUS :
-        getNextToken();
-        unaryExpression();
-        break;
-      // '@' '&' '*' '+' '-' '~' '!'
-      case TokenNameAT :
-        getNextToken();
-        if (token == TokenNameinclude || token == TokenNameinclude_once
-            || token == TokenNamerequire || token == TokenNamerequire_once) {
-          statement(TokenNameAT);
-        } else {
-          expr_without_variable(); //  castExpression();
-        }
-        break;
-      case TokenNameAND :
-        getNextToken();
-        castExpression();
-        break;
-      case TokenNameMULTIPLY :
-        getNextToken();
-        castExpression();
-        break;
-      case TokenNamePLUS :
-        getNextToken();
-        castExpression();
-        break;
-      case TokenNameMINUS :
-        getNextToken();
-        castExpression();
-        break;
-      case TokenNameTWIDDLE :
-        getNextToken();
-        castExpression();
-        break;
-      case TokenNameNOT :
-        getNextToken();
-        castExpression();
-        break;
-      default :
-        expr_without_variable();
+  //  private void variableList() {
+  //    do {
+  //      variable();
+  //      if (token == TokenNameCOMMA) {
+  //        getNextToken();
+  //      } else {
+  //        break;
+  //      }
+  //    } while (true);
+  //  }
+  private void variable_without_objects() {
+    //  variable_without_objects:
+    //                 reference_variable
+    //         | simple_indirect_reference reference_variable
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: variable_without_objects()");
     }
-  }
-  private void castExpression() {
-    //    if (token == TokenNameARGOPEN) {
-    //      getNextToken();
-    //      typeName();
-    //      if (token != TokenNameARGCLOSE) {
-    //        throwSyntaxError(") expected after cast-expression.");
-    //      }
-    //      getNextToken();
-    //    }
-    unaryExpression();
-  }
-  private void assignExpression() {
-    castExpression();
-    if (token == TokenNameEQUAL) { // =
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameDOT_EQUAL) { // .=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameEQUAL_GREATER) { // =>
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNamePLUS_EQUAL) { // +=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameMINUS_EQUAL) { // -=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameDIVIDE_EQUAL) { // *=
+    while (token == TokenNameDOLLAR) {
       getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameREMAINDER_EQUAL) { // %=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameAND_EQUAL) { // &=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameOR_EQUAL) { // |=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameXOR_EQUAL) { // ^=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
-      getNextToken();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
-      getNextToken();
-      logicalinclusiveorExpression();
     }
-  }
-  private void multiplicativeExpression() {
-    do {
-      assignExpression();
-      if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE
-          && token != TokenNameREMAINDER) {
-        return;
-      }
+    reference_variable();
+  }
+  private void function_call() {
+    //  function_call:
+    // T_STRING '(' function_call_parameter_list ')'
+    //| class_constant '(' function_call_parameter_list ')'
+    //| static_member '(' function_call_parameter_list ')'
+    //| variable_without_objects '(' function_call_parameter_list ')'
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: function_call()");
+    }
+    if (token == TokenNameIdentifier) {
       getNextToken();
-    } while (true);
-  }
-  private void concatenationExpression() {
-    do {
-      multiplicativeExpression();
-      if (token != TokenNameDOT) {
-        return;
+      switch (token) {
+        case TokenNamePAAMAYIM_NEKUDOTAYIM :
+          // static member:
+          getNextToken();
+          if (token == TokenNameIdentifier) {
+            // class _constant
+            getNextToken();
+          } else {
+            //        static member:
+            variable_without_objects();
+          }
+          break;
       }
+    } else {
+      variable_without_objects();
+    }
+    if (token != TokenNameLPAREN) {
+      // TODO is this ok ?
+      return;
+      //      throwSyntaxError("'(' expected in function call.");
+    }
+    getNextToken();
+    if (token == TokenNameRPAREN) {
       getNextToken();
-    } while (true);
+      return;
+    }
+    non_empty_function_call_parameter_list();
+    if (token != TokenNameRPAREN) {
+      throwSyntaxError("')' expected in function call.");
+    }
+    getNextToken();
   }
-  private void additiveExpression() {
-    do {
-      concatenationExpression();
-      if (token != TokenNamePLUS && token != TokenNameMINUS) {
-        return;
+  //  private void function_call_parameter_list() {
+  //    function_call_parameter_list:
+  //           non_empty_function_call_parameter_list { $$ = $1; }
+  //   | /* empty */
+  //  }
+  private void non_empty_function_call_parameter_list() {
+    //non_empty_function_call_parameter_list:
+    //         expr_without_variable
+    // | variable
+    // | '&' w_variable
+    // | non_empty_function_call_parameter_list ',' expr_without_variable
+    // | non_empty_function_call_parameter_list ',' variable
+    // | non_empty_function_call_parameter_list ',' '&' w_variable
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: non_empty_function_call_parameter_list()");
+    }
+    while (true) {
+      if (token == TokenNameAND) {
+        getNextToken();
+        w_variable();
+      } else {
+        //        if (token == TokenNameIdentifier || token == TokenNameVariable
+        //            || token == TokenNameDOLLAR) {
+        //          variable();
+        //        } else {
+        expr_without_variable(true);
+        //        }
       }
-      getNextToken();
-    } while (true);
-  }
-  private void shiftExpression() {
-    do {
-      additiveExpression();
-      if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
-        return;
+      if (token != TokenNameCOMMA) {
+        break;
       }
       getNextToken();
-    } while (true);
+    }
   }
-  private void relationalExpression() {
-    do {
-      shiftExpression();
-      if (token != TokenNameLESS && token != TokenNameGREATER
-          && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
-        return;
-      }
+  private void fully_qualified_class_name() {
+    if (token == TokenNameIdentifier) {
       getNextToken();
-    } while (true);
+    } else {
+      throwSyntaxError("Class name expected.");
+    }
   }
-  private void identicalExpression() {
-    do {
-      relationalExpression();
-      if (token != TokenNameEQUAL_EQUAL_EQUAL
-          && token != TokenNameNOT_EQUAL_EQUAL) {
-        return;
-      }
-      getNextToken();
-    } while (true);
+  private void static_member() {
+    //  static_member:
+    // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
+    // variable_without_objects
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: static_member()");
+    }
+    fully_qualified_class_name();
+    if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
+      throwSyntaxError("'::' expected after class name (static_member).");
+    }
+    getNextToken();
+    variable_without_objects();
+  }
+  private void base_variable_with_function_calls() {
+    //  base_variable_with_function_calls:
+    // base_variable
+    //| function_call
+    boolean functionCall = false;
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: base_variable_with_function_calls()");
+    }
+    //    if (token == TokenNameIdentifier) {
+    //      functionCall = true;
+    //    } else if (token == TokenNameVariable) {
+    //      int tempToken = token;
+    //      int tempPosition = scanner.currentPosition;
+    //      getNextToken();
+    //      if (token == TokenNameLPAREN) {
+    //        functionCall = true;
+    //      }
+    //      token = tempToken;
+    //      scanner.currentPosition = tempPosition;
+    //      scanner.phpMode = true;
+    //    }
+    //    if (functionCall) {
+    function_call();
+    //    } else {
+    //      base_variable();
+    //    }
   }
-  private void equalityExpression() {
-    do {
-      identicalExpression();
-      if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
-        return;
+  private void base_variable() {
+    //  base_variable:
+    //                 reference_variable
+    //         | simple_indirect_reference reference_variable
+    //         | static_member
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: base_variable()");
+    }
+    if (token == TokenNameIdentifier) {
+      static_member();
+    } else {
+      while (token == TokenNameDOLLAR) {
+        getNextToken();
       }
-      getNextToken();
-    } while (true);
+      reference_variable();
+    }
   }
-  private void ternaryExpression() {
-    equalityExpression();
-    if (token == TokenNameQUESTION) {
-      getNextToken();
-      expr();
-      if (token == TokenNameCOLON) {
+  //  private void simple_indirect_reference() {
+  //    // simple_indirect_reference:
+  //    // '$'
+  //    //| simple_indirect_reference '$'
+  //  }
+  private void reference_variable() {
+    //  reference_variable:
+    //                 reference_variable '[' dim_offset ']'
+    //         | reference_variable '{' expr '}'
+    //         | compound_variable
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: reference_variable()");
+    }
+    compound_variable();
+    while (true) {
+      if (token == TokenNameLBRACE) {
         getNextToken();
         expr();
+        if (token != TokenNameRBRACE) {
+          throwSyntaxError("'}' expected in reference variable.");
+        }
+        getNextToken();
+      } else if (token == TokenNameLBRACKET) {
+        getNextToken();
+        if (token != TokenNameRBRACKET) {
+          expr();
+          //        dim_offset();
+          if (token != TokenNameRBRACKET) {
+            throwSyntaxError("']' expected in reference variable.");
+          }
+        }
+        getNextToken();
       } else {
-        throwSyntaxError("':' expected in ternary operator '? :'.");
+        break;
       }
     }
   }
-  private void andExpression() {
-    do {
-      ternaryExpression();
-      if (token != TokenNameAND) {
-        return;
-      }
+  private void compound_variable() {
+    //  compound_variable:
+    //                 T_VARIABLE
+    //         | '$' '{' expr '}'
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: compound_variable()");
+    }
+    if (token == TokenNameVariable) {
       getNextToken();
-    } while (true);
-  }
-  private void exclusiveorExpression() {
-    do {
-      andExpression();
-      if (token != TokenNameXOR) {
-        return;
+    } else {
+      // because of simple_indirect_reference
+      while (token == TokenNameDOLLAR) {
+        getNextToken();
       }
-      getNextToken();
-    } while (true);
-  }
-  private void inclusiveorExpression() {
-    do {
-      exclusiveorExpression();
-      if (token != TokenNameOR) {
-        return;
+      if (token != TokenNameLBRACE) {
+        throwSyntaxError("'{' expected after compound variable token '$'.");
       }
       getNextToken();
-    } while (true);
-  }
-  private void booleanandExpression() {
-    do {
-      inclusiveorExpression();
-      if (token != TokenNameAND_AND) {
-        return;
+      expr();
+      if (token != TokenNameRBRACE) {
+        throwSyntaxError("'}' expected after compound variable token '$'.");
       }
       getNextToken();
-    } while (true);
+    }
   }
-  private void booleanorExpression() {
-    do {
-      booleanandExpression();
-      if (token != TokenNameOR_OR) {
-        return;
+  //  private void dim_offset() {
+  //    // dim_offset:
+  //    // /* empty */
+  //    // | expr
+  //    expr();
+  //  }
+  private void object_property() {
+    //  object_property:
+    // object_dim_list
+    //| variable_without_objects
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: object_property()");
+    }
+    if (token == TokenNameVariable || token == TokenNameDOLLAR) {
+      variable_without_objects();
+    } else {
+      object_dim_list();
+    }
+  }
+  private void object_dim_list() {
+    //object_dim_list:
+    // object_dim_list '[' dim_offset ']'
+    //| object_dim_list '{' expr '}'
+    //| variable_name
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: object_dim_list()");
+    }
+    variable_name();
+    while (true) {
+      if (token == TokenNameLBRACE) {
+        getNextToken();
+        expr();
+        if (token != TokenNameRBRACE) {
+          throwSyntaxError("'}' expected in object_dim_list.");
+        }
+        getNextToken();
+      } else if (token == TokenNameLBRACKET) {
+        getNextToken();
+        if (token == TokenNameRBRACKET) {
+          getNextToken();
+          continue;
+        }
+        expr();
+        if (token != TokenNameRBRACKET) {
+          throwSyntaxError("']' expected in object_dim_list.");
+        }
+        getNextToken();
+      } else {
+        break;
       }
-      getNextToken();
-    } while (true);
+    }
   }
-  private void logicalandExpression() {
-    do {
-      booleanorExpression();
-      if (token != TokenNameAND) {
-        return;
+  private void variable_name() {
+    //variable_name:
+    // T_STRING
+    //| '{' expr '}'
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: variable_name()");
+    }
+    if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
+      if (token > TokenNameKEYWORD) {
+        // TODO show a warning "Keyword used as variable" ?
       }
       getNextToken();
-    } while (true);
-  }
-  private void logicalexclusiveorExpression() {
-    do {
-      logicalandExpression();
-      if (token != TokenNameXOR) {
-        return;
+    } else {
+      if (token != TokenNameLBRACE) {
+        throwSyntaxError("'{' expected in variable name.");
       }
       getNextToken();
-    } while (true);
-  }
-  private void logicalinclusiveorExpression() {
-    do {
-      logicalexclusiveorExpression();
-      if (token != TokenNameOR) {
-        return;
+      expr();
+      if (token != TokenNameRBRACE) {
+        throwSyntaxError("'}' expected in variable name.");
       }
       getNextToken();
-    } while (true);
+    }
   }
-  //  public void assignmentExpression() {
-  //    if (token == TokenNameVARIABLE) {
-  //      getNextToken();
-  //      if (token == TokenNameSET) {
-  //        getNextToken();
-  //        logicalinclusiveorExpression();
-  //      }
-  //    } else {
-  //      logicalinclusiveorExpression();
-  //    }
-  //  }
-  private void variableList() {
-    do {
-      variable();
-      if (token == TokenNameCOMMA) {
-        getNextToken();
-      } else {
-        break;
-      }
-    } while (true);
+  private void r_variable() {
+    variable();
+  }
+  private void w_variable() {
+    variable();
+  }
+  private void rw_variable() {
+    variable();
   }
   private void variable() {
-    if (token == TokenNameDOLLAR_LBRACE) {
-      getNextToken();
-      expr();
-      ;
-      if (token != TokenNameRBRACE) {
-        throwSyntaxError("'}' expected after indirect variable token '${'.");
-      }
+    //    variable:
+    //         base_variable_with_function_calls T_OBJECT_OPERATOR
+    //                 object_property method_or_not variable_properties
+    // | base_variable_with_function_calls
+    base_variable_with_function_calls();
+    if (token == TokenNameMINUS_GREATER) {
+      getNextToken();
+      object_property();
+      method_or_not();
+      variable_properties();
+    }
+    //    if (token == TokenNameDOLLAR_LBRACE) {
+    //      getNextToken();
+    //      expr();
+    //      ;
+    //      if (token != TokenNameRBRACE) {
+    //        throwSyntaxError("'}' expected after indirect variable token '${'.");
+    //      }
+    //      getNextToken();
+    //    } else {
+    //      if (token == TokenNameVariable) {
+    //        getNextToken();
+    //        if (token == TokenNameLBRACKET) {
+    //          getNextToken();
+    //          expr();
+    //          if (token != TokenNameRBRACKET) {
+    //            throwSyntaxError("']' expected in variable-list.");
+    //          }
+    //          getNextToken();
+    //        } else if (token == TokenNameEQUAL) {
+    //          getNextToken();
+    //          static_scalar();
+    //        }
+    //      } else {
+    //        throwSyntaxError("$-variable expected in variable-list.");
+    //      }
+    //    }
+  }
+  private void variable_properties() {
+    //  variable_properties:
+    //                 variable_properties variable_property
+    //         | /* empty */
+    while (token == TokenNameMINUS_GREATER) {
+      variable_property();
+    }
+  }
+  private void variable_property() {
+    //  variable_property:
+    //                 T_OBJECT_OPERATOR object_property method_or_not
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: variable_property()");
+    }
+    if (token == TokenNameMINUS_GREATER) {
       getNextToken();
+      object_property();
+      method_or_not();
     } else {
-      if (token == TokenNameVariable) {
+      throwSyntaxError("'->' expected in variable_property.");
+    }
+  }
+  private void method_or_not() {
+    //  method_or_not:
+    //                 '(' function_call_parameter_list ')'
+    //         | /* empty */
+    if (Scanner.TRACE) {
+      System.out.println("TRACE: method_or_not()");
+    }
+    if (token == TokenNameLPAREN) {
+      getNextToken();
+      if (token == TokenNameRPAREN) {
         getNextToken();
-        if (token == TokenNameLBRACKET) {
-          getNextToken();
-          expr();
-          if (token != TokenNameRBRACKET) {
-            throwSyntaxError("']' expected in variable-list.");
-          }
-          getNextToken();
-        } else if (token == TokenNameEQUAL) {
-          getNextToken();
-          static_scalar();
-        }
-      } else {
-        throwSyntaxError("$-variable expected in variable-list.");
+        return;
+      }
+      non_empty_function_call_parameter_list();
+      if (token != TokenNameRPAREN) {
+        throwSyntaxError("')' expected in method_or_not.");
       }
+      getNextToken();
     }
   }
   private void exit_expr() {
@@ -2756,6 +2790,244 @@ public class Parser //extends PHPParserSuperclass
     }
     getNextToken();
   }
+  private void encaps_list() {
+    //                 encaps_list encaps_var
+    //         | encaps_list T_STRING
+    //         | encaps_list T_NUM_STRING
+    //         | encaps_list T_ENCAPSED_AND_WHITESPACE
+    //         | encaps_list T_CHARACTER
+    //         | encaps_list T_BAD_CHARACTER
+    //         | encaps_list '['
+    //         | encaps_list ']'
+    //         | encaps_list '{'
+    //         | encaps_list '}'
+    //         | encaps_list T_OBJECT_OPERATOR
+    //         | /* empty */
+    while (true) {
+      switch (token) {
+        case TokenNameSTRING :
+          getNextToken();
+          break;
+        case TokenNameLBRACE :
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+          break;
+        case TokenNameRBRACE :
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+          break;
+        case TokenNameLBRACKET :
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+          break;
+        case TokenNameRBRACKET :
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+          break;
+        case TokenNameMINUS_GREATER :
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+          break;
+        case TokenNameVariable :
+        case TokenNameDOLLAR_LBRACE :
+        case TokenNameCURLY_OPEN :
+          encaps_var();
+          break;
+        //        case TokenNameDOLLAR :
+        //          getNextToken();
+        //          if (token == TokenNameLBRACE) {
+        //            token = TokenNameDOLLAR_LBRACE;
+        //            encaps_var();
+        //          }
+        //          break;
+        default :
+          char encapsedChar = ((Character) scanner.encapsedStringStack.peek())
+              .charValue();
+          if (encapsedChar == '$') {
+            scanner.encapsedStringStack.pop();
+            encapsedChar = ((Character) scanner.encapsedStringStack.peek())
+                .charValue();
+            switch (encapsedChar) {
+              case '`' :
+                if (token == TokenNameEncapsedString0) {
+                  return;
+                }
+                token = TokenNameSTRING;
+                continue;
+              case '\'' :
+                if (token == TokenNameEncapsedString1) {
+                  return;
+                }
+                token = TokenNameSTRING;
+                continue;
+              case '"' :
+                if (token == TokenNameEncapsedString2) {
+                  return;
+                }
+                token = TokenNameSTRING;
+                continue;
+            }
+          }
+          return;
+      }
+    }
+  }
+  private void encaps_var() {
+    //                 T_VARIABLE
+    //         | T_VARIABLE '[' encaps_var_offset ']'
+    //         | T_VARIABLE T_OBJECT_OPERATOR T_STRING
+    //         | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
+    //         | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
+    //         | T_CURLY_OPEN variable '}'
+    switch (token) {
+      case TokenNameVariable :
+        getNextToken();
+        if (token == TokenNameLBRACKET) {
+          getNextToken();
+          //          if (token == TokenNameRBRACKET) {
+          //            getNextToken();
+          //          } else {
+          expr(); //encaps_var_offset();
+          if (token != TokenNameRBRACKET) {
+            throwSyntaxError("']' expected after variable.");
+          }
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+          //          }
+        } else if (token == TokenNameMINUS_GREATER) {
+          getNextToken();
+          if (token != TokenNameIdentifier) {
+            throwSyntaxError("Identifier expected after '->'.");
+          }
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+        }
+        //        else {
+        //          // scanner.encapsedStringStack.pop();
+        //          int tempToken = TokenNameSTRING;
+        //          if (!scanner.encapsedStringStack.isEmpty()
+        //              && (token == TokenNameEncapsedString0
+        //                  || token == TokenNameEncapsedString1
+        //                  || token == TokenNameEncapsedString2 || token == TokenNameERROR)) {
+        //            char encapsedChar = ((Character) scanner.encapsedStringStack.peek())
+        //                .charValue();
+        //            switch (token) {
+        //              case TokenNameEncapsedString0 :
+        //                if (encapsedChar == '`') {
+        //                  tempToken = TokenNameEncapsedString0;
+        //                }
+        //                break;
+        //              case TokenNameEncapsedString1 :
+        //                if (encapsedChar == '\'') {
+        //                  tempToken = TokenNameEncapsedString1;
+        //                }
+        //                break;
+        //              case TokenNameEncapsedString2 :
+        //                if (encapsedChar == '"') {
+        //                  tempToken = TokenNameEncapsedString2;
+        //                }
+        //                break;
+        //              case TokenNameERROR :
+        //                if (scanner.source[scanner.currentPosition - 1] == '\\') {
+        //                  scanner.currentPosition--;
+        //                  getNextToken();
+        //                }
+        //                break;
+        //            }
+        //          }
+        //          token = tempToken;
+        //        }
+        break;
+      case TokenNameDOLLAR_LBRACE :
+        getNextToken();
+        if (token == TokenNameIdentifier) {
+          getNextToken();
+          if (token == TokenNameLBRACKET) {
+            getNextToken();
+            //            if (token == TokenNameRBRACKET) {
+            //              getNextToken();
+            //            } else {
+            expr();
+            if (token != TokenNameRBRACKET) {
+              throwSyntaxError("']' expected after '${'.");
+            }
+            getNextToken();
+            //            }
+          }
+          if (token != TokenNameRBRACE) {
+            throwSyntaxError("'}' expected after '${'.");
+          }
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+        } else {
+          expr();
+          if (token != TokenNameRBRACE) {
+            throwSyntaxError("'}' expected.");
+          }
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+        }
+        break;
+      case TokenNameCURLY_OPEN :
+        getNextToken();
+        if (token == TokenNameIdentifier) {
+          getNextToken();
+          if (token == TokenNameLBRACKET) {
+            getNextToken();
+            //            if (token == TokenNameRBRACKET) {
+            //              getNextToken();
+            //            } else {
+            expr();
+            if (token != TokenNameRBRACKET) {
+              throwSyntaxError("']' expected after '{$'.");
+            }
+            getNextToken();
+            //            }
+          } else if (token == TokenNameMINUS_GREATER) {
+            getNextToken();
+            if (token != TokenNameIdentifier) {
+              throwSyntaxError("String token expected.");
+            }
+            getNextToken();
+          }
+          //          if (token != TokenNameRBRACE) {
+          //            throwSyntaxError("'}' expected after '{$'.");
+          //          }
+          //          // scanner.encapsedStringStack.pop();
+          //          getNextToken();
+        } else {
+          expr();
+          if (token != TokenNameRBRACE) {
+            throwSyntaxError("'}' expected.");
+          }
+          //          scanner.encapsedStringStack.pop();
+          getNextToken();
+        }
+        break;
+    }
+  }
+  private void encaps_var_offset() {
+    //                 T_STRING
+    //         | T_NUM_STRING
+    //         | T_VARIABLE
+    switch (token) {
+      case TokenNameSTRING :
+        getNextToken();
+        break;
+      case TokenNameIntegerLiteral :
+        getNextToken();
+        break;
+      case TokenNameVariable :
+        getNextToken();
+        break;
+      case TokenNameIdentifier :
+        getNextToken();
+        break;
+      default :
+        throwSyntaxError("Variable or String token expected.");
+        break;
+    }
+  }
   private void internal_functions_in_yacc() {
     switch (token) {
       case TokenNameisset :
@@ -2878,6 +3150,17 @@ public class Parser //extends PHPParserSuperclass
     }
     return false;
   }
+  private void scalar() {
+    //  scalar:
+    // T_STRING
+    //| T_STRING_VARNAME
+    //| class_constant
+    //| common_scalar
+    //| '"' encaps_list '"'
+    //| '\'' encaps_list '\''
+    //| T_START_HEREDOC encaps_list T_END_HEREDOC
+    throwSyntaxError("Not yet implemented (scalar).");
+  }
   private void static_scalar() {
     //    static_scalar: /* compile-time evaluated scalars */
     //         common_scalar
@@ -2903,6 +3186,48 @@ public class Parser //extends PHPParserSuperclass
           }
         }
         break;
+      case TokenNameEncapsedString0 :
+        try {
+          scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+          while (scanner.currentCharacter != '`') {
+            if (scanner.currentCharacter == '\\') {
+              scanner.currentPosition++;
+            }
+            scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+          }
+          getNextToken();
+        } catch (IndexOutOfBoundsException e) {
+          throwSyntaxError("'`' expected at end of static string.");
+        }
+        break;
+      case TokenNameEncapsedString1 :
+        try {
+          scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+          while (scanner.currentCharacter != '\'') {
+            if (scanner.currentCharacter == '\\') {
+              scanner.currentPosition++;
+            }
+            scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+          }
+          getNextToken();
+        } catch (IndexOutOfBoundsException e) {
+          throwSyntaxError("'\'' expected at end of static string.");
+        }
+        break;
+      case TokenNameEncapsedString2 :
+        try {
+          scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+          while (scanner.currentCharacter != '"') {
+            if (scanner.currentCharacter == '\\') {
+              scanner.currentPosition++;
+            }
+            scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+          }
+          getNextToken();
+        } catch (IndexOutOfBoundsException e) {
+          throwSyntaxError("'\"' expected at end of static string.");
+        }
+        break;
       case TokenNamePLUS :
         getNextToken();
         static_scalar();
@@ -2957,7 +3282,7 @@ public class Parser //extends PHPParserSuperclass
         break;
       }
       getNextToken();
-      if (token != TokenNameRPAREN) {
+      if (token == TokenNameRPAREN) {
         break;
       }
     }