diff libinterp/parse-tree/lex.ll @ 29864:e2e493712818

improve previous change for command syntax parsing (bug #60882) * symrec.h (symbol_record::variable): New static constant. (symbol_record_rep::is_variable, symbol_record_rep::mark_as_variable, symbol_record_rep::unmark_as_variable): New functions. (symbol_record_rep::mark_formal): Also mark as variable. (symbol_record::is_variable, symbol_record::mark_as_variable, symbol_record::unmark_as_variable): New functions. * symscope.h, symscope.cc (symbol_scope_rep::mark_as_variable, symbol_scope_rep::mark_as_variables, symbol_scope_rep::is_variable, symbol_scope::mark_as_variable, symbol_scope::mark_as_variables, symbol_scope::is_variable): New functions. * lex.h, lex.ll (lexical_feedback::m_pending_local_variables): Delete member variable and all uses. (CMD_OR_COMPUTED_ASSIGN_OP): Don't attempt Matlab compatibility for computed assignment operators. (lexical_feedback::mark_as_variable, lexical_feedback::mark_as_variables, lexical_feedback::is_variable): Store status of symbols as variables in scope objects instead of m_pending_local_variables lists. (base_lexer::handle_identifier): Don't check for variables when deciding whether an identifier can be recognized as a command. * parse.h, oct-parse.yy (parse_exception, parse_tree_validator): New classes. (base_parser::bison_error): New overloads that accept parse_exception and list of parse_exception objects. (base_parser::finish_classdef_file): Validate classdef object and local functions and return status. (base_parser::validate_primary_fcn, base_parser::finish_input): New functions. (file): Validate primary function after parser is finished reading and parsing file. (input): Call base_parser::finish_input to validate and accept statement list. * try.tst: Fix syntax in test.
author John W. Eaton <jwe@octave.org>
date Fri, 09 Jul 2021 04:05:58 -0400
parents 0b01806bb663
children da6e5914ddaf
line wrap: on
line diff
--- a/libinterp/parse-tree/lex.ll	Fri Jul 09 04:03:36 2021 -0400
+++ b/libinterp/parse-tree/lex.ll	Fri Jul 09 04:05:58 2021 -0400
@@ -183,7 +183,19 @@
      }                                                                  \
    while (0)
 
-#define CMD_OR_COMPUTED_ASSIGN_OP(PATTERN, TOK)                         \
+#if 0
+// Use the following to handle computed assignment operators
+// (+=, -=, etc.) in word list commands in a way that is compatible
+// with Matlab.  However, that will also make it impossible to use
+// these operators with a space before them:
+//
+//   x = 1;
+//   x+=2;   ## ok
+//   x+= 2;  ## ok
+//   x +=2;  ## error: invalid use of symbol as both variable and command
+//   x += 2; ## error: invalid use of symbol as both variable and command
+//
+#  define CMD_OR_COMPUTED_ASSIGN_OP(PATTERN, TOK)                       \
    do                                                                   \
      {                                                                  \
        curr_lexer->lexer_debug (PATTERN);                               \
@@ -198,6 +210,10 @@
          return curr_lexer->handle_op (TOK, false, false);              \
      }                                                                  \
    while (0)
+#else
+#  define CMD_OR_COMPUTED_ASSIGN_OP(PATTERN, TOK)                       \
+   return curr_lexer->handle_op (TOK, false, false)
+#endif
 
 #define CMD_OR_UNARY_OP(PATTERN, TOK, COMPAT)                           \
    do                                                                   \
@@ -2221,12 +2237,6 @@
     // The closest paren, brace, or bracket nesting is not an object
     // index.
     m_looking_at_object_index.push_front (false);
-
-    // Provide an initial set to store variables at the top-level.
-    // Don't clear this one when resetting lexical_feedback state.
-    // It should persist since the top-level scope does.  Hmm maybe
-    // we should just use the symbol scope object for this job?
-    m_pending_local_variables.push_front (std::set<std::string> ());
   }
 
   void
@@ -2284,9 +2294,6 @@
     while (! m_parsed_function_name.empty ())
       m_parsed_function_name.pop ();
 
-    while (m_pending_local_variables.size () > 1)
-      m_pending_local_variables.pop_front ();
-
     m_symtab_context.clear ();
     m_nesting_level.reset ();
     m_tokens.clear ();
@@ -2348,6 +2355,24 @@
     return tok ? tok->iskeyword () : false;
   }
 
+  void
+  lexical_feedback::mark_as_variable (const std::string& nm)
+  {
+    symbol_scope scope = m_symtab_context.curr_scope ();
+
+    if (scope)
+      scope.mark_as_variable (nm);
+  }
+
+  void
+  lexical_feedback::mark_as_variables (const std::list<std::string>& lst)
+  {
+    symbol_scope scope = m_symtab_context.curr_scope ();
+
+    if (scope)
+      scope.mark_as_variables (lst);
+  }
+
   bool
   lexical_feedback::previous_token_may_be_command (void) const
   {
@@ -2357,37 +2382,6 @@
     const token *tok = m_tokens.front ();
     return tok ? tok->may_be_command () : false;
   }
-
-  void
-  lexical_feedback::mark_as_variable (const std::string& nm)
-  {
-    auto& vars = m_pending_local_variables.front ();
-    vars.insert (nm);
-  }
-
-  void
-  lexical_feedback::mark_as_variables (const std::list<std::string>& lst)
-  {
-    auto& vars = m_pending_local_variables.front ();
-    for (const auto& nm : lst)
-      vars.insert (nm);
-  }
-
-  bool
-  lexical_feedback::is_variable (const std::string& nm) const
-  {
-    if (m_interpreter.at_top_level () && m_interpreter.is_variable (nm))
-      return true;
-
-    // Search current scope, then parents.
-    for (const auto& vars : m_pending_local_variables)
-      {
-        if (vars.find (nm) != vars.end ())
-          return true;
-      }
-
-    return false;
-  }
 }
 
 static bool
@@ -3599,7 +3593,6 @@
 
     if (m_at_beginning_of_statement
         && ! (m_parsing_anon_fcn_body
-              || is_variable (ident)
               || ident == "e" || ident == "pi"
               || ident == "I" || ident == "i"
               || ident == "J" || ident == "j"