diff src/oct-parse.yy @ 15037:56b8eb7c9c04 classdef

improvements in parsing classdef * liboctave/base-list.h (octave_base_list::octave_base_list (void), octave_base_list::octave_base_list (const std::list<elt_type>&), octave_base_list::operator = (const octave_base_list&), octave_base_list::~octave_base_list (void)): Now public. * pt-classdef.h, pt-classdef.cc: New files. * src/Makefile.am (PT_INCLUDES): Add pt-classdef.h to the list. (PT_SRC): Add pt-classdef.cc to the list. * pt-all.h: Include pt-classdef.h. * ov.cc: Include ov-classdef.h. * ov-classdef.cc: Include pt-classdef.h. (cdef_class:make_meta_class): New method. (F__meta_get_class__): Delete. (F__superclass_reference__, F__meta_class_query__): New functions. * pt-id.h: Include oct-lvalue.h. * pt-walk.h (tree_walker::visit_classdef (tree_classdef&), tree_walker::visit_classdef_attribute (tree_classdef_attribute&), tree_walker::visit_classdef_attribute_list (tree_classdef_attribute_list&), tree_walker::visit_classdef_superclass (tree_classdef_superclass&), tree_walker::visit_classdef_superclass_list (tree_classdef_superclass_list&), tree_walker::visit_classdef_property (tree_classdef_property&), tree_walker::visit_classdef_property_list (tree_classdef_property_list&), tree_walker::visit_classdef_properties_block (tree_classdef_properties_block&), tree_walker::visit_classdef_methods_list (tree_classdef_methods_list&), tree_walker::visit_classdef_methods_block (tree_classdef_methods_block&), tree_walker::visit_classdef_event (tree_classdef_event&), tree_walker::visit_classdef_events_list (tree_classdef_events_list&), tree_walker::visit_classdef_events_block (tree_classdef_events_block&), tree_walker::visit_classdef_enum (tree_classdef_enum&), tree_walker::visit_classdef_enum_list (tree_classdef_enum_list&), tree_walker::visit_classdef_enum_block (tree_classdef_enum_block&), tree_walker::visit_classdef_body (tree_classdef_body&)): New virtual functions. * token.h, token.cc (token::sc::mr, token::sc::cr, token::sc::pr, token::mc::mr, token::mc::pr): Delete. (token::sc::method_name, token::sc::package_name, token::sc::class_name, token::mc::package_name, token::mc::class_name): New member variables. (token::method_rec, token::class_rec, token::package_rec, token::meta_class_rec, token::meta_package_rec): Delete. (token::superclass_method_name, token::superclass_package_name, token::superclass_class_name, token::meta_package_name, token::meta_class_name): New methods. (token::token (symbol_table::symbol_record*, int, int), token::token (symbol_table::symbol_record*, symbol_table::symbol_record*, int, int), token::token (symbol_table::symbol_record*, symbol_table::symbol_record*, symbol_table::symbol_record*, int, int)): Delete. (token::token (const std::string&, const std::string&, int, int), token::token (const std::string&, const std::string&, const std::string&, int, int)): New constructors. (token::scls_rec_token, token::meta_rec_token): Delete enum values. (token::scls_name_token, token::meta_rec_token): New enum values. (token::~token): Delete sc and mc struct memebers. * lex.ll, lex.h (lexical_feedback::parsing_classdef_get_method, lexical_feedback::parsing_classdef_set_method)): New data members. (lexical_feedback::lexical_feedback, lexical_feedback::init): Initialize new data members. (prep_lexer_for_classdef_file): New function. (CLASSDEF_FILE_BEGIN): New exclusive start state. (handle_superclass_identifier, handle_meta_identifier): Split identifier here and create token with character strings. (display_token): Handle CLASSDEF_FILE. (display_state): Handle CLASSDEF_FILE_BEGIN. * oct-parse.yy: Include ov-classdef.h and pt-funcall.h. (classdef_object): New static variable. (make_superclass_ref, make_meta_class_query, make_classdef, make_classdef_properties_block, make_classdef_methods_block, make_classdef_events_block, make_classdef_enum_block)): New functions. (dummy_type): Delete unused nonterminal type. (tok_type, tree_funcall_type, tree_function_def_type, tree_classdef_type, tree_classdef_attribute_type, tree_classdef_attribute_list_type, tree_classdef_superclass_type, tree_classdef_superclass_list_type, tree_classdef_body_type, tree_classdef_property_type, tree_classdef_property_list_type, tree_classdef_properties_block_type, tree_classdef_methods_list_type, tree_classdef_methods_block_type, tree_classdef_event_type, tree_classdef_events_list_type, tree_classdef_events_block_type, tree_classdef_enum_type, tree_classdef_enum_list_type, tree_classdef_enum_block_type): New types for nonterminals. (CLASSDEF): Declare to have a tok_val token value. (CLASSDEF_FILE): New token. (classdef_end, properties_beg, methods_beg, events_beg, enum_beg, classdef1): Delete nonterminals. (property_list): Rename from properties_list. (attr, class_event, class_enum, class_property, property_list, properties_block, methods_list, methods_block, opt_attr_list, attr_list, events_list, events_blcok, enum_list, enum_block, class_body, classdef): Declare with specific types. Create parse tree objects for these nonterminals. (classdef_file): New nonterminal. (parse_fcn_file): Handle classdef files. Don't treat classdef files as scripts. (command): Don't handle classdef here. (input): Accept classdef_file here. (fcn_name): If GET, set lexer_flags.parsing_classdef_get_method. If SET, set lexer_flags.parsing_classdef_set_method.
author John W. Eaton <jwe@octave.org>
date Fri, 27 Jul 2012 17:10:25 -0400
parents 460a3c6d8bf1
children
line wrap: on
line diff
--- a/src/oct-parse.yy	Fri Jul 27 16:02:01 2012 -0400
+++ b/src/oct-parse.yy	Fri Jul 27 17:10:25 2012 -0400
@@ -62,6 +62,7 @@
 #include "load-path.h"
 #include "oct-hist.h"
 #include "oct-map.h"
