changeset 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 3037e865dee1
children 81b141d265a3
files libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/parse.h
diffstat 2 files changed, 87 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/oct-parse.in.yy	Wed Jun 21 11:46:31 2017 -0400
+++ b/libinterp/parse-tree/oct-parse.in.yy	Wed Jun 21 14:23:47 2017 -0400
@@ -111,10 +111,10 @@
 
 // Bison declarations.
 
-// The grammar currently has 8 shift/reduce conflicts.  Ensure that
+// The grammar currently has 9 shift/reduce conflicts.  Ensure that
 // we notice if that number changes.
 
-%expect 8
+%expect 9
 
 %API_PREFIX_DECL%
 
@@ -248,11 +248,11 @@
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
 %type <tree_identifier_type> identifier fcn_name magic_tilde
 %type <tree_funcall_type> superclass_identifier meta_identifier
-%type <octave_user_function_type> function1 function2
 %type <tree_index_expression_type> word_list_cmd
 %type <tree_argument_list_type> arg_list word_list assign_lhs
 %type <tree_argument_list_type> cell_or_matrix_row
-%type <tree_parameter_list_type> param_list param_list1 param_list2
+%type <tree_parameter_list_type> opt_param_list param_list
+%type <tree_parameter_list_type> param_list1 param_list2
 %type <tree_parameter_list_type> return_list return_list1
 %type <tree_command_type> command select_command loop_command
 %type <tree_command_type> jump_command except_command
@@ -1320,6 +1320,12 @@
                   }
                 ;
 
+opt_param_list  : // empty
+                  { $$ = 0; }
+                | param_list
+                  { $$ = $1; }
+                ;
+
 param_list      : param_list_beg param_list1 param_list_end
                   {
                     if ($2)
@@ -1484,22 +1490,6 @@
                   }
                 ;
 
-function        : function_beg stash_comment function1
-                  {
-                    $$ = parser.finish_function (0, $3, $2, $1->line (),
-                                                 $1->column ());
-                    parser.recover_from_parsing_function ();
-                  }
-                | function_beg stash_comment return_list '=' function1
-                  {
-                    YYUSE ($4);
-
-                    $$ = parser.finish_function ($3, $5, $2, $1->line (),
-                                                 $1->column ());
-                    parser.recover_from_parsing_function ();
-                  }
-                ;
-
 fcn_name        : identifier
                   {
                     std::string id = $1->name ();
@@ -1543,38 +1533,6 @@
                   }
                 ;
 
-function1       : fcn_name function2
-                  {
-                    std::string fname = $1->name ();
-
-                    delete $1;
-
-                    if (lexer.parsing_classdef_get_method)
-                      fname.insert (0, "get.");
-                    else if (lexer.parsing_classdef_set_method)
-                      fname.insert (0, "set.");
-
-                    lexer.parsing_classdef_get_method = false;
-                    lexer.parsing_classdef_set_method = false;
-
-                    $$ = parser.frob_function (fname, $2);
-                  }
-                ;
-
-function2       : param_list opt_sep opt_list function_end
-                  {
-                    YYUSE ($2);
-
-                    $$ = parser.start_function ($1, $3, $4);
-                  }
-                | opt_sep opt_list function_end
-                  {
-                    YYUSE ($1);
-
-                    $$ = parser.start_function (0, $2, $3);
-                  }
-                ;
-
 function_end    : END
                   {
                     parser.endfunction_found = true;
@@ -1624,6 +1582,23 @@
                   }
                 ;
 
+function        : function_beg stash_comment fcn_name
+                  opt_param_list opt_sep opt_list function_end
+                  {
+                    YYUSE ($5);
+
+                    $$ = parser.make_function ($1, 0, $3, $4, $6, $7, $2);
+                  }
+                | function_beg stash_comment return_list '=' fcn_name
+                  opt_param_list opt_sep opt_list function_end
+                  {
+                    YYUSE ($4);
+                    YYUSE ($7);
+
+                    $$ = parser.make_function ($1, $3, $5, $6, $8, $9, $2);
+                  }
+                ;
+
 // ========
 // Classdef
 // ========
@@ -3246,15 +3221,58 @@
     primary_fcn_ptr = script;
   }
 
