changeset 16141:c6b2409672e9

Merge in Julien's changes
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Wed, 27 Feb 2013 14:51:21 -0500
parents 797ac81586d1 (current diff) 2fd39ab12209 (diff)
children 26d65d677557
files
diffstat 13 files changed, 1049 insertions(+), 931 deletions(-) [+]
line wrap: on
line diff
--- a/build-aux/common.mk	Tue Feb 26 12:06:45 2013 +0100
+++ b/build-aux/common.mk	Wed Feb 27 14:51:21 2013 -0500
@@ -3,12 +3,15 @@
 AWK = @AWK@
 export AWK
 
-SED = @SED@
-export SED
+GREP = @GREP@
+export GREP
 
 FIND = @FIND@
 export FIND
 
+SED = @SED@
+export SED
+
 PERL = @PERL@
 export PERL
 
@@ -278,9 +281,9 @@
 
 ## Order matters, at least on some systems (Cygwin, for example).
 SPARSE_XLIBS = \
-    $(CHOLMOD_LIBS) $(UMFPACK_LIBS) \
-    $(AMD_LIBS) $(CAMD_LIBS) $(COLAMD_LIBS) \
-    $(CCOLAMD_LIBS) $(CXSPARSE_LIBS)
+  $(CHOLMOD_LIBS) $(UMFPACK_LIBS) \
+  $(AMD_LIBS) $(CAMD_LIBS) $(COLAMD_LIBS) \
+  $(CCOLAMD_LIBS) $(CXSPARSE_LIBS)
 
 TERM_LIBS = @TERM_LIBS@
 
@@ -696,42 +699,13 @@
   -e "s|%AWK%|${AWK}|g" \
   -e "s|%FIND%|${FIND}|g" \
   -e "s|%SED%|${SED}|g" \
-  -e "s|%library_path_var%|${library_path_var}|g" \
-  -e "s|%liboctinterp%|${SHLPRE}octinterp.${SHLEXT}|g" \
-  -e "s|%liboctave%|${SHLPRE}octave.${SHLEXT}|g" \
-  -e "s|%ldpreloadsep%|${ldpreloadsep}|g" \
-  -e "s|%srcdir%|${srcdir}|" \
-  -e "s|%top_srcdir%|${top_srcdir}|" \
   -e "s|%abs_top_srcdir%|${abs_top_srcdir}|" \
   -e "s|%builddir%|$(shell pwd)|" > $@-t
 $(simple_move_if_change_rule)
 endef
 
-define do_script_install
-$(top_srcdir)/build-aux/mkinstalldirs $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)
-for f in $(FCN_FILES); do \
-  fbase=`basename $$f`; \
-  rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/$$fbase; \
-  $(INSTALL_DATA) $$f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/$$fbase; \
-done
-$(top_srcdir)/mkpkgadd $(DESTDIR)$(fcnfiledir)/$(script_sub_dir) > $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t
-if [ -n "`cat $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t`" ]; then \
-  $(INSTALL_DATA) $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD ; \
-else \
-  rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t ; \
-fi
-endef
-
-define do_script_uninstall
-for f in $(FCN_FILES_NO_DIR); \
-  do rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/$$f; \
-done
-rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD
--rmdir $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)
-endef
-
 define test-file-commands
-( echo "## DO NOT EDIT!  Generated automatically from $(<F) by Make."; grep '^%!' $< ) > $@-t
+( echo "## DO NOT EDIT!  Generated automatically from $(<F) by Make."; $(GREP) '^%!' $< ) > $@-t
 mv $@-t $@
 endef
 
--- a/build-aux/find-files-with-tests.sh	Tue Feb 26 12:06:45 2013 +0100
+++ b/build-aux/find-files-with-tests.sh	Wed Feb 27 14:51:21 2013 -0500
@@ -1,6 +1,7 @@
 #! /bin/sh
 
 set -e
+GREP=${GREP:-grep}
 SED=${SED:-sed}
 
 srcdir="$1"
@@ -13,7 +14,7 @@
   else
     file="$srcdir/$arg"
   fi
-  if [ "`grep -l '^%!' $file`" ]; then
+  if [ "`$GREP -l '^%!' $file`" ]; then
     echo "$file" | $SED "s,\\$srcdir/,,";
   fi
 done
--- a/configure.ac	Tue Feb 26 12:06:45 2013 +0100
+++ b/configure.ac	Wed Feb 27 14:51:21 2013 -0500
@@ -97,6 +97,7 @@
 
 ## Programs used in Makefiles.
 AC_PROG_AWK
+AC_PROG_GREP
 OCTAVE_PROG_FIND
 OCTAVE_PROG_SED
 OCTAVE_PROG_PERL
--- a/doc/interpreter/octave.texi	Tue Feb 26 12:06:45 2013 +0100
+++ b/doc/interpreter/octave.texi	Wed Feb 27 14:51:21 2013 -0500
@@ -498,7 +498,7 @@
 * Plot Annotations::            
 * Multiple Plots on One Page::  
 * Multiple Plot Windows::       
-* Use of @code{axis}@comma{} @code{line}@comma{} and @code{patch} Functions
+* Use of axis@comma{} line@comma{} and patch Functions::
 * Manipulation of Plot Windows::
 * Use of the @code{interpreter} Property::
 * Printing and Saving Plots::              
--- a/doc/interpreter/plot.txi	Tue Feb 26 12:06:45 2013 +0100
+++ b/doc/interpreter/plot.txi	Wed Feb 27 14:51:21 2013 -0500
@@ -62,7 +62,7 @@
 * Plot Annotations::            
 * Multiple Plots on One Page::  
 * Multiple Plot Windows::       
-* Use of @code{axis}@comma{} @code{line}@comma{} and @code{patch} Functions::
+* Use of axis@comma{} line@comma{} and patch Functions::
 * Manipulation of Plot Windows::
 * Use of the @code{interpreter} Property::
 * Printing and Saving Plots::              
@@ -521,8 +521,8 @@
 
 @DOCSTRING(figure)
 
-@node Use of @code{axis}@comma{} @code{line}@comma{} and @code{patch} Functions
-@subsection Use of @code{axis}@comma{} @code{line}@comma{} and @code{patch} Functions
+@node Use of axis@comma{} line@comma{} and patch Functions
+@subsection Use of axis@comma{} line@comma{} and patch Functions
 
 You can create axes, line, and patch objects directly using the
 @code{axes}, @code{line}, and @code{patch} functions.  These objects
--- a/libinterp/interp-core/pt-jit.cc	Tue Feb 26 12:06:45 2013 +0100
+++ b/libinterp/interp-core/pt-jit.cc	Wed Feb 27 14:51:21 2013 -0500
@@ -36,12 +36,12 @@
 #include "symtab.h"
 #include "variables.h"
 
+#ifdef HAVE_LLVM
+
 static bool Venable_jit_debugging = false;
 
 static bool Venable_jit_compiler = true;
 
-#ifdef HAVE_LLVM
-
 #include <llvm/Analysis/CallGraph.h>
 #include <llvm/Analysis/Passes.h>
 #include <llvm/Analysis/Verifier.h>
--- a/libinterp/interpfcn/input.cc	Tue Feb 26 12:06:45 2013 +0100
+++ b/libinterp/interpfcn/input.cc	Wed Feb 27 14:51:21 2013 -0500
@@ -680,24 +680,31 @@
 
   frame.protect_var (curr_lexer);
   curr_lexer = new lexical_feedback ();
+  frame.add_fcn (lexical_feedback::cleanup, curr_lexer);
+
+  frame.protect_var (curr_parser);
+  curr_parser = new octave_parser ();
+  frame.add_fcn (octave_parser::cleanup, curr_parser);
 
   while (Vdebugging)
     {
+      unwind_protect middle_frame;
+
       reset_error_handler ();
 
-      reset_parser ();
+      curr_parser->reset ();
 
       // Save current value of global_command.
-      frame.protect_var (global_command);
+      middle_frame.protect_var (global_command);
 
       global_command = 0;
 
       // Do this with an unwind-protect cleanup function so that the
       // forced variables will be unmarked in the event of an interrupt.
       symbol_table::scope_id scope = symbol_table::top_scope ();
-      frame.add_fcn (symbol_table::unmark_forced_variables, scope);
+      middle_frame.add_fcn (symbol_table::unmark_forced_variables, scope);
 
-      int retval = octave_parse_input ();
+      int retval = curr_parser->run ();
 
       if (retval == 0 && global_command)
         {
@@ -715,10 +722,6 @@
             octave_completion_matches_called = false;
         }
 
-      // Unmark forced variables.
-      // Restore previous value of global_command.
-      frame.run (2);
-
       octave_quit ();
     }
 }
--- a/libinterp/interpfcn/toplev.cc	Tue Feb 26 12:06:45 2013 +0100
+++ b/libinterp/interpfcn/toplev.cc	Wed Feb 27 14:51:21 2013 -0500
@@ -561,6 +561,11 @@
 
   frame.protect_var (curr_lexer);
   curr_lexer = new lexical_feedback ();
+  frame.add_fcn (lexical_feedback::cleanup, curr_lexer);
+
+  frame.protect_var (curr_parser);
+  curr_parser = new octave_parser ();
+  frame.add_fcn (octave_parser::cleanup, curr_parser);
 
   // The big loop.
 
@@ -573,7 +578,7 @@
 
           reset_error_handler ();
 
-          reset_parser ();
+          curr_parser->reset ();
 
           if (symbol_table::at_top_level ())
             tree_evaluator::reset_debug_state ();
@@ -588,7 +593,7 @@
 
           global_command = 0;
 
-          retval = octave_parse_input ();
+          retval = curr_parser->run ();
 
           if (retval == 0)
             {
@@ -636,7 +641,7 @@
                         command_editor::increment_current_command_number ();
                     }
                 }
-              else if (curr_lexer->parser_end_of_input)
+              else if (curr_parser->end_of_input)
                 break;
             }
         }
--- a/libinterp/parse-tree/lex.h	Tue Feb 26 12:06:45 2013 +0100
+++ b/libinterp/parse-tree/lex.h	Wed Feb 27 14:51:21 2013 -0500
@@ -51,9 +51,6 @@
 // Is the given string a keyword?
 extern bool is_keyword (const std::string& s);
 
-extern void prep_lexer_for_script_file (void);
-extern void prep_lexer_for_function_file (void);
-
 class
 stream_reader
 {
@@ -185,7 +182,7 @@
       looking_for_object_index (false), 
       looking_at_indirect_ref (false), parsing_class_method (false),
       maybe_classdef_get_set_method (false), parsing_classdef (false),
-      quote_is_transpose (false), parser_end_of_input (false),
+      quote_is_transpose (false),
       input_line_number (1), current_input_column (1),
       bracketflag (0), braceflag (0),
       looping (0), defining_func (0), looking_at_function_handle (0),
@@ -205,12 +202,26 @@
     looking_at_object_index.push_front (false);
   }
 
+  void reset (void);
+
+  void prep_for_script_file (void);
+
+  void prep_for_function_file (void);
+
+  int octave_read (char *buf, unsigned int max_size);
+
+  char *flex_yytext (void);
+
+  int flex_yyleng (void);
+
   void do_comma_insert_check (void);
 
   int text_yyinput (void);
 
   void xunput (char c, char *buf);
 
+  void xunput (char c);
+
   void fixup_column_count (char *s);
 
   bool inside_any_object_index (void);
@@ -276,6 +287,16 @@
 
   void gripe_matlab_incompatible_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, const char *text);
+
   // TRUE means that we should convert spaces to a comma inside a
   // matrix definition.
   bool convert_spaces_to_comma;
@@ -329,9 +350,6 @@
   // Return transpose or start a string?
   bool quote_is_transpose;
 
-  // TRUE means that we have encountered EOF on the input stream.
-  bool parser_end_of_input;
-
   // The current input line number.
   int input_line_number;
 
