changeset 22196:dd992fd74fce

put parser, lexer, and evaluator in namespace; interpreter now owns evaluator * oct-parse.in.yy, parse.h: Move parser classes to octave namespace. * lex.ll, lex.h: Move lexer classes to octave namespace. * pt-eval.h, pt-eval.cc: Move evaluator class to octave namespace. Don't define global current evaluator pointer here. * debug.cc, error.cc, input.cc, input.h, ls-mat-ascii.cc, pt-jit.cc, sighandlers.cc, utils.cc, variables.cc, ov-usr-fcn.cc, pt-assign.cc, pt-exp.h, pt-id.cc: Update for namespaces. * interpreter.cc, interpreter.h (current_evaluator): New global var. (interpreter::m_evaluator): New data member. (interpreter::~interpreter): Delete evaluator.
author John W. Eaton <jwe@octave.org>
date Tue, 12 Jul 2016 14:28:07 -0400
parents 93ed9396f2c3
children e43d83253e28
files libinterp/corefcn/debug.cc libinterp/corefcn/error.cc libinterp/corefcn/input.cc libinterp/corefcn/input.h libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/corefcn/ls-mat-ascii.cc libinterp/corefcn/pt-jit.cc libinterp/corefcn/sighandlers.cc libinterp/corefcn/utils.cc libinterp/corefcn/variables.cc libinterp/octave-value/ov-usr-fcn.cc libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/parse.h libinterp/parse-tree/pt-assign.cc libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-exp.h libinterp/parse-tree/pt-id.cc
diffstat 21 files changed, 5643 insertions(+), 5585 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/debug.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/debug.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -623,7 +623,7 @@
 {
   if (cond.length () > 0)
     {
-      octave_parser parser (cond + " ;"); // ; to reject partial expr like "y=="
+      octave::parser parser (cond + " ;"); // ; to reject partial expr like "y=="
       parser.reset ();
       int parse_status = parser.run ();
       if (parse_status)
@@ -753,7 +753,7 @@
         }
     }
 
-  tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
+  octave::tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
 
   return retval;
 }
@@ -851,7 +851,7 @@
         }
     }
 
-  tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
+  octave::tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
 
   return retval;
 }
@@ -884,7 +884,7 @@
     error ("remove_all_breakpoint_in_file: "
            "unable to find function %s\n", fname.c_str ());
 
-  tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
+  octave::tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
 
   return retval;
 }
@@ -901,7 +901,7 @@
       remove_all_breakpoints_in_file (*it);
     }
 
-  tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
+  octave::tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
 }
 
 std::string
@@ -2096,14 +2096,14 @@
           Vdebugging = false;
           Vtrack_line_num = true;
 
-          tree_evaluator::dbstep_flag = -1;
+          octave::tree_evaluator::dbstep_flag = -1;
         }
       else if (arg == "out")
         {
           Vdebugging = false;
           Vtrack_line_num = true;
 
-          tree_evaluator::dbstep_flag = -2;
+          octave::tree_evaluator::dbstep_flag = -2;
         }
       else
         {
@@ -2115,7 +2115,7 @@
           Vdebugging = false;
           Vtrack_line_num = true;
 
-          tree_evaluator::dbstep_flag = n;
+          octave::tree_evaluator::dbstep_flag = n;
         }
     }
   else
@@ -2123,7 +2123,7 @@
       Vdebugging = false;
       Vtrack_line_num = true;
 
-      tree_evaluator::dbstep_flag = 1;
+      octave::tree_evaluator::dbstep_flag = 1;
     }
 
   return ovl ();
@@ -2147,7 +2147,7 @@
   Vdebugging = false;
   Vtrack_line_num = true;
 
-  tree_evaluator::reset_debug_state ();
+  octave::tree_evaluator::reset_debug_state ();
 
   return ovl ();
 }
@@ -2168,7 +2168,7 @@
 
   Vdebugging = false;
 
-  tree_evaluator::reset_debug_state ();
+  octave::tree_evaluator::reset_debug_state ();
 
   octave_throw_interrupt_exception ();
 
@@ -2207,7 +2207,7 @@
   if (nargin == 1)
     state = args(0).bool_value ();
 
-  tree_evaluator::quiet_breakpoint_flag = state;
+  octave::tree_evaluator::quiet_breakpoint_flag = state;
 
   return ovl ();
 }
--- a/libinterp/corefcn/error.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/error.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -325,9 +325,9 @@
       frame.protect_var (Vdebug_on_error);
       Vdebug_on_error = false;
 
-      tree_evaluator::debug_mode = true;
+      octave::tree_evaluator::debug_mode = true;
 
-      tree_evaluator::current_frame = octave_call_stack::current_frame ();
+      octave::tree_evaluator::current_frame = octave_call_stack::current_frame ();
 
       if (show_stack_trace)
         {
@@ -731,9 +731,9 @@
           frame.protect_var (Vdebug_on_warning);
           Vdebug_on_warning = false;
 
-          tree_evaluator::debug_mode = true;
+          octave::tree_evaluator::debug_mode = true;
 
-          tree_evaluator::current_frame = octave_call_stack::current_frame ();
+          octave::tree_evaluator::current_frame = octave_call_stack::current_frame ();
 
           do_keyboard (octave_value_list ());
         }
--- a/libinterp/corefcn/input.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/input.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -586,8 +586,8 @@
 {
   octave::unwind_protect frame;
 
-  bool silent = tree_evaluator::quiet_breakpoint_flag;
-  tree_evaluator::quiet_breakpoint_flag = false;
+  bool silent = octave::tree_evaluator::quiet_breakpoint_flag;
+  octave::tree_evaluator::quiet_breakpoint_flag = false;
 
   octave_user_code *caller = octave_call_stack::caller_user_code ();
   std::string nm;
@@ -681,7 +681,7 @@
       app->forced_interactive (true);
     }
 
-  octave_parser curr_parser;
+  octave::parser curr_parser;
 
   while (Vdebugging)
     {
@@ -701,7 +701,7 @@
             {
               if (retval == 0 && curr_parser.stmt_list)
                 {
-                  curr_parser.stmt_list->accept (*current_evaluator);
+                  curr_parser.stmt_list->accept (*octave::current_evaluator);
 
                   if (octave_completion_matches_called)
                     octave_completion_matches_called = false;
@@ -993,10 +993,10 @@
   // Skip the frame assigned to the keyboard function.
   octave_call_stack::goto_frame_relative (0);
 
-  tree_evaluator::debug_mode = true;
-  tree_evaluator::quiet_breakpoint_flag = false;
+  octave::tree_evaluator::debug_mode = true;
+  octave::tree_evaluator::quiet_breakpoint_flag = false;
 
-  tree_evaluator::current_frame = octave_call_stack::current_frame ();
+  octave::tree_evaluator::current_frame = octave_call_stack::current_frame ();
 
   do_keyboard (args);
 
--- a/libinterp/corefcn/input.h	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/input.h	Tue Jul 12 14:28:07 2016 -0400
@@ -36,7 +36,10 @@
 #include "pager.h"
 
 class octave_value;
-class octave_base_lexer;
+namespace octave
+{
+  class base_lexer;
+}
 
 extern OCTINTERP_API FILE *get_input_from_stdin (void);
 
@@ -89,7 +92,7 @@
 
   friend class octave_input_reader;
 
-  octave_base_reader (octave_base_lexer *lxr)
+  octave_base_reader (octave::base_lexer *lxr)
     : count (1), pflag (0), lexer (lxr)
   { }
 
@@ -138,7 +141,7 @@
 
   int pflag;
 
-  octave_base_lexer *lexer;
+  octave::base_lexer *lexer;
 
   void do_input_echo (const std::string&) const;
 
@@ -150,7 +153,7 @@
 {
 public:
 
-  octave_terminal_reader (octave_base_lexer *lxr = 0)
+  octave_terminal_reader (octave::base_lexer *lxr = 0)
     : octave_base_reader (lxr)
   { }
 
@@ -170,7 +173,7 @@
 {
 public:
 
-  octave_file_reader (FILE *f_arg, octave_base_lexer *lxr = 0)
+  octave_file_reader (FILE *f_arg, octave::base_lexer *lxr = 0)
     : octave_base_reader (lxr), file (f_arg) { }
 
   std::string get_input (bool& eof);
@@ -192,7 +195,7 @@
 public:
 
   octave_eval_string_reader (const std::string& str,
-                             octave_base_lexer *lxr = 0)
+                             octave::base_lexer *lxr = 0)
     : octave_base_reader (lxr), eval_string (str)
   { }
 
@@ -213,15 +216,15 @@
 octave_input_reader
 {
 public:
-  octave_input_reader (octave_base_lexer *lxr = 0)
+  octave_input_reader (octave::base_lexer *lxr = 0)
     : rep (new octave_terminal_reader (lxr))
   { }
 
-  octave_input_reader (FILE *file, octave_base_lexer *lxr = 0)
+  octave_input_reader (FILE *file, octave::base_lexer *lxr = 0)
     : rep (new octave_file_reader (file, lxr))
   { }
 
-  octave_input_reader (const std::string& str, octave_base_lexer *lxr = 0)
+  octave_input_reader (const std::string& str, octave::base_lexer *lxr = 0)
     : rep (new octave_eval_string_reader (str, lxr))
   { }
 
--- a/libinterp/corefcn/interpreter.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/interpreter.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -526,10 +526,15 @@
 
 namespace octave
 {
+  tree_evaluator *current_evaluator = 0;
+
   interpreter::interpreter (application *app_context, bool embedded)
-    : m_app_context (app_context), m_embedded (embedded),
-      m_interactive (false), m_quitting_gracefully (false)
+    : m_app_context (app_context), m_evaluator (new tree_evaluator (this)),
+      m_embedded (embedded), m_interactive (false),
+      m_quitting_gracefully (false)
   {
+    current_evaluator = m_evaluator;
+
     cmdline_options options = m_app_context->options ();
 
     // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting
@@ -645,6 +650,13 @@
     initialize_history (options.read_history_file ());
   }
 
+  interpreter::~interpreter (void)
+  {
+    current_evaluator = 0;
+
+    delete m_evaluator;
+  }
+
   int interpreter::execute (void)
   {
     cmdline_options options = m_app_context->options ();
@@ -858,11 +870,11 @@
 
     // The big loop.
 
-    octave_lexer *lxr = (octave::application::interactive ()
-                         ? new octave_lexer ()
-                         : new octave_lexer (stdin));
+    octave::lexer *lxr = (octave::application::interactive ()
+                          ? new octave::lexer ()
+                          : new octave::lexer (stdin));
 
-    octave_parser parser (*lxr);
+    octave::parser parser (*lxr);
 
     int retval = 0;
     do
@@ -874,7 +886,7 @@
             parser.reset ();
 
             if (symbol_table::at_top_level ())
-              tree_evaluator::reset_debug_state ();
+              octave::tree_evaluator::reset_debug_state ();
 
             retval = parser.run ();
 
--- a/libinterp/corefcn/interpreter.h	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/interpreter.h	Tue Jul 12 14:28:07 2016 -0400
@@ -30,6 +30,8 @@
 #include "quit.h"
 #include "str-vec.h"
 
+#include "pt-eval.h"
+
 typedef void (*octave_exit_func) (int);
 extern OCTINTERP_API octave_exit_func octave_exit;
 
@@ -85,6 +87,8 @@
 
 namespace octave
 {
+  extern tree_evaluator *current_evaluator;
+
   // The application object contains a pointer to the current
   // interpreter and the interpreter contains a pointer back to the
   // application context so we need a forward declaration for one (or
@@ -98,7 +102,7 @@
 
     interpreter (application *app_context = 0, bool embedded = false);
 
-    ~interpreter (void) { }
+    ~interpreter (void);
 
     int execute (void);
 
@@ -123,6 +127,8 @@
 
     application *m_app_context;
 
+    tree_evaluator *m_evaluator;
+
     bool m_embedded;
 
     // TRUE means this is an interactive interpreter (forced or not).
--- a/libinterp/corefcn/ls-mat-ascii.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/ls-mat-ascii.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -255,7 +255,7 @@
         varname[i] = '_';
     }
 
-  if (is_keyword (varname) || ! isalpha (varname[0]))
+  if (octave::is_keyword (varname) || ! isalpha (varname[0]))
     varname.insert (0, "X");
 
   if (! valid_identifier (varname))
--- a/libinterp/corefcn/pt-jit.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/pt-jit.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -780,7 +780,7 @@
     visit (cmd);
   else
     {
-      // stolen from tree_evaluator::visit_statement
+      // stolen from octave::tree_evaluator::visit_statement
       bool do_bind_ans = false;
 
       if (expr->is_identifier ())
--- a/libinterp/corefcn/sighandlers.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/sighandlers.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -490,7 +490,7 @@
           {
             if (! octave_debug_on_interrupt_state)
               {
-                tree_evaluator::debug_mode = true;
+                octave::tree_evaluator::debug_mode = true;
                 octave_debug_on_interrupt_state = true;
 
                 return;
@@ -499,7 +499,7 @@
               {
                 // Clear the flag and do normal interrupt stuff.
 
-                tree_evaluator::debug_mode
+                octave::tree_evaluator::debug_mode
                   = bp_table::have_breakpoints () || Vdebugging;
                 octave_debug_on_interrupt_state = false;
               }
--- a/libinterp/corefcn/utils.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/utils.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -105,7 +105,7 @@
     {
       std::string varname = args(0).string_value ();
 
-      retval = valid_identifier (varname) && ! is_keyword (varname);
+      retval = valid_identifier (varname) && ! octave::is_keyword (varname);
     }
 
   return retval;
--- a/libinterp/corefcn/variables.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/corefcn/variables.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -380,7 +380,7 @@
 int
 symbol_exist (const std::string& name, const std::string& type)
 {
-  if (is_keyword (name))
+  if (octave::is_keyword (name))
     return 0;
 
   bool search_any = type == "any";
--- a/libinterp/octave-value/ov-usr-fcn.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -141,15 +141,16 @@
 
       frame.add_fcn (octave_call_stack::pop);
 
+      // Update line number even if debugging.
       frame.protect_var (Vtrack_line_num);
-      Vtrack_line_num = true;    // update line no. even if debugging
+      Vtrack_line_num = true;
 
-      frame.protect_var (tree_evaluator::statement_context);
-      tree_evaluator::statement_context = tree_evaluator::script;
+      frame.protect_var (octave::tree_evaluator::statement_context);
+      octave::tree_evaluator::statement_context = octave::tree_evaluator::script;
 
       BEGIN_PROFILER_BLOCK (octave_user_script)
 
-        cmd_list->accept (*current_evaluator);
+        cmd_list->accept (*octave::current_evaluator);
 
       END_PROFILER_BLOCK
 
@@ -583,8 +584,8 @@
 
   // Evaluate the commands that make up the function.
 
-  frame.protect_var (tree_evaluator::statement_context);
-  tree_evaluator::statement_context = tree_evaluator::function;
+  frame.protect_var (octave::tree_evaluator::statement_context);
+  octave::tree_evaluator::statement_context = octave::tree_evaluator::function;
 
   BEGIN_PROFILER_BLOCK (octave_user_function)
 
@@ -598,7 +599,7 @@
                   : expr->rvalue (nargout));
     }
   else
-    cmd_list->accept (*current_evaluator);
+    cmd_list->accept (*octave::current_evaluator);
 
   END_PROFILER_BLOCK
 
--- a/libinterp/parse-tree/lex.h	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/parse-tree/lex.h	Tue Jul 12 14:28:07 2016 -0400
@@ -35,791 +35,820 @@
 #include "input.h"
 #include "token.h"
 
-// Is the given string a keyword?
-extern bool is_keyword (const std::string& s);
-
-// For communication between the lexer and parser.
+namespace octave
+{
+  class interpreter;
 
-class
-lexical_feedback
-{
-public:
+  // Is the given string a keyword?
+  extern bool is_keyword (const std::string& s);
 
-  // Track symbol table information when parsing functions.
+  // For communication between the lexer and parser.
 
-  class symbol_table_context
+  class
+  lexical_feedback
   {
   public:
 
-    symbol_table_context (void) : frame_stack () { }
+    // Track symbol table information when parsing functions.
 
-    void clear (void)
+    class symbol_table_context
     {
-      while (! frame_stack.empty ())
-        frame_stack.pop ();
-    }
+    public:
 
-    bool empty (void) const { return frame_stack.empty (); }
+      symbol_table_context (void) : frame_stack () { }
 
-    void pop (void)
-    {
-      if (empty ())
-        panic_impossible ();
+      void clear (void)
+      {
+        while (! frame_stack.empty ())
+          frame_stack.pop ();
+      }
 
-      frame_stack.pop ();
-    }
-
-    void push (symbol_table::scope_id scope = symbol_table::current_scope ())
-    {
-      frame_stack.push (scope);
-    }
+      bool empty (void) const { return frame_stack.empty (); }
 
-    symbol_table::scope_id curr_scope (void) const
-    {
-      return empty () ? symbol_table::current_scope () : frame_stack.top ();
-    }
+      void pop (void)
+      {
+        if (empty ())
+          panic_impossible ();
 
-  private:
-
-    std::stack<symbol_table::scope_id> frame_stack;
-  };
+        frame_stack.pop ();
+      }
 
-  // Track nesting of square brackets, curly braces, and parentheses.
-
-  class bbp_nesting_level
-  {
-  private:
+      void push (symbol_table::scope_id scope = symbol_table::current_scope ())
+      {
+        frame_stack.push (scope);
+      }
 
-    enum bracket_type
-    {
-      BRACKET = 1,
-      BRACE = 2,
-      PAREN = 3,
-      ANON_FCN_BODY = 4
+      symbol_table::scope_id curr_scope (void) const
+      {
+        return empty () ? symbol_table::current_scope () : frame_stack.top ();
+      }
+
+    private:
+
+      std::stack<symbol_table::scope_id> frame_stack;
     };
 
-  public:
+    // Track nesting of square brackets, curly braces, and parentheses.
+
+    class bbp_nesting_level
+    {
+    private:
 
-    bbp_nesting_level (void) : context () { }
+      enum bracket_type
+        {
+          BRACKET = 1,
+          BRACE = 2,
+          PAREN = 3,
+          ANON_FCN_BODY = 4
+        };
+
+    public:
+
+      bbp_nesting_level (void) : context () { }
+
+      bbp_nesting_level (const bbp_nesting_level& nl) : context (nl.context) { }
 
-    bbp_nesting_level (const bbp_nesting_level& nl) : context (nl.context) { }
+      bbp_nesting_level& operator = (const bbp_nesting_level& nl)
+      {
+        if (&nl != this)
+          context = nl.context;
+
+        return *this;
+      }
+
+      ~bbp_nesting_level (void) { }
 
-    bbp_nesting_level& operator = (const bbp_nesting_level& nl)
-    {
-      if (&nl != this)
-        context = nl.context;
+      void reset (void)
+      {
+        while (! context.empty ())
+          context.pop ();
+      }
+
+      void bracket (void) { context.push (BRACKET); }
+
+      bool is_bracket (void)
+      {
+        return ! context.empty () && context.top () == BRACKET;
+      }
+
+      void brace (void) { context.push (BRACE); }
 
-      return *this;
-    }
+      bool is_brace (void)
+      {
+        return ! context.empty () && context.top () == BRACE;
+      }
+
+      void paren (void) { context.push (PAREN); }
+
+      bool is_paren (void)
+      {
+        return ! context.empty () && context.top () == PAREN;
+      }
 
-    ~bbp_nesting_level (void) { }
+      void anon_fcn_body (void) { context.push (ANON_FCN_BODY); }
+
+      bool is_anon_fcn_body (void)
+      {
+        return ! context.empty () && context.top () == ANON_FCN_BODY;
+      }
+
+      bool is_bracket_or_brace (void)
+      {
+        return (! context.empty ()
+                && (context.top () == BRACKET || context.top () == BRACE));
+      }
 
-    void reset (void)
+      bool none (void) { return context.empty (); }
+
+      void remove (void)
+      {
+        if (! context.empty ())
+          context.pop ();
+      }
+
+      void clear (void)
+      {
+        while (! context.empty ())
+          context.pop ();
+      }
+
+    private:
+
+      std::stack<int> context;
+    };
+
+    class token_cache
     {
-      while (! context.empty ())
-        context.pop ();
-    }
+    public:
 
-    void bracket (void) { context.push (BRACKET); }
+      // Store an "unlimited" number of tokens.
+      token_cache (size_t sz_arg = std::numeric_limits<size_t>::max ())
+        : buffer (), sz (sz_arg)
+      { }
 
-    bool is_bracket (void)
-    {
-      return ! context.empty () && context.top () == BRACKET;
-    }
+      void push (token *tok)
+      {
+        if (buffer.size () == sz)
+          pop ();
+
+        buffer.push_front (tok);
+      }
+
+      void pop (void)
+      {
+        if (! empty ())
+          {
+            delete buffer.back ();
+            buffer.pop_back ();
+          }
+      }
+
+      // Direct access.
+      token *at (size_t n)
+      {
+        return empty () ? 0 : buffer.at (n);
+      }
 
-    void brace (void) { context.push (BRACE); }
+      const token *at (size_t n) const
+      {
+        return empty () ? 0 : buffer.at (n);
+      }
+
+      // Most recently pushed.
+      token *front (void)
+      {
+        return empty () ? 0 : buffer.front ();
+      }
 
-    bool is_brace (void)
-    {
-      return ! context.empty () && context.top () == BRACE;
-    }
+      const token *front (void) const
+      {
+        return empty () ? 0 : buffer.front ();
+      }
+
+      token *back (void)
+      {
+        return empty () ? 0 : buffer.back ();
+      }
+
+      const token *back (void) const
+      {
+        return empty () ? 0 : buffer.back ();
+      }
 
-    void paren (void) { context.push (PAREN); }
+      // Number of elements currently in the buffer, max of sz.
+      size_t size (void) const { return buffer.size (); }
+
+      bool empty (void) const { return buffer.empty (); }
+
+      void clear (void)
+      {
+        while (! empty ())
+          pop ();
+      }
+
+    private:
+
+      std::deque<token *> buffer;
+
+      size_t sz;
+
+      // No copying!
+
+      token_cache (const token_cache&);
+
+      token_cache& operator = (const token_cache&);
+    };
 
-    bool is_paren (void)
+    lexical_feedback (void)
+      : end_of_input (false), at_beginning_of_statement (true),
+        looking_at_anon_fcn_args (false), looking_at_return_list (false),
+        looking_at_parameter_list (false), looking_at_decl_list (false),
+        looking_at_initializer_expression (false),
+        looking_at_matrix_or_assign_lhs (false),
+        looking_for_object_index (false),
+        looking_at_indirect_ref (false), parsing_class_method (false),
+        parsing_classdef (false), maybe_classdef_get_set_method (false),
+        parsing_classdef_get_method (false),
+        parsing_classdef_set_method (false),
+        quote_is_transpose (false), force_script (false),
+        reading_fcn_file (false), reading_script_file (false),
+        reading_classdef_file (false),
+        input_line_number (1), current_input_column (1),
+        bracketflag (0), braceflag (0),
+        looping (0), defining_func (0), looking_at_function_handle (0),
+        block_comment_nesting_level (0), command_arg_paren_count (0),
+        token_count (0), current_input_line (), comment_text (),
+        help_text (), string_text (), string_line (0), string_column (0),
+        fcn_file_name (), fcn_file_full_name (), looking_at_object_index (),
+        parsed_function_name (), pending_local_variables (),
+        symtab_context (), nesting_level (), tokens ()
     {
-      return ! context.empty () && context.top () == PAREN;
-    }
-
-    void anon_fcn_body (void) { context.push (ANON_FCN_BODY); }
-
-    bool is_anon_fcn_body (void)
-    {
-      return ! context.empty () && context.top () == ANON_FCN_BODY;
+      init ();
     }
 
-    bool is_bracket_or_brace (void)
-    {
-      return (! context.empty ()
-              && (context.top () == BRACKET || context.top () == BRACE));
-    }
+    ~lexical_feedback (void);
+
+    void init (void);
+
+    void reset (void);
+
+    int previous_token_value (void) const;
+
+    bool previous_token_value_is (int tok_val) const;
+
+    void mark_previous_token_trailing_space (void);
+
+    bool space_follows_previous_token (void) const;
+
+    bool previous_token_is_binop (void) const;
+
+    bool previous_token_is_keyword (void) const;
+
+    bool previous_token_may_be_command (void) const;
+
+    void maybe_mark_previous_token_as_variable (void);
+
+    void mark_as_variable (const std::string& nm);
+    void mark_as_variables (const std::list<std::string>& lst);
+
+    // true means that we have encountered eof on the input stream.
+    bool end_of_input;
+
+    // true means we are at the beginning of a statement, where a
+    // command name is possible.
+    bool at_beginning_of_statement;
+
+    // true means we are parsing an anonymous function argument list.
+    bool looking_at_anon_fcn_args;
+
+    // true means we're parsing the return list for a function.
+    bool looking_at_return_list;
+
+    // true means we're parsing the parameter list for a function.
+    bool looking_at_parameter_list;
 
-    bool none (void) { return context.empty (); }
+    // true means we're parsing a declaration list (global or
+    // persistent).
+    bool looking_at_decl_list;
+
+    // true means we are looking at the initializer expression for a
+    // parameter list element.
+    bool looking_at_initializer_expression;
+
+    // true means we're parsing a matrix or the left hand side of
+    // multi-value assignment statement.
+    bool looking_at_matrix_or_assign_lhs;
+
+    // object index not possible until we've seen something.
+    bool looking_for_object_index;
+
+    // true means we're looking at an indirect reference to a
+    // structure element.
+    bool looking_at_indirect_ref;
+
+    // true means we are parsing a class method in function or classdef file.
+    bool parsing_class_method;
+
+    // true means we are parsing a classdef file
+    bool parsing_classdef;
+
+    // true means we are parsing a class method declaration line in a
+    // classdef file and can accept a property get or set method name.
+    // for example, "get.propertyname" is recognized as a function name.
+    bool maybe_classdef_get_set_method;
+
+    // TRUE means we are parsing a classdef get.method.
+    bool parsing_classdef_get_method;
+
+    // TRUE means we are parsing a classdef set.method.
+    bool parsing_classdef_set_method;
+
+    // return transpose or start a string?
+    bool quote_is_transpose;
+
+    // TRUE means treat the current file as a script even if the first
+    // token is "function" or "classdef".
+    bool force_script;
 
-    void remove (void)
-    {
-      if (! context.empty ())
-        context.pop ();
-    }
+    // TRUE means we're parsing a function file.
+    bool reading_fcn_file;
+
+    // TRUE means we're parsing a script file.
+    bool reading_script_file;
+
+    // TRUE means we're parsing a classdef file.
+    bool reading_classdef_file;
+
+    // the current input line number.
+    int input_line_number;
+
+    // the column of the current token.
+    int current_input_column;
+
+    // square bracket level count.
+    int bracketflag;
+
+    // curly brace level count.
+    int braceflag;
+
+    // true means we're in the middle of defining a loop.
+    int looping;
+
+    // nonzero means we're in the middle of defining a function.
+    int defining_func;
+
+    // nonzero means we are parsing a function handle.
+    int looking_at_function_handle;
+
+    // nestng level for blcok comments.
+    int block_comment_nesting_level;
+
+    // Parenthesis count for command argument parsing.
+    int command_arg_paren_count;
+
+    // Count of tokens recognized by this lexer since initialized or
+    // since the last reset.
+    size_t token_count;
 
-    void clear (void)
-    {
-      while (! context.empty ())
-        context.pop ();
-    }
+    // The current line of input.
+    std::string current_input_line;
+
+    // The current comment text.
+    std::string comment_text;
+
+    // The current help text.
+    std::string help_text;
+
+    // The current character string text.
+    std::string string_text;
+
+    // The position of the beginning of the current character string.
+    int string_line;
+    int string_column;
+
+    // Simple name of function file we are reading.
+    std::string fcn_file_name;
+
+    // Full name of file we are reading.
+    std::string fcn_file_full_name;
+
+    // if the front of the list is true, the closest paren, brace, or
+    // bracket nesting is an index for an object.
+    std::list<bool> looking_at_object_index;
+
+    // if the top of the stack is true, then we've already seen the name
+    // of the current function.  should only matter if
+    // current_function_level > 0
+    std::stack<bool> parsed_function_name;
+
+    // set of identifiers that might be local variable names.
+    std::set<std::string> pending_local_variables;
+
+    // Track current symbol table scope and context.
+    symbol_table_context symtab_context;
+
+    // is the closest nesting level a square bracket, squiggly brace,
+    // a paren, or an anonymous function body?
+    bbp_nesting_level nesting_level;
+
+    // Tokens generated by the lexer.
+    token_cache tokens;
 
   private:
 
-    std::stack<int> context;
-  };
-
-  class token_cache
-  {
-  public:
-
-    // Store an "unlimited" number of tokens.
-    token_cache (size_t sz_arg = std::numeric_limits<size_t>::max ())
-      : buffer (), sz (sz_arg)
-    { }
-
-    void push (token *tok)
-    {
-      if (buffer.size () == sz)
-        pop ();
-
-      buffer.push_front (tok);
-    }
-
-    void pop (void)
-    {
-      if (! empty ())
-        {
-          delete buffer.back ();
-          buffer.pop_back ();
-        }
-    }
-
-    // Direct access.
-    token *at (size_t n)
-    {
-      return empty () ? 0 : buffer.at (n);
-    }
-
-    const token *at (size_t n) const
-    {
-      return empty () ? 0 : buffer.at (n);
-    }
-
-    // Most recently pushed.
-    token *front (void)
-    {
-      return empty () ? 0 : buffer.front ();
-    }
-
-    const token *front (void) const
-    {
-      return empty () ? 0 : buffer.front ();
-    }
-
-    token *back (void)
-    {
-      return empty () ? 0 : buffer.back ();
-    }
-
-    const token *back (void) const
-    {
-      return empty () ? 0 : buffer.back ();
-    }
-
-    // Number of elements currently in the buffer, max of sz.
-    size_t size (void) const { return buffer.size (); }
-
-    bool empty (void) const { return buffer.empty (); }
-
-    void clear (void)
-    {
-      while (! empty ())
-        pop ();
-    }
-
-  private:
-
-    std::deque<token *> buffer;
-
-    size_t sz;
-
     // No copying!
 
-    token_cache (const token_cache&);
+    lexical_feedback (const lexical_feedback&);
 
-    token_cache& operator = (const token_cache&);
+    lexical_feedback& operator = (const lexical_feedback&);
   };
 
-  lexical_feedback (void)
-    : end_of_input (false), at_beginning_of_statement (true),
-      looking_at_anon_fcn_args (false), looking_at_return_list (false),
-      looking_at_parameter_list (false), looking_at_decl_list (false),
-      looking_at_initializer_expression (false),
-      looking_at_matrix_or_assign_lhs (false),
-      looking_for_object_index (false),
-      looking_at_indirect_ref (false), parsing_class_method (false),
-      parsing_classdef (false), maybe_classdef_get_set_method (false),
-      parsing_classdef_get_method (false),
-      parsing_classdef_set_method (false),
-      quote_is_transpose (false), force_script (false),
-      reading_fcn_file (false), reading_script_file (false),
-      reading_classdef_file (false),
-      input_line_number (1), current_input_column (1),
-      bracketflag (0), braceflag (0),
-      looping (0), defining_func (0), looking_at_function_handle (0),
-      block_comment_nesting_level (0), command_arg_paren_count (0),
-      token_count (0), current_input_line (), comment_text (),
-      help_text (), string_text (), string_line (0), string_column (0),
-      fcn_file_name (), fcn_file_full_name (), looking_at_object_index (),
-      parsed_function_name (), pending_local_variables (),
-      symtab_context (), nesting_level (), tokens ()
-  {
-    init ();
-  }
-
-  ~lexical_feedback (void);
-
-  void init (void);
-
-  void reset (void);
-
-  int previous_token_value (void) const;
-
-  bool previous_token_value_is (int tok_val) const;
-
-  void mark_previous_token_trailing_space (void);
-
-  bool space_follows_previous_token (void) const;
-
-  bool previous_token_is_binop (void) const;
-
-  bool previous_token_is_keyword (void) const;
-
-  bool previous_token_may_be_command (void) const;
-
-  void maybe_mark_previous_token_as_variable (void);
-
-  void mark_as_variable (const std::string& nm);
-  void mark_as_variables (const std::list<std::string>& lst);
-
-  // true means that we have encountered eof on the input stream.
-  bool end_of_input;
-
-  // true means we are at the beginning of a statement, where a
-  // command name is possible.
-  bool at_beginning_of_statement;
-
-  // true means we are parsing an anonymous function argument list.
-  bool looking_at_anon_fcn_args;
-
-  // true means we're parsing the return list for a function.
-  bool looking_at_return_list;
-
-  // true means we're parsing the parameter list for a function.
-  bool looking_at_parameter_list;
-
-  // true means we're parsing a declaration list (global or
-  // persistent).
-  bool looking_at_decl_list;
-
-  // true means we are looking at the initializer expression for a
-  // parameter list element.
-  bool looking_at_initializer_expression;
-
-  // true means we're parsing a matrix or the left hand side of
-  // multi-value assignment statement.
-  bool looking_at_matrix_or_assign_lhs;
-
-  // object index not possible until we've seen something.
-  bool looking_for_object_index;
-
-  // true means we're looking at an indirect reference to a
-  // structure element.
-  bool looking_at_indirect_ref;
-
-  // true means we are parsing a class method in function or classdef file.
-  bool parsing_class_method;
-
-  // true means we are parsing a classdef file
-  bool parsing_classdef;
-
-  // true means we are parsing a class method declaration line in a
-  // classdef file and can accept a property get or set method name.
-  // for example, "get.propertyname" is recognized as a function name.
-  bool maybe_classdef_get_set_method;
-
-  // TRUE means we are parsing a classdef get.method.
-  bool parsing_classdef_get_method;
-
-  // TRUE means we are parsing a classdef set.method.
-  bool parsing_classdef_set_method;
-
-  // return transpose or start a string?
-  bool quote_is_transpose;
+  // base_lexer inherits from lexical_feedback because we will
+  // eventually have several different constructors and it is easier to
+  // intialize if everything is grouped in a parent class rather than
+  // listing all the members in the base_lexer class.
 
-  // TRUE means treat the current file as a script even if the first
-  // token is "function" or "classdef".
-  bool force_script;
-
-  // TRUE means we're parsing a function file.
-  bool reading_fcn_file;
-
-  // TRUE means we're parsing a script file.
-  bool reading_script_file;
-
-  // TRUE means we're parsing a classdef file.
-  bool reading_classdef_file;
-
-  // the current input line number.
-  int input_line_number;
-
-  // the column of the current token.
-  int current_input_column;
-
-  // square bracket level count.
-  int bracketflag;
-
-  // curly brace level count.
-  int braceflag;
-
-  // true means we're in the middle of defining a loop.
-  int looping;
-
-  // nonzero means we're in the middle of defining a function.
-  int defining_func;
-
-  // nonzero means we are parsing a function handle.
-  int looking_at_function_handle;
-
-  // nestng level for blcok comments.
-  int block_comment_nesting_level;
-
-  // Parenthesis count for command argument parsing.
-  int command_arg_paren_count;
-
-  // Count of tokens recognized by this lexer since initialized or
-  // since the last reset.
-  size_t token_count;
-
-  // The current line of input.
-  std::string current_input_line;
-
-  // The current comment text.
-  std::string comment_text;
-
-  // The current help text.
-  std::string help_text;
-
-  // The current character string text.
-  std::string string_text;
-
-  // The position of the beginning of the current character string.
-  int string_line;
-  int string_column;
-
-  // Simple name of function file we are reading.
-  std::string fcn_file_name;
-
-  // Full name of file we are reading.
-  std::string fcn_file_full_name;
-
-  // if the front of the list is true, the closest paren, brace, or
-  // bracket nesting is an index for an object.
-  std::list<bool> looking_at_object_index;
-
-  // if the top of the stack is true, then we've already seen the name
-  // of the current function.  should only matter if
-  // current_function_level > 0
-  std::stack<bool> parsed_function_name;
-
-  // set of identifiers that might be local variable names.
-  std::set<std::string> pending_local_variables;
-
-  // Track current symbol table scope and context.
-  symbol_table_context symtab_context;
-
-  // is the closest nesting level a square bracket, squiggly brace,
-  // a paren, or an anonymous function body?
-  bbp_nesting_level nesting_level;
-
-  // Tokens generated by the lexer.
-  token_cache tokens;
-
-private:
-
-  // No copying!
-
-  lexical_feedback (const lexical_feedback&);
-
-  lexical_feedback& operator = (const lexical_feedback&);
-};
-
-// octave_base_lexer inherits from lexical_feedback because we will
-// eventually have several different constructors and it is easier to
-// intialize if everything is grouped in a parent class rather than
-// listing all the members in the octave_base_lexer class.
-
-class
-octave_base_lexer : public lexical_feedback
-{
-public:
-
-  // Handle buffering of input for lexer.
-
-  class input_buffer
+  class
+  base_lexer : public lexical_feedback
   {
   public:
 
-    input_buffer (void)
-      : buffer (), pos (0), chars_left (0), eof (false)
-    { }
+    // Handle buffering of input for lexer.
+
+    class input_buffer
+    {
+    public:
+
+      input_buffer (void)
+        : buffer (), pos (0), chars_left (0), eof (false)
+      { }
+
+      void fill (const std::string& input, bool eof_arg);
+
+      // Copy at most max_size characters to buf.
+      int copy_chunk (char *buf, size_t max_size);
+
+      bool empty (void) const { return chars_left == 0; }
+
+      bool at_eof (void) const { return eof; }
+
+    private:
+
+      std::string buffer;
+      const char *pos;
+      size_t chars_left;
+      bool eof;
+    };
+
+    // Collect comment text.
+
+    class
+    comment_buffer
+    {
+    public:
+
+      comment_buffer (void) : comment_list (0) { }
+
+      ~comment_buffer (void) { delete comment_list; }
+
+      void append (const std::string& s, octave_comment_elt::comment_type t)
+      {
+        if (! comment_list)
+          comment_list = new octave_comment_list ();
+
+        comment_list->append (s, t);
+      }
+
+      // Caller is expected to delete the returned value.
+
+      octave_comment_list *get_comment (void)
+      {
+        octave_comment_list *retval = comment_list;
+
+        comment_list = 0;
+
+        return retval;
+      }
 
-    void fill (const std::string& input, bool eof_arg);
+      void reset (void)
+      {
+        delete comment_list;
+
+        comment_list = 0;
+      }
+
+    private:
+
+      octave_comment_list *comment_list;
+    };
+
+    base_lexer (interpreter *interp_context = 0)
+      : lexical_feedback (), scanner (0), input_buf (), comment_buf (),
+        m_interp_context (interp_context)
+    {
+      init ();
+    }
+
+    virtual ~base_lexer (void);
+
+    void init (void);
+
+    virtual bool is_push_lexer (void) const { return false; }
+
+    virtual void reset (void);
+
+    void prep_for_file (void);
 
-    // Copy at most max_size characters to buf.
-    int copy_chunk (char *buf, size_t max_size);
+    void begin_string (int state);
+
+    virtual int fill_flex_buffer (char *buf, unsigned int max_size) = 0;
+
+    bool at_end_of_buffer (void) const { return input_buf.empty (); }
+
+    bool at_end_of_file (void) const { return input_buf.at_eof (); }
+
+    int handle_end_of_input (void);
+
+    char *flex_yytext (void);
+
+    int flex_yyleng (void);
+
+    int text_yyinput (void);
+
+    void xunput (char c, char *buf);
+
+    void xunput (char c);
+
+    bool looking_at_space (void);
+
+    bool inside_any_object_index (void);
+
+    bool is_variable (const std::string& name, symbol_table::scope_id scope);
+
+    int is_keyword_token (const std::string& s);
+
+    bool fq_identifier_contains_keyword (const std::string& s);
+
+    bool whitespace_is_significant (void);
 
-    bool empty (void) const { return chars_left == 0; }
+    void handle_number (void);
+
+    void handle_continuation (void);
+
+    void finish_comment (octave_comment_elt::comment_type typ);
+
+    octave_comment_list *get_comment (void) { return comment_buf.get_comment (); }
+
+    int handle_close_bracket (int bracket_type);
+
+    bool looks_like_command_arg (void);
+
+    int handle_superclass_identifier (void);
+
+    int handle_meta_identifier (void);
+
+    int handle_fq_identifier (void);
+
+    int handle_identifier (void);
+
+    void maybe_warn_separator_insert (char sep);
+
+    void warn_single_quote_string (void);
+
+    void warn_language_extension (const std::string& msg);
+
+    void maybe_warn_language_extension_comment (char c);
 
-    bool at_eof (void) const { return eof; }
+    void warn_language_extension_continuation (void);
+
+    void warn_language_extension_operator (const std::string& op);
+
+    void push_token (token *);
+
+    token *current_token (void);
+
+    void display_token (int tok);
+
+    void fatal_error (const char *msg);
+
+    void lexer_debug (const char *pattern);
+
+    // Internal state of the flex-generated lexer.
+    void *scanner;
+
+    // Object that reads and buffers input.
+    input_buffer input_buf;
+
+    // Object that collects comment text.
+    comment_buffer comment_buf;
+
+    // Interpreter that contains us, if any.
+    interpreter *m_interp_context;
+
+    virtual void increment_promptflag (void) = 0;
+
+    virtual void decrement_promptflag (void) = 0;
 
-  private:
+    virtual int promptflag (void) const = 0;
+
+    virtual int promptflag (int) = 0;
+
+    virtual std::string input_source (void) const { return "unknown"; }
+
+    virtual bool input_from_terminal (void) const { return false; }
+
+    virtual bool input_from_file (void) const { return false; }
+
+    virtual bool input_from_eval_string (void) const { return false; }
+
+    void push_start_state (int state);
+
+    void pop_start_state (void);
+
+    void clear_start_state (void);
+
+    int start_state (void) const { return start_state_stack.top (); }
+
+    void display_start_state (void) const;
+
+    int handle_op (const char *pattern, int tok, bool bos = false);
+
+    int handle_language_extension_op (const char *pattern, int tok,
+                                      bool bos = false);
+
+    bool maybe_unput_comma_before_unary_op (int tok);
 
-    std::string buffer;
-    const char *pos;
-    size_t chars_left;
-    bool eof;
+    int handle_unary_op (int tok, bool bos = false);
+
+    int handle_language_extension_unary_op (int tok, bool bos = false);
+
+    int handle_assign_op (const char *pattern, int tok);
+
+    int handle_language_extension_assign_op (const char *pattern, int tok);
+
+    int handle_op_internal (int tok, bool bos, bool compat);
+
+    int handle_token (const std::string& name, int tok);
+
+    int handle_token (int tok, token *tok_val = 0);
+
+    int count_token (int tok);
+
+    int count_token_internal (int tok);
+
+    int show_token (int tok);
+
+    void enable_fq_identifier (void);
+
+  protected:
+
+    std::stack<int> start_state_stack;
+
+    // No copying!
+
+    base_lexer (const base_lexer&);
+
+    base_lexer& operator = (const base_lexer&);
   };
 
-  // Collect comment text.
-
   class
-  comment_buffer
+  lexer : public base_lexer
   {
   public:
 
-    comment_buffer (void) : comment_list (0) { }
-
-    ~comment_buffer (void) { delete comment_list; }
-
-    void append (const std::string& s, octave_comment_elt::comment_type t)
-    {
-      if (! comment_list)
-        comment_list = new octave_comment_list ();
+    lexer (interpreter *interp_context = 0)
+      : base_lexer (interp_context), input_reader (this)
+    { }
 
-      comment_list->append (s, t);
-    }
-
-    // Caller is expected to delete the returned value.
+    lexer (FILE *file, interpreter *interp_context = 0)
+      : base_lexer (interp_context), input_reader (file, this)
+    { }
 
-    octave_comment_list *get_comment (void)
-    {
-      octave_comment_list *retval = comment_list;
-
-      comment_list = 0;
-
-      return retval;
-    }
+    lexer (const std::string& eval_string,
+                  interpreter *interp_context = 0)
+      : base_lexer (interp_context), input_reader (eval_string, this)
+    { }
 
     void reset (void)
     {
-      delete comment_list;
+      input_reader.reset ();
+
+      base_lexer::reset ();
+    }
+
+    void increment_promptflag (void) { input_reader.increment_promptflag (); }
 
-      comment_list = 0;
+    void decrement_promptflag (void) { input_reader.decrement_promptflag (); }
+
+    int promptflag (void) const { return input_reader.promptflag (); }
+
+    int promptflag (int n) { return input_reader.promptflag (n); }
+
+    std::string input_source (void) const
+    {
+      return input_reader.input_source ();
     }
 
-  private:
+    bool input_from_terminal (void) const
+    {
+      return input_reader.input_from_terminal ();
+    }
+
+    bool input_from_file (void) const
+    {
+      return input_reader.input_from_file ();
+    }
 
-    octave_comment_list *comment_list;
+    bool input_from_eval_string (void) const
+    {
+      return input_reader.input_from_eval_string ();
+    }
+
+    int fill_flex_buffer (char *buf, unsigned int max_size);
+
+    octave_input_reader input_reader;
+
+  protected:
+
+    // No copying!
+
+    lexer (const lexer&);
+
+    lexer& operator = (const lexer&);
   };
 
-  octave_base_lexer (void)
-    : lexical_feedback (), scanner (0), input_buf (), comment_buf ()
+  class
+  push_lexer : public base_lexer
   {
-    init ();
-  }
-
-  virtual ~octave_base_lexer (void);
-
-  void init (void);
-
-  virtual bool is_push_lexer (void) const { return false; }
-
-  virtual void reset (void);
-
-  void prep_for_file (void);
-
-  void begin_string (int state);
-
-  virtual int fill_flex_buffer (char *buf, unsigned int max_size) = 0;
-
-  bool at_end_of_buffer (void) const { return input_buf.empty (); }
-
-  bool at_end_of_file (void) const { return input_buf.at_eof (); }
-
-  int handle_end_of_input (void);
-
-  char *flex_yytext (void);
-
-  int flex_yyleng (void);
-
-  int text_yyinput (void);
-
-  void xunput (char c, char *buf);
+  public:
 
-  void xunput (char c);
-
-  bool looking_at_space (void);
-
-  bool inside_any_object_index (void);
-
-  bool is_variable (const std::string& name, symbol_table::scope_id scope);
-
-  int is_keyword_token (const std::string& s);
-
-  bool fq_identifier_contains_keyword (const std::string& s);
-
-  bool whitespace_is_significant (void);
-
-  void handle_number (void);
-
-  void handle_continuation (void);
+    push_lexer (interpreter *interp_context = 0)
+      : base_lexer (interp_context), pflag (1)
+    {
+      append_input ("", false);
+    }
 
-  void finish_comment (octave_comment_elt::comment_type typ);
-
-  octave_comment_list *get_comment (void) { return comment_buf.get_comment (); }
-
-  int handle_close_bracket (int bracket_type);
-
-  bool looks_like_command_arg (void);
-
-  int handle_superclass_identifier (void);
-
-  int handle_meta_identifier (void);
-
-  int handle_fq_identifier (void);
-
-  int handle_identifier (void);
-
-  void maybe_warn_separator_insert (char sep);
+    push_lexer (const std::string& input,
+                       interpreter *interp_context = 0)
+      : base_lexer (interp_context), pflag (1)
+    {
+      append_input (input, false);
+    }
 
-  void warn_single_quote_string (void);
-
-  void warn_language_extension (const std::string& msg);
-
-  void maybe_warn_language_extension_comment (char c);
-
-  void warn_language_extension_continuation (void);
-
-  void warn_language_extension_operator (const std::string& op);
-
-  void push_token (token *);
-
-  token *current_token (void);
-
-  void display_token (int tok);
-
-  void fatal_error (const char *msg);
-
-  void lexer_debug (const char *pattern);
-
-  // Internal state of the flex-generated lexer.
-  void *scanner;
-
-  // Object that reads and buffers input.
-  input_buffer input_buf;
-
-  // Object that collects comment text.
-  comment_buffer comment_buf;
-
-  virtual void increment_promptflag (void) = 0;
-
-  virtual void decrement_promptflag (void) = 0;
-
-  virtual int promptflag (void) const = 0;
+    push_lexer (bool eof, interpreter *interp_context = 0)
+      : base_lexer (interp_context), pflag (1)
+    {
+      append_input ("", eof);
+    }
 
-  virtual int promptflag (int) = 0;
-
-  virtual std::string input_source (void) const { return "unknown"; }
-
-  virtual bool input_from_terminal (void) const { return false; }
-
-  virtual bool input_from_file (void) const { return false; }
-
-  virtual bool input_from_eval_string (void) const { return false; }
-
-  void push_start_state (int state);
-
-  void pop_start_state (void);
-
-  void clear_start_state (void);
-
-  int start_state (void) const { return start_state_stack.top (); }
+    push_lexer (const std::string& input, bool eof,
+                       interpreter *interp_context = 0)
+      : base_lexer (interp_context), pflag (1)
+    {
+      append_input (input, eof);
+    }
 
-  void display_start_state (void) const;
-
-  int handle_op (const char *pattern, int tok, bool bos = false);
-
-  int handle_language_extension_op (const char *pattern, int tok,
-                                    bool bos = false);
-
-  bool maybe_unput_comma_before_unary_op (int tok);
+    bool is_push_lexer (void) const { return true; }
 
-  int handle_unary_op (int tok, bool bos = false);
-
-  int handle_language_extension_unary_op (int tok, bool bos = false);
-
-  int handle_assign_op (const char *pattern, int tok);
-
-  int handle_language_extension_assign_op (const char *pattern, int tok);
-
-  int handle_op_internal (int tok, bool bos, bool compat);
+    void reset (void)
+    {
+      promptflag (1);
 
-  int handle_token (const std::string& name, int tok);
-
-  int handle_token (int tok, token *tok_val = 0);
-
-  int count_token (int tok);
-
-  int count_token_internal (int tok);
-
-  int show_token (int tok);
-
-  void enable_fq_identifier (void);
-
-protected:
-
-  std::stack<int> start_state_stack;
-
-  // No copying!
-
-  octave_base_lexer (const octave_base_lexer&);
-
-  octave_base_lexer& operator = (const octave_base_lexer&);
-};
-
-class
-octave_lexer : public octave_base_lexer
-{
-public:
-
-  octave_lexer (void)
-    : octave_base_lexer (), input_reader (this)
-  { }
+      base_lexer::reset ();
+    }
 
-  octave_lexer (FILE *file)
-    : octave_base_lexer (), input_reader (file, this)
-  { }
-
-  octave_lexer (const std::string& eval_string)
-    : octave_base_lexer (), input_reader (eval_string, this)
-  { }
-
-  void reset (void)
-  {
-    input_reader.reset ();
-
-    octave_base_lexer::reset ();
-  }
-
-  void increment_promptflag (void) { input_reader.increment_promptflag (); }
-
-  void decrement_promptflag (void) { input_reader.decrement_promptflag (); }
+    void append_input (const std::string& input, bool eof)
+    {
+      input_buf.fill (input, eof);
+    }
 
-  int promptflag (void) const { return input_reader.promptflag (); }
-
-  int promptflag (int n) { return input_reader.promptflag (n); }
-
-  std::string input_source (void) const
-  {
-    return input_reader.input_source ();
-  }
+    void increment_promptflag (void) { pflag++; }
 
-  bool input_from_terminal (void) const
-  {
-    return input_reader.input_from_terminal ();
-  }
+    void decrement_promptflag (void) { pflag--; }
 
-  bool input_from_file (void) const
-  {
-    return input_reader.input_from_file ();
-  }
+    int promptflag (void) const { return pflag; }
 
-  bool input_from_eval_string (void) const
-  {
-    return input_reader.input_from_eval_string ();
-  }
-
-  int fill_flex_buffer (char *buf, unsigned int max_size);
-
-  octave_input_reader input_reader;
-
-protected:
-
-  // No copying!
-
-  octave_lexer (const octave_lexer&);
-
-  octave_lexer& operator = (const octave_lexer&);
-};
+    int promptflag (int n)
+    {
+      int retval = pflag;
+      pflag = n;
+      return retval;
+    }
 
-class
-octave_push_lexer : public octave_base_lexer
-{
-public:
+    std::string input_source (void) const { return "push buffer"; }
 
-  octave_push_lexer (const std::string& input = "",
-                     bool eof = false)
-    : octave_base_lexer (), pflag (1)
-  {
-    append_input (input, eof);
-  }
-
-  bool is_push_lexer (void) const { return true; }
-
-  void reset (void)
-  {
-    promptflag (1);
+    int fill_flex_buffer (char *buf, unsigned int max_size);
 
-    octave_base_lexer::reset ();
-  }
+  protected:
 
-  void append_input (const std::string& input, bool eof)
-  {
-    input_buf.fill (input, eof);
-  }
+    int pflag;
 
-  void increment_promptflag (void) { pflag++; }
-
-  void decrement_promptflag (void) { pflag--; }
-
-  int promptflag (void) const { return pflag; }
+    // No copying!
 
-  int promptflag (int n)
-  {
-    int retval = pflag;
-    pflag = n;
-    return retval;
-  }
-
-  std::string input_source (void) const { return "push buffer"; }
-
-  int fill_flex_buffer (char *buf, unsigned int max_size);
+    push_lexer (const push_lexer&);
 
-protected:
-
-  int pflag;
-
-  // No copying!
-
-  octave_push_lexer (const octave_push_lexer&);
-
-  octave_push_lexer& operator = (const octave_push_lexer&);
-};
+    push_lexer& operator = (const push_lexer&);
+  };
+}
 
 #endif
--- a/libinterp/parse-tree/lex.ll	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/parse-tree/lex.ll	Tue Jul 12 14:28:07 2016 -0400
@@ -139,7 +139,7 @@
 #error lex.l requires flex version 2.5.4 or later
 #endif
 
-#define YY_EXTRA_TYPE octave_base_lexer *
+#define YY_EXTRA_TYPE octave::base_lexer *
 #define curr_lexer yyextra
 
 // Arrange to get input via readline.
@@ -1959,21 +1959,24 @@
       }
 }
 
-bool
-is_keyword (const std::string& s)
+namespace octave
 {
-  // Parsing function names like "set.property_name" inside
-  // classdef-style class definitions is simplified by handling the
-  // "set" and "get" portions of the names using the same mechanism as
-  // is used for keywords.  However, they are not really keywords in
-  // the language, so omit them from the list of possible keywords.
-  // Likewise for "enumeration", "events", "methods", and
-  // "properties".
-
-  return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != 0
-          && ! (s == "set" || s == "get"
-                || s == "enumeration" || s == "events"
-                || s == "methods" || s == "properties"));
+  bool
+  is_keyword (const std::string& s)
+  {
+    // Parsing function names like "set.property_name" inside
+    // classdef-style class definitions is simplified by handling the
+    // "set" and "get" portions of the names using the same mechanism
+    // as is used for keywords.  However, they are not really keywords
+    // in the language, so omit them from the list of possible
+    // keywords.  Likewise for "enumeration", "events", "methods", and
+    // "properties".
+
+    return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != 0
+            && ! (s == "set" || s == "get"
+                  || s == "enumeration" || s == "events"
+                  || s == "methods" || s == "properties"));
+  }
 }
 
 DEFUN (iskeyword, args, ,
@@ -2017,7 +2020,7 @@
   else
     {
       std::string name = args(0).xstring_value ("iskeyword: NAME must be a string");
-      retval = is_keyword (name);
+      retval = octave::is_keyword (name);
     }
 
   return retval;
@@ -2074,152 +2077,155 @@
   return retval;
 }
 
-lexical_feedback::~lexical_feedback (void)
-{
-  tokens.clear ();
-}
-
-void
-lexical_feedback::init (void)
-{
-  // The closest paren, brace, or bracket nesting is not an object
-  // index.
-  looking_at_object_index.push_front (false);
-}
-
-void
-lexical_feedback::reset (void)
-{
-  end_of_input = false;
-  at_beginning_of_statement = true;
-  looking_at_anon_fcn_args = false;
-  looking_at_return_list = false;
-  looking_at_parameter_list = false;
-  looking_at_decl_list = false;
-  looking_at_initializer_expression = false;
-  looking_at_matrix_or_assign_lhs = false;
-  looking_for_object_index = false;
-  looking_at_indirect_ref = false;
-  parsing_class_method = false;
-  parsing_classdef = false;
-  maybe_classdef_get_set_method = false;
-  parsing_classdef_get_method = false;
-  parsing_classdef_set_method = false;
-  quote_is_transpose = false;
-  force_script = false;
-  reading_fcn_file = false;
-  reading_script_file = false;
-  reading_classdef_file = false;
-  input_line_number = 1;
-  current_input_column = 1;
-  bracketflag = 0;
-  braceflag = 0;
-  looping = 0;
-  defining_func = 0;
-  looking_at_function_handle = 0;
-  block_comment_nesting_level = 0;
-  command_arg_paren_count = 0;
-  token_count = 0;
-  current_input_line = "";
-  comment_text = "";
-  help_text = "";
-  string_text = "";
-  string_line = 0;
-  string_column = 0;
-  fcn_file_name = "";
-  fcn_file_full_name = "";
-  looking_at_object_index.clear ();
-  looking_at_object_index.push_front (false);
-
-  while (! parsed_function_name.empty ())
-    parsed_function_name.pop ();
-
-  pending_local_variables.clear ();
-  symtab_context.clear ();
-  nesting_level.reset ();
-  tokens.clear ();
-}
-
-int
-lexical_feedback::previous_token_value (void) const
+namespace octave
 {
-  const token *tok = tokens.front ();
-  return tok ? tok->token_value () : 0;
-}
-
-bool
-lexical_feedback::previous_token_value_is (int tok_val) const
-{
-  const token *tok = tokens.front ();
-  return tok ? tok->token_value_is (tok_val) : false;
-}
-
-void
-lexical_feedback::mark_previous_token_trailing_space (void)
-{
-  token *tok = tokens.front ();
-  if (tok && ! previous_token_value_is ('\n'))
-    tok->mark_trailing_space ();
-}
-
-bool
-lexical_feedback::space_follows_previous_token (void) const
-{
-  const token *tok = tokens.front ();
-  return tok ? tok->space_follows_token () : false;
-}
-
-bool
-lexical_feedback::previous_token_is_binop (void) const
-{
-  int tok = previous_token_value ();
-
-  return (tok == '+' || tok == '-' || tok == '@'
-          || tok == ',' || tok == ';' || tok == '*' || tok == '/'
-          || tok == ':' || tok == '=' || tok == ADD_EQ
-          || tok == AND_EQ || tok == DIV_EQ || tok == EDIV
-          || tok == EDIV_EQ || tok == ELEFTDIV || tok == ELEFTDIV_EQ
-          || tok == EMINUS || tok == EMUL || tok == EMUL_EQ
-          || tok == EPOW || tok == EPOW_EQ || tok == EXPR_AND
-          || tok == EXPR_AND_AND || tok == EXPR_EQ || tok == EXPR_GE
-          || tok == EXPR_GT || tok == EXPR_LE || tok == EXPR_LT
-          || tok == EXPR_NE || tok == EXPR_NOT || tok == EXPR_OR
-          || tok == EXPR_OR_OR || tok == LEFTDIV || tok == LEFTDIV_EQ
-          || tok == MUL_EQ || tok == OR_EQ || tok == POW
-          || tok == POW_EQ || tok == SUB_EQ);
-}
-
-bool
-lexical_feedback::previous_token_is_keyword (void) const
-{
-  const token *tok = tokens.front ();
-  return tok ? tok->is_keyword () : false;
-}
-
-bool
-lexical_feedback::previous_token_may_be_command (void) const
-{
-  const token *tok = tokens.front ();
-  return tok ? tok->may_be_command () : false;
-}
-
-void
-lexical_feedback::maybe_mark_previous_token_as_variable (void)
-{
-  token *tok = tokens.front ();
-
-  if (tok && tok->is_symbol ())
-    pending_local_variables.insert (tok->symbol_name ());
-}
-
-void
-lexical_feedback::mark_as_variables (const std::list<std::string>& lst)
-{
-  for (std::list<std::string>::const_iterator p = lst.begin ();
-       p != lst.end (); p++)
-    {
-      pending_local_variables.insert (*p);
-    }
+  lexical_feedback::~lexical_feedback (void)
+  {
+    tokens.clear ();
+  }
+
+  void
+  lexical_feedback::init (void)
+  {
+    // The closest paren, brace, or bracket nesting is not an object
+    // index.
+    looking_at_object_index.push_front (false);
+  }
+
+  void
+  lexical_feedback::reset (void)
+  {
+    end_of_input = false;
+    at_beginning_of_statement = true;
+    looking_at_anon_fcn_args = false;
+    looking_at_return_list = false;
+    looking_at_parameter_list = false;
+    looking_at_decl_list = false;
+    looking_at_initializer_expression = false;
+    looking_at_matrix_or_assign_lhs = false;
+    looking_for_object_index = false;
+    looking_at_indirect_ref = false;
+    parsing_class_method = false;
+    parsing_classdef = false;
+    maybe_classdef_get_set_method = false;
+    parsing_classdef_get_method = false;
+    parsing_classdef_set_method = false;
+    quote_is_transpose = false;
+    force_script = false;
+    reading_fcn_file = false;
+    reading_script_file = false;
+    reading_classdef_file = false;
+    input_line_number = 1;
+    current_input_column = 1;
+    bracketflag = 0;
+    braceflag = 0;
+    looping = 0;
+    defining_func = 0;
+    looking_at_function_handle = 0;
+    block_comment_nesting_level = 0;
+    command_arg_paren_count = 0;
+    token_count = 0;
+    current_input_line = "";
+    comment_text = "";
+    help_text = "";
+    string_text = "";
+    string_line = 0;
+    string_column = 0;
+    fcn_file_name = "";
+    fcn_file_full_name = "";
+    looking_at_object_index.clear ();
+    looking_at_object_index.push_front (false);
+
+    while (! parsed_function_name.empty ())
+      parsed_function_name.pop ();
+
+    pending_local_variables.clear ();
+    symtab_context.clear ();
+    nesting_level.reset ();
+    tokens.clear ();
+  }
+
+  int
+  lexical_feedback::previous_token_value (void) const
+  {
+    const token *tok = tokens.front ();
+    return tok ? tok->token_value () : 0;
+  }
+
+  bool
+  lexical_feedback::previous_token_value_is (int tok_val) const
+  {
+    const token *tok = tokens.front ();
+    return tok ? tok->token_value_is (tok_val) : false;
+  }
+
+  void
+  lexical_feedback::mark_previous_token_trailing_space (void)
+  {
+    token *tok = tokens.front ();
+    if (tok && ! previous_token_value_is ('\n'))
+      tok->mark_trailing_space ();
+  }
+
+  bool
+  lexical_feedback::space_follows_previous_token (void) const
+  {
+    const token *tok = tokens.front ();
+    return tok ? tok->space_follows_token () : false;
+  }
+
+  bool
+  lexical_feedback::previous_token_is_binop (void) const
+  {
+    int tok = previous_token_value ();
+
+    return (tok == '+' || tok == '-' || tok == '@'
+            || tok == ',' || tok == ';' || tok == '*' || tok == '/'
+            || tok == ':' || tok == '=' || tok == ADD_EQ
+            || tok == AND_EQ || tok == DIV_EQ || tok == EDIV
+            || tok == EDIV_EQ || tok == ELEFTDIV || tok == ELEFTDIV_EQ
+            || tok == EMINUS || tok == EMUL || tok == EMUL_EQ
+            || tok == EPOW || tok == EPOW_EQ || tok == EXPR_AND
+            || tok == EXPR_AND_AND || tok == EXPR_EQ || tok == EXPR_GE
+            || tok == EXPR_GT || tok == EXPR_LE || tok == EXPR_LT
+            || tok == EXPR_NE || tok == EXPR_NOT || tok == EXPR_OR
+            || tok == EXPR_OR_OR || tok == LEFTDIV || tok == LEFTDIV_EQ
+            || tok == MUL_EQ || tok == OR_EQ || tok == POW
+            || tok == POW_EQ || tok == SUB_EQ);
+  }
+
+  bool
+  lexical_feedback::previous_token_is_keyword (void) const
+  {
+    const token *tok = tokens.front ();
+    return tok ? tok->is_keyword () : false;
+  }
+
+  bool
+  lexical_feedback::previous_token_may_be_command (void) const
+  {
+    const token *tok = tokens.front ();
+    return tok ? tok->may_be_command () : false;
+  }
+
+  void
+  lexical_feedback::maybe_mark_previous_token_as_variable (void)
+  {
+    token *tok = tokens.front ();
+
+    if (tok && tok->is_symbol ())
+      pending_local_variables.insert (tok->symbol_name ());
+  }
+
+  void
+  lexical_feedback::mark_as_variables (const std::list<std::string>& lst)
+  {
+    for (std::list<std::string>::const_iterator p = lst.begin ();
+         p != lst.end (); p++)
+      {
+        pending_local_variables.insert (*p);
+      }
+  }
 }
 
 static bool
@@ -2237,508 +2243,511 @@
   return retval;
 }
 
-void
-octave_base_lexer::input_buffer::fill (const std::string& input, bool eof_arg)
-{
-  buffer = input;
-  chars_left = buffer.length ();
-  pos = buffer.c_str ();
-  eof = eof_arg;
-}
-
-int
-octave_base_lexer::input_buffer::copy_chunk (char *buf, size_t max_size)
-{
-  static const char * const eol = "\n";
-
-  size_t len = max_size > chars_left ? chars_left : max_size;
-  assert (len > 0);
-
-  memcpy (buf, pos, len);
-
-  chars_left -= len;
-  pos += len;
-
-  // Make sure input ends with a new line character.
-  if (chars_left == 0 && buf[len-1] != '\n')
-    {
-      if (len < max_size)
-        {
-          // There is enough room to plug the newline character in
-          // the buffer.
-          buf[len++] = '\n';
-        }
-      else
-        {
-          // There isn't enough room to plug the newline character
-          // in the buffer so arrange to have it returned on the next
-          // call to octave_base_lexer::read.
-          pos = eol;
-          chars_left = 1;
-        }
-    }
-
-  return len;
-}
-
-octave_base_lexer::~octave_base_lexer (void)
-{
-  yylex_destroy (scanner);
-}
-
-void
-octave_base_lexer::init (void)
-{
-  yylex_init (&scanner);
-
-  // Make octave_base_lexer object available through yyextra in
-  // flex-generated lexer.
-  yyset_extra (this, scanner);
-
-  clear_start_state ();
-}
-
-// Inside Flex-generated functions, yyg is the scanner cast to its real
-// type.  Some flex macros that we use in octave_base_lexer member functions
-// (for example, BEGIN) use yyg.  If we could perform the actions of
-// these macros with functions instead, we could eliminate the
-// OCTAVE_YYG macro.
-
-#define OCTAVE_YYG \
-  struct yyguts_t *yyg = static_cast<struct yyguts_t*> (scanner)
-
-void
-octave_base_lexer::reset (void)
-{
-  // Start off on the right foot.
-  clear_start_state ();
-
-  symtab_context.clear ();
-
-  // We do want a prompt by default.
-  promptflag (1);
-
-  // Only ask for input from stdin if we are expecting interactive
-  // input.
-
-  if (octave::application::interactive ()
-      && ! (reading_fcn_file
-            || reading_classdef_file
-            || reading_script_file
-            || input_from_eval_string ()))
-    yyrestart (stdin, scanner);
-
-  lexical_feedback::reset ();
-
-  comment_buf.reset ();
-}
-
-void
-octave_base_lexer::prep_for_file (void)
-{
-  reading_script_file = true;
-
-  push_start_state (INPUT_FILE_START);
-}
-
-void
-octave_base_lexer::begin_string (int state)
-{
-  string_line = input_line_number;
-  string_column = current_input_column;
-
-  push_start_state (state);
-}
-
-int
-octave_base_lexer::handle_end_of_input (void)
-{
-  lexer_debug ("<<EOF>>");
-
-  if (block_comment_nesting_level != 0)
-    {
-      warning ("block comment open at end of input");
-
-      if ((reading_fcn_file || reading_script_file || reading_classdef_file)
-          && ! fcn_file_name.empty ())
-        warning ("near line %d of file '%s.m'",
-                 input_line_number, fcn_file_name.c_str ());
-    }
-
-  return handle_token (END_OF_INPUT);
-}
-
-char *
-octave_base_lexer::flex_yytext (void)
-{
-  return yyget_text (scanner);
-}
-
-int
-octave_base_lexer::flex_yyleng (void)
-{
-  return yyget_leng (scanner);
-}
-
-int
-octave_base_lexer::text_yyinput (void)
-{
-  int c = yyinput (scanner);
-
-  if (lexer_debug_flag)
-    {
-      std::cerr << "I: ";
-      display_character (c);
-      std::cerr << std::endl;
-    }
-
-  // Convert CRLF into just LF and single CR into LF.
-
-  if (c == '\r')
-    {
-      c = yyinput (scanner);
-
-      if (lexer_debug_flag)
-        {
-          std::cerr << "I: ";
-          display_character (c);
-          std::cerr << std::endl;
-        }
-
-      if (c != '\n')
-        {
-          xunput (c);
-          c = '\n';
-        }
-    }
-
-  return c;
-}
-
-void
-octave_base_lexer::xunput (char c, char *buf)
-{
-  if (c != EOF)
-    {
-      if (lexer_debug_flag)
-        {
-          std::cerr << "U: ";
-          display_character (c);
-          std::cerr << std::endl;
-        }
-
-      yyunput (c, buf, scanner);
-    }
-}
-
-void
-octave_base_lexer::xunput (char c)
-{
-  char *yytxt = flex_yytext ();
-
-  xunput (c, yytxt);
-}
-
-bool
-octave_base_lexer::looking_at_space (void)
-{
-  int c = text_yyinput ();
-  xunput (c);
-  return (c == ' ' || c == '\t');
-}
-
-bool
-octave_base_lexer::inside_any_object_index (void)
-{
-  bool retval = false;
-
-  for (std::list<bool>::const_iterator i = looking_at_object_index.begin ();
-       i != looking_at_object_index.end (); i++)
-    {
-      if (*i)
-        {
-          retval = true;
-          break;
-        }
-    }
-
-  return retval;
-}
-
-bool
-octave_base_lexer::is_variable (const std::string& name,
-                               symbol_table::scope_id scope)
-{
-  return (symbol_table::is_variable (name, scope)
-          || (pending_local_variables.find (name)
-              != pending_local_variables.end ()));
-}
-
-// Handle keywords.  Return -1 if the keyword should be ignored.
-
-int
-octave_base_lexer::is_keyword_token (const std::string& s)
+namespace octave
 {
-  int l = input_line_number;
-  int c = current_input_column;
-
-  int len = s.length ();
-
-  const octave_kw *kw = octave_kw_hash::in_word_set (s.c_str (), len);
-
-  if (kw)
-    {
-      bool previous_at_bos = at_beginning_of_statement;
-
-      // May be reset to true for some token types.
-      at_beginning_of_statement = false;
-
-      token *tok_val = 0;
-
-      switch (kw->kw_id)
-        {
-        case break_kw:
-        case catch_kw:
-        case continue_kw:
-        case else_kw:
-        case otherwise_kw:
-        case return_kw:
-        case unwind_protect_cleanup_kw:
-          at_beginning_of_statement = true;
-          break;
-
-        case persistent_kw:
-        case global_kw:
-          looking_at_decl_list = true;
-          break;
-
-        case case_kw:
-        case elseif_kw:
-        case until_kw:
-          break;
-
-        case end_kw:
-          if (inside_any_object_index ()
-              || (defining_func
-                  && ! (looking_at_return_list
-                        || parsed_function_name.top ())))
+  void
+  base_lexer::input_buffer::fill (const std::string& input, bool eof_arg)
+  {
+    buffer = input;
+    chars_left = buffer.length ();
+    pos = buffer.c_str ();
+    eof = eof_arg;
+  }
+
+  int
+  base_lexer::input_buffer::copy_chunk (char *buf, size_t max_size)
+  {
+    static const char * const eol = "\n";
+
+    size_t len = max_size > chars_left ? chars_left : max_size;
+    assert (len > 0);
+
+    memcpy (buf, pos, len);
+
+    chars_left -= len;
+    pos += len;
+
+    // Make sure input ends with a new line character.
+    if (chars_left == 0 && buf[len-1] != '\n')
+      {
+        if (len < max_size)
+          {
+            // There is enough room to plug the newline character in
+            // the buffer.
+            buf[len++] = '\n';
+          }
+        else
+          {
+            // There isn't enough room to plug the newline character
+            // in the buffer so arrange to have it returned on the next
+            // call to base_lexer::read.
+            pos = eol;
+            chars_left = 1;
+          }
+      }
+
+    return len;
+  }
+
+  base_lexer::~base_lexer (void)
+  {
+    yylex_destroy (scanner);
+  }
+
+  void
+  base_lexer::init (void)
+  {
+    yylex_init (&scanner);
+
+    // Make base_lexer object available through yyextra in
+    // flex-generated lexer.
+    yyset_extra (this, scanner);
+
+    clear_start_state ();
+  }
+
+  // Inside Flex-generated functions, yyg is the scanner cast to its real
+  // type.  Some flex macros that we use in base_lexer member functions
+  // (for example, BEGIN) use yyg.  If we could perform the actions of
+  // these macros with functions instead, we could eliminate the
+  // OCTAVE_YYG macro.
+
+#define OCTAVE_YYG                                                      \
+  struct yyguts_t *yyg = static_cast<struct yyguts_t*> (scanner)
+
+  void
+  base_lexer::reset (void)
+  {
+    // Start off on the right foot.
+    clear_start_state ();
+
+    symtab_context.clear ();
+
+    // We do want a prompt by default.
+    promptflag (1);
+
+    // Only ask for input from stdin if we are expecting interactive
+    // input.
+
+    if (octave::application::interactive ()
+        && ! (reading_fcn_file
+              || reading_classdef_file
+              || reading_script_file
+              || input_from_eval_string ()))
+      yyrestart (stdin, scanner);
+
+    lexical_feedback::reset ();
+
+    comment_buf.reset ();
+  }
+
+  void
+  base_lexer::prep_for_file (void)
+  {
+    reading_script_file = true;
+
+    push_start_state (INPUT_FILE_START);
+  }
+
+  void
+  base_lexer::begin_string (int state)
+  {
+    string_line = input_line_number;
+    string_column = current_input_column;
+
+    push_start_state (state);
+  }
+
+  int
+  base_lexer::handle_end_of_input (void)
+  {
+    lexer_debug ("<<EOF>>");
+
+    if (block_comment_nesting_level != 0)
+      {
+        warning ("block comment open at end of input");
+
+        if ((reading_fcn_file || reading_script_file || reading_classdef_file)
+            && ! fcn_file_name.empty ())
+          warning ("near line %d of file '%s.m'",
+                   input_line_number, fcn_file_name.c_str ());
+      }
+
+    return handle_token (END_OF_INPUT);
+  }
+
+  char *
+  base_lexer::flex_yytext (void)
+  {
+    return yyget_text (scanner);
+  }
+
+  int
+  base_lexer::flex_yyleng (void)
+  {
+    return yyget_leng (scanner);
+  }
+
+  int
+  base_lexer::text_yyinput (void)
+  {
+    int c = yyinput (scanner);
+
+    if (lexer_debug_flag)
+      {
+        std::cerr << "I: ";
+        display_character (c);
+        std::cerr << std::endl;
+      }
+
+    // Convert CRLF into just LF and single CR into LF.
+
+    if (c == '\r')
+      {
+        c = yyinput (scanner);
+
+        if (lexer_debug_flag)
+          {
+            std::cerr << "I: ";
+            display_character (c);
+            std::cerr << std::endl;
+          }
+
+        if (c != '\n')
+          {
+            xunput (c);
+            c = '\n';
+          }
+      }
+
+    return c;
+  }
+
+  void
+  base_lexer::xunput (char c, char *buf)
+  {
+    if (c != EOF)
+      {
+        if (lexer_debug_flag)
+          {
+            std::cerr << "U: ";
+            display_character (c);
+            std::cerr << std::endl;
+          }
+
+        yyunput (c, buf, scanner);
+      }
+  }
+
+  void
+  base_lexer::xunput (char c)
+  {
+    char *yytxt = flex_yytext ();
+
+    xunput (c, yytxt);
+  }
+
+  bool
+  base_lexer::looking_at_space (void)
+  {
+    int c = text_yyinput ();
+    xunput (c);
+    return (c == ' ' || c == '\t');
+  }
+
+  bool
+  base_lexer::inside_any_object_index (void)
+  {
+    bool retval = false;
+
+    for (std::list<bool>::const_iterator i = looking_at_object_index.begin ();
+         i != looking_at_object_index.end (); i++)
+      {
+        if (*i)
+          {
+            retval = true;
+            break;
+          }
+      }
+
+    return retval;
+  }
+
+  bool
+  base_lexer::is_variable (const std::string& name,
+                                  symbol_table::scope_id scope)
+  {
+    return (symbol_table::is_variable (name, scope)
+            || (pending_local_variables.find (name)
+                != pending_local_variables.end ()));
+  }
+
+  // Handle keywords.  Return -1 if the keyword should be ignored.
+
+  int
+  base_lexer::is_keyword_token (const std::string& s)
+  {
+    int l = input_line_number;
+    int c = current_input_column;
+
+    int len = s.length ();
+
+    const octave_kw *kw = octave_kw_hash::in_word_set (s.c_str (), len);
+
+    if (kw)
+      {
+        bool previous_at_bos = at_beginning_of_statement;
+
+        // May be reset to true for some token types.
+        at_beginning_of_statement = false;
+
+        token *tok_val = 0;
+
+        switch (kw->kw_id)
+          {
+          case break_kw:
+          case catch_kw:
+          case continue_kw:
+          case else_kw:
+          case otherwise_kw:
+          case return_kw:
+          case unwind_protect_cleanup_kw:
+            at_beginning_of_statement = true;
+            break;
+
+          case persistent_kw:
+          case global_kw:
+            looking_at_decl_list = true;
+            break;
+
+          case case_kw:
+          case elseif_kw:
+          case until_kw:
+            break;
+
+          case end_kw:
+            if (inside_any_object_index ()
+                || (defining_func
+                    && ! (looking_at_return_list
+                          || parsed_function_name.top ())))
+              {
+                at_beginning_of_statement = previous_at_bos;
+                return 0;
+              }
+
+            tok_val = new token (end_kw, token::simple_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case end_try_catch_kw:
+            tok_val = new token (end_try_catch_kw, token::try_catch_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case end_unwind_protect_kw:
+            tok_val = new token (end_unwind_protect_kw,
+                                 token::unwind_protect_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endfor_kw:
+            tok_val = new token (endfor_kw, token::for_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endfunction_kw:
+            tok_val = new token (endfunction_kw, token::function_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endif_kw:
+            tok_val = new token (endif_kw, token::if_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endparfor_kw:
+            tok_val = new token (endparfor_kw, token::parfor_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endswitch_kw:
+            tok_val = new token (endswitch_kw, token::switch_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endwhile_kw:
+            tok_val = new token (endwhile_kw, token::while_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endclassdef_kw:
+            tok_val = new token (endclassdef_kw, token::classdef_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endenumeration_kw:
+            tok_val = new token (endenumeration_kw, token::enumeration_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endevents_kw:
+            tok_val = new token (endevents_kw, token::events_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endmethods_kw:
+            tok_val = new token (endmethods_kw, token::methods_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+          case endproperties_kw:
+            tok_val = new token (endproperties_kw, token::properties_end, l, c);
+            at_beginning_of_statement = true;
+            break;
+
+
+          case for_kw:
+          case parfor_kw:
+          case while_kw:
+            decrement_promptflag ();
+            looping++;
+            break;
+
+          case do_kw:
+            at_beginning_of_statement = true;
+            decrement_promptflag ();
+            looping++;
+            break;
+
+          case try_kw:
+          case unwind_protect_kw:
+            at_beginning_of_statement = true;
+            decrement_promptflag ();
+            break;
+
+          case if_kw:
+          case switch_kw:
+            decrement_promptflag ();
+            break;
+
+          case get_kw:
+          case set_kw:
+            // 'get' and 'set' are keywords in classdef method
+            // declarations.
+            if (! maybe_classdef_get_set_method)
+              {
+                at_beginning_of_statement = previous_at_bos;
+                return 0;
+              }
+            break;
+
+          case enumeration_kw:
+          case events_kw:
+          case methods_kw:
+          case properties_kw:
+            // 'properties', 'methods' and 'events' are keywords for
+            // classdef blocks.
+            if (! parsing_classdef)
+              {
+                at_beginning_of_statement = previous_at_bos;
+                return 0;
+              }
+            // fall through ...
+
+          case classdef_kw:
+            // 'classdef' is always a keyword.
+            decrement_promptflag ();
+
+            if (! force_script && token_count == 0 && input_from_file ())
+              {
+                reading_classdef_file = true;
+                reading_script_file = false;
+              }
+            break;
+
+          case function_kw:
+            decrement_promptflag ();
+
+            defining_func++;
+            parsed_function_name.push (false);
+
+            if (! force_script && token_count == 0 && input_from_file ())
+              {
+                reading_fcn_file = true;
+                reading_script_file = false;
+              }
+
+            if (! (reading_fcn_file || reading_script_file
+                   || reading_classdef_file))
+              input_line_number = 1;
+            break;
+
+          case magic_file_kw:
             {
-              at_beginning_of_statement = previous_at_bos;
-              return 0;
+              if ((reading_fcn_file || reading_script_file
+                   || reading_classdef_file)
+                  && ! fcn_file_full_name.empty ())
+                tok_val = new token (magic_file_kw, fcn_file_full_name, l, c);
+              else
+                tok_val = new token (magic_file_kw, "stdin", l, c);
             }
-
-          tok_val = new token (end_kw, token::simple_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case end_try_catch_kw:
-          tok_val = new token (end_try_catch_kw, token::try_catch_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case end_unwind_protect_kw:
-          tok_val = new token (end_unwind_protect_kw,
-                               token::unwind_protect_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endfor_kw:
-          tok_val = new token (endfor_kw, token::for_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endfunction_kw:
-          tok_val = new token (endfunction_kw, token::function_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endif_kw:
-          tok_val = new token (endif_kw, token::if_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endparfor_kw:
-          tok_val = new token (endparfor_kw, token::parfor_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endswitch_kw:
-          tok_val = new token (endswitch_kw, token::switch_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endwhile_kw:
-          tok_val = new token (endwhile_kw, token::while_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endclassdef_kw:
-          tok_val = new token (endclassdef_kw, token::classdef_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endenumeration_kw:
-          tok_val = new token (endenumeration_kw, token::enumeration_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endevents_kw:
-          tok_val = new token (endevents_kw, token::events_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endmethods_kw:
-          tok_val = new token (endmethods_kw, token::methods_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-        case endproperties_kw:
-          tok_val = new token (endproperties_kw, token::properties_end, l, c);
-          at_beginning_of_statement = true;
-          break;
-
-
-        case for_kw:
-        case parfor_kw:
-        case while_kw:
-          decrement_promptflag ();
-          looping++;
-          break;
-
-        case do_kw:
-          at_beginning_of_statement = true;
-          decrement_promptflag ();
-          looping++;
-          break;
-
-        case try_kw:
-        case unwind_protect_kw:
-          at_beginning_of_statement = true;
-          decrement_promptflag ();
-          break;
-
-        case if_kw:
-        case switch_kw:
-          decrement_promptflag ();
-          break;
-
-        case get_kw:
-        case set_kw:
-          // 'get' and 'set' are keywords in classdef method
-          // declarations.
-          if (! maybe_classdef_get_set_method)
-            {
-              at_beginning_of_statement = previous_at_bos;
-              return 0;
-            }
-          break;
-
-        case enumeration_kw:
-        case events_kw:
-        case methods_kw:
-        case properties_kw:
-          // 'properties', 'methods' and 'events' are keywords for
-          // classdef blocks.
-          if (! parsing_classdef)
-            {
-              at_beginning_of_statement = previous_at_bos;
-              return 0;
-            }
-          // fall through ...
-
-        case classdef_kw:
-          // 'classdef' is always a keyword.
-          decrement_promptflag ();
-
-          if (! force_script && token_count == 0 && input_from_file ())
-            {
-              reading_classdef_file = true;
-              reading_script_file = false;
-            }
-          break;
-
-        case function_kw:
-          decrement_promptflag ();
-
-          defining_func++;
-          parsed_function_name.push (false);
-
-          if (! force_script && token_count == 0 && input_from_file ())
-            {
-              reading_fcn_file = true;
-              reading_script_file = false;
-            }
-
-          if (! (reading_fcn_file || reading_script_file
-                 || reading_classdef_file))
-            input_line_number = 1;
-          break;
-
-        case magic_file_kw:
+            break;
+
+          case magic_line_kw:
+            tok_val = new token (magic_line_kw, static_cast<double> (l),
+                                 "", l, c);
+            break;
+
+          default:
+            panic_impossible ();
+          }
+
+        if (! tok_val)
+          tok_val = new token (kw->tok, true, l, c);
+
+        push_token (tok_val);
+
+        return kw->tok;
+      }
+
+    return 0;
+  }
+
+  bool
+  base_lexer::fq_identifier_contains_keyword (const std::string& s)
+  {
+    size_t p1 = 0;
+    size_t p2;
+
+    std::string s_part;
+
+    do
+      {
+        p2 = s.find ('.', p1);
+
+        if (p2 != std::string::npos)
           {
-            if ((reading_fcn_file || reading_script_file
-                 || reading_classdef_file)
-                && ! fcn_file_full_name.empty ())
-              tok_val = new token (magic_file_kw, fcn_file_full_name, l, c);
-            else
-              tok_val = new token (magic_file_kw, "stdin", l, c);
+            s_part = s.substr (p1, p2 - p1);
+            p1 = p2 + 1;
           }
-          break;
-
-        case magic_line_kw:
-          tok_val = new token (magic_line_kw, static_cast<double> (l),
-                               "", l, c);
-          break;
-
-        default:
-          panic_impossible ();
-        }
-
-      if (! tok_val)
-        tok_val = new token (kw->tok, true, l, c);
-
-      push_token (tok_val);
-
-      return kw->tok;
-    }
-
-  return 0;
-}
-
-bool
-octave_base_lexer::fq_identifier_contains_keyword (const std::string& s)
-{
-  size_t p1 = 0;
-  size_t p2;
-
-  std::string s_part;
-
-  do
-    {
-      p2 = s.find ('.', p1);
-
-      if (p2 != std::string::npos)
-        {
-          s_part = s.substr (p1, p2 - p1);
-          p1 = p2 + 1;
-        }
-      else
-        s_part = s.substr (p1);
-
-      if (is_keyword_token (s_part))
-        return true;
-    }
-  while (p2 != std::string::npos);
-
-  return false;
-}
-
-bool
-octave_base_lexer::whitespace_is_significant (void)
-{
-  return (nesting_level.is_bracket ()
-          || (nesting_level.is_brace ()
-              && ! looking_at_object_index.front ()));
+        else
+          s_part = s.substr (p1);
+
+        if (is_keyword_token (s_part))
+          return true;
+      }
+    while (p2 != std::string::npos);
+
+    return false;
+  }
+
+  bool
+  base_lexer::whitespace_is_significant (void)
+  {
+    return (nesting_level.is_bracket ()
+            || (nesting_level.is_brace ()
+                && ! looking_at_object_index.front ()));
+  }
 }
 
 static inline bool
@@ -2753,852 +2762,854 @@
   return (len > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'));
 }
 
-void
-octave_base_lexer::handle_number (void)
-{
-  double value = 0.0;
-  int nread = 0;
-
-  char *yytxt = flex_yytext ();
-
-  // Strip any underscores
-  char *tmptxt = strsave (yytxt);
-  char *rptr = tmptxt;
-  char *wptr = tmptxt;
-  while (*rptr)
-  {
-    *wptr = *rptr++;
-     wptr += (*wptr != '_');
-  }
-  *wptr = '\0';
-
-  if (looks_like_hex (tmptxt, strlen (tmptxt)))
-    {
-      uintmax_t long_int_value;
-
-      nread = sscanf (tmptxt, "%jx", &long_int_value);
-
-      value = static_cast<double> (long_int_value);
-    }
-  else if (looks_like_bin (tmptxt, strlen (tmptxt)))
-    {
-      uintmax_t long_int_value = 0;
-
-      for (size_t i = 0; i < strlen (tmptxt); i++)
-        {
-          long_int_value <<= 1;
-          long_int_value += static_cast<uintmax_t> (tmptxt[i] == '1');
-        }
-
-      value = static_cast<double> (long_int_value);
-
-      nread = 1;  // Just to pass the assert stmt below
-    }
-  else
-    {
-      char *idx = strpbrk (tmptxt, "Dd");
-
-      if (idx)
-        *idx = 'e';
-
-      nread = sscanf (tmptxt, "%lf", &value);
-    }
-
-  delete [] tmptxt;
-
-  // If yytext doesn't contain a valid number, we are in deep doo doo.
-
-  assert (nread == 1);
-
-  looking_for_object_index = false;
-  at_beginning_of_statement = false;
-
-  push_token (new token (NUM, value, yytxt, input_line_number,
-                         current_input_column));
-
-  current_input_column += flex_yyleng ();
-}
-
-void
-octave_base_lexer::handle_continuation (void)
-{
-  char *yytxt = flex_yytext ();
-  int yylng = flex_yyleng ();
-
-  int offset = 1;
-  if (yytxt[0] == '\\')
-    warn_language_extension_continuation ();
-  else
-    offset = 3;
-
-  bool have_space = false;
-  while (offset < yylng)
-    {
-      char c = yytxt[offset];
-      if (c == ' ' || c == '\t')
-        {
-          have_space = true;
-          offset++;
-        }
-      else
-        break;
-    }
-
-  if (have_space)
-    mark_previous_token_trailing_space ();
-
-  bool have_comment = false;
-  while (offset < yylng)
-    {
-      char c = yytxt[offset];
-      if (c == '#' || c == '%')
-        {
-          have_comment = true;
-          offset++;
-        }
-      else
-        break;
-    }
-
-  if (have_comment)
-    {
-      comment_text = &yytxt[offset];
-
-      // finish_comment sets at_beginning_of_statement to true but
-      // that's not be correct if we are handling a continued
-      // statement.  Preserve the current state.
-
-      bool saved_bos = at_beginning_of_statement;
-
-      finish_comment (octave_comment_elt::end_of_line);
-
-      at_beginning_of_statement = saved_bos;
-    }
-
-  decrement_promptflag ();
-  input_line_number++;
-  current_input_column = 1;
-}
-
-void
-octave_base_lexer::finish_comment (octave_comment_elt::comment_type typ)
-{
-  bool copyright = looks_like_copyright (comment_text);
-
-  if (nesting_level.none () && help_text.empty ()
-    && ! comment_text.empty () && ! copyright)
-    help_text = comment_text;
-
-  if (copyright)
-    typ = octave_comment_elt::copyright;
-
-  comment_buf.append (comment_text, typ);
-
-  comment_text = "";
-
-  at_beginning_of_statement = true;
-}
-
-int
-octave_base_lexer::handle_close_bracket (int bracket_type)
-{
-  int retval = bracket_type;
-
-  if (! nesting_level.none ())
-    {
-      nesting_level.remove ();
-
-      if (bracket_type == ']')
-        bracketflag--;
-      else if (bracket_type == '}')
-        braceflag--;
-      else
-        panic_impossible ();
-    }
-
-  pop_start_state ();
-
-  return retval;
-}
-
-bool
-octave_base_lexer::looks_like_command_arg (void)
-{
-  bool space_before = space_follows_previous_token ();
-  bool space_after = looking_at_space ();
-
-  return (space_before && ! space_after
-          && previous_token_may_be_command ());
-}
-
-int
-octave_base_lexer::handle_superclass_identifier (void)
-{
-  std::string meth = flex_yytext ();
-
-  size_t pos = meth.find ("@");
-  std::string cls = meth.substr (pos + 1);
-  meth = meth.substr (0, pos);
-
-  bool kw_token = (is_keyword_token (meth)
-                   || fq_identifier_contains_keyword (cls));
-
-  if (kw_token)
-    {
-      token *tok
-        = new token (LEXICAL_ERROR,
-                     "method, class, and package names may not be keywords",
-                     input_line_number, current_input_column);
-
-      push_token (tok);
-
-      return count_token_internal (LEXICAL_ERROR);
-    }
-
-  push_token (new token (SUPERCLASSREF, meth, cls,
-                         input_line_number, current_input_column));
-
-  current_input_column += flex_yyleng ();
-
-  return SUPERCLASSREF;
-}
-
-int
-octave_base_lexer::handle_meta_identifier (void)
-{
-  std::string cls = std::string(flex_yytext ()).substr (1);
-
-  if (fq_identifier_contains_keyword (cls))
-    {
-      token *tok = new token (LEXICAL_ERROR,
-                              "class and package names may not be keywords",
-                              input_line_number, current_input_column);
-      push_token (tok);
-
-      return count_token_internal (LEXICAL_ERROR);
-    }
-
-  push_token (new token (METAQUERY, cls, input_line_number,
-                         current_input_column));
-
-  current_input_column += flex_yyleng ();
-
-  return METAQUERY;
-}
-
-int
-octave_base_lexer::handle_fq_identifier (void)
-{
-  std::string fq_id = flex_yytext ();
-
-  if (fq_identifier_contains_keyword (fq_id))
-    {
-      token *tok
-        = new token (LEXICAL_ERROR,
-                     "function, method, class, and package names may not be keywords",
-                     input_line_number, current_input_column);
-
-      push_token (tok);
-
-      return count_token_internal (LEXICAL_ERROR);
-    }
-
-  push_token (new token (FQ_IDENT, fq_id, input_line_number,
-                         current_input_column));
-
-  current_input_column += flex_yyleng ();
-
-  return FQ_IDENT;
-}
-
-// Figure out exactly what kind of token to return when we have seen
-// an identifier.  Handles keywords.  Return -1 if the identifier
-// should be ignored.
-
-int
-octave_base_lexer::handle_identifier (void)
-{
-  std::string ident = flex_yytext ();
-
-  // If we are expecting a structure element, avoid recognizing
-  // keywords and other special names and return STRUCT_ELT, which is
-  // a string that is also a valid identifier.
-
-  if (looking_at_indirect_ref)
-    {
-      push_token (new token (STRUCT_ELT, ident, input_line_number,
-                             current_input_column));
-
-      looking_for_object_index = true;
-
-      current_input_column += flex_yyleng ();
-
-      return STRUCT_ELT;
-    }
-
-  // If ident is a keyword token, then is_keyword_token will set
-  // at_beginning_of_statement.  For example, if tok is an IF
-  // token, then at_beginning_of_statement will be false.
-
-  int kw_token = is_keyword_token (ident);
-
-  if (looking_at_function_handle)
-    {
-      if (kw_token)
-        {
-          token *tok
-            = new token (LEXICAL_ERROR,
-                         "function handles may not refer to keywords",
-                         input_line_number, current_input_column);
-
-          push_token (tok);
-
-          return count_token_internal (LEXICAL_ERROR);
-        }
-      else
-        {
-          push_token (new token (FCN_HANDLE, ident, input_line_number,
-                                 current_input_column));
-
-          current_input_column += flex_yyleng ();
-          looking_for_object_index = true;
-
-          at_beginning_of_statement = false;
-
-          return FCN_HANDLE;
-        }
-    }
-
-  // If we have a regular keyword, return it.
-  // Keywords can be followed by identifiers.
-
-  if (kw_token)
-    {
-      if (kw_token >= 0)
-        {
-          current_input_column += flex_yyleng ();
-          looking_for_object_index = false;
-        }
-
-      // The call to is_keyword_token set at_beginning_of_statement.
-
-      return kw_token;
-    }
-
-  // Find the token in the symbol table.
-
-  symbol_table::scope_id sid = symtab_context.curr_scope ();
-
-  token *tok = new token (NAME, &(symbol_table::insert (ident, sid)),
-                          input_line_number, current_input_column);
-
-  // The following symbols are handled specially so that things like
-  //
-  //   pi +1
-  //
-  // are parsed as an addition expression instead of as a command-style
-  // function call with the argument "+1".
-
-  if (at_beginning_of_statement
-      && (! (is_variable (ident, sid)
-             || ident == "e" || ident == "pi"
-             || ident == "I" || ident == "i"
-             || ident == "J" || ident == "j"
-             || ident == "Inf" || ident == "inf"
-             || ident == "NaN" || ident == "nan")))
-    tok->mark_may_be_command ();
-
-  push_token (tok);
-
-  current_input_column += flex_yyleng ();
-
-  // The magic end index can't be indexed.
-
-  if (ident != "end")
-    looking_for_object_index = true;
-
-  at_beginning_of_statement = false;
-
-  return NAME;
-}
-
-void
-octave_base_lexer::maybe_warn_separator_insert (char sep)
-{
-  std::string nm = fcn_file_full_name;
-
-  if (nm.empty ())
-    warning_with_id ("Octave:separator-insert",
-                     "potential auto-insertion of '%c' near line %d",
-                     sep, input_line_number);
-  else
-    warning_with_id ("Octave:separator-insert",
-                     "potential auto-insertion of '%c' near line %d of file %s",
-                     sep, input_line_number, nm.c_str ());
-}
-
-void
-octave_base_lexer::warn_single_quote_string (void)
-{
-  std::string nm = fcn_file_full_name;
-
-  if (nm.empty ())
-    warning_with_id ("Octave:single-quote-string",
-                     "single quote delimited string near line %d",
-                     input_line_number);
-  else
-    warning_with_id ("Octave:single-quote-string",
-                     "single quote delimited string near line %d of file %s",
-                     input_line_number, nm.c_str ());
-}
-
-void
-octave_base_lexer::warn_language_extension (const std::string& msg)
-{
-  std::string nm = fcn_file_full_name;
-
-  if (nm.empty ())
-    warning_with_id ("Octave:language-extension",
-                     "Octave language extension used: %s",
-                     msg.c_str ());
-  else
-    warning_with_id ("Octave:language-extension",
-                     "Octave language extension used: %s near line %d offile %s",
-                     msg.c_str (), input_line_number, nm.c_str ());
-}
-
-void
-octave_base_lexer::maybe_warn_language_extension_comment (char c)
-{
-  if (c == '#')
-    warn_language_extension ("# used as comment character");
-}
-
-void
-octave_base_lexer::warn_language_extension_continuation (void)
+namespace octave
 {
-  warn_language_extension ("\\ used as line continuation marker");
-}
-
-void
-octave_base_lexer::warn_language_extension_operator (const std::string& op)
-{
-  std::string t = op;
-  int n = t.length ();
-  if (t[n-1] == '\n')
-    t.resize (n-1);
-  warn_language_extension (t + " used as operator");
-}
-
-void
-octave_base_lexer::push_token (token *tok)
-{
-  YYSTYPE *lval = yyget_lval (scanner);
-  lval->tok_val = tok;
-  tokens.push (tok);
-}
-
-token *
-octave_base_lexer::current_token (void)
-{
-  YYSTYPE *lval = yyget_lval (scanner);
-  return lval->tok_val;
-}
-
-void
-octave_base_lexer::display_token (int tok)
-{
-  switch (tok)
-    {
-    case '=': std::cerr << "'='\n"; break;
-    case ':': std::cerr << "':'\n"; break;
-    case '-': std::cerr << "'-'\n"; break;
-    case '+': std::cerr << "'+'\n"; break;
-    case '*': std::cerr << "'*'\n"; break;
-    case '/': std::cerr << "'/'\n"; break;
-    case ADD_EQ: std::cerr << "ADD_EQ\n"; break;
-    case SUB_EQ: std::cerr << "SUB_EQ\n"; break;
-    case MUL_EQ: std::cerr << "MUL_EQ\n"; break;
-    case DIV_EQ: std::cerr << "DIV_EQ\n"; break;
-    case LEFTDIV_EQ: std::cerr << "LEFTDIV_EQ\n"; break;
-    case POW_EQ: std::cerr << "POW_EQ\n"; break;
-    case EMUL_EQ: std::cerr << "EMUL_EQ\n"; break;
-    case EDIV_EQ: std::cerr << "EDIV_EQ\n"; break;
-    case ELEFTDIV_EQ: std::cerr << "ELEFTDIV_EQ\n"; break;
-    case EPOW_EQ: std::cerr << "EPOW_EQ\n"; break;
-    case AND_EQ: std::cerr << "AND_EQ\n"; break;
-    case OR_EQ: std::cerr << "OR_EQ\n"; break;
-    case EXPR_AND_AND: std::cerr << "EXPR_AND_AND\n"; break;
-    case EXPR_OR_OR: std::cerr << "EXPR_OR_OR\n"; break;
-    case EXPR_AND: std::cerr << "EXPR_AND\n"; break;
-    case EXPR_OR: std::cerr << "EXPR_OR\n"; break;
-    case EXPR_NOT: std::cerr << "EXPR_NOT\n"; break;
-    case EXPR_LT: std::cerr << "EXPR_LT\n"; break;
-    case EXPR_LE: std::cerr << "EXPR_LE\n"; break;
-    case EXPR_EQ: std::cerr << "EXPR_EQ\n"; break;
-    case EXPR_NE: std::cerr << "EXPR_NE\n"; break;
-    case EXPR_GE: std::cerr << "EXPR_GE\n"; break;
-    case EXPR_GT: std::cerr << "EXPR_GT\n"; break;
-    case LEFTDIV: std::cerr << "LEFTDIV\n"; break;
-    case EMUL: std::cerr << "EMUL\n"; break;
-    case EDIV: std::cerr << "EDIV\n"; break;
-    case ELEFTDIV: std::cerr << "ELEFTDIV\n"; break;
-    case EPLUS: std::cerr << "EPLUS\n"; break;
-    case EMINUS: std::cerr << "EMINUS\n"; break;
-    case HERMITIAN: std::cerr << "HERMITIAN\n"; break;
-    case TRANSPOSE: std::cerr << "TRANSPOSE\n"; break;
-    case PLUS_PLUS: std::cerr << "PLUS_PLUS\n"; break;
-    case MINUS_MINUS: std::cerr << "MINUS_MINUS\n"; break;
-    case POW: std::cerr << "POW\n"; break;
-    case EPOW: std::cerr << "EPOW\n"; break;
-
-    case NUM:
-    case IMAG_NUM:
+  void
+  base_lexer::handle_number (void)
+  {
+    double value = 0.0;
+    int nread = 0;
+
+    char *yytxt = flex_yytext ();
+
+    // Strip any underscores
+    char *tmptxt = strsave (yytxt);
+    char *rptr = tmptxt;
+    char *wptr = tmptxt;
+    while (*rptr)
+      {
+        *wptr = *rptr++;
+        wptr += (*wptr != '_');
+      }
+    *wptr = '\0';
+
+    if (looks_like_hex (tmptxt, strlen (tmptxt)))
+      {
+        uintmax_t long_int_value;
+
+        nread = sscanf (tmptxt, "%jx", &long_int_value);
+
+        value = static_cast<double> (long_int_value);
+      }
+    else if (looks_like_bin (tmptxt, strlen (tmptxt)))
+      {
+        uintmax_t long_int_value = 0;
+
+        for (size_t i = 0; i < strlen (tmptxt); i++)
+          {
+            long_int_value <<= 1;
+            long_int_value += static_cast<uintmax_t> (tmptxt[i] == '1');
+          }
+
+        value = static_cast<double> (long_int_value);
+
+        nread = 1;  // Just to pass the assert stmt below
+      }
+    else
+      {
+        char *idx = strpbrk (tmptxt, "Dd");
+
+        if (idx)
+          *idx = 'e';
+
+        nread = sscanf (tmptxt, "%lf", &value);
+      }
+
+    delete [] tmptxt;
+
+    // If yytext doesn't contain a valid number, we are in deep doo doo.
+
+    assert (nread == 1);
+
+    looking_for_object_index = false;
+    at_beginning_of_statement = false;
+
+    push_token (new token (NUM, value, yytxt, input_line_number,
+                           current_input_column));
+
+    current_input_column += flex_yyleng ();
+  }
+
+  void
+  base_lexer::handle_continuation (void)
+  {
+    char *yytxt = flex_yytext ();
+    int yylng = flex_yyleng ();
+
+    int offset = 1;
+    if (yytxt[0] == '\\')
+      warn_language_extension_continuation ();
+    else
+      offset = 3;
+
+    bool have_space = false;
+    while (offset < yylng)
+      {
+        char c = yytxt[offset];
+        if (c == ' ' || c == '\t')
+          {
+            have_space = true;
+            offset++;
+          }
+        else
+          break;
+      }
+
+    if (have_space)
+      mark_previous_token_trailing_space ();
+
+    bool have_comment = false;
+    while (offset < yylng)
+      {
+        char c = yytxt[offset];
+        if (c == '#' || c == '%')
+          {
+            have_comment = true;
+            offset++;
+          }
+        else
+          break;
+      }
+
+    if (have_comment)
+      {
+        comment_text = &yytxt[offset];
+
+        // finish_comment sets at_beginning_of_statement to true but
+        // that's not be correct if we are handling a continued
+        // statement.  Preserve the current state.
+
+        bool saved_bos = at_beginning_of_statement;
+
+        finish_comment (octave_comment_elt::end_of_line);
+
+        at_beginning_of_statement = saved_bos;
+      }
+
+    decrement_promptflag ();
+    input_line_number++;
+    current_input_column = 1;
+  }
+
+  void
+  base_lexer::finish_comment (octave_comment_elt::comment_type typ)
+  {
+    bool copyright = looks_like_copyright (comment_text);
+
+    if (nesting_level.none () && help_text.empty ()
+        && ! comment_text.empty () && ! copyright)
+      help_text = comment_text;
+
+    if (copyright)
+      typ = octave_comment_elt::copyright;
+
+    comment_buf.append (comment_text, typ);
+
+    comment_text = "";
+
+    at_beginning_of_statement = true;
+  }
+
+  int
+  base_lexer::handle_close_bracket (int bracket_type)
+  {
+    int retval = bracket_type;
+
+    if (! nesting_level.none ())
       {
-        token *tok_val = current_token ();
-        std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM")
-                  << " [" << tok_val->number () << "]\n";
+        nesting_level.remove ();
+
+        if (bracket_type == ']')
+          bracketflag--;
+        else if (bracket_type == '}')
+          braceflag--;
+        else
+          panic_impossible ();
       }
-      break;
-
-    case STRUCT_ELT:
+
+    pop_start_state ();
+
+    return retval;
+  }
+
+  bool
+  base_lexer::looks_like_command_arg (void)
+  {
+    bool space_before = space_follows_previous_token ();
+    bool space_after = looking_at_space ();
+
+    return (space_before && ! space_after
+            && previous_token_may_be_command ());
+  }
+
+  int
+  base_lexer::handle_superclass_identifier (void)
+  {
+    std::string meth = flex_yytext ();
+
+    size_t pos = meth.find ("@");
+    std::string cls = meth.substr (pos + 1);
+    meth = meth.substr (0, pos);
+
+    bool kw_token = (is_keyword_token (meth)
+                     || fq_identifier_contains_keyword (cls));
+
+    if (kw_token)
       {
-        token *tok_val = current_token ();
-        std::cerr << "STRUCT_ELT [" << tok_val->text () << "]\n";
+        token *tok
+          = new token (LEXICAL_ERROR,
+                       "method, class, and package names may not be keywords",
+                       input_line_number, current_input_column);
+
+        push_token (tok);
+
+        return count_token_internal (LEXICAL_ERROR);
+      }
+
+    push_token (new token (SUPERCLASSREF, meth, cls,
+                           input_line_number, current_input_column));
+
+    current_input_column += flex_yyleng ();
+
+    return SUPERCLASSREF;
+  }
+
+  int
+  base_lexer::handle_meta_identifier (void)
+  {
+    std::string cls = std::string(flex_yytext ()).substr (1);
+
+    if (fq_identifier_contains_keyword (cls))
+      {
+        token *tok = new token (LEXICAL_ERROR,
+                                "class and package names may not be keywords",
+                                input_line_number, current_input_column);
+        push_token (tok);
+
+        return count_token_internal (LEXICAL_ERROR);
       }
-      break;
-
-    case NAME:
+
+    push_token (new token (METAQUERY, cls, input_line_number,
+                           current_input_column));
+
+    current_input_column += flex_yyleng ();
+
+    return METAQUERY;
+  }
+
+  int
+  base_lexer::handle_fq_identifier (void)
+  {
+    std::string fq_id = flex_yytext ();
+
+    if (fq_identifier_contains_keyword (fq_id))
+      {
+        token *tok
+          = new token (LEXICAL_ERROR,
+                       "function, method, class, and package names may not be keywords",
+                       input_line_number, current_input_column);
+
+        push_token (tok);
+
+        return count_token_internal (LEXICAL_ERROR);
+      }
+
+    push_token (new token (FQ_IDENT, fq_id, input_line_number,
+                           current_input_column));
+
+    current_input_column += flex_yyleng ();
+
+    return FQ_IDENT;
+  }
+
+  // Figure out exactly what kind of token to return when we have seen
+  // an identifier.  Handles keywords.  Return -1 if the identifier
+  // should be ignored.
+
+  int
+  base_lexer::handle_identifier (void)
+  {
+    std::string ident = flex_yytext ();
+
+    // If we are expecting a structure element, avoid recognizing
+    // keywords and other special names and return STRUCT_ELT, which is
+    // a string that is also a valid identifier.
+
+    if (looking_at_indirect_ref)
       {
-        token *tok_val = current_token ();
-        symbol_table::symbol_record *sr = tok_val->sym_rec ();
-        std::cerr << "NAME";
-        if (sr)
-          std::cerr << " [" << sr->name () << "]";
-        std::cerr << "\n";
+        push_token (new token (STRUCT_ELT, ident, input_line_number,
+                               current_input_column));
+
+        looking_for_object_index = true;
+
+        current_input_column += flex_yyleng ();
+
+        return STRUCT_ELT;
+      }
+
+    // If ident is a keyword token, then is_keyword_token will set
+    // at_beginning_of_statement.  For example, if tok is an IF
+    // token, then at_beginning_of_statement will be false.
+
+    int kw_token = is_keyword_token (ident);
+
+    if (looking_at_function_handle)
+      {
+        if (kw_token)
+          {
+            token *tok
+              = new token (LEXICAL_ERROR,
+                           "function handles may not refer to keywords",
+                           input_line_number, current_input_column);
+
+            push_token (tok);
+
+            return count_token_internal (LEXICAL_ERROR);
+          }
+        else
+          {
+            push_token (new token (FCN_HANDLE, ident, input_line_number,
+                                   current_input_column));
+
+            current_input_column += flex_yyleng ();
+            looking_for_object_index = true;
+
+            at_beginning_of_statement = false;
+
+            return FCN_HANDLE;
+          }
+      }
+
+    // If we have a regular keyword, return it.
+    // Keywords can be followed by identifiers.
+
+    if (kw_token)
+      {
+        if (kw_token >= 0)
+          {
+            current_input_column += flex_yyleng ();
+            looking_for_object_index = false;
+          }
+
+        // The call to is_keyword_token set at_beginning_of_statement.
+
+        return kw_token;
       }
-      break;
-
-    case END: std::cerr << "END\n"; break;
-
-    case DQ_STRING:
-    case SQ_STRING:
-      {
-        token *tok_val = current_token ();
-
-        std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING")
-                  << " [" << tok_val->text () << "]\n";
-      }
-      break;
-
-    case FOR: std::cerr << "FOR\n"; break;
-    case WHILE: std::cerr << "WHILE\n"; break;
-    case DO: std::cerr << "DO\n"; break;
-    case UNTIL: std::cerr << "UNTIL\n"; break;
-    case IF: std::cerr << "IF\n"; break;
-    case ELSEIF: std::cerr << "ELSEIF\n"; break;
-    case ELSE: std::cerr << "ELSE\n"; break;
-    case SWITCH: std::cerr << "SWITCH\n"; break;
-    case CASE: std::cerr << "CASE\n"; break;
-    case OTHERWISE: std::cerr << "OTHERWISE\n"; break;
-    case BREAK: std::cerr << "BREAK\n"; break;
-    case CONTINUE: std::cerr << "CONTINUE\n"; break;
-    case FUNC_RET: std::cerr << "FUNC_RET\n"; break;
-    case UNWIND: std::cerr << "UNWIND\n"; break;
-    case CLEANUP: std::cerr << "CLEANUP\n"; break;
-    case TRY: std::cerr << "TRY\n"; break;
-    case CATCH: std::cerr << "CATCH\n"; break;
-    case GLOBAL: std::cerr << "GLOBAL\n"; break;
-    case PERSISTENT: std::cerr << "PERSISTENT\n"; break;
-    case FCN_HANDLE: std::cerr << "FCN_HANDLE\n"; break;
-    case END_OF_INPUT: std::cerr << "END_OF_INPUT\n\n"; break;
-    case LEXICAL_ERROR: std::cerr << "LEXICAL_ERROR\n\n"; break;
-    case FCN: std::cerr << "FCN\n"; break;
-    case INPUT_FILE: std::cerr << "INPUT_FILE\n"; break;
-    case SUPERCLASSREF: std::cerr << "SUPERCLASSREF\n"; break;
-    case METAQUERY: std::cerr << "METAQUERY\n"; break;
-    case GET: std::cerr << "GET\n"; break;
-    case SET: std::cerr << "SET\n"; break;
-    case PROPERTIES: std::cerr << "PROPERTIES\n"; break;
-    case METHODS: std::cerr << "METHODS\n"; break;
-    case EVENTS: std::cerr << "EVENTS\n"; break;
-    case CLASSDEF: std::cerr << "CLASSDEF\n"; break;
-    case '\n': std::cerr << "\\n\n"; break;
-    case '\r': std::cerr << "\\r\n"; break;
-    case '\t': std::cerr << "TAB\n"; break;
-    default:
+
+    // Find the token in the symbol table.
+
+    symbol_table::scope_id sid = symtab_context.curr_scope ();
+
+    token *tok = new token (NAME, &(symbol_table::insert (ident, sid)),
+                            input_line_number, current_input_column);
+
+    // The following symbols are handled specially so that things like
+    //
+    //   pi +1
+    //
+    // are parsed as an addition expression instead of as a command-style
+    // function call with the argument "+1".
+
+    if (at_beginning_of_statement
+        && (! (is_variable (ident, sid)
+               || ident == "e" || ident == "pi"
+               || ident == "I" || ident == "i"
+               || ident == "J" || ident == "j"
+               || ident == "Inf" || ident == "inf"
+               || ident == "NaN" || ident == "nan")))
+      tok->mark_may_be_command ();
+
+    push_token (tok);
+
+    current_input_column += flex_yyleng ();
+
+    // The magic end index can't be indexed.
+
+    if (ident != "end")
+      looking_for_object_index = true;
+
+    at_beginning_of_statement = false;
+
+    return NAME;
+  }
+
+  void
+  base_lexer::maybe_warn_separator_insert (char sep)
+  {
+    std::string nm = fcn_file_full_name;
+
+    if (nm.empty ())
+      warning_with_id ("Octave:separator-insert",
+                       "potential auto-insertion of '%c' near line %d",
+                       sep, input_line_number);
+    else
+      warning_with_id ("Octave:separator-insert",
+                       "potential auto-insertion of '%c' near line %d of file %s",
+                       sep, input_line_number, nm.c_str ());
+  }
+
+  void
+  base_lexer::warn_single_quote_string (void)
+  {
+    std::string nm = fcn_file_full_name;
+
+    if (nm.empty ())
+      warning_with_id ("Octave:single-quote-string",
+                       "single quote delimited string near line %d",
+                       input_line_number);
+    else
+      warning_with_id ("Octave:single-quote-string",
+                       "single quote delimited string near line %d of file %s",
+                       input_line_number, nm.c_str ());
+  }
+
+  void
+  base_lexer::warn_language_extension (const std::string& msg)
+  {
+    std::string nm = fcn_file_full_name;
+
+    if (nm.empty ())
+      warning_with_id ("Octave:language-extension",
+                       "Octave language extension used: %s",
+                       msg.c_str ());
+    else
+      warning_with_id ("Octave:language-extension",
+                       "Octave language extension used: %s near line %d offile %s",
+                       msg.c_str (), input_line_number, nm.c_str ());
+  }
+
+  void
+  base_lexer::maybe_warn_language_extension_comment (char c)
+  {
+    if (c == '#')
+      warn_language_extension ("# used as comment character");
+  }
+
+  void
+  base_lexer::warn_language_extension_continuation (void)
+  {
+    warn_language_extension ("\\ used as line continuation marker");
+  }
+
+  void
+  base_lexer::warn_language_extension_operator (const std::string& op)
+  {
+    std::string t = op;
+    int n = t.length ();
+    if (t[n-1] == '\n')
+      t.resize (n-1);
+    warn_language_extension (t + " used as operator");
+  }
+
+  void
+  base_lexer::push_token (token *tok)
+  {
+    YYSTYPE *lval = yyget_lval (scanner);
+    lval->tok_val = tok;
+    tokens.push (tok);
+  }
+
+  token *
+  base_lexer::current_token (void)
+  {
+    YYSTYPE *lval = yyget_lval (scanner);
+    return lval->tok_val;
+  }
+
+  void
+  base_lexer::display_token (int tok)
+  {
+    switch (tok)
       {
-        if (tok < 256 && tok > 31)
-          std::cerr << static_cast<char> (tok) << "\n";
-        else
-          std::cerr << "UNKNOWN(" << tok << ")\n";
+      case '=': std::cerr << "'='\n"; break;
+      case ':': std::cerr << "':'\n"; break;
+      case '-': std::cerr << "'-'\n"; break;
+      case '+': std::cerr << "'+'\n"; break;
+      case '*': std::cerr << "'*'\n"; break;
+      case '/': std::cerr << "'/'\n"; break;
+      case ADD_EQ: std::cerr << "ADD_EQ\n"; break;
+      case SUB_EQ: std::cerr << "SUB_EQ\n"; break;
+      case MUL_EQ: std::cerr << "MUL_EQ\n"; break;
+      case DIV_EQ: std::cerr << "DIV_EQ\n"; break;
+      case LEFTDIV_EQ: std::cerr << "LEFTDIV_EQ\n"; break;
+      case POW_EQ: std::cerr << "POW_EQ\n"; break;
+      case EMUL_EQ: std::cerr << "EMUL_EQ\n"; break;
+      case EDIV_EQ: std::cerr << "EDIV_EQ\n"; break;
+      case ELEFTDIV_EQ: std::cerr << "ELEFTDIV_EQ\n"; break;
+      case EPOW_EQ: std::cerr << "EPOW_EQ\n"; break;
+      case AND_EQ: std::cerr << "AND_EQ\n"; break;
+      case OR_EQ: std::cerr << "OR_EQ\n"; break;
+      case EXPR_AND_AND: std::cerr << "EXPR_AND_AND\n"; break;
+      case EXPR_OR_OR: std::cerr << "EXPR_OR_OR\n"; break;
+      case EXPR_AND: std::cerr << "EXPR_AND\n"; break;
+      case EXPR_OR: std::cerr << "EXPR_OR\n"; break;
+      case EXPR_NOT: std::cerr << "EXPR_NOT\n"; break;
+      case EXPR_LT: std::cerr << "EXPR_LT\n"; break;
+      case EXPR_LE: std::cerr << "EXPR_LE\n"; break;
+      case EXPR_EQ: std::cerr << "EXPR_EQ\n"; break;
+      case EXPR_NE: std::cerr << "EXPR_NE\n"; break;
+      case EXPR_GE: std::cerr << "EXPR_GE\n"; break;
+      case EXPR_GT: std::cerr << "EXPR_GT\n"; break;
+      case LEFTDIV: std::cerr << "LEFTDIV\n"; break;
+      case EMUL: std::cerr << "EMUL\n"; break;
+      case EDIV: std::cerr << "EDIV\n"; break;
+      case ELEFTDIV: std::cerr << "ELEFTDIV\n"; break;
+      case EPLUS: std::cerr << "EPLUS\n"; break;
+      case EMINUS: std::cerr << "EMINUS\n"; break;
+      case HERMITIAN: std::cerr << "HERMITIAN\n"; break;
+      case TRANSPOSE: std::cerr << "TRANSPOSE\n"; break;
+      case PLUS_PLUS: std::cerr << "PLUS_PLUS\n"; break;
+      case MINUS_MINUS: std::cerr << "MINUS_MINUS\n"; break;
+      case POW: std::cerr << "POW\n"; break;
+      case EPOW: std::cerr << "EPOW\n"; break;
+
+      case NUM:
+      case IMAG_NUM:
+        {
+          token *tok_val = current_token ();
+          std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM")
+                    << " [" << tok_val->number () << "]\n";
+        }
+        break;
+
+      case STRUCT_ELT:
+        {
+          token *tok_val = current_token ();
+          std::cerr << "STRUCT_ELT [" << tok_val->text () << "]\n";
+        }
+        break;
+
+      case NAME:
+        {
+          token *tok_val = current_token ();
+          symbol_table::symbol_record *sr = tok_val->sym_rec ();
+          std::cerr << "NAME";
+          if (sr)
+            std::cerr << " [" << sr->name () << "]";
+          std::cerr << "\n";
+        }
+        break;
+
+      case END: std::cerr << "END\n"; break;
+
+      case DQ_STRING:
+      case SQ_STRING:
+        {
+          token *tok_val = current_token ();
+
+          std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING")
+                    << " [" << tok_val->text () << "]\n";
+        }
+        break;
+
+      case FOR: std::cerr << "FOR\n"; break;
+      case WHILE: std::cerr << "WHILE\n"; break;
+      case DO: std::cerr << "DO\n"; break;
+      case UNTIL: std::cerr << "UNTIL\n"; break;
+      case IF: std::cerr << "IF\n"; break;
+      case ELSEIF: std::cerr << "ELSEIF\n"; break;
+      case ELSE: std::cerr << "ELSE\n"; break;
+      case SWITCH: std::cerr << "SWITCH\n"; break;
+      case CASE: std::cerr << "CASE\n"; break;
+      case OTHERWISE: std::cerr << "OTHERWISE\n"; break;
+      case BREAK: std::cerr << "BREAK\n"; break;
+      case CONTINUE: std::cerr << "CONTINUE\n"; break;
+      case FUNC_RET: std::cerr << "FUNC_RET\n"; break;
+      case UNWIND: std::cerr << "UNWIND\n"; break;
+      case CLEANUP: std::cerr << "CLEANUP\n"; break;
+      case TRY: std::cerr << "TRY\n"; break;
+      case CATCH: std::cerr << "CATCH\n"; break;
+      case GLOBAL: std::cerr << "GLOBAL\n"; break;
+      case PERSISTENT: std::cerr << "PERSISTENT\n"; break;
+      case FCN_HANDLE: std::cerr << "FCN_HANDLE\n"; break;
+      case END_OF_INPUT: std::cerr << "END_OF_INPUT\n\n"; break;
+      case LEXICAL_ERROR: std::cerr << "LEXICAL_ERROR\n\n"; break;
+      case FCN: std::cerr << "FCN\n"; break;
+      case INPUT_FILE: std::cerr << "INPUT_FILE\n"; break;
+      case SUPERCLASSREF: std::cerr << "SUPERCLASSREF\n"; break;
+      case METAQUERY: std::cerr << "METAQUERY\n"; break;
+      case GET: std::cerr << "GET\n"; break;
+      case SET: std::cerr << "SET\n"; break;
+      case PROPERTIES: std::cerr << "PROPERTIES\n"; break;
+      case METHODS: std::cerr << "METHODS\n"; break;
+      case EVENTS: std::cerr << "EVENTS\n"; break;
+      case CLASSDEF: std::cerr << "CLASSDEF\n"; break;
+      case '\n': std::cerr << "\\n\n"; break;
+      case '\r': std::cerr << "\\r\n"; break;
+      case '\t': std::cerr << "TAB\n"; break;
+      default:
+        {
+          if (tok < 256 && tok > 31)
+            std::cerr << static_cast<char> (tok) << "\n";
+          else
+            std::cerr << "UNKNOWN(" << tok << ")\n";
+        }
+        break;
+      }
+  }
+
+  void
+  base_lexer::fatal_error (const char *msg)
+  {
+    error ("fatal lexer error: %s", msg);
+  }
+
+  void
+  base_lexer::lexer_debug (const char *pattern)
+  {
+    if (lexer_debug_flag)
+      {
+        std::cerr << std::endl;
+
+        display_start_state ();
+
+        std::cerr << "P: " << pattern << std::endl;
+        std::cerr << "T: " << flex_yytext () << std::endl;
       }
-      break;
-    }
-}
-
-void
-octave_base_lexer::fatal_error (const char *msg)
-{
-  error ("fatal lexer error: %s", msg);
-}
-
-void
-octave_base_lexer::lexer_debug (const char *pattern)
-{
-  if (lexer_debug_flag)
-    {
-      std::cerr << std::endl;
-
-      display_start_state ();
-
-      std::cerr << "P: " << pattern << std::endl;
-      std::cerr << "T: " << flex_yytext () << std::endl;
-    }
-}
-
-void
-octave_base_lexer::push_start_state (int state)
-{
-  OCTAVE_YYG;
-
-  start_state_stack.push (state);
-
-  BEGIN (start_state ());
-}
-
-void
-octave_base_lexer::pop_start_state (void)
-{
-  OCTAVE_YYG;
-
-  start_state_stack.pop ();
-
-  BEGIN (start_state ());
-}
-
-void
-octave_base_lexer::clear_start_state (void)
-{
-  while (! start_state_stack.empty ())
+  }
+
+  void
+  base_lexer::push_start_state (int state)
+  {
+    OCTAVE_YYG;
+
+    start_state_stack.push (state);
+
+    BEGIN (start_state ());
+  }
+
+  void
+  base_lexer::pop_start_state (void)
+  {
+    OCTAVE_YYG;
+
     start_state_stack.pop ();
 
-  push_start_state (INITIAL);
+    BEGIN (start_state ());
+  }
+
+  void
+  base_lexer::clear_start_state (void)
+  {
+    while (! start_state_stack.empty ())
+      start_state_stack.pop ();
+
+    push_start_state (INITIAL);
+  }
+
+  void
+  base_lexer::display_start_state (void) const
+  {
+    std::cerr << "S: ";
+
+    switch (start_state ())
+      {
+      case INITIAL:
+        std::cerr << "INITIAL" << std::endl;
+        break;
+
+      case COMMAND_START:
+        std::cerr << "COMMAND_START" << std::endl;
+        break;
+
+      case MATRIX_START:
+        std::cerr << "MATRIX_START" << std::endl;
+        break;
+
+      case INPUT_FILE_START:
+        std::cerr << "INPUT_FILE_BEGIN" << std::endl;
+        break;
+
+      case BLOCK_COMMENT_START:
+        std::cerr << "BLOCK_COMMENT_START" << std::endl;
+        break;
+
+      case LINE_COMMENT_START:
+        std::cerr << "LINE_COMMENT_START" << std::endl;
+        break;
+
+      case DQ_STRING_START:
+        std::cerr << "DQ_STRING_START" << std::endl;
+        break;
+
+      case SQ_STRING_START:
+        std::cerr << "SQ_STRING_START" << std::endl;
+        break;
+
+      default:
+        std::cerr << "UNKNOWN START STATE!" << std::endl;
+        break;
+      }
+  }
+
+  int
+  base_lexer::handle_op (const char *pattern, int tok, bool bos)
+  {
+    lexer_debug (pattern);
+
+    return handle_op_internal (tok, bos, true);
+  }
+
+  int
+  base_lexer::handle_language_extension_op (const char *pattern, int tok,
+                                                   bool bos)
+  {
+    lexer_debug (pattern);
+
+    return handle_op_internal (tok, bos, false);
+  }
+
+  bool
+  base_lexer::maybe_unput_comma_before_unary_op (int tok)
+  {
+    int prev_tok = previous_token_value ();
+
+    bool unput_comma = false;
+
+    if (whitespace_is_significant () && space_follows_previous_token ())
+      {
+        int c = text_yyinput ();
+        xunput (c);
+
+        bool space_after = (c == ' ' || c == '\t');
+
+        if (! (prev_tok == '[' || prev_tok == '{'
+               || previous_token_is_binop ()
+               || ((tok == '+' || tok == '-') && space_after)))
+          unput_comma = true;
+      }
+
+    return unput_comma;
+  }
+
+  int
+  base_lexer::handle_unary_op (int tok, bool bos)
+  {
+    return maybe_unput_comma_before_unary_op (tok)
+      ? -1 : handle_op_internal (tok, bos, true);
+  }
+
+  int
+  base_lexer::handle_language_extension_unary_op (int tok, bool bos)
+  {
+    return maybe_unput_comma_before_unary_op (tok)
+      ? -1 : handle_op_internal (tok, bos, false);
+  }
+
+  int
+  base_lexer::handle_op_internal (int tok, bool bos, bool compat)
+  {
+    if (! compat)
+      warn_language_extension_operator (flex_yytext ());
+
+    push_token (new token (tok, input_line_number, current_input_column));
+
+    current_input_column += flex_yyleng ();
+    looking_for_object_index = false;
+    at_beginning_of_statement = bos;
+
+    return count_token_internal (tok);
+  }
+
+  int
+  base_lexer::handle_token (const std::string& name, int tok)
+  {
+    token *tok_val = new token (tok, name, input_line_number,
+                                current_input_column);
+
+    return handle_token (tok, tok_val);
+  }
+
+  int
+  base_lexer::handle_token (int tok, token *tok_val)
+  {
+    if (! tok_val)
+      tok_val = new token (tok, input_line_number, current_input_column);
+
+    push_token (tok_val);
+
+    current_input_column += flex_yyleng ();
+
+    return count_token_internal (tok);
+  }
+
+  int
+  base_lexer::count_token (int tok)
+  {
+    token *tok_val = new token (tok, input_line_number, current_input_column);
+
+    push_token (tok_val);
+
+    return count_token_internal (tok);
+  }
+
+  int
+  base_lexer::count_token_internal (int tok)
+  {
+    if (tok != '\n')
+      {
+        Vtoken_count++;
+        token_count++;
+      }
+
+    return show_token (tok);
+  }
+
+  int
+  base_lexer::show_token (int tok)
+  {
+    if (Vdisplay_tokens)
+      display_token (tok);
+
+    if (lexer_debug_flag)
+      {
+        std::cerr << "R: ";
+        display_token (tok);
+        std::cerr << std::endl;
+      }
+
+    return tok;
+  }
+
+  void
+  base_lexer::enable_fq_identifier (void)
+  {
+    push_start_state (FQ_IDENT_START);
+  }
+
+  int
+  lexer::fill_flex_buffer (char *buf, unsigned max_size)
+  {
+    int status = 0;
+
+    if (input_buf.empty ())
+      {
+        bool eof = false;
+        current_input_line = input_reader.get_input (eof);
+        input_buf.fill (current_input_line, eof);
+      }
+
+    if (! input_buf.empty ())
+      status = input_buf.copy_chunk (buf, max_size);
+    else
+      status = YY_NULL;
+
+    return status;
+  }
+
+  int
+  push_lexer::fill_flex_buffer (char *buf, unsigned max_size)
+  {
+    int status = 0;
+
+    if (input_buf.empty () && ! input_buf.at_eof ())
+      input_buf.fill (std::string (1, static_cast<char> (1)), false);
+
+    if (! input_buf.empty ())
+      status = input_buf.copy_chunk (buf, max_size);
+    else
+      status = YY_NULL;
+
+    return status;
+  }
 }
-
-void
-octave_base_lexer::display_start_state (void) const
-{
-  std::cerr << "S: ";
-
-  switch (start_state ())
-    {
-    case INITIAL:
-      std::cerr << "INITIAL" << std::endl;
-      break;
-
-    case COMMAND_START:
-      std::cerr << "COMMAND_START" << std::endl;
-      break;
-
-    case MATRIX_START:
-      std::cerr << "MATRIX_START" << std::endl;
-      break;
-
-    case INPUT_FILE_START:
-      std::cerr << "INPUT_FILE_BEGIN" << std::endl;
-      break;
-
-    case BLOCK_COMMENT_START:
-      std::cerr << "BLOCK_COMMENT_START" << std::endl;
-      break;
-
-    case LINE_COMMENT_START:
-      std::cerr << "LINE_COMMENT_START" << std::endl;
-      break;
-
-    case DQ_STRING_START:
-      std::cerr << "DQ_STRING_START" << std::endl;
-      break;
-
-    case SQ_STRING_START:
-      std::cerr << "SQ_STRING_START" << std::endl;
-      break;
-
-    default:
-      std::cerr << "UNKNOWN START STATE!" << std::endl;
-      break;
-    }
-}
-
-int
-octave_base_lexer::handle_op (const char *pattern, int tok, bool bos)
-{
-  lexer_debug (pattern);
-
-  return handle_op_internal (tok, bos, true);
-}
-
-int
-octave_base_lexer::handle_language_extension_op (const char *pattern, int tok,
-                                                 bool bos)
-{
-  lexer_debug (pattern);
-
-  return handle_op_internal (tok, bos, false);
-}
-
-bool
-octave_base_lexer::maybe_unput_comma_before_unary_op (int tok)
-{
-  int prev_tok = previous_token_value ();
-
-  bool unput_comma = false;
-
-  if (whitespace_is_significant () && space_follows_previous_token ())
-    {
-      int c = text_yyinput ();
-      xunput (c);
-
-      bool space_after = (c == ' ' || c == '\t');
-
-      if (! (prev_tok == '[' || prev_tok == '{'
-             || previous_token_is_binop ()
-             || ((tok == '+' || tok == '-') && space_after)))
-        unput_comma = true;
-    }
-
-  return unput_comma;
-}
-
-int
-octave_base_lexer::handle_unary_op (int tok, bool bos)
-{
-  return maybe_unput_comma_before_unary_op (tok)
-    ? -1 : handle_op_internal (tok, bos, true);
-}
-
-int
-octave_base_lexer::handle_language_extension_unary_op (int tok, bool bos)
-{
-  return maybe_unput_comma_before_unary_op (tok)
-    ? -1 : handle_op_internal (tok, bos, false);
-}
-
-int
-octave_base_lexer::handle_op_internal (int tok, bool bos, bool compat)
-{
-  if (! compat)
-    warn_language_extension_operator (flex_yytext ());
-
-  push_token (new token (tok, input_line_number, current_input_column));
-
-  current_input_column += flex_yyleng ();
-  looking_for_object_index = false;
-  at_beginning_of_statement = bos;
-
-  return count_token_internal (tok);
-}
-
-int
-octave_base_lexer::handle_token (const std::string& name, int tok)
-{
-  token *tok_val = new token (tok, name, input_line_number,
-                              current_input_column);
-
-  return handle_token (tok, tok_val);
-}
-
-int
-octave_base_lexer::handle_token (int tok, token *tok_val)
-{
-  if (! tok_val)
-    tok_val = new token (tok, input_line_number, current_input_column);
-
-  push_token (tok_val);
-
-  current_input_column += flex_yyleng ();
-
-  return count_token_internal (tok);
-}
-
-int
-octave_base_lexer::count_token (int tok)
-{
-  token *tok_val = new token (tok, input_line_number, current_input_column);
-
-  push_token (tok_val);
-
-  return count_token_internal (tok);
-}
-
-int
-octave_base_lexer::count_token_internal (int tok)
-{
-  if (tok != '\n')
-    {
-      Vtoken_count++;
-      token_count++;
-    }
-
-  return show_token (tok);
-}
-
-int
-octave_base_lexer::show_token (int tok)
-{
-  if (Vdisplay_tokens)
-    display_token (tok);
-
-  if (lexer_debug_flag)
-    {
-      std::cerr << "R: ";
-      display_token (tok);
-      std::cerr << std::endl;
-    }
-
-  return tok;
-}
-
-void
-octave_base_lexer::enable_fq_identifier (void)
-{
-  push_start_state (FQ_IDENT_START);
-}
-
-int
-octave_lexer::fill_flex_buffer (char *buf, unsigned max_size)
-{
-  int status = 0;
-
-  if (input_buf.empty ())
-    {
-      bool eof = false;
-      current_input_line = input_reader.get_input (eof);
-      input_buf.fill (current_input_line, eof);
-    }
-
-  if (! input_buf.empty ())
-    status = input_buf.copy_chunk (buf, max_size);
-  else
-    status = YY_NULL;
-
-  return status;
-}
-
-int
-octave_push_lexer::fill_flex_buffer (char *buf, unsigned max_size)
-{
-  int status = 0;
-
-  if (input_buf.empty () && ! input_buf.at_eof ())
-    input_buf.fill (std::string (1, static_cast<char> (1)), false);
-
-  if (! input_buf.empty ())
-    status = input_buf.copy_chunk (buf, max_size);
-  else
-    status = YY_NULL;
-
-  return status;
-}
-
--- a/libinterp/parse-tree/oct-parse.in.yy	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/parse-tree/oct-parse.in.yy	Tue Jul 12 14:28:07 2016 -0400
@@ -88,7 +88,7 @@
 
 // Global access to currently active lexer.
 // FIXME: to be removed after more parser+lexer refactoring.
-octave_base_lexer *LEXER = 0;
+octave::base_lexer *LEXER = 0;
 
 // TRUE means we printed messages about reading startup files.
 bool reading_startup_message_printed = false;
@@ -99,7 +99,7 @@
 // Forward declarations for some functions defined at the bottom of
 // the file.
 
-static void yyerror (octave_base_parser& parser, const char *s);
+static void yyerror (octave::base_parser& parser, const char *s);
 
 #define lexer parser.lexer
 #define scanner lexer.scanner
@@ -134,7 +134,7 @@
 
 %define api.pure
 %PUSH_PULL_DECL%
-%parse-param { octave_base_parser& parser }
+%parse-param { octave::base_parser& parser }
 %lex-param { void *scanner }
 
 %union
@@ -1400,7 +1400,7 @@
                         // after parsing the function.  Any function
                         // definitions found in the file have already
                         // been stored in the symbol table or in
-                        // octave_base_parser::primary_fcn_ptr.
+                        // base_parser::primary_fcn_ptr.
 
                         delete $3;
                       }
@@ -2010,60 +2010,63 @@
 #undef lexer
 
 static void
-yyerror (octave_base_parser& parser, const char *s)
+yyerror (octave::base_parser& parser, const char *s)
 {
   parser.bison_error (s);
 }
 
-octave_base_parser::octave_base_parser (octave_base_lexer& lxr)
-  : endfunction_found (false), autoloading (false),
-    fcn_file_from_relative_lookup (false), parsing_subfunctions (false),
-    max_fcn_depth (0), curr_fcn_depth (0), primary_fcn_scope (-1),
-    curr_class_name (), curr_package_name (), function_scopes (),
-    primary_fcn_ptr (0), subfunction_names (), classdef_object (0),
-    stmt_list (0), lexer (lxr), parser_state (yypstate_new ())
-{ }
-
-octave_base_parser::~octave_base_parser (void)
+namespace octave
 {
-  delete stmt_list;
-
-  delete &lexer;
-
-  // FIXME: Deleting the internal Bison parser state structure does
-  // not clean up any partial parse trees in the event of an interrupt or
-  // error.  It's not clear how to safely do that with the C language
-  // parser that Bison generates.  The C++ language parser that Bison
-  // generates would do it for us automatically whenever an exception
-  // is thrown while parsing input, but there is currently no C++
-  // interface for a push parser.
-
-  yypstate_delete (static_cast<yypstate *> (parser_state));
-}
-
-void
-octave_base_parser::reset (void)
-{
-  endfunction_found = false;
-  autoloading = false;
-  fcn_file_from_relative_lookup = false;
-  parsing_subfunctions = false;
-  max_fcn_depth = 0;
-  curr_fcn_depth = 0;
-  primary_fcn_scope = -1;
-  curr_class_name = "";
-  curr_package_name = "";
-  function_scopes.clear ();
-  primary_fcn_ptr  = 0;
-  subfunction_names.clear ();
-
-  delete stmt_list;
-  stmt_list = 0;
-
-  lexer.reset ();
-
-  yypstate_delete (static_cast<yypstate *> (parser_state));
-  parser_state = yypstate_new ();
+  base_parser::base_parser (base_lexer& lxr)
+    : endfunction_found (false), autoloading (false),
+      fcn_file_from_relative_lookup (false), parsing_subfunctions (false),
+      max_fcn_depth (0), curr_fcn_depth (0), primary_fcn_scope (-1),
+      curr_class_name (), curr_package_name (), function_scopes (),
+      primary_fcn_ptr (0), subfunction_names (), classdef_object (0),
+      stmt_list (0), lexer (lxr), parser_state (yypstate_new ())
+  { }
+
+  base_parser::~base_parser (void)
+  {
+    delete stmt_list;
+
+    delete &lexer;
+
+    // FIXME: Deleting the internal Bison parser state structure does
+    // not clean up any partial parse trees in the event of an interrupt or
+    // error.  It's not clear how to safely do that with the C language
+    // parser that Bison generates.  The C++ language parser that Bison
+    // generates would do it for us automatically whenever an exception
+    // is thrown while parsing input, but there is currently no C++
+    // interface for a push parser.
+
+    yypstate_delete (static_cast<yypstate *> (parser_state));
+  }
+
+  void
+  base_parser::reset (void)
+  {
+    endfunction_found = false;
+    autoloading = false;
+    fcn_file_from_relative_lookup = false;
+    parsing_subfunctions = false;
+    max_fcn_depth = 0;
+    curr_fcn_depth = 0;
+    primary_fcn_scope = -1;
+    curr_class_name = "";
+    curr_package_name = "";
+    function_scopes.clear ();
+    primary_fcn_ptr  = 0;
+    subfunction_names.clear ();
+
+    delete stmt_list;
+    stmt_list = 0;
+
+    lexer.reset ();
+
+    yypstate_delete (static_cast<yypstate *> (parser_state));
+    parser_state = yypstate_new ();
+  }
 }
 
 // Error mesages for mismatched end tokens.
@@ -2139,1015 +2142,1230 @@
   return retval;
 }
 
-void
-octave_base_parser::end_token_error (token *tok, token::end_tok_type expected)
-{
-  std::string msg = ("'" + end_token_as_string (expected)
-                     + "' command matched by '"
-                     + end_token_as_string (tok->ettype ()) + "'");
-
-  bison_error (msg, tok->line (), tok->column ());
-}
-
-
-// Check to see that end tokens are properly matched.
-
-bool
-octave_base_parser::end_token_ok (token *tok, token::end_tok_type expected)
-{
-  token::end_tok_type ettype = tok->ettype ();
-
-  return ettype == expected || ettype == token::simple_end;
-}
-
-// Maybe print a warning if an assignment expression is used as the
-// test in a logical expression.
-
-void
-octave_base_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
-{
-  if (expr->is_assignment_expression ()
-      && expr->paren_count () < 2)
-    {
-      if (lexer.fcn_file_full_name.empty ())
-        warning_with_id
-          ("Octave:assign-as-truth-value",
-           "suggest parenthesis around assignment used as truth value");
-      else
-        warning_with_id
-          ("Octave:assign-as-truth-value",
-           "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'",
-           expr->line (), expr->column (), lexer.fcn_file_full_name.c_str ());
-    }
-}
-
-// Maybe print a warning about switch labels that aren't constants.
-
-void
-octave_base_parser::maybe_warn_variable_switch_label (tree_expression *expr)
-{
-  if (! expr->is_constant ())
-    {
-      if (lexer.fcn_file_full_name.empty ())
-        warning_with_id ("Octave:variable-switch-label",
-                         "variable switch label");
-      else
-        warning_with_id
-          ("Octave:variable-switch-label",
-           "variable switch label near line %d, column %d in file '%s'",
-           expr->line (), expr->column (), lexer.fcn_file_full_name.c_str ());
-    }
-}
-
-// Finish building a range.
-
-tree_expression *
-octave_base_parser::finish_colon_expression (tree_colon_expression *e)
-{
-  tree_expression *retval = e;
-
-  octave::unwind_protect frame;
-
-  frame.protect_var (discard_error_messages);
-  frame.protect_var (discard_warning_messages);
-
-  discard_error_messages = true;
-  discard_warning_messages = true;
-
-  tree_expression *base = e->base ();
-  tree_expression *limit = e->limit ();
-  tree_expression *incr = e->increment ();
-
-  if (base)
-    {
-      if (limit)
-        {
-          if (base->is_constant () && limit->is_constant ()
-              && (! incr || (incr && incr->is_constant ())))
-            {
-              try
-                {
-                  octave_value tmp = e->rvalue1 ();
-
-                  tree_constant *tc_retval
-                    = new tree_constant (tmp, base->line (), base->column ());
-
-                  std::ostringstream buf;
-
-                  tree_print_code tpc (buf);
-
-                  e->accept (tpc);
-
-                  tc_retval->stash_original_text (buf.str ());
-
-                  delete e;
-
-                  retval = tc_retval;
-                }
-              catch (const octave_execution_exception&)
-                {
-                  recover_from_exception ();
-                }
-            }
-        }
-      else
-        {
-          e->preserve_base ();
-          delete e;
-
-          retval = base;
-        }
-    }
-
-  return retval;
-}
-
-// Make a constant.
-
-tree_constant *
-octave_base_parser::make_constant (int op, token *tok_val)
-{
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  tree_constant *retval = 0;
-
-  switch (op)
-    {
-    case NUM:
-      {
-        octave_value tmp (tok_val->number ());
-        retval = new tree_constant (tmp, l, c);
-        retval->stash_original_text (tok_val->text_rep ());
-      }
-      break;
-
-    case IMAG_NUM:
-      {
-        octave_value tmp (Complex (0.0, tok_val->number ()));
-        retval = new tree_constant (tmp, l, c);
-        retval->stash_original_text (tok_val->text_rep ());
-      }
-      break;
-
-    case DQ_STRING:
-    case SQ_STRING:
-      {
-        std::string txt = tok_val->text ();
-
-        char delim = op == DQ_STRING ? '"' : '\'';
-        octave_value tmp (txt, delim);
-
-        if (txt.empty ())
-          {
-            if (op == DQ_STRING)
-              tmp = octave_null_str::instance;
-            else
-              tmp = octave_null_sq_str::instance;
-          }
-
-        retval = new tree_constant (tmp, l, c);
-
-        if (op == DQ_STRING)
-          txt = undo_string_escapes (txt);
-
-        // FIXME: maybe this should also be handled by
-        // tok_val->text_rep () for character strings?
-        retval->stash_original_text (delim + txt + delim);
-      }
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  return retval;
-}
-
-// Make a function handle.
-
-tree_fcn_handle *
-octave_base_parser::make_fcn_handle (token *tok_val)
-{
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  tree_fcn_handle *retval = new tree_fcn_handle (tok_val->text (), l, c);
-
-  return retval;
-}
-
-// Make an anonymous function handle.
-
-tree_anon_fcn_handle *
-octave_base_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
-                                          tree_statement *stmt)
-{
-  // FIXME: need to get these from the location of the @ symbol.
-  int l = lexer.input_line_number;
-  int c = lexer.current_input_column;
-
-  tree_parameter_list *ret_list = 0;
-
-  symbol_table::scope_id fcn_scope = lexer.symtab_context.curr_scope ();
-
-  lexer.symtab_context.pop ();
-
-  stmt->set_print_flag (false);
-
-  tree_statement_list *body = new tree_statement_list (stmt);
-
-  body->mark_as_anon_function_body ();
-
-  tree_anon_fcn_handle *retval
-    = new tree_anon_fcn_handle (param_list, ret_list, body, fcn_scope, l, c);
-  // FIXME: Stash the filename.  This does not work and produces
-  // errors when executed.
-  //retval->stash_file_name (lexer.fcn_file_name);
-
-  return retval;
-}
-
-// Build a binary expression.
-
-tree_expression *
-octave_base_parser::make_binary_op (int op, tree_expression *op1,
-                                    token *tok_val, tree_expression *op2)
+namespace octave
 {
-  octave_value::binary_op t = octave_value::unknown_binary_op;
-
-  switch (op)
-    {
-    case POW:
-      t = octave_value::op_pow;
-      break;
-
-    case EPOW:
-      t = octave_value::op_el_pow;
-      break;
-
-    case '+':
-      t = octave_value::op_add;
-      break;
-
-    case '-':
-      t = octave_value::op_sub;
-      break;
-
-    case '*':
-      t = octave_value::op_mul;
-      break;
-
-    case '/':
-      t = octave_value::op_div;
-      break;
-
-    case EMUL:
-      t = octave_value::op_el_mul;
-      break;
-
-    case EDIV:
-      t = octave_value::op_el_div;
-      break;
-
-    case LEFTDIV:
-      t = octave_value::op_ldiv;
-      break;
-
-    case ELEFTDIV:
-      t = octave_value::op_el_ldiv;
-      break;
-
-    case EXPR_LT:
-      t = octave_value::op_lt;
-      break;
-
-    case EXPR_LE:
-      t = octave_value::op_le;
-      break;
-
-    case EXPR_EQ:
-      t = octave_value::op_eq;
-      break;
-
-    case EXPR_GE:
-      t = octave_value::op_ge;
-      break;
-
-    case EXPR_GT:
-      t = octave_value::op_gt;
-      break;
-
-    case EXPR_NE:
-      t = octave_value::op_ne;
-      break;
-
-    case EXPR_AND:
-      t = octave_value::op_el_and;
-      break;
-
-    case EXPR_OR:
-      t = octave_value::op_el_or;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  return maybe_compound_binary_expression (op1, op2, l, c, t);
-}
-
-// Build a boolean expression.
-
-tree_expression *
-octave_base_parser::make_boolean_op (int op, tree_expression *op1,
-                                     token *tok_val, tree_expression *op2)
-{
-  tree_boolean_expression::type t;
-
-  switch (op)
-    {
-    case EXPR_AND_AND:
-      t = tree_boolean_expression::bool_and;
-      break;
-
-    case EXPR_OR_OR:
-      t = tree_boolean_expression::bool_or;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  return new tree_boolean_expression (op1, op2, l, c, t);
-}
-
-// Build a prefix expression.
-
-tree_expression *
-octave_base_parser::make_prefix_op (int op, tree_expression *op1,
-                                    token *tok_val)
-{
-  octave_value::unary_op t = octave_value::unknown_unary_op;
-
-  switch (op)
-    {
-    case EXPR_NOT:
-      t = octave_value::op_not;
-      break;
-
-    case '+':
-      t = octave_value::op_uplus;
-      break;
-
-    case '-':
-      t = octave_value::op_uminus;
-      break;
-
-    case PLUS_PLUS:
-      t = octave_value::op_incr;
-      break;
-
-    case MINUS_MINUS:
-      t = octave_value::op_decr;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  return new tree_prefix_expression (op1, l, c, t);
-}
-
-// Build a postfix expression.
-
-tree_expression *
-octave_base_parser::make_postfix_op (int op, tree_expression *op1,
-                                     token *tok_val)
-{
-  octave_value::unary_op t = octave_value::unknown_unary_op;
-
-  switch (op)
-    {
-    case HERMITIAN:
-      t = octave_value::op_hermitian;
-      break;
-
-    case TRANSPOSE:
-      t = octave_value::op_transpose;
-      break;
-
-    case PLUS_PLUS:
-      t = octave_value::op_incr;
-      break;
-
-    case MINUS_MINUS:
-      t = octave_value::op_decr;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  return new tree_postfix_expression (op1, l, c, t);
-}
-
-// Build an unwind-protect command.
-
-tree_command *
-octave_base_parser::make_unwind_command (token *unwind_tok,
-                                         tree_statement_list *body,
-                                         tree_statement_list *cleanup_stmts,
-                                         token *end_tok,
-                                         octave_comment_list *lc,
-                                         octave_comment_list *mc)
-{
-  tree_command *retval = 0;
-
-  if (end_token_ok (end_tok, token::unwind_protect_end))
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      int l = unwind_tok->line ();
-      int c = unwind_tok->column ();
-
-      retval = new tree_unwind_protect_command (body, cleanup_stmts,
-                                                lc, mc, tc, l, c);
-    }
-  else
-    {
-      delete body;
-      delete cleanup_stmts;
-
-      end_token_error (end_tok, token::unwind_protect_end);
-    }
-
-  return retval;
-}
-
-// Build a try-catch command.
-
-tree_command *
-octave_base_parser::make_try_command (token *try_tok,
+  void
+  base_parser::end_token_error (token *tok, token::end_tok_type expected)
+  {
+    std::string msg = ("'" + end_token_as_string (expected)
+                       + "' command matched by '"
+                       + end_token_as_string (tok->ettype ()) + "'");
+
+    bison_error (msg, tok->line (), tok->column ());
+  }
+
+  // Check to see that end tokens are properly matched.
+
+  bool
+  base_parser::end_token_ok (token *tok, token::end_tok_type expected)
+  {
+    token::end_tok_type ettype = tok->ettype ();
+
+    return ettype == expected || ettype == token::simple_end;
+  }
+
+  // Maybe print a warning if an assignment expression is used as the
+  // test in a logical expression.
+
+  void
+  base_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
+  {
+    if (expr->is_assignment_expression ()
+        && expr->paren_count () < 2)
+      {
+        if (lexer.fcn_file_full_name.empty ())
+          warning_with_id
+            ("Octave:assign-as-truth-value",
+             "suggest parenthesis around assignment used as truth value");
+        else
+          warning_with_id
+            ("Octave:assign-as-truth-value",
+             "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'",
+             expr->line (), expr->column (), lexer.fcn_file_full_name.c_str ());
+      }
+  }
+
+  // Maybe print a warning about switch labels that aren't constants.
+
+  void
+  base_parser::maybe_warn_variable_switch_label (tree_expression *expr)
+  {
+    if (! expr->is_constant ())
+      {
+        if (lexer.fcn_file_full_name.empty ())
+          warning_with_id ("Octave:variable-switch-label",
+                           "variable switch label");
+        else
+          warning_with_id
+            ("Octave:variable-switch-label",
+             "variable switch label near line %d, column %d in file '%s'",
+             expr->line (), expr->column (), lexer.fcn_file_full_name.c_str ());
+      }
+  }
+
+  // Finish building a range.
+
+  tree_expression *
+  base_parser::finish_colon_expression (tree_colon_expression *e)
+  {
+    tree_expression *retval = e;
+
+    octave::unwind_protect frame;
+
+    frame.protect_var (discard_error_messages);
+    frame.protect_var (discard_warning_messages);
+
+    discard_error_messages = true;
+    discard_warning_messages = true;
+
+    tree_expression *base = e->base ();
+    tree_expression *limit = e->limit ();
+    tree_expression *incr = e->increment ();
+
+    if (base)
+      {
+        if (limit)
+          {
+            if (base->is_constant () && limit->is_constant ()
+                && (! incr || (incr && incr->is_constant ())))
+              {
+                try
+                  {
+                    octave_value tmp = e->rvalue1 ();
+
+                    tree_constant *tc_retval
+                      = new tree_constant (tmp, base->line (), base->column ());
+
+                    std::ostringstream buf;
+
+                    tree_print_code tpc (buf);
+
+                    e->accept (tpc);
+
+                    tc_retval->stash_original_text (buf.str ());
+
+                    delete e;
+
+                    retval = tc_retval;
+                  }
+                catch (const octave_execution_exception&)
+                  {
+                    recover_from_exception ();
+                  }
+              }
+          }
+        else
+          {
+            e->preserve_base ();
+            delete e;
+
+            retval = base;
+          }
+      }
+
+    return retval;
+  }
+
+  // Make a constant.
+
+  tree_constant *
+  base_parser::make_constant (int op, token *tok_val)
+  {
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    tree_constant *retval = 0;
+
+    switch (op)
+      {
+      case NUM:
+        {
+          octave_value tmp (tok_val->number ());
+          retval = new tree_constant (tmp, l, c);
+          retval->stash_original_text (tok_val->text_rep ());
+        }
+        break;
+
+      case IMAG_NUM:
+        {
+          octave_value tmp (Complex (0.0, tok_val->number ()));
+          retval = new tree_constant (tmp, l, c);
+          retval->stash_original_text (tok_val->text_rep ());
+        }
+        break;
+
+      case DQ_STRING:
+      case SQ_STRING:
+        {
+          std::string txt = tok_val->text ();
+
+          char delim = op == DQ_STRING ? '"' : '\'';
+          octave_value tmp (txt, delim);
+
+          if (txt.empty ())
+            {
+              if (op == DQ_STRING)
+                tmp = octave_null_str::instance;
+              else
+                tmp = octave_null_sq_str::instance;
+            }
+
+          retval = new tree_constant (tmp, l, c);
+
+          if (op == DQ_STRING)
+            txt = undo_string_escapes (txt);
+
+          // FIXME: maybe this should also be handled by
+          // tok_val->text_rep () for character strings?
+          retval->stash_original_text (delim + txt + delim);
+        }
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    return retval;
+  }
+
+  // Make a function handle.
+
+  tree_fcn_handle *
+  base_parser::make_fcn_handle (token *tok_val)
+  {
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    tree_fcn_handle *retval = new tree_fcn_handle (tok_val->text (), l, c);
+
+    return retval;
+  }
+
+  // Make an anonymous function handle.
+
+  tree_anon_fcn_handle *
+  base_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
+                                     tree_statement *stmt)
+  {
+    // FIXME: need to get these from the location of the @ symbol.
+    int l = lexer.input_line_number;
+    int c = lexer.current_input_column;
+
+    tree_parameter_list *ret_list = 0;
+
+    symbol_table::scope_id fcn_scope = lexer.symtab_context.curr_scope ();
+
+    lexer.symtab_context.pop ();
+
+    stmt->set_print_flag (false);
+
+    tree_statement_list *body = new tree_statement_list (stmt);
+
+    body->mark_as_anon_function_body ();
+
+    tree_anon_fcn_handle *retval
+      = new tree_anon_fcn_handle (param_list, ret_list, body, fcn_scope, l, c);
+    // FIXME: Stash the filename.  This does not work and produces
+    // errors when executed.
+    //retval->stash_file_name (lexer.fcn_file_name);
+
+    return retval;
+  }
+
+  // Build a binary expression.
+
+  tree_expression *
+  base_parser::make_binary_op (int op, tree_expression *op1,
+                               token *tok_val, tree_expression *op2)
+  {
+    octave_value::binary_op t = octave_value::unknown_binary_op;
+
+    switch (op)
+      {
+      case POW:
+        t = octave_value::op_pow;
+        break;
+
+      case EPOW:
+        t = octave_value::op_el_pow;
+        break;
+
+      case '+':
+        t = octave_value::op_add;
+        break;
+
+      case '-':
+        t = octave_value::op_sub;
+        break;
+
+      case '*':
+        t = octave_value::op_mul;
+        break;
+
+      case '/':
+        t = octave_value::op_div;
+        break;
+
+      case EMUL:
+        t = octave_value::op_el_mul;
+        break;
+
+      case EDIV:
+        t = octave_value::op_el_div;
+        break;
+
+      case LEFTDIV:
+        t = octave_value::op_ldiv;
+        break;
+
+      case ELEFTDIV:
+        t = octave_value::op_el_ldiv;
+        break;
+
+      case EXPR_LT:
+        t = octave_value::op_lt;
+        break;
+
+      case EXPR_LE:
+        t = octave_value::op_le;
+        break;
+
+      case EXPR_EQ:
+        t = octave_value::op_eq;
+        break;
+
+      case EXPR_GE:
+        t = octave_value::op_ge;
+        break;
+
+      case EXPR_GT:
+        t = octave_value::op_gt;
+        break;
+
+      case EXPR_NE:
+        t = octave_value::op_ne;
+        break;
+
+      case EXPR_AND:
+        t = octave_value::op_el_and;
+        break;
+
+      case EXPR_OR:
+        t = octave_value::op_el_or;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    return maybe_compound_binary_expression (op1, op2, l, c, t);
+  }
+
+  // Build a boolean expression.
+
+  tree_expression *
+  base_parser::make_boolean_op (int op, tree_expression *op1,
+                                token *tok_val, tree_expression *op2)
+  {
+    tree_boolean_expression::type t;
+
+    switch (op)
+      {
+      case EXPR_AND_AND:
+        t = tree_boolean_expression::bool_and;
+        break;
+
+      case EXPR_OR_OR:
+        t = tree_boolean_expression::bool_or;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    return new tree_boolean_expression (op1, op2, l, c, t);
+  }
+
+  // Build a prefix expression.
+
+  tree_expression *
+  base_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val)
+  {
+    octave_value::unary_op t = octave_value::unknown_unary_op;
+
+    switch (op)
+      {
+      case EXPR_NOT:
+        t = octave_value::op_not;
+        break;
+
+      case '+':
+        t = octave_value::op_uplus;
+        break;
+
+      case '-':
+        t = octave_value::op_uminus;
+        break;
+
+      case PLUS_PLUS:
+        t = octave_value::op_incr;
+        break;
+
+      case MINUS_MINUS:
+        t = octave_value::op_decr;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    return new tree_prefix_expression (op1, l, c, t);
+  }
+
+  // Build a postfix expression.
+
+  tree_expression *
+  base_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val)
+  {
+    octave_value::unary_op t = octave_value::unknown_unary_op;
+
+    switch (op)
+      {
+      case HERMITIAN:
+        t = octave_value::op_hermitian;
+        break;
+
+      case TRANSPOSE:
+        t = octave_value::op_transpose;
+        break;
+
+      case PLUS_PLUS:
+        t = octave_value::op_incr;
+        break;
+
+      case MINUS_MINUS:
+        t = octave_value::op_decr;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    return new tree_postfix_expression (op1, l, c, t);
+  }
+
+  // Build an unwind-protect command.
+
+  tree_command *
+  base_parser::make_unwind_command (token *unwind_tok,
+                                    tree_statement_list *body,
+                                    tree_statement_list *cleanup_stmts,
+                                    token *end_tok,
+                                    octave_comment_list *lc,
+                                    octave_comment_list *mc)
+  {
+    tree_command *retval = 0;
+
+    if (end_token_ok (end_tok, token::unwind_protect_end))
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        int l = unwind_tok->line ();
+        int c = unwind_tok->column ();
+
+        retval = new tree_unwind_protect_command (body, cleanup_stmts,
+                                                  lc, mc, tc, l, c);
+      }
+    else
+      {
+        delete body;
+        delete cleanup_stmts;
+
+        end_token_error (end_tok, token::unwind_protect_end);
+      }
+
+    return retval;
+  }
+
+  // Build a try-catch command.
+
+  tree_command *
+  base_parser::make_try_command (token *try_tok,
+                                 tree_statement_list *body,
+                                 char catch_sep,
+                                 tree_statement_list *cleanup_stmts,
+                                 token *end_tok,
+                                 octave_comment_list *lc,
+                                 octave_comment_list *mc)
+  {
+    tree_command *retval = 0;
+
+    if (end_token_ok (end_tok, token::try_catch_end))
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        int l = try_tok->line ();
+        int c = try_tok->column ();
+
+        tree_identifier *id = 0;
+
+        if (! catch_sep && cleanup_stmts && ! cleanup_stmts->empty ())
+          {
+            tree_statement *stmt = cleanup_stmts->front ();
+
+            if (stmt)
+              {
+                tree_expression *expr = stmt->expression ();
+
+                if (expr && expr->is_identifier ())
+                  {
+                    id = dynamic_cast<tree_identifier *> (expr);
+
+                    cleanup_stmts->pop_front ();
+
+                    stmt->set_expression (0);
+                    delete stmt;
+                  }
+              }
+          }
+
+        retval = new tree_try_catch_command (body, cleanup_stmts, id,
+                                             lc, mc, tc, l, c);
+      }
+    else
+      {
+        delete body;
+        delete cleanup_stmts;
+
+        end_token_error (end_tok, token::try_catch_end);
+      }
+
+    return retval;
+  }
+
+  // Build a while command.
+
+  tree_command *
+  base_parser::make_while_command (token *while_tok,
+                                   tree_expression *expr,
+                                   tree_statement_list *body,
+                                   token *end_tok,
+                                   octave_comment_list *lc)
+  {
+    tree_command *retval = 0;
+
+    maybe_warn_assign_as_truth_value (expr);
+
+    if (end_token_ok (end_tok, token::while_end))
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        lexer.looping--;
+
+        int l = while_tok->line ();
+        int c = while_tok->column ();
+
+        retval = new tree_while_command (expr, body, lc, tc, l, c);
+      }
+    else
+      {
+        delete expr;
+        delete body;
+
+        end_token_error (end_tok, token::while_end);
+      }
+
+    return retval;
+  }
+
+  // Build a do-until command.
+
+  tree_command *
+  base_parser::make_do_until_command (token *until_tok,
                                       tree_statement_list *body,
-                                      char catch_sep,
-                                      tree_statement_list *cleanup_stmts,
-                                      token *end_tok,
-                                      octave_comment_list *lc,
-                                      octave_comment_list *mc)
-{
-  tree_command *retval = 0;
-
-  if (end_token_ok (end_tok, token::try_catch_end))
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      int l = try_tok->line ();
-      int c = try_tok->column ();
-
-      tree_identifier *id = 0;
-
-      if (! catch_sep && cleanup_stmts && ! cleanup_stmts->empty ())
-        {
-          tree_statement *stmt = cleanup_stmts->front ();
-
-          if (stmt)
-            {
-              tree_expression *expr = stmt->expression ();
-
-              if (expr && expr->is_identifier ())
-                {
-                  id = dynamic_cast<tree_identifier *> (expr);
-
-                  cleanup_stmts->pop_front ();
-
-                  stmt->set_expression (0);
-                  delete stmt;
-                }
-            }
-        }
-
-      retval = new tree_try_catch_command (body, cleanup_stmts, id,
-                                           lc, mc, tc, l, c);
-    }
-  else
-    {
-      delete body;
-      delete cleanup_stmts;
-
-      end_token_error (end_tok, token::try_catch_end);
-    }
-
-  return retval;
-}
-
-// Build a while command.
-
-tree_command *
-octave_base_parser::make_while_command (token *while_tok,
-                                        tree_expression *expr,
-                                        tree_statement_list *body,
-                                        token *end_tok,
-                                        octave_comment_list *lc)
-{
-  tree_command *retval = 0;
-
-  maybe_warn_assign_as_truth_value (expr);
-
-  if (end_token_ok (end_tok, token::while_end))
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      lexer.looping--;
-
-      int l = while_tok->line ();
-      int c = while_tok->column ();
-
-      retval = new tree_while_command (expr, body, lc, tc, l, c);
-    }
-  else
-    {
-      delete expr;
-      delete body;
-
-      end_token_error (end_tok, token::while_end);
-    }
-
-  return retval;
-}
-
-// Build a do-until command.
-
-tree_command *
-octave_base_parser::make_do_until_command (token *until_tok,
-                                           tree_statement_list *body,
-                                           tree_expression *expr,
-                                           octave_comment_list *lc)
-{
-  maybe_warn_assign_as_truth_value (expr);
-
-  octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-  lexer.looping--;
-
-  int l = until_tok->line ();
-  int c = until_tok->column ();
-
-  return new tree_do_until_command (expr, body, lc, tc, l, c);
-}
-
-// Build a for command.
-
-tree_command *
-octave_base_parser::make_for_command (int tok_id, token *for_tok,
-                                      tree_argument_list *lhs,
                                       tree_expression *expr,
-                                      tree_expression *maxproc,
-                                      tree_statement_list *body,
+                                      octave_comment_list *lc)
+  {
+    maybe_warn_assign_as_truth_value (expr);
+
+    octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+    lexer.looping--;
+
+    int l = until_tok->line ();
+    int c = until_tok->column ();
+
+    return new tree_do_until_command (expr, body, lc, tc, l, c);
+  }
+
+  // Build a for command.
+
+  tree_command *
+  base_parser::make_for_command (int tok_id, token *for_tok,
+                                 tree_argument_list *lhs,
+                                 tree_expression *expr,
+                                 tree_expression *maxproc,
+                                 tree_statement_list *body,
+                                 token *end_tok,
+                                 octave_comment_list *lc)
+  {
+    tree_command *retval = 0;
+
+    bool parfor = tok_id == PARFOR;
+
+    if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
+      {
+        expr->mark_as_for_cmd_expr ();
+
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        lexer.looping--;
+
+        int l = for_tok->line ();
+        int c = for_tok->column ();
+
+        if (lhs->length () == 1)
+          {
+            tree_expression *tmp = lhs->remove_front ();
+
+            retval = new tree_simple_for_command (parfor, tmp, expr, maxproc,
+                                                  body, lc, tc, l, c);
+
+            delete lhs;
+          }
+        else
+          {
+            if (parfor)
+              {
+                delete lhs;
+                delete expr;
+                delete maxproc;
+                delete body;
+
+                bison_error ("invalid syntax for parfor statement");
+              }
+            else
+              retval = new tree_complex_for_command (lhs, expr, body,
+                                                     lc, tc, l, c);
+          }
+      }
+    else
+      {
+        delete lhs;
+        delete expr;
+        delete maxproc;
+        delete body;
+
+        end_token_error (end_tok, parfor ? token::parfor_end : token::for_end);
+      }
+
+    return retval;
+  }
+
+  // Build a break command.
+
+  tree_command *
+  base_parser::make_break_command (token *break_tok)
+  {
+    int l = break_tok->line ();
+    int c = break_tok->column ();
+
+    return new tree_break_command (l, c);
+  }
+
+  // Build a continue command.
+
+  tree_command *
+  base_parser::make_continue_command (token *continue_tok)
+  {
+    int l = continue_tok->line ();
+    int c = continue_tok->column ();
+
+    return new tree_continue_command (l, c);
+  }
+
+  // Build a return command.
+
+  tree_command *
+  base_parser::make_return_command (token *return_tok)
+  {
+    int l = return_tok->line ();
+    int c = return_tok->column ();
+
+    return new tree_return_command (l, c);
+  }
+
+  // Start an if command.
+
+  tree_if_command_list *
+  base_parser::start_if_command (tree_expression *expr,
+                                 tree_statement_list *list)
+  {
+    maybe_warn_assign_as_truth_value (expr);
+
+    tree_if_clause *t = new tree_if_clause (expr, list);
+
+    return new tree_if_command_list (t);
+  }
+
+  // Finish an if command.
+
+  tree_if_command *
+  base_parser::finish_if_command (token *if_tok,
+                                  tree_if_command_list *list,
+                                  token *end_tok,
+                                  octave_comment_list *lc)
+  {
+    tree_if_command *retval = 0;
+
+    if (end_token_ok (end_tok, token::if_end))
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        int l = if_tok->line ();
+        int c = if_tok->column ();
+
+        if (list && ! list->empty ())
+          {
+            tree_if_clause *elt = list->front ();
+
+            if (elt)
+              {
+                elt->line (l);
+                elt->column (c);
+              }
+          }
+
+        retval = new tree_if_command (list, lc, tc, l, c);
+      }
+    else
+      {
+        delete list;
+
+        end_token_error (end_tok, token::if_end);
+      }
+
+    return retval;
+  }
+
+  // Build an elseif clause.
+
+  tree_if_clause *
+  base_parser::make_elseif_clause (token *elseif_tok,
+                                   tree_expression *expr,
+                                   tree_statement_list *list,
+                                   octave_comment_list *lc)
+  {
+    maybe_warn_assign_as_truth_value (expr);
+
+    int l = elseif_tok->line ();
+    int c = elseif_tok->column ();
+
+    return new tree_if_clause (expr, list, lc, l, c);
+  }
+
+  // Finish a switch command.
+
+  tree_switch_command *
+  base_parser::finish_switch_command (token *switch_tok,
+                                      tree_expression *expr,
+                                      tree_switch_case_list *list,
                                       token *end_tok,
                                       octave_comment_list *lc)
-{
-  tree_command *retval = 0;
-
-  bool parfor = tok_id == PARFOR;
-
-  if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
-    {
-      expr->mark_as_for_cmd_expr ();
-
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      lexer.looping--;
-
-      int l = for_tok->line ();
-      int c = for_tok->column ();
-
-      if (lhs->length () == 1)
-        {
-          tree_expression *tmp = lhs->remove_front ();
-
-          retval = new tree_simple_for_command (parfor, tmp, expr, maxproc,
-                                                body, lc, tc, l, c);
-
-          delete lhs;
-        }
-      else
-        {
-          if (parfor)
-            {
-              delete lhs;
-              delete expr;
-              delete maxproc;
-              delete body;
-
-              bison_error ("invalid syntax for parfor statement");
-            }
-          else
-            retval = new tree_complex_for_command (lhs, expr, body,
-                                                   lc, tc, l, c);
-        }
-    }
-  else
-    {
-      delete lhs;
-      delete expr;
-      delete maxproc;
-      delete body;
-
-      end_token_error (end_tok, parfor ? token::parfor_end : token::for_end);
-    }
-
-  return retval;
-}
-
-// Build a break command.
-
-tree_command *
-octave_base_parser::make_break_command (token *break_tok)
-{
-  int l = break_tok->line ();
-  int c = break_tok->column ();
-
-  return new tree_break_command (l, c);
-}
-
-// Build a continue command.
-
-tree_command *
-octave_base_parser::make_continue_command (token *continue_tok)
-{
-  int l = continue_tok->line ();
-  int c = continue_tok->column ();
-
-  return new tree_continue_command (l, c);
-}
-
-// Build a return command.
-
-tree_command *
-octave_base_parser::make_return_command (token *return_tok)
-{
-  int l = return_tok->line ();
-  int c = return_tok->column ();
-
-  return new tree_return_command (l, c);
-}
-
-// Start an if command.
-
-tree_if_command_list *
-octave_base_parser::start_if_command (tree_expression *expr,
-                                      tree_statement_list *list)
-{
-  maybe_warn_assign_as_truth_value (expr);
-
-  tree_if_clause *t = new tree_if_clause (expr, list);
-
-  return new tree_if_command_list (t);
-}
-
-// Finish an if command.
-
-tree_if_command *
-octave_base_parser::finish_if_command (token *if_tok,
-                                       tree_if_command_list *list,
-                                       token *end_tok,
-                                       octave_comment_list *lc)
-{
-  tree_if_command *retval = 0;
-
-  if (end_token_ok (end_tok, token::if_end))
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      int l = if_tok->line ();
-      int c = if_tok->column ();
-
-      if (list && ! list->empty ())
-        {
-          tree_if_clause *elt = list->front ();
-
-          if (elt)
-            {
-              elt->line (l);
-              elt->column (c);
-            }
-        }
-
-      retval = new tree_if_command (list, lc, tc, l, c);
-    }
-  else
-    {
-      delete list;
-
-      end_token_error (end_tok, token::if_end);
-    }
-
-  return retval;
-}
-
-// Build an elseif clause.
-
-tree_if_clause *
-octave_base_parser::make_elseif_clause (token *elseif_tok,
-                                        tree_expression *expr,
-                                        tree_statement_list *list,
-                                        octave_comment_list *lc)
-{
-  maybe_warn_assign_as_truth_value (expr);
-
-  int l = elseif_tok->line ();
-  int c = elseif_tok->column ();
-
-  return new tree_if_clause (expr, list, lc, l, c);
-}
-
-// Finish a switch command.
-
-tree_switch_command *
-octave_base_parser::finish_switch_command (token *switch_tok,
-                                           tree_expression *expr,
-                                           tree_switch_case_list *list,
-                                           token *end_tok,
-                                           octave_comment_list *lc)
-{
-  tree_switch_command *retval = 0;
-
-  if (end_token_ok (end_tok, token::switch_end))
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      int l = switch_tok->line ();
-      int c = switch_tok->column ();
-
-      if (list && ! list->empty ())
-        {
-          tree_switch_case *elt = list->front ();
-
-          if (elt)
-            {
-              elt->line (l);
-              elt->column (c);
-            }
-        }
-
-      retval = new tree_switch_command (expr, list, lc, tc, l, c);
-    }
-  else
-    {
-      delete expr;
-      delete list;
-
-      end_token_error (end_tok, token::switch_end);
-    }
-
-  return retval;
-}
-
-// Build a switch case.
-
-tree_switch_case *
-octave_base_parser::make_switch_case (token *case_tok,
-                                      tree_expression *expr,
-                                      tree_statement_list *list,
-                                      octave_comment_list *lc)
-{
-  maybe_warn_variable_switch_label (expr);
-
-  int l = case_tok->line ();
-  int c = case_tok->column ();
-
-  return new tree_switch_case (expr, list, lc, l, c);
-}
-
-// Build an assignment to a variable.
-
-tree_expression *
-octave_base_parser::make_assign_op (int op, tree_argument_list *lhs,
-                                    token *eq_tok, tree_expression *rhs)
-{
-  octave_value::assign_op t = octave_value::unknown_assign_op;
-
-  switch (op)
-    {
-    case '=':
-      t = octave_value::op_asn_eq;
-      break;
-
-    case ADD_EQ:
-      t = octave_value::op_add_eq;
-      break;
-
-    case SUB_EQ:
-      t = octave_value::op_sub_eq;
-      break;
-
-    case MUL_EQ:
-      t = octave_value::op_mul_eq;
-      break;
-
-    case DIV_EQ:
-      t = octave_value::op_div_eq;
-      break;
-
-    case LEFTDIV_EQ:
-      t = octave_value::op_ldiv_eq;
-      break;
-
-    case POW_EQ:
-      t = octave_value::op_pow_eq;
-      break;
-
-    case EMUL_EQ:
-      t = octave_value::op_el_mul_eq;
-      break;
-
-    case EDIV_EQ:
-      t = octave_value::op_el_div_eq;
-      break;
-
-    case ELEFTDIV_EQ:
-      t = octave_value::op_el_ldiv_eq;
-      break;
-
-    case EPOW_EQ:
-      t = octave_value::op_el_pow_eq;
-      break;
-
-    case AND_EQ:
-      t = octave_value::op_el_and_eq;
-      break;
-
-    case OR_EQ:
-      t = octave_value::op_el_or_eq;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = eq_tok->line ();
-  int c = eq_tok->column ();
-
-  if (! lhs->is_simple_assign_lhs () && t != octave_value::op_asn_eq)
-    {
-      // Multiple assignments like [x,y] OP= rhs are only valid for
-      // '=', not '+=', etc.
-
-      delete lhs;
-      delete rhs;
-
-      bison_error ("computed multiple assignment not allowed", l, c);
-
-      return 0;
-    }
-
-  if (lhs->is_simple_assign_lhs ())
-    {
-      // We are looking at a simple assignment statement like x = rhs;
-
-      tree_expression *tmp = lhs->remove_front ();
-
-      if ((tmp->is_identifier () || tmp->is_index_expression ())
-          && is_keyword (tmp->name ()))
-        {
-          std::string kw = tmp->name ();
-
-          delete tmp;
-          delete lhs;
-          delete rhs;
-
-          bison_error ("invalid assignment to keyword \"" + kw + "\"", l, c);
-
-          return 0;
-        }
-
-      delete lhs;
-
-      return new tree_simple_assignment (tmp, rhs, false, l, c, t);
-    }
-  else
-    {
-      std::list<std::string> names = lhs->variable_names ();
-
-      for (std::list<std::string>::const_iterator it = names.begin ();
-           it != names.end (); it++)
-        {
-          std::string kw = *it;
-
-          if (is_keyword (kw))
-            {
-              delete lhs;
-              delete rhs;
-
-              bison_error ("invalid assignment to keyword \"" + kw + "\"",
-                           l, c);
-
-              return 0;
-            }
-        }
-
-      return new tree_multi_assignment (lhs, rhs, false, l, c);
-    }
-}
-
-// Define a script.
-
-void
-octave_base_parser::make_script (tree_statement_list *cmds,
-                                 tree_statement *end_script)
-{
-  if (! cmds)
-    cmds = new tree_statement_list ();
-
-  cmds->append (end_script);
-
-  octave_user_script *script
-    = new octave_user_script (lexer.fcn_file_full_name,
-                              lexer.fcn_file_name,
-                              cmds, lexer.help_text);
-
-  lexer.help_text = "";
-
-  octave::sys::time now;
-
-  script->stash_fcn_file_time (now);
-
-  primary_fcn_ptr = script;
-}
-
-// Begin defining a function.
-
-octave_user_function *
-octave_base_parser::start_function (tree_parameter_list *param_list,
-                                    tree_statement_list *body,
-                                    tree_statement *end_fcn_stmt)
-{
-  // We'll fill in the return list later.
-
-  if (! body)
-    body = new tree_statement_list ();
-
-  body->append (end_fcn_stmt);
-
-  octave_user_function *fcn
-    = new octave_user_function (lexer.symtab_context.curr_scope (),
-                                param_list, 0, body);
-
-  if (fcn)
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      fcn->stash_trailing_comment (tc);
-      fcn->stash_fcn_end_location (end_fcn_stmt->line (),
-                                   end_fcn_stmt->column ());
-    }
-
-  return fcn;
-}
-
-tree_statement *
-octave_base_parser::make_end (const std::string& type, bool eof, int l, int c)
-{
-  return make_statement (new tree_no_op_command (type, eof, l, c));
-}
-
-// Do most of the work for defining a function.
-
-octave_user_function *
-octave_base_parser::frob_function (const std::string& fname,
-                                   octave_user_function *fcn)
-{
-  std::string id_name = fname;
-
-  // If input is coming from a file, issue a warning if the name of
-  // the file does not match the name of the function stated in the
-  // file.  Matlab doesn't provide a diagnostic (it ignores the stated
-  // name).
-  if (! autoloading && lexer.reading_fcn_file
-      && curr_fcn_depth == 1 && ! parsing_subfunctions)
+  {
+    tree_switch_command *retval = 0;
+
+    if (end_token_ok (end_tok, token::switch_end))
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        int l = switch_tok->line ();
+        int c = switch_tok->column ();
+
+        if (list && ! list->empty ())
+          {
+            tree_switch_case *elt = list->front ();
+
+            if (elt)
+              {
+                elt->line (l);
+                elt->column (c);
+              }
+          }
+
+        retval = new tree_switch_command (expr, list, lc, tc, l, c);
+      }
+    else
+      {
+        delete expr;
+        delete list;
+
+        end_token_error (end_tok, token::switch_end);
+      }
+
+    return retval;
+  }
+
+  // Build a switch case.
+
+  tree_switch_case *
+  base_parser::make_switch_case (token *case_tok,
+                                 tree_expression *expr,
+                                 tree_statement_list *list,
+                                 octave_comment_list *lc)
+  {
+    maybe_warn_variable_switch_label (expr);
+
+    int l = case_tok->line ();
+    int c = case_tok->column ();
+
+    return new tree_switch_case (expr, list, lc, l, c);
+  }
+
+  // Build an assignment to a variable.
+
+  tree_expression *
+  base_parser::make_assign_op (int op, tree_argument_list *lhs,
+                               token *eq_tok, tree_expression *rhs)
+  {
+    octave_value::assign_op t = octave_value::unknown_assign_op;
+
+    switch (op)
+      {
+      case '=':
+        t = octave_value::op_asn_eq;
+        break;
+
+      case ADD_EQ:
+        t = octave_value::op_add_eq;
+        break;
+
+      case SUB_EQ:
+        t = octave_value::op_sub_eq;
+        break;
+
+      case MUL_EQ:
+        t = octave_value::op_mul_eq;
+        break;
+
+      case DIV_EQ:
+        t = octave_value::op_div_eq;
+        break;
+
+      case LEFTDIV_EQ:
+        t = octave_value::op_ldiv_eq;
+        break;
+
+      case POW_EQ:
+        t = octave_value::op_pow_eq;
+        break;
+
+      case EMUL_EQ:
+        t = octave_value::op_el_mul_eq;
+        break;
+
+      case EDIV_EQ:
+        t = octave_value::op_el_div_eq;
+        break;
+
+      case ELEFTDIV_EQ:
+        t = octave_value::op_el_ldiv_eq;
+        break;
+
+      case EPOW_EQ:
+        t = octave_value::op_el_pow_eq;
+        break;
+
+      case AND_EQ:
+        t = octave_value::op_el_and_eq;
+        break;
+
+      case OR_EQ:
+        t = octave_value::op_el_or_eq;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = eq_tok->line ();
+    int c = eq_tok->column ();
+
+    if (! lhs->is_simple_assign_lhs () && t != octave_value::op_asn_eq)
+      {
+        // Multiple assignments like [x,y] OP= rhs are only valid for
+        // '=', not '+=', etc.
+
+        delete lhs;
+        delete rhs;
+
+        bison_error ("computed multiple assignment not allowed", l, c);
+
+        return 0;
+      }
+
+    if (lhs->is_simple_assign_lhs ())
+      {
+        // We are looking at a simple assignment statement like x = rhs;
+
+        tree_expression *tmp = lhs->remove_front ();
+
+        if ((tmp->is_identifier () || tmp->is_index_expression ())
+            && is_keyword (tmp->name ()))
+          {
+            std::string kw = tmp->name ();
+
+            delete tmp;
+            delete lhs;
+            delete rhs;
+
+            bison_error ("invalid assignment to keyword \"" + kw + "\"", l, c);
+
+            return 0;
+          }
+
+        delete lhs;
+
+        return new tree_simple_assignment (tmp, rhs, false, l, c, t);
+      }
+    else
+      {
+        std::list<std::string> names = lhs->variable_names ();
+
+        for (std::list<std::string>::const_iterator it = names.begin ();
+             it != names.end (); it++)
+          {
+            std::string kw = *it;
+
+            if (is_keyword (kw))
+              {
+                delete lhs;
+                delete rhs;
+
+                bison_error ("invalid assignment to keyword \"" + kw + "\"",
+                             l, c);
+
+                return 0;
+              }
+          }
+
+        return new tree_multi_assignment (lhs, rhs, false, l, c);
+      }
+  }
+
+  // Define a script.
+
+  void
+  base_parser::make_script (tree_statement_list *cmds,
+                            tree_statement *end_script)
+  {
+    if (! cmds)
+      cmds = new tree_statement_list ();
+
+    cmds->append (end_script);
+
+    octave_user_script *script
+      = new octave_user_script (lexer.fcn_file_full_name,
+                                lexer.fcn_file_name,
+                                cmds, lexer.help_text);
+
+    lexer.help_text = "";
+
+    octave::sys::time now;
+
+    script->stash_fcn_file_time (now);
+
+    primary_fcn_ptr = script;
+  }
+
+  // Begin defining a function.
+
+  octave_user_function *
+  base_parser::start_function (tree_parameter_list *param_list,
+                               tree_statement_list *body,
+                               tree_statement *end_fcn_stmt)
   {
-    // FIXME: should lexer.fcn_file_name already be
-    // preprocessed when we get here?  It seems to only be a
-    // problem with relative filenames.
+    // We'll fill in the return list later.
+
+    if (! body)
+      body = new tree_statement_list ();
+
+    body->append (end_fcn_stmt);
+
+    octave_user_function *fcn
+      = new octave_user_function (lexer.symtab_context.curr_scope (),
+                                  param_list, 0, body);
+
+    if (fcn)
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        fcn->stash_trailing_comment (tc);
+        fcn->stash_fcn_end_location (end_fcn_stmt->line (),
+                                     end_fcn_stmt->column ());
+      }
+
+    return fcn;
+  }
+
+  tree_statement *
+  base_parser::make_end (const std::string& type, bool eof, int l, int c)
+  {
+    return make_statement (new tree_no_op_command (type, eof, l, c));
+  }
+
+  // Do most of the work for defining a function.
+
+  octave_user_function *
+  base_parser::frob_function (const std::string& fname,
+                              octave_user_function *fcn)
+  {
+    std::string id_name = fname;
+
+    // If input is coming from a file, issue a warning if the name of
+    // the file does not match the name of the function stated in the
+    // file.  Matlab doesn't provide a diagnostic (it ignores the stated
+    // name).
+    if (! autoloading && lexer.reading_fcn_file
+        && curr_fcn_depth == 1 && ! parsing_subfunctions)
+      {
+        // FIXME: should lexer.fcn_file_name already be
+        // preprocessed when we get here?  It seems to only be a
+        // problem with relative filenames.
+
+        std::string nm = lexer.fcn_file_name;
+
+        size_t pos = nm.find_last_of (octave::sys::file_ops::dir_sep_chars ());
+
+        if (pos != std::string::npos)
+          nm = lexer.fcn_file_name.substr (pos+1);
+
+        if (nm != id_name)
+          {
+            warning_with_id
+              ("Octave:function-name-clash",
+               "function name '%s' does not agree with function filename '%s'",
+               id_name.c_str (), lexer.fcn_file_full_name.c_str ());
+
+            id_name = nm;
+          }
+      }
+
+    if (lexer.reading_fcn_file || lexer.reading_classdef_file || autoloading)
+      {
+        octave::sys::time now;
+
+        fcn->stash_fcn_file_name (lexer.fcn_file_full_name);
+        fcn->stash_fcn_file_time (now);
+        fcn->mark_as_system_fcn_file ();
+
+        if (fcn_file_from_relative_lookup)
+          fcn->mark_relative ();
+
+        if (curr_fcn_depth > 1 || parsing_subfunctions)
+          {
+            fcn->stash_parent_fcn_name (lexer.fcn_file_name);
+
+            if (curr_fcn_depth > 1)
+              fcn->stash_parent_fcn_scope (function_scopes[function_scopes.size ()-2]);
+            else
+              fcn->stash_parent_fcn_scope (primary_fcn_scope);
+          }
+
+        if (lexer.parsing_class_method)
+          {
+            if (curr_class_name == id_name)
+              fcn->mark_as_class_constructor ();
+            else
+              fcn->mark_as_class_method ();
+
+            fcn->stash_dispatch_class (curr_class_name);
+          }
+
+        std::string nm = fcn->fcn_file_name ();
+
+        octave::sys::file_stat fs (nm);
+
+        if (fs && fs.is_newer (now))
+          warning_with_id ("Octave:future-time-stamp",
+                           "time stamp for '%s' is in the future", nm.c_str ());
+      }
+    else if (! input_from_tmp_history_file
+             && ! lexer.force_script
+             && lexer.reading_script_file
+             && lexer.fcn_file_name == id_name)
+      {
+        warning ("function '%s' defined within script file '%s'",
+                 id_name.c_str (), lexer.fcn_file_full_name.c_str ());
+      }
+
+    fcn->stash_function_name (id_name);
+
+    if (! lexer.help_text.empty () && curr_fcn_depth == 1
+        && ! parsing_subfunctions)
+      {
+        fcn->document (lexer.help_text);
+
+        lexer.help_text = "";
+      }
+
+    if (lexer.reading_fcn_file && curr_fcn_depth == 1
+        && ! parsing_subfunctions)
+      primary_fcn_ptr = fcn;
+
+    return fcn;
+  }
+
+  tree_function_def *
+  base_parser::finish_function (tree_parameter_list *ret_list,
+                                octave_user_function *fcn,
+                                octave_comment_list *lc,
+                                int l, int c)
+  {
+    tree_function_def *retval = 0;
+
+    if (ret_list)
+      ret_list->mark_as_formal_parameters ();
+
+    if (fcn)
+      {
+        std::string nm = fcn->name ();
+        std::string file = fcn->fcn_file_name ();
+
+        std::string tmp = nm;
+        if (! file.empty ())
+          tmp += ": " + file;
+
+        symbol_table::cache_name (fcn->scope (), tmp);
+
+        if (lc)
+          fcn->stash_leading_comment (lc);
+
+        fcn->define_ret_list (ret_list);
+
+        if (curr_fcn_depth > 1 || parsing_subfunctions)
+          {
+            fcn->mark_as_subfunction ();
+            fcn->stash_fcn_location (l, c);
+
+            subfunction_names.push_back (nm);
+
+            if (endfunction_found && function_scopes.size () > 1)
+              {
+                symbol_table::scope_id pscope
+                  = function_scopes[function_scopes.size ()-2];
+
+                symbol_table::install_nestfunction (nm, octave_value (fcn),
+                                                    pscope);
+              }
+            else
+              symbol_table::install_subfunction (nm, octave_value (fcn),
+                                                 primary_fcn_scope);
+          }
+
+        if (curr_fcn_depth == 1 && fcn)
+          symbol_table::update_nest (fcn->scope ());
+
+        if (! lexer.reading_fcn_file && curr_fcn_depth == 1)
+          {
+            // We are either reading a script file or defining a function
+            // at the command line, so this definition creates a
+            // tree_function object that is placed in the parse tree.
+            // Otherwise, it is just inserted in the symbol table,
+            // either as a subfunction or nested function (see above),
+            // or as the primary function for the file, via
+            // primary_fcn_ptr (see also load_fcn_from_file,,
+            // parse_fcn_file, and
+            // symbol_table::fcn_info::fcn_info_rep::find_user_function).
+
+            retval = new tree_function_def (fcn);
+          }
+      }
+
+    return retval;
+  }
+
+  void
+  base_parser::recover_from_parsing_function (void)
+  {
+    lexer.symtab_context.pop ();
+
+    if (lexer.reading_fcn_file && curr_fcn_depth == 1
+        && ! parsing_subfunctions)
+      parsing_subfunctions = true;
+
+    curr_fcn_depth--;
+    function_scopes.pop_back ();
+
+    lexer.defining_func--;
+    lexer.parsed_function_name.pop ();
+    lexer.looking_at_return_list = false;
+    lexer.looking_at_parameter_list = false;
+  }
+
+  tree_funcall *
+  base_parser::make_superclass_ref (const std::string& method_nm,
+                                    const std::string& class_nm)
+  {
+    octave_value_list args;
+
+    args(1) = class_nm;
+    args(0) = method_nm;
+
+    octave_value fcn
+      = symbol_table::find_built_in_function ("__superclass_reference__");
+
+    return new tree_funcall (fcn, args);
+  }
+
+  tree_funcall *
+  base_parser::make_meta_class_query (const std::string& class_nm)
+  {
+    octave_value_list args;
+
+    args(0) = class_nm;
+
+    octave_value fcn
+      = symbol_table::find_built_in_function ("__meta_class_query__");
+
+    return new tree_funcall (fcn, args);
+  }
+
+  // A CLASSDEF block defines a class that has a constructor and other
+  // methods, but it is not an executable command.  Parsing the block
+  // makes some changes in the symbol table (inserting the constructor
+  // and methods, and adding to the list of known objects) and creates
+  // a parse tree containing meta information about the class.
+
+  tree_classdef *
+  base_parser::make_classdef (token *tok_val,
+                              tree_classdef_attribute_list *a,
+                              tree_identifier *id,
+                              tree_classdef_superclass_list *sc,
+                              tree_classdef_body *body, token *end_tok,
+                              octave_comment_list *lc)
+  {
+    tree_classdef *retval = 0;
+
+    std::string cls_name = id->name ();
 
     std::string nm = lexer.fcn_file_name;
 
@@ -3156,969 +3374,754 @@
     if (pos != std::string::npos)
       nm = lexer.fcn_file_name.substr (pos+1);
 
-    if (nm != id_name)
+    if (nm != cls_name)
+      {
+        delete a;
+        delete id;
+        delete sc;
+        delete body;
+
+        bison_error ("invalid classdef definition, the class name must match the filename");
+
+      }
+    else
+      {
+        if (end_token_ok (end_tok, token::classdef_end))
+          {
+            octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+            int l = tok_val->line ();
+            int c = tok_val->column ();
+
+            if (! body)
+              body = new tree_classdef_body ();
+
+            retval = new tree_classdef (a, id, sc, body, lc, tc,
+                                        curr_package_name, l, c);
+          }
+        else
+          {
+            delete a;
+            delete id;
+            delete sc;
+            delete body;
+
+            end_token_error (end_tok, token::switch_end);
+          }
+      }
+
+    return retval;
+  }
+
+  tree_classdef_properties_block *
+  base_parser::make_classdef_properties_block (token *tok_val,
+                                               tree_classdef_attribute_list *a,
+                                               tree_classdef_property_list *plist,
+                                               token *end_tok,
+                                               octave_comment_list *lc)
+  {
+    tree_classdef_properties_block *retval = 0;
+
+    if (end_token_ok (end_tok, token::properties_end))
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        int l = tok_val->line ();
+        int c = tok_val->column ();
+
+        if (! plist)
+          plist = new tree_classdef_property_list ();
+
+        retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
+      }
+    else
+      {
+        delete a;
+        delete plist;
+
+        end_token_error (end_tok, token::properties_end);
+      }
+
+    return retval;
+  }
+
+  tree_classdef_methods_block *
+  base_parser::make_classdef_methods_block (token *tok_val,
+                                            tree_classdef_attribute_list *a,
+                                            tree_classdef_methods_list *mlist,
+                                            token *end_tok,
+                                            octave_comment_list *lc)
+  {
+    tree_classdef_methods_block *retval = 0;
+
+    if (end_token_ok (end_tok, token::methods_end))
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        int l = tok_val->line ();
+        int c = tok_val->column ();
+
+        if (! mlist)
+          mlist = new tree_classdef_methods_list ();
+
+        retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
+      }
+    else
+      {
+        delete a;
+        delete mlist;
+
+        end_token_error (end_tok, token::methods_end);
+      }
+
+    return retval;
+  }
+
+  tree_classdef_events_block *
+  base_parser::make_classdef_events_block (token *tok_val,
+                                           tree_classdef_attribute_list *a,
+                                           tree_classdef_events_list *elist,
+                                           token *end_tok,
+                                           octave_comment_list *lc)
+  {
+    tree_classdef_events_block *retval = 0;
+
+    if (end_token_ok (end_tok, token::events_end))
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        int l = tok_val->line ();
+        int c = tok_val->column ();
+
+        if (! elist)
+          elist = new tree_classdef_events_list ();
+
+        retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
+      }
+    else
+      {
+        delete a;
+        delete elist;
+
+        end_token_error (end_tok, token::events_end);
+      }
+
+    return retval;
+  }
+
+  tree_classdef_enum_block *
+  base_parser::make_classdef_enum_block (token *tok_val,
+                                         tree_classdef_attribute_list *a,
+                                         tree_classdef_enum_list *elist,
+                                         token *end_tok,
+                                         octave_comment_list *lc)
+  {
+    tree_classdef_enum_block *retval = 0;
+
+    if (end_token_ok (end_tok, token::enumeration_end))
+      {
+        octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+        int l = tok_val->line ();
+        int c = tok_val->column ();
+
+        if (! elist)
+          elist = new tree_classdef_enum_list ();
+
+        retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
+      }
+    else
+      {
+        delete a;
+        delete elist;
+
+        end_token_error (end_tok, token::enumeration_end);
+      }
+
+    return retval;
+  }
+
+  octave_user_function*
+  base_parser::start_classdef_external_method (tree_identifier *id,
+                                               tree_parameter_list *pl)
+  {
+    octave_user_function* retval = 0;
+
+    // External methods are only allowed within @-folders. In this case,
+    // curr_class_name will be non-empty.
+
+    if (! curr_class_name.empty ())
+      {
+
+        std::string mname = id->name ();
+
+        // Methods that cannot be declared outside the classdef file:
+        // - methods with '.' character (e.g. property accessors)
+        // - class constructor
+        // - `delete'
+
+        if (mname.find_first_of (".") == std::string::npos
+            && mname != "delete"
+            && mname != curr_class_name)
+          {
+            // Create a dummy function that is used until the real method
+            // is loaded.
+
+            retval = new octave_user_function (-1, pl);
+
+            retval->stash_function_name (mname);
+
+            int l = id->line ();
+            int c = id->column ();
+
+            retval->stash_fcn_location (l, c);
+          }
+        else
+          bison_error ("invalid external method declaration, an external "
+                       "method cannot be the class constructor, `delete' "
+                       "or have a dot (.) character in its name");
+      }
+    else
+      bison_error ("external methods are only allowed in @-folders");
+
+    if (! retval)
+      delete id;
+
+    return retval;
+  }
+
+  tree_function_def *
+  base_parser::finish_classdef_external_method (octave_user_function *fcn,
+                                                tree_parameter_list *ret_list,
+                                                octave_comment_list *cl)
+  {
+    if (ret_list)
+      fcn->define_ret_list (ret_list);
+
+    if (cl)
+      fcn->stash_leading_comment (cl);
+
+    int l = fcn->beginning_line ();
+    int c = fcn->beginning_column ();
+
+    return new tree_function_def (fcn, l, c);
+  }
+
+  // Make an index expression.
+
+  tree_index_expression *
+  base_parser::make_index_expression (tree_expression *expr,
+                                      tree_argument_list *args,
+                                      char type)
+  {
+    tree_index_expression *retval = 0;
+
+    if (args && args->has_magic_tilde ())
+      {
+        delete expr;
+        delete args;
+
+        bison_error ("invalid use of empty argument (~) in index expression");
+      }
+    else
       {
-        warning_with_id
-          ("Octave:function-name-clash",
-           "function name '%s' does not agree with function filename '%s'",
-           id_name.c_str (), lexer.fcn_file_full_name.c_str ());
-
-        id_name = nm;
+        int l = expr->line ();
+        int c = expr->column ();
+
+        if (! expr->is_postfix_indexed ())
+          expr->set_postfix_index (type);
+
+        if (expr->is_index_expression ())
+          {
+            tree_index_expression *tmp =
+              static_cast<tree_index_expression *> (expr);
+
+            tmp->append (args, type);
+
+            retval = tmp;
+          }
+        else
+          retval = new tree_index_expression (expr, args, l, c, type);
+      }
+
+    return retval;
+  }
+
+  // Make an indirect reference expression.
+
+  tree_index_expression *
+  base_parser::make_indirect_ref (tree_expression *expr,
+                                  const std::string& elt)
+  {
+    tree_index_expression *retval = 0;
+
+    int l = expr->line ();
+    int c = expr->column ();
+
+    if (! expr->is_postfix_indexed ())
+      expr->set_postfix_index ('.');
+
+    if (expr->is_index_expression ())
+      {
+        tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+
+        tmp->append (elt);
+
+        retval = tmp;
+      }
+    else
+      retval = new tree_index_expression (expr, elt, l, c);
+
+    lexer.looking_at_indirect_ref = false;
+
+    return retval;
+  }
+
+  // Make an indirect reference expression with dynamic field name.
+
+  tree_index_expression *
+  base_parser::make_indirect_ref (tree_expression *expr,
+                                  tree_expression *elt)
+  {
+    tree_index_expression *retval = 0;
+
+    int l = expr->line ();
+    int c = expr->column ();
+
+    if (! expr->is_postfix_indexed ())
+      expr->set_postfix_index ('.');
+
+    if (expr->is_index_expression ())
+      {
+        tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+
+        tmp->append (elt);
+
+        retval = tmp;
+      }
+    else
+      retval = new tree_index_expression (expr, elt, l, c);
+
+    lexer.looking_at_indirect_ref = false;
+
+    return retval;
+  }
+
+  // Make a declaration command.
+
+  tree_decl_command *
+  base_parser::make_decl_command (int tok, token *tok_val,
+                                  tree_decl_init_list *lst)
+  {
+    tree_decl_command *retval = 0;
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    switch (tok)
+      {
+      case GLOBAL:
+        retval = new tree_global_command (lst, l, c);
+        break;
+
+      case PERSISTENT:
+        if (curr_fcn_depth > 0)
+          retval = new tree_persistent_command (lst, l, c);
+        else
+          {
+            if (lexer.reading_script_file)
+              warning ("ignoring persistent declaration near line %d of file '%s'",
+                       l, lexer.fcn_file_full_name.c_str ());
+            else
+              warning ("ignoring persistent declaration near line %d", l);
+          }
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    return retval;
+  }
+
+  bool
+  base_parser::validate_array_list (tree_expression *e)
+  {
+    bool retval = true;
+
+    tree_array_list *al = dynamic_cast<tree_array_list *> (e);
+
+    for (tree_array_list::iterator i = al->begin (); i != al->end (); i++)
+      {
+        tree_argument_list *row = *i;
+
+        if (row && row->has_magic_tilde ())
+          {
+            retval = false;
+
+            if (e->is_matrix ())
+              bison_error ("invalid use of tilde (~) in matrix expression");
+            else
+              bison_error ("invalid use of tilde (~) in cell expression");
+
+            break;
+          }
+      }
+
+    return retval;
+  }
+
+  tree_argument_list *
+  base_parser::validate_matrix_for_assignment (tree_expression *e)
+  {
+    tree_argument_list *retval = 0;
+
+    if (e->is_constant ())
+      {
+        octave_value ov = e->rvalue1 ();
+
+        delete e;
+
+        if (ov.is_empty ())
+          bison_error ("invalid empty left hand side of assignment");
+        else
+          bison_error ("invalid constant left hand side of assignment");
+      }
+    else
+      {
+        bool is_simple_assign = true;
+
+        tree_argument_list *tmp = 0;
+
+        if (e->is_matrix ())
+          {
+            tree_matrix *mat = dynamic_cast<tree_matrix *> (e);
+
+            if (mat && mat->size () == 1)
+              {
+                tmp = mat->front ();
+                mat->pop_front ();
+                delete e;
+                is_simple_assign = false;
+              }
+          }
+        else
+          tmp = new tree_argument_list (e);
+
+        if (tmp && tmp->is_valid_lvalue_list ())
+          {
+            lexer.mark_as_variables (tmp->variable_names ());
+            retval = tmp;
+          }
+        else
+          {
+            delete tmp;
+
+            bison_error ("invalid left hand side of assignment");
+          }
+
+        if (retval && is_simple_assign)
+          retval->mark_as_simple_assign_lhs ();
+      }
+
+    return retval;
+  }
+
+  // Finish building an array_list.
+
+  tree_expression *
+  base_parser::finish_array_list (tree_array_list *array_list)
+  {
+    tree_expression *retval = array_list;
+
+    octave::unwind_protect frame;
+
+    frame.protect_var (discard_error_messages);
+    frame.protect_var (discard_warning_messages);
+
+    discard_error_messages = true;
+    discard_warning_messages = true;
+
+    if (array_list->all_elements_are_constant ())
+      {
+        try
+          {
+            octave_value tmp = array_list->rvalue1 ();
+
+            tree_constant *tc_retval
+              = new tree_constant (tmp, array_list->line (),
+                                   array_list->column ());
+
+            std::ostringstream buf;
+
+            tree_print_code tpc (buf);
+
+            array_list->accept (tpc);
+
+            tc_retval->stash_original_text (buf.str ());
+
+            delete array_list;
+
+            retval = tc_retval;
+          }
+        catch (const octave_execution_exception&)
+          {
+            recover_from_exception ();
+          }
+      }
+
+    return retval;
+  }
+
+  // Finish building a matrix list.
+
+  tree_expression *
+  base_parser::finish_matrix (tree_matrix *m)
+  {
+    return (m
+            ? finish_array_list (m)
+            : new tree_constant (octave_null_matrix::instance));
+  }
+
+  // Finish building a cell list.
+
+  tree_expression *
+  base_parser::finish_cell (tree_cell *c)
+  {
+    return (c
+            ? finish_array_list (c)
+            : new tree_constant (octave_value (Cell ())));
+  }
+
+  void
+  base_parser::maybe_warn_missing_semi (tree_statement_list *t)
+  {
+    if (curr_fcn_depth > 0)
+      {
+        tree_statement *tmp = t->back ();
+
+        if (tmp->is_expression ())
+          warning_with_id
+            ("Octave:missing-semicolon",
+             "missing semicolon near line %d, column %d in file '%s'",
+             tmp->line (), tmp->column (), lexer.fcn_file_full_name.c_str ());
       }
   }
 
-  if (lexer.reading_fcn_file || lexer.reading_classdef_file || autoloading)
-    {
-      octave::sys::time now;
-
-      fcn->stash_fcn_file_name (lexer.fcn_file_full_name);
-      fcn->stash_fcn_file_time (now);
-      fcn->mark_as_system_fcn_file ();
-
-      if (fcn_file_from_relative_lookup)
-        fcn->mark_relative ();
-
-      if (curr_fcn_depth > 1 || parsing_subfunctions)
-        {
-          fcn->stash_parent_fcn_name (lexer.fcn_file_name);
-
-          if (curr_fcn_depth > 1)
-            fcn->stash_parent_fcn_scope (function_scopes[function_scopes.size ()-2]);
-          else
-            fcn->stash_parent_fcn_scope (primary_fcn_scope);
-        }
-
-      if (lexer.parsing_class_method)
-        {
-          if (curr_class_name == id_name)
-            fcn->mark_as_class_constructor ();
-          else
-            fcn->mark_as_class_method ();
-
-          fcn->stash_dispatch_class (curr_class_name);
-        }
-
-      std::string nm = fcn->fcn_file_name ();
-
-      octave::sys::file_stat fs (nm);
-
-      if (fs && fs.is_newer (now))
-        warning_with_id ("Octave:future-time-stamp",
-                         "time stamp for '%s' is in the future", nm.c_str ());
-    }
-  else if (! input_from_tmp_history_file
-           && ! lexer.force_script
-           && lexer.reading_script_file
-           && lexer.fcn_file_name == id_name)
-    {
-      warning ("function '%s' defined within script file '%s'",
-               id_name.c_str (), lexer.fcn_file_full_name.c_str ());
-    }
-
-  fcn->stash_function_name (id_name);
-
-  if (! lexer.help_text.empty () && curr_fcn_depth == 1
-      && ! parsing_subfunctions)
-    {
-      fcn->document (lexer.help_text);
-
-      lexer.help_text = "";
-    }
-
-  if (lexer.reading_fcn_file && curr_fcn_depth == 1
-      && ! parsing_subfunctions)
-    primary_fcn_ptr = fcn;
-
-  return fcn;
-}
-
-tree_function_def *
-octave_base_parser::finish_function (tree_parameter_list *ret_list,
-                                     octave_user_function *fcn,
-                                     octave_comment_list *lc,
-                                     int l, int c)
-{
-  tree_function_def *retval = 0;
-
-  if (ret_list)
-    ret_list->mark_as_formal_parameters ();
-
-  if (fcn)
-    {
-      std::string nm = fcn->name ();
-      std::string file = fcn->fcn_file_name ();
-
-      std::string tmp = nm;
-      if (! file.empty ())
-        tmp += ": " + file;
-
-      symbol_table::cache_name (fcn->scope (), tmp);
-
-      if (lc)
-        fcn->stash_leading_comment (lc);
-
-      fcn->define_ret_list (ret_list);
-
-      if (curr_fcn_depth > 1 || parsing_subfunctions)
-        {
-          fcn->mark_as_subfunction ();
-          fcn->stash_fcn_location (l, c);
-
-          subfunction_names.push_back (nm);
-
-          if (endfunction_found && function_scopes.size () > 1)
-            {
-              symbol_table::scope_id pscope
-                = function_scopes[function_scopes.size ()-2];
-
-              symbol_table::install_nestfunction (nm, octave_value (fcn),
-                                                  pscope);
-            }
-          else
-            symbol_table::install_subfunction (nm, octave_value (fcn),
-                                               primary_fcn_scope);
-        }
-
-      if (curr_fcn_depth == 1 && fcn)
-        symbol_table::update_nest (fcn->scope ());
-
-      if (! lexer.reading_fcn_file && curr_fcn_depth == 1)
-        {
-          // We are either reading a script file or defining a function
-          // at the command line, so this definition creates a
-          // tree_function object that is placed in the parse tree.
-          // Otherwise, it is just inserted in the symbol table,
-          // either as a subfunction or nested function (see above),
-          // or as the primary function for the file, via
-          // primary_fcn_ptr (see also load_fcn_from_file,,
-          // parse_fcn_file, and
-          // symbol_table::fcn_info::fcn_info_rep::find_user_function).
-
-          retval = new tree_function_def (fcn);
-        }
-    }
-
-  return retval;
-}
-
-void
-octave_base_parser::recover_from_parsing_function (void)
-{
-  lexer.symtab_context.pop ();
-
-  if (lexer.reading_fcn_file && curr_fcn_depth == 1
-      && ! parsing_subfunctions)
-    parsing_subfunctions = true;
-
-  curr_fcn_depth--;
-  function_scopes.pop_back ();
-
-  lexer.defining_func--;
-  lexer.parsed_function_name.pop ();
-  lexer.looking_at_return_list = false;
-  lexer.looking_at_parameter_list = false;
-}
-
-tree_funcall *
-octave_base_parser::make_superclass_ref (const std::string& method_nm,
-                                         const std::string& class_nm)
-{
-  octave_value_list args;
-
-  args(1) = class_nm;
-  args(0) = method_nm;
-
-  octave_value fcn
-    = symbol_table::find_built_in_function ("__superclass_reference__");
-
-  return new tree_funcall (fcn, args);
-}
-
-tree_funcall *
-octave_base_parser::make_meta_class_query (const std::string& class_nm)
-{
-  octave_value_list args;
-
-  args(0) = class_nm;
-
-  octave_value fcn
-    = symbol_table::find_built_in_function ("__meta_class_query__");
-
-  return new tree_funcall (fcn, args);
-}
-
-// A CLASSDEF block defines a class that has a constructor and other
-// methods, but it is not an executable command.  Parsing the block
-// makes some changes in the symbol table (inserting the constructor
-// and methods, and adding to the list of known objects) and creates
-// a parse tree containing meta information about the class.
-
-tree_classdef *
-octave_base_parser::make_classdef (token *tok_val,
-                                   tree_classdef_attribute_list *a,
-                                   tree_identifier *id,
-                                   tree_classdef_superclass_list *sc,
-                                   tree_classdef_body *body, token *end_tok,
-                                   octave_comment_list *lc)
-{
-  tree_classdef *retval = 0;
-
-  std::string cls_name = id->name ();
-
-  std::string nm = lexer.fcn_file_name;
-
-  size_t pos = nm.find_last_of (octave::sys::file_ops::dir_sep_chars ());
-
-  if (pos != std::string::npos)
-    nm = lexer.fcn_file_name.substr (pos+1);
-
-  if (nm != cls_name)
-    {
-      delete a;
-      delete id;
-      delete sc;
-      delete body;
-
-      bison_error ("invalid classdef definition, the class name must match the filename");
-
-    }
-  else
-    {
-      if (end_token_ok (end_tok, token::classdef_end))
-        {
-          octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-          int l = tok_val->line ();
-          int c = tok_val->column ();
-
-          if (! body)
-            body = new tree_classdef_body ();
-
-          retval = new tree_classdef (a, id, sc, body, lc, tc,
-                                      curr_package_name, l, c);
-        }
-      else
-        {
-          delete a;
-          delete id;
-          delete sc;
-          delete body;
-
-          end_token_error (end_tok, token::switch_end);
-        }
-    }
-
-  return retval;
-}
-
-tree_classdef_properties_block *
-octave_base_parser::make_classdef_properties_block (token *tok_val,
-                                                    tree_classdef_attribute_list *a,
-                                                    tree_classdef_property_list *plist,
-                                                    token *end_tok,
-                                                    octave_comment_list *lc)
-{
-  tree_classdef_properties_block *retval = 0;
-
-  if (end_token_ok (end_tok, token::properties_end))
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      int l = tok_val->line ();
-      int c = tok_val->column ();
-
-      if (! plist)
-        plist = new tree_classdef_property_list ();
-
-      retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
-    }
-  else
-    {
-      delete a;
-      delete plist;
-
-      end_token_error (end_tok, token::properties_end);
-    }
-
-  return retval;
-}
-
-tree_classdef_methods_block *
-octave_base_parser::make_classdef_methods_block (token *tok_val,
-                                                 tree_classdef_attribute_list *a,
-                                                 tree_classdef_methods_list *mlist,
-                                                 token *end_tok,
-                                                 octave_comment_list *lc)
-{
-  tree_classdef_methods_block *retval = 0;
-
-  if (end_token_ok (end_tok, token::methods_end))
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      int l = tok_val->line ();
-      int c = tok_val->column ();
-
-      if (! mlist)
-        mlist = new tree_classdef_methods_list ();
-
-      retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
-    }
-  else
-    {
-      delete a;
-      delete mlist;
-
-      end_token_error (end_tok, token::methods_end);
-    }
-
-  return retval;
-}
-
-tree_classdef_events_block *
-octave_base_parser::make_classdef_events_block (token *tok_val,
-                                                tree_classdef_attribute_list *a,
-                                                tree_classdef_events_list *elist,
-                                                token *end_tok,
-                                                octave_comment_list *lc)
-{
-  tree_classdef_events_block *retval = 0;
-
-  if (end_token_ok (end_tok, token::events_end))
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      int l = tok_val->line ();
-      int c = tok_val->column ();
-
-      if (! elist)
-        elist = new tree_classdef_events_list ();
-
-      retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
-    }
-  else
-    {
-      delete a;
-      delete elist;
-
-      end_token_error (end_tok, token::events_end);
-    }
-
-  return retval;
-}
-
-tree_classdef_enum_block *
-octave_base_parser::make_classdef_enum_block (token *tok_val,
-                                              tree_classdef_attribute_list *a,
-                                              tree_classdef_enum_list *elist,
-                                              token *end_tok,
-                                              octave_comment_list *lc)
-{
-  tree_classdef_enum_block *retval = 0;
-
-  if (end_token_ok (end_tok, token::enumeration_end))
-    {
-      octave_comment_list *tc = lexer.comment_buf.get_comment ();
-
-      int l = tok_val->line ();
-      int c = tok_val->column ();
-
-      if (! elist)
-        elist = new tree_classdef_enum_list ();
-
-      retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
-    }
-  else
-    {
-      delete a;
-      delete elist;
-
-      end_token_error (end_tok, token::enumeration_end);
-    }
-
-  return retval;
-}
-
-octave_user_function*
-octave_base_parser::start_classdef_external_method (tree_identifier *id,
-                                                    tree_parameter_list *pl)
-{
-  octave_user_function* retval = 0;
-
-  // External methods are only allowed within @-folders. In this case,
-  // curr_class_name will be non-empty.
-
-  if (! curr_class_name.empty ())
-    {
-
-      std::string mname = id->name ();
-
-      // Methods that cannot be declared outside the classdef file:
-      // - methods with '.' character (e.g. property accessors)
-      // - class constructor
-      // - `delete'
-
-      if (mname.find_first_of (".") == std::string::npos
-          && mname != "delete"
-          && mname != curr_class_name)
-        {
-          // Create a dummy function that is used until the real method
-          // is loaded.
-
-          retval = new octave_user_function (-1, pl);
-
-          retval->stash_function_name (mname);
-
-          int l = id->line ();
-          int c = id->column ();
-
-          retval->stash_fcn_location (l, c);
-        }
-      else
-        bison_error ("invalid external method declaration, an external "
-                     "method cannot be the class constructor, `delete' "
-                     "or have a dot (.) character in its name");
-    }
-  else
-    bison_error ("external methods are only allowed in @-folders");
-
-  if (! retval)
-    delete id;
-
-  return retval;
-}
-
-tree_function_def *
-octave_base_parser::finish_classdef_external_method (octave_user_function *fcn,
-                                                     tree_parameter_list *ret_list,
-                                                     octave_comment_list *cl)
-{
-  if (ret_list)
-    fcn->define_ret_list (ret_list);
-
-  if (cl)
-    fcn->stash_leading_comment (cl);
-
-  int l = fcn->beginning_line ();
-  int c = fcn->beginning_column ();
-
-  return new tree_function_def (fcn, l, c);
-}
-
-// Make an index expression.
-
-tree_index_expression *
-octave_base_parser::make_index_expression (tree_expression *expr,
-                                           tree_argument_list *args,
-                                           char type)
-{
-  tree_index_expression *retval = 0;
-
-  if (args && args->has_magic_tilde ())
-    {
-      delete expr;
-      delete args;
-
-      bison_error ("invalid use of empty argument (~) in index expression");
-    }
-  else
-    {
-      int l = expr->line ();
-      int c = expr->column ();
-
-      if (! expr->is_postfix_indexed ())
-        expr->set_postfix_index (type);
-
-      if (expr->is_index_expression ())
-        {
-          tree_index_expression *tmp =
-            static_cast<tree_index_expression *> (expr);
-
-          tmp->append (args, type);
-
-          retval = tmp;
-        }
-      else
-        retval = new tree_index_expression (expr, args, l, c, type);
-    }
-
-  return retval;
-}
-
-// Make an indirect reference expression.
-
-tree_index_expression *
-octave_base_parser::make_indirect_ref (tree_expression *expr,
-                                       const std::string& elt)
-{
-  tree_index_expression *retval = 0;
-
-  int l = expr->line ();
-  int c = expr->column ();
-
-  if (! expr->is_postfix_indexed ())
-    expr->set_postfix_index ('.');
-
-  if (expr->is_index_expression ())
-    {
-      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
-
-      tmp->append (elt);
-
-      retval = tmp;
-    }
-  else
-    retval = new tree_index_expression (expr, elt, l, c);
-
-  lexer.looking_at_indirect_ref = false;
-
-  return retval;
-}
-
-// Make an indirect reference expression with dynamic field name.
-
-tree_index_expression *
-octave_base_parser::make_indirect_ref (tree_expression *expr,
-                                       tree_expression *elt)
-{
-  tree_index_expression *retval = 0;
-
-  int l = expr->line ();
-  int c = expr->column ();
-
-  if (! expr->is_postfix_indexed ())
-    expr->set_postfix_index ('.');
-
-  if (expr->is_index_expression ())
-    {
-      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
-
-      tmp->append (elt);
-
-      retval = tmp;
-    }
-  else
-    retval = new tree_index_expression (expr, elt, l, c);
-
-  lexer.looking_at_indirect_ref = false;
-
-  return retval;
-}
-
-// Make a declaration command.
-
-tree_decl_command *
-octave_base_parser::make_decl_command (int tok, token *tok_val,
-                                       tree_decl_init_list *lst)
-{
-  tree_decl_command *retval = 0;
-
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  switch (tok)
-    {
-    case GLOBAL:
-      retval = new tree_global_command (lst, l, c);
-      break;
-
-    case PERSISTENT:
-      if (curr_fcn_depth > 0)
-        retval = new tree_persistent_command (lst, l, c);
-      else
-        {
-          if (lexer.reading_script_file)
-            warning ("ignoring persistent declaration near line %d of file '%s'",
-                     l, lexer.fcn_file_full_name.c_str ());
-          else
-            warning ("ignoring persistent declaration near line %d", l);
-        }
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  return retval;
-}
-
-bool
-octave_base_parser::validate_array_list (tree_expression *e)
-{
-  bool retval = true;
-
-  tree_array_list *al = dynamic_cast<tree_array_list *> (e);
-
-  for (tree_array_list::iterator i = al->begin (); i != al->end (); i++)
-    {
-      tree_argument_list *row = *i;
-
-      if (row && row->has_magic_tilde ())
-        {
-          retval = false;
-
-          if (e->is_matrix ())
-            bison_error ("invalid use of tilde (~) in matrix expression");
-          else
-            bison_error ("invalid use of tilde (~) in cell expression");
-
-          break;
-        }
-    }
-
-  return retval;
-}
-
-tree_argument_list *
-octave_base_parser::validate_matrix_for_assignment (tree_expression *e)
-{
-  tree_argument_list *retval = 0;
-
-  if (e->is_constant ())
-    {
-      octave_value ov = e->rvalue1 ();
-
-      delete e;
-
-      if (ov.is_empty ())
-        bison_error ("invalid empty left hand side of assignment");
-      else
-        bison_error ("invalid constant left hand side of assignment");
-    }
-  else
-    {
-      bool is_simple_assign = true;
-
-      tree_argument_list *tmp = 0;
-
-      if (e->is_matrix ())
-        {
-          tree_matrix *mat = dynamic_cast<tree_matrix *> (e);
-
-          if (mat && mat->size () == 1)
-            {
-              tmp = mat->front ();
-              mat->pop_front ();
-              delete e;
-              is_simple_assign = false;
-            }
-        }
-      else
-        tmp = new tree_argument_list (e);
-
-      if (tmp && tmp->is_valid_lvalue_list ())
-        {
-          lexer.mark_as_variables (tmp->variable_names ());
-          retval = tmp;
-        }
-      else
-        {
-          delete tmp;
-
-          bison_error ("invalid left hand side of assignment");
-        }
-
-      if (retval && is_simple_assign)
-        retval->mark_as_simple_assign_lhs ();
-    }
-
-  return retval;
-}
-
-// Finish building an array_list.
-
-tree_expression *
-octave_base_parser::finish_array_list (tree_array_list *array_list)
-{
-  tree_expression *retval = array_list;
-
-  octave::unwind_protect frame;
-
-  frame.protect_var (discard_error_messages);
-  frame.protect_var (discard_warning_messages);
-
-  discard_error_messages = true;
-  discard_warning_messages = true;
-
-  if (array_list->all_elements_are_constant ())
-    {
-      try
-        {
-          octave_value tmp = array_list->rvalue1 ();
-
-          tree_constant *tc_retval
-            = new tree_constant (tmp, array_list->line (),
-                                 array_list->column ());
-
-          std::ostringstream buf;
-
-          tree_print_code tpc (buf);
-
-          array_list->accept (tpc);
-
-          tc_retval->stash_original_text (buf.str ());
-
-          delete array_list;
-
-          retval = tc_retval;
-        }
-      catch (const octave_execution_exception&)
-        {
-          recover_from_exception ();
-        }
-    }
-
-  return retval;
-}
-
-// Finish building a matrix list.
-
-tree_expression *
-octave_base_parser::finish_matrix (tree_matrix *m)
-{
-  return (m
-          ? finish_array_list (m)
-          : new tree_constant (octave_null_matrix::instance));
-}
-
-// Finish building a cell list.
-
-tree_expression *
-octave_base_parser::finish_cell (tree_cell *c)
-{
-  return (c
-          ? finish_array_list (c)
-          : new tree_constant (octave_value (Cell ())));
-}
-
-void
-octave_base_parser::maybe_warn_missing_semi (tree_statement_list *t)
-{
-  if (curr_fcn_depth > 0)
-    {
-      tree_statement *tmp = t->back ();
-
-      if (tmp->is_expression ())
-        warning_with_id
-          ("Octave:missing-semicolon",
-           "missing semicolon near line %d, column %d in file '%s'",
-            tmp->line (), tmp->column (), lexer.fcn_file_full_name.c_str ());
-    }
-}
-
-tree_statement_list *
-octave_base_parser::set_stmt_print_flag (tree_statement_list *list,
-                                         char sep, bool warn_missing_semi)
-{
-  tree_statement *tmp = list->back ();
-
-  switch (sep)
-    {
-    case ';':
-      tmp->set_print_flag (false);
-      break;
-
-    case 0:
-    case ',':
-    case '\n':
-      tmp->set_print_flag (true);
-      if (warn_missing_semi)
-        maybe_warn_missing_semi (list);
-      break;
-
-    default:
-      warning ("unrecognized separator type!");
-      break;
-    }
-
-  // Even if a statement is null, we add it to the list then remove it
-  // here so that the print flag is applied to the correct statement.
-
-  if (tmp->is_null_statement ())
-    {
-      list->pop_back ();
-      delete tmp;
-    }
-
-  return list;
-}
-
-// Finish building a statement.
-template <typename T>
-tree_statement *
-octave_base_parser::make_statement (T *arg)
-{
-  octave_comment_list *comment = lexer.get_comment ();
-
-  return new tree_statement (arg, comment);
-}
-
-tree_statement_list *
-octave_base_parser::make_statement_list (tree_statement *stmt)
-{
-  return new tree_statement_list (stmt);
-}
-
-tree_statement_list *
-octave_base_parser::append_statement_list (tree_statement_list *list,
-                                           char sep, tree_statement *stmt,
-                                           bool warn_missing_semi)
-{
-  set_stmt_print_flag (list, sep, warn_missing_semi);
-
-  list->append (stmt);
-
-  return list;
-}
-
-void
-octave_base_parser::bison_error (const std::string& str, int l, int c)
-{
-  int err_line = l < 0 ? lexer.input_line_number : l;
-  int err_col = c < 0 ? lexer.current_input_column - 1 : c;
-
-  std::ostringstream output_buf;
-
-  if (lexer.reading_fcn_file || lexer.reading_script_file
-      || lexer.reading_classdef_file)
-    output_buf << "parse error near line " << err_line
-               << " of file " << lexer.fcn_file_full_name;
-  else
-    output_buf << "parse error:";
-
-  if (str != "parse error")
-    output_buf << "\n\n  " << str;
-
-  output_buf << "\n\n";
-
-  std::string curr_line = lexer.current_input_line;
-
-  if (! curr_line.empty ())
-    {
-      size_t len = curr_line.length ();
-
-      if (curr_line[len-1] == '\n')
-        curr_line.resize (len-1);
-
-      // Print the line, maybe with a pointer near the error token.
-
-      output_buf << ">>> " << curr_line << "\n";
-
-      if (err_col == 0)
-        err_col = len;
-
-      for (int i = 0; i < err_col + 3; i++)
-        output_buf << " ";
-
-      output_buf << "^";
-    }
-
-  output_buf << "\n";
-
-  parse_error_msg = output_buf.str ();
-}
-
-int
-octave_parser::run (void)
-{
-  int status = -1;
-
-  yypstate *pstate = static_cast<yypstate *> (parser_state);
-
-  try
-    {
-      status = octave_pull_parse (pstate, *this);
-    }
-  catch (octave_execution_exception& e)
-    {
-      std::string file = lexer.fcn_file_full_name;
-
-      if (file.empty ())
-        error (e, "parse error");
-      else
-        error (e, "parse error in %s", file.c_str ());
-    }
-  catch (octave_interrupt_exception &)
-    {
-      throw;
-    }
-  catch (...)
-    {
-      std::string file = lexer.fcn_file_full_name;
-
-      if (file.empty ())
-        error ("unexpected exception while parsing input");
-      else
-        error ("unexpected exception while parsing %s", file.c_str ());
-    }
-
-  if (status != 0)
-    parse_error ("%s", parse_error_msg.c_str ());
-
-  return status;
-}
-
-// Parse input from INPUT.  Pass TRUE for EOF if the end of INPUT should
-// finish the parse.
-
-int
-octave_push_parser::run (const std::string& input, bool eof)
-{
-  int status = -1;
-
-  dynamic_cast<octave_push_lexer&> (lexer).append_input (input, eof);
-
-  do
-    {
-      YYSTYPE lval;
-
-      int token = octave_lex (&lval, scanner);
-
-      if (token < 0)
-        {
-          if (! eof && lexer.at_end_of_buffer ())
-            {
-              status = -1;
-              break;
-            }
-        }
-
-      yypstate *pstate = static_cast<yypstate *> (parser_state);
-
-      try
-        {
-          status = octave_push_parse (pstate, token, &lval, *this);
-        }
-      catch (octave_execution_exception& e)
-        {
-          std::string file = lexer.fcn_file_full_name;
-
-          if (file.empty ())
-            error (e, "parse error");
-          else
-            error (e, "parse error in %s", file.c_str ());
-        }
-      catch (octave_interrupt_exception &)
-        {
-          throw;
-        }
-      catch (...)
-        {
-          std::string file = lexer.fcn_file_full_name;
-
-          if (file.empty ())
-            error ("unexpected exception while parsing input");
-          else
-            error ("unexpected exception while parsing %s", file.c_str ());
-        }
-    }
-  while (status == YYPUSH_MORE);
-
-  if (status != 0)
-    parse_error ("%s", parse_error_msg.c_str ());
-
-  return status;
+  tree_statement_list *
+  base_parser::set_stmt_print_flag (tree_statement_list *list,
+                                    char sep, bool warn_missing_semi)
+  {
+    tree_statement *tmp = list->back ();
+
+    switch (sep)
+      {
+      case ';':
+        tmp->set_print_flag (false);
+        break;
+
+      case 0:
+      case ',':
+      case '\n':
+        tmp->set_print_flag (true);
+        if (warn_missing_semi)
+          maybe_warn_missing_semi (list);
+        break;
+
+      default:
+        warning ("unrecognized separator type!");
+        break;
+      }
+
+    // Even if a statement is null, we add it to the list then remove it
+    // here so that the print flag is applied to the correct statement.
+
+    if (tmp->is_null_statement ())
+      {
+        list->pop_back ();
+        delete tmp;
+      }
+
+    return list;
+  }
+
+  // Finish building a statement.
+  template <typename T>
+  tree_statement *
+  base_parser::make_statement (T *arg)
+  {
+    octave_comment_list *comment = lexer.get_comment ();
+
+    return new tree_statement (arg, comment);
+  }
+
+  tree_statement_list *
+  base_parser::make_statement_list (tree_statement *stmt)
+  {
+    return new tree_statement_list (stmt);
+  }
+
+  tree_statement_list *
+  base_parser::append_statement_list (tree_statement_list *list,
+                                      char sep, tree_statement *stmt,
+                                      bool warn_missing_semi)
+  {
+    set_stmt_print_flag (list, sep, warn_missing_semi);
+
+    list->append (stmt);
+
+    return list;
+  }
+
+  void
+  base_parser::bison_error (const std::string& str, int l, int c)
+  {
+    int err_line = l < 0 ? lexer.input_line_number : l;
+    int err_col = c < 0 ? lexer.current_input_column - 1 : c;
+
+    std::ostringstream output_buf;
+
+    if (lexer.reading_fcn_file || lexer.reading_script_file
+        || lexer.reading_classdef_file)
+      output_buf << "parse error near line " << err_line
+                 << " of file " << lexer.fcn_file_full_name;
+    else
+      output_buf << "parse error:";
+
+    if (str != "parse error")
+      output_buf << "\n\n  " << str;
+
+    output_buf << "\n\n";
+
+    std::string curr_line = lexer.current_input_line;
+
+    if (! curr_line.empty ())
+      {
+        size_t len = curr_line.length ();
+
+        if (curr_line[len-1] == '\n')
+          curr_line.resize (len-1);
+
+        // Print the line, maybe with a pointer near the error token.
+
+        output_buf << ">>> " << curr_line << "\n";
+
+        if (err_col == 0)
+          err_col = len;
+
+        for (int i = 0; i < err_col + 3; i++)
+          output_buf << " ";
+
+        output_buf << "^";
+      }
+
+    output_buf << "\n";
+
+    parse_error_msg = output_buf.str ();
+  }
+
+  int
+  parser::run (void)
+  {
+    int status = -1;
+
+    yypstate *pstate = static_cast<yypstate *> (parser_state);
+
+    try
+      {
+        status = octave_pull_parse (pstate, *this);
+      }
+    catch (octave_execution_exception& e)
+      {
+        std::string file = lexer.fcn_file_full_name;
+
+        if (file.empty ())
+          error (e, "parse error");
+        else
+          error (e, "parse error in %s", file.c_str ());
+      }
+    catch (octave_interrupt_exception &)
+      {
+        throw;
+      }
+    catch (...)
+      {
+        std::string file = lexer.fcn_file_full_name;
+
+        if (file.empty ())
+          error ("unexpected exception while parsing input");
+        else
+          error ("unexpected exception while parsing %s", file.c_str ());
+      }
+
+    if (status != 0)
+      parse_error ("%s", parse_error_msg.c_str ());
+
+    return status;
+  }
+
+  // Parse input from INPUT.  Pass TRUE for EOF if the end of INPUT should
+  // finish the parse.
+
+  int
+  push_parser::run (const std::string& input, bool eof)
+  {
+    int status = -1;
+
+    dynamic_cast<push_lexer&> (lexer).append_input (input, eof);
+
+    do
+      {
+        YYSTYPE lval;
+
+        int token = octave_lex (&lval, scanner);
+
+        if (token < 0)
+          {
+            if (! eof && lexer.at_end_of_buffer ())
+              {
+                status = -1;
+                break;
+              }
+          }
+
+        yypstate *pstate = static_cast<yypstate *> (parser_state);
+
+        try
+          {
+            status = octave_push_parse (pstate, token, &lval, *this);
+          }
+        catch (octave_execution_exception& e)
+          {
+            std::string file = lexer.fcn_file_full_name;
+
+            if (file.empty ())
+              error (e, "parse error");
+            else
+              error (e, "parse error in %s", file.c_str ());
+          }
+        catch (octave_interrupt_exception &)
+          {
+            throw;
+          }
+        catch (...)
+          {
+            std::string file = lexer.fcn_file_full_name;
+
+            if (file.empty ())
+              error ("unexpected exception while parsing input");
+            else
+              error ("unexpected exception while parsing %s", file.c_str ());
+          }
+      }
+    while (status == YYPUSH_MORE);
+
+    if (status != 0)
+      parse_error ("%s", parse_error_msg.c_str ());
+
+    return status;
+  }
 }
 
 static void
@@ -4159,10 +4162,10 @@
     {
       frame.add_fcn (safe_fclose, ffile);
 
-      // octave_base_parser constructor sets this for us.
+      // octave::base_parser constructor sets this for us.
       frame.protect_var (LEXER);
 
-      octave_parser parser (ffile);
+      octave::parser parser (ffile);
 
       parser.curr_class_name = dispatch_type;
       parser.curr_package_name = package_name;
@@ -4942,7 +4945,7 @@
 {
   octave_value_list retval;
 
-  octave_parser parser (eval_str);
+  octave::parser parser (eval_str);
 
   do
     {
@@ -4986,7 +4989,7 @@
                     retval = octave_value_list ();
                 }
               else if (nargout == 0)
-                parser.stmt_list->accept (*current_evaluator);
+                parser.stmt_list->accept (*octave::current_evaluator);
               else
                 error ("eval: invalid use of statement list");
 
@@ -5208,7 +5211,7 @@
       // generally.  Any that go through Octave's parser should have
       // already been checked.
 
-      if (is_keyword (nm))
+      if (octave::is_keyword (nm))
         error ("assignin: invalid assignment to keyword '%s'", nm.c_str ());
 
       symbol_table::assign (nm, args(2));
--- a/libinterp/parse-tree/parse.h	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/parse-tree/parse.h	Tue Jul 12 14:28:07 2016 -0400
@@ -138,390 +138,393 @@
 
 extern OCTINTERP_API void cleanup_statement_list (tree_statement_list **lst);
 
-// Global access to currently active lexer.
-// FIXME: to be removed after more parser+lexer refactoring.
-extern octave_base_lexer *LEXER;
-
-class
-octave_base_parser
+namespace octave
 {
-public:
+  // Global access to currently active lexer.
+  // FIXME: to be removed after more parser+lexer refactoring.
+  extern base_lexer *LEXER;
 
-  octave_base_parser (octave_base_lexer& lxr);
+  class
+  base_parser
+  {
+  public:
 
-  ~octave_base_parser (void);
+    base_parser (base_lexer& lxr);
 
-  void reset (void);
+    ~base_parser (void);
 
-  // Error mesages for mismatched end tokens.
-  void end_token_error (token *tok, token::end_tok_type expected);
+    void reset (void);
+
+    // Error mesages for mismatched end tokens.
+    void end_token_error (token *tok, token::end_tok_type expected);
 
-  // Check to see that end tokens are properly matched.
-  bool end_token_ok (token *tok, token::end_tok_type expected);
+    // Check to see that end tokens are properly matched.
+    bool end_token_ok (token *tok, token::end_tok_type expected);
 
-  // Maybe print a warning if an assignment expression is used as the
-  // test in a logical expression.
-  void maybe_warn_assign_as_truth_value (tree_expression *expr);
+    // Maybe print a warning if an assignment expression is used as the
+    // test in a logical expression.
+    void maybe_warn_assign_as_truth_value (tree_expression *expr);
+
+    // Maybe print a warning about switch labels that aren't constants.
+    void maybe_warn_variable_switch_label (tree_expression *expr);
 
-  // Maybe print a warning about switch labels that aren't constants.
-  void maybe_warn_variable_switch_label (tree_expression *expr);
+    // Finish building a range.
+    tree_expression *finish_colon_expression (tree_colon_expression *e);
 
-  // Finish building a range.
-  tree_expression *finish_colon_expression (tree_colon_expression *e);
+    // Build a constant.
+    tree_constant *make_constant (int op, token *tok_val);
 
-  // Build a constant.
-  tree_constant *make_constant (int op, token *tok_val);
+    // Build a function handle.
+    tree_fcn_handle *make_fcn_handle (token *tok_val);
 
-  // Build a function handle.
-  tree_fcn_handle *make_fcn_handle (token *tok_val);
+    // Build an anonymous function handle.
+    tree_anon_fcn_handle *
+    make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt);
 
-  // Build an anonymous function handle.
-  tree_anon_fcn_handle *
-  make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt);
-
-  // Build a binary expression.
-  tree_expression *
-  make_binary_op (int op, tree_expression *op1, token *tok_val,
-                  tree_expression *op2);
+    // Build a binary expression.
+    tree_expression *
+    make_binary_op (int op, tree_expression *op1, token *tok_val,
+                    tree_expression *op2);
 
-  // Build a boolean expression.
-  tree_expression *
-  make_boolean_op (int op, tree_expression *op1, token *tok_val,
-                   tree_expression *op2);
+    // Build a boolean expression.
+    tree_expression *
+    make_boolean_op (int op, tree_expression *op1, token *tok_val,
+                     tree_expression *op2);
 
-  // Build a prefix expression.
-  tree_expression *
-  make_prefix_op (int op, tree_expression *op1, token *tok_val);
+    // Build a prefix expression.
+    tree_expression *
+    make_prefix_op (int op, tree_expression *op1, token *tok_val);
+
+    // Build a postfix expression.
+    tree_expression *
+    make_postfix_op (int op, tree_expression *op1, token *tok_val);
 
-  // Build a postfix expression.
-  tree_expression *
-  make_postfix_op (int op, tree_expression *op1, token *tok_val);
+    // Build an unwind-protect command.
+    tree_command *
+    make_unwind_command (token *unwind_tok, tree_statement_list *body,
+                         tree_statement_list *cleanup, token *end_tok,
+                         octave_comment_list *lc, octave_comment_list *mc);
 
-  // Build an unwind-protect command.
-  tree_command *
-  make_unwind_command (token *unwind_tok, tree_statement_list *body,
-                       tree_statement_list *cleanup, token *end_tok,
-                       octave_comment_list *lc, octave_comment_list *mc);
+    // Build a try-catch command.
+    tree_command *
+    make_try_command (token *try_tok, tree_statement_list *body,
+                      char catch_sep, tree_statement_list *cleanup,
+                      token *end_tok, octave_comment_list *lc,
+                      octave_comment_list *mc);
 
-  // Build a try-catch command.
-  tree_command *
-  make_try_command (token *try_tok, tree_statement_list *body,
-                    char catch_sep, tree_statement_list *cleanup,
-                    token *end_tok, octave_comment_list *lc,
-                    octave_comment_list *mc);
+    // Build a while command.
+    tree_command *
+    make_while_command (token *while_tok, tree_expression *expr,
+                        tree_statement_list *body, token *end_tok,
+                        octave_comment_list *lc);
 
-  // Build a while command.
-  tree_command *
-  make_while_command (token *while_tok, tree_expression *expr,
+    // Build a do-until command.
+    tree_command *
+    make_do_until_command (token *until_tok, tree_statement_list *body,
+                           tree_expression *expr, octave_comment_list *lc);
+
+    // Build a for command.
+    tree_command *
+    make_for_command (int tok_id, token *for_tok, tree_argument_list *lhs,
+                      tree_expression *expr, tree_expression *maxproc,
                       tree_statement_list *body, token *end_tok,
                       octave_comment_list *lc);
 
-  // Build a do-until command.
-  tree_command *
-  make_do_until_command (token *until_tok, tree_statement_list *body,
-                         tree_expression *expr, octave_comment_list *lc);
+    // Build a break command.
+    tree_command *make_break_command (token *break_tok);
+
+    // Build a continue command.
+    tree_command *make_continue_command (token *continue_tok);
 
-  // Build a for command.
-  tree_command *
-  make_for_command (int tok_id, token *for_tok, tree_argument_list *lhs,
-                    tree_expression *expr, tree_expression *maxproc,
-                    tree_statement_list *body, token *end_tok,
-                    octave_comment_list *lc);
+    // Build a return command.
+    tree_command *make_return_command (token *return_tok);
 
-  // Build a break command.
-  tree_command *make_break_command (token *break_tok);
+    // Start an if command.
+    tree_if_command_list *
+    start_if_command (tree_expression *expr, tree_statement_list *list);
 
-  // Build a continue command.
-  tree_command *make_continue_command (token *continue_tok);
+    // Finish an if command.
+    tree_if_command *
+    finish_if_command (token *if_tok, tree_if_command_list *list,
+                       token *end_tok, octave_comment_list *lc);
 
-  // Build a return command.
-  tree_command *make_return_command (token *return_tok);
+    // Build an elseif clause.
+    tree_if_clause *
+    make_elseif_clause (token *elseif_tok, tree_expression *expr,
+                        tree_statement_list *list, octave_comment_list *lc);
 
-  // Start an if command.
-  tree_if_command_list *
-  start_if_command (tree_expression *expr, tree_statement_list *list);
+    // Finish a switch command.
+    tree_switch_command *
+    finish_switch_command (token *switch_tok, tree_expression *expr,
+                           tree_switch_case_list *list, token *end_tok,
+                           octave_comment_list *lc);
 
-  // Finish an if command.
-  tree_if_command *
-  finish_if_command (token *if_tok, tree_if_command_list *list,
-                     token *end_tok, octave_comment_list *lc);
-
-  // Build an elseif clause.
-  tree_if_clause *
-  make_elseif_clause (token *elseif_tok, tree_expression *expr,
+    // Build a switch case.
+    tree_switch_case *
+    make_switch_case (token *case_tok, tree_expression *expr,
                       tree_statement_list *list, octave_comment_list *lc);
 
-  // Finish a switch command.
-  tree_switch_command *
-  finish_switch_command (token *switch_tok, tree_expression *expr,
-                         tree_switch_case_list *list, token *end_tok,
-                         octave_comment_list *lc);
+    // Build an assignment to a variable.
+    tree_expression *
+    make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
+                    tree_expression *rhs);
 
-  // Build a switch case.
-  tree_switch_case *
-  make_switch_case (token *case_tok, tree_expression *expr,
-                    tree_statement_list *list, octave_comment_list *lc);
+    // Define a script.
+    void make_script (tree_statement_list *cmds, tree_statement *end_script);
+
+    // Begin defining a function.
+    octave_user_function *
+    start_function (tree_parameter_list *param_list, tree_statement_list *body,
+                    tree_statement *end_function);
 
-  // Build an assignment to a variable.
-  tree_expression *
-  make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
-                  tree_expression *rhs);
+    // Create a no-op statement for end_function.
+    tree_statement *make_end (const std::string& type, bool eof, int l, int c);
 
-  // Define a script.
-  void make_script (tree_statement_list *cmds, tree_statement *end_script);
+    // Do most of the work for defining a function.
+    octave_user_function *
+    frob_function (const std::string& fname, octave_user_function *fcn);
 
-  // Begin defining a function.
-  octave_user_function *
-  start_function (tree_parameter_list *param_list, tree_statement_list *body,
-                  tree_statement *end_function);
+    // Finish defining a function.
+    tree_function_def *
+    finish_function (tree_parameter_list *ret_list,
+                     octave_user_function *fcn, octave_comment_list *lc,
+                     int l, int c);
 
-  // Create a no-op statement for end_function.
-  tree_statement *make_end (const std::string& type, bool eof, int l, int c);
-
-  // Do most of the work for defining a function.
-  octave_user_function *
-  frob_function (const std::string& fname, octave_user_function *fcn);
+    // Reset state after parsing function.
+    void
+    recover_from_parsing_function (void);
 
-  // Finish defining a function.
-  tree_function_def *
-  finish_function (tree_parameter_list *ret_list,
-                   octave_user_function *fcn, octave_comment_list *lc,
-                   int l, int c);
+    tree_funcall *
+    make_superclass_ref (const std::string& method_nm,
+                         const std::string& class_nm);
 
-  // Reset state after parsing function.
-  void
-  recover_from_parsing_function (void);
+    tree_funcall *
+    make_meta_class_query (const std::string& class_nm);
 
-  tree_funcall *
-  make_superclass_ref (const std::string& method_nm,
-                       const std::string& class_nm);
-
-  tree_funcall *
-  make_meta_class_query (const std::string& class_nm);
+    tree_classdef *
+    make_classdef (token *tok_val, tree_classdef_attribute_list *a,
+                   tree_identifier *id, tree_classdef_superclass_list *sc,
+                   tree_classdef_body *body, token *end_tok,
+                   octave_comment_list *lc);
 
-  tree_classdef *
-  make_classdef (token *tok_val, tree_classdef_attribute_list *a,
-                 tree_identifier *id, tree_classdef_superclass_list *sc,
-                 tree_classdef_body *body, token *end_tok,
-                 octave_comment_list *lc);
+    tree_classdef_properties_block *
+    make_classdef_properties_block (token *tok_val,
+                                    tree_classdef_attribute_list *a,
+                                    tree_classdef_property_list *plist,
+                                    token *end_tok, octave_comment_list *lc);
 
-  tree_classdef_properties_block *
-  make_classdef_properties_block (token *tok_val,
-                                  tree_classdef_attribute_list *a,
-                                  tree_classdef_property_list *plist,
-                                  token *end_tok, octave_comment_list *lc);
+    tree_classdef_methods_block *
+    make_classdef_methods_block (token *tok_val,
+                                 tree_classdef_attribute_list *a,
+                                 tree_classdef_methods_list *mlist,
+                                 token *end_tok, octave_comment_list *lc);
 
-  tree_classdef_methods_block *
-  make_classdef_methods_block (token *tok_val,
-                               tree_classdef_attribute_list *a,
-                               tree_classdef_methods_list *mlist,
-                               token *end_tok, octave_comment_list *lc);
+    tree_classdef_events_block *
+    make_classdef_events_block (token *tok_val,
+                                tree_classdef_attribute_list *a,
+                                tree_classdef_events_list *elist,
+                                token *end_tok, octave_comment_list *lc);
 
-  tree_classdef_events_block *
-  make_classdef_events_block (token *tok_val,
+    tree_classdef_enum_block *
+    make_classdef_enum_block (token *tok_val,
                               tree_classdef_attribute_list *a,
-                              tree_classdef_events_list *elist,
+                              tree_classdef_enum_list *elist,
                               token *end_tok, octave_comment_list *lc);
 
-  tree_classdef_enum_block *
-  make_classdef_enum_block (token *tok_val,
-                            tree_classdef_attribute_list *a,
-                            tree_classdef_enum_list *elist,
-                            token *end_tok, octave_comment_list *lc);
+    octave_user_function *
+    start_classdef_external_method (tree_identifier *id,
+                                    tree_parameter_list *pl);
 
-  octave_user_function *
-  start_classdef_external_method (tree_identifier *id,
-                                  tree_parameter_list *pl);
+    tree_function_def *
+    finish_classdef_external_method (octave_user_function *fcn,
+                                     tree_parameter_list *ret_list,
+                                     octave_comment_list *cl);
 
-  tree_function_def *
-  finish_classdef_external_method (octave_user_function *fcn,
-                                   tree_parameter_list *ret_list,
-                                   octave_comment_list *cl);
+    // Make an index expression.
+    tree_index_expression *
+    make_index_expression (tree_expression *expr,
+                           tree_argument_list *args, char type);
 
-  // Make an index expression.
-  tree_index_expression *
-  make_index_expression (tree_expression *expr,
-                         tree_argument_list *args, char type);
+    // Make an indirect reference expression.
+    tree_index_expression *
+    make_indirect_ref (tree_expression *expr, const std::string&);
 
-  // Make an indirect reference expression.
-  tree_index_expression *
-  make_indirect_ref (tree_expression *expr, const std::string&);
+    // Make an indirect reference expression with dynamic field name.
+    tree_index_expression *
+    make_indirect_ref (tree_expression *expr, tree_expression *field);
 
-  // Make an indirect reference expression with dynamic field name.
-  tree_index_expression *
-  make_indirect_ref (tree_expression *expr, tree_expression *field);
+    // Make a declaration command.
+    tree_decl_command *
+    make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst);
 
-  // Make a declaration command.
-  tree_decl_command *
-  make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst);
+    // Validate matrix or cell
+    bool validate_array_list (tree_expression *e);
 
-  // Validate matrix or cell
-  bool validate_array_list (tree_expression *e);
+    // Validate matrix object used in "[lhs] = ..." assignments.
+    tree_argument_list *validate_matrix_for_assignment (tree_expression *e);
 
-  // Validate matrix object used in "[lhs] = ..." assignments.
-  tree_argument_list *validate_matrix_for_assignment (tree_expression *e);
+    // Finish building an array_list (common action for finish_matrix
+    // and finish_cell).
+    tree_expression *finish_array_list (tree_array_list *a);
 
-  // Finish building an array_list (common action for finish_matrix
-  // and finish_cell).
-  tree_expression *finish_array_list (tree_array_list *a);
+    // Finish building a matrix list.
+    tree_expression *finish_matrix (tree_matrix *m);
 
-  // Finish building a matrix list.
-  tree_expression *finish_matrix (tree_matrix *m);
+    // Finish building a cell list.
+    tree_expression *finish_cell (tree_cell *c);
 
-  // Finish building a cell list.
-  tree_expression *finish_cell (tree_cell *c);
+    // Maybe print a warning.  Duh.
+    void maybe_warn_missing_semi (tree_statement_list *);
 
-  // Maybe print a warning.  Duh.
-  void maybe_warn_missing_semi (tree_statement_list *);
+    // Set the print flag for a statement based on the separator type.
+    tree_statement_list *
+    set_stmt_print_flag (tree_statement_list *, char, bool);
 
-  // Set the print flag for a statement based on the separator type.
-  tree_statement_list *
-  set_stmt_print_flag (tree_statement_list *, char, bool);
+    // Finish building a statement.
+    template <typename T>
+    tree_statement *make_statement (T *arg);
 
-  // Finish building a statement.
-  template <typename T>
-  tree_statement *make_statement (T *arg);
+    // Create a statement list.
+    tree_statement_list *make_statement_list (tree_statement *stmt);
 
-  // Create a statement list.
-  tree_statement_list *make_statement_list (tree_statement *stmt);
+    // Append a statement to an existing statement list.
+    tree_statement_list *
+    append_statement_list (tree_statement_list *list, char sep,
+                           tree_statement *stmt, bool warn_missing_semi);
 
-  // Append a statement to an existing statement list.
-  tree_statement_list *
-  append_statement_list (tree_statement_list *list, char sep,
-                         tree_statement *stmt, bool warn_missing_semi);
+    // Generic error messages.
+    void bison_error (const std::string& s, int l = -1, int c = -1);
 
-  // Generic error messages.
-  void bison_error (const std::string& s, int l = -1, int c = -1);
+    // Contains error message if Bison-generated parser returns non-zero
+    // status.
+    std::string parse_error_msg;
+
+    // Have we found an explicit end to a function?
+    bool endfunction_found;
 
-  // Contains error message if Bison-generated parser returns non-zero
-  // status.
-  std::string parse_error_msg;
-
-  // Have we found an explicit end to a function?
-  bool endfunction_found;
+    // TRUE means we are in the process of autoloading a function.
+    bool autoloading;
 
-  // TRUE means we are in the process of autoloading a function.
-  bool autoloading;
+    // TRUE means the current function file was found in a relative path
+    // element.
+    bool fcn_file_from_relative_lookup;
 
-  // TRUE means the current function file was found in a relative path
-  // element.
-  bool fcn_file_from_relative_lookup;
+    // FALSE if we are still at the primary function.  Subfunctions can
+    // only be declared inside function files.
+    bool parsing_subfunctions;
 
-  // FALSE if we are still at the primary function.  Subfunctions can
-  // only be declared inside function files.
-  bool parsing_subfunctions;
+    // Maximum function depth detected.  Used to determine whether
+    // we have nested functions or just implicitly ended subfunctions.
+    int max_fcn_depth;
 
-  // Maximum function depth detected.  Used to determine whether
-  // we have nested functions or just implicitly ended subfunctions.
-  int max_fcn_depth;
+    // = 0 currently outside any function.
+    // = 1 inside the primary function or a subfunction.
+    // > 1 means we are looking at a function definition that seems to be
+    //     inside a function.  Note that the function still might not be a
+    //     nested function.
+    int curr_fcn_depth;
 
-  // = 0 currently outside any function.
-  // = 1 inside the primary function or a subfunction.
-  // > 1 means we are looking at a function definition that seems to be
-  //     inside a function.  Note that the function still might not be a
-  //     nested function.
-  int curr_fcn_depth;
+    // Scope where we install all subfunctions and nested functions.  Only
+    // used while reading function files.
+    symbol_table::scope_id primary_fcn_scope;
 
-  // Scope where we install all subfunctions and nested functions.  Only
-  // used while reading function files.
-  symbol_table::scope_id primary_fcn_scope;
+    // Name of the current class when we are parsing class methods or
+    // constructors.
+    std::string curr_class_name;
 
-  // Name of the current class when we are parsing class methods or
-  // constructors.
-  std::string curr_class_name;
-
-  // Name of the current package when we are parsing an element contained
-  // in a package directory (+-directory).
-  std::string curr_package_name;
+    // Name of the current package when we are parsing an element contained
+    // in a package directory (+-directory).
+    std::string curr_package_name;
 
-  // A stack holding the nested function scopes being parsed.
-  // We don't use std::stack, because we want the clear method.  Also, we
-  // must access one from the top
-  std::vector<symbol_table::scope_id> function_scopes;
+    // A stack holding the nested function scopes being parsed.
+    // We don't use std::stack, because we want the clear method.  Also, we
+    // must access one from the top
+    std::vector<symbol_table::scope_id> function_scopes;
 
-  // Pointer to the primary user function or user script function.
-  octave_function *primary_fcn_ptr;
+    // Pointer to the primary user function or user script function.
+    octave_function *primary_fcn_ptr;
 
-  // List of subfunction names, initially in the order they are
-  // installed in the symbol table, then ordered as they appear in the
-  // file.  Eventually stashed in the primary function object.
-  std::list<std::string> subfunction_names;
+    // List of subfunction names, initially in the order they are
+    // installed in the symbol table, then ordered as they appear in the
+    // file.  Eventually stashed in the primary function object.
+    std::list<std::string> subfunction_names;
 
-  // Pointer to the classdef object we just parsed, if any.
-  tree_classdef *classdef_object;
+    // Pointer to the classdef object we just parsed, if any.
+    tree_classdef *classdef_object;
 
-  // Result of parsing input.
-  tree_statement_list *stmt_list;
+    // Result of parsing input.
+    tree_statement_list *stmt_list;
 
-  // State of the lexer.
-  octave_base_lexer& lexer;
+    // State of the lexer.
+    base_lexer& lexer;
 
-  // Internal state of the Bison parser.
-  void *parser_state;
+    // Internal state of the Bison parser.
+    void *parser_state;
 
-private:
+  private:
 
-  // No copying!
+    // No copying!
 
-  octave_base_parser (const octave_base_parser&);
+    base_parser (const base_parser&);
 
-  octave_base_parser& operator = (const octave_base_parser&);
-};
+    base_parser& operator = (const base_parser&);
+  };
 
-class
-octave_parser : public octave_base_parser
-{
-public:
+  class
+  parser : public base_parser
+  {
+  public:
 
-  octave_parser (void)
-    : octave_base_parser (*(new octave_lexer ()))
-  { }
+    parser (void)
+      : base_parser (*(new octave::lexer ()))
+    { }
 
-  octave_parser (FILE *file)
-    : octave_base_parser (*(new octave_lexer (file)))
-  { }
+    parser (FILE *file)
+      : base_parser (*(new octave::lexer (file)))
+    { }
 
-  octave_parser (const std::string& eval_string)
-    : octave_base_parser (*(new octave_lexer (eval_string)))
-  { }
+    parser (const std::string& eval_string)
+      : base_parser (*(new octave::lexer (eval_string)))
+    { }
 
-  octave_parser (octave_lexer& lxr)
-    : octave_base_parser (lxr)
-  { }
+    parser (octave::lexer& lxr)
+      : base_parser (lxr)
+    { }
 
-  ~octave_parser (void) { }
+    ~parser (void) { }
 
-  int run (void);
+    int run (void);
+
+  private:
 
-private:
+    // No copying!
 
-  // No copying!
+    parser (const parser&);
 
-  octave_parser (const octave_parser&);
-
-  octave_parser& operator = (const octave_parser&);
-};
+    parser& operator = (const parser&);
+  };
 
-class
-octave_push_parser : public octave_base_parser
-{
-public:
+  class
+  push_parser : public base_parser
+  {
+  public:
+
+    push_parser (void)
+      : base_parser (*(new octave::push_lexer ()))
+    { }
 
-  octave_push_parser (void)
-    : octave_base_parser (*(new octave_push_lexer ()))
-  { }
+    ~push_parser (void) { }
 
-  ~octave_push_parser (void) { }
+    int run (const std::string& input, bool eof);
 
-  int run (const std::string& input, bool eof);
+  private:
 
-private:
+    // No copying!
 
-  // No copying!
+    push_parser (const push_parser&);
 
-  octave_push_parser (const octave_push_parser&);
-
-  octave_push_parser& operator = (const octave_push_parser&);
-};
+    push_parser& operator = (const push_parser&);
+  };
+}
 
 #endif
--- a/libinterp/parse-tree/pt-assign.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/parse-tree/pt-assign.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -105,7 +105,7 @@
             retval = ult.value ();
 
           if (print_result ()
-              && tree_evaluator::statement_printing_enabled ())
+              && octave::tree_evaluator::statement_printing_enabled ())
             {
               // We clear any index here so that we can
               // get the new value of the referenced
@@ -319,7 +319,7 @@
             }
 
           if (print_result ()
-              && tree_evaluator::statement_printing_enabled ())
+              && octave::tree_evaluator::statement_printing_enabled ())
             {
               // We clear any index here so that we can get
               // the new value of the referenced object below,
--- a/libinterp/parse-tree/pt-eval.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/parse-tree/pt-eval.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -49,23 +49,6 @@
 //FIXME: This should be part of tree_evaluator
 #include "pt-jit.h"
 
-static tree_evaluator std_evaluator;
-
-tree_evaluator *current_evaluator = &std_evaluator;
-
-int tree_evaluator::dbstep_flag = 0;
-
-size_t tree_evaluator::current_frame = 0;
-
-bool tree_evaluator::debug_mode = false;
-
-bool tree_evaluator::quiet_breakpoint_flag = false;
-
-tree_evaluator::stmt_list_type tree_evaluator::statement_context
-  = tree_evaluator::other;
-
-bool tree_evaluator::in_loop_command = false;
-
 // Maximum nesting level for functions, scripts, or sourced files called
 // recursively.
 int Vmax_recursion_depth = 256;
@@ -74,67 +57,83 @@
 // semicolon has been appended to each statement).
 static bool Vsilent_functions = false;
 
-// Normal evaluator.
-
-void
-tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&)
+namespace octave
 {
-  panic_impossible ();
-}
+  int tree_evaluator::dbstep_flag = 0;
+
+  size_t tree_evaluator::current_frame = 0;
+
+  bool tree_evaluator::debug_mode = false;
 
-void
-tree_evaluator::visit_argument_list (tree_argument_list&)
-{
-  panic_impossible ();
-}
+  bool tree_evaluator::quiet_breakpoint_flag = false;
+
+  tree_evaluator::stmt_list_type tree_evaluator::statement_context
+  = tree_evaluator::other;
+
+  bool tree_evaluator::in_loop_command = false;
+
+  // Normal evaluator.
 
-void
-tree_evaluator::visit_binary_expression (tree_binary_expression&)
-{
-  panic_impossible ();
-}
+  void
+  tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&)
+  {
+    panic_impossible ();
+  }
 
-void
-tree_evaluator::visit_break_command (tree_break_command& cmd)
-{
-  if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint (true));
+  void
+  tree_evaluator::visit_argument_list (tree_argument_list&)
+  {
+    panic_impossible ();
+  }
 
-  if (statement_context == function || statement_context == script
-      || in_loop_command)
-    tree_break_command::breaking = 1;
-}
+  void
+  tree_evaluator::visit_binary_expression (tree_binary_expression&)
+  {
+    panic_impossible ();
+  }
 
-void
-tree_evaluator::visit_colon_expression (tree_colon_expression&)
-{
-  panic_impossible ();
-}
+  void
+  tree_evaluator::visit_break_command (tree_break_command& cmd)
+  {
+    if (debug_mode)
+      do_breakpoint (cmd.is_breakpoint (true));
 
-void
-tree_evaluator::visit_continue_command (tree_continue_command& cmd)
-{
-  if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint (true));
+    if (statement_context == function || statement_context == script
+        || in_loop_command)
+      tree_break_command::breaking = 1;
+  }
+
+  void
+  tree_evaluator::visit_colon_expression (tree_colon_expression&)
+  {
+    panic_impossible ();
+  }
 
-  if (statement_context == function || statement_context == script
-      || in_loop_command)
-    tree_continue_command::continuing = 1;
-}
+  void
+  tree_evaluator::visit_continue_command (tree_continue_command& cmd)
+  {
+    if (debug_mode)
+      do_breakpoint (cmd.is_breakpoint (true));
+
+    if (statement_context == function || statement_context == script
+        || in_loop_command)
+      tree_continue_command::continuing = 1;
+  }
 
-void
-tree_evaluator::reset_debug_state (void)
-{
-  debug_mode = bp_table::have_breakpoints () || Vdebugging;
+  void
+  tree_evaluator::reset_debug_state (void)
+  {
+    debug_mode = bp_table::have_breakpoints () || Vdebugging;
 
-  dbstep_flag = 0;
-}
+    dbstep_flag = 0;
+  }
 
-bool
-tree_evaluator::statement_printing_enabled (void)
-{
-  return ! (Vsilent_functions && (statement_context == function
-                                  || statement_context == script));
+  bool
+  tree_evaluator::statement_printing_enabled (void)
+  {
+    return ! (Vsilent_functions && (statement_context == function
+                                    || statement_context == script));
+  }
 }
 
 static inline void
@@ -191,71 +190,53 @@
     }
 }
 
-void
-tree_evaluator::do_decl_init_list (decl_elt_init_fcn fcn,
-                                   tree_decl_init_list *init_list)
+namespace octave
 {
-  if (init_list)
-    {
-      for (tree_decl_init_list::iterator p = init_list->begin ();
-           p != init_list->end (); p++)
-        {
-          tree_decl_elt *elt = *p;
+  void
+  tree_evaluator::do_decl_init_list (decl_elt_init_fcn fcn,
+                                     tree_decl_init_list *init_list)
+  {
+    if (init_list)
+      {
+        for (tree_decl_init_list::iterator p = init_list->begin ();
+             p != init_list->end (); p++)
+          {
+            tree_decl_elt *elt = *p;
 
-          fcn (*elt);
-        }
-    }
-}
+            fcn (*elt);
+          }
+      }
+  }
 
-void
-tree_evaluator::visit_global_command (tree_global_command& cmd)
-{
-  if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint (true));
-
-  do_decl_init_list (do_global_init, cmd.initializer_list ());
-}
-
-void
-tree_evaluator::visit_persistent_command (tree_persistent_command& cmd)
-{
-  if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint (true));
+  void
+  tree_evaluator::visit_global_command (tree_global_command& cmd)
+  {
+    if (debug_mode)
+      do_breakpoint (cmd.is_breakpoint (true));
 
-  do_decl_init_list (do_static_init, cmd.initializer_list ());
-}
+    do_decl_init_list (do_global_init, cmd.initializer_list ());
+  }
 
-void
-tree_evaluator::visit_decl_elt (tree_decl_elt&)
-{
-  panic_impossible ();
-}
+  void
+  tree_evaluator::visit_persistent_command (tree_persistent_command& cmd)
+  {
+    if (debug_mode)
+      do_breakpoint (cmd.is_breakpoint (true));
 
-#if 0
-bool
-tree_decl_elt::eval (void)
-{
-  bool retval = false;
+    do_decl_init_list (do_static_init, cmd.initializer_list ());
+  }
 
-  if (id && expr)
-    {
-      octave_lvalue ult = id->lvalue ();
-
-      octave_value init_val = expr->rvalue1 ();
-
-      ult.assign (octave_value::op_asn_eq, init_val);
+  void
+  tree_evaluator::visit_decl_elt (tree_decl_elt&)
+  {
+    panic_impossible ();
+  }
 
-      retval = true;
-    }
-
-  return retval;
-}
-#endif
-
-void
-tree_evaluator::visit_decl_init_list (tree_decl_init_list&)
-{
-  panic_impossible ();
+  void
+  tree_evaluator::visit_decl_init_list (tree_decl_init_list&)
+  {
+    panic_impossible ();
+  }
 }
 
 // Decide if it's time to quit a for or while loop.
@@ -279,920 +260,922 @@
   return quit;
 }
 
-void
-tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd)
+namespace octave
 {
-  if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint (true));
-
-  // FIXME: need to handle PARFOR loops here using cmd.in_parallel ()
-  // and cmd.maxproc_expr ();
+  void
+  tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd)
+  {
+    if (debug_mode)
+      do_breakpoint (cmd.is_breakpoint (true));
 
-  octave::unwind_protect frame;
+    // FIXME: need to handle PARFOR loops here using cmd.in_parallel ()
+    // and cmd.maxproc_expr ();
 
-  frame.protect_var (in_loop_command);
+    octave::unwind_protect frame;
 
-  in_loop_command = true;
+    frame.protect_var (in_loop_command);
+
+    in_loop_command = true;
 
-  tree_expression *expr = cmd.control_expr ();
+    tree_expression *expr = cmd.control_expr ();
 
-  octave_value rhs = expr->rvalue1 ();
+    octave_value rhs = expr->rvalue1 ();
 
 #if defined (HAVE_LLVM)
-  if (tree_jit::execute (cmd, rhs))
-    return;
+    if (tree_jit::execute (cmd, rhs))
+      return;
 #endif
 
-  if (rhs.is_undefined ())
-    return;
+    if (rhs.is_undefined ())
+      return;
+
+    tree_expression *lhs = cmd.left_hand_side ();
+
+    octave_lvalue ult = lhs->lvalue ();
+
+    tree_statement_list *loop_body = cmd.body ();
+
+    if (rhs.is_range ())
+      {
+        Range rng = rhs.range_value ();
+
+        octave_idx_type steps = rng.numel ();
+
+        for (octave_idx_type i = 0; i < steps; i++)
+          {
+            octave_value val (rng.elem (i));
+
+            ult.assign (octave_value::op_asn_eq, val);
+
+            if (loop_body)
+              loop_body->accept (*this);
 
-  tree_expression *lhs = cmd.left_hand_side ();
+            if (quit_loop_now ())
+              break;
+          }
+      }
+    else if (rhs.is_scalar_type ())
+      {
+        ult.assign (octave_value::op_asn_eq, rhs);
+
+        if (loop_body)
+          loop_body->accept (*this);
 
-  octave_lvalue ult = lhs->lvalue ();
+        // Maybe decrement break and continue states.
+        quit_loop_now ();
+      }
+    else if (rhs.is_matrix_type () || rhs.is_cell () || rhs.is_string ()
+             || rhs.is_map ())
+      {
+        // A matrix or cell is reshaped to 2 dimensions and iterated by
+        // columns.
+
+        dim_vector dv = rhs.dims ().redim (2);
+
+        octave_idx_type nrows = dv(0);
+        octave_idx_type steps = dv(1);
+
+        if (steps > 0)
+          {
+            octave_value arg = rhs;
+            if (rhs.ndims () > 2)
+              arg = arg.reshape (dv);
 
-  tree_statement_list *loop_body = cmd.body ();
+            // for row vectors, use single index to speed things up.
+            octave_value_list idx;
+            octave_idx_type iidx;
+            if (nrows == 1)
+              {
+                idx.resize (1);
+                iidx = 0;
+              }
+            else
+              {
+                idx.resize (2);
+                idx(0) = octave_value::magic_colon_t;
+                iidx = 1;
+              }
+
+            for (octave_idx_type i = 1; i <= steps; i++)
+              {
+                // do_index_op expects one-based indices.
+                idx(iidx) = i;
+                octave_value val = arg.do_index_op (idx);
+
+                ult.assign (octave_value::op_asn_eq, val);
+
+                if (loop_body)
+                  loop_body->accept (*this);
+
+                if (quit_loop_now ())
+                  break;
+              }
+          }
+      }
+    else
+      error ("invalid type in for loop expression near line %d, column %d",
+             cmd.line (), cmd.column ());
+  }
 
-  if (rhs.is_range ())
-    {
-      Range rng = rhs.range_value ();
+  void
+  tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd)
+  {
+    if (debug_mode)
+      do_breakpoint (cmd.is_breakpoint (true));
+
+    octave::unwind_protect frame;
+
+    frame.protect_var (in_loop_command);
+
+    in_loop_command = true;
+
+    tree_expression *expr = cmd.control_expr ();
+
+    octave_value rhs = expr->rvalue1 ();
+
+    if (rhs.is_undefined ())
+      return;
+
+    if (! rhs.is_map ())
+      error ("in statement 'for [X, Y] = VAL', VAL must be a structure");
 
-      octave_idx_type steps = rng.numel ();
+    // Cycle through structure elements.  First element of id_list
+    // is set to value and the second is set to the name of the
+    // structure element.
+
+    tree_argument_list *lhs = cmd.left_hand_side ();
+
+    tree_argument_list::iterator p = lhs->begin ();
+
+    tree_expression *elt = *p++;
+
+    octave_lvalue val_ref = elt->lvalue ();
+
+    elt = *p;
+
+    octave_lvalue key_ref = elt->lvalue ();
+
+    const octave_map tmp_val = rhs.map_value ();
+
+    tree_statement_list *loop_body = cmd.body ();
+
+    string_vector keys = tmp_val.keys ();
+
+    octave_idx_type nel = keys.numel ();
 
-      for (octave_idx_type i = 0; i < steps; i++)
-        {
-          octave_value val (rng.elem (i));
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        std::string key = keys[i];
+
+        const Cell val_lst = tmp_val.contents (key);
+
+        octave_idx_type n = val_lst.numel ();
+
+        octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst);
+
+        val_ref.assign (octave_value::op_asn_eq, val);
+        key_ref.assign (octave_value::op_asn_eq, key);
+
+        if (loop_body)
+          loop_body->accept (*this);
+
+        if (quit_loop_now ())
+          break;
+      }
+  }
+
+  void
+  tree_evaluator::visit_octave_user_script (octave_user_script&)
+  {
+    panic_impossible ();
+  }
 
-          ult.assign (octave_value::op_asn_eq, val);
+  void
+  tree_evaluator::visit_octave_user_function (octave_user_function&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_octave_user_function_header (octave_user_function&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_octave_user_function_trailer (octave_user_function&)
+  {
+    panic_impossible ();
+  }
 
-          if (loop_body)
-            loop_body->accept (*this);
+  void
+  tree_evaluator::visit_function_def (tree_function_def& cmd)
+  {
+    octave_value fcn = cmd.function ();
+
+    octave_function *f = fcn.function_value ();
+
+    if (f)
+      {
+        std::string nm = f->name ();
+
+        symbol_table::install_cmdline_function (nm, fcn);
+
+        // Make sure that any variable with the same name as the new
+        // function is cleared.
+
+        symbol_table::assign (nm);
+      }
+  }
 
-          if (quit_loop_now ())
+  void
+  tree_evaluator::visit_identifier (tree_identifier&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_if_clause (tree_if_clause&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_if_command (tree_if_command& cmd)
+  {
+    tree_if_command_list *lst = cmd.cmd_list ();
+
+    if (lst)
+      lst->accept (*this);
+  }
+
+  void
+  tree_evaluator::visit_if_command_list (tree_if_command_list& lst)
+  {
+    for (tree_if_command_list::iterator p = lst.begin (); p != lst.end (); p++)
+      {
+        tree_if_clause *tic = *p;
+
+        tree_expression *expr = tic->condition ();
+
+        if (statement_context == function || statement_context == script)
+          octave_call_stack::set_location (tic->line (), tic->column ());
+
+        if (debug_mode && ! tic->is_else_clause ())
+          do_breakpoint (tic->is_breakpoint (true));
+
+        if (tic->is_else_clause () || expr->is_logically_true ("if"))
+          {
+            tree_statement_list *stmt_lst = tic->commands ();
+
+            if (stmt_lst)
+              stmt_lst->accept (*this);
+
             break;
-        }
-    }
-  else if (rhs.is_scalar_type ())
-    {
-      ult.assign (octave_value::op_asn_eq, rhs);
+          }
+      }
+  }
+
+  void
+  tree_evaluator::visit_index_expression (tree_index_expression&)
+  {
+    panic_impossible ();
+  }
 
-      if (loop_body)
-        loop_body->accept (*this);
+  void
+  tree_evaluator::visit_matrix (tree_matrix&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_cell (tree_cell&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_multi_assignment (tree_multi_assignment&)
+  {
+    panic_impossible ();
+  }
 
-      // Maybe decrement break and continue states.
-      quit_loop_now ();
-    }
-  else if (rhs.is_matrix_type () || rhs.is_cell () || rhs.is_string ()
-           || rhs.is_map ())
-    {
-      // A matrix or cell is reshaped to 2 dimensions and iterated by
-      // columns.
+  void
+  tree_evaluator::visit_no_op_command (tree_no_op_command& cmd)
+  {
+    if (debug_mode && cmd.is_end_of_fcn_or_script ())
+      do_breakpoint (cmd.is_breakpoint (true), true);
+  }
+
+  void
+  tree_evaluator::visit_constant (tree_constant&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_fcn_handle (tree_fcn_handle&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_funcall (tree_funcall&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_parameter_list (tree_parameter_list&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_postfix_expression (tree_postfix_expression&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_prefix_expression (tree_prefix_expression&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_return_command (tree_return_command& cmd)
+  {
+    if (debug_mode)
+      do_breakpoint (cmd.is_breakpoint (true));
+
+    // Act like dbcont.
+
+    if (Vdebugging
+        && octave_call_stack::current_frame () == current_frame)
+      {
+        Vdebugging = false;
+
+        reset_debug_state ();
+      }
+    else if (statement_context == function || statement_context == script
+             || in_loop_command)
+      tree_return_command::returning = 1;
+  }
 
-      dim_vector dv = rhs.dims ().redim (2);
+  void
+  tree_evaluator::visit_return_list (tree_return_list&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_simple_assignment (tree_simple_assignment&)
+  {
+    panic_impossible ();
+  }
 
-      octave_idx_type nrows = dv(0);
-      octave_idx_type steps = dv(1);
+  void
+  tree_evaluator::visit_statement (tree_statement& stmt)
+  {
+    tree_command *cmd = stmt.command ();
+    tree_expression *expr = stmt.expression ();
+
+    if (cmd || expr)
+      {
+        if (statement_context == function || statement_context == script)
+          {
+            // Skip commands issued at a debug> prompt to avoid disturbing
+            // the state of the program we are debugging.
+
+            if (Vtrack_line_num)
+              octave_call_stack::set_location (stmt.line (), stmt.column ());
 
-      if (steps > 0)
-        {
-          octave_value arg = rhs;
-          if (rhs.ndims () > 2)
-            arg = arg.reshape (dv);
+            if ((statement_context == script
+                 && ((Vecho_executing_commands & ECHO_SCRIPTS
+                      && octave_call_stack::all_scripts ())
+                     || Vecho_executing_commands & ECHO_FUNCTIONS))
+                || (statement_context == function
+                    && Vecho_executing_commands & ECHO_FUNCTIONS))
+              stmt.echo_code ();
+          }
+
+        try
+          {
+            if (cmd)
+              cmd->accept (*this);
+            else
+              {
+                if (debug_mode)
+                  do_breakpoint (expr->is_breakpoint (true));
+
+                // FIXME: maybe all of this should be packaged in
+                // one virtual function that returns a flag saying whether
+                // or not the expression will take care of binding ans and
+                // printing the result.
+
+                // FIXME: it seems that we should just have to
+                // call expr->rvalue1 () and that should take care of
+                // everything, binding ans as necessary?
+
+                bool do_bind_ans = false;
+
+                if (expr->is_identifier ())
+                  {
+                    tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
+
+                    do_bind_ans = (! id->is_variable ());
+                  }
+                else
+                  do_bind_ans = (! expr->is_assignment_expression ());
+
+                octave_value tmp_result = expr->rvalue1 (0);
+
+                if (do_bind_ans && tmp_result.is_defined ())
+                  bind_ans (tmp_result, expr->print_result ()
+                            && statement_printing_enabled ());
 
-          // for row vectors, use single index to speed things up.
-          octave_value_list idx;
-          octave_idx_type iidx;
-          if (nrows == 1)
+                //              if (tmp_result.is_defined ())
+                //                result_values(0) = tmp_result;
+              }
+          }
+        catch (const std::bad_alloc&)
+          {
+            // FIXME: We want to use error_with_id here so that give users
+            // control over this error message but error_with_id will
+            // require some memory allocations.  Is there anything we can
+            // do to make those more likely to succeed?
+
+            error_with_id ("Octave:bad-alloc",
+                           "out of memory or dimension too large for Octave's index type");
+          }
+      }
+  }
+
+  void
+  tree_evaluator::visit_statement_list (tree_statement_list& lst)
+  {
+    // FIXME: commented out along with else clause below.
+    // static octave_value_list empty_list;
+
+    tree_statement_list::iterator p = lst.begin ();
+
+    if (p != lst.end ())
+      {
+        while (true)
+          {
+            tree_statement *elt = *p++;
+
+            if (! elt)
+              error ("invalid statement found in statement list!");
+
+            octave_quit ();
+
+            elt->accept (*this);
+
+            if (tree_break_command::breaking
+                || tree_continue_command::continuing)
+              break;
+
+            if (tree_return_command::returning)
+              break;
+
+            if (p == lst.end ())
+              break;
+            else
+              {
+                // Clear previous values before next statement is
+                // evaluated so that we aren't holding an extra
+                // reference to a value that may be used next.  For
+                // example, in code like this:
+                //
+                //   X = rand (N);  # refcount for X should be 1
+                //                  # after this statement
+                //
+                //   X(idx) = val;  # no extra copy of X should be
+                //                  # needed, but we will be faked
+                //                  # out if retval is not cleared
+                //                  # between statements here
+
+                //              result_values = empty_list;
+              }
+          }
+      }
+  }
+
+  void
+  tree_evaluator::visit_switch_case (tree_switch_case&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_switch_case_list (tree_switch_case_list&)
+  {
+    panic_impossible ();
+  }
+
+  void
+  tree_evaluator::visit_switch_command (tree_switch_command& cmd)
+  {
+    if (debug_mode)
+      do_breakpoint (cmd.is_breakpoint (true));
+
+    tree_expression *expr = cmd.switch_value ();
+
+    if (! expr)
+      error ("missing value in switch command near line %d, column %d",
+             cmd.line (), cmd.column ());
+
+    octave_value val = expr->rvalue1 ();
+
+    tree_switch_case_list *lst = cmd.case_list ();
+
+    if (lst)
+      {
+        for (tree_switch_case_list::iterator p = lst->begin ();
+             p != lst->end (); p++)
+          {
+            tree_switch_case *t = *p;
+
+            if (t->is_default_case () || t->label_matches (val))
+              {
+                tree_statement_list *stmt_lst = t->commands ();
+
+                if (stmt_lst)
+                  stmt_lst->accept (*this);
+
+                break;
+              }
+          }
+      }
+  }
+
+  void
+  tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd)
+  {
+    bool execution_error = false;
+
+    { // unwind frame before catch block
+      octave::unwind_protect frame;
+
+      frame.protect_var (buffer_error_messages);
+      frame.protect_var (Vdebug_on_error);
+      frame.protect_var (Vdebug_on_warning);
+
+      buffer_error_messages++;
+      Vdebug_on_error = false;
+      Vdebug_on_warning = false;
+
+      // The catch code is *not* added to unwind_protect stack;
+      // it doesn't need to be run on interrupts.
+
+      tree_statement_list *try_code = cmd.body ();
+
+      if (try_code)
+        {
+          try
             {
-              idx.resize (1);
-              iidx = 0;
-            }
-          else
-            {
-              idx.resize (2);
-              idx(0) = octave_value::magic_colon_t;
-              iidx = 1;
+              in_try_catch++;
+              try_code->accept (*this);
+              in_try_catch--;
             }
-
-          for (octave_idx_type i = 1; i <= steps; i++)
+          catch (const octave_execution_exception&)
             {
-              // do_index_op expects one-based indices.
-              idx(iidx) = i;
-              octave_value val = arg.do_index_op (idx);
+              recover_from_exception ();
 
-              ult.assign (octave_value::op_asn_eq, val);
-
-              if (loop_body)
-                loop_body->accept (*this);
-
-              if (quit_loop_now ())
-                break;
+              in_try_catch--;          // must be restored before "catch" block
+              execution_error = true;
             }
         }
+      // Unwind to let the user print any messages from
+      // errors that occurred in the body of the try_catch statement,
+      // or throw further errors.
     }
-  else
-    error ("invalid type in for loop expression near line %d, column %d",
-           cmd.line (), cmd.column ());
-}
-
-void
-tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd)
-{
-  if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint (true));
-
-  octave::unwind_protect frame;
-
-  frame.protect_var (in_loop_command);
-
-  in_loop_command = true;
-
-  tree_expression *expr = cmd.control_expr ();
-
-  octave_value rhs = expr->rvalue1 ();
-
-  if (rhs.is_undefined ())
-    return;
-
-  if (! rhs.is_map ())
-    error ("in statement 'for [X, Y] = VAL', VAL must be a structure");
-
-  // Cycle through structure elements.  First element of id_list
-  // is set to value and the second is set to the name of the
-  // structure element.
-
-  tree_argument_list *lhs = cmd.left_hand_side ();
-
-  tree_argument_list::iterator p = lhs->begin ();
-
-  tree_expression *elt = *p++;
-
-  octave_lvalue val_ref = elt->lvalue ();
-
-  elt = *p;
-
-  octave_lvalue key_ref = elt->lvalue ();
-
-  const octave_map tmp_val = rhs.map_value ();
-
-  tree_statement_list *loop_body = cmd.body ();
-
-  string_vector keys = tmp_val.keys ();
-
-  octave_idx_type nel = keys.numel ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      std::string key = keys[i];
-
-      const Cell val_lst = tmp_val.contents (key);
-
-      octave_idx_type n = val_lst.numel ();
-
-      octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst);
-
-      val_ref.assign (octave_value::op_asn_eq, val);
-      key_ref.assign (octave_value::op_asn_eq, key);
-
-      if (loop_body)
-        loop_body->accept (*this);
-
-      if (quit_loop_now ())
-        break;
-    }
-}
-
-void
-tree_evaluator::visit_octave_user_script (octave_user_script&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_octave_user_function (octave_user_function&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_octave_user_function_header (octave_user_function&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_octave_user_function_trailer (octave_user_function&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_function_def (tree_function_def& cmd)
-{
-  octave_value fcn = cmd.function ();
-
-  octave_function *f = fcn.function_value ();
-
-  if (f)
-    {
-      std::string nm = f->name ();
-
-      symbol_table::install_cmdline_function (nm, fcn);
 
-      // Make sure that any variable with the same name as the new
-      // function is cleared.
-
-      symbol_table::assign (nm);
-    }
-}
-
-void
-tree_evaluator::visit_identifier (tree_identifier&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_if_clause (tree_if_clause&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_if_command (tree_if_command& cmd)
-{
-  tree_if_command_list *lst = cmd.cmd_list ();
-
-  if (lst)
-    lst->accept (*this);
-}
-
-void
-tree_evaluator::visit_if_command_list (tree_if_command_list& lst)
-{
-  for (tree_if_command_list::iterator p = lst.begin (); p != lst.end (); p++)
-    {
-      tree_if_clause *tic = *p;
-
-      tree_expression *expr = tic->condition ();
-
-      if (statement_context == function || statement_context == script)
-        octave_call_stack::set_location (tic->line (), tic->column ());
-
-      if (debug_mode && ! tic->is_else_clause ())
-        do_breakpoint (tic->is_breakpoint (true));
-
-      if (tic->is_else_clause () || expr->is_logically_true ("if"))
-        {
-          tree_statement_list *stmt_lst = tic->commands ();
-
-          if (stmt_lst)
-            stmt_lst->accept (*this);
-
-          break;
-        }
-    }
-}
+    if (execution_error)
+      {
+        tree_statement_list *catch_code = cmd.cleanup ();
+        if (catch_code)
+          {
+            tree_identifier *expr_id = cmd.identifier ();
+            octave_lvalue ult;
 
-void
-tree_evaluator::visit_index_expression (tree_index_expression&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_matrix (tree_matrix&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_cell (tree_cell&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_multi_assignment (tree_multi_assignment&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_no_op_command (tree_no_op_command& cmd)
-{
-  if (debug_mode && cmd.is_end_of_fcn_or_script ())
-    do_breakpoint (cmd.is_breakpoint (true), true);
-}
-
-void
-tree_evaluator::visit_constant (tree_constant&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_fcn_handle (tree_fcn_handle&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_funcall (tree_funcall&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_parameter_list (tree_parameter_list&)
-{
-  panic_impossible ();
-}
+            if (expr_id)
+              {
+                ult = expr_id->lvalue ();
 
-void
-tree_evaluator::visit_postfix_expression (tree_postfix_expression&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_prefix_expression (tree_prefix_expression&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_return_command (tree_return_command& cmd)
-{
-  if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint (true));
-
-  // Act like dbcont.
-
-  if (Vdebugging
-      && octave_call_stack::current_frame () == current_frame)
-    {
-      Vdebugging = false;
-
-      reset_debug_state ();
-    }
-  else if (statement_context == function || statement_context == script
-           || in_loop_command)
-    tree_return_command::returning = 1;
-}
-
-void
-tree_evaluator::visit_return_list (tree_return_list&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_simple_assignment (tree_simple_assignment&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_statement (tree_statement& stmt)
-{
-  tree_command *cmd = stmt.command ();
-  tree_expression *expr = stmt.expression ();
+                octave_scalar_map err;
 
-  if (cmd || expr)
-    {
-      if (statement_context == function || statement_context == script)
-        {
-          // Skip commands issued at a debug> prompt to avoid disturbing
-          // the state of the program we are debugging, but still track
-          // progress through user functions called from debug> prompt.
-
-          if (Vtrack_line_num)
-            octave_call_stack::set_location (stmt.line (), stmt.column ());
-
-          if ((statement_context == script
-               && ((Vecho_executing_commands & ECHO_SCRIPTS
-                    && octave_call_stack::all_scripts ())
-                   || Vecho_executing_commands & ECHO_FUNCTIONS))
-              || (statement_context == function
-                  && Vecho_executing_commands & ECHO_FUNCTIONS))
-            stmt.echo_code ();
-        }
+                err.assign ("message", last_error_message ());
+                err.assign ("identifier", last_error_id ());
+                err.assign ("stack", last_error_stack ());
 
-      try
-        {
-          if (cmd)
-            cmd->accept (*this);
-          else
-            {
-              if (debug_mode)
-                do_breakpoint (expr->is_breakpoint (true));
-
-              // FIXME: maybe all of this should be packaged in
-              // one virtual function that returns a flag saying whether
-              // or not the expression will take care of binding ans and
-              // printing the result.
-
-              // FIXME: it seems that we should just have to
-              // call expr->rvalue1 () and that should take care of
-              // everything, binding ans as necessary?
-
-              bool do_bind_ans = false;
-
-              if (expr->is_identifier ())
-                {
-                  tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
-
-                  do_bind_ans = (! id->is_variable ());
-                }
-              else
-                do_bind_ans = (! expr->is_assignment_expression ());
-
-              octave_value tmp_result = expr->rvalue1 (0);
-
-              if (do_bind_ans && tmp_result.is_defined ())
-                bind_ans (tmp_result, expr->print_result ()
-                          && statement_printing_enabled ());
+                ult.assign (octave_value::op_asn_eq, err);
+              }
 
-              //              if (tmp_result.is_defined ())
-              //                result_values(0) = tmp_result;
-            }
-        }
-      catch (const std::bad_alloc&)
-        {
-          // FIXME: We want to use error_with_id here so that give users
-          // control over this error message but error_with_id will
-          // require some memory allocations.  Is there anything we can
-          // do to make those more likely to succeed?
-
-          error_with_id ("Octave:bad-alloc",
-                         "out of memory or dimension too large for Octave's index type");
-        }
-    }
-}
-
-void
-tree_evaluator::visit_statement_list (tree_statement_list& lst)
-{
-  // FIXME: commented out along with else clause below.
-  // static octave_value_list empty_list;
-
-  tree_statement_list::iterator p = lst.begin ();
-
-  if (p != lst.end ())
-    {
-      while (true)
-        {
-          tree_statement *elt = *p++;
-
-          if (! elt)
-            error ("invalid statement found in statement list!");
-
-          octave_quit ();
-
-          elt->accept (*this);
-
-          if (tree_break_command::breaking
-              || tree_continue_command::continuing)
-            break;
-
-          if (tree_return_command::returning)
-            break;
+            // perform actual "catch" block
+            if (catch_code)
+              catch_code->accept (*this);
+          }
+      }
+  }
 
-          if (p == lst.end ())
-            break;
-          else
-            {
-              // Clear previous values before next statement is
-              // evaluated so that we aren't holding an extra
-              // reference to a value that may be used next.  For
-              // example, in code like this:
-              //
-              //   X = rand (N);  # refcount for X should be 1
-              //                  # after this statement
-              //
-              //   X(idx) = val;  # no extra copy of X should be
-              //                  # needed, but we will be faked
-              //                  # out if retval is not cleared
-              //                  # between statements here
-
-              //              result_values = empty_list;
-            }
-        }
-    }
-}
-
-void
-tree_evaluator::visit_switch_case (tree_switch_case&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_switch_case_list (tree_switch_case_list&)
-{
-  panic_impossible ();
-}
-
-void
-tree_evaluator::visit_switch_command (tree_switch_command& cmd)
-{
-  if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint (true));
-
-  tree_expression *expr = cmd.switch_value ();
-
-  if (! expr)
-    error ("missing value in switch command near line %d, column %d",
-           cmd.line (), cmd.column ());
-
-  octave_value val = expr->rvalue1 ();
-
-  tree_switch_case_list *lst = cmd.case_list ();
-
-  if (lst)
-    {
-      for (tree_switch_case_list::iterator p = lst->begin ();
-           p != lst->end (); p++)
-        {
-          tree_switch_case *t = *p;
-
-          if (t->is_default_case () || t->label_matches (val))
-            {
-              tree_statement_list *stmt_lst = t->commands ();
-
-              if (stmt_lst)
-                stmt_lst->accept (*this);
-
-              break;
-            }
-        }
-    }
-}
-
-void
-tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd)
-{
-  bool execution_error = false;
-
-  { // unwind frame before catch block
+  void
+  tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list)
+  {
     octave::unwind_protect frame;
 
-    frame.protect_var (buffer_error_messages);
-    frame.protect_var (Vdebug_on_error);
-    frame.protect_var (Vdebug_on_warning);
+    frame.protect_var (octave_interrupt_state);
+    octave_interrupt_state = 0;
+
+    // We want to preserve the last location info for possible
+    // backtracking.
+    frame.add_fcn (octave_call_stack::set_line,
+                   octave_call_stack::current_line ());
+    frame.add_fcn (octave_call_stack::set_column,
+                   octave_call_stack::current_column ());
+
+    // Similarly, if we have seen a return or break statement, allow all
+    // the cleanup code to run before returning or handling the break.
+    // We don't have to worry about continue statements because they can
+    // only occur in loops.
+
+    frame.protect_var (tree_return_command::returning);
+    tree_return_command::returning = 0;
+
+    frame.protect_var (tree_break_command::breaking);
+    tree_break_command::breaking = 0;
+
+    try
+      {
+        if (list)
+          list->accept (*this);
+      }
+    catch (const octave_execution_exception&)
+      {
+        recover_from_exception ();
+
+        if (tree_break_command::breaking || tree_return_command::returning)
+          frame.discard (2);
+        else
+          frame.run (2);
+
+        frame.discard (2);
+
+        throw;
+      }
 
-    buffer_error_messages++;
-    Vdebug_on_error = false;
-    Vdebug_on_warning = false;
+    // The unwind_protects are popped off the stack in the reverse of
+    // the order they are pushed on.
 
-    // The catch code is *not* added to unwind_protect stack;
-    // it doesn't need to be run on interrupts.
+    // FIXME: these statements say that if we see a break or
+    // return statement in the cleanup block, that we want to use the
+    // new value of the breaking or returning flag instead of restoring
+    // the previous value.  Is that the right thing to do?  I think so.
+    // Consider the case of
+    //
+    //   function foo ()
+    //     unwind_protect
+    //       fprintf (stderr, "1: this should always be executed\n");
+    //       break;
+    //       fprintf (stderr, "1: this should never be executed\n");
+    //     unwind_protect_cleanup
+    //       fprintf (stderr, "2: this should always be executed\n");
+    //       return;
+    //       fprintf (stderr, "2: this should never be executed\n");
+    //     end_unwind_protect
+    //   endfunction
+    //
+    // If we reset the value of the breaking flag, both the returning
+    // flag and the breaking flag will be set, and we shouldn't have
+    // both.  So, use the most recent one.  If there is no return or
+    // break in the cleanup block, the values should be reset to
+    // whatever they were when the cleanup block was entered.
 
-    tree_statement_list *try_code = cmd.body ();
+    if (tree_break_command::breaking || tree_return_command::returning)
+      frame.discard (2);
+    else
+      frame.run (2);
+  }
 
-    if (try_code)
+  void
+  tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd)
+  {
+    tree_statement_list *cleanup_code = cmd.cleanup ();
+
+    tree_statement_list *unwind_protect_code = cmd.body ();
+
+    if (unwind_protect_code)
       {
         try
           {
-            in_try_catch++;
-            try_code->accept (*this);
-            in_try_catch--;
+            unwind_protect_code->accept (*this);
           }
         catch (const octave_execution_exception&)
           {
+            // FIXME: Maybe we should be able to temporarily set the
+            // interpreter's exception handling state to something "safe"
+            // while the cleanup block runs instead of just resetting it
+            // here?
             recover_from_exception ();
 
-            in_try_catch--;          // must be restored before "catch" block
-            execution_error = true;
+            // Run the cleanup code on exceptions, so that it is run even
+            // in case of interrupt or out-of-memory.
+            do_unwind_protect_cleanup_code (cleanup_code);
+
+            // If an error occurs inside the cleanup code, a new
+            // exception will be thrown instead of the original.
+            throw;
           }
+
+        // Also execute the unwind_protect_cleanump code if the
+        // unwind_protect block runs without error.
+        do_unwind_protect_cleanup_code (cleanup_code);
       }
-  // Unwind to let the user print any messages from
-  // errors that occurred in the body of the try_catch statement,
-  // or throw further errors.
   }
 
-  if (execution_error)
-    {
-      tree_statement_list *catch_code = cmd.cleanup ();
-      if (catch_code)
-        {
-          tree_identifier *expr_id = cmd.identifier ();
-          octave_lvalue ult;
-
-          if (expr_id)
-            {
-              ult = expr_id->lvalue ();
-
-              octave_scalar_map err;
-
-              err.assign ("message", last_error_message ());
-              err.assign ("identifier", last_error_id ());
-              err.assign ("stack", last_error_stack ());
-
-              ult.assign (octave_value::op_asn_eq, err);
-            }
-
-          // perform actual "catch" block
-          if (catch_code)
-            catch_code->accept (*this);
-        }
-    }
-}
-
-void
-tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list)
-{
-  octave::unwind_protect frame;
-
-  frame.protect_var (octave_interrupt_state);
-  octave_interrupt_state = 0;
+  void
+  tree_evaluator::visit_while_command (tree_while_command& cmd)
+  {
+#if defined (HAVE_LLVM)
+    if (tree_jit::execute (cmd))
+      return;
+#endif
 
-  // We want to preserve the last location info for possible
-  // backtracking.
-  frame.add_fcn (octave_call_stack::set_line,
-                 octave_call_stack::current_line ());
-  frame.add_fcn (octave_call_stack::set_column,
-                 octave_call_stack::current_column ());
+    octave::unwind_protect frame;
 
-  // Similarly, if we have seen a return or break statement, allow all
-  // the cleanup code to run before returning or handling the break.
-  // We don't have to worry about continue statements because they can
-  // only occur in loops.
-
-  frame.protect_var (tree_return_command::returning);
-  tree_return_command::returning = 0;
-
-  frame.protect_var (tree_break_command::breaking);
-  tree_break_command::breaking = 0;
+    frame.protect_var (in_loop_command);
 
-  try
-    {
-      if (list)
-        list->accept (*this);
-    }
-  catch (const octave_execution_exception&)
-    {
-      recover_from_exception ();
+    in_loop_command = true;
 
-      if (tree_break_command::breaking || tree_return_command::returning)
-        frame.discard (2);
-      else
-        frame.run (2);
+    tree_expression *expr = cmd.condition ();
 
-      frame.discard (2);
-
-      throw;
-    }
+    if (! expr)
+      panic_impossible ();
 
-  // The unwind_protects are popped off the stack in the reverse of
-  // the order they are pushed on.
+    for (;;)
+      {
+        if (debug_mode)
+          do_breakpoint (cmd.is_breakpoint (true));
 
-  // FIXME: these statements say that if we see a break or
-  // return statement in the cleanup block, that we want to use the
-  // new value of the breaking or returning flag instead of restoring
-  // the previous value.  Is that the right thing to do?  I think so.
-  // Consider the case of
-  //
-  //   function foo ()
-  //     unwind_protect
-  //       fprintf (stderr, "1: this should always be executed\n");
-  //       break;
-  //       fprintf (stderr, "1: this should never be executed\n");
-  //     unwind_protect_cleanup
-  //       fprintf (stderr, "2: this should always be executed\n");
-  //       return;
-  //       fprintf (stderr, "2: this should never be executed\n");
-  //     end_unwind_protect
-  //   endfunction
-  //
-  // If we reset the value of the breaking flag, both the returning
-  // flag and the breaking flag will be set, and we shouldn't have
-  // both.  So, use the most recent one.  If there is no return or
-  // break in the cleanup block, the values should be reset to
-  // whatever they were when the cleanup block was entered.
+        if (expr->is_logically_true ("while"))
+          {
+            tree_statement_list *loop_body = cmd.body ();
 
-  if (tree_break_command::breaking || tree_return_command::returning)
-    frame.discard (2);
-  else
-    frame.run (2);
-}
-
-void
-tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd)
-{
-  tree_statement_list *cleanup_code = cmd.cleanup ();
+            if (loop_body)
+              loop_body->accept (*this);
 
-  tree_statement_list *unwind_protect_code = cmd.body ();
-
-  if (unwind_protect_code)
-    {
-      try
-        {
-          unwind_protect_code->accept (*this);
-        }
-      catch (const octave_execution_exception&)
-        {
-          // FIXME: Maybe we should be able to temporarily set the
-          // interpreter's exception handling state to something "safe"
-          // while the cleanup block runs instead of just resetting it
-          // here?
-          recover_from_exception ();
+            if (quit_loop_now ())
+              break;
+          }
+        else
+          break;
+      }
+  }
 
-          // Run the cleanup code on exceptions, so that it is run even
-          // in case of interrupt or out-of-memory.
-          do_unwind_protect_cleanup_code (cleanup_code);
-
-          // If an error occurs inside the cleanup code, a new
-          // exception will be thrown instead of the original.
-          throw;
-        }
-
-      // Also execute the unwind_protect_cleanump code if the
-      // unwind_protect block runs without error.
-      do_unwind_protect_cleanup_code (cleanup_code);
-    }
-}
-
-void
-tree_evaluator::visit_while_command (tree_while_command& cmd)
-{
+  void
+  tree_evaluator::visit_do_until_command (tree_do_until_command& cmd)
+  {
 #if defined (HAVE_LLVM)
-  if (tree_jit::execute (cmd))
-    return;
+    if (tree_jit::execute (cmd))
+      return;
 #endif
 
-  octave::unwind_protect frame;
-
-  frame.protect_var (in_loop_command);
+    octave::unwind_protect frame;
 
-  in_loop_command = true;
+    frame.protect_var (in_loop_command);
 
-  tree_expression *expr = cmd.condition ();
+    in_loop_command = true;
 
-  if (! expr)
-    panic_impossible ();
+    tree_expression *expr = cmd.condition ();
+    int until_line = cmd.line ();
+    int until_column = cmd.column ();
 
-  for (;;)
-    {
-      if (debug_mode)
-        do_breakpoint (cmd.is_breakpoint (true));
-
-      if (expr->is_logically_true ("while"))
-        {
-          tree_statement_list *loop_body = cmd.body ();
+    if (! expr)
+      panic_impossible ();
 
-          if (loop_body)
-            loop_body->accept (*this);
+    for (;;)
+      {
+        tree_statement_list *loop_body = cmd.body ();
+
+        if (loop_body)
+          loop_body->accept (*this);
 
-          if (quit_loop_now ())
-            break;
-        }
-      else
-        break;
-    }
-}
+        if (quit_loop_now ())
+          break;
 
-void
-tree_evaluator::visit_do_until_command (tree_do_until_command& cmd)
-{
-#if defined (HAVE_LLVM)
-  if (tree_jit::execute (cmd))
-    return;
-#endif
+        if (debug_mode)
+          do_breakpoint (cmd.is_breakpoint (true));
 
-  octave::unwind_protect frame;
+        octave_call_stack::set_location (until_line, until_column);
 
-  frame.protect_var (in_loop_command);
-
-  in_loop_command = true;
-
-  tree_expression *expr = cmd.condition ();
-  int until_line = cmd.line ();
-  int until_column = cmd.column ();
+        if (expr->is_logically_true ("do-until"))
+          break;
+      }
+  }
 
-  if (! expr)
-    panic_impossible ();
-
-  for (;;)
-    {
-      tree_statement_list *loop_body = cmd.body ();
-
-      if (loop_body)
-        loop_body->accept (*this);
-
-      if (quit_loop_now ())
-        break;
+  void
+  tree_evaluator::do_breakpoint (tree_statement& stmt) const
+  {
+    do_breakpoint (stmt.is_breakpoint (true), stmt.is_end_of_fcn_or_script ());
+  }
 
-      if (debug_mode)
-        do_breakpoint (cmd.is_breakpoint (true));
-
-      octave_call_stack::set_location (until_line, until_column);
+  void
+  tree_evaluator::do_breakpoint (bool is_breakpoint,
+                                 bool is_end_of_fcn_or_script) const
+  {
+    bool break_on_this_statement = false;
 
-      if (expr->is_logically_true ("do-until"))
-        break;
-    }
-}
+    if (octave_debug_on_interrupt_state)
+      {
+        break_on_this_statement = true;
 
-void
-tree_evaluator::do_breakpoint (tree_statement& stmt) const
-{
-  do_breakpoint (stmt.is_breakpoint (true), stmt.is_end_of_fcn_or_script ());
-}
+        octave_debug_on_interrupt_state = false;
 
-void
-tree_evaluator::do_breakpoint (bool is_breakpoint,
-                               bool is_end_of_fcn_or_script) const
-{
-  bool break_on_this_statement = false;
+        current_frame = octave_call_stack::current_frame ();
+      }
+    else if (is_breakpoint)
+      {
+        break_on_this_statement = true;
+
+        dbstep_flag = 0;
 
-  if (octave_debug_on_interrupt_state)
-    {
-      break_on_this_statement = true;
-
-      octave_debug_on_interrupt_state = false;
+        current_frame = octave_call_stack::current_frame ();
+      }
+    else if (dbstep_flag > 0)
+      {
+        if (octave_call_stack::current_frame () == current_frame)
+          {
+            if (dbstep_flag == 1 || is_end_of_fcn_or_script)
+              {
+                // We get here if we are doing a "dbstep" or a "dbstep N" and the
+                // count has reached 1 so that we must stop and return to debug
+                // prompt.  Alternatively, "dbstep N" has been used but the end
+                // of the frame has been reached so we stop at the last line and
+                // return to prompt.
 
-      current_frame = octave_call_stack::current_frame ();
-    }
-  else if (is_breakpoint)
-    {
-      break_on_this_statement = true;
-
-      dbstep_flag = 0;
+                break_on_this_statement = true;
 
-      current_frame = octave_call_stack::current_frame ();
-    }
-  else if (dbstep_flag > 0)
-    {
-      if (octave_call_stack::current_frame () == current_frame)
-        {
-          if (dbstep_flag == 1 || is_end_of_fcn_or_script)
-            {
-              // We get here if we are doing a "dbstep" or a "dbstep N" and the
-              // count has reached 1 so that we must stop and return to debug
-              // prompt.  Alternatively, "dbstep N" has been used but the end
-              // of the frame has been reached so we stop at the last line and
-              // return to prompt.
+                dbstep_flag = 0;
+              }
+            else
+              {
+                // Executing "dbstep N".  Decrease N by one and continue.
+
+                dbstep_flag--;
+              }
 
-              break_on_this_statement = true;
+          }
+        else if (dbstep_flag == 1
+                 && octave_call_stack::current_frame () < current_frame)
+          {
+            // We stepped out from the end of a function.
 
-              dbstep_flag = 0;
-            }
-          else
-            {
-              // Executing "dbstep N".  Decrease N by one and continue.
+            current_frame = octave_call_stack::current_frame ();
 
-              dbstep_flag--;
-            }
+            break_on_this_statement = true;
 
-        }
-      else if (dbstep_flag == 1
-               && octave_call_stack::current_frame () < current_frame)
-        {
-          // We stepped out from the end of a function.
-
-          current_frame = octave_call_stack::current_frame ();
-
-          break_on_this_statement = true;
+            dbstep_flag = 0;
+          }
+      }
+    else if (dbstep_flag == -1)
+      {
+        // We get here if we are doing a "dbstep in".
 
-          dbstep_flag = 0;
-        }
-    }
-  else if (dbstep_flag == -1)
-    {
-      // We get here if we are doing a "dbstep in".
+        break_on_this_statement = true;
 
-      break_on_this_statement = true;
-
-      dbstep_flag = 0;
+        dbstep_flag = 0;
 
-      current_frame = octave_call_stack::current_frame ();
-    }
-  else if (dbstep_flag == -2)
-    {
-      // We get here if we are doing a "dbstep out".  Check for end of
-      // function and whether the current frame is the same as the
-      // cached value because we want to step out from the frame where
-      // "dbstep out" was evaluated, not from any functions called from
-      // that frame.
+        current_frame = octave_call_stack::current_frame ();
+      }
+    else if (dbstep_flag == -2)
+      {
+        // We get here if we are doing a "dbstep out".  Check for end of
+        // function and whether the current frame is the same as the
+        // cached value because we want to step out from the frame where
+        // "dbstep out" was evaluated, not from any functions called from
+        // that frame.
+
+        if (is_end_of_fcn_or_script
+            && octave_call_stack::current_frame () == current_frame)
+          dbstep_flag = -1;
+      }
 
-      if (is_end_of_fcn_or_script
-          && octave_call_stack::current_frame () == current_frame)
-        dbstep_flag = -1;
-    }
+    if (break_on_this_statement)
+      do_keyboard ();
 
-  if (break_on_this_statement)
-    do_keyboard ();
+  }
 
-}
+  // ARGS is currently unused, but since the do_keyboard function in
+  // input.cc accepts an argument list, we preserve it here so that the
+  // interface won't have to change if we decide to use it in the future.
 
-// ARGS is currently unused, but since the do_keyboard function in
-// input.cc accepts an argument list, we preserve it here so that the
-// interface won't have to change if we decide to use it in the future.
-
-octave_value
-tree_evaluator::do_keyboard (const octave_value_list& args) const
-{
-  return ::do_keyboard (args);
+  octave_value
+  tree_evaluator::do_keyboard (const octave_value_list& args) const
+  {
+    return ::do_keyboard (args);
+  }
 }
 
 DEFUN (max_recursion_depth, args, nargout,
--- a/libinterp/parse-tree/pt-eval.h	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/parse-tree/pt-eval.h	Tue Jul 12 14:28:07 2016 -0400
@@ -34,162 +34,169 @@
 
 class tree_expression;
 
-// How to evaluate the code that the parse trees represent.
+namespace octave
+{
+  class interpreter;
 
-class
-OCTINTERP_API
-tree_evaluator : public tree_walker
-{
-public:
+  // How to evaluate the code that the parse trees represent.
 
-  typedef void (*decl_elt_init_fcn) (tree_decl_elt&);
-
-  tree_evaluator (void) { }
+  class
+  OCTINTERP_API
+  tree_evaluator : public tree_walker
+  {
+  public:
 
-  ~tree_evaluator (void) { }
+    typedef void (*decl_elt_init_fcn) (tree_decl_elt&);
 
-  void visit_anon_fcn_handle (tree_anon_fcn_handle&);
+    tree_evaluator (interpreter *interp_context)
+      : m_interp_context (interp_context)
+    { }
 
-  void visit_argument_list (tree_argument_list&);
+    ~tree_evaluator (void) { }
 
-  void visit_binary_expression (tree_binary_expression&);
+    void visit_anon_fcn_handle (tree_anon_fcn_handle&);
 
-  void visit_break_command (tree_break_command&);
+    void visit_argument_list (tree_argument_list&);
 
-  void visit_colon_expression (tree_colon_expression&);
+    void visit_binary_expression (tree_binary_expression&);
 
-  void visit_continue_command (tree_continue_command&);
+    void visit_break_command (tree_break_command&);
 
-  void visit_global_command (tree_global_command&);
+    void visit_colon_expression (tree_colon_expression&);
 
-  void visit_persistent_command (tree_persistent_command&);
+    void visit_continue_command (tree_continue_command&);
 
-  void visit_decl_elt (tree_decl_elt&);
+    void visit_global_command (tree_global_command&);
 
-  void visit_decl_init_list (tree_decl_init_list&);
+    void visit_persistent_command (tree_persistent_command&);
 
-  void visit_simple_for_command (tree_simple_for_command&);
+    void visit_decl_elt (tree_decl_elt&);
 
-  void visit_complex_for_command (tree_complex_for_command&);
+    void visit_decl_init_list (tree_decl_init_list&);
 
-  void visit_octave_user_script (octave_user_script&);
+    void visit_simple_for_command (tree_simple_for_command&);
 
-  void visit_octave_user_function (octave_user_function&);
+    void visit_complex_for_command (tree_complex_for_command&);
 
-  void visit_octave_user_function_header (octave_user_function&);
+    void visit_octave_user_script (octave_user_script&);
 
-  void visit_octave_user_function_trailer (octave_user_function&);
+    void visit_octave_user_function (octave_user_function&);
 
-  void visit_function_def (tree_function_def&);
+    void visit_octave_user_function_header (octave_user_function&);
 
-  void visit_identifier (tree_identifier&);
+    void visit_octave_user_function_trailer (octave_user_function&);
 
-  void visit_if_clause (tree_if_clause&);
+    void visit_function_def (tree_function_def&);
 
-  void visit_if_command (tree_if_command&);
+    void visit_identifier (tree_identifier&);
 
-  void visit_if_command_list (tree_if_command_list&);
+    void visit_if_clause (tree_if_clause&);
 
-  void visit_index_expression (tree_index_expression&);
+    void visit_if_command (tree_if_command&);
 
-  void visit_matrix (tree_matrix&);
+    void visit_if_command_list (tree_if_command_list&);
 
-  void visit_cell (tree_cell&);
+    void visit_index_expression (tree_index_expression&);
 
-  void visit_multi_assignment (tree_multi_assignment&);
+    void visit_matrix (tree_matrix&);
 
-  void visit_no_op_command (tree_no_op_command&);
+    void visit_cell (tree_cell&);
 
-  void visit_constant (tree_constant&);
+    void visit_multi_assignment (tree_multi_assignment&);
 
-  void visit_fcn_handle (tree_fcn_handle&);
+    void visit_no_op_command (tree_no_op_command&);
 
-  void visit_funcall (tree_funcall&);
+    void visit_constant (tree_constant&);
+
+    void visit_fcn_handle (tree_fcn_handle&);
 
-  void visit_parameter_list (tree_parameter_list&);
+    void visit_funcall (tree_funcall&);
 
-  void visit_postfix_expression (tree_postfix_expression&);
+    void visit_parameter_list (tree_parameter_list&);
 
-  void visit_prefix_expression (tree_prefix_expression&);
+    void visit_postfix_expression (tree_postfix_expression&);
 
-  void visit_return_command (tree_return_command&);
+    void visit_prefix_expression (tree_prefix_expression&);
 
-  void visit_return_list (tree_return_list&);
+    void visit_return_command (tree_return_command&);
 
-  void visit_simple_assignment (tree_simple_assignment&);
+    void visit_return_list (tree_return_list&);
 
-  void visit_statement (tree_statement&);
+    void visit_simple_assignment (tree_simple_assignment&);
+
+    void visit_statement (tree_statement&);
 
-  void visit_statement_list (tree_statement_list&);
+    void visit_statement_list (tree_statement_list&);
 
-  void visit_switch_case (tree_switch_case&);
+    void visit_switch_case (tree_switch_case&);
 
-  void visit_switch_case_list (tree_switch_case_list&);
+    void visit_switch_case_list (tree_switch_case_list&);
 
-  void visit_switch_command (tree_switch_command&);
+    void visit_switch_command (tree_switch_command&);
 
-  void visit_try_catch_command (tree_try_catch_command&);
+    void visit_try_catch_command (tree_try_catch_command&);
 
-  void do_unwind_protect_cleanup_code (tree_statement_list *list);
+    void do_unwind_protect_cleanup_code (tree_statement_list *list);
 
-  void visit_unwind_protect_command (tree_unwind_protect_command&);
+    void visit_unwind_protect_command (tree_unwind_protect_command&);
 
-  void visit_while_command (tree_while_command&);
+    void visit_while_command (tree_while_command&);
 
-  void visit_do_until_command (tree_do_until_command&);
+    void visit_do_until_command (tree_do_until_command&);
 
-  static void reset_debug_state (void);
+    static void reset_debug_state (void);
 
-  static bool statement_printing_enabled (void);
+    static bool statement_printing_enabled (void);
 
-  // If > 0, stop executing at the (N-1)th stopping point, counting
-  //         from the the current execution point in the current frame.
-  //
-  // If < 0, stop executing at the next possible stopping point.
-  static int dbstep_flag;
+    // If > 0, stop executing at the (N-1)th stopping point, counting
+    //         from the the current execution point in the current frame.
+    //
+    // If < 0, stop executing at the next possible stopping point.
+    static int dbstep_flag;
 
-  // The number of the stack frame we are currently debugging.
-  static size_t current_frame;
+    // The number of the stack frame we are currently debugging.
+    static size_t current_frame;
 
-  static bool debug_mode;
+    static bool debug_mode;
 
-  static bool quiet_breakpoint_flag;
+    static bool quiet_breakpoint_flag;
 
-  // Possible types of evaluation contexts.
-  enum stmt_list_type
-  {
-    function,  // function body
-    script,    // script file
-    other      // command-line input or eval string
-  };
+    // Possible types of evaluation contexts.
+    enum stmt_list_type
+    {
+      function,  // function body
+      script,    // script file
+      other      // command-line input or eval string
+    };
 
-  // The context for the current evaluation.
-  static stmt_list_type statement_context;
+    // The context for the current evaluation.
+    static stmt_list_type statement_context;
 
-  // TRUE means we are evaluating some kind of looping construct.
-  static bool in_loop_command;
+    // TRUE means we are evaluating some kind of looping construct.
+    static bool in_loop_command;
 
-private:
+  private:
 
-  void do_decl_init_list (decl_elt_init_fcn fcn,
-                          tree_decl_init_list *init_list);
+    void do_decl_init_list (decl_elt_init_fcn fcn,
+                            tree_decl_init_list *init_list);
 
-  void do_breakpoint (tree_statement& stmt) const;
+    void do_breakpoint (tree_statement& stmt) const;
 
-  void do_breakpoint (bool is_breakpoint,
-                      bool is_end_of_fcn_or_script = false) const;
+    void do_breakpoint (bool is_breakpoint,
+                        bool is_end_of_fcn_or_script = false) const;
 
-  virtual octave_value
-  do_keyboard (const octave_value_list& args = octave_value_list ()) const;
+    virtual octave_value
+      do_keyboard (const octave_value_list& args = octave_value_list ()) const;
 
-  // No copying!
+    interpreter *m_interp_context;
 
-  tree_evaluator (const tree_evaluator&);
+    // No copying!
+
+    tree_evaluator (const tree_evaluator&);
 
-  tree_evaluator& operator = (const tree_evaluator&);
-};
-
-extern tree_evaluator *current_evaluator;
+    tree_evaluator& operator = (const tree_evaluator&);
+  };
+}
 
 // Maximum nesting level for functions, scripts, or sourced files called
 // recursively.
--- a/libinterp/parse-tree/pt-exp.h	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/parse-tree/pt-exp.h	Tue Jul 12 14:28:07 2016 -0400
@@ -95,7 +95,7 @@
 
   // Check if the result of the expression should be printed.
   // Should normally be used in conjunction with
-  // tree_evaluator::statement_printing_enabled.
+  // octave::tree_evaluator::statement_printing_enabled.
   bool print_result (void) const { return print_flag; }
 
   virtual std::string oper (void) const { return "<unknown>"; }
--- a/libinterp/parse-tree/pt-id.cc	Mon Aug 01 09:52:51 2016 -0700
+++ b/libinterp/parse-tree/pt-id.cc	Tue Jul 12 14:28:07 2016 -0400
@@ -94,7 +94,7 @@
       else
         {
           if (print_result () && nargout == 0
-              && tree_evaluator::statement_printing_enabled ())
+              && octave::tree_evaluator::statement_printing_enabled ())
             val.print_with_name (octave_stdout, name ());
 
           retval = val;