+  // Define a function.
+
+  // FIXME: combining start_function, finish_function, and
+  // recover_from_parsing_function should be possible, but it makes
+  // for a large mess.  Maybe this could be a bit better organized?
+
+  tree_function_def *
+  base_parser::make_function (token *fcn_tok,
+                              tree_parameter_list *ret_list,
+                              tree_identifier *id,
+                              tree_parameter_list *param_list,
+                              tree_statement_list *body,
+                              tree_statement *end_fcn_stmt,
+                              octave_comment_list *lc)
+  {
+    tree_function_def *retval = 0;
+
+    int l = fcn_tok->line ();
+    int c = fcn_tok->column ();
+
+    octave_user_function *tmp_fcn
+      = start_function (id, param_list, body, end_fcn_stmt);
+
+    retval = finish_function (ret_list, tmp_fcn, lc, l, c);
+
+    recover_from_parsing_function ();
+
+    return retval;
+  }
+
   // Begin defining a function.
 
   octave_user_function *
-  base_parser::start_function (tree_parameter_list *param_list,
+  base_parser::start_function (tree_identifier *id,
+                               tree_parameter_list *param_list,
                                tree_statement_list *body,
                                tree_statement *end_fcn_stmt)
   {
     // We'll fill in the return list later.
 
+    std::string id_name = id->name ();
+
+    delete id;
+
+    if (lexer.parsing_classdef_get_method)
+      id_name.insert (0, "get.");
+    else if (lexer.parsing_classdef_set_method)
+      id_name.insert (0, "set.");
+
+    lexer.parsing_classdef_get_method = false;
+    lexer.parsing_classdef_set_method = false;
+
     if (! body)
       body = new tree_statement_list ();
 
@@ -3273,23 +3291,6 @@
                                      end_fcn_stmt->column ());
       }
 
-    return fcn;
-  }
-
-  tree_statement *
-  base_parser::make_end (const std::string& type, bool eof, int l, int c)
-  {
-    return make_statement (new tree_no_op_command (type, eof, l, c));
-  }
-
-  // Do most of the work for defining a function.
-
-  octave_user_function *
-  base_parser::frob_function (const std::string& fname,
-                              octave_user_function *fcn)
-  {
-    std::string id_name = fname;
-
     // If input is coming from a file, issue a warning if the name of
     // the file does not match the name of the function stated in the
     // file.  Matlab doesn't provide a diagnostic (it ignores the stated
@@ -3386,6 +3387,12 @@
     return fcn;
   }
 
+  tree_statement *
+  base_parser::make_end (const std::string& type, bool eof, int l, int c)
+  {
+    return make_statement (new tree_no_op_command (type, eof, l, c));
+  }
+
   tree_function_def *
   base_parser::finish_function (tree_parameter_list *ret_list,
                                 octave_user_function *fcn,
--- a/libinterp/parse-tree/parse.h	Wed Jun 21 11:46:31 2017 -0400
+++ b/libinterp/parse-tree/parse.h	Wed Jun 21 14:23:47 2017 -0400
@@ -276,17 +276,24 @@
     // Define a script.
     void make_script (tree_statement_list *cmds, tree_statement *end_script);
 
+    // Define a function.
+    tree_function_def *
+    make_function (token *fcn_tok, tree_parameter_list *ret_list,
+                   tree_identifier *id, tree_parameter_list *param_list,
+                   tree_statement_list *body, tree_statement *end_fcn_stmt,
+                   octave_comment_list *lc);
+
     // Begin defining a function.
     octave_user_function *
-    start_function (tree_parameter_list *param_list, tree_statement_list *body,
-                    tree_statement *end_function);
+    start_function (tree_identifier *id, tree_parameter_list *param_list,
+                    tree_statement_list *body, tree_statement *end_function);
 
     // Create a no-op statement for end_function.
     tree_statement * make_end (const std::string& type, bool eof, int l, int c);
 
     // Do most of the work for defining a function.
     octave_user_function *
-    frob_function (const std::string& fname, octave_user_function *fcn);
+    frob_function (tree_identifier *id, octave_user_function *fcn);
 
     // Finish defining a function.
     tree_function_def *