changeset 16360:11115c237231

recognize variables when parsing (bug #38576) * lex.h, lex.ll (lexical_feedback::mark_as_variable, lexical_feedback::maybe_mark_previous_token_as_variable, lexical_feedback::mark_as_variables, octave_lexer::is_variable): New fucntions. ("="): Call maybe_mark_previous_toke_as_variable. (handle_identifier): Don't tag variables as possible commands. (param_list): Mark names in list as variables. (octave_base_parser::validate_matrix_for_assignment): Likewise. * pt-arg-list.h, pt-arg-list.cc (tree_argument_list::variable_names): New function. * pt-misc.h, pt-misc.cc (tree_parameter_list::variable_names): New function. * token.h, token.cc (token::symbol_name, token::is_symbol): New functions. * test/bug-38576.tst: New file. * test/Makefile.am (FCN_FILES): Add bug-38576.tst to the list.
author John W. Eaton <jwe@octave.org>
date Sat, 23 Mar 2013 15:02:29 -0400
parents 253e13e77d12
children e1dcd834751f
files libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/pt-arg-list.cc libinterp/parse-tree/pt-arg-list.h libinterp/parse-tree/pt-misc.cc libinterp/parse-tree/pt-misc.h libinterp/parse-tree/token.cc libinterp/parse-tree/token.h test/Makefile.am test/bug-38576.tst
diffstat 11 files changed, 124 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/lex.h	Sat Mar 23 00:09:25 2013 +0100
+++ b/libinterp/parse-tree/lex.h	Sat Mar 23 15:02:29 2013 -0400
@@ -307,6 +307,11 @@
 
   bool previous_token_may_be_command (void) const;
 
+  void maybe_mark_previous_token_as_variable (void);
+
+  void mark_as_variable (const std::string& nm);
+  void mark_as_variables (const std::list<std::string>& lst);
+
   // true means that we have encountered eof on the input stream.
   bool end_of_input;
 
@@ -518,6 +523,8 @@
 
   bool inside_any_object_index (void);
 
+  bool is_variable (const std::string& name);
+
   int is_keyword_token (const std::string& s);
 
   bool whitespace_is_significant (void);
--- a/libinterp/parse-tree/lex.ll	Sat Mar 23 00:09:25 2013 +0100
+++ b/libinterp/parse-tree/lex.ll	Sat Mar 23 15:02:29 2013 -0400
@@ -1056,7 +1056,12 @@
 // = and op= operators.
 %}
 
-"="    { return curr_lexer->handle_op ("=", '='); }
+"=" {
+    curr_lexer->maybe_mark_previous_token_as_variable ();
+
+    return curr_lexer->handle_op ("=", '=');
+  }
+
 "+="   { return curr_lexer->handle_incompatible_op ("+=", ADD_EQ); }
 "-="   { return curr_lexer->handle_incompatible_op ("-=", SUB_EQ); }
 "*="   { return curr_lexer->handle_incompatible_op ("*=", MUL_EQ); }
@@ -1551,6 +1556,24 @@
   return tok ? tok->may_be_command () : false;
 }
 
+void
+lexical_feedback::maybe_mark_previous_token_as_variable (void)
+{
+  token *tok = tokens.front ();
+  if (tok->is_symbol ())
+    pending_local_variables.insert (tok->symbol_name ());
+}
+
+void
+lexical_feedback::mark_as_variables (const std::list<std::string>& lst)
+{
+  for (std::list<std::string>::const_iterator p = lst.begin ();
+       p != lst.end (); p++)
+    {
+      pending_local_variables.insert (*p);
+    }
+}
+
 static bool
 looks_like_copyright (const std::string& s)
 {
@@ -1784,6 +1807,14 @@
   return retval;
 }
 
+bool
+octave_base_lexer::is_variable (const std::string& name)
+{
+  return (symbol_table::is_variable (name)
+          || (pending_local_variables.find (name)
+              != pending_local_variables.end ()));
+}
+
 // Handle keywords.  Return -1 if the keyword should be ignored.
 
 int