@@ -372,13 +390,16 @@
   // a paren?
   bbp_nesting_level nesting_level;
 
+  // For unwind protect.
+  static void cleanup (lexical_feedback *lexer) { delete lexer; }
+
+private:
+
   // Stack to hold tokens so that we can delete them when the parser is
   // reset and avoid growing forever just because we are stashing some
   // information.
   std::stack <token*> token_stack;
 
-private:
-
   // No copying!
 
   lexical_feedback (const lexical_feedback&);
--- a/libinterp/parse-tree/lex.ll	Tue Feb 26 12:06:45 2013 +0100
+++ b/libinterp/parse-tree/lex.ll	Wed Feb 27 14:51:21 2013 -0500
@@ -103,7 +103,7 @@
 #undef YY_INPUT
 #endif
 #define YY_INPUT(buf, result, max_size) \
-  result = octave_read (buf, max_size)
+  result = curr_lexer->octave_read (buf, max_size)
 
 // Try to avoid crashing out completely on fatal scanner errors.
 // The call to yy_fatal_error should never happen, but it avoids a
@@ -113,24 +113,18 @@
 #undef YY_FATAL_ERROR
 #endif
 #define YY_FATAL_ERROR(msg) \
-  do \
-    { \
-      error (msg); \
-      OCTAVE_QUIT; \
-      yy_fatal_error (msg); \
-    } \
-  while (0)
+  curr_lexer->fatal_error (msg)
 
 #define DISPLAY_TOK_AND_RETURN(tok) \
   do \
     { \
       int tok_val = tok; \
       if (Vdisplay_tokens) \
-        display_token (tok_val); \
+        curr_lexer->display_token (tok_val); \
       if (lexer_debug_flag) \
         { \
           std::cerr << "R: "; \
-          display_token (tok_val); \
+          curr_lexer->display_token (tok_val); \
           std::cerr << std::endl;  \
         } \
       return tok_val; \
@@ -158,9 +152,9 @@
 #define TOK_PUSH_AND_RETURN(name, tok) \
   do \
     { \
-      yylval.tok_val = new token (name, curr_lexer->input_line_number, \
-                                  curr_lexer->current_input_column); \
-      curr_lexer->token_stack.push (yylval.tok_val); \
+      curr_lexer->push_token \
+        (new token (name, curr_lexer->input_line_number, \
+         curr_lexer->current_input_column)); \
       TOK_RETURN (tok); \
     } \
   while (0)
@@ -168,9 +162,9 @@
 #define BIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \
   do \
     { \
-      yylval.tok_val = new token (curr_lexer->input_line_number, \
-                                  curr_lexer->current_input_column); \
-      curr_lexer->token_stack.push (yylval.tok_val); \
+      curr_lexer->push_token \
+        (new token (curr_lexer->input_line_number, \
+         curr_lexer->current_input_column)); \
       curr_lexer->current_input_column += yyleng; \
       curr_lexer->quote_is_transpose = qit; \
       curr_lexer->convert_spaces_to_comma = convert; \
@@ -207,7 +201,7 @@
   do \
     { \
       if (lexer_debug_flag) \
-        lexer_debug (pattern, yytext); \
+        curr_lexer->lexer_debug (pattern, yytext); \
     } \
   while (0)
 
@@ -225,9 +219,6 @@
 // file that are needed inside the lexer actions.
 
 static std::string strip_trailing_whitespace (char *s);
-static int octave_read (char *buf, unsigned int max_size);
-static void display_token (int tok);
-static void lexer_debug (const char *pattern, const char *text);
 
 %}
 
@@ -259,7 +250,7 @@
     LEXER_DEBUG ("<SCRIPT_FILE_BEGIN>.");
 
     BEGIN (INITIAL);
-    curr_lexer->xunput (yytext[0], yytext);
+    curr_lexer->xunput (yytext[0]);
     COUNT_TOK_AND_RETURN (SCRIPT_FILE);
   }
 
@@ -267,7 +258,7 @@
     LEXER_DEBUG ("<FUNCTION_FILE_BEGIN>.");
 
     BEGIN (INITIAL);
-    curr_lexer->xunput (yytext[0], yytext);
+    curr_lexer->xunput (yytext[0]);
     COUNT_TOK_AND_RETURN (FUNCTION_FILE);
   }
 
@@ -357,7 +348,7 @@
     int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, ']');
 
     if (spc_gobbled)
-      curr_lexer->xunput (' ', yytext);
+      curr_lexer->xunput (' ');
 
     COUNT_TOK_AND_RETURN (tok_to_return);
   }
@@ -383,7 +374,7 @@
     int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, '}');
 
     if (spc_gobbled)
-      curr_lexer->xunput (' ', yytext);
+      curr_lexer->xunput (' ');
 
     COUNT_TOK_AND_RETURN (tok_to_return);
   }
@@ -412,7 +403,7 @@
           {
             curr_lexer->maybe_warn_separator_insert (';');
 
-            curr_lexer->xunput (';', yytext);
+            curr_lexer->xunput (';');
           }
       }
 
@@ -449,7 +440,7 @@
               {
                 curr_lexer->maybe_warn_separator_insert (';');
 
-                curr_lexer->xunput (';', yytext);
+                curr_lexer->xunput (';');
               }
 
             curr_lexer->quote_is_transpose = false;
@@ -769,7 +760,7 @@
 
     curr_lexer->looking_for_object_index = false;
 
-    curr_lexer->xunput (yytext[0], yytext);
+    curr_lexer->xunput (yytext[0]);
 
     bool eof = false;
     int tok = curr_lexer->process_comment (false, eof);
@@ -959,7 +950,7 @@
 . {
     LEXER_DEBUG (".");
 
-    curr_lexer->xunput (yytext[0], yytext);
+    curr_lexer->xunput (yytext[0]);
 
     int c = curr_lexer->text_yyinput ();
 
@@ -979,38 +970,6 @@
 
 %%
 
-// Fix things up for errors or interrupts.  The parser is never called
-// recursively, so it is always safe to reinitialize its state before
-// doing any parsing.
-
-void
-reset_parser (void)
-{
-  // Start off on the right foot.
-  BEGIN (INITIAL);
-
-  parser_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 (! quitting_gracefully
-      && (interactive || forced_interactive)
-      && ! (reading_fcn_file
-            || reading_classdef_file
-            || reading_script_file
-            || get_input_from_eval_string
-            || input_from_startup_file))
-    yyrestart (stdin);
-
-  // Clear the buffer for help text.
-  while (! help_buf.empty ())
-    help_buf.pop ();
-}
-
 static void
 display_character (char c)
 {
@@ -1212,8 +1171,6 @@
 void
 cleanup_parser (void)
 {
-  reset_parser ();
-
   clear_all_buffers ();
 }
 
@@ -1233,26 +1190,6 @@
   delete_buffer (static_cast<YY_BUFFER_STATE> (buf));
 }
 
-class
-flex_stream_reader : public stream_reader
-{
-public:
-  flex_stream_reader (char *buf_arg) : stream_reader (), buf (buf_arg) { }
-
-  int getc (void) { return curr_lexer->text_yyinput (); }
-  int ungetc (int c) { curr_lexer->xunput (c, buf); return 0; }
-
-private:
-
-  // No copying!
-
-  flex_stream_reader (const flex_stream_reader&);
-
-  flex_stream_reader& operator = (const flex_stream_reader&);
-
-  char *buf;
-};
-
 // Return 1 if the given character matches any character in the given
 // string.
 
@@ -1354,18 +1291,6 @@
 
 */
 
-void
-prep_lexer_for_script_file (void)
-{
-  BEGIN (SCRIPT_FILE_BEGIN);
-}
-
-void
-prep_lexer_for_function_file (void)
-{
-  BEGIN (FUNCTION_FILE_BEGIN);
-}
-
 // Used to delete trailing white space from tokens.
 
 static std::string
@@ -1381,8 +1306,117 @@
   return retval;
 }
 
-static int
-octave_read (char *buf, unsigned max_size)
+DEFUN (__display_tokens__, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __display_tokens__ ()\n\
+Query or set the internal variable that determines whether Octave's\n\
+lexer displays tokens as they are read.\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (display_tokens);
+}
+
+DEFUN (__token_count__, , ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __token_count__ ()\n\
+Number of language tokens processed since Octave startup.\n\
+@end deftypefn")
+{
+  return octave_value (Vtoken_count);
+}
+
+DEFUN (__lexer_debug_flag__, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val}))\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  retval = set_internal_variable (lexer_debug_flag, args, nargout,
+                                  "__lexer_debug_flag__");
+
+  return retval;
+}
+
+class
+flex_stream_reader : public stream_reader
+{
+public:
+  flex_stream_reader (lexical_feedback *l, char *buf_arg)
+    : stream_reader (), lexer (l), buf (buf_arg)
+  { }
+
+  int getc (void) { return lexer->text_yyinput (); }
+  int ungetc (int c) { lexer->xunput (c, buf); return 0; }
+
+private:
+
+  // No copying!
+
+  flex_stream_reader (const flex_stream_reader&);
+
+  flex_stream_reader& operator = (const flex_stream_reader&);
+
+  lexical_feedback *lexer;
+
+  char *buf;
+};
+
+lexical_feedback::~lexical_feedback (void)
+{
+  // Clear out the stack of token info used to track line and
+  // column numbers.
+
+  while (! token_stack.empty ())
+    {
+      delete token_stack.top ();
+      token_stack.pop ();
+    }
+}
+
+void
+lexical_feedback::reset (void)
+{
+  // Start off on the right foot.
+  BEGIN (INITIAL);
+
+  parser_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 (! quitting_gracefully
+      && (interactive || forced_interactive)
+      && ! (reading_fcn_file
+            || reading_classdef_file
+            || reading_script_file
+            || get_input_from_eval_string
+            || input_from_startup_file))
+    yyrestart (stdin);
+
+  // Clear the buffer for help text.
+  while (! help_buf.empty ())
+    help_buf.pop ();
+}
+
+void
+lexical_feedback::prep_for_script_file (void)
+{
+  BEGIN (SCRIPT_FILE_BEGIN);
+}
+
+void
+lexical_feedback::prep_for_function_file (void)
+{
+  BEGIN (FUNCTION_FILE_BEGIN);
+}
+
+int
+lexical_feedback::octave_read (char *buf, unsigned max_size)
 {
   static const char * const eol = "\n";
   static std::string input_buf;
@@ -1445,219 +1479,16 @@
   return status;
 }
 
-static void
-display_token (int tok)
+char *
+lexical_feedback::flex_yytext (void)
 {
-  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 LSHIFT_EQ: std::cerr << "LSHIFT_EQ\n"; break;
-    case RSHIFT_EQ: std::cerr << "RSHIFT_EQ\n"; break;
-    case LSHIFT: std::cerr << "LSHIFT\n"; break;
-    case RSHIFT: std::cerr << "RSHIFT\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 QUOTE: std::cerr << "QUOTE\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:
-      std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM")
-                << " [" << yylval.tok_val->number () << "]\n";
-      break;
-
-    case STRUCT_ELT:
-      std::cerr << "STRUCT_ELT [" << yylval.tok_val->text () << "]\n"; break;
-
-    case NAME:
-      {
-        symbol_table::symbol_record *sr = yylval.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:
-      std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING")
-                << " [" << yylval.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 CLOSE_BRACE: std::cerr << "CLOSE_BRACE\n"; break;
-    case SCRIPT_FILE: std::cerr << "SCRIPT_FILE\n"; break;
-    case FUNCTION_FILE: std::cerr << "FUNCTION_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)
-          std::cerr << static_cast<char> (tok) << "\n";
-        else
-          std::cerr << "UNKNOWN(" << tok << ")\n";
-      }
-      break;
-    }
+  return yytext;
 }
 