+#include "ov-classdef.h"
 #include "ov-fcn-handle.h"
 #include "ov-usr-fcn.h"
 #include "ov-null-mat.h"
@@ -71,6 +72,7 @@
 #include "parse-private.h"
 #include "pt-all.h"
 #include "pt-eval.h"
+#include "pt-funcall.h"
 #include "symtab.h"
 #include "token.h"
 #include "unwind-prot.h"
@@ -152,6 +154,9 @@
 // used while reading function files.
 static symbol_table::scope_id primary_fcn_scope;
 
+// Pointer to the classdef object we just parsed, if any.
+static tree_classdef *classdef_object = 0;
+
 // List of autoloads (function -> file mapping).
 static std::map<std::string, std::string> autoload_map;
 
@@ -356,6 +361,47 @@
 append_statement_list (tree_statement_list *list, char sep,
                        tree_statement *stmt, bool warn_missing_semi);
 
+static tree_funcall *
+make_superclass_ref (const std::string& method_nm,
+                     const std::string& package_nm,
+                     const std::string& class_nm,
+                     int l, int c);
+
+static tree_funcall *
+make_meta_class_query (const std::string& package_nm,
+                       const std::string& class_nm,
+                       int l, int c);
+
+static tree_classdef *
+make_classdef (token *tok_val, tree_classdef_attribute_list *a,
+               tree_identifier *id, tree_classdef_superclass_list *sc,
+               tree_classdef_body *body, token *end_tok,
+               octave_comment_list *lc);
+
+static tree_classdef_properties_block *
+make_classdef_properties_block (token *tok_val,
+                                tree_classdef_attribute_list *a,
+                                tree_classdef_property_list *plist,
+                                token *end_tok, octave_comment_list *lc);
+
+static tree_classdef_methods_block *
+make_classdef_methods_block (token *tok_val,
+                             tree_classdef_attribute_list *a,
+                             tree_classdef_methods_list *mlist,
+                             token *end_tok, octave_comment_list *lc);
+
+static tree_classdef_events_block *
+make_classdef_events_block (token *tok_val,
+                            tree_classdef_attribute_list *a,
+                            tree_classdef_events_list *elist,
+                            token *end_tok, octave_comment_list *lc);
+
+static tree_classdef_enum_block *
+make_classdef_enum_block (token *tok_val,
+                          tree_classdef_attribute_list *a,
+                          tree_classdef_enum_list *elist,
+                          token *end_tok, octave_comment_list *lc);
+
 // Finish building a statement.
 template <class T>
 static tree_statement *
@@ -400,12 +446,15 @@
 
   // Types for the nonterminals we generate.
   char sep_type;
+  token *tok_type;
   tree *tree_type;
   tree_matrix *tree_matrix_type;
   tree_cell *tree_cell_type;
   tree_expression *tree_expression_type;
   tree_constant *tree_constant_type;
   tree_fcn_handle *tree_fcn_handle_type;
