Mercurial > octave
comparison libinterp/parse-tree/oct-parse.in.yy @ 21369:105224df2330
also disallow assignment to keywords in assignin (bug #46459)
* lex.ll (is_keyword): Don't treat "enumeration", "events", "methods",
or "properties" as keywords.
* oct-parse.in.yy, parse.h: New tests.
(Fassignin): Check for assignments to keywords.
(octave_base_parser::valid_id_for_assignment): Delete.
(octave_base_parser::make_assign_op): Use is_keyword instead of
valid_id_for_assignment.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 26 Feb 2016 20:35:45 -0500 |
parents | 9ca194f7a858 |
children | 74a676d5ce09 |
comparison
equal
deleted
inserted
replaced
21368:e789571034bc | 21369:105224df2330 |
---|---|
3033 // We are looking at a simple assignment statement like x = rhs; | 3033 // We are looking at a simple assignment statement like x = rhs; |
3034 | 3034 |
3035 tree_expression *tmp = lhs->remove_front (); | 3035 tree_expression *tmp = lhs->remove_front (); |
3036 | 3036 |
3037 if ((tmp->is_identifier () || tmp->is_index_expression ()) | 3037 if ((tmp->is_identifier () || tmp->is_index_expression ()) |
3038 && ! valid_id_for_assignment (tmp->name ())) | 3038 && is_keyword (tmp->name ())) |
3039 { | 3039 { |
3040 std::string kw = tmp->name (); | 3040 std::string kw = tmp->name (); |
3041 | 3041 |
3042 delete tmp; | 3042 delete tmp; |
3043 delete lhs; | 3043 delete lhs; |
3059 for (std::list<std::string>::const_iterator it = names.begin (); | 3059 for (std::list<std::string>::const_iterator it = names.begin (); |
3060 it != names.end (); it++) | 3060 it != names.end (); it++) |
3061 { | 3061 { |
3062 std::string kw = *it; | 3062 std::string kw = *it; |
3063 | 3063 |
3064 if (! valid_id_for_assignment (kw)) | 3064 if (is_keyword (kw)) |
3065 { | 3065 { |
3066 delete lhs; | 3066 delete lhs; |
3067 delete rhs; | 3067 delete rhs; |
3068 | 3068 |
3069 bison_error ("invalid assignment to keyword \"" + kw + "\"", l, c); | 3069 bison_error ("invalid assignment to keyword \"" + kw + "\"", l, c); |
4020 } | 4020 } |
4021 | 4021 |
4022 output_buf << "\n"; | 4022 output_buf << "\n"; |
4023 | 4023 |
4024 parse_error_msg = output_buf.str (); | 4024 parse_error_msg = output_buf.str (); |
4025 } | |
4026 | |
4027 bool | |
4028 octave_base_parser::valid_id_for_assignment (const std::string& s) | |
4029 { | |
4030 // is_keyword will return true for some identfiers that are only | |
4031 // keywords in certain contexts. | |
4032 | |
4033 return (! is_keyword (s) | |
4034 || (! lexer.parsing_classdef | |
4035 && (s == "enumeration" || s == "events" | |
4036 || s == "methods" || s == "properties"))); | |
4037 } | 4025 } |
4038 | 4026 |
4039 int | 4027 int |
4040 octave_parser::run (void) | 4028 octave_parser::run (void) |
4041 { | 4029 { |
5129 % bug #35645 | 5117 % bug #35645 |
5130 %!test | 5118 %!test |
5131 %! [a,] = gcd (1,2); | 5119 %! [a,] = gcd (1,2); |
5132 %! [a,b,] = gcd (1, 2); | 5120 %! [a,b,] = gcd (1, 2); |
5133 | 5121 |
5122 %!error eval ("switch = 13;"); | |
5123 | |
5134 */ | 5124 */ |
5135 | 5125 |
5136 DEFUN (assignin, args, , | 5126 DEFUN (assignin, args, , |
5137 "-*- texinfo -*-\n\ | 5127 "-*- texinfo -*-\n\ |
5138 @deftypefn {} {} assignin (@var{context}, @var{varname}, @var{value})\n\ | 5128 @deftypefn {} {} assignin (@var{context}, @var{varname}, @var{value})\n\ |
5160 frame.add_fcn (octave_call_stack::pop); | 5150 frame.add_fcn (octave_call_stack::pop); |
5161 | 5151 |
5162 std::string nm = args(1).xstring_value ("assignin: VARNAME must be a string"); | 5152 std::string nm = args(1).xstring_value ("assignin: VARNAME must be a string"); |
5163 | 5153 |
5164 if (valid_identifier (nm)) | 5154 if (valid_identifier (nm)) |
5165 symbol_table::assign (nm, args(2)); | 5155 { |
5156 // Put the check here so that we don't slow down assignments | |
5157 // generally. Any that go through Octave's parser should have | |
5158 // already been checked. | |
5159 | |
5160 if (is_keyword (nm)) | |
5161 error ("assignin: invalid assignment to keyword '%s'", nm.c_str ()); | |
5162 | |
5163 symbol_table::assign (nm, args(2)); | |
5164 } | |
5166 else | 5165 else |
5167 error ("assignin: invalid variable name in argument VARNAME"); | 5166 error ("assignin: invalid variable name in argument VARNAME"); |
5168 | 5167 |
5169 return retval; | 5168 return retval; |
5170 } | 5169 } |
5170 | |
5171 /* | |
5172 | |
5173 %!error assignin ("base", "switch", "13"); | |
5174 | |
5175 */ | |
5171 | 5176 |
5172 DEFUN (evalin, args, nargout, | 5177 DEFUN (evalin, args, nargout, |
5173 "-*- texinfo -*-\n\ | 5178 "-*- texinfo -*-\n\ |
5174 @deftypefn {} {} evalin (@var{context}, @var{try})\n\ | 5179 @deftypefn {} {} evalin (@var{context}, @var{try})\n\ |
5175 @deftypefnx {} {} evalin (@var{context}, @var{try}, @var{catch})\n\ | 5180 @deftypefnx {} {} evalin (@var{context}, @var{try}, @var{catch})\n\ |
5383 | 5388 |
5384 %!test | 5389 %!test |
5385 %! warning ("off", "quiet", "local"); | 5390 %! warning ("off", "quiet", "local"); |
5386 %! assert (evalc ("error ('foo')", "warning ('bar')"), "warning: bar\n"); | 5391 %! assert (evalc ("error ('foo')", "warning ('bar')"), "warning: bar\n"); |
5387 | 5392 |
5393 %!error evalc ("switch = 13;"); | |
5394 | |
5388 */ | 5395 */ |
5389 | 5396 |
5390 DEFUN (__parser_debug_flag__, args, nargout, | 5397 DEFUN (__parser_debug_flag__, args, nargout, |
5391 "-*- texinfo -*-\n\ | 5398 "-*- texinfo -*-\n\ |
5392 @deftypefn {} {@var{val} =} __parser_debug_flag__ ()\n\ | 5399 @deftypefn {} {@var{val} =} __parser_debug_flag__ ()\n\ |