# HG changeset patch # User John W. Eaton # Date 1584072881 14400 # Node ID 884a9f759eaa31f2a906097445fa7a105ee83815 # Parent 043deadaecf920c88e48c713994f7fd2eaaeaf7d# Parent 22cddebcb0d015546c103caa5fcad7532fb6cbe7 maint: merge stable to default. diff -r 043deadaecf9 -r 884a9f759eaa libinterp/parse-tree/lex.h --- a/libinterp/parse-tree/lex.h Thu Mar 12 16:56:46 2020 -0700 +++ b/libinterp/parse-tree/lex.h Fri Mar 13 00:14:41 2020 -0400 @@ -655,8 +655,6 @@ bool is_variable (const std::string& name, const symbol_scope& scope); - bool is_keyword_token (const std::string& s); - int make_keyword_token (const std::string& s); bool fq_identifier_contains_keyword (const std::string& s); diff -r 043deadaecf9 -r 884a9f759eaa libinterp/parse-tree/lex.ll --- a/libinterp/parse-tree/lex.ll Thu Mar 12 16:56:46 2020 -0700 +++ b/libinterp/parse-tree/lex.ll Fri Mar 13 00:14:41 2020 -0400 @@ -301,6 +301,25 @@ return c == ' ' || c == '\t' || c == '\n' || c == '\r'; } +namespace octave +{ + bool iskeyword (const std::string& s) + { + // Parsing function names like "set.property_name" inside + // classdef-style class definitions is simplified by handling the + // "set" and "get" portions of the names using the same mechanism + // as is used for keywords. However, they are not really keywords + // in the language, so omit them from the list of possible + // keywords. Likewise for "enumeration", "events", "methods", and + // "properties". + + return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != nullptr + && ! (s == "set" || s == "get" + || s == "enumeration" || s == "events" + || s == "methods" || s == "properties")); + } +} + %} D [0-9] @@ -1377,11 +1396,9 @@ ident.erase (std::remove_if (ident.begin (), ident.end (), is_space_or_tab), ident.end ()); - bool kw_token = curr_lexer->is_keyword_token (ident); - octave::token *tok; - if (kw_token) + if (octave::iskeyword (ident)) tok = new octave::token (LEXICAL_ERROR, "function handles may not refer to keywords", curr_lexer->m_tok_beg, @@ -2030,26 +2047,6 @@ } } -namespace octave -{ - bool - iskeyword (const std::string& s) - { - // Parsing function names like "set.property_name" inside - // classdef-style class definitions is simplified by handling the - // "set" and "get" portions of the names using the same mechanism - // as is used for keywords. However, they are not really keywords - // in the language, so omit them from the list of possible - // keywords. Likewise for "enumeration", "events", "methods", and - // "properties". - - return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != nullptr - && ! (s == "set" || s == "get" - || s == "enumeration" || s == "events" - || s == "methods" || s == "properties")); - } -} - DEFUN (iskeyword, args, , doc: /* -*- texinfo -*- @deftypefn {} {} iskeyword () @@ -2080,7 +2077,9 @@ { std::string kword = wordlist[i].name; - if (kword != "set" && kword != "get") + if (! (kword == "set" || kword == "get" + || kword == "enumeration" || kword == "events" + || kword == "methods" || kword == "properties")) lst[j++] = kword; } @@ -2580,16 +2579,6 @@ != m_pending_local_variables.end ())); } - // Handle keywords. Return -1 if the keyword should be ignored. - - bool - base_lexer::is_keyword_token (const std::string& s) - { - int len = s.length (); - - return octave_kw_hash::in_word_set (s.c_str (), len); - } - int base_lexer::make_keyword_token (const std::string& s) { @@ -2854,7 +2843,7 @@ else s_part = s.substr (p1); - if (is_keyword_token (s_part)) + if (iskeyword (s_part)) return true; } while (p2 != std::string::npos); @@ -3086,10 +3075,7 @@ std::string meth = txt.substr (0, pos); std::string cls = txt.substr (pos + 1); - bool kw_token = (is_keyword_token (meth) - || fq_identifier_contains_keyword (cls)); - - if (kw_token) + if (iskeyword (meth) || fq_identifier_contains_keyword (cls)) { token *tok = new token (LEXICAL_ERROR, @@ -3193,7 +3179,7 @@ return STRUCT_ELT; } - // If ident is a keyword token, then is_keyword_token will set + // If ident is a keyword token, then make_keyword_token will set // m_at_beginning_of_statement. For example, if tok is an IF // token, then m_at_beginning_of_statement will be false. diff -r 043deadaecf9 -r 884a9f759eaa test/fcn-handle/keyword.tst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/fcn-handle/keyword.tst Fri Mar 13 00:14:41 2020 -0400 @@ -0,0 +1,48 @@ +######################################################################## +## +## Copyright (C) 2020 The Octave Project Developers +## +## See the file COPYRIGHT.md in the top-level directory of this +## distribution or . +## +## This file is part of Octave. +## +## Octave is free software: you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . +## +######################################################################## + +%!test <*57988> +%! fh = @get; +%! fh = @set; +%! fh = @enumeration; +%! fh = @events; +%! fh = @methods; +%! fh = @properties; + +%!test <*57988> +%! kwords = iskeyword (); +%! for i = 1:numel (kwords) +%! unexpected_success = true; +%! kword = kwords{i}; +%! try +%! eval (sprintf ("@%s;", kword)); +%! catch +%! unexpected_success = false; +%! end_try_catch +%! if (unexpected_success) +%! error ("constructing function handle from keyword '%s' succeeded!", +%! kword); +%! endif +%! endfor diff -r 043deadaecf9 -r 884a9f759eaa test/fcn-handle/module.mk --- a/test/fcn-handle/module.mk Thu Mar 12 16:56:46 2020 -0700 +++ b/test/fcn-handle/module.mk Fri Mar 13 00:14:41 2020 -0400 @@ -14,6 +14,7 @@ %reldir%/bug51709_c.m \ %reldir%/derived-resolution.tst \ %reldir%/f1.m \ + %reldir%/keyword.tst \ %reldir%/object-method.tst \ %reldir%/package-function.tst \ %reldir%/static-method.tst