+  tree_funcall *tree_funcall_type;
+  tree_function_def *tree_function_def_type;
   tree_anon_fcn_handle *tree_anon_fcn_handle_type;
   tree_identifier *tree_identifier_type;
   tree_index_expression *tree_index_expression_type;
@@ -425,7 +474,24 @@
   tree_statement *tree_statement_type;
   tree_statement_list *tree_statement_list_type;
   octave_user_function *octave_user_function_type;
-  void *dummy_type;
+
+  tree_classdef *tree_classdef_type;
+  tree_classdef_attribute* tree_classdef_attribute_type;
+  tree_classdef_attribute_list* tree_classdef_attribute_list_type;
+  tree_classdef_superclass* tree_classdef_superclass_type;
+  tree_classdef_superclass_list* tree_classdef_superclass_list_type;
+  tree_classdef_body* tree_classdef_body_type;
+  tree_classdef_property* tree_classdef_property_type;
+  tree_classdef_property_list* tree_classdef_property_list_type;
+  tree_classdef_properties_block* tree_classdef_properties_block_type;
+  tree_classdef_methods_list* tree_classdef_methods_list_type;
+  tree_classdef_methods_block* tree_classdef_methods_block_type;
+  tree_classdef_event* tree_classdef_event_type;
+  tree_classdef_events_list* tree_classdef_events_list_type;
+  tree_classdef_events_block* tree_classdef_events_block_type;
+  tree_classdef_enum* tree_classdef_enum_type;
+  tree_classdef_enum_list* tree_classdef_enum_list_type;
+  tree_classdef_enum_block* tree_classdef_enum_block_type;
 }
 
 // Tokens with line and column information.
@@ -452,6 +518,7 @@
 %token <tok_val> TRY CATCH
 %token <tok_val> GLOBAL PERSISTENT
 %token <tok_val> FCN_HANDLE
+%token <tok_val> CLASSDEF
 %token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
 %token <tok_val> METAQUERY
 %token <tok_val> SUPERCLASSREF
@@ -459,13 +526,13 @@
 
 // Other tokens.
 %token END_OF_INPUT LEXICAL_ERROR
-%token FCN SCRIPT_FILE FUNCTION_FILE CLASSDEF
+%token FCN SCRIPT_FILE CLASSDEF_FILE FUNCTION_FILE
 // %token VARARGIN VARARGOUT
 %token CLOSE_BRACE
 
 // Nonterminals we construct.
-%type <comment_type> stash_comment function_beg classdef_beg
-%type <comment_type> properties_beg methods_beg events_beg enum_beg
+%type <comment_type> stash_comment function_beg
+%type <tok_type> classdef_beg
 %type <sep_type> sep_no_nl opt_sep_no_nl sep opt_sep opt_comma
 %type <tree_type> input
 %type <tree_constant_type> string constant magic_colon
@@ -477,18 +544,19 @@
 %type <tree_expression_type> primary_expr oper_expr
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
 %type <tree_identifier_type> identifier fcn_name magic_tilde
-%type <tree_identifier_type> superclass_identifier meta_identifier
-%type <octave_user_function_type> function1 function2 classdef1
+%type <tree_funcall_type> superclass_identifier meta_identifier
+%type <octave_user_function_type> function1 function2
 %type <tree_index_expression_type> word_list_cmd
 %type <tree_colon_expression_type> colon_expr1
 %type <tree_argument_list_type> arg_list word_list assign_lhs
 %type <tree_argument_list_type> cell_or_matrix_row
 %type <tree_parameter_list_type> param_list param_list1 param_list2
 %type <tree_parameter_list_type> return_list return_list1
-%type <tree_parameter_list_type> superclasses opt_superclasses
 %type <tree_command_type> command select_command loop_command
-%type <tree_command_type> jump_command except_command function
-%type <tree_command_type> script_file classdef
+%type <tree_command_type> jump_command except_command
+%type <tree_function_def_type> function
+%type <tree_classdef_type> classdef
+%type <tree_command_type> script_file classdef_file
 %type <tree_command_type> function_file function_list
 %type <tree_if_command_type> if_command
 %type <tree_if_clause_type> elseif_clause else_clause
@@ -499,25 +567,26 @@
 %type <tree_decl_elt_type> decl2
 %type <tree_decl_init_list_type> decl1
 %type <tree_decl_command_type> declaration
