changeset 16681:d3619d4d267c

recognize character string at beginning of statement (bug #38926, #38958) * lex.ll ("'"): Always begin a character string if at the beginning of a statement. * oct-parse.in.yy (stmt_begin): New non-terminal. (anon_fcn_handle, if_cmd_list1, elseif_clause, switch_case, loop_command): Use it. * pt-fcn-handle.cc, for.tst, if.tst, switch.tst, while.tst: New tests.
author John W. Eaton <jwe@octave.org>
date Sat, 18 May 2013 16:21:32 -0400
parents de79cdbbdf7c
children e1c6ad54259f 5c5c46a81ad5
files libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/pt-fcn-handle.cc test/for.tst test/if.tst test/switch.tst test/while.tst
diffstat 7 files changed, 81 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/lex.ll	Sat May 18 14:34:25 2013 -0400
+++ b/libinterp/parse-tree/lex.ll	Sat May 18 16:21:32 2013 -0400
@@ -863,6 +863,12 @@
         yyless (0);
         curr_lexer->push_start_state (COMMAND_START);
       }
+    else if (curr_lexer->at_beginning_of_statement)
+      {
+        curr_lexer->current_input_column++;
+        int retval = curr_lexer->handle_string ('\'');
+        return curr_lexer->count_token_internal (retval);
+      }
     else
       {
         int tok = curr_lexer->previous_token_value ();
--- a/libinterp/parse-tree/oct-parse.in.yy	Sat May 18 14:34:25 2013 -0400
+++ b/libinterp/parse-tree/oct-parse.in.yy	Sat May 18 16:21:32 2013 -0400
@@ -488,9 +488,9 @@
                   }
                 ;
 
-anon_fcn_handle : '@' param_list statement
+anon_fcn_handle : '@' param_list stmt_begin statement
                   {
-                    $$ = parser.make_anon_fcn_handle ($2, $3);
+                    $$ = parser.make_anon_fcn_handle ($2, $4);
                     lexer.nesting_level.remove ();
                   }
                 ;
@@ -831,11 +831,11 @@
                   }
                 ;
 
-if_cmd_list1    : expression opt_sep opt_list
+if_cmd_list1    : expression stmt_begin opt_sep opt_list
                   {
                     $1->mark_braindead_shortcircuit (lexer.fcn_file_full_name);
 
-                    $$ = parser.start_if_command ($1, $3);
+                    $$ = parser.start_if_command ($1, $4);
                   }
                 | if_cmd_list1 elseif_clause
                   {
@@ -844,11 +844,11 @@
                   }
                 ;
 
-elseif_clause   : ELSEIF stash_comment opt_sep expression opt_sep opt_list
+elseif_clause   : ELSEIF stash_comment opt_sep expression stmt_begin opt_sep opt_list
                   {
                     $4->mark_braindead_shortcircuit (lexer.fcn_file_full_name);
 
-                    $$ = parser.make_elseif_clause ($1, $4, $6, $2);
+                    $$ = parser.make_elseif_clause ($1, $4, $7, $2);
                   }
                 ;
 
@@ -889,8 +889,8 @@
                   }
                 ;
 
-switch_case     : CASE stash_comment opt_sep expression opt_sep opt_list
-                  { $$ = parser.make_switch_case ($1, $4, $6, $2); }
+switch_case     : CASE stash_comment opt_sep expression stmt_begin opt_sep opt_list
+                  { $$ = parser.make_switch_case ($1, $4, $7, $2); }
                 ;
 
 default_case    : OTHERWISE stash_comment opt_sep opt_list
@@ -903,11 +903,11 @@
 // Looping
 // =======
 
-loop_command    : WHILE stash_comment expression opt_sep opt_list END
+loop_command    : WHILE stash_comment expression stmt_begin opt_sep opt_list END
                   {
                     $3->mark_braindead_shortcircuit (lexer.fcn_file_full_name);
 
-                    if (! ($$ = parser.make_while_command ($1, $3, $5, $6, $2)))
+                    if (! ($$ = parser.make_while_command ($1, $3, $6, $7, $2)))
                       ABORT_PARSE;
                   }
                 | DO stash_comment opt_sep opt_list UNTIL expression
@@ -915,10 +915,10 @@
                     if (! ($$ = parser.make_do_until_command ($5, $4, $6, $2)))
                       ABORT_PARSE;
                   }
