Mercurial > octave
comparison libinterp/parse-tree/oct-parse.yy @ 28511:59dfd9ed72a3 stable
capture comments for classdef classes, properties, events, and enumerations
* parse.h, oct-parse.yy: Refactor parser rules for collecting comments
and docstrings for classdef parse tree elements.
* pt-classdef.h, pt-classdef.cc
(tree_classdef_property, tree_classdef_event, tree_classdef_enum):
Store comments and docstrings and provide access to them.
(tree_classdef_body): Store docstring for classdef object.
(tree_classdef): Provide access to classdef docstring from classdef
body object.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 28 May 2020 13:48:37 -0400 |
parents | 06bc2f0bf760 |
children | 70d155283f33 3dae50cf0bc5 |
comparison
equal
deleted
inserted
replaced
28510:a3ea758870dc | 28511:59dfd9ed72a3 |
---|---|
1729 | 1729 |
1730 classdef : classdef_beg stash_comment attr_list identifier opt_sep superclass_list class_body END | 1730 classdef : classdef_beg stash_comment attr_list identifier opt_sep superclass_list class_body END |
1731 { | 1731 { |
1732 YYUSE ($5); | 1732 YYUSE ($5); |
1733 | 1733 |
1734 octave::comment_list *lc = $2; | |
1735 octave::comment_list *tc = lexer.get_comment (); | |
1736 | |
1734 lexer.m_parsing_classdef = false; | 1737 lexer.m_parsing_classdef = false; |
1735 | 1738 |
1736 if (! ($$ = parser.make_classdef ($1, $3, $4, $6, $7, $8, $2))) | 1739 if (! ($$ = parser.make_classdef ($1, $3, $4, $6, $7, $8, |
1740 lc, tc))) | |
1737 { | 1741 { |
1738 // make_classdef deleted $3, $4, $6, and $7. | 1742 // make_classdef deleted $3, $4, $6, $7, LC, and |
1743 // TC. | |
1739 YYABORT; | 1744 YYABORT; |
1740 } | 1745 } |
1741 } | 1746 } |
1742 ; | 1747 ; |
1743 | 1748 |
1866 $$ = $1; | 1871 $$ = $1; |
1867 } | 1872 } |
1868 ; | 1873 ; |
1869 | 1874 |
1870 properties_block | 1875 properties_block |
1871 : PROPERTIES opt_sep stash_comment attr_list property_list END | 1876 : PROPERTIES stash_comment opt_sep attr_list property_list END |
1872 { | 1877 { |
1873 YYUSE ($2); | 1878 YYUSE ($3); |
1879 | |
1880 octave::comment_list *lc = $2; | |
1881 octave::comment_list *tc = lexer.get_comment (); | |
1874 | 1882 |
1875 if (! ($$ = parser.make_classdef_properties_block | 1883 if (! ($$ = parser.make_classdef_properties_block |
1876 ($1, $4, $5, $6, $3))) | 1884 ($1, $4, $5, $6, lc, tc))) |
1877 { | 1885 { |
1878 // make_classdef_properties_block deleted $4 and $5. | 1886 // make_classdef_properties_block deleted $4, |
1887 // $5, LC, and TC. | |
1879 YYABORT; | 1888 YYABORT; |
1880 } | 1889 } |
1881 } | 1890 } |
1882 ; | 1891 ; |
1883 | 1892 |
1896 { $$ = new octave::tree_classdef_property_list ($1); } | 1905 { $$ = new octave::tree_classdef_property_list ($1); } |
1897 | property_list1 sep class_property | 1906 | property_list1 sep class_property |
1898 { | 1907 { |
1899 YYUSE ($2); | 1908 YYUSE ($2); |
1900 | 1909 |
1910 // We don't look ahead to grab end-of-line comments. | |
1911 // Instead, they are grabbed when we see the | |
1912 // identifier that becomes the next element in the | |
1913 // list. If the element at the end of the list | |
1914 // doesn't have a doc string, see whether the | |
1915 // element we are adding is stroing an end-of-line | |
1916 // comment for us to use. | |
1917 | |
1918 octave::tree_classdef_property *last_elt = $1->back (); | |
1919 | |
1920 if (! last_elt->have_doc_string ()) | |
1921 { | |
1922 octave::comment_list *cl = $3->comments (); | |
1923 | |
1924 if (cl) | |
1925 { | |
1926 octave::comment_elt elt = cl->front (); | |
1927 | |
1928 if (elt.is_end_of_line ()) | |
1929 last_elt->doc_string (elt.text ()); | |
1930 } | |
1931 } | |
1932 | |
1901 $1->append ($3); | 1933 $1->append ($3); |
1902 $$ = $1; | 1934 $$ = $1; |
1903 } | 1935 } |
1904 ; | 1936 ; |
1905 | 1937 |
1906 class_property : identifier | 1938 class_property : stash_comment identifier |
1907 { $$ = new octave::tree_classdef_property ($1); } | 1939 { |
1908 | identifier '=' decl_param_init expression | 1940 $$ = new octave::tree_classdef_property ($2, $1); |
1909 { | 1941 } |
1910 YYUSE ($2); | 1942 | stash_comment identifier '=' decl_param_init expression |
1943 { | |
1944 YYUSE ($3); | |
1911 | 1945 |
1912 lexer.m_looking_at_initializer_expression = false; | 1946 lexer.m_looking_at_initializer_expression = false; |
1913 $$ = new octave::tree_classdef_property ($1, $4); | 1947 |
1914 } | 1948 $$ = new octave::tree_classdef_property ($2, $5, $1); |
1915 ; | 1949 } |
1916 | 1950 ; |
1917 methods_block : METHODS opt_sep stash_comment attr_list methods_list END | 1951 |
1918 { | 1952 methods_block : METHODS stash_comment opt_sep attr_list methods_list END |
1919 YYUSE ($2); | 1953 { |
1954 YYUSE ($3); | |
1955 | |
1956 octave::comment_list *lc = $2; | |
1957 octave::comment_list *tc = lexer.get_comment (); | |
1920 | 1958 |
1921 if (! ($$ = parser.make_classdef_methods_block | 1959 if (! ($$ = parser.make_classdef_methods_block |
1922 ($1, $4, $5, $6, $3))) | 1960 ($1, $4, $5, $6, lc, tc))) |
1923 { | 1961 { |
1924 // make_classdef_methods_block deleted $4 and $5. | 1962 // make_classdef_methods_block deleted $4, $5, |
1963 // LC, and TC. | |
1925 YYABORT; | 1964 YYABORT; |
1926 } | 1965 } |
1927 } | 1966 } |
1928 ; | 1967 ; |
1929 | 1968 |
1950 } | 1989 } |
1951 method_decl1 | 1990 method_decl1 |
1952 { | 1991 { |
1953 lexer.m_defining_func--; | 1992 lexer.m_defining_func--; |
1954 lexer.m_parsed_function_name.pop (); | 1993 lexer.m_parsed_function_name.pop (); |
1994 | |
1955 $$ = parser.finish_classdef_external_method ($5, $2, $1); | 1995 $$ = parser.finish_classdef_external_method ($5, $2, $1); |
1956 } | 1996 } |
1957 ; | 1997 ; |
1958 | 1998 |
1959 method : method_decl | 1999 method : method_decl |
1992 $1->append (fcn); | 2032 $1->append (fcn); |
1993 $$ = $1; | 2033 $$ = $1; |
1994 } | 2034 } |
1995 ; | 2035 ; |
1996 | 2036 |
1997 events_block : EVENTS opt_sep stash_comment attr_list events_list END | 2037 events_block : EVENTS stash_comment opt_sep attr_list events_list END |
1998 { | 2038 { |
1999 YYUSE ($2); | 2039 YYUSE ($3); |
2040 | |
2041 octave::comment_list *lc = $2; | |
2042 octave::comment_list *tc = lexer.get_comment (); | |
2000 | 2043 |
2001 if (! ($$ = parser.make_classdef_events_block | 2044 if (! ($$ = parser.make_classdef_events_block |
2002 ($1, $4, $5, $6, $3))) | 2045 ($1, $4, $5, $6, lc, tc))) |
2003 { | 2046 { |
2004 // make_classdef_events_block deleted $4 and $5. | 2047 // make_classdef_events_block deleted $4, $5, |
2048 // LC, and TC. | |
2005 YYABORT; | 2049 YYABORT; |
2006 } | 2050 } |
2007 } | 2051 } |
2008 ; | 2052 ; |
2009 | 2053 |
2026 $1->append ($3); | 2070 $1->append ($3); |
2027 $$ = $1; | 2071 $$ = $1; |
2028 } | 2072 } |
2029 ; | 2073 ; |
2030 | 2074 |
2031 class_event : identifier | 2075 class_event : stash_comment identifier |
2032 { $$ = new octave::tree_classdef_event ($1); } | 2076 { $$ = new octave::tree_classdef_event ($2, $1); } |
2033 ; | 2077 ; |
2034 | 2078 |
2035 enum_block : ENUMERATION opt_sep stash_comment attr_list enum_list END | 2079 enum_block : ENUMERATION stash_comment opt_sep attr_list enum_list END |
2036 { | 2080 { |
2037 YYUSE ($2); | 2081 YYUSE ($3); |
2082 | |
2083 octave::comment_list *lc = $2; | |
2084 octave::comment_list *tc = lexer.get_comment (); | |
2038 | 2085 |
2039 if (! ($$ = parser.make_classdef_enum_block | 2086 if (! ($$ = parser.make_classdef_enum_block |
2040 ($1, $4, $5, $6, $3))) | 2087 ($1, $4, $5, $6, lc, tc))) |
2041 { | 2088 { |
2042 // make_classdef_enum_block deleted $3 and $4. | 2089 // make_classdef_enum_block deleted $4, $5, LC, |
2090 // and TC. | |
2043 YYABORT; | 2091 YYABORT; |
2044 } | 2092 } |
2045 } | 2093 } |
2046 ; | 2094 ; |
2047 | 2095 |
2064 $1->append ($3); | 2112 $1->append ($3); |
2065 $$ = $1; | 2113 $$ = $1; |
2066 } | 2114 } |
2067 ; | 2115 ; |
2068 | 2116 |
2069 class_enum : identifier '(' expression ')' | 2117 class_enum : stash_comment identifier '(' expression ')' |
2070 { | 2118 { |
2071 YYUSE ($2); | 2119 YYUSE ($3); |
2072 YYUSE ($4); | 2120 YYUSE ($5); |
2073 | 2121 |
2074 $$ = new octave::tree_classdef_enum ($1, $3); | 2122 $$ = new octave::tree_classdef_enum ($2, $4, $1); |
2075 } | 2123 } |
2076 ; | 2124 ; |
2077 | 2125 |
2078 // ============= | 2126 // ============= |
2079 // Miscellaneous | 2127 // Miscellaneous |
3785 // methods, but it is not an executable command. Parsing the block | 3833 // methods, but it is not an executable command. Parsing the block |
3786 // makes some changes in the symbol table (inserting the constructor | 3834 // makes some changes in the symbol table (inserting the constructor |
3787 // and methods, and adding to the list of known objects) and creates | 3835 // and methods, and adding to the list of known objects) and creates |
3788 // a parse tree containing meta information about the class. | 3836 // a parse tree containing meta information about the class. |
3789 | 3837 |
3838 // LC contains comments appearing before the classdef keyword. | |
3839 // TC contains comments appearing between the classdef elements | |
3840 // and the final end token for the classdef block. | |
3841 | |
3790 tree_classdef * | 3842 tree_classdef * |
3791 base_parser::make_classdef (token *tok_val, | 3843 base_parser::make_classdef (token *tok_val, |
3792 tree_classdef_attribute_list *a, | 3844 tree_classdef_attribute_list *a, |
3793 tree_identifier *id, | 3845 tree_identifier *id, |
3794 tree_classdef_superclass_list *sc, | 3846 tree_classdef_superclass_list *sc, |
3795 tree_classdef_body *body, token *end_tok, | 3847 tree_classdef_body *body, token *end_tok, |
3796 comment_list *lc) | 3848 comment_list *lc, comment_list *tc) |
3797 { | 3849 { |
3798 tree_classdef *retval = nullptr; | 3850 tree_classdef *retval = nullptr; |
3799 | 3851 |
3800 m_lexer.m_symtab_context.pop (); | 3852 m_lexer.m_symtab_context.pop (); |
3801 | 3853 |
3815 | 3867 |
3816 delete a; | 3868 delete a; |
3817 delete id; | 3869 delete id; |
3818 delete sc; | 3870 delete sc; |
3819 delete body; | 3871 delete body; |
3872 delete lc; | |
3873 delete tc; | |
3820 | 3874 |
3821 bison_error ("invalid classdef definition, the class name must match the filename", l, c); | 3875 bison_error ("invalid classdef definition, the class name must match the filename", l, c); |
3822 | 3876 |
3823 } | 3877 } |
3824 else | 3878 else |
3825 { | 3879 { |
3826 if (end_token_ok (end_tok, token::classdef_end)) | 3880 if (end_token_ok (end_tok, token::classdef_end)) |
3827 { | 3881 { |
3828 comment_list *tc = m_lexer.m_comment_buf.get_comment (); | |
3829 | |
3830 int l = tok_val->line (); | 3882 int l = tok_val->line (); |
3831 int c = tok_val->column (); | 3883 int c = tok_val->column (); |
3832 | 3884 |
3833 if (! body) | 3885 if (! body) |
3834 body = new tree_classdef_body (); | 3886 body = new tree_classdef_body (); |
3841 { | 3893 { |
3842 delete a; | 3894 delete a; |
3843 delete id; | 3895 delete id; |
3844 delete sc; | 3896 delete sc; |
3845 delete body; | 3897 delete body; |
3898 delete lc; | |
3899 delete tc; | |
3846 | 3900 |
3847 end_token_error (end_tok, token::switch_end); | 3901 end_token_error (end_tok, token::switch_end); |
3848 } | 3902 } |
3849 } | 3903 } |
3850 | 3904 |
3851 return retval; | 3905 return retval; |
3852 } | 3906 } |
3907 | |
3908 // LC contains comments appearing before the properties keyword. | |
3909 // If this properties block appears first in the list of classdef | |
3910 // elements, this comment list will be used for the help text for the | |
3911 // classdef block. | |
3912 | |
3913 // TC contains comments appearing between the list of properties | |
3914 // and the final end token for the properties block and may be used to | |
3915 // find the doc string for the final property in the list. | |
3853 | 3916 |
3854 tree_classdef_properties_block * | 3917 tree_classdef_properties_block * |
3855 base_parser::make_classdef_properties_block (token *tok_val, | 3918 base_parser::make_classdef_properties_block (token *tok_val, |
3856 tree_classdef_attribute_list *a, | 3919 tree_classdef_attribute_list *a, |
3857 tree_classdef_property_list *plist, | 3920 tree_classdef_property_list *plist, |
3858 token *end_tok, | 3921 token *end_tok, |
3859 comment_list *lc) | 3922 comment_list *lc, |
3923 comment_list *tc) | |
3860 { | 3924 { |
3861 tree_classdef_properties_block *retval = nullptr; | 3925 tree_classdef_properties_block *retval = nullptr; |
3862 | 3926 |
3863 if (end_token_ok (end_tok, token::properties_end)) | 3927 if (end_token_ok (end_tok, token::properties_end)) |
3864 { | 3928 { |
3865 comment_list *tc = m_lexer.m_comment_buf.get_comment (); | |
3866 | |
3867 int l = tok_val->line (); | 3929 int l = tok_val->line (); |
3868 int c = tok_val->column (); | 3930 int c = tok_val->column (); |
3869 | 3931 |
3870 if (! plist) | 3932 if (plist) |
3933 { | |
3934 // If the element at the end of the list doesn't have a doc | |
3935 // string, see whether the first element of TC is an | |
3936 // end-of-line comment for us to use. | |
3937 | |
3938 if (tc) | |
3939 { | |
3940 tree_classdef_property *last_elt = plist->back (); | |
3941 | |
3942 if (! last_elt->have_doc_string ()) | |
3943 { | |
3944 comment_elt first_comment_elt = tc->front (); | |
3945 | |
3946 if (first_comment_elt.is_end_of_line ()) | |
3947 { | |
3948 std::string eol_comment = first_comment_elt.text (); | |
3949 | |
3950 last_elt->doc_string (eol_comment); | |
3951 } | |
3952 } | |
3953 } | |
3954 } | |
3955 else | |
3871 plist = new tree_classdef_property_list (); | 3956 plist = new tree_classdef_property_list (); |
3872 | 3957 |
3873 retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c); | 3958 retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c); |
3874 } | 3959 } |
3875 else | 3960 else |
3876 { | 3961 { |
3877 delete a; | 3962 delete a; |
3878 delete plist; | 3963 delete plist; |
3964 delete lc; | |
3965 delete tc; | |
3879 | 3966 |
3880 end_token_error (end_tok, token::properties_end); | 3967 end_token_error (end_tok, token::properties_end); |
3881 } | 3968 } |
3882 | 3969 |
3883 return retval; | 3970 return retval; |
3884 } | 3971 } |
3972 | |
3973 // LC contains comments appearing before the methods keyword. | |
3974 // If this methods block appears first in the list of classdef | |
3975 // elements, this comment list will be used for the help text for the | |
3976 // classdef block. | |
3885 | 3977 |
3886 tree_classdef_methods_block * | 3978 tree_classdef_methods_block * |
3887 base_parser::make_classdef_methods_block (token *tok_val, | 3979 base_parser::make_classdef_methods_block (token *tok_val, |
3888 tree_classdef_attribute_list *a, | 3980 tree_classdef_attribute_list *a, |
3889 tree_classdef_methods_list *mlist, | 3981 tree_classdef_methods_list *mlist, |
3890 token *end_tok, | 3982 token *end_tok, comment_list *lc, |
3891 comment_list *lc) | 3983 comment_list *tc) |
3892 { | 3984 { |
3893 tree_classdef_methods_block *retval = nullptr; | 3985 tree_classdef_methods_block *retval = nullptr; |
3894 | 3986 |
3895 if (end_token_ok (end_tok, token::methods_end)) | 3987 if (end_token_ok (end_tok, token::methods_end)) |
3896 { | 3988 { |
3897 comment_list *tc = m_lexer.m_comment_buf.get_comment (); | |
3898 | |
3899 int l = tok_val->line (); | 3989 int l = tok_val->line (); |
3900 int c = tok_val->column (); | 3990 int c = tok_val->column (); |
3901 | 3991 |
3902 if (! mlist) | 3992 if (! mlist) |
3903 mlist = new tree_classdef_methods_list (); | 3993 mlist = new tree_classdef_methods_list (); |
3906 } | 3996 } |
3907 else | 3997 else |
3908 { | 3998 { |
3909 delete a; | 3999 delete a; |
3910 delete mlist; | 4000 delete mlist; |
4001 delete lc; | |
4002 delete tc; | |
3911 | 4003 |
3912 end_token_error (end_tok, token::methods_end); | 4004 end_token_error (end_tok, token::methods_end); |
3913 } | 4005 } |
3914 | 4006 |
3915 return retval; | 4007 return retval; |
3916 } | 4008 } |
4009 | |
4010 // LC contains comments appearing before the events keyword. | |
4011 // If this events block appears first in the list of classdef | |
4012 // elements, this comment list will be used for the help text for the | |
4013 // classdef block. | |
4014 | |
4015 // TC contains comments appearing between the list of events and | |
4016 // the final end token for the events block and may be used to find | |
4017 // the doc string for the final event in the list. | |
3917 | 4018 |
3918 tree_classdef_events_block * | 4019 tree_classdef_events_block * |
3919 base_parser::make_classdef_events_block (token *tok_val, | 4020 base_parser::make_classdef_events_block (token *tok_val, |
3920 tree_classdef_attribute_list *a, | 4021 tree_classdef_attribute_list *a, |
3921 tree_classdef_events_list *elist, | 4022 tree_classdef_events_list *elist, |
3922 token *end_tok, | 4023 token *end_tok, |
3923 comment_list *lc) | 4024 comment_list *lc, |
4025 comment_list *tc) | |
3924 { | 4026 { |
3925 tree_classdef_events_block *retval = nullptr; | 4027 tree_classdef_events_block *retval = nullptr; |
3926 | 4028 |
3927 if (end_token_ok (end_tok, token::events_end)) | 4029 if (end_token_ok (end_tok, token::events_end)) |
3928 { | 4030 { |
3929 comment_list *tc = m_lexer.m_comment_buf.get_comment (); | |
3930 | |
3931 int l = tok_val->line (); | 4031 int l = tok_val->line (); |
3932 int c = tok_val->column (); | 4032 int c = tok_val->column (); |
3933 | 4033 |
3934 if (! elist) | 4034 if (! elist) |
3935 elist = new tree_classdef_events_list (); | 4035 elist = new tree_classdef_events_list (); |
3938 } | 4038 } |
3939 else | 4039 else |
3940 { | 4040 { |
3941 delete a; | 4041 delete a; |
3942 delete elist; | 4042 delete elist; |
4043 delete lc; | |
4044 delete tc; | |
3943 | 4045 |
3944 end_token_error (end_tok, token::events_end); | 4046 end_token_error (end_tok, token::events_end); |
3945 } | 4047 } |
3946 | 4048 |
3947 return retval; | 4049 return retval; |
3948 } | 4050 } |
4051 | |
4052 // LC contains comments appearing before the enumeration keyword. | |
4053 // If this enumeration block appears first in the list of classdef | |
4054 // elements, this comment list will be used for the help text for the | |
4055 // classdef block. | |
4056 | |
4057 // TC contains comments appearing between the list of | |
4058 // enumerations and the final end token for the enumeration block and | |
4059 // may be used to find the doc string for the final enumeration in the | |
4060 // list. | |
3949 | 4061 |
3950 tree_classdef_enum_block * | 4062 tree_classdef_enum_block * |
3951 base_parser::make_classdef_enum_block (token *tok_val, | 4063 base_parser::make_classdef_enum_block (token *tok_val, |
3952 tree_classdef_attribute_list *a, | 4064 tree_classdef_attribute_list *a, |
3953 tree_classdef_enum_list *elist, | 4065 tree_classdef_enum_list *elist, |
3954 token *end_tok, | 4066 token *end_tok, |
3955 comment_list *lc) | 4067 comment_list *lc, |
4068 comment_list *tc) | |
3956 { | 4069 { |
3957 tree_classdef_enum_block *retval = nullptr; | 4070 tree_classdef_enum_block *retval = nullptr; |
3958 | 4071 |
3959 if (end_token_ok (end_tok, token::enumeration_end)) | 4072 if (end_token_ok (end_tok, token::enumeration_end)) |
3960 { | 4073 { |
3961 comment_list *tc = m_lexer.m_comment_buf.get_comment (); | |
3962 | |
3963 int l = tok_val->line (); | 4074 int l = tok_val->line (); |
3964 int c = tok_val->column (); | 4075 int c = tok_val->column (); |
3965 | 4076 |
3966 if (! elist) | 4077 if (! elist) |
3967 elist = new tree_classdef_enum_list (); | 4078 elist = new tree_classdef_enum_list (); |
3970 } | 4081 } |
3971 else | 4082 else |
3972 { | 4083 { |
3973 delete a; | 4084 delete a; |
3974 delete elist; | 4085 delete elist; |
4086 delete lc; | |
4087 delete tc; | |
3975 | 4088 |
3976 end_token_error (end_tok, token::enumeration_end); | 4089 end_token_error (end_tok, token::enumeration_end); |
3977 } | 4090 } |
3978 | 4091 |
3979 return retval; | 4092 return retval; |