@@ -2551,7 +2582,8 @@
                               input_line_number, current_input_column);
 
   if (at_beginning_of_statement
-      && (! (tok == "e"
+      && (! (is_variable (tok)
+             || tok == "e"
              || tok == "I" || tok == "i"
              || tok == "J" || tok == "j"
              || tok == "Inf" || tok == "inf"
--- a/libinterp/parse-tree/oct-parse.in.yy	Sat Mar 23 00:09:25 2013 +0100
+++ b/libinterp/parse-tree/oct-parse.in.yy	Sat Mar 23 15:02:29 2013 -0400
@@ -1036,7 +1036,12 @@
                 ;
 
 param_list      : param_list_beg param_list1 param_list_end
-                  { $$ = $2; }
+                  {
+                    if ($2)
+                      lexer.mark_as_variables ($2->variable_names ());
+
+                    $$ = $2;
+                  }
                 | param_list_beg error
                   {
                     parser.bison_error ("invalid parameter list");
@@ -1051,7 +1056,10 @@
                   {
                     $1->mark_as_formal_parameters ();
                     if ($1->validate (tree_parameter_list::in))
-                      $$ = $1;
+                      {
+                        lexer.mark_as_variables ($1->variable_names ());
+                        $$ = $1;
+                      }
                     else
                       ABORT_PARSE;
                   }
@@ -2969,7 +2977,10 @@
         tmp = new tree_argument_list (e);
 
       if (tmp && tmp->is_valid_lvalue_list ())
-        retval = tmp;
+        {
+          lexer.mark_as_variables (tmp->variable_names ());
+          retval = tmp;
+        }
       else
         {
           bison_error ("invalid left hand side of assignment");
--- a/libinterp/parse-tree/pt-arg-list.cc	Sat Mar 23 00:09:25 2013 +0100
+++ b/libinterp/parse-tree/pt-arg-list.cc	Sat Mar 23 15:02:29 2013 -0400
@@ -283,6 +283,26 @@
   return retval;
 }
 
+std::list<std::string>
+tree_argument_list::variable_names (void) const
+{
+  std::list<std::string> retval;
+
+  for (const_iterator p = begin (); p != end (); p++)
+    {
+      tree_expression *elt = *p;
+
+      if (elt->is_identifier ())
+        {
+          tree_identifier *id = dynamic_cast<tree_identifier *> (elt);
+      
+          retval.push_back (id->name ());
+        }
+    }
+
+  return retval;
+}
+
 tree_argument_list *
 tree_argument_list::dup (symbol_table::scope_id scope,
                          symbol_table::context_id context) const
--- a/libinterp/parse-tree/pt-arg-list.h	Sat Mar 23 00:09:25 2013 +0100
+++ b/libinterp/parse-tree/pt-arg-list.h	Sat Mar 23 15:02:29 2013 -0400
@@ -85,6 +85,8 @@
 
   string_vector get_arg_names (void) const;
 
+  std::list<std::string> variable_names (void) const;
+
   tree_argument_list *dup (symbol_table::scope_id scope,
                            symbol_table::context_id context) const;
 
--- a/libinterp/parse-tree/pt-misc.cc	Sat Mar 23 00:09:25 2013 +0100
+++ b/libinterp/parse-tree/pt-misc.cc	Sat Mar 23 15:02:29 2013 -0400
@@ -228,6 +228,21 @@
     }
 }
 
+std::list<std::string>
+tree_parameter_list::variable_names (void) const
+{
+  std::list<std::string> retval;
+
+  for (const_iterator p = begin (); p != end (); p++)
+    {
+      tree_decl_elt *elt = *p;
+      
+      retval.push_back (elt->name ());
+    }
+
+  return retval;
+}
+
 octave_value_list
 tree_parameter_list::convert_to_const_vector (int nargout,
                                               const Cell& varargout)
--- a/libinterp/parse-tree/pt-misc.h	Sat Mar 23 00:09:25 2013 +0100
+++ b/libinterp/parse-tree/pt-misc.h	Sat Mar 23 15:02:29 2013 -0400
@@ -78,6 +78,8 @@
 
   bool is_defined (void);
 
+  std::list<std::string> variable_names (void) const;
+
   octave_value_list convert_to_const_vector (int nargout, const Cell& varargout);
 
   tree_parameter_list *dup (symbol_table::scope_id scope,
--- a/libinterp/parse-tree/token.cc	Sat Mar 23 00:09:25 2013 +0100
+++ b/libinterp/parse-tree/token.cc	Sat Mar 23 15:02:29 2013 -0400
@@ -138,6 +138,13 @@
   return *str;
 }
 
+std::string
+token::symbol_name (void) const
+{
+  assert (type_tag == sym_rec_token);
+  return sr->name ();
+}
+
 double
 token::number (void) const
 {
--- a/libinterp/parse-tree/token.h	Sat Mar 23 00:09:25 2013 +0100
+++ b/libinterp/parse-tree/token.h	Sat Mar 23 15:02:29 2013 -0400
@@ -94,7 +94,13 @@
     return type_tag == keyword_token || type_tag == ettype_token;
   }
 
+  bool is_symbol (void) const
+  {
+    return type_tag == sym_rec_token;
+  }
+
   std::string text (void) const;
+  std::string symbol_name (void) const;
   double number (void) const;
   token_type ttype (void) const;
   end_tok_type ettype (void) const;
--- a/test/Makefile.am	Sat Mar 23 00:09:25 2013 +0100
+++ b/test/Makefile.am	Sat Mar 23 15:02:29 2013 -0400
@@ -24,6 +24,7 @@
   fntests.m \
   args.tst \
   bug-31371.tst \
+  bug-38576.tst \
   diag-perm.tst \
   error.tst \
   eval-catch.tst \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-38576.tst	Sat Mar 23 15:02:29 2013 -0400
@@ -0,0 +1,16 @@
+%!function r = f1 ()
+%!  ls = svd (1);
+%!  r = eval ("ls -1;");
+%!endfunction
+%!function r = f2 ()
+%!  [u,ls,v] = svd (1);
+%!  r = eval ("ls -1;");
+%!endfunction
+%!function r = f3 (ls)
+%!  r = eval ("ls -1;");
+%!endfunction
+
+%!assert (f1 (), 0);
+%!assert (f2 (), 0);
+%!assert (ischar (f3 ()), true);
+%!assert (f3 (1), 0);