-static void
-display_state (void)
-{
-  std::cerr << "S: ";
-
-  switch (YY_START)
-    {
-    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 SCRIPT_FILE_BEGIN:
-      std::cerr << "SCRIPT_FILE_BEGIN" << std::endl;
-      break;
-
-    case FUNCTION_FILE_BEGIN:
-      std::cerr << "FUNCTION_FILE_BEGIN" << std::endl;
-      break;
-
-    default:
-      std::cerr << "UNKNOWN START STATE!" << std::endl;
-      break;
-    }
-}
-
-static void
-lexer_debug (const char *pattern, const char *text)
+int
+lexical_feedback::flex_yyleng (void)
 {
-  std::cerr << std::endl;
-
-  display_state ();
-
-  std::cerr << "P: " << pattern << std::endl;
-  std::cerr << "T: " << text << std::endl;
-}
-
-DEFUN (__display_tokens__, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} __display_tokens__ ()\n\
-Query or set the internal variable that determines whether Octave's\n\
-lexer displays tokens as they are read.\n\
-@end deftypefn")
-{
-  return SET_INTERNAL_VARIABLE (display_tokens);
-}
-
-DEFUN (__token_count__, , ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} __token_count__ ()\n\
-Number of language tokens processed since Octave startup.\n\
-@end deftypefn")
-{
-  return octave_value (Vtoken_count);
-}
-
-DEFUN (__lexer_debug_flag__, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val}))\n\
-Undocumented internal function.\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  retval = set_internal_variable (lexer_debug_flag, args, nargout,
-                                  "__lexer_debug_flag__");
-
-  return retval;
-}
-
-lexical_feedback::~lexical_feedback (void)
-{
-  // Clear out the stack of token info used to track line and
-  // column numbers.
-
-  while (! token_stack.empty ())
-    {
-      delete token_stack.top ();
-      token_stack.pop ();
-    }
+  return yyleng;
 }
 
 // GAG.
@@ -1672,10 +1503,10 @@
 
   int c = text_yyinput ();
 
-  xunput (c, yytext);
+  xunput (c);
 
   if (spc_gobbled)
-    xunput (' ', yytext);
+    xunput (' ');
 
   do_comma_insert = (! looking_at_object_index.front ()
                      && bracketflag && c == '[');
@@ -1708,7 +1539,7 @@
 
       if (c != '\n')
         {
-          xunput (c, yytext);
+          xunput (c);
           c = '\n';
         }
     }
@@ -1735,6 +1566,13 @@
   yyunput (c, buf);
 }
 
+void
+lexical_feedback::xunput (char c)
+{
+  char *yytxt = flex_yytext ();
+  xunput (c, yytxt);
+}
+
 // If we read some newlines, we need figure out what column we're
 // really looking at.
 
@@ -1786,7 +1624,7 @@
 
   if (kw)
     {
-      yylval.tok_val = 0;
+      token *tok_val = 0;
 
       switch (kw->kw_id)
         {
@@ -1831,72 +1669,72 @@
                             || parsed_function_name.top ()))))
             return 0;
 
-          yylval.tok_val = new token (token::simple_end, l, c);
+          tok_val = new token (token::simple_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case end_try_catch_kw:
-          yylval.tok_val = new token (token::try_catch_end, l, c);
+          tok_val = new token (token::try_catch_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case end_unwind_protect_kw:
-          yylval.tok_val = new token (token::unwind_protect_end, l, c);
+          tok_val = new token (token::unwind_protect_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endfor_kw:
-          yylval.tok_val = new token (token::for_end, l, c);
+          tok_val = new token (token::for_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endfunction_kw:
-          yylval.tok_val = new token (token::function_end, l, c);
+          tok_val = new token (token::function_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endif_kw:
-          yylval.tok_val = new token (token::if_end, l, c);
+          tok_val = new token (token::if_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endparfor_kw:
-          yylval.tok_val = new token (token::parfor_end, l, c);
+          tok_val = new token (token::parfor_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endswitch_kw:
-          yylval.tok_val = new token (token::switch_end, l, c);
+          tok_val = new token (token::switch_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endwhile_kw:
-          yylval.tok_val = new token (token::while_end, l, c);
+          tok_val = new token (token::while_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endclassdef_kw:
-          yylval.tok_val = new token (token::classdef_end, l, c);
+          tok_val = new token (token::classdef_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endenumeration_kw:
-          yylval.tok_val = new token (token::enumeration_end, l, c);
+          tok_val = new token (token::enumeration_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endevents_kw:
-          yylval.tok_val = new token (token::events_end, l, c);
+          tok_val = new token (token::events_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endmethods_kw:
-          yylval.tok_val = new token (token::methods_end, l, c);
+          tok_val = new token (token::methods_end, l, c);
           at_beginning_of_statement = true;
           break;
 
         case endproperties_kw:
-          yylval.tok_val = new token (token::properties_end, l, c);
+          tok_val = new token (token::properties_end, l, c);
           at_beginning_of_statement = true;
           break;
 
@@ -1964,24 +1802,24 @@
             if ((reading_fcn_file || reading_script_file
                  || reading_classdef_file)
                 && ! curr_fcn_file_full_name.empty ())
-              yylval.tok_val = new token (curr_fcn_file_full_name, l, c);
+              tok_val = new token (curr_fcn_file_full_name, l, c);
             else
-              yylval.tok_val = new token ("stdin", l, c);
+              tok_val = new token ("stdin", l, c);
           }
           break;
 
         case magic_line_kw:
-          yylval.tok_val = new token (static_cast<double> (l), "", l, c);
+          tok_val = new token (static_cast<double> (l), "", l, c);
           break;
 
         default:
           panic_impossible ();
         }
 
-      if (! yylval.tok_val)
-        yylval.tok_val = new token (l, c);
-
-      token_stack.push (yylval.tok_val);
+      if (! tok_val)
+        tok_val = new token (l, c);
+
+      curr_lexer->push_token (tok_val);
 
       return kw->tok;
     }
@@ -2253,7 +2091,8 @@
   if (! help_buf.empty ())
     help_txt = help_buf.top ();
 
-  flex_stream_reader flex_reader (yytext);
+  char *yytxt = flex_yytext ();
+  flex_stream_reader flex_reader (this, yytxt);
 
   // process_comment is only supposed to be called when we are not
   // initially looking at a block comment.
@@ -2303,7 +2142,7 @@
 
   retval = match_any (c, ",;\n]");
 
-  xunput (c, yytext);
+  xunput (c);
 
   return retval;
 }
@@ -2326,22 +2165,22 @@
     {
       int c1 = text_yyinput ();
       un_op = (c1 == '\'');
-      xunput (c1, yytext);
+      xunput (c1);
     }
   else if (c0 == '+')
     {
       int c1 = text_yyinput ();
       un_op = (c1 == '+');
-      xunput (c1, yytext);
+      xunput (c1);
     }
   else if (c0 == '-')
     {
       int c1 = text_yyinput ();
       un_op = (c1 == '-');
-      xunput (c1, yytext);
+      xunput (c1);
     }
 
-  xunput (c0, yytext);
+  xunput (c0);
 
   return un_op;
 }
@@ -2390,7 +2229,7 @@
             break;
           }
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2414,7 +2253,7 @@
           // A structure element reference is a binary op.
           bin_op = true;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2444,7 +2283,7 @@
         if (c1 == '=')
           bin_op = true;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2452,7 +2291,7 @@
       break;
     }
 
-  xunput (c0, yytext);
+  xunput (c0);
 
   return bin_op;
 }
@@ -2622,7 +2461,7 @@
     octave_comment_buffer::append (comment_buf);
 
  done:
-  xunput (c, yytext);
+  xunput (c);
   current_input_column--;
   return retval;
 }
@@ -2639,17 +2478,19 @@
   double value = 0.0;
   int nread = 0;
 
-  if (looks_like_hex (yytext, strlen (yytext)))
+  char *yytxt = flex_yytext ();
+
+  if (looks_like_hex (yytxt, strlen (yytxt)))
     {
       unsigned long ival;
 
-      nread = sscanf (yytext, "%lx", &ival);
+      nread = sscanf (yytxt, "%lx", &ival);
 
       value = static_cast<double> (ival);
     }
   else
     {
-      char *tmp = strsave (yytext);
+      char *tmp = strsave (yytxt);
 
       char *idx = strpbrk (tmp, "Dd");
 
@@ -2670,12 +2511,10 @@
   looking_for_object_index = false;
   at_beginning_of_statement = false;
 
-  yylval.tok_val = new token (value, yytext, input_line_number,
-                              current_input_column);
-
-  token_stack.push (yylval.tok_val);
-
-  current_input_column += yyleng;
+  curr_lexer->push_token (new token (value, yytxt, input_line_number,
+                                     current_input_column));
+
+  current_input_column += flex_yyleng ();
 
   do_comma_insert_check ();
 }
@@ -2761,7 +2600,7 @@
         }
     }
 
-  xunput (c, yytext);
+  xunput (c);
   return false;
 
 cleanup:
@@ -2770,7 +2609,7 @@
 
   int len = s.length ();
   while (len--)
-    xunput (s[len], yytext);
+    xunput (s[len]);
 
   return false;
 }
@@ -2790,12 +2629,12 @@
         return true;
       else
         {
-          xunput (c2, yytext);
-          xunput (c1, yytext);
+          xunput (c2);
+          xunput (c1);
         }
     }
   else
-    xunput (c1, yytext);
+    xunput (c1);
 
   return false;
 }
@@ -2814,7 +2653,7 @@
       || (c == '\\' && have_continuation ()))
     retval = eat_whitespace ();
   else
-    xunput (c, yytext);
+    xunput (c);
 
   return retval;
 }
@@ -2877,7 +2716,7 @@
               else
                 {
                   std::string s;
-                  xunput (c, yytext);
+                  xunput (c);
 
                   if (delim == '\'')
                     s = buf.str ();
@@ -2887,8 +2726,7 @@
                   quote_is_transpose = true;
                   convert_spaces_to_comma = true;
 
-                  yylval.tok_val = new token (s, bos_line, bos_col);
-                  token_stack.push (yylval.tok_val);
+                  curr_lexer->push_token (new token (s, bos_line, bos_col));
 
                   if (delim == '"')
                     gripe_matlab_incompatible ("\" used as string delimiter");
@@ -2925,7 +2763,7 @@
     case '=':
       {
         int c1 = text_yyinput ();
-        xunput (c1, yytext);
+        xunput (c1);
         if (c1 != '=')
           retval = true;
       }
@@ -2940,7 +2778,7 @@
     case '|':
       {
         int c1 = text_yyinput ();
-        xunput (c1, yytext);
+        xunput (c1);
         if (c1 == '=')
           retval = true;
       }
@@ -2952,11 +2790,11 @@
         if (match_any (c1, "+-*/\\"))
           {
             int c2 = text_yyinput ();
-            xunput (c2, yytext);
+            xunput (c2);
             if (c2 == '=')
               retval = true;
           }
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2966,11 +2804,11 @@
         if (c1 == '>')
           {
             int c2 = text_yyinput ();
-            xunput (c2, yytext);
+            xunput (c2);
             if (c2 == '=')
               retval = true;
           }
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2980,11 +2818,11 @@
         if (c1 == '<')
           {
             int c2 = text_yyinput ();
-            xunput (c2, yytext);
+            xunput (c2);
             if (c2 == '=')
               retval = true;
           }
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2992,7 +2830,7 @@
       break;
     }
 
-  xunput (c0, yytext);
+  xunput (c0);
 
   return retval;
 }
@@ -3001,7 +2839,7 @@
 lexical_feedback::next_token_is_index_op (void)
 {
   int c = text_yyinput ();
-  xunput (c, yytext);
+  xunput (c);
   return c == '(' || c == '{';
 }
 
@@ -3059,7 +2897,7 @@
             {
               maybe_warn_separator_insert (',');
 
-              xunput (',', yytext);
+              xunput (',');
               return retval;
             }
         }
