comparison libinterp/parse-tree/oct-parse.yy @ 32892:80d3a6abfc4d stable

improve capture of classdef and classdef method doc strings * lex.h, lex.ll (lexical_feedback::m_classdef_help_text): New data member. (lexical_feedback::lexical_feedback): Initialize it. (lexical_feedback::reset): Reset it to the empty string. * parse.h, oct-parse.yy (function): Also capture comments that appear just before the function body. (base_parser::make_function): New argument ot accept these comments. Maybe capture comments inside a classdef ctor or method as help text. (CLASSDEF): Transfer lexer.m_help_text to lexer.m_classdef_help. (classdef): Also capture comments that appear just before the class body and use the first block of them as classdef help if it is not already set. (base_parser::make_classdef): Pass m_lexer.m_classdef_help_text to tree_classdef ctor then set m_lexer.m_classdef_help_text the empty string. (properties_beg, methods_beg, events_beg, enumeration_beg): Set lexer.m_help_text to the empty string. * pt-classdef.h (tree_classdef::m_help_text): New data member. (tree_classdef::tree_classdef): Initialize it. (tree_classdef::doc_string): Return it instead of m_element_list->doc_string ().
author John W. Eaton <jwe@octave.org>
date Wed, 31 Jan 2024 23:19:10 -0500
parents cb3163ba60c1
children 9104b087dc26 82b67791bf1b
comparison
equal deleted inserted replaced
32891:ff1d5873f805 32892:80d3a6abfc4d
1650 $$ = parser.make_end ("endfunction", true, 1650 $$ = parser.make_end ("endfunction", true,
1651 $1->beg_pos (), $1->end_pos ()); 1651 $1->beg_pos (), $1->end_pos ());
1652 } 1652 }
1653 ; 1653 ;
1654 1654
1655 function : function_beg stash_comment fcn_name 1655 function : function_beg stash_comment fcn_name opt_param_list opt_sep stash_comment function_body function_end
1656 opt_param_list opt_sep function_body function_end
1657 { 1656 {
1658 OCTAVE_YYUSE ($5); 1657 OCTAVE_YYUSE ($5);
1659 1658
1660 $$ = parser.make_function ($1, nullptr, $3, $4, $6, $7, $2); 1659 $$ = parser.make_function ($1, nullptr, $3, $4, $7, $8, $2, $6);
1661 } 1660 }
1662 | function_beg stash_comment return_list '=' fcn_name 1661 | function_beg stash_comment return_list '=' fcn_name opt_param_list opt_sep stash_comment function_body function_end
1663 opt_param_list opt_sep function_body function_end
1664 { 1662 {
1665 OCTAVE_YYUSE ($4, $7); 1663 OCTAVE_YYUSE ($4, $7);
1666 1664
1667 $$ = parser.make_function ($1, $3, $5, $6, $8, $9, $2); 1665 $$ = parser.make_function ($1, $3, $5, $6, $9, $10, $2, $8);
1668 } 1666 }
1669 ; 1667 ;
1670 1668
1671 function_body : at_first_executable_stmt opt_list 1669 function_body : at_first_executable_stmt opt_list
1672 { 1670 {
1832 { 1830 {
1833 parser.bison_error ("classdef must appear inside a file containing only a class definition"); 1831 parser.bison_error ("classdef must appear inside a file containing only a class definition");
1834 YYABORT; 1832 YYABORT;
1835 } 1833 }
1836 1834
1835 lexer.m_classdef_help_text = lexer.m_help_text;
1836 lexer.m_help_text = "";
1837
1837 // Create invalid parent scope. 1838 // Create invalid parent scope.
1838 lexer.m_symtab_context.push (octave::symbol_scope::anonymous ()); 1839 lexer.m_symtab_context.push (octave::symbol_scope::anonymous ());
1839 lexer.m_parsing_classdef = true; 1840 lexer.m_parsing_classdef = true;
1840 lexer.m_parsing_classdef_decl = true; 1841 lexer.m_parsing_classdef_decl = true;
1841 lexer.m_classdef_element_names_are_keywords = true; 1842 lexer.m_classdef_element_names_are_keywords = true;
1842 1843
1843 $$ = $1; 1844 $$ = $1;
1844 } 1845 }
1845 ; 1846 ;
1846 1847
1847 classdef : classdef_beg stash_comment attr_list identifier opt_sep superclass_list class_body END 1848 classdef : classdef_beg attr_list identifier opt_sep stash_comment superclass_list stash_comment class_body END
1848 { 1849 {
1849 OCTAVE_YYUSE ($5); 1850 OCTAVE_YYUSE ($4);
1850 1851
1851 octave::comment_list *lc = $2; 1852 octave::comment_list *lc = $5;
1852 octave::comment_list *tc = lexer.get_comment (); 1853 octave::comment_list *tc = lexer.get_comment ();
1853 1854
1855 if (lexer.m_classdef_help_text.empty () && $7 && ! $7->empty ())
1856 {
1857 const octave::comment_elt& elt = $7->front ();
1858 lexer.m_classdef_help_text = elt.text ();
1859 }
1860
1854 lexer.m_parsing_classdef = false; 1861 lexer.m_parsing_classdef = false;
1855 1862
1856 if (! ($$ = parser.make_classdef ($1, $3, $4, $6, $7, $8, 1863 if (! ($$ = parser.make_classdef ($1, $2, $3, $6, $8, $9,
1857 lc, tc))) 1864 lc, tc)))
1858 { 1865 {
1859 // make_classdef deleted $3, $4, $6, $7, LC, and 1866 // make_classdef deleted $2, $3, $6, $8, LC, and
1860 // TC. 1867 // TC.
1861 YYABORT; 1868 YYABORT;
1862 } 1869 }
1863 } 1870 }
1864 ; 1871 ;
2008 } 2015 }
2009 ; 2016 ;
2010 2017
2011 properties_beg : PROPERTIES 2018 properties_beg : PROPERTIES
2012 { 2019 {
2020 lexer.m_help_text = "";
2021
2013 lexer.m_classdef_element_names_are_keywords = false; 2022 lexer.m_classdef_element_names_are_keywords = false;
2014 $$ = $1; 2023 $$ = $1;
2015 } 2024 }
2016 ; 2025 ;
2017 2026
2084 } 2093 }
2085 ; 2094 ;
2086 2095
2087 methods_beg : METHODS 2096 methods_beg : METHODS
2088 { 2097 {
2098 lexer.m_help_text = "";
2099
2089 lexer.m_classdef_element_names_are_keywords = false; 2100 lexer.m_classdef_element_names_are_keywords = false;
2090 $$ = $1; 2101 $$ = $1;
2091 } 2102 }
2092 ; 2103 ;
2093 2104
2168 } 2179 }
2169 ; 2180 ;
2170 2181
2171 events_beg : EVENTS 2182 events_beg : EVENTS
2172 { 2183 {
2184 lexer.m_help_text = "";
2185
2173 lexer.m_classdef_element_names_are_keywords = false; 2186 lexer.m_classdef_element_names_are_keywords = false;
2174 $$ = $1; 2187 $$ = $1;
2175 } 2188 }
2176 ; 2189 ;
2177 2190
2220 } 2233 }
2221 ; 2234 ;
2222 2235
2223 enumeration_beg : ENUMERATION 2236 enumeration_beg : ENUMERATION
2224 { 2237 {
2238 lexer.m_help_text = "";
2239
2225 lexer.m_classdef_element_names_are_keywords = false; 2240 lexer.m_classdef_element_names_are_keywords = false;
2226 $$ = $1; 2241 $$ = $1;
2227 } 2242 }
2228 ; 2243 ;
2229 2244
3946 tree_parameter_list *ret_list, 3961 tree_parameter_list *ret_list,
3947 tree_identifier *id, 3962 tree_identifier *id,
3948 tree_parameter_list *param_list, 3963 tree_parameter_list *param_list,
3949 tree_statement_list *body, 3964 tree_statement_list *body,
3950 tree_statement *end_fcn_stmt, 3965 tree_statement *end_fcn_stmt,
3951 comment_list *lc) 3966 comment_list *lc, comment_list *bc)
3952 { 3967 {
3968 // If we are looking at a classdef method and there is a comment
3969 // prior to the function keyword and another after, choose the one
3970 // inside the function definition for compatibility with Matlab.
3971
3972 if (m_lexer.m_parsing_classdef && ! m_lexer.m_help_text.empty () && bc && ! bc->empty ())
3973 {
3974 const octave::comment_elt& elt = bc->front ();
3975 m_lexer.m_help_text = elt.text ();
3976 }
3977
3978
3953 int l = fcn_tok->line (); 3979 int l = fcn_tok->line ();
3954 int c = fcn_tok->column (); 3980 int c = fcn_tok->column ();
3955 3981
3956 octave_user_function *tmp_fcn 3982 octave_user_function *tmp_fcn
3957 = start_function (id, param_list, body, end_fcn_stmt); 3983 = start_function (id, param_list, body, end_fcn_stmt);
4376 4402
4377 if (! body) 4403 if (! body)
4378 body = new tree_classdef_body (); 4404 body = new tree_classdef_body ();
4379 4405
4380 retval = new tree_classdef (m_lexer.m_symtab_context.curr_scope (), 4406 retval = new tree_classdef (m_lexer.m_symtab_context.curr_scope (),
4407 m_lexer.m_classdef_help_text,
4381 a, id, sc, body, lc, tc, 4408 a, id, sc, body, lc, tc,
4382 m_curr_package_name, full_name, l, c); 4409 m_curr_package_name, full_name, l, c);
4410
4411 m_lexer.m_classdef_help_text = "";
4383 } 4412 }
4384 else 4413 else
4385 { 4414 {
4386 delete a; 4415 delete a;
4387 delete id; 4416 delete id;