changeset 16287:04a7953496a7

create base class for parser; use reference for curr_lexer * lex.h, lex.ll (octave_base_parser): New base class for parser class. Move most of previous octave_parser class here. Use reference for curr_lexer object instead of pointer. Change all uses. (octave_parser): Derive from octave_base_parser.
author John W. Eaton <jwe@octave.org>
date Tue, 12 Mar 2013 00:18:28 -0400
parents 3389152014ca
children fe3b9a51e625
files libinterp/interpfcn/toplev.cc libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/parse.h
diffstat 3 files changed, 262 insertions(+), 269 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/interpfcn/toplev.cc	Mon Mar 11 18:19:10 2013 -0400
+++ b/libinterp/interpfcn/toplev.cc	Tue Mar 12 00:18:28 2013 -0400
@@ -620,7 +620,7 @@
                         command_editor::increment_current_command_number ();
                     }
                 }
-              else if (curr_parser.curr_lexer->end_of_input)
+              else if (curr_parser.curr_lexer.end_of_input)
                 break;
             }
         }
--- a/libinterp/parse-tree/oct-parse.in.yy	Mon Mar 11 18:19:10 2013 -0400
+++ b/libinterp/parse-tree/oct-parse.in.yy	Tue Mar 12 00:18:28 2013 -0400
@@ -107,7 +107,7 @@
 // Forward declarations for some functions defined at the bottom of
 // the file.
 
-static void yyerror (octave_parser& curr_parser, const char *s);
+static void yyerror (octave_base_parser& curr_parser, const char *s);
 
 // Finish building a statement.
 template <class T>
@@ -126,7 +126,7 @@
       if (! parser_symtab_context.empty ()) \
         parser_symtab_context.pop (); \
       if ((interactive || forced_interactive)   \
-          && ! (curr_lexer)->input_from_eval_string ()) \
+          && ! curr_lexer.input_from_eval_string ()) \
         YYACCEPT; \
       else \
         YYABORT; \
@@ -134,7 +134,7 @@
   while (0)
 
 #define curr_lexer curr_parser.curr_lexer
-#define scanner curr_lexer->scanner
+#define scanner curr_lexer.scanner
 
 %}
 
@@ -156,7 +156,7 @@
 
 %define api.pure
 %PUSH_PULL_DECL%
-%parse-param { octave_parser& curr_parser }
+%parse-param { octave_base_parser& curr_parser }
 %lex-param { void *scanner }
 
 %union
@@ -326,7 +326,7 @@
                   { $$ = 0; }
                 | END_OF_INPUT
                   {
-                    curr_lexer->end_of_input = true;
+                    curr_lexer.end_of_input = true;
                     $$ = 0;
                   }
                 | simple_list
@@ -484,14 +484,14 @@
 fcn_handle      : '@' FCN_HANDLE
                   {
                     $$ = curr_parser.make_fcn_handle ($2);
-                    curr_lexer->looking_at_function_handle--;
+                    curr_lexer.looking_at_function_handle--;
                   }
                 ;
 
 anon_fcn_handle : '@' param_list statement
                   {
                     $$ = curr_parser.make_anon_fcn_handle ($2, $3);
-                    curr_lexer->nesting_level.remove ();
+                    curr_lexer.nesting_level.remove ();
                   }
                 ;
 
@@ -503,7 +503,7 @@
                   { $$ = $1; }
                 | matrix
                   {
-                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    curr_lexer.looking_at_matrix_or_assign_lhs = false;
                     $$ = $1;
                   }
                 | cell
@@ -553,7 +553,7 @@
                 ;
 
 indirect_ref_op : '.'
-                  { curr_lexer->looking_at_indirect_ref = true; }
+                  { curr_lexer.looking_at_indirect_ref = true; }
                 ;
 
 oper_expr       : primary_expr
@@ -660,7 +660,7 @@
                     $$ = curr_parser.validate_matrix_for_assignment ($1);
 
                     if ($$)