@@ -3085,8 +2923,8 @@
       int c1 = text_yyinput ();
       int c2 = text_yyinput ();
 
-      xunput (c2, yytext);
-      xunput (c1, yytext);
+      xunput (c2);
+      xunput (c1);
 
       int sep_op = next_token_is_sep_op ();
 
@@ -3106,7 +2944,7 @@
 
       maybe_warn_separator_insert (',');
 
-      xunput (',', yytext);
+      xunput (',');
     }
 }
 
@@ -3131,7 +2969,7 @@
   // Restore input.
   while (! buf.empty ())
     {
-      xunput (buf.top (), yytext);
+      xunput (buf.top ());
 
       buf.pop ();
     }
@@ -3174,12 +3012,12 @@
                 && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3229,12 +3067,12 @@
                   && next_token_can_follow_bin_op ())
                 retval = false;
 
-              xunput (c2, yytext);
+              xunput (c2);
             }
             break;
           }
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3249,7 +3087,7 @@
             && next_token_can_follow_bin_op ())
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3270,13 +3108,13 @@
                     && next_token_can_follow_bin_op ())
                   retval = false;
 
-                xunput (c3, yytext);
+                xunput (c3);
               }
             else if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t')
                      && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else if (! match_any (c1, ",;\n")
                  && (! isdigit (c1) && c1 != ' ' && c1 != '\t'
@@ -3287,7 +3125,7 @@
             retval = false;
           }
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3306,13 +3144,13 @@
                 && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t')
                  && next_token_can_follow_bin_op ())
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3330,13 +3168,13 @@
                 && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t')
                  && next_token_can_follow_bin_op ())
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3355,13 +3193,13 @@
                 && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t')
                  && next_token_can_follow_bin_op ())
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3369,7 +3207,7 @@
       break;
     }
 
-  xunput (c0, yytext);
+  xunput (c0);
 
   return retval;
 }
@@ -3380,7 +3218,8 @@
   eat_continuation ();
 
   std::string pkg;
-  std::string meth = strip_trailing_whitespace (yytext);
+  char *yytxt = flex_yytext ();
+  std::string meth = strip_trailing_whitespace (yytxt);
   size_t pos = meth.find ("@");
   std::string cls = meth.substr (pos).substr (1);
   meth = meth.substr (0, pos - 1);
@@ -3400,16 +3239,14 @@
       return LEXICAL_ERROR;
     }
 
-  yylval.tok_val
-    = new token (meth.empty () ? 0 : &(symbol_table::insert (meth)),
-                 cls.empty () ? 0 : &(symbol_table::insert (cls)),
-                 pkg.empty () ? 0 : &(symbol_table::insert (pkg)),
-                 input_line_number,
-                 current_input_column);
-  token_stack.push (yylval.tok_val);
+  curr_lexer->push_token
+    (new token (meth.empty () ? 0 : &(symbol_table::insert (meth)),
+                cls.empty () ? 0 : &(symbol_table::insert (cls)),
+                pkg.empty () ? 0 : &(symbol_table::insert (pkg)),
+                input_line_number, current_input_column));
 
   convert_spaces_to_comma = true;
-  current_input_column += yyleng;
+  current_input_column += flex_yyleng ();
 
   return SUPERCLASSREF;
 }
@@ -3420,7 +3257,8 @@
   eat_continuation ();
 
   std::string pkg;
-  std::string cls = strip_trailing_whitespace (yytext).substr (1);
+  char *yytxt = flex_yytext ();
+  std::string cls = strip_trailing_whitespace (yytxt).substr (1);
   size_t pos = cls.find (".");
 
   if (pos != std::string::npos)
@@ -3436,16 +3274,13 @@
       return LEXICAL_ERROR;
     }
 
-  yylval.tok_val
-    = new token (cls.empty () ? 0 : &(symbol_table::insert (cls)),
-                 pkg.empty () ? 0 : &(symbol_table::insert (pkg)),
-                 input_line_number,
-                 current_input_column);
-
-  token_stack.push (yylval.tok_val);
+  curr_lexer->push_token
+    (new token (cls.empty () ? 0 : &(symbol_table::insert (cls)),
+                pkg.empty () ? 0 : &(symbol_table::insert (pkg)),
+                input_line_number, current_input_column));
 
   convert_spaces_to_comma = true;
-  current_input_column += yyleng;
+  current_input_column += flex_yyleng ();
 
   return METAQUERY;
 }
@@ -3459,9 +3294,11 @@
 {
   bool at_bos = at_beginning_of_statement;
 
-  std::string tok = strip_trailing_whitespace (yytext);
-
-  int c = yytext[yyleng-1];
+  char *yytxt = flex_yytext ();
+
+  std::string tok = strip_trailing_whitespace (yytxt);
+
+  int c = yytxt[flex_yyleng()-1];
 
   bool cont_is_spc = (eat_continuation () != lexical_feedback::NO_WHITESPACE);
 
@@ -3478,16 +3315,14 @@
 
       maybe_unput_comma (spc_gobbled);
 
-      yylval.tok_val = new token (tok, input_line_number,
-                                  current_input_column);
-
-      token_stack.push (yylval.tok_val);
+      curr_lexer->push_token (new token (tok, input_line_number,
+                                         current_input_column));
 
       quote_is_transpose = true;
       convert_spaces_to_comma = true;
       looking_for_object_index = true;
 
-      current_input_column += yyleng;
+      current_input_column += flex_yyleng ();
 
       return STRUCT_ELT;
     }
@@ -3515,12 +3350,10 @@
         }
       else
         {
-          yylval.tok_val = new token (tok, input_line_number,
-                                      current_input_column);
-
-          token_stack.push (yylval.tok_val);
-
-          current_input_column += yyleng;
+          curr_lexer->push_token (new token (tok, input_line_number,
+                                             current_input_column));
+
+          current_input_column += flex_yyleng ();
           quote_is_transpose = false;
           convert_spaces_to_comma = true;
           looking_for_object_index = true;
@@ -3536,7 +3369,7 @@
     {
       if (kw_token >= 0)
         {
-          current_input_column += yyleng;
+          current_input_column += flex_yyleng ();
           quote_is_transpose = false;
           convert_spaces_to_comma = true;
           looking_for_object_index = false;
@@ -3553,13 +3386,13 @@
   if (c1 == '=')
     {
       int c2 = text_yyinput ();
-      xunput (c2, yytext);
+      xunput (c2);
 
       if (c2 != '=')
         next_tok_is_eq = true;
     }
 
-  xunput (c1, yytext);
+  xunput (c1);
 
   // Kluge alert.
   //
@@ -3598,11 +3431,8 @@
   if (tok == "end")
     tok = "__end__";
 
-  yylval.tok_val = new token (&(symbol_table::insert (tok)),
-                              input_line_number,
-                              current_input_column);
-
-  token_stack.push (yylval.tok_val);
+  curr_lexer->push_token (new token (&(symbol_table::insert (tok)),
+                                     input_line_number, current_input_column));
 
   // After seeing an identifer, it is ok to convert spaces to a comma
   // (if needed).
@@ -3618,7 +3448,7 @@
       maybe_unput_comma (spc_gobbled);
     }
 
-  current_input_column += yyleng;
+  current_input_column += flex_yyleng ();
 
   if (tok != "__end__")
     looking_for_object_index = true;
@@ -3693,3 +3523,208 @@
     t.resize (n-1);
   gripe_matlab_incompatible (t + " used as operator");
 }
+
+void
+lexical_feedback::push_token (token *tok)
+{
+  yylval.tok_val = tok;
+  token_stack.push (tok);
+}
+
+token *
+lexical_feedback::current_token (void)
+{
+  return yylval.tok_val;
+}
+
+void
+lexical_feedback::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 LSHIFT_EQ: std::cerr << "LSHIFT_EQ\n"; break;
+    case RSHIFT_EQ: std::cerr << "RSHIFT_EQ\n"; break;
+    case LSHIFT: std::cerr << "LSHIFT\n"; break;
+    case RSHIFT: std::cerr << "RSHIFT\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 QUOTE: std::cerr << "QUOTE\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 = curr_lexer->current_token ();
+        std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM")
+                  << " [" << tok_val->number () << "]\n";
+      }
+      break;
+
+    case STRUCT_ELT:
+      {
+        token *tok_val = curr_lexer->current_token ();
+        std::cerr << "STRUCT_ELT [" << tok_val->text () << "]\n";
+      }
+      break;
+
+    case NAME:
+      {
+        token *tok_val = curr_lexer->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 = curr_lexer->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 CLOSE_BRACE: std::cerr << "CLOSE_BRACE\n"; break;
+    case SCRIPT_FILE: std::cerr << "SCRIPT_FILE\n"; break;
+    case FUNCTION_FILE: std::cerr << "FUNCTION_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)
+          std::cerr << static_cast<char> (tok) << "\n";
+        else
+          std::cerr << "UNKNOWN(" << tok << ")\n";
+      }
+      break;
+    }
+}
+
+static void
+display_state (int state)
+{
+  std::cerr << "S: ";
+
+  switch (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 SCRIPT_FILE_BEGIN:
+      std::cerr << "SCRIPT_FILE_BEGIN" << std::endl;
+      break;
+
+    case FUNCTION_FILE_BEGIN:
+      std::cerr << "FUNCTION_FILE_BEGIN" << std::endl;
+      break;
+
+    default:
+      std::cerr << "UNKNOWN START STATE!" << std::endl;
+      break;
+    }
+}
+
+void
+lexical_feedback::fatal_error (const char *msg)
+{
+  error (msg);
+
+  OCTAVE_QUIT;
+
+  yy_fatal_error (msg);
+}
+
+void
+lexical_feedback::lexer_debug (const char *pattern, const char *text)
+{
+  std::cerr << std::endl;
+
+  display_state (YY_START);
+
+  std::cerr << "P: " << pattern << std::endl;
+  std::cerr << "T: " << text << std::endl;
+}
--- a/libinterp/parse-tree/oct-parse.yy	Tue Feb 26 12:06:45 2013 +0100
+++ b/libinterp/parse-tree/oct-parse.yy	Wed Feb 27 14:51:21 2013 -0500
@@ -86,6 +86,9 @@
 #define malloc GNULIB_NAMESPACE::malloc
 #endif
 
+// The state of the parser.
+octave_parser *curr_parser = 0;
+
 // Buffer for help text snagged from function files.
 std::stack<std::string> help_buf;
 
@@ -156,200 +159,6 @@
 static void
 yyerror (const char *s);
 
