comparison libinterp/parse-tree/oct-parse.in.yy @ 23673:1d1ce4df5255

refactor bison rules for parsing functions * parse.h, oct-parse.in.yy: Expect 9 shift/reduce errors. (base_parser::make_function): New function. (function1, function1): Combine non-terminal rules with function rule. (opt_param_list): New non-terminal. (function): Combine rules as much as possible. Move all processing to make_function.
author John W. Eaton <jwe@octave.org>
date Wed, 21 Jun 2017 14:23:47 -0400
parents 2d4a7ae1f6cd
children b9378eff6d13
comparison
equal deleted inserted replaced
23672:3037e865dee1 23673:1d1ce4df5255
109 109
110 %} 110 %}
111 111
112 // Bison declarations. 112 // Bison declarations.
113 113
114 // The grammar currently has 8 shift/reduce conflicts. Ensure that 114 // The grammar currently has 9 shift/reduce conflicts. Ensure that
115 // we notice if that number changes. 115 // we notice if that number changes.
116 116
117 %expect 8 117 %expect 9
118 118
119 %API_PREFIX_DECL% 119 %API_PREFIX_DECL%
120 120
121 // We are using the pure parser interface and the reentrant lexer 121 // We are using the pure parser interface and the reentrant lexer
122 // interface but the Octave parser and lexer are NOT properly 122 // interface but the Octave parser and lexer are NOT properly
246 %type <tree_expression_type> matrix cell 246 %type <tree_expression_type> matrix cell
247 %type <tree_expression_type> primary_expr oper_expr power_expr expr_no_assign 247 %type <tree_expression_type> primary_expr oper_expr power_expr expr_no_assign
248 %type <tree_expression_type> simple_expr colon_expr assign_expr expression 248 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
249 %type <tree_identifier_type> identifier fcn_name magic_tilde 249 %type <tree_identifier_type> identifier fcn_name magic_tilde
250 %type <tree_funcall_type> superclass_identifier meta_identifier 250 %type <tree_funcall_type> superclass_identifier meta_identifier
251 %type <octave_user_function_type> function1 function2
252 %type <tree_index_expression_type> word_list_cmd 251 %type <tree_index_expression_type> word_list_cmd
253 %type <tree_argument_list_type> arg_list word_list assign_lhs 252 %type <tree_argument_list_type> arg_list word_list assign_lhs
254 %type <tree_argument_list_type> cell_or_matrix_row 253 %type <tree_argument_list_type> cell_or_matrix_row
255 %type <tree_parameter_list_type> param_list param_list1 param_list2 254 %type <tree_parameter_list_type> opt_param_list param_list
255 %type <tree_parameter_list_type> param_list1 param_list2
256 %type <tree_parameter_list_type> return_list return_list1 256 %type <tree_parameter_list_type> return_list return_list1
257 %type <tree_command_type> command select_command loop_command 257 %type <tree_command_type> command select_command loop_command
258 %type <tree_command_type> jump_command except_command 258 %type <tree_command_type> jump_command except_command
259 %type <tree_function_def_type> function 259 %type <tree_function_def_type> function
260 %type <tree_classdef_type> classdef 260 %type <tree_classdef_type> classdef
1318 lexer.looking_at_parameter_list = false; 1318 lexer.looking_at_parameter_list = false;
1319 lexer.looking_for_object_index = false; 1319 lexer.looking_for_object_index = false;
1320 } 1320 }
1321 ; 1321 ;
1322 1322
1323 opt_param_list : // empty
1324 { $$ = 0; }
1325 | param_list
1326 { $$ = $1; }
1327 ;
1328
1323 param_list : param_list_beg param_list1 param_list_end 1329 param_list : param_list_beg param_list1 param_list_end
1324 { 1330 {
1325 if ($2) 1331 if ($2)
1326 lexer.mark_as_variables ($2->variable_names ()); 1332 lexer.mark_as_variables ($2->variable_names ());
1327 1333
1482 || lexer.parsing_classdef) 1488 || lexer.parsing_classdef)
1483 lexer.maybe_classdef_get_set_method = true; 1489 lexer.maybe_classdef_get_set_method = true;
1484 } 1490 }
1485 ; 1491 ;
1486 1492
1487 function : function_beg stash_comment function1
1488 {
1489 $$ = parser.finish_function (0, $3, $2, $1->line (),
1490 $1->column ());
1491 parser.recover_from_parsing_function ();
1492 }
1493 | function_beg stash_comment return_list '=' function1
1494 {
1495 YYUSE ($4);
1496
1497 $$ = parser.finish_function ($3, $5, $2, $1->line (),
1498 $1->column ());
1499 parser.recover_from_parsing_function ();
1500 }
1501 ;
1502
1503 fcn_name : identifier 1493 fcn_name : identifier
1504 { 1494 {
1505 std::string id = $1->name (); 1495 std::string id = $1->name ();
1506 1496
1507 if (! parser.function_scopes.name_current_scope (id)) 1497 if (! parser.function_scopes.name_current_scope (id))
1538 1528
1539 lexer.parsed_function_name.top () = true; 1529 lexer.parsed_function_name.top () = true;
1540 lexer.maybe_classdef_get_set_method = false; 1530 lexer.maybe_classdef_get_set_method = false;
1541 lexer.parsing_classdef_set_method = true; 1531 lexer.parsing_classdef_set_method = true;
1542 $$ = $3; 1532 $$ = $3;
1543 }
1544 ;
1545
1546 function1 : fcn_name function2
1547 {
1548 std::string fname = $1->name ();
1549
1550 delete $1;
1551
1552 if (lexer.parsing_classdef_get_method)
1553 fname.insert (0, "get.");
1554 else if (lexer.parsing_classdef_set_method)
1555 fname.insert (0, "set.");
1556
1557 lexer.parsing_classdef_get_method = false;
1558 lexer.parsing_classdef_set_method = false;
1559
1560 $$ = parser.frob_function (fname, $2);
1561 }
1562 ;
1563
1564 function2 : param_list opt_sep opt_list function_end
1565 {
1566 YYUSE ($2);
1567
1568 $$ = parser.start_function ($1, $3, $4);
1569 }
1570 | opt_sep opt_list function_end
1571 {
1572 YYUSE ($1);
1573
1574 $$ = parser.start_function (0, $2, $3);
1575 } 1533 }
1576 ; 1534 ;
1577 1535
1578 function_end : END 1536 function_end : END
1579 { 1537 {
1619 } 1577 }
1620 1578
1621 $$ = parser.make_end ("endfunction", true, 1579 $$ = parser.make_end ("endfunction", true,
1622 lexer.input_line_number, 1580 lexer.input_line_number,
1623 lexer.current_input_column); 1581 lexer.current_input_column);
1582 }
1583 ;
1584
1585 function : function_beg stash_comment fcn_name
1586 opt_param_list opt_sep opt_list function_end
1587 {
1588 YYUSE ($5);
1589
1590 $$ = parser.make_function ($1, 0, $3, $4, $6, $7, $2);
1591 }
1592 | function_beg stash_comment return_list '=' fcn_name
1593 opt_param_list opt_sep opt_list function_end
1594 {
1595 YYUSE ($4);
1596 YYUSE ($7);
1597
1598 $$ = parser.make_function ($1, $3, $5, $6, $8, $9, $2);
1624 } 1599 }
1625 ; 1600 ;
1626 1601
1627 // ======== 1602 // ========
1628 // Classdef 1603 // Classdef
3244 script->stash_fcn_file_time (now); 3219 script->stash_fcn_file_time (now);
3245 3220
3246 primary_fcn_ptr = script; 3221 primary_fcn_ptr = script;
3247 } 3222 }
3248 3223
3224 // Define a function.
3225
3226 // FIXME: combining start_function, finish_function, and
3227 // recover_from_parsing_function should be possible, but it makes
3228 // for a large mess. Maybe this could be a bit better organized?
3229
3230 tree_function_def *
3231 base_parser::make_function (token *fcn_tok,
3232 tree_parameter_list *ret_list,
3233 tree_identifier *id,
3234 tree_parameter_list *param_list,
3235 tree_statement_list *body,
3236 tree_statement *end_fcn_stmt,
3237 octave_comment_list *lc)
3238 {
3239 tree_function_def *retval = 0;
3240
3241 int l = fcn_tok->line ();
3242 int c = fcn_tok->column ();
3243
3244 octave_user_function *tmp_fcn
3245 = start_function (id, param_list, body, end_fcn_stmt);
3246
3247 retval = finish_function (ret_list, tmp_fcn, lc, l, c);
3248
3249 recover_from_parsing_function ();
3250
3251 return retval;
3252 }
3253
3249 // Begin defining a function. 3254 // Begin defining a function.
3250 3255
3251 octave_user_function * 3256 octave_user_function *
3252 base_parser::start_function (tree_parameter_list *param_list, 3257 base_parser::start_function (tree_identifier *id,
3258 tree_parameter_list *param_list,
3253 tree_statement_list *body, 3259 tree_statement_list *body,
3254 tree_statement *end_fcn_stmt) 3260 tree_statement *end_fcn_stmt)
3255 { 3261 {
3256 // We'll fill in the return list later. 3262 // We'll fill in the return list later.
3263
3264 std::string id_name = id->name ();
3265
3266 delete id;
3267
3268 if (lexer.parsing_classdef_get_method)
3269 id_name.insert (0, "get.");
3270 else if (lexer.parsing_classdef_set_method)
3271 id_name.insert (0, "set.");
3272
3273 lexer.parsing_classdef_get_method = false;
3274 lexer.parsing_classdef_set_method = false;
3257 3275
3258 if (! body) 3276 if (! body)
3259 body = new tree_statement_list (); 3277 body = new tree_statement_list ();
3260 3278
3261 body->append (end_fcn_stmt); 3279 body->append (end_fcn_stmt);
3270 3288
3271 fcn->stash_trailing_comment (tc); 3289 fcn->stash_trailing_comment (tc);
3272 fcn->stash_fcn_end_location (end_fcn_stmt->line (), 3290 fcn->stash_fcn_end_location (end_fcn_stmt->line (),
3273 end_fcn_stmt->column ()); 3291 end_fcn_stmt->column ());
3274 } 3292 }
3275
3276 return fcn;
3277 }
3278
3279 tree_statement *
3280 base_parser::make_end (const std::string& type, bool eof, int l, int c)
3281 {
3282 return make_statement (new tree_no_op_command (type, eof, l, c));
3283 }
3284
3285 // Do most of the work for defining a function.
3286
3287 octave_user_function *
3288 base_parser::frob_function (const std::string& fname,
3289 octave_user_function *fcn)
3290 {
3291 std::string id_name = fname;
3292 3293
3293 // If input is coming from a file, issue a warning if the name of 3294 // If input is coming from a file, issue a warning if the name of
3294 // the file does not match the name of the function stated in the 3295 // the file does not match the name of the function stated in the
3295 // file. Matlab doesn't provide a diagnostic (it ignores the stated 3296 // file. Matlab doesn't provide a diagnostic (it ignores the stated
3296 // name). 3297 // name).
3382 if (lexer.reading_fcn_file && curr_fcn_depth == 1 3383 if (lexer.reading_fcn_file && curr_fcn_depth == 1
3383 && ! parsing_subfunctions) 3384 && ! parsing_subfunctions)
3384 primary_fcn_ptr = fcn; 3385 primary_fcn_ptr = fcn;
3385 3386
3386 return fcn; 3387 return fcn;
3388 }
3389
3390 tree_statement *
3391 base_parser::make_end (const std::string& type, bool eof, int l, int c)
3392 {
3393 return make_statement (new tree_no_op_command (type, eof, l, c));
3387 } 3394 }
3388 3395
3389 tree_function_def * 3396 tree_function_def *
3390 base_parser::finish_function (tree_parameter_list *ret_list, 3397 base_parser::finish_function (tree_parameter_list *ret_list,
3391 octave_user_function *fcn, 3398 octave_user_function *fcn,