Mercurial > hg > octave-nkf
changeset 16360:11115c237231
recognize variables when parsing (bug #38576)
* lex.h, lex.ll (lexical_feedback::mark_as_variable,
lexical_feedback::maybe_mark_previous_token_as_variable,
lexical_feedback::mark_as_variables, octave_lexer::is_variable):
New fucntions.
("="): Call maybe_mark_previous_toke_as_variable.
(handle_identifier): Don't tag variables as possible commands.
(param_list): Mark names in list as variables.
(octave_base_parser::validate_matrix_for_assignment): Likewise.
* pt-arg-list.h, pt-arg-list.cc (tree_argument_list::variable_names):
New function.
* pt-misc.h, pt-misc.cc (tree_parameter_list::variable_names):
New function.
* token.h, token.cc (token::symbol_name, token::is_symbol):
New functions.
* test/bug-38576.tst: New file.
* test/Makefile.am (FCN_FILES): Add bug-38576.tst to the list.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 23 Mar 2013 15:02:29 -0400 |
parents | 253e13e77d12 |
children | e1dcd834751f |
files | libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/pt-arg-list.cc libinterp/parse-tree/pt-arg-list.h libinterp/parse-tree/pt-misc.cc libinterp/parse-tree/pt-misc.h libinterp/parse-tree/token.cc libinterp/parse-tree/token.h test/Makefile.am test/bug-38576.tst |
diffstat | 11 files changed, 124 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/parse-tree/lex.h +++ b/libinterp/parse-tree/lex.h @@ -307,6 +307,11 @@ bool previous_token_may_be_command (void) const; + void maybe_mark_previous_token_as_variable (void); + + void mark_as_variable (const std::string& nm); + void mark_as_variables (const std::list<std::string>& lst); + // true means that we have encountered eof on the input stream. bool end_of_input; @@ -518,6 +523,8 @@ bool inside_any_object_index (void); + bool is_variable (const std::string& name); + int is_keyword_token (const std::string& s); bool whitespace_is_significant (void);
--- a/libinterp/parse-tree/lex.ll +++ b/libinterp/parse-tree/lex.ll @@ -1056,7 +1056,12 @@ // = and op= operators. %} -"=" { return curr_lexer->handle_op ("=", '='); } +"=" { + curr_lexer->maybe_mark_previous_token_as_variable (); + + return curr_lexer->handle_op ("=", '='); + } + "+=" { return curr_lexer->handle_incompatible_op ("+=", ADD_EQ); } "-=" { return curr_lexer->handle_incompatible_op ("-=", SUB_EQ); } "*=" { return curr_lexer->handle_incompatible_op ("*=", MUL_EQ); } @@ -1551,6 +1556,24 @@ return tok ? tok->may_be_command () : false; } +void +lexical_feedback::maybe_mark_previous_token_as_variable (void) +{ + token *tok = tokens.front (); + if (tok->is_symbol ()) + pending_local_variables.insert (tok->symbol_name ()); +} + +void +lexical_feedback::mark_as_variables (const std::list<std::string>& lst) +{ + for (std::list<std::string>::const_iterator p = lst.begin (); + p != lst.end (); p++) + { + pending_local_variables.insert (*p); + } +} + static bool looks_like_copyright (const std::string& s) { @@ -1784,6 +1807,14 @@ return retval; } +bool +octave_base_lexer::is_variable (const std::string& name) +{ + return (symbol_table::is_variable (name) + || (pending_local_variables.find (name) + != pending_local_variables.end ())); +} + // Handle keywords. Return -1 if the keyword should be ignored. int @@ -2551,7 +2582,8 @@ input_line_number, current_input_column); if (at_beginning_of_statement - && (! (tok == "e" + && (! (is_variable (tok) + || tok == "e" || tok == "I" || tok == "i" || tok == "J" || tok == "j" || tok == "Inf" || tok == "inf"
--- a/libinterp/parse-tree/oct-parse.in.yy +++ b/libinterp/parse-tree/oct-parse.in.yy @@ -1036,7 +1036,12 @@ ; param_list : param_list_beg param_list1 param_list_end - { $$ = $2; } + { + if ($2) + lexer.mark_as_variables ($2->variable_names ()); + + $$ = $2; + } | param_list_beg error { parser.bison_error ("invalid parameter list"); @@ -1051,7 +1056,10 @@ { $1->mark_as_formal_parameters (); if ($1->validate (tree_parameter_list::in)) - $$ = $1; + { + lexer.mark_as_variables ($1->variable_names ()); + $$ = $1; + } else ABORT_PARSE; } @@ -2969,7 +2977,10 @@ tmp = new tree_argument_list (e); if (tmp && tmp->is_valid_lvalue_list ()) - retval = tmp; + { + lexer.mark_as_variables (tmp->variable_names ()); + retval = tmp; + } else { bison_error ("invalid left hand side of assignment");
--- a/libinterp/parse-tree/pt-arg-list.cc +++ b/libinterp/parse-tree/pt-arg-list.cc @@ -283,6 +283,26 @@ return retval; } +std::list<std::string> +tree_argument_list::variable_names (void) const +{ + std::list<std::string> retval; + + for (const_iterator p = begin (); p != end (); p++) + { + tree_expression *elt = *p; + + if (elt->is_identifier ()) + { + tree_identifier *id = dynamic_cast<tree_identifier *> (elt); + + retval.push_back (id->name ()); + } + } + + return retval; +} + tree_argument_list * tree_argument_list::dup (symbol_table::scope_id scope, symbol_table::context_id context) const
--- a/libinterp/parse-tree/pt-arg-list.h +++ b/libinterp/parse-tree/pt-arg-list.h @@ -85,6 +85,8 @@ string_vector get_arg_names (void) const; + std::list<std::string> variable_names (void) const; + tree_argument_list *dup (symbol_table::scope_id scope, symbol_table::context_id context) const;
--- a/libinterp/parse-tree/pt-misc.cc +++ b/libinterp/parse-tree/pt-misc.cc @@ -228,6 +228,21 @@ } } +std::list<std::string> +tree_parameter_list::variable_names (void) const +{ + std::list<std::string> retval; + + for (const_iterator p = begin (); p != end (); p++) + { + tree_decl_elt *elt = *p; + + retval.push_back (elt->name ()); + } + + return retval; +} + octave_value_list tree_parameter_list::convert_to_const_vector (int nargout, const Cell& varargout)
--- a/libinterp/parse-tree/pt-misc.h +++ b/libinterp/parse-tree/pt-misc.h @@ -78,6 +78,8 @@ bool is_defined (void); + std::list<std::string> variable_names (void) const; + octave_value_list convert_to_const_vector (int nargout, const Cell& varargout); tree_parameter_list *dup (symbol_table::scope_id scope,
--- a/libinterp/parse-tree/token.cc +++ b/libinterp/parse-tree/token.cc @@ -138,6 +138,13 @@ return *str; } +std::string +token::symbol_name (void) const +{ + assert (type_tag == sym_rec_token); + return sr->name (); +} + double token::number (void) const {
--- a/libinterp/parse-tree/token.h +++ b/libinterp/parse-tree/token.h @@ -94,7 +94,13 @@ return type_tag == keyword_token || type_tag == ettype_token; } + bool is_symbol (void) const + { + return type_tag == sym_rec_token; + } + std::string text (void) const; + std::string symbol_name (void) const; double number (void) const; token_type ttype (void) const; end_tok_type ettype (void) const;
--- a/test/Makefile.am +++ b/test/Makefile.am @@ -24,6 +24,7 @@ fntests.m \ args.tst \ bug-31371.tst \ + bug-38576.tst \ diag-perm.tst \ error.tst \ eval-catch.tst \
new file mode 100644 --- /dev/null +++ b/test/bug-38576.tst @@ -0,0 +1,16 @@ +%!function r = f1 () +%! ls = svd (1); +%! r = eval ("ls -1;"); +%!endfunction +%!function r = f2 () +%! [u,ls,v] = svd (1); +%! r = eval ("ls -1;"); +%!endfunction +%!function r = f3 (ls) +%! r = eval ("ls -1;"); +%!endfunction + +%!assert (f1 (), 0); +%!assert (f2 (), 0); +%!assert (ischar (f3 ()), true); +%!assert (f3 (1), 0);