-                      { curr_lexer->looking_at_matrix_or_assign_lhs = false; }
+                      { curr_lexer.looking_at_matrix_or_assign_lhs = false; }
                     else
                       {
                         // validate_matrix_for_assignment deleted $1.
@@ -751,12 +751,12 @@
 declaration     : GLOBAL decl1
                   {
                     $$ = curr_parser.make_decl_command (GLOBAL, $1, $2);
-                    curr_lexer->looking_at_decl_list = false;
+                    curr_lexer.looking_at_decl_list = false;
                   }
                 | PERSISTENT decl1
                   {
                     $$ = curr_parser.make_decl_command (PERSISTENT, $1, $2);
-                    curr_lexer->looking_at_decl_list = false;
+                    curr_lexer.looking_at_decl_list = false;
                   }
                 ;
 
@@ -770,13 +770,13 @@
                 ;
 
 decl_param_init : // empty
-                { curr_lexer->looking_at_initializer_expression = true; }
+                { curr_lexer.looking_at_initializer_expression = true; }
 
 decl2           : identifier
                   { $$ = new tree_decl_elt ($1); }
                 | identifier '=' decl_param_init expression
                   {
-                    curr_lexer->looking_at_initializer_expression = false;
+                    curr_lexer.looking_at_initializer_expression = false;
                     $$ = new tree_decl_elt ($1, $4);
                   }
                 | magic_tilde
@@ -817,7 +817,7 @@
 
 if_cmd_list1    : expression opt_sep opt_list
                   {
-                    $1->mark_braindead_shortcircuit (curr_lexer->fcn_file_full_name);
+                    $1->mark_braindead_shortcircuit (curr_lexer.fcn_file_full_name);
 
                     $$ = curr_parser.start_if_command ($1, $3);
                   }
@@ -830,7 +830,7 @@
 
 elseif_clause   : ELSEIF stash_comment opt_sep expression opt_sep opt_list
                   {
-                    $4->mark_braindead_shortcircuit (curr_lexer->fcn_file_full_name);
+                    $4->mark_braindead_shortcircuit (curr_lexer.fcn_file_full_name);
 
                     $$ = curr_parser.make_elseif_clause ($1, $4, $6, $2);
                   }
@@ -889,7 +889,7 @@
 
 loop_command    : WHILE stash_comment expression opt_sep opt_list END
                   {
-                    $3->mark_braindead_shortcircuit (curr_lexer->fcn_file_full_name);
+                    $3->mark_braindead_shortcircuit (curr_lexer.fcn_file_full_name);
 
                     if (! ($$ = curr_parser.make_while_command ($1, $3, $5, $6, $2)))
                       ABORT_PARSE;
@@ -986,12 +986,12 @@
 
                     curr_parser.function_scopes.push_back (symbol_table::current_scope ());
 
-                    if (! curr_lexer->reading_script_file
+                    if (! curr_lexer.reading_script_file
                         && curr_parser.curr_fcn_depth == 1
                         && ! curr_parser.parsing_subfunctions)
                       curr_parser.primary_fcn_scope = symbol_table::current_scope ();
 
-                    if (curr_lexer->reading_script_file
+                    if (curr_lexer.reading_script_file
                         && curr_parser.curr_fcn_depth > 1)
                       curr_parser.bison_error ("nested functions not implemented in this context");
                   }
@@ -1003,22 +1003,22 @@
 
 param_list_beg  : '('
                   {
-                    curr_lexer->looking_at_parameter_list = true;
-
-                    if (curr_lexer->looking_at_function_handle)
+                    curr_lexer.looking_at_parameter_list = true;
+
+                    if (curr_lexer.looking_at_function_handle)
                       {
                         parser_symtab_context.push ();
                         symbol_table::set_scope (symbol_table::alloc_scope ());
-                        curr_lexer->looking_at_function_handle--;
-                        curr_lexer->looking_at_anon_fcn_args = true;
+                        curr_lexer.looking_at_function_handle--;
+                        curr_lexer.looking_at_anon_fcn_args = true;
                       }
                   }
                 ;
 
 param_list_end  : ')'
                   {
-                    curr_lexer->looking_at_parameter_list = false;
-                    curr_lexer->looking_for_object_index = false;
+                    curr_lexer.looking_at_parameter_list = false;
+                    curr_lexer.looking_for_object_index = false;
                   }
                 ;
 
@@ -1059,12 +1059,12 @@
 
 return_list     : '[' ']'
                   {
-                    curr_lexer->looking_at_return_list = false;
+                    curr_lexer.looking_at_return_list = false;
                     $$ = new tree_parameter_list ();
                   }
                 | return_list1
                   {
-                    curr_lexer->looking_at_return_list = false;
+                    curr_lexer.looking_at_return_list = false;
                     if ($1->validate (tree_parameter_list::out))
                       $$ = $1;
                     else
@@ -1072,7 +1072,7 @@
                   }
                 | '[' return_list1 ']'
                   {
-                    curr_lexer->looking_at_return_list = false;
+                    curr_lexer.looking_at_return_list = false;
                     if ($2->validate (tree_parameter_list::out))
                       $$ = $2;
                     else
@@ -1095,12 +1095,12 @@
 
 file            : INPUT_FILE opt_nl opt_list END_OF_INPUT
                   {
-                    if (! curr_lexer->reading_fcn_file)
+                    if (! curr_lexer.reading_fcn_file)
                       {
                         tree_statement *end_of_script
                           = curr_parser.make_end ("endscript",
-                                                  curr_lexer->input_line_number,
-                                                  curr_lexer->current_input_column);
+                                                  curr_lexer.input_line_number,
+                                                  curr_lexer.current_input_column);
 
                         curr_parser.make_script ($3, end_of_script);
                       }
@@ -1116,9 +1116,9 @@
 function_beg    : push_fcn_symtab FCN stash_comment
                   {
                     $$ = $3;
-                    if (curr_lexer->reading_classdef_file
-                        || curr_lexer->parsing_classdef)
-                      curr_lexer->maybe_classdef_get_set_method = true;
+                    if (curr_lexer.reading_classdef_file
+                        || curr_lexer.parsing_classdef)
+                      curr_lexer.maybe_classdef_get_set_method = true;
                   }
                 ;
 
@@ -1138,21 +1138,21 @@
                   {
                     std::string id_name = $1->name ();
 
-                    curr_lexer->parsed_function_name.top () = true;
-                    curr_lexer->maybe_classdef_get_set_method = false;
+                    curr_lexer.parsed_function_name.top () = true;
+                    curr_lexer.maybe_classdef_get_set_method = false;
 
                     $$ = $1;
                   }
                 | GET '.' identifier
                   {
-                    curr_lexer->parsed_function_name.top () = true;
-                    curr_lexer->maybe_classdef_get_set_method = false;
+                    curr_lexer.parsed_function_name.top () = true;
+                    curr_lexer.maybe_classdef_get_set_method = false;
                     $$ = $3;
                   }
                 | SET '.' identifier
                   {
-                    curr_lexer->parsed_function_name.top () = true;
-                    curr_lexer->maybe_classdef_get_set_method = false;
+                    curr_lexer.parsed_function_name.top () = true;
+                    curr_lexer.maybe_classdef_get_set_method = false;
                     $$ = $3;
                   }
                 ;
@@ -1185,7 +1185,7 @@
                 | END_OF_INPUT
                   {
 // A lot of tests are based on the assumption that this is OK
-//                  if (curr_lexer->reading_script_file)
+//                  if (curr_lexer.reading_script_file)
 //                    {
 //                      curr_parser.bison_error ("function body open at end of script");
 //                      YYABORT;
@@ -1199,22 +1199,22 @@
                         YYABORT;
                       }
 
-                    if (! (curr_lexer->reading_fcn_file || curr_lexer->reading_script_file
-                           || (curr_lexer)->input_from_eval_string ()))
+                    if (! (curr_lexer.reading_fcn_file || curr_lexer.reading_script_file
+                           || curr_lexer.input_from_eval_string ()))
                       {
                         curr_parser.bison_error ("function body open at end of input");
                         YYABORT;
                       }
 
-                    if (curr_lexer->reading_classdef_file)
+                    if (curr_lexer.reading_classdef_file)
                       {
                         curr_parser.bison_error ("classdef body open at end of input");
                         YYABORT;
                       }
 
                     $$ = curr_parser.make_end ("endfunction",
-                                                curr_lexer->input_line_number,
-                                                curr_lexer->current_input_column);
+                                                curr_lexer.input_line_number,
+                                                curr_lexer.current_input_column);
                   }
                 ;
 
@@ -1225,13 +1225,13 @@
 classdef_beg    : CLASSDEF stash_comment
                   {
                     $$ = 0;
-                    curr_lexer->parsing_classdef = true;
+                    curr_lexer.parsing_classdef = true;
                   }
                 ;
 
 classdef_end    : END
                   {
-                    curr_lexer->parsing_classdef = false;
+                    curr_lexer.parsing_classdef = false;
 
                     if (curr_parser.end_token_ok ($1, token::classdef_end))
                       $$ = curr_parser.make_end ("endclassdef", $1->line (), $1->column ());
@@ -1443,12 +1443,12 @@
 #undef curr_lexer
 
 static void
-yyerror (octave_parser& curr_parser, const char *s)
+yyerror (octave_base_parser& curr_parser, const char *s)
 {
   curr_parser.bison_error (s);
 }
 
-octave_parser::~octave_parser (void)
+octave_base_parser::~octave_base_parser (void)
 {
 #if defined (OCTAVE_USE_PUSH_PARSER)
   yypstate_delete (static_cast<yypstate *> (parser_state));
@@ -1456,60 +1456,33 @@
 
   delete stmt_list;
 
-  delete curr_lexer;
+  delete &curr_lexer;
 }
-void octave_parser::init (void)
+
+void octave_base_parser::init (void)
 {
 #if defined (OCTAVE_USE_PUSH_PARSER)
   parser_state = yypstate_new ();
 #endif
 
-  CURR_LEXER = curr_lexer;
+  CURR_LEXER = &curr_lexer;
 }
 
 void
-octave_parser::reset (void)
+octave_base_parser::reset (void)
 {
   delete stmt_list;
 
   stmt_list = 0;
 
-  curr_lexer->reset ();
-}
-
-int
-octave_parser::run (void)
-{
-  int status = 0;
-
-#if defined (OCTAVE_USE_PUSH_PARSER)
-
-  do
-    {
-      YYSTYPE lval;
-
-      int token = octave_lex (&lval, scanner);
-
-      yypstate *pstate = static_cast<yypstate *> (parser_state);
-
-      status = octave_push_parse (pstate, token, &lval, *this);
-    }
-  while (status == YYPUSH_MORE);
-
-#else
-
-  status = octave_parse (*this);
-
-#endif
-
-  return status;
+  curr_lexer.reset ();
 }
 
 // Error mesages for mismatched end tokens.
 
 void
-octave_parser::end_error (const char *type, token::end_tok_type ettype,
-                          int l, int c)
+octave_base_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";
@@ -1561,7 +1534,7 @@
 // Check to see that end tokens are properly matched.
 
 bool
-octave_parser::end_token_ok (token *tok, token::end_tok_type expected)
+octave_base_parser::end_token_ok (token *tok, token::end_tok_type expected)
 {
   bool retval = true;
 
@@ -1631,12 +1604,12 @@
 // test in a logical expression.
 
 void
-octave_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
+octave_base_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
 {
   if (expr->is_assignment_expression ()
       && expr->paren_count () < 2)
     {
-      if (curr_lexer->fcn_file_full_name.empty ())
+      if (curr_lexer.fcn_file_full_name.empty ())
         warning_with_id
           ("Octave:assign-as-truth-value",
            "suggest parenthesis around assignment used as truth value");
@@ -1644,25 +1617,25 @@
         warning_with_id
           ("Octave:assign-as-truth-value",
            "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'",
-           expr->line (), expr->column (), curr_lexer->fcn_file_full_name.c_str ());
+           expr->line (), expr->column (), curr_lexer.fcn_file_full_name.c_str ());
     }
 }
 
 // Maybe print a warning about switch labels that aren't constants.
 
 void
-octave_parser::maybe_warn_variable_switch_label (tree_expression *expr)
+octave_base_parser::maybe_warn_variable_switch_label (tree_expression *expr)
 {
   if (! expr->is_constant ())
     {
-      if (curr_lexer->fcn_file_full_name.empty ())
+      if (curr_lexer.fcn_file_full_name.empty ())
         warning_with_id ("Octave:variable-switch-label",
                          "variable switch label");
       else
         warning_with_id
           ("Octave:variable-switch-label",
            "variable switch label near line %d, column %d in file '%s'",
-           expr->line (), expr->column (), curr_lexer->fcn_file_full_name.c_str ());
+           expr->line (), expr->column (), curr_lexer.fcn_file_full_name.c_str ());
     }
 }
 
@@ -1758,7 +1731,7 @@
 // Finish building a range.
 
 tree_expression *
-octave_parser::finish_colon_expression (tree_colon_expression *e)
+octave_base_parser::finish_colon_expression (tree_colon_expression *e)
 {
   tree_expression *retval = e;
 
@@ -1822,7 +1795,7 @@
 // Make a constant.
 
 tree_constant *
-octave_parser::make_constant (int op, token *tok_val)
+octave_base_parser::make_constant (int op, token *tok_val)
 {
   int l = tok_val->line ();
   int c = tok_val->column ();
@@ -1885,7 +1858,7 @@
 // Make a function handle.
 
 tree_fcn_handle *
-octave_parser::make_fcn_handle (token *tok_val)
+octave_base_parser::make_fcn_handle (token *tok_val)
 {
   int l = tok_val->line ();
   int c = tok_val->column ();
@@ -1898,12 +1871,12 @@
 // Make an anonymous function handle.
 
 tree_anon_fcn_handle *
-octave_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
-                                     tree_statement *stmt)
+octave_base_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
+                                          tree_statement *stmt)
 {
   // FIXME -- need to get these from the location of the @ symbol.
-  int l = curr_lexer->input_line_number;
-  int c = curr_lexer->current_input_column;
+  int l = curr_lexer.input_line_number;
+  int c = curr_lexer.current_input_column;
 
   tree_parameter_list *ret_list = 0;
 
@@ -1924,7 +1897,7 @@
     = new tree_anon_fcn_handle (param_list, ret_list, body, fcn_scope, l, c);
   // FIXME: Stash the filename.  This does not work and produces
   // errors when executed.
-  //retval->stash_file_name (curr_lexer->fcn_file_name);
+  //retval->stash_file_name (curr_lexer.fcn_file_name);
 
   return retval;
 }
@@ -1932,8 +1905,8 @@
 // Build a binary expression.
 
 tree_expression *
-octave_parser::make_binary_op (int op, tree_expression *op1, token *tok_val,
-                               tree_expression *op2)
+octave_base_parser::make_binary_op (int op, tree_expression *op1,
+                                    token *tok_val, tree_expression *op2)
 {
   octave_value::binary_op t = octave_value::unknown_binary_op;
 
@@ -2036,8 +2009,8 @@
 // Build a boolean expression.
 
 tree_expression *
-octave_parser::make_boolean_op (int op, tree_expression *op1, token *tok_val,
-                                tree_expression *op2)
+octave_base_parser::make_boolean_op (int op, tree_expression *op1,
+                                     token *tok_val, tree_expression *op2)
 {
   tree_boolean_expression::type t;
 
@@ -2068,7 +2041,8 @@
 // Build a prefix expression.
 
 tree_expression *
-octave_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val)
+octave_base_parser::make_prefix_op (int op, tree_expression *op1,
+                                    token *tok_val)
 {
   octave_value::unary_op t = octave_value::unknown_unary_op;
 
@@ -2111,7 +2085,8 @@
 // Build a postfix expression.
 
 tree_expression *
-octave_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val)
+octave_base_parser::make_postfix_op (int op, tree_expression *op1,
+                                     token *tok_val)
 {
   octave_value::unary_op t = octave_value::unknown_unary_op;
 
@@ -2150,12 +2125,12 @@
 // Build an unwind-protect command.
 
 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)
+octave_base_parser::make_unwind_command (token *unwind_tok,
+                                         tree_statement_list *body,
+                                         tree_statement_list *cleanup_stmts,
+                                         token *end_tok,
+                                         octave_comment_list *lc,
+                                         octave_comment_list *mc)
 {
   tree_command *retval = 0;
 
@@ -2176,11 +2151,12 @@
 // Build a try-catch command.
 
 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)
+octave_base_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;
 
@@ -2201,9 +2177,11 @@
 // Build a while command.
 
 tree_command *
-octave_parser::make_while_command (token *while_tok, tree_expression *expr,
-                                   tree_statement_list *body, token *end_tok,
-                                   octave_comment_list *lc)
+octave_base_parser::make_while_command (token *while_tok,
+                                        tree_expression *expr,
+                                        tree_statement_list *body,
+                                        token *end_tok,
+                                        octave_comment_list *lc)
 {
   tree_command *retval = 0;
 
@@ -2213,7 +2191,7 @@
     {
       octave_comment_list *tc = octave_comment_buffer::get_comment ();
 
-      curr_lexer->looping--;
+      curr_lexer.looping--;
 
       int l = while_tok->line ();
       int c = while_tok->column ();
@@ -2227,10 +2205,10 @@
 // Build a do-until command.
 
 tree_command *
-octave_parser::make_do_until_command (token *until_tok,
-                                      tree_statement_list *body,
-                                      tree_expression *expr,
-                                      octave_comment_list *lc)
+octave_base_parser::make_do_until_command (token *until_tok,
+                                           tree_statement_list *body,
+                                           tree_expression *expr,
+                                           octave_comment_list *lc)
 {
   tree_command *retval = 0;
 
@@ -2238,7 +2216,7 @@
 
   octave_comment_list *tc = octave_comment_buffer::get_comment ();
 
-  curr_lexer->looping--;
+  curr_lexer.looping--;
 
   int l = until_tok->line ();
   int c = until_tok->column ();
@@ -2251,12 +2229,13 @@
 // Build a for command.
 
 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)
+octave_base_parser::make_for_command (int tok_id, token *for_tok,
+                                      tree_argument_list *lhs,
+                                      tree_expression *expr,
+                                      tree_expression *maxproc,
+                                      tree_statement_list *body,
+                                      token *end_tok,
+                                      octave_comment_list *lc)
 {
   tree_command *retval = 0;
 
@@ -2266,7 +2245,7 @@
     {
       octave_comment_list *tc = octave_comment_buffer::get_comment ();
 
-      curr_lexer->looping--;
+      curr_lexer.looping--;
 
       int l = for_tok->line ();
       int c = for_tok->column ();
@@ -2296,7 +2275,7 @@
 // Build a break command.
 
 tree_command *
-octave_parser::make_break_command (token *break_tok)
+octave_base_parser::make_break_command (token *break_tok)
 {
   tree_command *retval = 0;
 
@@ -2311,7 +2290,7 @@
 // Build a continue command.
 
 tree_command *
-octave_parser::make_continue_command (token *continue_tok)
+octave_base_parser::make_continue_command (token *continue_tok)
 {
   tree_command *retval = 0;
 
@@ -2326,7 +2305,7 @@
 // Build a return command.
 
 tree_command *
-octave_parser::make_return_command (token *return_tok)
+octave_base_parser::make_return_command (token *return_tok)
 {
   tree_command *retval = 0;
 
@@ -2341,8 +2320,8 @@
 // Start an if command.
 
 tree_if_command_list *
-octave_parser::start_if_command (tree_expression *expr,
-                                 tree_statement_list *list)
+octave_base_parser::start_if_command (tree_expression *expr,
+                                      tree_statement_list *list)
 {
   maybe_warn_assign_as_truth_value (expr);
 
@@ -2354,8 +2333,10 @@
 // Finish an if command.
 
 tree_if_command *
-octave_parser::finish_if_command (token *if_tok, tree_if_command_list *list,
-                                  token *end_tok, octave_comment_list *lc)
+octave_base_parser::finish_if_command (token *if_tok,
+                                       tree_if_command_list *list,
+                                       token *end_tok,
+                                       octave_comment_list *lc)
 {
   tree_if_command *retval = 0;
 
@@ -2386,9 +2367,10 @@
 // Build an elseif clause.
 
 tree_if_clause *
-octave_parser::make_elseif_clause (token *elseif_tok, tree_expression *expr,
-                                   tree_statement_list *list,
-                                   octave_comment_list *lc)
+octave_base_parser::make_elseif_clause (token *elseif_tok,
+                                        tree_expression *expr,
+                                        tree_statement_list *list,
+                                        octave_comment_list *lc)
 {
   maybe_warn_assign_as_truth_value (expr);
 
@@ -2401,9 +2383,11 @@
 // Finish a switch command.
 
 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)
+octave_base_parser::finish_switch_command (token *switch_tok,
+                                           tree_expression *expr,
+                                           tree_switch_case_list *list,
+                                           token *end_tok,
+                                           octave_comment_list *lc)
 {
   tree_switch_command *retval = 0;
 
@@ -2434,9 +2418,10 @@
 // Build a switch case.
 
 tree_switch_case *
-octave_parser::make_switch_case (token *case_tok, tree_expression *expr,
-                                 tree_statement_list *list,
-                                 octave_comment_list *lc)
+octave_base_parser::make_switch_case (token *case_tok,
+                                      tree_expression *expr,
+                                      tree_statement_list *list,
+                                      octave_comment_list *lc)
 {
   maybe_warn_variable_switch_label (expr);
 
@@ -2449,8 +2434,8 @@
 // Build an assignment to a variable.
 
 tree_expression *
-octave_parser::make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
-                               tree_expression *rhs)
+octave_base_parser::make_assign_op (int op, tree_argument_list *lhs,
+                                    token *eq_tok, tree_expression *rhs)
 {
   tree_expression *retval = 0;
 
@@ -2545,8 +2530,8 @@
 // Define a script.
 
 void
-octave_parser::make_script (tree_statement_list *cmds,
-                            tree_statement *end_script)
+octave_base_parser::make_script (tree_statement_list *cmds,
+                                 tree_statement *end_script)
 {
   if (! cmds)
     cmds = new tree_statement_list ();
@@ -2554,11 +2539,11 @@
   cmds->append (end_script);
 
   octave_user_script *script
-    = new octave_user_script (curr_lexer->fcn_file_full_name,
-                              curr_lexer->fcn_file_name,
-                              cmds, curr_lexer->help_text);
-
-  curr_lexer->help_text = "";
+    = new octave_user_script (curr_lexer.fcn_file_full_name,
+                              curr_lexer.fcn_file_name,
+                              cmds, curr_lexer.help_text);
+
+  curr_lexer.help_text = "";
 
   octave_time now;
 
@@ -2570,9 +2555,9 @@
 // Begin defining a function.
 
 octave_user_function *
-octave_parser::start_function (tree_parameter_list *param_list,
-                               tree_statement_list *body,
-                               tree_statement *end_fcn_stmt)
+octave_base_parser::start_function (tree_parameter_list *param_list,
+                                    tree_statement_list *body,
+                                    tree_statement *end_fcn_stmt)
 {
   // We'll fill in the return list later.
 
@@ -2596,7 +2581,7 @@
 }
 
 tree_statement *
-octave_parser::make_end (const std::string& type, int l, int c)
+octave_base_parser::make_end (const std::string& type, int l, int c)
 {
   return make_statement (new tree_no_op_command (type, l, c));
 }
@@ -2604,8 +2589,8 @@
 // Do most of the work for defining a function.
 
 octave_user_function *
-octave_parser::frob_function (const std::string& fname,
-                              octave_user_function *fcn)
+octave_base_parser::frob_function (const std::string& fname,
+                                   octave_user_function *fcn)
 {
   std::string id_name = fname;
 
@@ -2613,36 +2598,36 @@
   // the file does not match the name of the function stated in the
   // file.  Matlab doesn't provide a diagnostic (it ignores the stated
   // name).
-  if (! autoloading && curr_lexer->reading_fcn_file
+  if (! autoloading && curr_lexer.reading_fcn_file
       && curr_fcn_depth == 1 && ! parsing_subfunctions)
   {
-    // FIXME -- should curr_lexer->fcn_file_name already be
+    // FIXME -- should curr_lexer.fcn_file_name already be
     // preprocessed when we get here?  It seems to only be a
     // problem with relative file names.
 
-    std::string nm = curr_lexer->fcn_file_name;
+    std::string nm = curr_lexer.fcn_file_name;
 
     size_t pos = nm.find_last_of (file_ops::dir_sep_chars ());
 
     if (pos != std::string::npos)
-      nm = curr_lexer->fcn_file_name.substr (pos+1);
+      nm = curr_lexer.fcn_file_name.substr (pos+1);
 
     if (nm != id_name)
       {
         warning_with_id
           ("Octave:function-name-clash",
            "function name '%s' does not agree with function file name '%s'",
-           id_name.c_str (), curr_lexer->fcn_file_full_name.c_str ());
+           id_name.c_str (), curr_lexer.fcn_file_full_name.c_str ());
 
         id_name = nm;
       }
   }
 
-  if (curr_lexer->reading_fcn_file || curr_lexer->reading_classdef_file || autoloading)
+  if (curr_lexer.reading_fcn_file || curr_lexer.reading_classdef_file || autoloading)
     {
       octave_time now;
 
-      fcn->stash_fcn_file_name (curr_lexer->fcn_file_full_name);
+      fcn->stash_fcn_file_name (curr_lexer.fcn_file_full_name);
       fcn->stash_fcn_file_time (now);
       fcn->mark_as_system_fcn_file ();
 
@@ -2651,7 +2636,7 @@
 
       if (curr_fcn_depth > 1 || parsing_subfunctions)
         {
-          fcn->stash_parent_fcn_name (curr_lexer->fcn_file_name);
+          fcn->stash_parent_fcn_name (curr_lexer.fcn_file_name);
 
           if (curr_fcn_depth > 1)
             fcn->stash_parent_fcn_scope (function_scopes[function_scopes.size ()-2]);
@@ -2659,7 +2644,7 @@
             fcn->stash_parent_fcn_scope (primary_fcn_scope);
         }
 
-      if (curr_lexer->parsing_class_method)
+      if (curr_lexer.parsing_class_method)
         {
           if (curr_class_name == id_name)
             fcn->mark_as_class_constructor ();
@@ -2678,27 +2663,27 @@
                          "time stamp for '%s' is in the future", nm.c_str ());
     }
   else if (! input_from_tmp_history_file
-           && ! curr_lexer->force_script
-           && curr_lexer->reading_script_file
-           && curr_lexer->fcn_file_name == id_name)
+           && ! curr_lexer.force_script
+           && curr_lexer.reading_script_file
+           && curr_lexer.fcn_file_name == id_name)
     {
       warning ("function '%s' defined within script file '%s'",
-               id_name.c_str (), curr_lexer->fcn_file_full_name.c_str ());
+               id_name.c_str (), curr_lexer.fcn_file_full_name.c_str ());
     }
 
   fcn->stash_function_name (id_name);
-  fcn->stash_fcn_location (curr_lexer->input_line_number,
-                           curr_lexer->current_input_column);
-
-  if (! curr_lexer->help_text.empty () && curr_fcn_depth == 1
+  fcn->stash_fcn_location (curr_lexer.input_line_number,
+                           curr_lexer.current_input_column);
+
+  if (! curr_lexer.help_text.empty () && curr_fcn_depth == 1
       && ! parsing_subfunctions)
     {
-      fcn->document (curr_lexer->help_text);
-
-      curr_lexer->help_text = "";
+      fcn->document (curr_lexer.help_text);
+
+      curr_lexer.help_text = "";
     }
 
-  if (curr_lexer->reading_fcn_file && curr_fcn_depth == 1
+  if (curr_lexer.reading_fcn_file && curr_fcn_depth == 1
       && ! parsing_subfunctions)
     primary_fcn_ptr = fcn;
 
@@ -2706,9 +2691,9 @@
 }
 
 tree_function_def *
-octave_parser::finish_function (tree_parameter_list *ret_list,
-                                octave_user_function *fcn,
-                                octave_comment_list *lc)
+octave_base_parser::finish_function (tree_parameter_list *ret_list,
+                                     octave_user_function *fcn,
+                                     octave_comment_list *lc)
 {
   tree_function_def *retval = 0;
 
@@ -2751,7 +2736,7 @@
       if (curr_fcn_depth == 1 && fcn)
         symbol_table::update_nest (fcn->scope ());
 
-      if (! curr_lexer->reading_fcn_file && curr_fcn_depth == 1)
+      if (! curr_lexer.reading_fcn_file && curr_fcn_depth == 1)
         {
           // We are either reading a script file or defining a function
           // at the command line, so this definition creates a
@@ -2771,31 +2756,32 @@
 }
 
 void
-octave_parser::recover_from_parsing_function (void)
+octave_base_parser::recover_from_parsing_function (void)
 {
   if (parser_symtab_context.empty ())
     panic_impossible ();
 
   parser_symtab_context.pop ();
 
-  if (curr_lexer->reading_fcn_file && curr_fcn_depth == 1
+  if (curr_lexer.reading_fcn_file && curr_fcn_depth == 1
       && ! parsing_subfunctions)
     parsing_subfunctions = true;
 
   curr_fcn_depth--;
   function_scopes.pop_back ();
 
-  curr_lexer->defining_func--;
-  curr_lexer->parsed_function_name.pop ();
-  curr_lexer->looking_at_return_list = false;
-  curr_lexer->looking_at_parameter_list = false;
+  curr_lexer.defining_func--;
+  curr_lexer.parsed_function_name.pop ();
+  curr_lexer.looking_at_return_list = false;
+  curr_lexer.looking_at_parameter_list = false;
 }
 
 // Make an index expression.
 
 tree_index_expression *
-octave_parser::make_index_expression (tree_expression *expr,
-                                      tree_argument_list *args, char type)
+octave_base_parser::make_index_expression (tree_expression *expr,
+                                           tree_argument_list *args,
+                                           char type)
 {
   tree_index_expression *retval = 0;
 
@@ -2827,8 +2813,8 @@
 // Make an indirect reference expression.
 
 tree_index_expression *
-octave_parser::make_indirect_ref (tree_expression *expr,
-                                  const std::string& elt)
+octave_base_parser::make_indirect_ref (tree_expression *expr,
+                                       const std::string& elt)
 {
   tree_index_expression *retval = 0;
 
@@ -2846,7 +2832,7 @@
   else
     retval = new tree_index_expression (expr, elt, l, c);
 
-  curr_lexer->looking_at_indirect_ref = false;
+  curr_lexer.looking_at_indirect_ref = false;
 
   return retval;
 }
@@ -2854,7 +2840,7 @@
 // Make an indirect reference expression with dynamic field name.
 
 tree_index_expression *
-octave_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt)
+octave_base_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt)
 {
   tree_index_expression *retval = 0;
 
@@ -2872,7 +2858,7 @@
   else
     retval = new tree_index_expression (expr, elt, l, c);
 
-  curr_lexer->looking_at_indirect_ref = false;
+  curr_lexer.looking_at_indirect_ref = false;
 
   return retval;
 }
@@ -2880,8 +2866,8 @@
 // Make a declaration command.
 
 tree_decl_command *
-octave_parser::make_decl_command (int tok, token *tok_val,
-                                  tree_decl_init_list *lst)
+octave_base_parser::make_decl_command (int tok, token *tok_val,
+                                       tree_decl_init_list *lst)
 {
   tree_decl_command *retval = 0;
 
@@ -2899,9 +2885,9 @@
         retval = new tree_persistent_command (lst, l, c);
       else
         {
-          if (curr_lexer->reading_script_file)
+          if (curr_lexer.reading_script_file)
             warning ("ignoring persistent declaration near line %d of file '%s'",
-                     l, curr_lexer->fcn_file_full_name.c_str ());
+                     l, curr_lexer.fcn_file_full_name.c_str ());
           else
             warning ("ignoring persistent declaration near line %d", l);
         }
@@ -2916,7 +2902,7 @@
 }
 
 bool
-octave_parser::validate_array_list (tree_expression *e)
+octave_base_parser::validate_array_list (tree_expression *e)
 {
   bool retval = true;
 
@@ -2941,7 +2927,7 @@
 }
 
 tree_argument_list *
-octave_parser::validate_matrix_for_assignment (tree_expression *e)
+octave_base_parser::validate_matrix_for_assignment (tree_expression *e)
 {
   tree_argument_list *retval = 0;
 
@@ -2995,7 +2981,7 @@
 // Finish building an array_list.
 
 tree_expression *
-octave_parser::finish_array_list (tree_array_list *array_list)
+octave_base_parser::finish_array_list (tree_array_list *array_list)
 {
   tree_expression *retval = array_list;
 
@@ -3040,7 +3026,7 @@
 // Finish building a matrix list.
 
 tree_expression *
-octave_parser::finish_matrix (tree_matrix *m)
+octave_base_parser::finish_matrix (tree_matrix *m)
 {
   return finish_array_list (m);
 }
@@ -3048,13 +3034,13 @@
 // Finish building a cell list.
 
 tree_expression *
-octave_parser::finish_cell (tree_cell *c)
+octave_base_parser::finish_cell (tree_cell *c)
 {
   return finish_array_list (c);
 }
 
 void
-octave_parser::maybe_warn_missing_semi (tree_statement_list *t)
+octave_base_parser::maybe_warn_missing_semi (tree_statement_list *t)
 {
   if (curr_fcn_depth > 0)
     {
@@ -3064,13 +3050,13 @@
         warning_with_id
           ("Octave:missing-semicolon",
            "missing semicolon near line %d, column %d in file '%s'",
-            tmp->line (), tmp->column (), curr_lexer->fcn_file_full_name.c_str ());
+            tmp->line (), tmp->column (), curr_lexer.fcn_file_full_name.c_str ());
     }
 }
 
 tree_statement_list *
-octave_parser::set_stmt_print_flag (tree_statement_list *list, char sep,
-                                    bool warn_missing_semi)
+octave_base_parser::set_stmt_print_flag (tree_statement_list *list,
+                                         char sep, bool warn_missing_semi)
 {
   tree_statement *tmp = list->back ();
 
@@ -3106,15 +3092,15 @@
 }
 
 tree_statement_list *
-octave_parser::make_statement_list (tree_statement *stmt)
+octave_base_parser::make_statement_list (tree_statement *stmt)
 {
   return new tree_statement_list (stmt);
 }
 
 tree_statement_list *
-octave_parser::append_statement_list (tree_statement_list *list, char sep,
-                                      tree_statement *stmt,
-                                      bool warn_missing_semi)
+octave_base_parser::append_statement_list (tree_statement_list *list,
+                                           char sep, tree_statement *stmt,
+                                           bool warn_missing_semi)
 {
   set_stmt_print_flag (list, sep, warn_missing_semi);
 
@@ -3124,15 +3110,15 @@
 }
 
 void
-octave_parser::bison_error (const char *s)
+octave_base_parser::bison_error (const char *s)
 {
-  int err_col = curr_lexer->current_input_column - 1;
+  int err_col = curr_lexer.current_input_column - 1;
 
   std::ostringstream output_buf;
 
-  if (curr_lexer->reading_fcn_file || curr_lexer->reading_script_file || curr_lexer->reading_classdef_file)
-    output_buf << "parse error near line " << curr_lexer->input_line_number
-               << " of file " << curr_lexer->fcn_file_full_name;
+  if (curr_lexer.reading_fcn_file || curr_lexer.reading_script_file || curr_lexer.reading_classdef_file)
+    output_buf << "parse error near line " << curr_lexer.input_line_number
+               << " of file " << curr_lexer.fcn_file_full_name;
   else
     output_buf << "parse error:";
 
@@ -3141,7 +3127,7 @@
 
   output_buf << "\n\n";
 
-  std::string curr_line = curr_lexer->current_input_line;
+  std::string curr_line = curr_lexer.current_input_line;
 
   if (! curr_line.empty ())
     {
@@ -3170,6 +3156,12 @@
   parse_error ("%s", msg.c_str ());
 }
 
+int
+octave_parser::run (void)
+{
+  return octave_parse (*this);
+}
+
 static void
 safe_fclose (FILE *f)
 {
@@ -3216,7 +3208,7 @@
 
   if (ffile)
     {
-      // octave_parser constructor sets this for us.
+      // octave_base_parser constructor sets this for us.
       frame.protect_var (CURR_LEXER);
 
       octave_parser curr_parser (ffile);
@@ -3225,12 +3217,12 @@
       curr_parser.autoloading = autoload;
       curr_parser.fcn_file_from_relative_lookup = relative_lookup;
 
-      curr_parser.curr_lexer->force_script = force_script;
-      curr_parser.curr_lexer->prep_for_file ();
-      curr_parser.curr_lexer->parsing_class_method = ! dispatch_type.empty ();
-
-      curr_parser.curr_lexer->fcn_file_name = file;
-      curr_parser.curr_lexer->fcn_file_full_name = full_file;
+      curr_parser.curr_lexer.force_script = force_script;
+      curr_parser.curr_lexer.prep_for_file ();
+      curr_parser.curr_lexer.parsing_class_method = ! dispatch_type.empty ();
+
+      curr_parser.curr_lexer.fcn_file_name = file;
+      curr_parser.curr_lexer.fcn_file_full_name = full_file;
 
       int status = curr_parser.run ();
 
@@ -3912,7 +3904,7 @@
 
   unwind_protect frame;
 
-  // octave_parser constructor sets this for us.
+  // octave_base_parser constructor sets this for us.
   frame.protect_var (CURR_LEXER);
 
   octave_parser curr_parser (eval_str);
@@ -3972,7 +3964,7 @@
                   || tree_continue_command::continuing)
                 break;
             }
-          else if (curr_parser.curr_lexer->end_of_input)
+          else if (curr_parser.curr_lexer.end_of_input)
             break;
         }
     }
--- a/libinterp/parse-tree/parse.h	Mon Mar 11 18:19:10 2013 -0400
+++ b/libinterp/parse-tree/parse.h	Tue Mar 12 00:18:28 2013 -0400
@@ -126,54 +126,28 @@
 extern octave_lexer *CURR_LEXER;
 
 class
-octave_parser
+octave_base_parser
 {
 public:
 
-  octave_parser (void)
-    : endfunction_found (false),
-      autoloading (false), fcn_file_from_relative_lookup (false),
-      parsing_subfunctions (false), max_fcn_depth (0),
-      curr_fcn_depth (0), primary_fcn_scope (-1),
-      curr_class_name (), function_scopes (), primary_fcn_ptr (0),
-      stmt_list (0),
-      curr_lexer (new octave_lexer ()), parser_state (0)
-  {
-    init ();
-  }
-
-  octave_parser (FILE *file)
+  octave_base_parser (octave_lexer& lxr)
     : endfunction_found (false),
       autoloading (false), fcn_file_from_relative_lookup (false),
       parsing_subfunctions (false), max_fcn_depth (0),
       curr_fcn_depth (0), primary_fcn_scope (-1),
       curr_class_name (), function_scopes (), primary_fcn_ptr (0),
       stmt_list (0),
-      curr_lexer (new octave_lexer (file)), parser_state (0)
+      curr_lexer (lxr), parser_state (0)
   {
     init ();
   }
 
-  octave_parser (const std::string& eval_string)
-    : endfunction_found (false),
-      autoloading (false), fcn_file_from_relative_lookup (false),
-      parsing_subfunctions (false), max_fcn_depth (0),
-      curr_fcn_depth (0), primary_fcn_scope (-1),
-      curr_class_name (), function_scopes (), primary_fcn_ptr (0),
-      stmt_list (0),
-      curr_lexer (new octave_lexer (eval_string)), parser_state (0)
-  {
-    init ();
-  }
-
-  ~octave_parser (void);
+  virtual ~octave_base_parser (void);
 
   void init (void);
 
   void reset (void);
 
-  int run (void);
-
   // Error mesages for mismatched end tokens.
   void end_error (const char *type, token::end_tok_type ettype, int l, int c);
 
@@ -407,14 +381,41 @@
   tree_statement_list *stmt_list;
 
   // State of the lexer.
-  octave_lexer *curr_lexer;
+  octave_lexer& curr_lexer;
 
   // Internal state of the parser.  Only used if USE_PUSH_PARSER is
   // defined.
   void *parser_state;
 
-  // For unwind protect.
-  static void cleanup (octave_parser *parser) { delete parser; }
+private:
+
+  // No copying!
+
+  octave_base_parser (const octave_base_parser&);
+
+  octave_base_parser& operator = (const octave_base_parser&);
+};
+
+class
+octave_parser : public octave_base_parser
+{
+public:
+
+  octave_parser (void)
+    : octave_base_parser (*(new octave_lexer ()))
+  { }
+
+  octave_parser (FILE *file)
+    : octave_base_parser (*(new octave_lexer (file)))
+  { }
+
+  octave_parser (const std::string& eval_string)
+    : octave_base_parser (*(new octave_lexer (eval_string)))
+  { }
+
+  ~octave_parser (void) { }
+
+  int run (void);
 
 private: