changeset 29759:ad1491462d13

allow properties function to be called inside classdef method (bug #60763) * lex.h, lex.ll (lexical_feedback::m_classdef_element_names_are_keywords): New data member with initial value of false. (lexical_feedback::reset): Reset it to false. (base_lexer::make_keyword_token): Use m_classdef_element_names_are_keywords instead of m_parsing_classdef to decide whether "properties", "methods", "events", and "enumeration" are handled as keywords. * oct-parse.yy (properties_beg, methods_beg, events_beg, enumeration_beg): New non-terminals. Use instead of PROPERTIES, METHODS, EVENTS, and ENUMERATION in properties_block, methods_block, events_block, and enum_block. Set lexer.m_classdef_element_names_are_keywords to false once a block name is recognized. (property_list, methods_list, events_list, enum_list): Set lexer.m_classdef_element_names_are_keywords to true at the end of a block. (classdef_beg): Set lexer.m_classdef_element_names_are_keywords to true. (class_body): Set lexer.m_classdef_element_names_are_keywords to false. * test/classdef/bug_60763.m: New file. * test/classdef/module.mk: Update. * classdef.tst: New test.
author John W. Eaton <jwe@octave.org>
date Mon, 14 Jun 2021 16:43:33 -0400
parents 1511b7cd3474
children 61eb6602189b
files libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.yy test/classdef/bug_60763.m test/classdef/classdef.tst test/classdef/module.mk
diffstat 6 files changed, 85 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/lex.h	Mon Jun 14 22:00:52 2021 +0200
+++ b/libinterp/parse-tree/lex.h	Mon Jun 14 16:43:33 2021 -0400
@@ -276,6 +276,7 @@
         m_looking_for_object_index (false),
         m_looking_at_indirect_ref (false),
         m_arguments_is_keyword (false),
+        m_classdef_element_names_are_keywords (false),
         m_parsing_anon_fcn_body (false),
         m_parsing_class_method (false),
         m_parsing_classdef (false),
@@ -390,6 +391,10 @@
     // true means arguments is handled as keyword.
     bool m_arguments_is_keyword;
 
+    // true means "properties", "methods", "events", and "enumeration"
+    // are treated like keywords.
+    bool m_classdef_element_names_are_keywords;
+
     // true means we are parsing the body of an anonymous function.
     bool m_parsing_anon_fcn_body;
 
--- a/libinterp/parse-tree/lex.ll	Mon Jun 14 22:00:52 2021 +0200
+++ b/libinterp/parse-tree/lex.ll	Mon Jun 14 16:43:33 2021 -0400
@@ -2239,6 +2239,7 @@
     m_looking_for_object_index = false;
     m_looking_at_indirect_ref = false;
     m_arguments_is_keyword = false;
+    m_classdef_element_names_are_keywords = false;
     m_parsing_anon_fcn_body = false;
     m_parsing_class_method = false;
     m_parsing_classdef = false;
@@ -2843,7 +2844,7 @@
       case properties_kw:
         // 'properties', 'methods' and 'events' are keywords for
         // classdef blocks.
-        if (! m_parsing_classdef)
+        if (! m_classdef_element_names_are_keywords)
           {
             m_at_beginning_of_statement = previous_at_bos;
             return 0;
--- a/libinterp/parse-tree/oct-parse.yy	Mon Jun 14 22:00:52 2021 +0200
+++ b/libinterp/parse-tree/oct-parse.yy	Mon Jun 14 16:43:33 2021 -0400
@@ -249,6 +249,7 @@
 %type <dummy_type> parsing_local_fcns parse_error at_first_executable_stmt
 %type <comment_type> stash_comment
 %type <tok_val> function_beg classdef_beg arguments_beg
+%type <tok_val> properties_beg methods_beg events_beg enumeration_beg
 %type <punct_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep
 %type <tree_type> input
 %type <tree_constant_type> string constant magic_colon
@@ -1841,7 +1842,6 @@
                   }
                 ;
 
-
 args_attr_list  : // empty
                   { $$ = nullptr; }
                 | '(' identifier ')'
@@ -1954,6 +1954,7 @@
                     lexer.m_symtab_context.push (octave::symbol_scope ());
                     lexer.m_parsing_classdef = true;
                     lexer.m_parsing_classdef_decl = true;
+                    lexer.m_classdef_element_names_are_keywords = true;
 
                     $$ = $1;
                   }
@@ -2056,11 +2057,15 @@
                 ;
 
 class_body      : // empty
-                  { $$ = nullptr; }
+                  {
+                    lexer.m_classdef_element_names_are_keywords = false;
+                    $$ = nullptr;
+                  }
                 | class_body1 opt_sep
                   {
                     OCTAVE_YYUSE ($2);
 
+                    lexer.m_classdef_element_names_are_keywords = false;
                     $$ = $1;
                   }
                 ;
@@ -2104,7 +2109,7 @@
                 ;
 
 properties_block
-                : PROPERTIES stash_comment opt_sep attr_list property_list END
+                : properties_beg stash_comment opt_sep attr_list property_list END
                   {
                     OCTAVE_YYUSE ($3);
 
@@ -2121,12 +2126,23 @@
                   }
                 ;
 
