changeset 18520:932aca9a7c57

Allow multi-level classdef package. * lex.h (octave_base_lexer::fq_identifier_contains_keyword, octave_base_lexer::handle_fq_identifier, octave_base_lexer::enable_fq_identifier): New methods. * lex.ll (octave_base_lexer::fq_identifier_contains_keyword, octave_base_lexer::handle_fq_identifier, octave_base_lexer::enable_fq_identifier): Likewise. (FQ_IDENT_START, FQIDENT): New exclusive start condition and regex to handle fully-qualified identifier. (superclass reference rule, metaclass query rule): Use FQIDENT. (octave_base_lexer::handle_superclass_identifier, octave_base_lexer::handle_meta_identifier): Don't split package name. * parse.h (octave_base_parser::make_superclass_ref, octave_base_parser::make_meta_class_query): Remove package_nm argument. * pt-classdef.h (tree_classdef_superclass::id, tree_classdef_superclass::pkg): Removed members, replaced by cls_name. (tree_classdef_superclass::~tree_classdef_superclass): Remove deletion of removed members. (tree_classdef_superclass::cls_name): New member. (tree_classdef_superclass::tree_classdef_superclass): Initialize it. (tree_classdef_superclass::ident, tree_classdef_superclass::package): Removed methods. (tree_classdef_superclass::class_name): New method. * token.h (token::meta_name_token): Remove enum value. (token(int, std::string, std::string, std::string, int, int)): Remove constructor. (token::superclass_package_name, token::meta_package_name, token::meta_class_name): Remove methods. (token::sc::package_nm, token::mc): Remove union members. * token.cc (token(int, std::string, std::string, std::string, int, int)): Remove constructor. (token::~token): Remove case of meta_name_token. (token::superclass_package_name, token::meta_package_name, token::meta_class_name): Remove methods. * oct-parse.in.yy (FQ_IDENT): New terminal. (superclass_identifier): Adapt to changes in class token and class octave_base_parser. (meta_identifier): Likewise. (superclass_list): Add mid-rule to enable fully-qualified identifier. (superclass): Use FQ_IDENT. (octave_base_parser::make_superclass_ref, octave_base_parser::make_meta_class_query): Remove package_nm argument. * ov-classdef.cc (octave_classdef_superclass_ref::do_multi_index_op): Adapt to removal of package_nm argument. (F__meta_class_query__): Likewise. (cdef_class::make_meta_class): Adapt to changes in class tree_classdef_superclass.
author Michael Goffioul <michael.goffioul@gmail.com>
date Sat, 22 Feb 2014 19:56:17 -0500
parents e1b9c8277ada
children bae00174787c
files libinterp/octave-value/ov-classdef.cc libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/parse.h libinterp/parse-tree/pt-classdef.h libinterp/parse-tree/token.cc libinterp/parse-tree/token.h
diffstat 8 files changed, 141 insertions(+), 151 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-classdef.cc	Sat Feb 22 08:23:26 2014 -0800
+++ b/libinterp/octave-value/ov-classdef.cc	Sat Feb 22 19:56:17 2014 -0500
@@ -1221,12 +1221,9 @@
       if (! error_state && ctx.ok ())
         {
           std::string mname = args(0).string_value ();
-          std::string pname = args(1).string_value ();
-          std::string cname = args(2).string_value ();
-
-          std::string cls_name = (pname.empty () ?
-                                  cname : pname + "." + cname);
-          cdef_class cls = lookup_class (cls_name);
+          std::string cname = args(1).string_value ();
+
+          cdef_class cls = lookup_class (cname);
 
           if (! error_state)
             {
@@ -1248,7 +1245,7 @@
                     }
                   else
                     ::error ("`%s' is not a direct superclass of `%s'",
-                             cls_name.c_str (), ctx.get_name ().c_str ());
+                             cname.c_str (), ctx.get_name ().c_str ());
                 }
               else
                 {
@@ -1274,11 +1271,11 @@
                                                    meth_name);
                           else
                             ::error ("no method `%s' found in superclass `%s'",
-                                     meth_name.c_str (), cls_name.c_str ());
+                                     meth_name.c_str (), cname.c_str ());
                         }
                       else
                         ::error ("`%s' is not a superclass of `%s'",
-                                 cls_name.c_str (), ctx.get_name ().c_str ());
+                                 cname.c_str (), ctx.get_name ().c_str ());
                     }
                   else
                     ::error ("method name mismatch (`%s' != `%s')",
@@ -1969,14 +1966,9 @@
 
                   if (args(0).string_value () == obj_name)
                     {
-                      std::string package_name = args(1).string_value ();
-                      std::string class_name = args(2).string_value ();
-
-                      std::string ctor_name = (package_name.empty ()
-                                               ? class_name
-                                               : package_name + "." + class_name);
-
-                      cdef_class cls = lookup_class (ctor_name, false);
+                      std::string class_name = args(1).string_value ();
+
+                      cdef_class cls = lookup_class (class_name, false);
 
                       if (cls.ok ())
                         ctor_list.push_back (cls);
@@ -2702,9 +2694,7 @@
       for (tree_classdef_superclass_list::iterator it = t->superclass_list ()->begin ();
            ! error_state && it != t->superclass_list ()->end (); ++it)
         {
-          std::string sclass_name =
-            ((*it)->package () ? (*it)->package ()->name () + "." : std::string ())
-            + (*it)->ident ()->name ();
+          std::string sclass_name = (*it)->class_name ();
 
           gnulib::printf ("superclass: %s\n", sclass_name.c_str ());
 
@@ -3872,17 +3862,12 @@
   octave_value retval;
 
   std::cerr << "__meta_class_query__ ("
-            << args(0).string_value () << ", "
-            << args(1).string_value () << ")"
+            << args(0).string_value () << ")"
             << std::endl;
 
-  if (args.length () == 2)
+  if (args.length () == 1)
     {
-      std::string pkg = args(0).string_value ();
-      std::string cls = args(1).string_value ();
-
-      if (! pkg.empty ())
-        cls = pkg + "." + cls;
+      std::string cls = args(0).string_value ();
 
       if (! error_state)
 	retval = to_ov (lookup_class (cls));
--- a/libinterp/parse-tree/lex.h	Sat Feb 22 08:23:26 2014 -0800
+++ b/libinterp/parse-tree/lex.h	Sat Feb 22 19:56:17 2014 -0500
@@ -580,6 +580,8 @@
 
   int is_keyword_token (const std::string& s);
 
+  bool fq_identifier_contains_keyword (const std::string& s);
+
   bool whitespace_is_significant (void);
 
   void handle_number (void);
@@ -598,6 +600,8 @@
 
   int handle_meta_identifier (void);
 
+  int handle_fq_identifier (void);
+
   int handle_identifier (void);
 
   void maybe_warn_separator_insert (char sep);
@@ -683,6 +687,8 @@
 
   int show_token (int tok);
 
+  void enable_fq_identifier (void);
+
 protected:
 
   std::stack<int> start_state_stack;
--- a/libinterp/parse-tree/lex.ll	Sat Feb 22 08:23:26 2014 -0800
+++ b/libinterp/parse-tree/lex.ll	Sat Feb 22 19:56:17 2014 -0500
@@ -54,6 +54,8 @@
 %x DQ_STRING_START
 %x SQ_STRING_START
 
+%x FQ_IDENT_START
+
 %{
 
 #include <cctype>
@@ -311,6 +313,7 @@
 Im      [iIjJ]
 CCHAR   [#%]
 IDENT   ([_$a-zA-Z][_$a-zA-Z0-9]*)
+FQIDENT ({IDENT}(\.{IDENT})*)
 EXPON   ([DdEe][+-]?{D}+)
 NUMBER  (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?)|(0[xX][0-9a-fA-F]+))
 
@@ -1031,6 +1034,35 @@
   }
 
 %{
+// Fully-qualified identifiers (used for classdef).
+%}
+
+<FQ_IDENT_START>{FQIDENT} {
+    curr_lexer->lexer_debug ("<FQ_IDENT_START>{FQIDENT}");
+    curr_lexer->pop_start_state ();
+
+    int id_tok = curr_lexer->handle_fq_identifier ();
+
+    if (id_tok >= 0)
+      {
+        curr_lexer->looking_for_object_index = true;
+
+        return curr_lexer->count_token_internal (id_tok);
+      }
+  }
+
+<FQ_IDENT_START>{S}+ {
+    curr_lexer->current_input_column += yyleng;
+
+    curr_lexer->mark_previous_token_trailing_space ();
+  }
+
+<FQ_IDENT_START>. {
+    yyless (0);
+    curr_lexer->pop_start_state ();
+  }
+
+%{
 // Imaginary numbers.
 %}
 
@@ -1168,9 +1200,8 @@
 // Superclass method identifiers.
 %}
 
-{IDENT}@{IDENT} |
-{IDENT}@{IDENT}\.{IDENT} {
-    curr_lexer->lexer_debug ("{IDENT}@{IDENT}|{IDENT}@{IDENT}\\.{IDENT}");
+{IDENT}@{FQIDENT} {
+    curr_lexer->lexer_debug ("{IDENT}@{FQIDENT}");
 
     if (curr_lexer->previous_token_may_be_command ())
       {
@@ -1194,9 +1225,8 @@
 // Metaclass query
 %}
 
-\?{IDENT} |
-\?{IDENT}\.{IDENT} {
-    curr_lexer->lexer_debug ("\\?{IDENT}|\\?{IDENT}\\.{IDENT}");
+\?{FQIDENT} {
+    curr_lexer->lexer_debug ("\\?{FQIDENT}");
 
     if (curr_lexer->previous_token_may_be_command ()
         &&  curr_lexer->space_follows_previous_token ())
@@ -2560,6 +2590,34 @@
 }
 
 bool
+octave_base_lexer::fq_identifier_contains_keyword (const std::string& s)
+{
+  size_t p1 = 0;
+  size_t p2;
+
+  std::string s_part;
+
+  do
+    {
+      p2 = s.find ('.', p1);
+
+      if (p2 != std::string::npos)
+        {
+          s_part = s.substr (p1, p2 - p1);
+          p1 = p2 + 1;
+        }
+      else
+        s_part = s.substr (p1);
+
+      if (is_keyword_token (s_part))
+        return true;
+    }
+  while (p2 != std::string::npos);
+
+  return false;
+}
+
+bool
 octave_base_lexer::whitespace_is_significant (void)
 {
   return (nesting_level.is_bracket ()
@@ -2737,23 +2795,16 @@
   std::string cls = meth.substr (pos + 1);
   meth = meth.substr (0, pos);
 
-  std::string pkg;
-  pos = cls.find (".");
-  if (pos != std::string::npos)
-    {
-      pkg = cls.substr (0, pos);
-      cls = cls.substr (pos + 1);
-    }
-
-  int kw_token = (is_keyword_token (meth) || is_keyword_token (cls)
-                  || is_keyword_token (pkg));
+  bool kw_token = (is_keyword_token (meth)
+                   || fq_identifier_contains_keyword (cls));
+
   if (kw_token)
     {
       error ("method, class, and package names may not be keywords");
       return LEXICAL_ERROR;
     }
 
-  push_token (new token (SUPERCLASSREF, meth, pkg, cls,
+  push_token (new token (SUPERCLASSREF, meth, cls,
                          input_line_number, current_input_column));
 
   current_input_column += flex_yyleng ();
@@ -2766,22 +2817,13 @@
 {
   std::string cls = std::string(flex_yytext ()).substr (1);
 
-  std::string pkg;
-  size_t pos = cls.find (".");
-  if (pos != std::string::npos)
-    {
-      pkg = cls.substr (0, pos);
-      cls = cls.substr (pos + 1);
-    }
-
-  int kw_token = is_keyword_token (cls) || is_keyword_token (pkg);
-  if (kw_token)
+  if (fq_identifier_contains_keyword (cls))
     {
       error ("class and package names may not be keywords");
       return LEXICAL_ERROR;
     }
 
-  push_token (new token (METAQUERY, pkg, cls, input_line_number,
+  push_token (new token (METAQUERY, cls, input_line_number,
                          current_input_column));
 
   current_input_column += flex_yyleng ();
@@ -2789,6 +2831,25 @@
   return METAQUERY;
 }
 
+int
+octave_base_lexer::handle_fq_identifier (void)
+{
+  std::string tok = flex_yytext ();
+
+  if (fq_identifier_contains_keyword (tok))
+    {
+      error ("function, method, class, and package names may not be keywords");
+      return LEXICAL_ERROR;
+    }
+
+  push_token (new token (FQ_IDENT, tok, input_line_number,
+                         current_input_column));
+
+  current_input_column += flex_yyleng ();
+
+  return FQ_IDENT;
+}
+
 // Figure out exactly what kind of token to return when we have seen
 // an identifier.  Handles keywords.  Return -1 if the identifier
 // should be ignored.
@@ -3346,6 +3407,12 @@
   return tok;
 }
 
+void
+octave_base_lexer::enable_fq_identifier (void)
+{
+  push_start_state (FQ_IDENT_START);
+}
+
 int
 octave_lexer::fill_flex_buffer (char *buf, unsigned max_size)
 {
--- a/libinterp/parse-tree/oct-parse.in.yy	Sat Feb 22 08:23:26 2014 -0800
+++ b/libinterp/parse-tree/oct-parse.in.yy	Sat Feb 22 19:56:17 2014 -0500
@@ -235,6 +235,7 @@
 %token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
 %token <tok_val> METAQUERY
 %token <tok_val> SUPERCLASSREF
+%token <tok_val> FQ_IDENT
 %token <tok_val> GET SET
 %token <tok_val> FCN
 
@@ -485,23 +486,20 @@
                 : SUPERCLASSREF
                   {
                     std::string method_nm = $1->superclass_method_name ();
-                    std::string package_nm = $1->superclass_package_name ();
                     std::string class_nm = $1->superclass_class_name ();
 
                     $$ = parser.make_superclass_ref
-                                       (method_nm, package_nm, class_nm,
+                                       (method_nm, class_nm,
                                         $1->line (), $1->column ());
                   }
                 ;
 
 meta_identifier : METAQUERY
                   {
-                    std::string package_nm = $1->meta_package_name ();
-                    std::string class_nm = $1->meta_class_name ();
-
-                    $$ = parser.make_meta_class_query
-                                       (package_nm, class_nm,
-                                        $1->line (), $1->column ());
+                    std::string class_nm = $1->text ();
+
+                    $$ = parser.make_meta_class_query (class_nm, $1->line (),
+                                                       $1->column ());
                   }
                 ;
 
@@ -1553,19 +1551,21 @@
                   { $$ = $1; }
                 ;
 
-superclass_list : EXPR_LT superclass
-                  { $$ = new tree_classdef_superclass_list ($2); }
-                | superclass_list EXPR_AND superclass
+superclass_list : EXPR_LT
+                  { lexer.enable_fq_identifier (); }
+                  superclass
+                  { $$ = new tree_classdef_superclass_list ($3); }
+                | superclass_list EXPR_AND
+                  { lexer.enable_fq_identifier (); }
+                  superclass
                   {
-                    $1->append ($3);
+                    $1->append ($4);
                     $$ = $1;
                   }
                 ;
 
-superclass      : identifier
-                  { $$ = new tree_classdef_superclass ($1); }
-                | identifier '.' identifier
-                  { $$ = new tree_classdef_superclass ($3, $1); }
+superclass      : FQ_IDENT
+                  { $$ = new tree_classdef_superclass ($1->text ()); }
                 ;
 
 class_body      : properties_block
@@ -3115,14 +3115,12 @@
 
 tree_funcall *
 octave_base_parser::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(1) = class_nm;
   args(0) = method_nm;
 
   octave_value fcn
@@ -3132,14 +3130,12 @@
 }
 
 tree_funcall *
-octave_base_parser::make_meta_class_query (const std::string& package_nm,
-                                           const std::string& class_nm,
+octave_base_parser::make_meta_class_query (const std::string& class_nm,
                                            int l, int c)
 {
   octave_value_list args;
 
-  args(1) = class_nm;
-  args(0) = package_nm;
+  args(0) = class_nm;
 
   octave_value fcn
     = symbol_table::find_built_in_function ("__meta_class_query__");
--- a/libinterp/parse-tree/parse.h	Sat Feb 22 08:23:26 2014 -0800
+++ b/libinterp/parse-tree/parse.h	Sat Feb 22 19:56:17 2014 -0500
@@ -300,13 +300,11 @@
 
   tree_funcall *
   make_superclass_ref (const std::string& method_nm,
-                       const std::string& package_nm,
                        const std::string& class_nm,
                        int l, int c);
 
   tree_funcall *
-  make_meta_class_query (const std::string& package_nm,
-                         const std::string& class_nm,
+  make_meta_class_query (const std::string& class_nm,
                          int l, int c);
 
   tree_classdef *
--- a/libinterp/parse-tree/pt-classdef.h	Sat Feb 22 08:23:26 2014 -0800
+++ b/libinterp/parse-tree/pt-classdef.h	Sat Feb 22 19:56:17 2014 -0500
@@ -100,25 +100,18 @@
 {
 public:
 
-  tree_classdef_superclass (tree_identifier *i = 0, tree_identifier *p = 0)
-    : id (i), pkg (p) { }
+  tree_classdef_superclass (const std::string& cname)
+    : cls_name (cname) { }
 
-  ~tree_classdef_superclass (void)
-  {
-    delete id;
-    delete pkg;
-  }
+  ~tree_classdef_superclass (void) { }
 
-  tree_identifier *ident (void) { return id; }
-
-  tree_identifier * package (void) { return pkg; }
+  std::string class_name (void) { return cls_name; }
 
   void accept (tree_walker&);
 
 private:
 
-  tree_identifier *id;
-  tree_identifier *pkg;
+  std::string cls_name;
 
   // No copying!
 
--- a/libinterp/parse-tree/token.cc	Sat Feb 22 08:23:26 2014 -0800
+++ b/libinterp/parse-tree/token.cc	Sat Feb 22 19:56:17 2014 -0500
@@ -97,7 +97,7 @@
   sr = s;
 }
 
-token::token (int tv, const std::string& pkg, const std::string& cls,
+token::token (int tv, const std::string& mth, const std::string& cls,
               int l, int c)
 {
   maybe_cmd = false;
@@ -105,22 +105,8 @@
   line_num = l;
   column_num = c;
   tok_val = tv;
-  type_tag = meta_name_token;
-  mc.package_nm = new std::string (pkg);
-  mc.class_nm = new std::string (cls);
-}
-
-token::token (int tv, const std::string& mth, const std::string& pkg,
-              const std::string& cls, int l, int c)
-{
-  maybe_cmd = false;
-  tspc = false;
-  line_num = l;
-  column_num = c;
-  tok_val = tv;
   type_tag = scls_name_token;
   sc.method_nm = new std::string (mth);
-  sc.package_nm = new std::string (pkg);
   sc.class_nm = new std::string (cls);
 }
 
@@ -132,15 +118,8 @@
   if (type_tag == scls_name_token)
     {
       delete sc.method_nm;
-      delete sc.package_nm;
       delete sc.class_nm;
     }
-
-  if (type_tag == meta_name_token)
-    {
-      delete mc.package_nm;
-      delete mc.class_nm;
-    }
 }
 
 std::string
@@ -192,13 +171,6 @@
 }
 
 std::string
-token::superclass_package_name (void)
-{
-  assert (type_tag == scls_name_token);
-  return *sc.package_nm;
-}
-
-std::string
 token::superclass_class_name (void)
 {
   assert (type_tag == scls_name_token);
@@ -206,20 +178,6 @@
 }
 
 std::string
-token::meta_package_name (void)
-{
-  assert (type_tag == meta_name_token);
-  return *mc.package_nm;
-}
-
-std::string
-token::meta_class_name (void)
-{
-  assert (type_tag == meta_name_token);
-  return *mc.class_nm;
-}
-
-std::string
 token::text_rep (void)
 {
   return orig_text;
--- a/libinterp/parse-tree/token.h	Sat Feb 22 08:23:26 2014 -0800
+++ b/libinterp/parse-tree/token.h	Sat Feb 22 19:56:17 2014 -0500
@@ -41,7 +41,6 @@
     ettype_token,
     sym_rec_token,
     scls_name_token,
-    meta_name_token
   };
 
   enum end_tok_type
@@ -69,10 +68,8 @@
          int l = -1, int c = -1);
   token (int tv, end_tok_type t, int l = -1, int c = -1);
   token (int tv, symbol_table::symbol_record *s, int l = -1, int c = -1);
-  token (int tv, const std::string& pkg, const std::string& cls,
+  token (int tv, const std::string& mth, const std::string& cls,
          int l = -1, int c = -1);
-  token (int tv, const std::string& mth, const std::string& pkg,
-         const std::string& cls, int l = -1, int c = -1);
 
   ~token (void);
 
@@ -106,12 +103,8 @@
   symbol_table::symbol_record *sym_rec (void);
 
   std::string superclass_method_name (void);
-  std::string superclass_package_name (void);
   std::string superclass_class_name (void);
 
-  std::string meta_package_name (void);
-  std::string meta_class_name (void);
-
   std::string text_rep (void);
 
 private:
@@ -137,14 +130,8 @@
     struct
     {
       std::string *method_nm;
-      std::string *package_nm;
       std::string *class_nm;
     } sc;
-    struct
-    {
-      std::string *package_nm;
-      std::string *class_nm;
-    } mc;
   };
   std::string orig_text;
 };