Improved calculation of function/methods sourceEnd for code folding
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Parser.java
index d3e2a3c..0b0ae25 100644 (file)
@@ -310,7 +310,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
    */
   public void parse(String s, HashMap variables) {
     fMethodVariables = variables;
-    fStackUnassigned = new Stack();
+    fStackUnassigned = new ArrayList();
     init(s);
     parse();
   }
@@ -418,10 +418,11 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       } catch (SyntaxError sytaxErr1) {
         return;
       } finally {
-        int sourceEnd = scanner.getCurrentTokenStartPosition();
+        int sourceEnd = methodDecl.sourceEnd;
         if (sourceEnd <= 0 || methodDecl.declarationSourceStart > sourceEnd) {
           sourceEnd = methodDecl.declarationSourceStart + 1;
         }
+        methodDecl.sourceEnd = sourceEnd;
         methodDecl.declarationSourceEnd = sourceEnd;
       }
     }
@@ -474,9 +475,9 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
         statement = statement();
         blockStatements.add(statement);
         if (branchStatement && statement != null) {
-//          reportSyntaxError("Unreachable code", statement.sourceStart, statement.sourceEnd);
-          problemReporter.unreachableCode(new String(scanner.getCurrentIdentifierSource()),statement.sourceStart, statement.sourceEnd,
-              referenceContext, compilationUnit.compilationResult);
+          //          reportSyntaxError("Unreachable code", statement.sourceStart, statement.sourceEnd);
+          problemReporter.unreachableCode(new String(scanner.getCurrentIdentifierSource()), statement.sourceStart,
+              statement.sourceEnd, referenceContext, compilationUnit.compilationResult);
         }
         if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse)
             || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
@@ -554,15 +555,17 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     if (token == TokenNameLBRACE) {
       getNextToken();
     } else {
+      methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
       throwSyntaxError("'{' expected in compound-statement.");
     }
     if (token != TokenNameRBRACE) {
       statementList();
     }
     if (token == TokenNameRBRACE) {
-      //      methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
+      methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
       getNextToken();
     } else {
+      methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
       throwSyntaxError("'}' expected in compound-statement.");
     }
   }
@@ -723,7 +726,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       foreach_optional_arg();
       if (token == TokenNameEQUAL_GREATER) {
         getNextToken();
-        variable(false);
+        variable(false, false);
       }
       if (token == TokenNameRPAREN) {
         getNextToken();
@@ -865,11 +868,12 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
         getNextToken();
         functionDefinition(methodDecl);
       } finally {
-        sourceEnd = scanner.getCurrentTokenStartPosition();
+        sourceEnd = methodDecl.sourceEnd;
         if (sourceEnd <= 0 || methodDecl.declarationSourceStart > sourceEnd) {
           sourceEnd = methodDecl.declarationSourceStart + 1;
         }
         methodDecl.declarationSourceEnd = sourceEnd;
+        methodDecl.sourceEnd = sourceEnd;
       }
       return statement;
     } else if (token == TokenNamedeclare) {
@@ -1129,7 +1133,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
         if (fMethodVariables != null) {
           VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_STATIC_VAR);
           fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info);
-        } 
+        }
         addVariableSet(set);
         getNextToken();
         if (token == TokenNameEQUAL) {
@@ -1153,7 +1157,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     //    unset_variable:
     //                 variable
     while (true) {
-      variable(false);
+      variable(false, false);
       if (token != TokenNameCOMMA) {
         break;
       }
@@ -1427,11 +1431,12 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
           getNextToken();
           functionDefinition(methodDecl);
         } finally {
-          int sourceEnd = scanner.getCurrentTokenStartPosition();
+          int sourceEnd = methodDecl.sourceEnd;
           if (sourceEnd <= 0 || methodDecl.declarationSourceStart > sourceEnd) {
             sourceEnd = methodDecl.declarationSourceStart + 1;
           }
           methodDecl.declarationSourceEnd = sourceEnd;
+          methodDecl.sourceEnd = sourceEnd;
         }
       } else {
         if (!hasModifiers) {
@@ -1617,10 +1622,11 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       }
     }
     try {
-      pushVariableSet();
+      pushFunctionVariableSet();
       functionDeclarator(methodDecl);
       if (token == TokenNameSEMICOLON) {
         if (!isAbstract) {
+          methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
           throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector));
         }
         getNextToken();