-                | FOR stash_comment assign_lhs '=' expression opt_sep opt_list END
+                | FOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
                   {
                     if (! ($$ = parser.make_for_command (FOR, $1, $3, $5, 0,
-                                                  $7, $8, $2)))
+                                                  $8, $9, $2)))
                       ABORT_PARSE;
                   }
                 | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END
@@ -927,10 +927,10 @@
                                                   $9, $10, $2)))
                       ABORT_PARSE;
                   }
-                | PARFOR stash_comment assign_lhs '=' expression opt_sep opt_list END
+                | PARFOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
                   {
                     if (! ($$ = parser.make_for_command (PARFOR, $1, $3, $5,
-                                                  0, $7, $8, $2)))
+                                                  0, $8, $9, $2)))
                       ABORT_PARSE;
                   }
                 | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END
@@ -1406,6 +1406,10 @@
 // Miscellaneous
 // =============
 
+stmt_begin      : // empty
+                  { lexer.at_beginning_of_statement = true; }
+                ;
+
 stash_comment   : // empty
                   { $$ = octave_comment_buffer::get_comment (); }
                 ;
--- a/libinterp/parse-tree/pt-fcn-handle.cc	Sat May 18 14:34:25 2013 -0400
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Sat May 18 16:21:32 2013 -0400
@@ -159,6 +159,19 @@
 %! g = @(f, x) h (x);
 %! f = @() g (@(x) h, pi);
 %! assert (f () == sin (pi));
+
+The next two tests are intended to test parsing of a character string
+vs. hermitian operator at the beginning of an anonymous function
+expression.  The use of ' for the character string and the spacing is
+intentional, so don't change it.
+
+%!test
+%! f = @() 'foo';
+%! assert (f (), 'foo');
+
+%!test
+%! f = @()'foo';
+%! assert (f (), 'foo');
 */
 
 octave_value_list
--- a/test/for.tst	Sat May 18 14:34:25 2013 -0400
+++ b/test/for.tst	Sat May 18 16:21:32 2013 -0400
@@ -109,3 +109,11 @@
 %! for i = cat (3, a, cellfun (@(x) 4 + x, a, "UniformOutput", 0))
 %!   assert (i, {1 + 2*j; 2 + 2*j++})
 %! endfor
+
+%% test parsing of single-quoted character string appearing at the
+%% beginning of a for loop
+%!test
+%! for i = 1:5
+%!   'foo';
+%! endfor
+%! assert (i, 5);
--- a/test/if.tst	Sat May 18 14:34:25 2013 -0400
+++ b/test/if.tst	Sat May 18 16:21:32 2013 -0400
@@ -85,3 +85,22 @@
 %! end
 %! assert (__prog_output_assert__ ("pass"));
 
+%% test parsing of single-quoted character string appearing at the
+%% beginning of an if condition
+%!test
+%! if (1)
+%!   'foo';
+%!   x = 13;
+%! endif
+%! assert (x, 13);
+
+%% test parsing of single-quoted character string appearing at the
+%% beginning of an if condition
+%!test
+%! if (0)
+%!   x = 42;
+%! elseif (1)
+%!   'foo';
+%!   x = 13;
+%! endif
+%! assert (x, 13);
--- a/test/switch.tst	Sat May 18 14:34:25 2013 -0400
+++ b/test/switch.tst	Sat May 18 16:21:32 2013 -0400
@@ -93,3 +93,12 @@
 %% test/octave.test/switch/switch-6.m
 %!error <syntax error> eval ("switch 1 default 1; endswitch")
 
+%% test parsing of single-quoted character string appearing immediately
+%% after a switch case
+%!test
+%! switch (1)
+%!   case 1
+%!     'foo';
+%!     x = 13;
+%! endswitch
+%! assert (x, 13);
--- a/test/while.tst	Sat May 18 14:34:25 2013 -0400
+++ b/test/while.tst	Sat May 18 16:21:32 2013 -0400
@@ -68,3 +68,11 @@
 %! __printf_assert__ ("\n");
 %! assert (__prog_output_assert__ ("34"));
 
+%% test parsing of single-quoted character string appearing immediately
+%% after a while condition.
+%!test
+%! i = 0;
+%! while (++i < 5)
+%!   'foo';
+%! endwhile
+%! assert (i, 5);