+properties_beg  : PROPERTIES
+                  {
+                    lexer.m_classdef_element_names_are_keywords = false;
+                    $$ = $1;
+                  }
+                ;
+
 property_list   : // empty
-                  { $$ = nullptr; }
+                  {
+                    lexer.m_classdef_element_names_are_keywords = true;
+                    $$ = nullptr;
+                  }
                 | property_list1 opt_sep
                   {
                     OCTAVE_YYUSE ($2);
 
+                    lexer.m_classdef_element_names_are_keywords = true;
                     $$ = $1;
                   }
                 ;
@@ -2183,7 +2199,7 @@
                   }
                 ;
 
-methods_block   : METHODS stash_comment opt_sep attr_list methods_list END
+methods_block   : methods_beg stash_comment opt_sep attr_list methods_list END
                   {
                     OCTAVE_YYUSE ($3);
 
@@ -2200,6 +2216,13 @@
                   }
                 ;
 
+methods_beg     : METHODS
+                  {
+                    lexer.m_classdef_element_names_are_keywords = false;
+                    $$ = $1;
+                  }
+                ;
+
 method_decl1    : identifier
                   {
                     if (! ($$ = parser.start_classdef_external_method ($1, nullptr)))
@@ -2237,11 +2260,15 @@
                 ;
 
 methods_list    : // empty
-                  { $$ = nullptr; }
+                  {
+                    lexer.m_classdef_element_names_are_keywords = true;
+                    $$ = nullptr;
+                  }
                 | methods_list1 opt_sep
                   {
                     OCTAVE_YYUSE ($2);
 
+                    lexer.m_classdef_element_names_are_keywords = true;
                     $$ = $1;
                   }
                 ;
@@ -2268,7 +2295,7 @@
                   }
                 ;
 
-events_block    : EVENTS stash_comment opt_sep attr_list events_list END
+events_block    : events_beg stash_comment opt_sep attr_list events_list END
                   {
                     OCTAVE_YYUSE ($3);
 
@@ -2285,12 +2312,23 @@
                   }
                 ;
 
+events_beg      : EVENTS
+                  {
+                    lexer.m_classdef_element_names_are_keywords = false;
+                    $$ = $1;
+                  }
+                ;
+
 events_list     : // empty
-                  { $$ = nullptr; }
+                  {
+                    lexer.m_classdef_element_names_are_keywords = true;
+                    $$ = nullptr;
+                  }
                 | events_list1 opt_sep
                   {
                     OCTAVE_YYUSE ($2);
 
+                    lexer.m_classdef_element_names_are_keywords = true;
                     $$ = $1;
                   }
                 ;
@@ -2310,7 +2348,7 @@
                   { $$ = new octave::tree_classdef_event ($2, $1); }
                 ;
 
-enum_block      : ENUMERATION stash_comment opt_sep attr_list enum_list END
+enum_block      : enumeration_beg stash_comment opt_sep attr_list enum_list END
                   {
                     OCTAVE_YYUSE ($3);
 
@@ -2327,12 +2365,23 @@
                   }
                 ;
 
+enumeration_beg : ENUMERATION
+                  {
+                    lexer.m_classdef_element_names_are_keywords = false;
+                    $$ = $1;
+                  }
+                ;
+
 enum_list       : // empty
-                  { $$ = nullptr; }
+                  {
+                    lexer.m_classdef_element_names_are_keywords = true;
+                    $$ = nullptr;
+                  }
                 | enum_list1 opt_sep
                   {
                     OCTAVE_YYUSE ($2);
 
+                    lexer.m_classdef_element_names_are_keywords = true;
                     $$ = $1;
                   }
                 ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/bug_60763.m	Mon Jun 14 16:43:33 2021 -0400
@@ -0,0 +1,13 @@
+classdef bug_60763
+  properties
+    some_property;
+  endproperties
+  methods
+    function p = foobar (instance)
+      p = properties (instance);
+    endfunction
+    function m = methods (instance)
+      m = 42;
+    endfunction
+  endmethods
+endclassdef
--- a/test/classdef/classdef.tst	Mon Jun 14 22:00:52 2021 +0200
+++ b/test/classdef/classdef.tst	Mon Jun 14 16:43:33 2021 -0400
@@ -205,3 +205,8 @@
 %! x = class_bug55766 ();
 %! props = {"notahiddentestprop"; "publictestprop"; "testprop"};
 %! assert (properties (x), props);
+
+%!test <60763>
+%! x = bug_69763 ();
+%! assert (x.foobar (), {"some_property"});
+%! assert (x.methods (), 42);
--- a/test/classdef/module.mk	Mon Jun 14 22:00:52 2021 +0200
+++ b/test/classdef/module.mk	Mon Jun 14 16:43:33 2021 -0400
@@ -1,4 +1,5 @@
 classdef_TEST_FILES = \
+  %reldir%/bug_60763.m \
   %reldir%/class_bug52614A.m \
   %reldir%/class_bug52614B.m \
   %reldir%/class_bug55766.m \