Added "Task Tags" functionality (TODO,...)
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Parser.java
index dceae31..238bdbe 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
  **********************************************************************/
 package net.sourceforge.phpdt.internal.compiler.parser;
 import java.util.ArrayList;
+
 import net.sourceforge.phpdt.core.compiler.CharOperation;
 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
 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 net.sourceforge.phpdt.internal.compiler.util.Util;
+
 import org.eclipse.core.resources.IFile;
 public class Parser //extends PHPParserSuperclass
     implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
@@ -62,10 +67,12 @@ 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() {
+  protected Parser(ProblemReporter problemReporter) {
+    this.problemReporter = problemReporter;
+    this.options = problemReporter.options;
     this.currentPHPString = 0;
     //         PHPParserSuperclass.fileToParse = fileToParse;
     this.phpList = null;
@@ -115,7 +122,14 @@ public class Parser //extends PHPParserSuperclass
     this.initializeScanner();
   }
   public void initializeScanner() {
-    this.scanner = new Scanner(false, false, false, false);
+       this.scanner = new Scanner(
+               false /*comment*/, 
+               false /*whitespace*/, 
+               this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /*nls*/, 
+               false, 
+               false, 
+               this.options.taskTags/*taskTags*/,
+               this.options.taskPriorites/*taskPriorities*/);
   }
   /**
    * Create marker for the parse error
@@ -136,7 +150,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
@@ -165,6 +179,12 @@ public class Parser //extends PHPParserSuperclass
             problemEndPosition, referenceContext,
             compilationUnit.compilationResult);
   }
+  private void reportSyntaxWarning(String error, int problemStartPosition,
+      int problemEndPosition) {
+    problemReporter.phpParsingWarning(new String[]{error},
+        problemStartPosition, problemEndPosition, referenceContext,
+        compilationUnit.compilationResult);
+  }
   /**
    * Method Declaration.
    * 
@@ -200,426 +220,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;
@@ -627,7 +227,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);
@@ -641,7 +241,7 @@ public class Parser //extends PHPParserSuperclass
     //    this.rowCount = 1;
     //    this.columnCount = 0;
     this.phpEnd = false;
-    this.phpMode = phpMode;
+    //    this.phpMode = phpMode;
     scanner.setPHPMode(phpMode);
   }
   /**
@@ -688,7 +288,7 @@ public class Parser //extends PHPParserSuperclass
           }
           throwSyntaxError("End-of-file not reached.");
         }
-        return;
+        break;
       } catch (SyntaxError sytaxErr1) {
         // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
         // ERROR);
@@ -707,7 +307,7 @@ public class Parser //extends PHPParserSuperclass
             getNextToken();
           }
           if (token == TokenNameEOF || token == TokenNameERROR) {
-            return;
+            break;
           }
         } catch (SyntaxError sytaxErr2) {
           //    setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
@@ -715,10 +315,48 @@ public class Parser //extends PHPParserSuperclass
           //          setMarker(sytaxErr2.getMessage(),
           // scanner.getCurrentTokenStartPosition(),
           // scanner.getCurrentTokenEndPosition(), ERROR);
-          return;
+          break;
         }
       }
     } while (true);
+    
+    endParse(0);
+  }
+    
+  protected CompilationUnitDeclaration endParse(int act) {
+
+    this.lastAct = act;
+
+    if (currentElement != null) {
+      currentElement.topElement().updateParseTree();
+      if (VERBOSE_RECOVERY) {
+        System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
+        System.out.println("--------------------------"); //$NON-NLS-1$
+        System.out.println(compilationUnit);
+        System.out.println("----------------------------------"); //$NON-NLS-1$
+      }
+    } else {
+      if (diet & VERBOSE_RECOVERY) {
+        System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
+        System.out.println("--------------------------"); //$NON-NLS-1$
+        System.out.println(compilationUnit);
+        System.out.println("----------------------------------"); //$NON-NLS-1$
+      }
+    }
+    if (scanner.recordLineSeparator) {
+      compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
+    }
+    if (scanner.taskTags != null) {
+      for (int i = 0; i < scanner.foundTaskCount; i++) {
+        problemReporter().task(
+          new String(scanner.foundTaskTags[i]),
+          new String(scanner.foundTaskMessages[i]),
+          scanner.foundTaskPriorities[i] == null ? null : new String(scanner.foundTaskPriorities[i]),
+          scanner.foundTaskPositions[i][0],
+          scanner.foundTaskPositions[i][1]);
+      }
+    }
+    return compilationUnit;
   }
   //  public PHPOutlineInfo parseInfo(Object parent, String s) {
   //    PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
@@ -740,7 +378,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) {
@@ -943,49 +581,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();
@@ -1073,16 +713,16 @@ public class Parser //extends PHPParserSuperclass
       getNextToken();
       if (token == TokenNameLBRACE) {
         getNextToken();
+        if (token != TokenNameRBRACE) {
+          statementList();
+        }
+        if (token == TokenNameRBRACE) {
+          getNextToken();
+        } else {
+          throwSyntaxError("'}' expected after 'do' keyword.");
+        }
       } else {
-        throwSyntaxError("'{' expected after 'do' keyword.");
-      }
-      if (token != TokenNameRBRACE) {
-        statementList();
-      }
-      if (token == TokenNameRBRACE) {
-        getNextToken();
-      } else {
-        throwSyntaxError("'}' expected after 'do' keyword.");
+        statement(TokenNameEOF);
       }
       if (token == TokenNamewhile) {
         getNextToken();
@@ -1103,7 +743,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();
@@ -1122,7 +762,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();
@@ -1143,7 +785,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();
@@ -1155,12 +797,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();
@@ -1173,83 +818,48 @@ 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 == TokenNameunset) {
+    } else if (token == TokenNamestatic) {
       getNextToken();
-      if (token == TokenNameLPAREN) {
-        getNextToken();
-      } else {
-        throwSyntaxError("'(' expected after 'unset' statement.");
-      }
-      unset_variables();
-      if (token == TokenNameRPAREN) {
-        getNextToken();
-      } else {
-        throwSyntaxError("')' expected after 'unset' statement.");
-      }
+      static_var_list();
       if (token == TokenNameSEMICOLON) {
         getNextToken();
       } else {
-        if (token != TokenNameStopPHP) {
-          throwSyntaxError("';' expected after 'unset' statement.");
+        if (token != TokenNameINLINE_HTML) {
+          throwSyntaxError("';' expected after 'static' 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) {
+    } else if (token == TokenNameunset) {
       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();
+        throwSyntaxError("'(' expected after 'unset' statement.");
       }
+      unset_variables();
       if (token == TokenNameRPAREN) {
         getNextToken();
       } else {
-        throwSyntaxError("')' expected after 'define' statement.");
+        throwSyntaxError("')' expected after 'unset' statement.");
       }
       if (token == TokenNameSEMICOLON) {
         getNextToken();
       } else {
-        if (token != TokenNameStopPHP) {
-          throwSyntaxError("';' expected after 'define' statement.");
+        if (token != TokenNameINLINE_HTML) {
+          throwSyntaxError("';' expected after 'unset' statement.");
         }
         getNextToken();
       }
@@ -1262,6 +872,55 @@ 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();
+      if (token != TokenNameRBRACE) {
+        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(
@@ -1300,7 +959,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) + ")");
         }
@@ -1308,6 +967,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
@@ -1381,14 +1138,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 {
@@ -1410,10 +1166,10 @@ public class Parser //extends PHPParserSuperclass
         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
         getNextToken();
       } else {
-        throwSyntaxError("'}' expected at end of interface body.");
+        throwSyntaxError("'}' expected at end of class body.");
       }
     } else {
-      throwSyntaxError("'{' expected at start of interface body.");
+      throwSyntaxError("'{' expected at start of class body.");
     }
   }
   private void class_entry_type() {
@@ -1431,12 +1187,13 @@ public class Parser //extends PHPParserSuperclass
       getNextToken();
     } else if (token == TokenNamefinal) {
       checkAndSetModifiers(AccFinal);
+      getNextToken();
       if (token != TokenNameclass) {
         throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
       }
       getNextToken();
     } else {
-        throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
+      throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
     }
   }
   private void interface_extends_list() {
@@ -1491,7 +1248,11 @@ public class Parser //extends PHPParserSuperclass
   private void class_statement_list() {
     do {
       class_statement();
-    } while (token == TokenNamefunction || token == TokenNamevar);
+    } while (token == TokenNamepublic || token == TokenNameprotected
+        || token == TokenNameprivate || token == TokenNamestatic
+        || token == TokenNameabstract || token == TokenNamefinal
+        || token == TokenNamefunction || token == TokenNamevar
+        || token == TokenNameconst);
   }
   private void class_statement() {
     //    class_statement:
@@ -1502,12 +1263,18 @@ public class Parser //extends PHPParserSuperclass
     initializeModifiers();
     if (token == TokenNamevar) {
       checkAndSetModifiers(AccPublic);
-      reportSyntaxError(
-          "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected' modifier for field declarations.",
-          scanner.getCurrentTokenStartPosition(), scanner
-              .getCurrentTokenEndPosition());
+      problemReporter.phpVarDeprecatedWarning(scanner
+          .getCurrentTokenStartPosition(),
+          scanner.getCurrentTokenEndPosition(), referenceContext,
+          compilationUnit.compilationResult);
+      getNextToken();
+      class_variable_declaration();
+    } else if (token == TokenNameconst) {
+      class_constant_declaration();
+      if (token != TokenNameSEMICOLON) {
+        throwSyntaxError("';' expected after class const declaration.");
+      }
       getNextToken();
-      classProperty();
     } else {
       boolean hasModifiers = member_modifiers();
       if (token == TokenNamefunction) {
@@ -1525,7 +1292,7 @@ public class Parser //extends PHPParserSuperclass
         if (!hasModifiers) {
           throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
         }
-        classProperty();
+        class_variable_declaration();
       }
     }
     //    if (token == TokenNamefunction) {
@@ -1542,6 +1309,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
@@ -1610,34 +1401,42 @@ public class Parser //extends PHPParserSuperclass
     }
     return foundToken;
   }
-  private void classProperty() {
-    //'var' variable ';'
-    //'var' variable '=' constant ';'
+  private void class_variable_declaration() {
+    //    class_variable_declaration:
+    //         class_variable_declaration ',' T_VARIABLE
+    // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
+    // | T_VARIABLE
+    // | T_VARIABLE '=' static_scalar
     do {
       if (token == TokenNameVariable) {
+        FieldDeclaration fieldDeclaration = new FieldDeclaration(null, scanner
+            .getCurrentIdentifierSource(), scanner
+            .getCurrentTokenStartPosition(), scanner
+            .getCurrentTokenEndPosition());
         getNextToken();
         if (token == TokenNameEQUAL) {
           getNextToken();
-          constant();
+          static_scalar();
         }
       } else {
-        if (token == TokenNamethis) {
-          throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
-        }
-        throwSyntaxError("Variable expected after keyword '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;
       }
       getNextToken();
     } while (true);
-    if (token == TokenNameSEMICOLON) {
-      getNextToken();
-    } else {
-      throwSyntaxError("';' expected after variable declaration.");
+    if (token != TokenNameSEMICOLON) {
+      throwSyntaxError("';' expected after field declaration.");
     }
+    getNextToken();
   }
   private void functionDefinition(MethodDeclaration methodDecl) {
+    boolean isAbstract = false;
     if (astPtr == 0) {
       compilationUnit.types.add(methodDecl);
     } else {
@@ -1657,9 +1456,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) {
@@ -1678,7 +1490,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.");
@@ -1695,16 +1507,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
@@ -1722,13 +1572,14 @@ public class Parser //extends PHPParserSuperclass
       getNextToken();
       if (token == TokenNameEQUAL) {
         getNextToken();
-        constant();
+        static_scalar();
       }
       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) {
@@ -1740,10 +1591,8 @@ public class Parser //extends PHPParserSuperclass
         expr(); //constant();
         if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
           getNextToken();
-          if (token == TokenNamecase || token == TokenNamedefault) { // empty
-            // case
-            // statement
-            // ?
+          if (token == TokenNamecase || token == TokenNamedefault) { 
+            // empty case statement ?
             continue;
           }
           statementList();
@@ -1769,6 +1618,10 @@ public class Parser //extends PHPParserSuperclass
         getNextToken();
         if (token == TokenNameCOLON) {
           getNextToken();
+          if (token==TokenNameRBRACE) {
+            // empty default case
+            break;
+          }
           statementList();
         } else {
           throwSyntaxError("':' character after 'default' expected.");
@@ -2032,29 +1885,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 :
@@ -2065,601 +1974,863 @@ public class Parser //extends PHPParserSuperclass
       case TokenNamerequire_once :
         internal_functions_in_yacc();
         break;
-      case TokenNamenew :
+      //       | '(' expr ')'
+      case TokenNameLPAREN :
         getNextToken();
         expr();
+        if (token == TokenNameRPAREN) {
+          getNextToken();
+        } else {
+          throwSyntaxError("')' expected in expression.");
+        }
         break;
-      case TokenNamenull :
-        getNextToken();
-        break;
-      case TokenNamefalse :
-        getNextToken();
-        break;
-      case TokenNametrue :
-        getNextToken();
-        break;
-      case TokenNameStringConstant :
+      //    | 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 TokenNameHEREDOC :
-      case TokenNameStringInterpolated :
-      case TokenNameStringLiteral :
+      case TokenNameexit :
         getNextToken();
+        exit_expr();
         break;
-      case TokenNameLPAREN :
+      //  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();
-        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;
+        try {
+          if (token == TokenNameEncapsedString0) {
+          } else {
+            encaps_list();
+            if (token != TokenNameEncapsedString0) {
+              throwSyntaxError("\'`\' expected at end of string"
+                  + "(Found token: " + scanner.toStringAction(token) + " )");
             }
           }
-        }
-        if (castFlag) {
+        } finally {
+          scanner.encapsedStringStack.pop();
           getNextToken();
-          if (arrayFlag && token == TokenNameLPAREN) {
-            getNextToken();
-            if (token == TokenNameRPAREN) {
-              getNextToken();
-            } else {
-              expr();
-              if (token != TokenNameRPAREN) {
-                throwSyntaxError(") expected after 'array('.");
-              }
+        }
+        break;
+      //      | '\'' encaps_list '\''
+      case TokenNameEncapsedString1 :
+        scanner.encapsedStringStack.push(new Character('\''));
+        getNextToken();
+        try {
+          if (token == TokenNameEncapsedString1) {
+          } else {
+            encaps_list();
+            if (token != TokenNameEncapsedString1) {
+              throwSyntaxError("\'\'\' expected at end of string"
+                  + "(Found token: " + scanner.toStringAction(token) + " )");
             }
           }
-          if (token != TokenNameRPAREN) {
-            throwSyntaxError(") expected after cast-type '" + str + "'.");
-          }
+        } finally {
+          scanner.encapsedStringStack.pop();
           getNextToken();
-          expr();
-          break;
-        } else {
-          expr();
-        }
-        if (token != TokenNameRPAREN) {
-          throwSyntaxError(") expected in postfix-expression.");
         }
-        getNextToken();
         break;
-      case TokenNameDoubleLiteral :
+      //| '"' encaps_list '"'
+      case TokenNameEncapsedString2 :
+        scanner.encapsedStringStack.push(new Character('"'));
         getNextToken();
+        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 :
-        getNextToken();
+      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 TokenNameDOLLAR_LBRACE :
-        getNextToken();
-        expr();
-        if (token != TokenNameRBRACE) {
-          throwSyntaxError("'}' expected after indirect variable token '${'.");
-        }
+      case TokenNameHEREDOC :
         getNextToken();
         break;
-      case TokenNameVariable :
-      case TokenNamethis :
-        ident = scanner.getCurrentIdentifierSource();
+      case TokenNamearray :
+        //    T_ARRAY '(' array_pair_list ')'
         getNextToken();
-        if (token == TokenNameLBRACE) {
+        if (token == TokenNameLPAREN) {
           getNextToken();
-          expr();
-          if (token != TokenNameRBRACE) {
-            throwSyntaxError("'}' expected after variable '"
-                + new String(ident) + "' in variable-expression.");
+          if (token == TokenNameRPAREN) {
+            getNextToken();
+            break;
           }
-          getNextToken();
-        } else if (token == TokenNameLPAREN) {
-          getNextToken();
+          array_pair_list();
           if (token != TokenNameRPAREN) {
-            expressionList();
-            if (token != TokenNameRPAREN) {
-              throwSyntaxError("')' expected after variable '"
-                  + new String(ident) + "' in postfix-expression.");
-            }
+            throwSyntaxError("')' expected after keyword 'array'"
+                + "(Found token: " + scanner.toStringAction(token) + ")");
           }
           getNextToken();
+        } else {
+          throwSyntaxError("'(' expected after keyword 'array'"
+              + "(Found token: " + scanner.toStringAction(token) + ")");
         }
         break;
-      case TokenNameIdentifier :
-        ident = scanner.getCurrentIdentifierSource();
+      case TokenNamelist :
+        //    | T_LIST '(' assignment_list ')' '=' expr
         getNextToken();
         if (token == TokenNameLPAREN) {
           getNextToken();
+          assignment_list();
           if (token != TokenNameRPAREN) {
-            expressionList();
-            if (token != TokenNameRPAREN) {
-              throwSyntaxError("')' expected after identifier '"
-                  + new String(ident) + "' in postfix-expression."
-                  + "(Found token: " + scanner.toStringAction(token) + ")");
-            }
+            throwSyntaxError("')' expected after 'list' keyword.");
+          }
+          getNextToken();
+          if (token != TokenNameEQUAL) {
+            throwSyntaxError("'=' expected after 'list' keyword.");
           }
           getNextToken();
+          expr();
+        } else {
+          throwSyntaxError("'(' expected after 'list' keyword.");
         }
         break;
-      case TokenNameprint :
+      case TokenNamenew :
+        //     | T_NEW class_name_reference ctor_arguments
         getNextToken();
-        expr();
+        class_name_reference();
+        ctor_arguments();
         break;
-      case TokenNameexit :
+      //       | T_INC rw_variable
+      //       | T_DEC rw_variable
+      case TokenNamePLUS_PLUS :
+      case TokenNameMINUS_MINUS :
         getNextToken();
-        exit_expr();
+        rw_variable();
         break;
-      case TokenNamelist :
-        getNextToken();
-        if (token == TokenNameLPAREN) {
-          getNextToken();
-          if (token == TokenNameCOMMA) {
+      //       | 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();
-          }
-          expressionList();
-          if (token != TokenNameRPAREN) {
-            throwSyntaxError("')' expected after 'list' keyword.");
-          }
-          getNextToken();
-          //          if (token == TokenNameSET) {
-          //            getNextToken();
-          //            logicalinclusiveorExpression();
-          //          }
-        } else {
-          throwSyntaxError("'(' expected after 'list' keyword.");
+            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;
-    //      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;
+      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.");
-          }
-          getNextToken();
-          break;
-        case TokenNameCOLON_COLON :
-        // ::
-        case TokenNameMINUS_GREATER :
-          // ->
-          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();
-            }
-          }
           break;
-        case TokenNamePLUS_PLUS :
+        //  | expr T_INSTANCEOF class_name_reference
+        //     | expr '?' expr ':' expr
+        case TokenNameinstanceof :
           getNextToken();
+          class_name_reference();
           break;
-        case TokenNameMINUS_MINUS :
+        case TokenNameQUESTION :
           getNextToken();
+          expr();
+          if (token == TokenNameCOLON) {
+            getNextToken();
+            expr();
+          }
           break;
         default :
-          while_flag = false;
+          return;
       }
-    } while (while_flag);
-  }
-  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 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) { // *=
-      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) { // >>=
+  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();
-      logicalinclusiveorExpression();
-    } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
+    } 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();
-      logicalinclusiveorExpression();
+      object_property();
+      dynamic_class_name_variable_properties();
     }
   }
-  private void multiplicativeExpression() {
-    do {
-      assignExpression();
-      if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE
-          && token != TokenNameREMAINDER) {
-        return;
-      }
+  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();
-    } while (true);
+      object_property();
+    }
   }
-  private void concatenationExpression() {
-    do {
-      multiplicativeExpression();
-      if (token != TokenNameDOT) {
+  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();
-    } while (true);
+    }
   }
-  private void additiveExpression() {
-    do {
-      concatenationExpression();
-      if (token != TokenNamePLUS && token != TokenNameMINUS) {
-        return;
+  private void assignment_list() {
+    //  assignment_list:
+    // assignment_list ',' assignment_list_element
+    //| assignment_list_element
+    while (true) {
+      assignment_list_element();
+      if (token != TokenNameCOMMA) {
+        break;
       }
       getNextToken();
-    } while (true);
+    }
   }
-  private void shiftExpression() {
-    do {
-      additiveExpression();
-      if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
-        return;
+  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();
+          assignment_list();
+          if (token != TokenNameRPAREN) {
+            throwSyntaxError("')' expected after 'list' keyword.");
+          }
+          getNextToken();
+        } else {
+          throwSyntaxError("'(' expected after 'list' keyword.");
+        }
       }
+    }
+  }
+  private void array_pair_list() {
+    //  array_pair_list:
+    // /* empty */
+    //| non_empty_array_pair_list possible_comma
+    non_empty_array_pair_list();
+    if (token == TokenNameCOMMA) {
       getNextToken();
-    } while (true);
+    }
   }