@@ -1628,7 +1634,9 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       }
       functionBody(methodDecl);
     } finally {
-      fStackUnassigned.pop();
+      if (!fStackUnassigned.isEmpty()) {
+        fStackUnassigned.remove(fStackUnassigned.size() - 1);
+      }
     }
   }
 
@@ -1649,12 +1657,14 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       if (token == TokenNameLPAREN) {
         getNextToken();
       } else {
+        methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
         throwSyntaxError("'(' expected in function declaration.");
       }
       if (token != TokenNameRPAREN) {
         parameter_list(methodDecl);
       }
       if (token != TokenNameRPAREN) {
+        methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
         throwSyntaxError("')' expected in function declaration.");
       } else {
         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
@@ -1662,6 +1672,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       }
     } else {
       methodDecl.selector = "<undefined>".toCharArray();
+      methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
       throwSyntaxError("Function name expected after keyword 'function'.");
     }
   }
@@ -1810,13 +1821,38 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
 
   private void ifStatementColon(IfStatement iState) {
     // T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
-    Block b = inner_statement_list();
-    iState.thenStatement = b;
-    checkUnreachable(iState, b);
+    HashSet assignedVariableSet = null;
+    try {
+      Block b = inner_statement_list();
+      iState.thenStatement = b;
+      checkUnreachable(iState, b);
+    } finally {
+      assignedVariableSet = removeIfVariableSet();
+    }
     if (token == TokenNameelseif) {
-      new_elseif_list(iState);
+      try {
+        pushIfVariableSet();
+        new_elseif_list(iState);
+      } finally {
+        HashSet set = removeIfVariableSet();
+        if (assignedVariableSet != null) {
+          assignedVariableSet.addAll(set);
+        }
+      }
+    }
+    try {
+      pushIfVariableSet();
+      new_else_single(iState);
+    } finally {
+      HashSet set = removeIfVariableSet();
+      if (assignedVariableSet != null) {
+        HashSet topSet = peekVariableSet();
+        if (topSet != null) {
+          topSet.addAll(set);
+          topSet.addAll(assignedVariableSet);
+        }
+      }
     }
-    new_else_single(iState);
     if (token != TokenNameendif) {
       throwSyntaxError("'endif' expected.");
     }
@@ -1832,13 +1868,40 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
 
   private void ifStatement(IfStatement iState) {
     //  T_IF '(' expr ')' statement elseif_list else_single
-    Statement s = statement();
-    iState.thenStatement = s;
-    checkUnreachable(iState, s);
+    HashSet assignedVariableSet = null;
+    try {
+      pushIfVariableSet();
+      Statement s = statement();
+      iState.thenStatement = s;
+      checkUnreachable(iState, s);
+    } finally {
+      assignedVariableSet = removeIfVariableSet();
+    }
+
     if (token == TokenNameelseif) {
-      elseif_list(iState);
+      try {
+        pushIfVariableSet();
+        elseif_list(iState);
+      } finally {
+        HashSet set = removeIfVariableSet();
+        if (assignedVariableSet != null) {
+          assignedVariableSet.addAll(set);
+        }
+      }
+    }
+    try {
+      pushIfVariableSet();
+      else_single(iState);
+    } finally {
+      HashSet set = removeIfVariableSet();
+      if (assignedVariableSet != null) {
+        HashSet topSet = peekVariableSet();
+        if (topSet != null) {
+          topSet.addAll(set);
+          topSet.addAll(assignedVariableSet);
+        }
+      }
     }
-    else_single(iState);
   }
 
   private void elseif_list(IfStatement iState) {
@@ -2217,7 +2280,30 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       }
       switch (token) {
       case TokenNameisset:
+        //     T_ISSET '(' isset_variables ')'
+        getNextToken();
+        if (token != TokenNameLPAREN) {
+          throwSyntaxError("'(' expected after keyword 'isset'");
+        }
+        getNextToken();
+        isset_variables();
+        if (token != TokenNameRPAREN) {
+          throwSyntaxError("')' expected after keyword 'isset'");
+        }
+        getNextToken();
+        break;
       case TokenNameempty:
+        getNextToken();
+        if (token != TokenNameLPAREN) {
+          throwSyntaxError("'(' expected after keyword 'empty'");
+        }
+        getNextToken();
+        variable(true, false);
+        if (token != TokenNameRPAREN) {
+          throwSyntaxError("')' expected after keyword 'empty'");
+        }
+        getNextToken();
+        break;
       case TokenNameeval:
       case TokenNameinclude:
       case TokenNameinclude_once:
@@ -2435,18 +2521,29 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       case TokenNameIdentifier:
       case TokenNameVariable:
       case TokenNameDOLLAR:
-        boolean rememberedVar = false;
-//        char[] lhsVar = null;
-//        if (token==TokenNameVariable) {
-//          lhsVar = scanner.getCurrentTokenSource();
-//        }
-        Expression lhs = variable(true);
+        boolean rememberedVar = false; 
+        Expression lhs = variable(true, true);
+        if (lhs != null && lhs instanceof FieldReference && token != TokenNameEQUAL && token != TokenNamePLUS_EQUAL
+            && token != TokenNameMINUS_EQUAL && token != TokenNameMULTIPLY_EQUAL && token != TokenNameDIVIDE_EQUAL
+            && token != TokenNameDOT_EQUAL && token != TokenNameREMAINDER_EQUAL && token != TokenNameAND_EQUAL
+            && token != TokenNameOR_EQUAL && token != TokenNameXOR_EQUAL && token != TokenNameRIGHT_SHIFT_EQUAL
+            && token != TokenNameLEFT_SHIFT_EQUAL) {
+          FieldReference ref = (FieldReference) lhs;
+          if (!containsVariableSet(ref.token)) {
+            problemReporter.uninitializedLocalVariable(new String(ref.token), ref.sourceStart(), ref.sourceEnd(), referenceContext,
+                compilationUnit.compilationResult);
+            addVariableSet(ref.token);
+          }
+        }
 
         switch (token) {
         case TokenNameEQUAL:
-//          if (lhsVar != null) {
-//            addVariableSet(lhsVar);
-//          }
+          if (lhs != null && lhs instanceof FieldReference) {
+            addVariableSet(((FieldReference) lhs).token);
+          }
+          //          if (lhsVar != null) {
+          //            addVariableSet(lhsVar);
+          //          }
           getNextToken();
           if (token == TokenNameAND) {
             getNextToken();
@@ -2470,7 +2567,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
                 }
               }
             } else {
-              Expression rhs = variable(false);
+              Expression rhs = variable(false, false);
               if (rhs != null && rhs instanceof FieldReference && lhs != null && lhs instanceof FieldReference) {
                 // example:
                 // $var = &$ref;
@@ -2533,6 +2630,9 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
         case TokenNameXOR_EQUAL:
         case TokenNameRIGHT_SHIFT_EQUAL:
         case TokenNameLEFT_SHIFT_EQUAL:
+          if (lhs != null && lhs instanceof FieldReference) {
+            addVariableSet(((FieldReference) lhs).token);
+          }
           getNextToken();
           expr();
           break;
@@ -2759,9 +2859,9 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     //| T_LIST '(' assignment_list ')'
     //| /* empty */
     if (token == TokenNameVariable) {
-      variable(true);
+      variable(true, false);
     } else if (token == TokenNameDOLLAR) {
-      variable(false);
+      variable(false, false);
     } else {
       if (token == TokenNamelist) {
         getNextToken();
@@ -2802,17 +2902,17 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     while (true) {
       if (token == TokenNameAND) {
         getNextToken();
-        variable(false);
+        variable(true, false);
       } else {
         expr();
         if (token == TokenNameAND) {
           getNextToken();
-          variable(false);
+          variable(true, false);
         } else if (token == TokenNameEQUAL_GREATER) {
           getNextToken();
           if (token == TokenNameAND) {
             getNextToken();
-            variable(false);
+            variable(true, false);
           } else {
             expr();
           }
@@ -2838,7 +2938,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
   //      }
   //    } while (true);
   //  }
-  private Expression variable_without_objects(boolean lefthandside) {
+  private Expression variable_without_objects(boolean lefthandside, boolean ignoreVar) {
     //  variable_without_objects:
     //                 reference_variable
     //         | simple_indirect_reference reference_variable
@@ -2848,10 +2948,10 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     while (token == TokenNameDOLLAR) {
       getNextToken();
     }
-    return reference_variable(lefthandside);
+    return reference_variable(lefthandside, ignoreVar);
   }
 
-  private Expression function_call(boolean lefthandside) {
+  private Expression function_call(boolean lefthandside, boolean ignoreVar) {
     //  function_call:
     // T_STRING '(' function_call_parameter_list ')'
     //| class_constant '(' function_call_parameter_list ')'
@@ -2881,12 +2981,12 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
           getNextToken();
         } else {
           //        static member:
-          variable_without_objects(false);
+          variable_without_objects(true, false);
         }
         break;
       }
     } else {
-      ref = variable_without_objects(lefthandside);
+      ref = variable_without_objects(lefthandside, ignoreVar);
     }
     if (token != TokenNameLPAREN) {
       if (defineName != null) {
@@ -2957,7 +3057,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     while (true) {
       if (token == TokenNameAND) {
         getNextToken();
-        w_variable(false);
+        w_variable(true);
       } else {
         //        if (token == TokenNameIdentifier || token ==
         // TokenNameVariable
@@ -2994,10 +3094,10 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       throwSyntaxError("'::' expected after class name (static_member).");
     }
     getNextToken();
-    variable_without_objects(false);
+    variable_without_objects(false, false);
   }
 
-  private Expression base_variable_with_function_calls(boolean lefthandside) {
+  private Expression base_variable_with_function_calls(boolean lefthandside, boolean ignoreVar) {
     //  base_variable_with_function_calls:
     // base_variable
     //| function_call
@@ -3019,7 +3119,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     //      scanner.phpMode = true;
     //    }
     //    if (functionCall) {
-    return function_call(lefthandside);
+    return function_call(lefthandside, ignoreVar);
     //    } else {
     //      base_variable();
     //    }
@@ -3040,7 +3140,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       while (token == TokenNameDOLLAR) {
         getNextToken();
       }
-      reference_variable(false);
+      reference_variable(false, false);
     }
     return ref;
   }
@@ -3050,7 +3150,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
   //    // '$'
   //    //| simple_indirect_reference '$'
   //  }
-  private Expression reference_variable(boolean lefthandside) {
+  private Expression reference_variable(boolean lefthandside, boolean ignoreVar) {
     //  reference_variable:
     //                 reference_variable '[' dim_offset ']'
     //         | reference_variable '{' expr '}'
@@ -3059,7 +3159,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     if (Scanner.TRACE) {
       System.out.println("TRACE: reference_variable()");
     }
-    ref = compound_variable(lefthandside);
+    ref = compound_variable(lefthandside, ignoreVar);
     while (true) {
       if (token == TokenNameLBRACE) {
         ref = null;
@@ -3070,6 +3170,10 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
         }
         getNextToken();
       } else if (token == TokenNameLBRACKET) {
+        if (ref != null && ref instanceof FieldReference) {
+          FieldReference fref = (FieldReference) ref;
+          addVariableSet(fref.token);
+        }
         ref = null;
         getNextToken();
         if (token != TokenNameRBRACKET) {
@@ -3087,7 +3191,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     return ref;
   }
 
-  private Expression compound_variable(boolean lefthandside) {
+  private Expression compound_variable(boolean lefthandside, boolean ignoreVar) {
     //  compound_variable:
     //                 T_VARIABLE
     //         | '$' '{' expr '}'
@@ -3097,13 +3201,16 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     if (token == TokenNameVariable) {
       if (!lefthandside) {
         if (!containsVariableSet()) {
-//          reportSyntaxError("The local variable " + new String(scanner.getCurrentIdentifierSource())
-//              + " may not have been initialized");
-          problemReporter.uninitializedLocalVariable(new String(scanner.getCurrentIdentifierSource()),scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
-              referenceContext, compilationUnit.compilationResult);
+          //          reportSyntaxError("The local variable " + new String(scanner.getCurrentIdentifierSource())
+          //              + " may not have been initialized");
+          problemReporter.uninitializedLocalVariable(new String(scanner.getCurrentIdentifierSource()), scanner
+              .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), referenceContext,
+              compilationUnit.compilationResult);
         }
       } else {
-        addVariableSet();
+        if (!ignoreVar) {
+          addVariableSet();
+        }
       }
       FieldReference ref = new FieldReference(scanner.getCurrentIdentifierSource(), scanner.getCurrentTokenStartPosition());
       getNextToken();
@@ -3125,11 +3232,8 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       getNextToken();
     }
     return null;
-  }
+  } //  private void dim_offset() { // // dim_offset: // // /* empty */
 
-  //  private void dim_offset() {
-  //    // dim_offset:
-  //    // /* empty */
   //    // | expr
   //    expr();
   //  }
@@ -3141,7 +3245,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       System.out.println("TRACE: object_property()");
     }
     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
-      variable_without_objects(false);
+      variable_without_objects(false, false);
     } else {
       object_dim_list();
     }
@@ -3207,23 +3311,23 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
   }
 
   private void r_variable() {
-    variable(false);
+    variable(false, false);
   }
 
   private void w_variable(boolean lefthandside) {
-    variable(lefthandside);
+    variable(lefthandside, false);
   }
 
   private void rw_variable() {
-    variable(false);
+    variable(false, false);
   }
 
-  private Expression variable(boolean lefthandside) {
+  private Expression variable(boolean lefthandside, boolean ignoreVar) {
     //    variable:
     //         base_variable_with_function_calls T_OBJECT_OPERATOR
     //                 object_property method_or_not variable_properties
     // | base_variable_with_function_calls
-    Expression ref = base_variable_with_function_calls(lefthandside);
+    Expression ref = base_variable_with_function_calls(lefthandside, ignoreVar);
     if (token == TokenNameMINUS_GREATER) {
       ref = null;
       getNextToken();
@@ -3542,32 +3646,32 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
   private void internal_functions_in_yacc() {
     //    int start = 0;
     switch (token) {
-    case TokenNameisset:
-      //       T_ISSET '(' isset_variables ')'
-      getNextToken();
-      if (token != TokenNameLPAREN) {
-        throwSyntaxError("'(' expected after keyword 'isset'");
-      }
-      getNextToken();
-      isset_variables();
-      if (token != TokenNameRPAREN) {
-        throwSyntaxError("')' expected after keyword 'isset'");
-      }
-      getNextToken();
-      break;
-    case TokenNameempty:
-      //       T_EMPTY '(' variable ')'
-      getNextToken();
-      if (token != TokenNameLPAREN) {
-        throwSyntaxError("'(' expected after keyword 'empty'");
-      }
-      getNextToken();
-      variable(false);
-      if (token != TokenNameRPAREN) {
-        throwSyntaxError("')' expected after keyword 'empty'");
-      }
-      getNextToken();
-      break;
+    //    case TokenNameisset:
+    //      // T_ISSET '(' isset_variables ')'
+    //      getNextToken();
+    //      if (token != TokenNameLPAREN) {
+    //        throwSyntaxError("'(' expected after keyword 'isset'");
+    //      }
+    //      getNextToken();
+    //      isset_variables();
+    //      if (token != TokenNameRPAREN) {
+    //        throwSyntaxError("')' expected after keyword 'isset'");
+    //      }
+    //      getNextToken();
+    //      break;
+    //    case TokenNameempty:
+    //      // T_EMPTY '(' variable ')'
+    //      getNextToken();
+    //      if (token != TokenNameLPAREN) {
+    //        throwSyntaxError("'(' expected after keyword 'empty'");
+    //      }
+    //      getNextToken();
+    //      variable(false);
+    //      if (token != TokenNameRPAREN) {
+    //        throwSyntaxError("')' expected after keyword 'empty'");
+    //      }
+    //      getNextToken();
+    //      break;
     case TokenNameinclude:
       //T_INCLUDE expr
       checkFileName(token);
@@ -3694,7 +3798,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       throwSyntaxError("Variable expected after keyword 'isset'");
     }
     while (true) {
-      variable(false);
+      variable(true, false);
       if (token == TokenNameCOMMA) {
         getNextToken();
       } else {
@@ -4012,7 +4116,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
 
   HashMap fMethodVariables = null;
 
-  Stack fStackUnassigned = new Stack();
+  ArrayList fStackUnassigned = new ArrayList();
 
   //ast stack
   final static int AstStackIncrement = 100;
@@ -4528,25 +4632,41 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       "$_POST",
       "$_REQUEST",
       "$_SESSION",
-      "$_SERVER"
-  };
+      "$_SERVER" };
+
   /**
-   * 
+   *  
    */
-  private void pushVariableSet() {
-    HashSet set =new HashSet();
-    for (int i = 0; i < GLOBALS.length; i++) {
-      set.add(GLOBALS[i]);
+  private void pushFunctionVariableSet() {
+    HashSet set = new HashSet();
+    if (fStackUnassigned.isEmpty()) {
+      for (int i = 0; i < GLOBALS.length; i++) {
+        set.add(GLOBALS[i]);
+      }
+    }
+    fStackUnassigned.add(set);
+  }
+
+  private void pushIfVariableSet() {
+    if (!fStackUnassigned.isEmpty()) {
+      HashSet set = new HashSet();
+      fStackUnassigned.add(set);
+    }
+  }
+
+  private HashSet removeIfVariableSet() {
+    if (!fStackUnassigned.isEmpty()) {
+      return (HashSet) fStackUnassigned.remove(fStackUnassigned.size() - 1);
     }
-    fStackUnassigned.push(set);
+    return null;
   }
-  
+
   /**
    * Returns the <i>set of assigned variables </i> returns null if no Set is defined at the current scanner position
    */
   private HashSet peekVariableSet() {
     if (!fStackUnassigned.isEmpty()) {
-      return (HashSet) fStackUnassigned.peek();
+      return (HashSet) fStackUnassigned.get(fStackUnassigned.size() - 1);
     }
     return null;
   }
@@ -4590,9 +4710,33 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
    *  
    */
   private boolean containsVariableSet() {
-    HashSet set = peekVariableSet();
-    if (set != null) {
-      return set.contains(new String(scanner.getCurrentTokenSource()));
+    return containsVariableSet(scanner.getCurrentTokenSource());
+    //    if (!fStackUnassigned.isEmpty()) {
+    //      HashSet set;
+    //      String str = new String(scanner.getCurrentTokenSource());
+    //      for (int i = 0; i < fStackUnassigned.size(); i++) {
+    //        set = (HashSet) fStackUnassigned.get(i);
+    //        if (set.contains(str)) {
+    //          return true;
+    //        }
+    //      }
+    //      return false;
+    //    }
+    //    return true;
+  }
+
+  private boolean containsVariableSet(char[] token) {
+
+    if (!fStackUnassigned.isEmpty()) {
+      HashSet set;
+      String str = new String(token);
+      for (int i = 0; i < fStackUnassigned.size(); i++) {
+        set = (HashSet) fStackUnassigned.get(i);
+        if (set.contains(str)) {
+          return true;
+        }
+      }
+      return false;
     }
     return true;
   }