Mercurial > octave
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, |