# HG changeset patch
# User Stefan Mahr <dac922@gmx.de>
# Date 1365538312 -7200
# Node ID 3c5fb46ecad2bc259078982a51d43a48ef3ca18e
# Parent  7a71ea0b7ae90cd4a548db92098af32017a6773f
improve try-catch-statement to save exception to a variable

* oct-parse.in.yy, parse.h: extend parser to handle additional expression
* pt-pr-code.cc, pt-except.cc, pt-except.h, pt-check.cc, pt-eval.cc: add handling of expression

diff -r 7a71ea0b7ae9 -r 3c5fb46ecad2 libinterp/parse-tree/oct-parse.in.yy
--- a/libinterp/parse-tree/oct-parse.in.yy	Tue Apr 09 13:47:43 2013 -0400
+++ b/libinterp/parse-tree/oct-parse.in.yy	Tue Apr 09 22:11:52 2013 +0200
@@ -973,12 +973,18 @@
                 | TRY stash_comment opt_sep opt_list CATCH
                   stash_comment opt_sep opt_list END
                   {
-                    if (! ($$ = parser.make_try_command ($1, $4, $8, $9, $2, $6)))
+                    if (! ($$ = parser.make_try_command ($1, $4, $8, 0, $9, $2, $6)))
+                      ABORT_PARSE;
+                  }
+                | TRY stash_comment opt_sep opt_list CATCH assign_lhs
+                  stash_comment opt_sep opt_list END
+                  {
+                    if (! ($$ = parser.make_try_command ($1, $4, $9, $6, $10, $2, $7)))
                       ABORT_PARSE;
                   }
                 | TRY stash_comment opt_sep opt_list END
                   {
-                    if (! ($$ = parser.make_try_command ($1, $4, 0, $5, $2, 0)))
+                    if (! ($$ = parser.make_try_command ($1, $4, 0, 0, $5, $2, 0)))
                       ABORT_PARSE;
                   }
                 ;
@@ -2167,6 +2173,7 @@
 octave_base_parser::make_try_command (token *try_tok,
                                       tree_statement_list *body,
                                       tree_statement_list *cleanup_stmts,
+                                      tree_argument_list *lhs,
                                       token *end_tok,
                                       octave_comment_list *lc,
                                       octave_comment_list *mc)
@@ -2180,8 +2187,25 @@
       int l = try_tok->line ();
       int c = try_tok->column ();
 
-      retval = new tree_try_catch_command (body, cleanup_stmts,
+      tree_expression *tmp = NULL;
+
+      if (lhs)
+        {
+          if (lhs->length () == 1)
+            tmp = lhs->remove_front ();
+          else
+            {
+              bison_error ("invalid syntax for try catch statement");
+              return retval;
+            }
+        }
+
+      retval = new tree_try_catch_command (body, cleanup_stmts, tmp,
                                            lc, mc, tc, l, c);
+
+      if (lhs)
+        delete lhs;
+
     }
 
   return retval;
diff -r 7a71ea0b7ae9 -r 3c5fb46ecad2 libinterp/parse-tree/parse.h
--- a/libinterp/parse-tree/parse.h	Tue Apr 09 13:47:43 2013 -0400
+++ b/libinterp/parse-tree/parse.h	Tue Apr 09 22:11:52 2013 +0200
@@ -201,7 +201,7 @@
   // Build a try-catch command.
   tree_command *
   make_try_command (token *try_tok, tree_statement_list *body,
-                    tree_statement_list *cleanup, token *end_tok,
+                    tree_statement_list *cleanup, tree_argument_list *lhs, token *end_tok,
                     octave_comment_list *lc, octave_comment_list *mc);
 
   // Build a while command.