-// Error mesages for mismatched end tokens.
-static void
-end_error (const char *type, token::end_tok_type ettype, int l, int c);
-
-// Check to see that end tokens are properly matched.
-static 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.
-static void
-maybe_warn_assign_as_truth_value (tree_expression *expr);
-
-// Maybe print a warning about switch labels that aren't constants.
-static void
-maybe_warn_variable_switch_label (tree_expression *expr);
-
-// Finish building a range.
-static tree_expression *
-finish_colon_expression (tree_colon_expression *e);
-
-// Build a constant.
-static tree_constant *
-make_constant (int op, token *tok_val);
-
-// Build a function handle.
-static tree_fcn_handle *
-make_fcn_handle (token *tok_val);
-
-// Build an anonymous function handle.
-static tree_anon_fcn_handle *
-make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt);
-
-// Build a binary expression.
-static tree_expression *
-make_binary_op (int op, tree_expression *op1, token *tok_val,
-                tree_expression *op2);
-
-// Build a boolean expression.
-static tree_expression *
-make_boolean_op (int op, tree_expression *op1, token *tok_val,
-                 tree_expression *op2);
-
-// Build a prefix expression.
-static tree_expression *
-make_prefix_op (int op, tree_expression *op1, token *tok_val);
-
-// Build a postfix expression.
-static tree_expression *
-make_postfix_op (int op, tree_expression *op1, token *tok_val);
-
-// Build an unwind-protect command.
-static 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.
-static tree_command *
-make_try_command (token *try_tok, tree_statement_list *body,
-                  tree_statement_list *cleanup, token *end_tok,
-                  octave_comment_list *lc, octave_comment_list *mc);
-
-// Build a while command.
-static tree_command *
-make_while_command (token *while_tok, tree_expression *expr,
-                    tree_statement_list *body, token *end_tok,
-                    octave_comment_list *lc);
-
-// Build a do-until command.
-static tree_command *
-make_do_until_command (token *until_tok, tree_statement_list *body,
-                       tree_expression *expr, octave_comment_list *lc);
-
-// Build a for command.
-static 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 break command.
-static tree_command *
-make_break_command (token *break_tok);
-
-// Build a continue command.
-static tree_command *
-make_continue_command (token *continue_tok);
-
-// Build a return command.
-static tree_command *
-make_return_command (token *return_tok);
-
-// Start an if command.
-static tree_if_command_list *
-start_if_command (tree_expression *expr, tree_statement_list *list);
-
-// Finish an if command.
-static 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.
-static tree_if_clause *
-make_elseif_clause (token *elseif_tok, tree_expression *expr,
-                    tree_statement_list *list, octave_comment_list *lc);
-
-// Finish a switch command.
-static 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 a switch case.
-static tree_switch_case *
-make_switch_case (token *case_tok, tree_expression *expr,
-                  tree_statement_list *list, octave_comment_list *lc);
-
-// Build an assignment to a variable.
-static tree_expression *
-make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
-                tree_expression *rhs);
-
-// Define a script.
-static void
-make_script (tree_statement_list *cmds, tree_statement *end_script);
-
-// Begin defining a function.
-static octave_user_function *
-start_function (tree_parameter_list *param_list, tree_statement_list *body,
-                tree_statement *end_function);
-
-// Create a no-op statement for end_function.
-static tree_statement *
-make_end (const std::string& type, int l, int c);
-
-// Do most of the work for defining a function.
-static octave_user_function *
-frob_function (const std::string& fname, octave_user_function *fcn);
-
-// Finish defining a function.
-static tree_function_def *
-finish_function (tree_parameter_list *ret_list,
-                 octave_user_function *fcn, octave_comment_list *lc);
-
-// Reset state after parsing function.
-static void
-recover_from_parsing_function (void);
-
-// Make an index expression.
-static tree_index_expression *
-make_index_expression (tree_expression *expr,
-                       tree_argument_list *args, char type);
-
-// Make an indirect reference expression.
-static tree_index_expression *
-make_indirect_ref (tree_expression *expr, const std::string&);
-
-// Make an indirect reference expression with dynamic field name.
-static tree_index_expression *
-make_indirect_ref (tree_expression *expr, tree_expression *field);
-
-// Make a declaration command.
-static tree_decl_command *
-make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst);
-
-// Validate argument list forming a matrix or cell row.
-static tree_argument_list *
-validate_matrix_row (tree_argument_list *row);
-
-// Finish building a matrix list.
-static tree_expression *
-finish_matrix (tree_matrix *m);
-
-// Finish building a cell list.
-static tree_expression *
-finish_cell (tree_cell *c);
-
-// Maybe print a warning.  Duh.
-static void
-maybe_warn_missing_semi (tree_statement_list *);
-
-// Set the print flag for a statement based on the separator type.
-static tree_statement_list *
-set_stmt_print_flag (tree_statement_list *, char, bool);
-
-// Create a statement list.
-static tree_statement_list *make_statement_list (tree_statement *stmt);
-
-// Append a statement to an existing statement list.
-static tree_statement_list *
-append_statement_list (tree_statement_list *list, char sep,
-                       tree_statement *stmt, bool warn_missing_semi);
-
 // Finish building a statement.
 template <class T>
 static tree_statement *
@@ -556,7 +365,7 @@
                   { $$ = 0; }
                 | END_OF_INPUT
                   {
-                    curr_lexer->parser_end_of_input = 1;
+                    curr_parser->end_of_input = true;
                     $$ = 0;
                   }
                 | simple_list
@@ -568,13 +377,13 @@
                 ;
 
 simple_list     : simple_list1 opt_sep_no_nl
-                  { $$ = set_stmt_print_flag ($1, $2, false); }
+                  { $$ = curr_parser->set_stmt_print_flag ($1, $2, false); }
                 ;
 
 simple_list1    : statement
-                  { $$ = make_statement_list ($1); }
+                  { $$ = curr_parser->make_statement_list ($1); }
                 | simple_list1 sep_no_nl statement
-                  { $$ = append_statement_list ($1, $2, $3, false); }
+                  { $$ = curr_parser->append_statement_list ($1, $2, $3, false); }
                 ;
 
 opt_list        : // empty
@@ -584,13 +393,13 @@
                 ;
 
 list            : list1 opt_sep
-                  { $$ = set_stmt_print_flag ($1, $2, true); }
+                  { $$ = curr_parser->set_stmt_print_flag ($1, $2, true); }
                 ;
 
 list1           : statement
-                  { $$ = make_statement_list ($1); }
+                  { $$ = curr_parser->make_statement_list ($1); }
                 | list1 sep statement
-                  { $$ = append_statement_list ($1, $2, $3, true); }
+                  { $$ = curr_parser->append_statement_list ($1, $2, $3, true); }
                 ;
 
 statement       : expression
@@ -610,7 +419,7 @@
 // WHILE, etc.
 
 word_list_cmd   : identifier word_list
-                  { $$ = make_index_expression ($1, $2, '('); }
+                  { $$ = curr_parser->make_index_expression ($1, $2, '('); }
                 ;
 
 word_list       : string
@@ -643,15 +452,15 @@
                 ;
 
 string          : DQ_STRING
-                  { $$ = make_constant (DQ_STRING, $1); }
+                  { $$ = curr_parser->make_constant (DQ_STRING, $1); }
                 | SQ_STRING
-                  { $$ = make_constant (SQ_STRING, $1); }
+                  { $$ = curr_parser->make_constant (SQ_STRING, $1); }
                 ;
 
 constant        : NUM
-                  { $$ = make_constant (NUM, $1); }
+                  { $$ = curr_parser->make_constant (NUM, $1); }
                 | IMAG_NUM
-                  { $$ = make_constant (IMAG_NUM, $1); }
+                  { $$ = curr_parser->make_constant (IMAG_NUM, $1); }
                 | string
                   { $$ = $1; }
                 ;
@@ -676,7 +485,7 @@
                   }
                 | '[' matrix_rows ']'
                   {
-                    $$ = finish_matrix ($2);
+                    $$ = curr_parser->finish_matrix ($2);
                     curr_lexer->looking_at_matrix_or_assign_lhs = false;
                     curr_lexer->pending_local_variables.clear ();
                   }
@@ -702,7 +511,7 @@
                 | '{' ';' '}'
                   { $$ = new tree_constant (octave_value (Cell ())); }
                 | '{' cell_rows '}'
-                  { $$ = finish_cell ($2); }
+                  { $$ = curr_parser->finish_cell ($2); }
                 ;
 
 cell_rows       : cell_rows1
@@ -722,14 +531,14 @@
 
 cell_or_matrix_row
                 : arg_list
-                  { $$ = validate_matrix_row ($1); }
+                  { $$ = curr_parser->validate_matrix_row ($1); }
                 | arg_list ','  // Ignore trailing comma.
-                  { $$ = validate_matrix_row ($1); }
+                  { $$ = curr_parser->validate_matrix_row ($1); }
                 ;
 
 fcn_handle      : '@' FCN_HANDLE
                   {
-                    $$ = make_fcn_handle ($2);
+                    $$ = curr_parser->make_fcn_handle ($2);
                     curr_lexer->looking_at_function_handle--;
                   }
                 ;
@@ -737,7 +546,7 @@
 anon_fcn_handle : '@' param_list statement
                   {
                     curr_lexer->quote_is_transpose = false;
-                    $$ = make_anon_fcn_handle ($2, $3);
+                    $$ = curr_parser->make_anon_fcn_handle ($2, $3);
                   }
                 ;
 
@@ -802,63 +611,63 @@
 oper_expr       : primary_expr
                   { $$ = $1; }
                 | oper_expr PLUS_PLUS
