Mercurial > octave
changeset 33400:b4b98a35906e bytecode-interpreter
maint: merge default to bytecode-interpreter
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 13 Apr 2024 15:02:36 -0400 |
parents | 453132956401 (current diff) 29c07704f120 (diff) |
children | 0978c2874881 |
files | libinterp/parse-tree/module.mk |
diffstat | 5 files changed, 391 insertions(+), 231 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/parse-tree/lex.ll Sat Apr 13 14:31:24 2024 -0400 +++ b/libinterp/parse-tree/lex.ll Sat Apr 13 15:02:36 2024 -0400 @@ -3944,7 +3944,13 @@ { push_token (tok); - return count_token_internal (tok->token_id ()); + int tok_id = tok->token_id (); + + if (m_arguments_is_keyword + && ! (tok_id == ';' || tok_id == ',' || tok_id == '\n')) + m_arguments_is_keyword = false; + + return count_token_internal (tok_id); } int
--- a/libinterp/parse-tree/module.mk Sat Apr 13 14:31:24 2024 -0400 +++ b/libinterp/parse-tree/module.mk Sat Apr 13 15:02:36 2024 -0400 @@ -46,6 +46,7 @@ %reldir%/pt-unop.h \ %reldir%/pt-walk.h \ %reldir%/pt.h \ + %reldir%/separator-list.h \ %reldir%/token.h
--- a/libinterp/parse-tree/oct-parse.yy Sat Apr 13 14:31:24 2024 -0400 +++ b/libinterp/parse-tree/oct-parse.yy Sat Apr 13 15:02:36 2024 -0400 @@ -73,6 +73,7 @@ #include "parse.h" #include "pt-all.h" #include "pt-eval.h" +#include "separator-list.h" #include "symtab.h" #include "token.h" #include "unwind-prot.h" @@ -141,8 +142,10 @@ // The type of the basic tokens returned by the lexer. octave::token *tok; + // Lists of separators with optional comment lists attached. + octave::separator_list *sep_list_type; + // Types for the nonterminals we generate. - char punct_type; octave::tree *tree_type; octave::tree_matrix *tree_matrix_type; octave::tree_cell *tree_cell_type; @@ -243,11 +246,11 @@ // Nonterminals we construct. %type <dummy_type> push_fcn_symtab push_script_symtab begin_file %type <dummy_type> stmt_begin anon_fcn_begin -%type <dummy_type> parsing_local_fcns parse_error at_first_executable_stmt +%type <dummy_type> parsing_local_fcns parse_error %type <tok> param_list_beg param_list_end %type <tok> function_beg classdef_beg arguments_beg indirect_ref_op %type <tok> 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 <sep_list_type> sep_no_nl opt_sep_no_nl sep opt_sep %type <tree_type> input %type <tree_constant_type> string constant magic_colon %type <tree_anon_fcn_handle_type> anon_fcn_handle @@ -283,7 +286,8 @@ %type <tree_decl_command_type> declaration %type <tree_statement_type> statement function_end %type <tree_statement_list_type> simple_list simple_list1 list list1 -%type <tree_statement_list_type> opt_list function_body function_body1 +%type <tree_statement_list_type> statement_list opt_list +%type <tree_statement_list_type> arguments_block_list function_body %type <tree_statement_list_type> opt_fcn_list fcn_list fcn_list1 %type <tree_classdef_attribute_type> attr %type <tree_classdef_attribute_list_type> attr_list attr_list1 @@ -443,7 +447,10 @@ simple_list : opt_sep_no_nl { - OCTAVE_YYUSE ($1); + // FIXME: should we return an empty statement list + // with the separators attached? For now, delete + // the unused list. + delete $1; $$ = nullptr; } @@ -457,6 +464,16 @@ { $$ = parser.append_statement_list ($1, $2, $3, false); } ; +statement_list : opt_sep opt_list + { + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $1; + + $$ = $2; + } + ; + opt_list : // empty { $$ = nullptr; } | list @@ -464,7 +481,13 @@ ; list : list1 opt_sep - { $$ = parser.set_stmt_print_flag ($1, $2, true); } + { + $$ = parser.set_stmt_print_flag ($1, $2, true); + + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; + } ; list1 : statement @@ -481,7 +504,9 @@ fcn_list : fcn_list1 opt_sep { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; $$ = $1; } @@ -586,6 +611,7 @@ { $$ = nullptr; } | ',' { + // FIXME: Need to capture separator token info here. OCTAVE_YYUSE ($1); $$ = nullptr; @@ -594,18 +620,21 @@ { $$ = $1; } | arg_list ',' { + // FIXME: Need to capture separator token info here. OCTAVE_YYUSE ($2); $$ = $1; } | ',' arg_list { + // FIXME: Need to capture separator token info here. OCTAVE_YYUSE ($1); $$ = $2; } | ',' arg_list ',' { + // FIXME: Need to capture separator token info here. OCTAVE_YYUSE ($1, $3); $$ = $2; @@ -1018,30 +1047,18 @@ { $$ = parser.append_if_clause ($1, $2); } ; -if_clause : IF opt_sep expression stmt_begin opt_sep opt_list - { - OCTAVE_YYUSE ($2, $5); - - $$ = parser.make_if_clause ($1, $3, $6); - } +if_clause : IF opt_sep expression stmt_begin statement_list + { $$ = parser.make_if_clause ($1, $2, $3, $5); } ; -elseif_clause : ELSEIF opt_sep expression stmt_begin opt_sep opt_list - { - OCTAVE_YYUSE ($2, $5); - - $$ = parser.make_if_clause ($1, $3, $6); - } +elseif_clause : ELSEIF opt_sep expression stmt_begin statement_list + { $$ = parser.make_if_clause ($1, $2, $3, $5); } ; else_clause : // empty { $$ = nullptr; } - | ELSE opt_sep opt_list - { - OCTAVE_YYUSE ($2); - - $$ = parser.make_if_clause ($1, nullptr, $3); - } + | ELSE statement_list + { $$ = parser.make_if_clause ($1, nullptr, nullptr, $2); } ; // ================ @@ -1050,7 +1067,9 @@ switch_command : SWITCH expression opt_sep case_list END { - OCTAVE_YYUSE ($3); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $3; if (! ($$ = parser.finish_switch_command ($1, $2, $4, $5))) { @@ -1076,81 +1095,76 @@ { $$ = parser.append_switch_case ($1, $2); } ; -switch_case : CASE opt_sep expression stmt_begin opt_sep opt_list +switch_case : CASE opt_sep expression stmt_begin statement_list { - OCTAVE_YYUSE ($2, $5); - - $$ = parser.make_switch_case ($1, $3, $6); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; + + $$ = parser.make_switch_case ($1, $3, $5); } ; -default_case : OTHERWISE opt_sep opt_list - { - OCTAVE_YYUSE ($2); - - $$ = parser.make_default_switch_case ($1, $3); - } +default_case : OTHERWISE statement_list + { $$ = parser.make_default_switch_case ($1, $2); } ; // ======= // Looping // ======= -loop_command : WHILE expression stmt_begin opt_sep opt_list END +loop_command : WHILE expression stmt_begin statement_list END { - OCTAVE_YYUSE ($4); - parser.maybe_convert_to_braindead_shortcircuit ($2); - if (! ($$ = parser.make_while_command ($1, $2, $5, $6))) + if (! ($$ = parser.make_while_command ($1, $2, $4, $5))) { - // make_while_command deleted $2 and $5. + // make_while_command deleted $2 and $4. YYABORT; } } - | DO opt_sep opt_list UNTIL expression + | DO statement_list UNTIL expression { - OCTAVE_YYUSE ($2); - - $$ = parser.make_do_until_command ($1, $3, $4, $5); + $$ = parser.make_do_until_command ($1, $2, $3, $4); } - | FOR assign_lhs '=' expression stmt_begin opt_sep opt_list END + | FOR assign_lhs '=' expression stmt_begin statement_list END { - OCTAVE_YYUSE ($6); - - if (! ($$ = parser.make_for_command ($1, nullptr, $2, $3, $4, nullptr, nullptr, nullptr, $7, $8))) + if (! ($$ = parser.make_for_command ($1, nullptr, $2, $3, $4, nullptr, nullptr, nullptr, $6, $7))) { - // make_for_command deleted $2, $4, and $7. + // make_for_command deleted $2, $4, and $6. YYABORT; } } - | FOR '(' assign_lhs '=' expression ')' opt_sep opt_list END + | FOR '(' assign_lhs '=' expression ')' statement_list END { - OCTAVE_YYUSE ($2, $4, $6, $7); - - if (! ($$ = parser.make_for_command ($1, $2, $3, $4, $5, nullptr, nullptr, $6, $8, $9))) + // FIXME: Need to capture token info here. + OCTAVE_YYUSE ($2, $4, $6); + + if (! ($$ = parser.make_for_command ($1, $2, $3, $4, $5, nullptr, nullptr, $6, $7, $8))) { - // make_for_command deleted $3, $5, and $8. + // make_for_command deleted $3, $5, and $7. YYABORT; } } - | PARFOR assign_lhs '=' expression stmt_begin opt_sep opt_list END + | PARFOR assign_lhs '=' expression stmt_begin statement_list END { - OCTAVE_YYUSE ($3, $6); - - if (! ($$ = parser.make_for_command ($1, nullptr, $2, $3, $4, nullptr, nullptr, nullptr, $7, $8))) + // FIXME: Need to capture token info here. + OCTAVE_YYUSE ($3); + + if (! ($$ = parser.make_for_command ($1, nullptr, $2, $3, $4, nullptr, nullptr, nullptr, $6, $7))) { - // make_for_command deleted $2, $4, and $7. + // make_for_command deleted $2, $4, and $6. YYABORT; } } - | PARFOR '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END + | PARFOR '(' assign_lhs '=' expression ',' expression ')' statement_list END { - OCTAVE_YYUSE ($2, $4, $6, $8, $9); - - if (! ($$ = parser.make_for_command ($1, $2, $3, $4, $5, $6, $7, $8, $10, $11))) + // FIXME: Need to capture token info here. + OCTAVE_YYUSE ($2, $4, $6, $8); + + if (! ($$ = parser.make_for_command ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10))) { - // make_for_command deleted $3, $5, $7, and $10. + // make_for_command deleted $3, $5, $7, and $9. YYABORT; } } @@ -1178,13 +1192,11 @@ // Parallel execution pool // ======================= -spmd_command : SPMD opt_sep opt_list END +spmd_command : SPMD statement_list END { - OCTAVE_YYUSE ($2); - - if (! ($$ = parser.make_spmd_command ($1, $3, $4))) + if (! ($$ = parser.make_spmd_command ($1, $2, $3))) { - // make_spmd_command deleted $3. + // make_spmd_command deleted $2. YYABORT; } } @@ -1194,33 +1206,27 @@ // Exceptions // ========== -except_command : UNWIND opt_sep opt_list CLEANUP opt_sep opt_list END +except_command : UNWIND statement_list CLEANUP statement_list END { - OCTAVE_YYUSE ($2, $5); - - if (! ($$ = parser.make_unwind_command ($1, $3, $4, $6, $7))) + if (! ($$ = parser.make_unwind_command ($1, $2, $3, $4, $5))) { - // make_unwind_command deleted $3 and $6. + // make_unwind_command deleted $2 and $4. YYABORT; } } - | TRY opt_sep opt_list CATCH opt_sep opt_list END + | TRY statement_list CATCH opt_sep opt_list END { - OCTAVE_YYUSE ($2); - - if (! ($$ = parser.make_try_command ($1, $3, $4, $5, $6, $7))) + if (! ($$ = parser.make_try_command ($1, $2, $3, $4, $5, $6))) { - // make_try_command deleted $3 and $6. + // make_try_command deleted $2, $4, and $5. YYABORT; } } - | TRY opt_sep opt_list END + | TRY statement_list END { - OCTAVE_YYUSE ($2); - - if (! ($$ = parser.make_try_command ($1, $3, nullptr, 0, nullptr, $4))) + if (! ($$ = parser.make_try_command ($1, $2, nullptr, nullptr, nullptr, $3))) { - // make_try_command deleted $3. + // make_try_command deleted $2. YYABORT; } } @@ -1400,10 +1406,8 @@ { $$ = 0; } ; -file : begin_file opt_nl opt_list END_OF_INPUT +file : begin_file statement_list END_OF_INPUT { - OCTAVE_YYUSE ($2); - if (lexer.m_reading_fcn_file) { // Delete the dummy statement_list we created @@ -1415,13 +1419,13 @@ // Unused symbol table context. lexer.m_symtab_context.pop (); - delete $3; + delete $2; } else { - octave::tree_statement *end_of_script = parser.make_end ("endscript", true, $4); - - parser.make_script ($3, end_of_script); + octave::tree_statement *end_of_script = parser.make_end ("endscript", true, $3); + + parser.make_script ($2, end_of_script); } if (! parser.validate_primary_fcn ()) @@ -1429,9 +1433,21 @@ $$ = nullptr; } - | begin_file opt_nl classdef parsing_local_fcns opt_sep opt_fcn_list END_OF_INPUT + | begin_file opt_sep classdef parsing_local_fcns opt_sep opt_fcn_list END_OF_INPUT { - OCTAVE_YYUSE ($2, $5); + // We need to skip whitespace before the classdef + // keyword. The opt_sep rule is more liberal than + // we need to be because it accepts ';' and ',' in + // addition to '\n', but we need to use it to avoid + // creating a reduce/reduce conflict with the rule + // above. Matching the extra ';' and ',' characters + // doesn't cause trouble because the lexer ensures + // that classdef is the first token in the file. + + // FIXME: Need to capture separator lists here. + // For now, delete the unused lists. + delete $2; + delete $5; // Unused symbol table context. lexer.m_symtab_context.pop (); @@ -1532,42 +1548,34 @@ } ; -function : function_beg fcn_name opt_param_list opt_sep function_body function_end +function : function_beg fcn_name opt_param_list function_body function_end { - OCTAVE_YYUSE ($4); - - $$ = parser.make_function ($1, nullptr, nullptr, $2, $3, $5, $6); + $$ = parser.make_function ($1, nullptr, nullptr, $2, $3, $4, $5); } - | function_beg return_list '=' fcn_name opt_param_list opt_sep function_body function_end + | function_beg return_list '=' fcn_name opt_param_list function_body function_end { - OCTAVE_YYUSE ($6); - - $$ = parser.make_function ($1, $2, $3, $4, $5, $7, $8); + $$ = parser.make_function ($1, $2, $3, $4, $5, $6, $7); } ; -function_body : at_first_executable_stmt opt_list - { $$ = $2; } - | function_body1 opt_sep at_first_executable_stmt opt_list +function_body : statement_list { - OCTAVE_YYUSE ($2); - - $$ = parser.append_function_body ($1, $4); + $$ = $1; + } + | opt_sep arguments_block_list statement_list + { + $$ = parser.append_function_body ($2, $3); } ; -at_first_executable_stmt - : // empty - { lexer.m_arguments_is_keyword = false; } - ; - -function_body1 : arguments_block +arguments_block_list + : arguments_block { octave::tree_statement *stmt = parser.make_statement ($1); $$ = parser.make_statement_list (stmt); } - | function_body1 opt_sep arguments_block + | arguments_block_list opt_sep arguments_block { octave::tree_statement *stmt = parser.make_statement ($3); @@ -1577,7 +1585,10 @@ arguments_block : arguments_beg opt_sep args_attr_list args_validation_list opt_sep END { - OCTAVE_YYUSE ($2, $5); + // FIXME: Need to capture separator list here. + // For now, delete the unused lists. + delete $2; + delete $5; if (! ($$ = parser.make_arguments_block ($1, $3, $4, $6))) { @@ -1592,6 +1603,7 @@ arguments_beg : ARGUMENTS { $$ = $1; + lexer.m_arguments_is_keyword = false; } ; @@ -1619,7 +1631,9 @@ } | args_validation_list sep arg_name arg_validation { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture SEP here. + // For now, delete the unused list. + delete $2; $4->arg_name ($3); $$ = parser.append_args_validation_list ($1, $4); @@ -1711,7 +1725,9 @@ classdef : classdef_beg attr_list identifier opt_sep superclass_list class_body END { - OCTAVE_YYUSE ($4); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $4; lexer.m_parsing_classdef = false; @@ -1727,7 +1743,9 @@ { $$ = nullptr; } | '(' attr_list1 ')' opt_sep { - OCTAVE_YYUSE ($4); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $4; $$ = $2->mark_in_delims (*($1), *($3)); } @@ -1757,7 +1775,9 @@ } | superclass_list1 opt_sep { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; lexer.m_parsing_classdef_decl = false; lexer.m_parsing_classdef_superclass = false; @@ -1783,7 +1803,9 @@ } | class_body1 opt_sep { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; lexer.m_classdef_element_names_are_keywords = false; $$ = $1; @@ -1800,25 +1822,33 @@ { $$ = parser.make_classdef_body ($1); } | class_body1 opt_sep properties_block { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; $$ = parser.append_classdef_properties_block ($1, $3); } | class_body1 opt_sep methods_block { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; $$ = parser.append_classdef_methods_block ($1, $3); } | class_body1 opt_sep events_block { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; $$ = parser.append_classdef_events_block ($1, $3); } | class_body1 opt_sep enum_block { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; $$ = parser.append_classdef_enum_block ($1, $3); } @@ -1827,7 +1857,9 @@ properties_block : properties_beg opt_sep attr_list property_list END { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; if (! ($$ = parser.make_classdef_properties_block ($1, $3, $4, $5))) { @@ -1851,7 +1883,9 @@ } | property_list1 opt_sep { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; lexer.m_classdef_element_names_are_keywords = true; $$ = $1; @@ -1863,7 +1897,9 @@ { $$ = parser.make_classdef_property_list ($1); } | property_list1 sep class_property { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture SEP here. + // For now, delete the unused list. + delete $2; // We don't look ahead to grab end-of-line comments. // Instead, they are grabbed when we see the @@ -1898,7 +1934,9 @@ methods_block : methods_beg opt_sep attr_list method_list END { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; if (! ($$ = parser.make_classdef_methods_block ($1, $3, $4, $5))) { @@ -1956,7 +1994,9 @@ } | method_list1 opt_sep { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; lexer.m_classdef_element_names_are_keywords = true; $$ = $1; @@ -1967,7 +2007,9 @@ { $$ = parser.make_classdef_method_list ($1); } | method_list1 opt_sep method { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; $$ = parser.append_classdef_method ($1, $3); } @@ -1975,7 +2017,9 @@ events_block : events_beg opt_sep attr_list event_list END { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; if (! ($$ = parser.make_classdef_events_block ($1, $3, $4, $5))) { @@ -1999,7 +2043,9 @@ } | event_list1 opt_sep { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; lexer.m_classdef_element_names_are_keywords = true; $$ = $1; @@ -2010,7 +2056,9 @@ { $$ = parser.make_classdef_event_list ($1); } | event_list1 opt_sep class_event { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; $$ = parser.append_classdef_event ($1, $3); } @@ -2022,7 +2070,9 @@ enum_block : enumeration_beg opt_sep attr_list enum_list END { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; if (! ($$ = parser.make_classdef_enum_block ($1, $3, $4, $5))) { @@ -2046,7 +2096,9 @@ } | enum_list1 opt_sep { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; lexer.m_classdef_element_names_are_keywords = true; $$ = $1; @@ -2057,7 +2109,9 @@ { $$ = parser.make_classdef_enum_list ($1); } | enum_list1 opt_sep class_enum { - OCTAVE_YYUSE ($2); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete $2; $$ = parser.append_classdef_enum ($1, $3); } @@ -2097,97 +2151,37 @@ ; sep_no_nl : ',' - { - OCTAVE_YYUSE ($1); - - $$ = ','; - } + { $$ = new octave::separator_list (*($1)); } | ';' - { - OCTAVE_YYUSE ($1); - - $$ = ';'; - } + { $$ = new octave::separator_list (*($1)); } | sep_no_nl ',' - { - OCTAVE_YYUSE ($2); - - $$ = $1; - } + { $$ = $1->append (*($2)); } | sep_no_nl ';' - { - OCTAVE_YYUSE ($2); - - $$ = $1; - } + { $$ = $1->append (*($2)); } ; opt_sep_no_nl : // empty - { $$ = 0; } + { $$ = nullptr; } | sep_no_nl { $$ = $1; } ; -opt_nl : // empty - { $$ = 0; } - | nl - { $$ = $1; } - ; - -nl : '\n' - { - OCTAVE_YYUSE ($1); - - $$ = '\n'; - } - | nl '\n' - { - OCTAVE_YYUSE ($2); - - $$ = $1; - } - ; - sep : ',' - { - OCTAVE_YYUSE ($1); - - $$ = ','; - } + { $$ = new octave::separator_list (*($1)); } | ';' - { - OCTAVE_YYUSE ($1); - - $$ = ';'; - } + { $$ = new octave::separator_list (*($1)); } | '\n' - { - OCTAVE_YYUSE ($1); - - $$ = '\n'; - } + { $$ = new octave::separator_list (*($1)); } | sep ',' - { - OCTAVE_YYUSE ($2); - - $$ = $1; - } + { $$ = $1->append (*($2)); } | sep ';' - { - OCTAVE_YYUSE ($2); - - $$ = $1; - } + { $$ = $1->append (*($2)); } | sep '\n' - { - OCTAVE_YYUSE ($2); - - $$ = $1; - } + { $$ = $1->append (*($2)); } ; opt_sep : // empty - { $$ = 0; } + { $$ = nullptr; } | sep { $$ = $1; } ; @@ -2334,7 +2328,7 @@ static LIST_T * list_append (LIST_T *list, const token& /*sep_tok*/, ELT_T elt) { - // FIXME XXX! need to capture SEP_TOK here + // FIXME: Need to capture SEP_TOK here list->push_back (elt); return list; } @@ -3089,7 +3083,7 @@ // Build a try-catch command. tree_command * -base_parser::make_try_command (token *try_tok, tree_statement_list *body, token *catch_tok, char catch_sep, tree_statement_list *cleanup_stmts, token *end_tok) +base_parser::make_try_command (token *try_tok, tree_statement_list *body, token *catch_tok, separator_list *catch_sep_list, tree_statement_list *cleanup_stmts, token *end_tok) { tree_command *retval = nullptr; @@ -3097,10 +3091,30 @@ { tree_identifier *id = nullptr; - // Look for exception ID. Could this be done in the grammar or - // does that create another shift-reduce conflict? - - if (! catch_sep && cleanup_stmts && ! cleanup_stmts->empty ()) + // Look for exception ID. Note that adding a separate rule to + // match + // + // try + // try-body + // catch IDENTIFIER + // catch-body + // end + // + // in the grammar leads to yet another shift-reduce conflict, so + // instead we only match + // + // try + // try-body + // catch + // catch-body + // end + // + // and then recognize the first form above by checking that the + // first element of CATCH-BODY is an identifier and that there is + // is no separator (comma, semicolon, or newline) between the + // CATCH token and the identifier. + + if (! catch_sep_list && cleanup_stmts && ! cleanup_stmts->empty ()) { tree_statement *stmt = cleanup_stmts->front (); @@ -3122,11 +3136,16 @@ token tmp_catch_tok = catch_tok ? *catch_tok : token (); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete catch_sep_list; + retval = new tree_try_catch_command (*try_tok, body, tmp_catch_tok, id, cleanup_stmts, *end_tok); } else { delete body; + delete catch_sep_list; delete cleanup_stmts; end_token_error (end_tok, token::try_catch_end); @@ -3324,7 +3343,7 @@ // Build an if, elseif, or else clause. tree_if_clause * -base_parser::make_if_clause (token *tok, tree_expression *expr, tree_statement_list *list) +base_parser::make_if_clause (token *if_tok, separator_list *if_sep_list, tree_expression *expr, tree_statement_list *list) { if (expr) { @@ -3333,7 +3352,11 @@ maybe_convert_to_braindead_shortcircuit (expr); } - return new tree_if_clause (*tok, expr, list); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete if_sep_list; + + return new tree_if_clause (*if_tok, expr, list); } tree_if_command_list * @@ -4594,7 +4617,7 @@ tree_decl_elt * base_parser::make_decl_elt (tree_identifier *id, token */*eq_op*/, tree_expression *expr) { - // FIXME XXX! need to capture EQ_OP here. + // FIXME: Need to capture EQ_OP here. return expr ? new tree_decl_elt (id, expr) : new tree_decl_elt (id); } @@ -4893,17 +4916,17 @@ } tree_statement_list * -base_parser::set_stmt_print_flag (tree_statement_list *list, char sep, bool warn_missing_semi) +base_parser::set_stmt_print_flag (tree_statement_list *list, int sep_char, bool warn_missing_semi) { tree_statement *tmp = list->back (); - switch (sep) + switch (sep_char) { case ';': tmp->set_print_flag (false); break; - case 0: + case '\0': case ',': case '\n': tmp->set_print_flag (true); @@ -4928,6 +4951,20 @@ return list; } +tree_statement_list * +base_parser::set_stmt_print_flag (tree_statement_list *list, const token& sep_tok, bool warn_missing_semi) +{ + return set_stmt_print_flag (list, sep_tok.token_id (), warn_missing_semi); +} + +tree_statement_list * +base_parser::set_stmt_print_flag (tree_statement_list *list, separator_list *sep_list, bool warn_missing_semi) +{ + return (sep_list + ? set_stmt_print_flag (list, sep_list->front (), warn_missing_semi) + : set_stmt_print_flag (list, '\0', warn_missing_semi)); +} + // Finish building a statement. template <typename T> tree_statement * @@ -4943,9 +4980,34 @@ } tree_statement_list * -base_parser::append_statement_list (tree_statement_list *list, char sep, tree_statement *stmt, bool warn_missing_semi) -{ - set_stmt_print_flag (list, sep, warn_missing_semi); +base_parser::append_statement_list (tree_statement_list *list, int sep_char, tree_statement *stmt, bool warn_missing_semi) +{ + set_stmt_print_flag (list, sep_char, warn_missing_semi); + + // FIXME: need to capture SEP_CHAR here. + return list_append (list, stmt); +} + +tree_statement_list * +base_parser::append_statement_list (tree_statement_list *list, token *sep_tok, tree_statement *stmt, bool warn_missing_semi) +{ + if (sep_tok) + set_stmt_print_flag (list, *sep_tok, warn_missing_semi); + else + set_stmt_print_flag (list, '\0', warn_missing_semi); + + // FIXME: need to capture SEP_TOK here. + return list_append (list, stmt); +} + +tree_statement_list * +base_parser::append_statement_list (tree_statement_list *list, separator_list *sep_list, tree_statement *stmt, bool warn_missing_semi) +{ + set_stmt_print_flag (list, sep_list, warn_missing_semi); + + // FIXME: need to capture separator list here. + // For now, delete the unused list. + delete sep_list; return list_append (list, stmt); } @@ -4959,10 +5021,14 @@ } tree_statement_list * -base_parser::append_function_def_list (tree_statement_list *list, char, tree_function_def *fcn_def) +base_parser::append_function_def_list (tree_statement_list *list, separator_list *sep_list, tree_function_def *fcn_def) { tree_statement *stmt = make_statement (fcn_def); + // FIXME: Need to capture separator list here. + // For now, delete the unused list. + delete sep_list; + return list_append (list, stmt); }
--- a/libinterp/parse-tree/parse.h Sat Apr 13 14:31:24 2024 -0400 +++ b/libinterp/parse-tree/parse.h Sat Apr 13 15:02:36 2024 -0400 @@ -49,6 +49,7 @@ OCTAVE_BEGIN_NAMESPACE(octave) class parse_exception; +class separator_list; class tree; class tree_anon_fcn_handle; class tree_arg_size_spec; @@ -288,7 +289,7 @@ // Build a try-catch command. OCTINTERP_API tree_command * - make_try_command (token *try_tok, tree_statement_list *body, token *catch_tok, char catch_sep, tree_statement_list *cleanup, token *end_tok); + make_try_command (token *try_tok, tree_statement_list *body, token *catch_tok, separator_list *catch_sep_list, tree_statement_list *cleanup, token *end_tok); // Build a while command. OCTINTERP_API tree_command * @@ -326,7 +327,7 @@ // Build an elseif clause. OCTINTERP_API tree_if_clause * - make_if_clause (token *if_tok, tree_expression *expr, tree_statement_list *list); + make_if_clause (token *if_tok, separator_list *if_sep_list, tree_expression *expr, tree_statement_list *list); OCTINTERP_API tree_if_command_list * append_if_clause (tree_if_command_list *list, tree_if_clause *clause); @@ -582,7 +583,15 @@ // Set the print flag for a statement based on the separator type. OCTINTERP_API tree_statement_list * - set_stmt_print_flag (tree_statement_list *, char, bool); + set_stmt_print_flag (tree_statement_list *list, int sep_char, bool warn_missing_semi); + + // Set the print flag for a statement based on the separator type. + OCTINTERP_API tree_statement_list * + set_stmt_print_flag (tree_statement_list *list, const token& sep_tok, bool warn_missing_semi); + + // Set the print flag for a statement based on the separator type. + OCTINTERP_API tree_statement_list * + set_stmt_print_flag (tree_statement_list *list, separator_list *sep_list, bool warn_missing_semi); // Finish building a statement. template <typename T> @@ -594,7 +603,15 @@ // Append a statement to an existing statement list. OCTINTERP_API tree_statement_list * - append_statement_list (tree_statement_list *list, char sep, tree_statement *stmt, bool warn_missing_semi); + append_statement_list (tree_statement_list *list, int sep_char, tree_statement *stmt, bool warn_missing_semi); + + // Append a statement to an existing statement list. + OCTINTERP_API tree_statement_list * + append_statement_list (tree_statement_list *list, token *sep_tok, tree_statement *stmt, bool warn_missing_semi); + + // Append a statement to an existing statement list. + OCTINTERP_API tree_statement_list * + append_statement_list (tree_statement_list *list, separator_list *sep_list, tree_statement *stmt, bool warn_missing_semi); // Create a statement list containing only function_def commands. OCTINTERP_API tree_statement_list * @@ -603,7 +620,7 @@ // Append a function_def command to an existing statement list (that // should contain only other function_def commands). OCTINTERP_API tree_statement_list * - append_function_def_list (tree_statement_list *list, char sep, tree_function_def *fcn_def); + append_function_def_list (tree_statement_list *list, separator_list *sep_list, tree_function_def *fcn_def); OCTINTERP_API tree_argument_list * make_argument_list (tree_expression *expr);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/separator-list.h Sat Apr 13 15:02:36 2024 -0400 @@ -0,0 +1,70 @@ +//////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 The Octave Project Developers +// +// See the file COPYRIGHT.md in the top-level directory of this +// distribution or <https://octave.org/copyright/>. +// +// This file is part of Octave. +// +// Octave is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Octave is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Octave; see the file COPYING. If not, see +// <https://www.gnu.org/licenses/>. +// +//////////////////////////////////////////////////////////////////////// + +#if ! defined (octave_separator_list_h) +#define octave_separator_list_h 1 + +#include "octave-config.h" + +#include <list> + +#include "token.h" + +OCTAVE_BEGIN_NAMESPACE(octave) + +class separator_list : public std::list<token> +{ +public: + + separator_list (const token& tok) + { + append (tok); + } + + OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (separator_list) + + separator_list *append (const token& tok) + { + push_back (tok); + + return this; + } + + int first_sep_char () const + { + token tok = front (); + + return tok.token_id (); + } + + separator_list * dup () const + { + return new separator_list (*this); + } +}; + +OCTAVE_END_NAMESPACE(octave) + +#endif