diff -r 7a71ea0b7ae9 -r 3c5fb46ecad2 libinterp/parse-tree/pt-check.cc
--- a/libinterp/parse-tree/pt-check.cc	Tue Apr 09 13:47:43 2013 -0400
+++ b/libinterp/parse-tree/pt-check.cc	Tue Apr 09 22:11:52 2013 +0200
@@ -499,6 +499,14 @@
 {
   tree_statement_list *try_code = cmd.body ();
 
+  tree_expression *lhs = cmd.left_hand_side ();
+
+  if (lhs)
+    {
+      if (! lhs->lvalue_ok ())
+        gripe ("invalid lvalue in for command", cmd.line ());
+    }
+
   if (try_code)
     try_code->accept (*this);
 
diff -r 7a71ea0b7ae9 -r 3c5fb46ecad2 libinterp/parse-tree/pt-eval.cc
--- a/libinterp/parse-tree/pt-eval.cc	Tue Apr 09 13:47:43 2013 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Tue Apr 09 22:11:52 2013 +0200
@@ -921,6 +921,27 @@
 
           buffer_error_messages--;
 
+          tree_expression *lhs = cmd.left_hand_side ();
+          octave_lvalue ult;
+
+          if (lhs)
+            {
+
+              octave_scalar_map err;
+
+              ult = lhs->lvalue ();
+            
+              if (error_state)
+                return;
+
+              err.assign ("message", last_error_message ());
+              err.assign ("identifier", last_error_id ());
+
+              if (! error_state)
+                ult.assign(octave_value::op_asn_eq, err);
+
+            }
+
           if (catch_code)
             catch_code->accept (*this);
         }
diff -r 7a71ea0b7ae9 -r 3c5fb46ecad2 libinterp/parse-tree/pt-except.cc
--- a/libinterp/parse-tree/pt-except.cc	Tue Apr 09 13:47:43 2013 -0400
+++ b/libinterp/parse-tree/pt-except.cc	Tue Apr 09 22:11:52 2013 +0200
@@ -43,6 +43,7 @@
 
 tree_try_catch_command::~tree_try_catch_command (void)
 {
+  delete lhs;
   delete try_code;
   delete catch_code;
   delete lead_comm;
@@ -57,6 +58,7 @@
   return new
     tree_try_catch_command (try_code ? try_code->dup (scope, context) : 0,
                             catch_code ? catch_code->dup (scope, context) : 0,
+                            lhs ? lhs->dup (scope, context) : 0,
                             lead_comm ? lead_comm->dup () : 0,
                             mid_comm ? mid_comm->dup () : 0,
                             trail_comm ? trail_comm->dup () : 0,
diff -r 7a71ea0b7ae9 -r 3c5fb46ecad2 libinterp/parse-tree/pt-except.h
--- a/libinterp/parse-tree/pt-except.h	Tue Apr 09 13:47:43 2013 -0400
+++ b/libinterp/parse-tree/pt-except.h	Tue Apr 09 22:11:52 2013 +0200
@@ -39,19 +39,22 @@
 public:
 
   tree_try_catch_command (int l = -1, int c = -1)
-    : tree_command (l, c), try_code (0), catch_code (0), lead_comm (0),
+    : tree_command (l, c), try_code (0), catch_code (0), lhs (0), lead_comm (0),
       mid_comm (0), trail_comm (0) { }
 
   tree_try_catch_command (tree_statement_list *tc, tree_statement_list *cc,
+                          tree_expression *le,
                           octave_comment_list *cl = 0,
                           octave_comment_list *cm = 0,
                           octave_comment_list *ct = 0,
                           int l = -1, int c = -1)
-    : tree_command (l, c), try_code (tc), catch_code (cc),
+    : tree_command (l, c), try_code (tc), catch_code (cc), lhs (le),
       lead_comm (cl), mid_comm (cm), trail_comm (ct) { }
 
   ~tree_try_catch_command (void);
 
+  tree_expression *left_hand_side (void) { return lhs; }
+
   tree_statement_list *body (void) { return try_code; }
 
   tree_statement_list *cleanup (void) { return catch_code; }
@@ -75,6 +78,9 @@
   // The code to execute if an error occurs in the first block.
   tree_statement_list *catch_code;
 
+  // Expression to modify.
+  tree_expression *lhs;
+  
   // Comment preceding TRY token.
   octave_comment_list *lead_comm;
 
diff -r 7a71ea0b7ae9 -r 3c5fb46ecad2 libinterp/parse-tree/pt-pr-code.cc
--- a/libinterp/parse-tree/pt-pr-code.cc	Tue Apr 09 13:47:43 2013 -0400
+++ b/libinterp/parse-tree/pt-pr-code.cc	Tue Apr 09 22:11:52 2013 +0200
@@ -994,6 +994,11 @@
 
   tree_statement_list *try_code = cmd.body ();
 
+  tree_expression *lhs = cmd.left_hand_side ();
+
+  if (lhs)
+    lhs->accept (*this);
+
   if (try_code)
     {
       increment_indent_level ();