-                  { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
+                  { $$ = curr_parser->make_postfix_op (PLUS_PLUS, $1, $2); }
                 | oper_expr MINUS_MINUS
-                  { $$ = make_postfix_op (MINUS_MINUS, $1, $2); }
+                  { $$ = curr_parser->make_postfix_op (MINUS_MINUS, $1, $2); }
                 | oper_expr '(' ')'
-                  { $$ = make_index_expression ($1, 0, '('); }
+                  { $$ = curr_parser->make_index_expression ($1, 0, '('); }
                 | oper_expr '(' arg_list ')'
-                  { $$ = make_index_expression ($1, $3, '('); }
+                  { $$ = curr_parser->make_index_expression ($1, $3, '('); }
                 | oper_expr '{' '}'
-                  { $$ = make_index_expression ($1, 0, '{'); }
+                  { $$ = curr_parser->make_index_expression ($1, 0, '{'); }
                 | oper_expr '{' arg_list '}'
-                  { $$ = make_index_expression ($1, $3, '{'); }
+                  { $$ = curr_parser->make_index_expression ($1, $3, '{'); }
                 | oper_expr QUOTE
-                  { $$ = make_postfix_op (QUOTE, $1, $2); }
+                  { $$ = curr_parser->make_postfix_op (QUOTE, $1, $2); }
                 | oper_expr TRANSPOSE
-                  { $$ = make_postfix_op (TRANSPOSE, $1, $2); }
+                  { $$ = curr_parser->make_postfix_op (TRANSPOSE, $1, $2); }
                 | oper_expr indirect_ref_op STRUCT_ELT
-                  { $$ = make_indirect_ref ($1, $3->text ()); }
+                  { $$ = curr_parser->make_indirect_ref ($1, $3->text ()); }
                 | oper_expr indirect_ref_op '(' expression ')'
-                  { $$ = make_indirect_ref ($1, $4); }
+                  { $$ = curr_parser->make_indirect_ref ($1, $4); }
                 | PLUS_PLUS oper_expr %prec UNARY
-                  { $$ = make_prefix_op (PLUS_PLUS, $2, $1); }
+                  { $$ = curr_parser->make_prefix_op (PLUS_PLUS, $2, $1); }
                 | MINUS_MINUS oper_expr %prec UNARY
-                  { $$ = make_prefix_op (MINUS_MINUS, $2, $1); }
+                  { $$ = curr_parser->make_prefix_op (MINUS_MINUS, $2, $1); }
                 | EXPR_NOT oper_expr %prec UNARY
-                  { $$ = make_prefix_op (EXPR_NOT, $2, $1); }
+                  { $$ = curr_parser->make_prefix_op (EXPR_NOT, $2, $1); }
                 | '+' oper_expr %prec UNARY
-                  { $$ = make_prefix_op ('+', $2, $1); }
+                  { $$ = curr_parser->make_prefix_op ('+', $2, $1); }
                 | '-' oper_expr %prec UNARY
-                  { $$ = make_prefix_op ('-', $2, $1); }
+                  { $$ = curr_parser->make_prefix_op ('-', $2, $1); }
                 | oper_expr POW oper_expr
-                  { $$ = make_binary_op (POW, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (POW, $1, $2, $3); }
                 | oper_expr EPOW oper_expr
-                  { $$ = make_binary_op (EPOW, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EPOW, $1, $2, $3); }
                 | oper_expr '+' oper_expr
-                  { $$ = make_binary_op ('+', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('+', $1, $2, $3); }
                 | oper_expr '-' oper_expr
-                  { $$ = make_binary_op ('-', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('-', $1, $2, $3); }
                 | oper_expr '*' oper_expr
-                  { $$ = make_binary_op ('*', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('*', $1, $2, $3); }
                 | oper_expr '/' oper_expr
-                  { $$ = make_binary_op ('/', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('/', $1, $2, $3); }
                 | oper_expr EPLUS oper_expr
-                  { $$ = make_binary_op ('+', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('+', $1, $2, $3); }
                 | oper_expr EMINUS oper_expr
-                  { $$ = make_binary_op ('-', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('-', $1, $2, $3); }
                 | oper_expr EMUL oper_expr
-                  { $$ = make_binary_op (EMUL, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EMUL, $1, $2, $3); }
                 | oper_expr EDIV oper_expr
-                  { $$ = make_binary_op (EDIV, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EDIV, $1, $2, $3); }
                 | oper_expr LEFTDIV oper_expr
-                  { $$ = make_binary_op (LEFTDIV, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (LEFTDIV, $1, $2, $3); }
                 | oper_expr ELEFTDIV oper_expr
-                  { $$ = make_binary_op (ELEFTDIV, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (ELEFTDIV, $1, $2, $3); }
                 ;
 
 colon_expr      : colon_expr1
-                  { $$ = finish_colon_expression ($1); }
+                  { $$ = curr_parser->finish_colon_expression ($1); }
                 ;
 
 colon_expr1     : oper_expr
@@ -873,29 +682,29 @@
 simple_expr     : colon_expr
                   { $$ = $1; }
                 | simple_expr LSHIFT simple_expr
-                  { $$ = make_binary_op (LSHIFT, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (LSHIFT, $1, $2, $3); }
                 | simple_expr RSHIFT simple_expr
-                  { $$ = make_binary_op (RSHIFT, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (RSHIFT, $1, $2, $3); }
                 | simple_expr EXPR_LT simple_expr
-                  { $$ = make_binary_op (EXPR_LT, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_LT, $1, $2, $3); }
                 | simple_expr EXPR_LE simple_expr
-                  { $$ = make_binary_op (EXPR_LE, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_LE, $1, $2, $3); }
                 | simple_expr EXPR_EQ simple_expr
-                  { $$ = make_binary_op (EXPR_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_EQ, $1, $2, $3); }
                 | simple_expr EXPR_GE simple_expr
-                  { $$ = make_binary_op (EXPR_GE, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_GE, $1, $2, $3); }
                 | simple_expr EXPR_GT simple_expr
-                  { $$ = make_binary_op (EXPR_GT, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_GT, $1, $2, $3); }
                 | simple_expr EXPR_NE simple_expr
-                  { $$ = make_binary_op (EXPR_NE, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_NE, $1, $2, $3); }
                 | simple_expr EXPR_AND simple_expr
-                  { $$ = make_binary_op (EXPR_AND, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_AND, $1, $2, $3); }
                 | simple_expr EXPR_OR simple_expr
-                  { $$ = make_binary_op (EXPR_OR, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_OR, $1, $2, $3); }
                 | simple_expr EXPR_AND_AND simple_expr
-                  { $$ = make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
+                  { $$ = curr_parser->make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
                 | simple_expr EXPR_OR_OR simple_expr
-                  { $$ = make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
+                  { $$ = curr_parser->make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
                 ;
 
 // Arrange for the lexer to return CLOSE_BRACE for ']' by looking ahead
@@ -921,35 +730,35 @@
                 ;
 
 assign_expr     : assign_lhs '=' expression
-                  { $$ = make_assign_op ('=', $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op ('=', $1, $2, $3); }
                 | assign_lhs ADD_EQ expression
-                  { $$ = make_assign_op (ADD_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (ADD_EQ, $1, $2, $3); }
                 | assign_lhs SUB_EQ expression
-                  { $$ = make_assign_op (SUB_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (SUB_EQ, $1, $2, $3); }
                 | assign_lhs MUL_EQ expression
-                  { $$ = make_assign_op (MUL_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (MUL_EQ, $1, $2, $3); }
                 | assign_lhs DIV_EQ expression
-                  { $$ = make_assign_op (DIV_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (DIV_EQ, $1, $2, $3); }
                 | assign_lhs LEFTDIV_EQ expression
-                  { $$ = make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
                 | assign_lhs POW_EQ expression
-                  { $$ = make_assign_op (POW_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (POW_EQ, $1, $2, $3); }
                 | assign_lhs LSHIFT_EQ expression
-                  { $$ = make_assign_op (LSHIFT_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (LSHIFT_EQ, $1, $2, $3); }
                 | assign_lhs RSHIFT_EQ expression
-                  { $$ = make_assign_op (RSHIFT_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (RSHIFT_EQ, $1, $2, $3); }
                 | assign_lhs EMUL_EQ expression
-                  { $$ = make_assign_op (EMUL_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (EMUL_EQ, $1, $2, $3); }
                 | assign_lhs EDIV_EQ expression
-                  { $$ = make_assign_op (EDIV_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (EDIV_EQ, $1, $2, $3); }
                 | assign_lhs ELEFTDIV_EQ expression
-                  { $$ = make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
                 | assign_lhs EPOW_EQ expression
-                  { $$ = make_assign_op (EPOW_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (EPOW_EQ, $1, $2, $3); }
                 | assign_lhs AND_EQ expression
-                  { $$ = make_assign_op (AND_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (AND_EQ, $1, $2, $3); }
                 | assign_lhs OR_EQ expression
-                  { $$ = make_assign_op (OR_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (OR_EQ, $1, $2, $3); }
                 ;
 
 expression      : simple_expr
@@ -992,12 +801,12 @@
 
 declaration     : GLOBAL parsing_decl_list decl1
                   {
-                    $$ = make_decl_command (GLOBAL, $1, $3);
+                    $$ = curr_parser->make_decl_command (GLOBAL, $1, $3);
                     curr_lexer->looking_at_decl_list = false;
                   }
                 | PERSISTENT parsing_decl_list decl1
                   {
-                    $$ = make_decl_command (PERSISTENT, $1, $3);
+                    $$ = curr_parser->make_decl_command (PERSISTENT, $1, $3);
                     curr_lexer->looking_at_decl_list = false;
                   }
                 ;
@@ -1043,7 +852,7 @@
 
 if_command      : IF stash_comment if_cmd_list END
                   {
-                    if (! ($$ = finish_if_command ($1, $3, $4, $2)))
+                    if (! ($$ = curr_parser->finish_if_command ($1, $3, $4, $2)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1061,7 +870,7 @@
                   {
                     $1->mark_braindead_shortcircuit (curr_fcn_file_full_name);
 
-                    $$ = start_if_command ($1, $3);
+                    $$ = curr_parser->start_if_command ($1, $3);
                   }
                 | if_cmd_list1 elseif_clause
                   {
@@ -1074,7 +883,7 @@
                   {
                     $4->mark_braindead_shortcircuit (curr_fcn_file_full_name);
 
-                    $$ = make_elseif_clause ($1, $4, $6, $2);
+                    $$ = curr_parser->make_elseif_clause ($1, $4, $6, $2);
                   }
                 ;
 
@@ -1088,7 +897,7 @@
 
 switch_command  : SWITCH stash_comment expression opt_sep case_list END
                   {
-                    if (! ($$ = finish_switch_command ($1, $3, $5, $6, $2)))
+                    if (! ($$ = curr_parser->finish_switch_command ($1, $3, $5, $6, $2)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1116,7 +925,7 @@
                 ;
 
 switch_case     : CASE stash_comment opt_sep expression opt_sep opt_list
-                  { $$ = make_switch_case ($1, $4, $6, $2); }
+                  { $$ = curr_parser->make_switch_case ($1, $4, $6, $2); }
                 ;
 
 default_case    : OTHERWISE stash_comment opt_sep opt_list
@@ -1133,35 +942,35 @@
                   {
                     $3->mark_braindead_shortcircuit (curr_fcn_file_full_name);
 
-                    if (! ($$ = make_while_command ($1, $3, $5, $6, $2)))
+                    if (! ($$ = curr_parser->make_while_command ($1, $3, $5, $6, $2)))
                       ABORT_PARSE;
                   }
                 | DO stash_comment opt_sep opt_list UNTIL expression
                   {
-                    if (! ($$ = make_do_until_command ($5, $4, $6, $2)))
+                    if (! ($$ = curr_parser->make_do_until_command ($5, $4, $6, $2)))
                       ABORT_PARSE;
                   }
                 | FOR stash_comment assign_lhs '=' expression opt_sep opt_list END
                   {
-                    if (! ($$ = make_for_command (FOR, $1, $3, $5, 0,
+                    if (! ($$ = curr_parser->make_for_command (FOR, $1, $3, $5, 0,
                                                   $7, $8, $2)))
                       ABORT_PARSE;
                   }
                 | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END
                   {
-                    if (! ($$ = make_for_command (FOR, $1, $4, $6, 0,
+                    if (! ($$ = curr_parser->make_for_command (FOR, $1, $4, $6, 0,
                                                   $9, $10, $2)))
                       ABORT_PARSE;
                   }
                 | PARFOR stash_comment assign_lhs '=' expression opt_sep opt_list END
                   {
-                    if (! ($$ = make_for_command (PARFOR, $1, $3, $5,
+                    if (! ($$ = curr_parser->make_for_command (PARFOR, $1, $3, $5,
                                                   0, $7, $8, $2)))
                       ABORT_PARSE;
                   }
                 | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END
                   {
-                    if (! ($$ = make_for_command (PARFOR, $1, $4, $6,
+                    if (! ($$ = curr_parser->make_for_command (PARFOR, $1, $4, $6,
                                                   $8, $11, $12, $2)))
                       ABORT_PARSE;
                   }
@@ -1173,17 +982,17 @@
 
 jump_command    : BREAK
                   {
-                    if (! ($$ = make_break_command ($1)))
+                    if (! ($$ = curr_parser->make_break_command ($1)))
                       ABORT_PARSE;
                   }
                 | CONTINUE
                   {
-                    if (! ($$ = make_continue_command ($1)))
+                    if (! ($$ = curr_parser->make_continue_command ($1)))
                       ABORT_PARSE;
                   }
                 | FUNC_RET
                   {
-                    if (! ($$ = make_return_command ($1)))
+                    if (! ($$ = curr_parser->make_return_command ($1)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1195,18 +1004,18 @@
 except_command  : UNWIND stash_comment opt_sep opt_list CLEANUP
                   stash_comment opt_sep opt_list END
                   {
-                    if (! ($$ = make_unwind_command ($1, $4, $8, $9, $2, $6)))
+                    if (! ($$ = curr_parser->make_unwind_command ($1, $4, $8, $9, $2, $6)))
                       ABORT_PARSE;
                   }
                 | TRY stash_comment opt_sep opt_list CATCH
                   stash_comment opt_sep opt_list END
                   {
-                    if (! ($$ = make_try_command ($1, $4, $8, $9, $2, $6)))
+                    if (! ($$ = curr_parser->make_try_command ($1, $4, $8, $9, $2, $6)))
                       ABORT_PARSE;
                   }
                 | TRY stash_comment opt_sep opt_list END
                   {
-                    if (! ($$ = make_try_command ($1, $4, 0, $5, $2, 0)))
+                    if (! ($$ = curr_parser->make_try_command ($1, $4, 0, $5, $2, 0)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1339,10 +1148,11 @@
 script_file     : SCRIPT_FILE opt_list END_OF_INPUT
                   {
                     tree_statement *end_of_script
-                      = make_end ("endscript", curr_lexer->input_line_number,
-                                  curr_lexer->current_input_column);
-
-                    make_script ($2, end_of_script);
+                      = curr_parser->make_end ("endscript",
+                                               curr_lexer->input_line_number,
+                                               curr_lexer->current_input_column);
+
+                    curr_parser->make_script ($2, end_of_script);
 
                     $$ = 0;
                   }
@@ -1375,13 +1185,13 @@
 
 function        : function_beg function1
                   {
-                    $$ = finish_function (0, $2, $1);
-                    recover_from_parsing_function ();
+                    $$ = curr_parser->finish_function (0, $2, $1);
+                    curr_parser->recover_from_parsing_function ();
                   }
                 | function_beg return_list '=' function1
                   {
-                    $$ = finish_function ($2, $4, $1);
-                    recover_from_parsing_function ();
+                    $$ = curr_parser->finish_function ($2, $4, $1);
+                    curr_parser->recover_from_parsing_function ();
                   }
                 ;
 
@@ -1414,22 +1224,22 @@
 
                     delete $1;
 
-                    if (! ($$ = frob_function (fname, $2)))
+                    if (! ($$ = curr_parser->frob_function (fname, $2)))
                       ABORT_PARSE;
                   }
                 ;
 
 function2       : param_list opt_sep opt_list function_end
-                  { $$ = start_function ($1, $3, $4); }
+                  { $$ = curr_parser->start_function ($1, $3, $4); }
                 | opt_sep opt_list function_end
-                  { $$ = start_function (0, $2, $3); }
+                  { $$ = curr_parser->start_function (0, $2, $3); }
                 ;
 
 function_end    : END
                   {
                     endfunction_found = true;
-                    if (end_token_ok ($1, token::function_end))
-                      $$ = make_end ("endfunction", $1->line (), $1->column ());
+                    if (curr_parser->end_token_ok ($1, token::function_end))
+                      $$ = curr_parser->make_end ("endfunction", $1->line (), $1->column ());
                     else
                       ABORT_PARSE;
                   }
@@ -1463,8 +1273,9 @@
                         YYABORT;
                       }
 
-                    $$ = make_end ("endfunction", curr_lexer->input_line_number,
-                                   curr_lexer->current_input_column);
+                    $$ = curr_parser->make_end ("endfunction",
+                                                curr_lexer->input_line_number,
+                                                curr_lexer->current_input_column);
                   }
                 ;
 
@@ -1483,8 +1294,8 @@
                   {
                     curr_lexer->parsing_classdef = false;
 
-                    if (end_token_ok ($1, token::classdef_end))
-                      $$ = make_end ("endclassdef", $1->line (), $1->column ());
+                    if (curr_parser->end_token_ok ($1, token::classdef_end))
+                      $$ = curr_parser->make_end ("endclassdef", $1->line (), $1->column ());
                     else
                       ABORT_PARSE;
                   }
@@ -1729,10 +1540,17 @@
   parse_error ("%s", msg.c_str ());
 }
 
+int
+octave_parser::run (void)
+{
+  return octave_parse ();
+}
+
 // Error mesages for mismatched end tokens.
 
-static void
-end_error (const char *type, token::end_tok_type ettype, int l, int c)
+void
+octave_parser::end_error (const char *type, token::end_tok_type ettype,
+                          int l, int c)
 {
   static const char *fmt
     = "'%s' command matched by '%s' near line %d column %d";
@@ -1783,8 +1601,8 @@
 
 // Check to see that end tokens are properly matched.
 
-static bool
-end_token_ok (token *tok, token::end_tok_type expected)
+bool
+octave_parser::end_token_ok (token *tok, token::end_tok_type expected)
 {
   bool retval = true;
 
@@ -1853,8 +1671,8 @@
 // Maybe print a warning if an assignment expression is used as the
 // test in a logical expression.
 
-static void
-maybe_warn_assign_as_truth_value (tree_expression *expr)
+void
+octave_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
 {
   if (expr->is_assignment_expression ()
       && expr->paren_count () < 2)
@@ -1873,8 +1691,8 @@
 
 // Maybe print a warning about switch labels that aren't constants.
 
-static void
-maybe_warn_variable_switch_label (tree_expression *expr)
+void
+octave_parser::maybe_warn_variable_switch_label (tree_expression *expr)
 {
   if (! expr->is_constant ())
     {
@@ -1980,8 +1798,8 @@
 
 // Finish building a range.
 
-static tree_expression *
-finish_colon_expression (tree_colon_expression *e)
+tree_expression *
+octave_parser::finish_colon_expression (tree_colon_expression *e)
 {
   tree_expression *retval = e;
 
@@ -2044,8 +1862,8 @@
 
 // Make a constant.
 
-static tree_constant *
-make_constant (int op, token *tok_val)
+tree_constant *
+octave_parser::make_constant (int op, token *tok_val)
 {
   int l = tok_val->line ();
   int c = tok_val->column ();
@@ -2107,8 +1925,8 @@
 
 // Make a function handle.
 
-static tree_fcn_handle *
-make_fcn_handle (token *tok_val)
+tree_fcn_handle *
+octave_parser::make_fcn_handle (token *tok_val)
 {
   int l = tok_val->line ();
   int c = tok_val->column ();
@@ -2120,8 +1938,9 @@
 
 // Make an anonymous function handle.
 
-static tree_anon_fcn_handle *
-make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt)
+tree_anon_fcn_handle *
+octave_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 = curr_lexer->input_line_number;
@@ -2153,9 +1972,9 @@
 
 // Build a binary expression.
 
-static tree_expression *
-make_binary_op (int op, tree_expression *op1, token *tok_val,
-                tree_expression *op2)
+tree_expression *
+octave_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;
 
@@ -2257,9 +2076,9 @@
 
 // Build a boolean expression.
 
-static tree_expression *
-make_boolean_op (int op, tree_expression *op1, token *tok_val,
-                 tree_expression *op2)
+tree_expression *
+octave_parser::make_boolean_op (int op, tree_expression *op1, token *tok_val,
+                                tree_expression *op2)
 {
   tree_boolean_expression::type t;
 
@@ -2289,8 +2108,8 @@
 
 // Build a prefix expression.
 
-static tree_expression *
-make_prefix_op (int op, tree_expression *op1, token *tok_val)
+tree_expression *
+octave_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val)
 {
   octave_value::unary_op t = octave_value::unknown_unary_op;
 
@@ -2332,8 +2151,8 @@
 
 // Build a postfix expression.
 
-static tree_expression *
-make_postfix_op (int op, tree_expression *op1, token *tok_val)
+tree_expression *
+octave_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val)
 {
   octave_value::unary_op t = octave_value::unknown_unary_op;
 
@@ -2371,10 +2190,13 @@
 
 // Build an unwind-protect command.
 
-static 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)
+tree_command *
+octave_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;
 
@@ -2385,7 +2207,7 @@
       int l = unwind_tok->line ();
       int c = unwind_tok->column ();
 
-      retval = new tree_unwind_protect_command (body, cleanup,
+      retval = new tree_unwind_protect_command (body, cleanup_stmts,
                                                 lc, mc, tc, l, c);
     }
 
@@ -2394,10 +2216,12 @@
 
 // Build a try-catch command.
 
-static tree_command *
-make_try_command (token *try_tok, tree_statement_list *body,
-                  tree_statement_list *cleanup, token *end_tok,
-                  octave_comment_list *lc, octave_comment_list *mc)
+tree_command *
+octave_parser::make_try_command (token *try_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;
 
@@ -2408,7 +2232,7 @@
       int l = try_tok->line ();
       int c = try_tok->column ();
 
-      retval = new tree_try_catch_command (body, cleanup,
+      retval = new tree_try_catch_command (body, cleanup_stmts,
                                            lc, mc, tc, l, c);
     }
 
@@ -2417,10 +2241,10 @@
 
 // Build a while command.
 
-static tree_command *
-make_while_command (token *while_tok, tree_expression *expr,
-                    tree_statement_list *body, token *end_tok,
-                    octave_comment_list *lc)
+tree_command *
+octave_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;
 
@@ -2443,9 +2267,11 @@
 
 // Build a do-until command.
 
-static tree_command *
-make_do_until_command (token *until_tok, tree_statement_list *body,
-                       tree_expression *expr, octave_comment_list *lc)
+tree_command *
+octave_parser::make_do_until_command (token *until_tok,
+                                      tree_statement_list *body,
+                                      tree_expression *expr,
+                                      octave_comment_list *lc)
 {
   tree_command *retval = 0;
 
@@ -2465,11 +2291,13 @@
 
 // Build a for command.
 
-static 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)
+tree_command *
+octave_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;
 
@@ -2508,8 +2336,8 @@
 
 // Build a break command.
 
-static tree_command *
-make_break_command (token *break_tok)
+tree_command *
+octave_parser::make_break_command (token *break_tok)
 {
   tree_command *retval = 0;
 
@@ -2523,8 +2351,8 @@
 
 // Build a continue command.
 
-static tree_command *
-make_continue_command (token *continue_tok)
+tree_command *
+octave_parser::make_continue_command (token *continue_tok)
 {
   tree_command *retval = 0;
 
@@ -2538,8 +2366,8 @@
 
 // Build a return command.
 
-static tree_command *
-make_return_command (token *return_tok)
+tree_command *
+octave_parser::make_return_command (token *return_tok)
 {
   tree_command *retval = 0;
 
@@ -2553,8 +2381,9 @@
 
 // Start an if command.
 
-static tree_if_command_list *
-start_if_command (tree_expression *expr, tree_statement_list *list)
+tree_if_command_list *
+octave_parser::start_if_command (tree_expression *expr,
+                                 tree_statement_list *list)
 {
   maybe_warn_assign_as_truth_value (expr);
 
@@ -2565,9 +2394,9 @@
 
 // Finish an if command.
 
-static tree_if_command *
-finish_if_command (token *if_tok, tree_if_command_list *list,
-                   token *end_tok, octave_comment_list *lc)
+tree_if_command *
+octave_parser::finish_if_command (token *if_tok, tree_if_command_list *list,
+                                  token *end_tok, octave_comment_list *lc)
 {
   tree_if_command *retval = 0;
 
@@ -2597,9 +2426,10 @@
 
 // Build an elseif clause.
 
-static tree_if_clause *
-make_elseif_clause (token *elseif_tok, tree_expression *expr,
-                    tree_statement_list *list, octave_comment_list *lc)
+tree_if_clause *
+octave_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);
 
@@ -2611,10 +2441,10 @@
 
 // Finish a switch command.
 
-static tree_switch_command *
-finish_switch_command (token *switch_tok, tree_expression *expr,
-                       tree_switch_case_list *list, token *end_tok,
-                       octave_comment_list *lc)
+tree_switch_command *
+octave_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;
 
@@ -2644,9 +2474,10 @@
 
 // Build a switch case.
 
-static tree_switch_case *
-make_switch_case (token *case_tok, tree_expression *expr,
-                  tree_statement_list *list, octave_comment_list *lc)
+tree_switch_case *
+octave_parser::make_switch_case (token *case_tok, tree_expression *expr,
+                                 tree_statement_list *list,
+                                 octave_comment_list *lc)
 {
   maybe_warn_variable_switch_label (expr);
 
@@ -2658,9 +2489,9 @@
 
 // Build an assignment to a variable.
 
-static tree_expression *
-make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
-                tree_expression *rhs)
+tree_expression *
+octave_parser::make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
+                               tree_expression *rhs)
 {
   tree_expression *retval = 0;
 
@@ -2754,8 +2585,9 @@
 
 // Define a script.
 
-static void
-make_script (tree_statement_list *cmds, tree_statement *end_script)
+void
+octave_parser::make_script (tree_statement_list *cmds,
+                            tree_statement *end_script)
 {
   std::string doc_string;
 
@@ -2788,9 +2620,10 @@
 
 // Begin defining a function.
 
-static octave_user_function *
-start_function (tree_parameter_list *param_list, tree_statement_list *body,
-                tree_statement *end_fcn_stmt)
+octave_user_function *
+octave_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.
 
@@ -2813,16 +2646,17 @@
   return fcn;
 }
 
-static tree_statement *
-make_end (const std::string& type, int l, int c)
+tree_statement *
+octave_parser::make_end (const std::string& type, int l, int c)
 {
   return make_statement (new tree_no_op_command (type, l, c));
 }
 
 // Do most of the work for defining a function.
 
-static octave_user_function *
-frob_function (const std::string& fname, octave_user_function *fcn)
+octave_user_function *
+octave_parser::frob_function (const std::string& fname,
+                              octave_user_function *fcn)
 {
   std::string id_name = fname;
 
@@ -2921,9 +2755,10 @@
   return fcn;
 }
 
-static tree_function_def *
-finish_function (tree_parameter_list *ret_list,
-                 octave_user_function *fcn, octave_comment_list *lc)
+tree_function_def *
+octave_parser::finish_function (tree_parameter_list *ret_list,
+                                octave_user_function *fcn,
+                                octave_comment_list *lc)
 {
   tree_function_def *retval = 0;
 
@@ -2991,8 +2826,8 @@
   return retval;
 }
 
-static void
-recover_from_parsing_function (void)
+void
+octave_parser::recover_from_parsing_function (void)
 {
   if (parser_symtab_context.empty ())
     panic_impossible ();
@@ -3014,9 +2849,9 @@
 
 // Make an index expression.
 
-static tree_index_expression *
-make_index_expression (tree_expression *expr, tree_argument_list *args,
-                       char type)
+tree_index_expression *
+octave_parser::make_index_expression (tree_expression *expr,
+                                      tree_argument_list *args, char type)
 {
   tree_index_expression *retval = 0;
 
@@ -3047,8 +2882,9 @@
 
 // Make an indirect reference expression.
 
-static tree_index_expression *
-make_indirect_ref (tree_expression *expr, const std::string& elt)
+tree_index_expression *
+octave_parser::make_indirect_ref (tree_expression *expr,
+                                  const std::string& elt)
 {
   tree_index_expression *retval = 0;
 
@@ -3073,8 +2909,8 @@
 
 // Make an indirect reference expression with dynamic field name.
 
-static tree_index_expression *
-make_indirect_ref (tree_expression *expr, tree_expression *elt)
+tree_index_expression *
+octave_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt)
 {
   tree_index_expression *retval = 0;
 
@@ -3099,8 +2935,9 @@
 
 // Make a declaration command.
 
-static tree_decl_command *
-make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst)
+tree_decl_command *
+octave_parser::make_decl_command (int tok, token *tok_val,
+                                  tree_decl_init_list *lst)
 {
   tree_decl_command *retval = 0;
 
@@ -3134,8 +2971,8 @@
   return retval;
 }
 
-static tree_argument_list *
-validate_matrix_row (tree_argument_list *row)
+tree_argument_list *
+octave_parser::validate_matrix_row (tree_argument_list *row)
 {
   if (row && row->has_magic_tilde ())
     yyerror ("invalid use of tilde (~) in matrix expression");
@@ -3144,8 +2981,8 @@
 
 // Finish building a matrix list.
 
-static tree_expression *
-finish_matrix (tree_matrix *m)
+tree_expression *
+octave_parser::finish_matrix (tree_matrix *m)
 {
   tree_expression *retval = m;
 
@@ -3188,14 +3025,14 @@
 
 // Finish building a cell list.
 
-static tree_expression *
-finish_cell (tree_cell *c)
+tree_expression *
+octave_parser::finish_cell (tree_cell *c)
 {
   return finish_matrix (c);
 }
 
-static void
-maybe_warn_missing_semi (tree_statement_list *t)
+void
+octave_parser::maybe_warn_missing_semi (tree_statement_list *t)
 {
   if (current_function_depth > 0)
     {
@@ -3209,9 +3046,9 @@
     }
 }
 
-static tree_statement_list *
-set_stmt_print_flag (tree_statement_list *list, char sep,
-                     bool warn_missing_semi)
+tree_statement_list *
+octave_parser::set_stmt_print_flag (tree_statement_list *list, char sep,
+                                    bool warn_missing_semi)
 {
   tree_statement *tmp = list->back ();
 
@@ -3246,15 +3083,16 @@
   return list;
 }
 
-static tree_statement_list *
-make_statement_list (tree_statement *stmt)
+tree_statement_list *
+octave_parser::make_statement_list (tree_statement *stmt)
 {
   return new tree_statement_list (stmt);
 }
 
-static tree_statement_list *
-append_statement_list (tree_statement_list *list, char sep,
-                       tree_statement *stmt, bool warn_missing_semi)
+tree_statement_list *
+octave_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);
 
@@ -3500,10 +3338,14 @@
       bool eof;
 
       frame.protect_var (curr_lexer);
-
       curr_lexer = new lexical_feedback ();
-
-      reset_parser ();
+      frame.add_fcn (lexical_feedback::cleanup, curr_lexer);
+
+      frame.protect_var (curr_parser);
+      curr_parser = new octave_parser ();
+      frame.add_fcn (octave_parser::cleanup, curr_parser);
+
+      curr_parser->reset ();
 
       std::string help_txt = gobble_leading_white_space (ffile, eof);
 
@@ -3578,9 +3420,9 @@
             help_buf.push (help_txt);
 
           if (reading_script_file)
-            prep_lexer_for_script_file ();
+            curr_lexer->prep_for_script_file ();
           else
-            prep_lexer_for_function_file ();
+            curr_lexer->prep_for_function_file ();
 
           curr_lexer->parsing_class_method = ! dispatch_type.empty ();
 
@@ -3588,7 +3430,7 @@
 
           global_command = 0;
 
-          int status = octave_parse_input ();
+          int status = curr_parser->run ();
 
           // Use an unwind-protect cleanup function so that the
           // global_command list will be deleted in the event of an
@@ -3605,10 +3447,10 @@
       else
         {
           tree_statement *end_of_script
-            = make_end ("endscript", curr_lexer->input_line_number,
-                        curr_lexer->current_input_column);
-
-          make_script (0, end_of_script);
+            = curr_parser->make_end ("endscript", curr_lexer->input_line_number,
+                                     curr_lexer->current_input_column);
+
+          curr_parser->make_script (0, end_of_script);
 
           fcn_ptr = primary_fcn_ptr;
         }
@@ -4306,6 +4148,12 @@
   unwind_protect frame;
 
   frame.protect_var (curr_lexer);
+  curr_lexer = new lexical_feedback ();
+  frame.add_fcn (lexical_feedback::cleanup, curr_lexer);
+
+  frame.protect_var (curr_parser);
+  curr_parser = new octave_parser ();
+  frame.add_fcn (octave_parser::cleanup, curr_parser);
 
   frame.protect_var (get_input_from_eval_string);
   frame.protect_var (line_editing);
@@ -4319,8 +4167,6 @@
   frame.protect_var (reading_script_file);
   frame.protect_var (reading_classdef_file);
 
-  curr_lexer = new lexical_feedback ();
-
   get_input_from_eval_string = true;
   line_editing = false;
   current_function_depth = 0;
@@ -4344,7 +4190,7 @@
 
   do
     {
-      reset_parser ();
+      curr_parser->reset ();
 
       frame.protect_var (global_command);
 
@@ -4356,7 +4202,7 @@
       symbol_table::scope_id scope = symbol_table::top_scope ();
       frame.add_fcn (symbol_table::unmark_forced_variables, scope);
 
-      parse_status = octave_parse_input ();
+      parse_status = curr_parser->run ();
 
       tree_statement_list *command_list = global_command;
 
@@ -4418,7 +4264,7 @@
                   || tree_continue_command::continuing)
                 break;
             }
-          else if (curr_lexer->parser_end_of_input)
+          else if (curr_parser->end_of_input)
             break;
         }
     }
@@ -4465,12 +4311,6 @@
     }
 }
 
-int
-octave_parse_input (void)
-{
-  return octave_parse ();
-}
-
 DEFUN (eval, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} eval (@var{try})\n\
--- a/libinterp/parse-tree/parse.h	Tue Feb 26 12:06:45 2013 +0100
+++ b/libinterp/parse-tree/parse.h	Wed Feb 27 14:51:21 2013 -0500
@@ -29,14 +29,40 @@
 
 #include <stack>
 
-extern void reset_parser (void);
+#include "lex.h"
+#include "token.h"
+
 extern int octave_lex (void);
 
+class octave_comment_list;
+class octave_function;
+class octave_user_function;
 class tree;
-class tree_matrix;
+class tree_anon_fcn_handle;
+class tree_argument_list;
+class tree_cell;
+class tree_colon_expression;
+class tree_command;
+class tree_constant;
+class tree_decl_command;
+class tree_decl_init_list;
+class tree_expression;
+class tree_fcn_handle;
+class tree_function_def;
 class tree_identifier;
+class tree_if_clause;
+class tree_if_command;
+class tree_if_command_list;
+class tree_index_expression;
+class tree_matrix;
+class tree_matrix;
+class tree_parameter_list;
+class tree_statement;
 class tree_statement_list;
-class octave_function;
+class tree_statement_listtree_statement;
+class tree_switch_case;
+class tree_switch_case_list;
+class tree_switch_command;
 
 #include "oct-obj.h"
 
@@ -106,6 +132,216 @@
 
 extern OCTINTERP_API void cleanup_statement_list (tree_statement_list **lst);
 
-extern OCTINTERP_API int octave_parse_input (void);
+class
+octave_parser
+{
+public:
+
+  octave_parser (void) : end_of_input (false) { }
+
+  ~octave_parser (void) { }
+
+  void reset (void)
+  {
+    curr_lexer->reset ();
+  }
+
+  int run (void);
+
+  // Error mesages for mismatched end tokens.
+  void end_error (const char *type, token::end_tok_type ettype, int l, int c);
+
+  // 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 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);
+
+  // 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 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 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 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 a try-catch command.
+  tree_command *
+  make_try_command (token *try_tok, tree_statement_list *body,
+                    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 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 break command.
+  tree_command *make_break_command (token *break_tok);
+
+  // Build a continue command.
+  tree_command *make_continue_command (token *continue_tok);
+
+  // Build a return command.
+  tree_command *make_return_command (token *return_tok);
+
+  // Start an if command.
+  tree_if_command_list *
+  start_if_command (tree_expression *expr, tree_statement_list *list);
+
+  // 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,
+                      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 a switch case.
+  tree_switch_case *
+  make_switch_case (token *case_tok, tree_expression *expr,
+                    tree_statement_list *list, 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);
+
+  // 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);
+
+  // Create a no-op statement for end_function.
+  tree_statement *make_end (const std::string& type, 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);
+
+  // Finish defining a function.
+  tree_function_def *
+  finish_function (tree_parameter_list *ret_list,
+                   octave_user_function *fcn, octave_comment_list *lc);
+
+  // Reset state after parsing function.
+  void
+  recover_from_parsing_function (void);
+
+  // 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 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);
+
+  // Validate argument list forming a matrix or cell row.
+  tree_argument_list *validate_matrix_row (tree_argument_list *row);
+
+  // Finish building a matrix list.
+  tree_expression *finish_matrix (tree_matrix *m);
+
+  // 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 *);
+
+  // Set the print flag for a statement based on the separator type.
+  tree_statement_list *
+  set_stmt_print_flag (tree_statement_list *, char, bool);
+
+  // 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);
+
+  // TRUE means that we have encountered EOF on the input stream.
+  bool end_of_input;
+
+  // For unwind protect.
+  static void cleanup (octave_parser *parser) { delete parser; }
+
+private:
+
+  // No copying!
+
+  octave_parser (const octave_parser&);
+
+  octave_parser& operator = (const octave_parser&);
+};
+
+// The current state of the parser.
+extern octave_parser *curr_parser;
 
 #endif
--- a/libinterp/parse-tree/token.h	Tue Feb 26 12:06:45 2013 +0100
+++ b/libinterp/parse-tree/token.h	Wed Feb 27 14:51:21 2013 -0500
@@ -25,6 +25,8 @@
 
 #include <string>
 
+#include "symtab.h"
+
 class
 token
 {