-%type <tree_statement_type> statement function_end classdef_end
+%type <tree_statement_type> statement function_end
 %type <tree_statement_list_type> simple_list simple_list1 list list1
 %type <tree_statement_list_type> opt_list input1
-// These types need to be specified.
-%type <dummy_type> attr
-%type <dummy_type> class_event
-%type <dummy_type> class_enum
-%type <dummy_type> class_property
-%type <dummy_type> properties_list
-%type <dummy_type> properties_block
-%type <dummy_type> methods_list
-%type <dummy_type> methods_block
-%type <dummy_type> opt_attr_list
-%type <dummy_type> attr_list
-%type <dummy_type> events_list
-%type <dummy_type> events_block
-%type <dummy_type> enum_list
-%type <dummy_type> enum_block
-%type <dummy_type> class_body
+
+%type <tree_classdef_attribute_type> attr
+%type <tree_classdef_attribute_list_type> attr_list opt_attr_list
+%type <tree_classdef_superclass_type> superclass
+%type <tree_classdef_superclass_list_type> superclass_list opt_superclass_list
+%type <tree_classdef_body_type> class_body
+%type <tree_classdef_property_type> class_property
+%type <tree_classdef_property_list_type> property_list
+%type <tree_classdef_properties_block_type> properties_block
+%type <tree_classdef_methods_list_type> methods_list
+%type <tree_classdef_methods_block_type> methods_block
+%type <tree_classdef_event_type> class_event
+%type <tree_classdef_events_list_type> events_list
+%type <tree_classdef_events_block_type> events_block
+%type <tree_classdef_enum_type> class_enum
+%type <tree_classdef_enum_list_type> enum_list
+%type <tree_classdef_enum_block_type> enum_block
 
 // Precedence and associativity.
 %right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ
@@ -552,6 +621,8 @@
                   }
                 | function_file
                   { YYACCEPT; }
+                | classdef_file
+                  { YYACCEPT; }
                 | simple_list parse_error
                   { ABORT_PARSE; }
                 | parse_error
@@ -641,11 +712,24 @@
 
 superclass_identifier
                 : SUPERCLASSREF
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string method_nm = $1->superclass_method_name ();
+                    std::string package_nm = $1->superclass_package_name ();
+                    std::string class_nm = $1->superclass_class_name ();
+
+                    $$ = make_superclass_ref (method_nm, package_nm, class_nm,
+                                              $1->line (), $1->column ());
+                  }
                 ;
 
 meta_identifier : METAQUERY
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string package_nm = $1->meta_package_name ();
+                    std::string class_nm = $1->meta_class_name ();
+
+                    $$ = make_meta_class_query (package_nm, class_nm,
+                                                $1->line (), $1->column ());
+                  }
                 ;
 
 string          : DQ_STRING
@@ -984,8 +1068,6 @@
                   { $$ = $1; }
                 | script_file
                   { $$ = $1; }
-                | classdef
-                  { $$ = $1; }
                 ;
 
 // =====================
@@ -1404,12 +1486,14 @@
                   {
                     lexer_flags.parsed_function_name.top () = true;
                     lexer_flags.maybe_classdef_get_set_method = false;
+                    lexer_flags.parsing_classdef_get_method = true;
                     $$ = $3;
                   }
                 | SET '.' identifier
                   {
                     lexer_flags.parsed_function_name.top () = true;
                     lexer_flags.maybe_classdef_get_set_method = false;
+                    lexer_flags.parsing_classdef_set_method = true;
                     $$ = $3;
                   }
                 ;
@@ -1474,161 +1558,211 @@
                   }
                 ;
 
+// =============
+// Classdef file
+// =============
+
+classdef_file   : CLASSDEF_FILE classdef opt_sep END_OF_INPUT
+                  {
+                    classdef_object = $2;
+                    $$ = 0;
+                  }
+                ;
+
 // ========
 // Classdef
 // ========
 
-classdef_beg    : CLASSDEF stash_comment
+classdef_beg    : CLASSDEF
                   {
-                    $$ = 0;
+                    if (! reading_classdef_file)
+                      {
+                        yyerror ("classdef must appear inside a file containing only a class definition");
+                        YYABORT;
+                      }
+
                     lexer_flags.parsing_classdef = true;
+                    $$ = $1;
                   }
                 ;
 
-classdef_end    : END
+classdef        : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END
                   {
                     lexer_flags.parsing_classdef = false;
-
-                    if (end_token_ok ($1, token::classdef_end))
-                      $$ = make_end ("endclassdef", $1->line (), $1->column ());
-                    else
-                      ABORT_PARSE;
+                    $$ = make_classdef ($1, $3, $4, $5, $7, $9, $2);
                   }
                 ;
 
