# HG changeset patch # User John W. Eaton # Date 1623703413 14400 # Node ID ad1491462d13771b764ce197c1c1229ba14fd207 # Parent 1511b7cd34747533406d0ce6e01ac14b6eb375ee 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. diff -r 1511b7cd3474 -r ad1491462d13 libinterp/parse-tree/lex.h --- 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; diff -r 1511b7cd3474 -r ad1491462d13 libinterp/parse-tree/lex.ll --- 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; diff -r 1511b7cd3474 -r ad1491462d13 libinterp/parse-tree/oct-parse.yy --- 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 parsing_local_fcns parse_error at_first_executable_stmt %type stash_comment %type function_beg classdef_beg arguments_beg +%type properties_beg methods_beg events_beg enumeration_beg %type sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep %type input %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; } ; diff -r 1511b7cd3474 -r ad1491462d13 test/classdef/bug_60763.m --- /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 diff -r 1511b7cd3474 -r ad1491462d13 test/classdef/classdef.tst --- 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); diff -r 1511b7cd3474 -r ad1491462d13 test/classdef/module.mk --- 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 \