# HG changeset patch # User John W. Eaton # Date 1368908492 14400 # Node ID d3619d4d267cfe733bec1e2b4496af490557ff58 # Parent de79cdbbdf7ca417865b256a1d98af19236f8951 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. diff --git a/libinterp/parse-tree/lex.ll b/libinterp/parse-tree/lex.ll --- a/libinterp/parse-tree/lex.ll +++ b/libinterp/parse-tree/lex.ll @@ -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 (); diff --git a/libinterp/parse-tree/oct-parse.in.yy b/libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy +++ b/libinterp/parse-tree/oct-parse.in.yy @@ -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 (); } ; diff --git a/libinterp/parse-tree/pt-fcn-handle.cc b/libinterp/parse-tree/pt-fcn-handle.cc --- a/libinterp/parse-tree/pt-fcn-handle.cc +++ b/libinterp/parse-tree/pt-fcn-handle.cc @@ -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 diff --git a/test/for.tst b/test/for.tst --- a/test/for.tst +++ b/test/for.tst @@ -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); diff --git a/test/if.tst b/test/if.tst --- a/test/if.tst +++ b/test/if.tst @@ -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); diff --git a/test/switch.tst b/test/switch.tst --- a/test/switch.tst +++ b/test/switch.tst @@ -93,3 +93,12 @@ %% test/octave.test/switch/switch-6.m %!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); diff --git a/test/while.tst b/test/while.tst --- a/test/while.tst +++ b/test/while.tst @@ -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);