-classdef1       : classdef_beg opt_attr_list identifier opt_superclasses
-                  { $$ = 0; }
-                ;
-
-classdef        : classdef1 opt_sep class_body opt_sep stash_comment classdef_end
-                  { $$ = 0; }
-                ;
-
 opt_attr_list   : // empty
                   { $$ = 0; }
                 | '(' attr_list ')'
-                  { $$ = 0; }
+                  { $$ = $2; }
                 ;
 
 attr_list       : attr
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute_list ($1); }
                 | attr_list ',' attr
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 attr            : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute ($1); }
                 | identifier '=' decl_param_init expression
-                  { $$ = 0; }
+                  {
+                    lexer_flags.looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_attribute ($1, $4);
+                  }
                 | EXPR_NOT identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute ($2, false); }
                 ;
 
-opt_superclasses
+opt_superclass_list
                 : // empty
                   { $$ = 0; }
-                | superclasses
-                  { $$ = 0; }
+                | superclass_list
+                  { $$ = $1; }
                 ;
 
-superclasses    : EXPR_LT identifier '.' identifier
-                  { $$ = 0; }
-                | EXPR_LT identifier
-                  { $$ = 0; }
-                | superclasses EXPR_AND identifier '.' identifier
-                  { $$ = 0; }
-                | superclasses EXPR_AND identifier
-                  { $$ = 0; }
+superclass_list : EXPR_LT superclass
+                  { $$ = new tree_classdef_superclass_list ($2); }
+                | superclass_list EXPR_AND superclass
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+superclass      : identifier
+                  { $$ = new tree_classdef_superclass ($1); }
+                | identifier '.' identifier
+                  { $$ = new tree_classdef_superclass ($3, $1); }
                 ;
 
 class_body      : properties_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | methods_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | events_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | enum_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | class_body opt_sep properties_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep methods_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep events_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep enum_block