-  private void relationalExpression() {
-    do {
-      shiftExpression();
-      if (token != TokenNameLESS && token != TokenNameGREATER
-          && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
+  private void non_empty_array_pair_list() {
+    //non_empty_array_pair_list:
+    // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
+    //| non_empty_array_pair_list ',' expr
+    //| expr T_DOUBLE_ARROW expr
+    //| expr
+    //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
+    //| non_empty_array_pair_list ',' '&' w_variable
+    //| expr T_DOUBLE_ARROW '&' w_variable
+    //| '&' w_variable
+    while (true) {
+      if (token == TokenNameAND) {
+        getNextToken();
+        variable();
+      } else {
+        expr();
+        if (token == TokenNameAND) {
+          getNextToken();
+          variable();
+        } else if (token == TokenNameEQUAL_GREATER) {
+          getNextToken();
+          if (token == TokenNameAND) {
+            getNextToken();
+            variable();
+          } else {
+            expr();
+          }
+        }
+      }
+      if (token != TokenNameCOMMA) {
         return;
       }
       getNextToken();
-    } while (true);
-  }
-  private void identicalExpression() {
-    do {
-      relationalExpression();
-      if (token != TokenNameEQUAL_EQUAL_EQUAL
-          && token != TokenNameNOT_EQUAL_EQUAL) {
+      if (token == TokenNameRPAREN) {
         return;
       }
-      getNextToken();
-    } while (true);
+    }
   }
-  private void equalityExpression() {
-    do {
-      identicalExpression();
-      if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
-        return;
+  //  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()");
+    }
+    while (token == TokenNameDOLLAR) {
+      getNextToken();
+    }
+    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();
+      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 ternaryExpression() {
-    equalityExpression();
-    if (token == TokenNameQUESTION) {
-      getNextToken();
-      expr();
-      if (token == TokenNameCOLON) {
+  //  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();
-        expr();
+        w_variable();
       } else {
-        throwSyntaxError("':' expected in ternary operator '? :'.");
+        //        if (token == TokenNameIdentifier || token == TokenNameVariable
+        //            || token == TokenNameDOLLAR) {
+        //          variable();
+        //        } else {
+        expr_without_variable(true);
+        //        }
       }
-    }
-  }
-  private void andExpression() {
-    do {
-      ternaryExpression();
-      if (token != TokenNameAND) {
-        return;
+      if (token != TokenNameCOMMA) {
+        break;
       }
       getNextToken();
-    } while (true);
+    }
   }
-  private void exclusiveorExpression() {
-    do {
-      andExpression();
-      if (token != TokenNameXOR) {
-        return;
-      }
+  private void fully_qualified_class_name() {
+    if (token == TokenNameIdentifier) {
       getNextToken();
-    } while (true);
+    } else {
+      throwSyntaxError("Class name expected.");
+    }
   }
-  private void inclusiveorExpression() {
-    do {
-      exclusiveorExpression();
-      if (token != TokenNameOR) {
-        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 booleanandExpression() {
-    do {
-      inclusiveorExpression();
-      if (token != TokenNameAND_AND) {
-        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 booleanorExpression() {
-    do {
-      booleanandExpression();
-      if (token != TokenNameOR_OR) {
-        return;
+  //  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 {
+        break;
       }
-      getNextToken();
-    } while (true);
+    }
   }
-  private void logicalandExpression() {
-    do {
-      booleanorExpression();
-      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 logicalexclusiveorExpression() {
-    do {
-      logicalandExpression();
-      if (token != TokenNameXOR) {
-        return;
+    } else {
+      // because of simple_indirect_reference
+      while (token == TokenNameDOLLAR) {
+        getNextToken();
+      }
+      if (token != TokenNameLBRACE) {
+        throwSyntaxError("'{' expected after compound variable token '$'.");
       }
       getNextToken();
-    } while (true);
-  }
-  private void logicalinclusiveorExpression() {
-    do {
-      logicalexclusiveorExpression();
-      if (token != TokenNameOR) {
-        return;
+      expr();
+      if (token != TokenNameRBRACE) {
+        throwSyntaxError("'}' expected after compound variable token '$'.");
       }
       getNextToken();
-    } while (true);
+    }
   }
-  //  public void assignmentExpression() {
-  //    if (token == TokenNameVARIABLE) {
-  //      getNextToken();
-  //      if (token == TokenNameSET) {
-  //        getNextToken();
-  //        logicalinclusiveorExpression();
-  //      }
-  //    } else {
-  //      logicalinclusiveorExpression();
-  //    }
+  //  private void dim_offset() {
+  //    // dim_offset:
+  //    // /* empty */
+  //    // | expr
+  //    expr();
   //  }
-  private void variableList() {
-    do {
-      variable();
-      if (token == TokenNameCOMMA) {
+  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;
       }
-    } while (true);
+    }
   }
-  private void variable() {
-    if (token == TokenNameDOLLAR_LBRACE) {
+  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();
+    } else {
+      if (token != TokenNameLBRACE) {
+        throwSyntaxError("'{' expected in variable name.");
+      }
       getNextToken();
       expr();
-      ;
       if (token != TokenNameRBRACE) {
-        throwSyntaxError("'}' expected after indirect variable token '${'.");
+        throwSyntaxError("'}' expected in variable name.");
       }
       getNextToken();
+    }
+  }
+  private void r_variable() {
+    variable();
+  }
+  private void w_variable() {
+    variable();
+  }
+  private void rw_variable() {
+    variable();
+  }
+  private void variable() {
+    //    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();
-          constant();
-        }
-      } 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() {
@@ -2680,6 +2851,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 :
@@ -2758,80 +3167,185 @@ public class Parser //extends PHPParserSuperclass
       }
     }
   }
-  /**
-   * It will look for a value (after a '=' for example) @
-   */
-  private void constant() {
-    //   String ident;
+  private boolean common_scalar() {
+    //  common_scalar:
+    // T_LNUMBER
+    // | T_DNUMBER
+    // | T_CONSTANT_ENCAPSED_STRING
+    // | T_LINE
+    // | T_FILE
+    // | T_CLASS_C
+    // | T_METHOD_C
+    // | T_FUNC_C
     switch (token) {
-      case TokenNamePLUS :
+      case TokenNameIntegerLiteral :
         getNextToken();
-        switch (token) {
-          case TokenNameDoubleLiteral :
-            getNextToken();
-            break;
-          case TokenNameIntegerLiteral :
-            getNextToken();
-            break;
-          default :
-            throwSyntaxError("Constant expected after '+' presign.");
-        }
-        break;
-      case TokenNameMINUS :
+        return true;
+      case TokenNameDoubleLiteral :
         getNextToken();
-        switch (token) {
-          case TokenNameDoubleLiteral :
-            getNextToken();
-            break;
-          case TokenNameIntegerLiteral :
-            getNextToken();
-            break;
-          default :
-            throwSyntaxError("Constant expected after '-' presign.");
-        }
-        break;
-      case TokenNamenull :
+        return true;
+      case TokenNameStringLiteral :
         getNextToken();
-        break;
-      case TokenNamefalse :
+        return true;
+      case TokenNameStringConstant :
         getNextToken();
-        break;
-      case TokenNametrue :
+        return true;
+      case TokenNameStringInterpolated :
         getNextToken();
-        break;
+        return true;
+      case TokenNameFILE :
+        getNextToken();
+        return true;
+      case TokenNameLINE :
+        getNextToken();
+        return true;
+      case TokenNameCLASS_C :
+        getNextToken();
+        return true;
+      case TokenNameMETHOD_C :
+        getNextToken();
+        return true;
+      case TokenNameFUNC_C :
+        getNextToken();
+        return true;
+    }
+    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
+    // | T_STRING
+    // | '+' static_scalar
+    // | '-' static_scalar
+    // | T_ARRAY '(' static_array_pair_list ')'
+    // | static_class_constant
+    if (common_scalar()) {
+      return;
+    }
+    switch (token) {
       case TokenNameIdentifier :
-        //   ident = identifier;
-        char[] ident = scanner.getCurrentIdentifierSource();
         getNextToken();
-        if (token == TokenNameLPAREN) {
+        //        static_class_constant:
+        //             T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
+        if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
           getNextToken();
-          if (token != TokenNameRPAREN) {
-            expressionList();
-            if (token != TokenNameRPAREN) {
-              throwSyntaxError("')' expected after identifier '"
-                  + new String(ident) + "' in postfix-expression.");
+          if (token == TokenNameIdentifier) {
+            getNextToken();
+          } else {
+            throwSyntaxError("Identifier expected after '::' operator.");
+          }
+        }
+        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 TokenNameStringLiteral :
-        getNextToken();
+      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 TokenNameStringConstant :
-        getNextToken();
+      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 TokenNameStringInterpolated :
+      case TokenNamePLUS :
         getNextToken();
+        static_scalar();
         break;
-      case TokenNameDoubleLiteral :
+      case TokenNameMINUS :
         getNextToken();
+        static_scalar();
         break;
-      case TokenNameIntegerLiteral :
+      case TokenNamearray :
+        getNextToken();
+        if (token != TokenNameLPAREN) {
+          throwSyntaxError("'(' expected after keyword 'array'");
+        }
+        getNextToken();
+        if (token == TokenNameRPAREN) {
+          getNextToken();
+          break;
+        }
+        non_empty_static_array_pair_list();
+        if (token != TokenNameRPAREN) {
+          throwSyntaxError("')' expected after keyword 'array'");
+        }
         getNextToken();
         break;
+      //      case TokenNamenull :
+      //        getNextToken();
+      //        break;
+      //      case TokenNamefalse :
+      //        getNextToken();
+      //        break;
+      //      case TokenNametrue :
+      //        getNextToken();
+      //        break;
       default :
-        throwSyntaxError("Constant expected.");
+        throwSyntaxError("Static scalar/constant expected.");
+    }
+  }
+  private void non_empty_static_array_pair_list() {
+    //  non_empty_static_array_pair_list:
+    // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
+    // static_scalar
+    //| non_empty_static_array_pair_list ',' static_scalar
+    //| static_scalar T_DOUBLE_ARROW static_scalar
+    //| static_scalar
+    while (true) {
+      static_scalar();
+      if (token == TokenNameEQUAL_GREATER) {
+        getNextToken();
+        static_scalar();
+      }
+      if (token != TokenNameCOMMA) {
+        break;
+      }
+      getNextToken();
+      if (token == TokenNameRPAREN) {
+        break;
+      }
     }
   }
   public void reportSyntaxError() { //int act, int currentKind, int
@@ -2956,6 +3470,7 @@ public class Parser //extends PHPParserSuperclass
                                                       */
   protected ReferenceContext referenceContext;
   protected ProblemReporter problemReporter;
+  protected CompilerOptions options;
   //  protected CompilationResult compilationResult;
   /**
    * Returns this parser's problem reporter initialized with its reference