-                  { $$ = 0; }
-                ;
-
-properties_beg  : PROPERTIES stash_comment
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 properties_block
-                : properties_beg opt_attr_list opt_sep properties_list opt_sep END
-                  { $$ = 0; }
+                : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END
+                  {
+                    if (! ($$ = make_classdef_properties_block ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
-properties_list
+property_list
                 : class_property
-                  { $$ = 0; }
-                | properties_list opt_sep class_property
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_property_list ($1); }
+                | property_list opt_sep class_property
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_property  : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_property ($1); }
                 | identifier '=' decl_param_init expression ';'
-                  { $$ = 0; }
+                  {
+                    lexer_flags.looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_property ($1, $4);
+                  }
                 ;
 
-methods_beg     : METHODS stash_comment
-                  { $$ = 0; }
-                ;
-
-methods_block   : methods_beg opt_attr_list opt_sep methods_list opt_sep END
-                  { $$ = 0; }
+methods_block   : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END
+                  {
+                    if (! ($$ = make_classdef_methods_block ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
 methods_list    : function
-                  { $$ = 0; }
+                  {
+                    octave_value fcn;
+                    if ($1)
+                      fcn = $1->function ();
+                    delete $1;
+                    $$ = new tree_classdef_methods_list (fcn);
+                  }
                 | methods_list opt_sep function
-                  { $$ = 0; }
+                  {
+                    octave_value fcn;
+                    if ($3)
+                      fcn = $3->function ();
+                    delete $3;
+
+                    $1->append (fcn);
+                    $$ = $1;
+                  }
                 ;
 
-events_beg      : EVENTS stash_comment
-                  { $$ = 0; }
-                ;
-
-events_block    : events_beg opt_attr_list opt_sep events_list opt_sep END
-                  { $$ = 0; }
+events_block    : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END
+                  {
+                    if (! ($$ = make_classdef_events_block ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
 events_list     : class_event
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_events_list ($1); }
                 | events_list opt_sep class_event
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_event     : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_event ($1); }
                 ;
 
-enum_beg        : ENUMERATION stash_comment
-                  { $$ = 0; }
-                ;
-
-enum_block      : enum_beg opt_attr_list opt_sep enum_list opt_sep END
-                  { $$ = 0; }
+enum_block      : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END
+                  {
+                    if (! ($$ = make_classdef_enum_block ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
 enum_list       : class_enum
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_enum_list ($1); }
                 | enum_list opt_sep class_enum
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_enum      : identifier '(' expression ')'
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_enum ($1, $3); }
                 ;
 
 // =============
@@ -3268,6 +3402,151 @@
   return list;
 }
 
+static tree_funcall *
+make_superclass_ref (const std::string& method_nm,
+                     const std::string& package_nm,
+                     const std::string& class_nm,
+                     int l, int c)
+{
+  octave_value_list args;
+
+  args(2) = class_nm;
+  args(1) = package_nm;
+  args(0) = method_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__superclass_reference__");
+
+  return new tree_funcall (fcn, args);
+}
+
+static tree_funcall *
+make_meta_class_query (const std::string& package_nm,
+                       const std::string& class_nm,
+                       int l, int c)
+{
+  octave_value_list args;
+
+  args(1) = class_nm;
+  args(0) = package_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__meta_class_query__");
+
+  return new tree_funcall (fcn, args);
+}
+
+// A CLASSDEF block defines a class that has a constructor and other
+// methods, but it is not an executable command.  Parsing the block
+// makes some changes in the symbol table (inserting the constructor
+// and methods, and adding to the list of known objects) and creates
+// a parse tree containing meta information about the class.
+
+static tree_classdef *
+make_classdef (token *tok_val, tree_classdef_attribute_list *a,
+               tree_identifier *id, tree_classdef_superclass_list *sc,
+               tree_classdef_body *body, token *end_tok,
+               octave_comment_list *lc)
+{
+  tree_classdef *retval = 0;
+
+  if (end_token_ok (end_tok, token::classdef_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef (a, id, sc, body, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+static tree_classdef_properties_block *
+make_classdef_properties_block (token *tok_val,
+                                tree_classdef_attribute_list *a,
+                                tree_classdef_property_list *plist,
+                                token *end_tok, octave_comment_list *lc)
+{
+  tree_classdef_properties_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::properties_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+static tree_classdef_methods_block *
+make_classdef_methods_block (token *tok_val,
+                             tree_classdef_attribute_list *a,
+                             tree_classdef_methods_list *mlist,
+                             token *end_tok, octave_comment_list *lc)
+{
+  tree_classdef_methods_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::methods_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+static tree_classdef_events_block *
+make_classdef_events_block (token *tok_val,
+                            tree_classdef_attribute_list *a,
+                            tree_classdef_events_list *elist,
+                            token *end_tok, octave_comment_list *lc)
+{
+  tree_classdef_events_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::events_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+static tree_classdef_enum_block *
+make_classdef_enum_block (token *tok_val,
+                          tree_classdef_attribute_list *a,
+                          tree_classdef_enum_list *elist,
+                          token *end_tok, octave_comment_list *lc)
+{
+  tree_classdef_enum_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::enumeration_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
 static void
 safe_fclose (FILE *f)
 {
@@ -3546,11 +3825,7 @@
 
               reading_classdef_file = true;
               reading_fcn_file = false;
-              // FIXME -- Should classdef files be handled as
-              // scripts or separately?  Currently, without setting up
-              // for reading script files, parsing classdef files
-              // fails.
-              reading_script_file = true;
+              reading_script_file = false;
             }
           else
             {
@@ -3574,6 +3849,9 @@
           frame.protect_var (primary_fcn_ptr);
           primary_fcn_ptr = 0;
 
+          frame.protect_var (classdef_object);
+          classdef_object = 0;
+
           reset_parser ();
 
           // Do this with an unwind-protect cleanup function so that
@@ -3587,6 +3865,8 @@
 
           if (reading_script_file)
             prep_lexer_for_script_file ();
+          else if (reading_classdef_file)
+            prep_lexer_for_classdef_file ();
           else
             prep_lexer_for_function_file ();
 
@@ -3606,9 +3886,22 @@
 
           fcn_ptr = primary_fcn_ptr;
 
-          if (status != 0)
-            error ("parse error while reading %s file %s",
-                   file_type.c_str (), ff.c_str ());
+          if (status == 0)
+            {
+              if (reading_classdef_file && classdef_object)
+                {
+                  // Convert parse tree for classdef object to
+                  // meta.class info (and stash it in the symbol
+                  // table?).  Return pointer to constructor?
+                  
+                  octave_value meta_class = classdef_object->make_meta_class ();
+                }
+            }
+          else
+            {
+              error ("parse error while reading %s file %s",
+                     file_type.c_str(), ff.c_str ());
+            }
         }
       else
         {