comparison libinterp/parse-tree/lex.ll @ 28156:22cddebcb0d0 stable

allow @get and @set to work properly again (bug #57988) * lex.h, lex.ll (base_lexer::is_keyword_token): Delete. Replace all uses with iskeyword. (Fiskeyword): When creating list, also omit "enumeration", "events", "methods", and "properties". * keyword.tst: New file. * test/fcn-handle/module.mk: Update
author John W. Eaton <jwe@octave.org>
date Thu, 12 Mar 2020 23:51:49 -0400
parents 026bff6a54d7
children 3e3ad0ae247f
comparison
equal deleted inserted replaced
28154:e7fe6703a81f 28156:22cddebcb0d0
299 is_space_or_tab_or_eol (char c) 299 is_space_or_tab_or_eol (char c)
300 { 300 {
301 return c == ' ' || c == '\t' || c == '\n' || c == '\r'; 301 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
302 } 302 }
303 303
304 namespace octave
305 {
306 bool iskeyword (const std::string& s)
307 {
308 // Parsing function names like "set.property_name" inside
309 // classdef-style class definitions is simplified by handling the
310 // "set" and "get" portions of the names using the same mechanism
311 // as is used for keywords. However, they are not really keywords
312 // in the language, so omit them from the list of possible
313 // keywords. Likewise for "enumeration", "events", "methods", and
314 // "properties".
315
316 return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != nullptr
317 && ! (s == "set" || s == "get"
318 || s == "enumeration" || s == "events"
319 || s == "methods" || s == "properties"));
320 }
321 }
322
304 %} 323 %}
305 324
306 D [0-9] 325 D [0-9]
307 D_ [0-9_] 326 D_ [0-9_]
308 S [ \t] 327 S [ \t]
1375 { 1394 {
1376 ident = ident.substr (1); 1395 ident = ident.substr (1);
1377 ident.erase (std::remove_if (ident.begin (), ident.end (), 1396 ident.erase (std::remove_if (ident.begin (), ident.end (),
1378 is_space_or_tab), ident.end ()); 1397 is_space_or_tab), ident.end ());
1379 1398
1380 bool kw_token = curr_lexer->is_keyword_token (ident);
1381
1382 octave::token *tok; 1399 octave::token *tok;
1383 1400
1384 if (kw_token) 1401 if (octave::iskeyword (ident))
1385 tok = new octave::token (LEXICAL_ERROR, 1402 tok = new octave::token (LEXICAL_ERROR,
1386 "function handles may not refer to keywords", 1403 "function handles may not refer to keywords",
1387 curr_lexer->m_tok_beg, 1404 curr_lexer->m_tok_beg,
1388 curr_lexer->m_tok_end); 1405 curr_lexer->m_tok_end);
1389 else 1406 else
2028 std::cerr << "DEL"; 2045 std::cerr << "DEL";
2029 break; 2046 break;
2030 } 2047 }
2031 } 2048 }
2032 2049
2033 namespace octave
2034 {
2035 bool
2036 iskeyword (const std::string& s)
2037 {
2038 // Parsing function names like "set.property_name" inside
2039 // classdef-style class definitions is simplified by handling the
2040 // "set" and "get" portions of the names using the same mechanism
2041 // as is used for keywords. However, they are not really keywords
2042 // in the language, so omit them from the list of possible
2043 // keywords. Likewise for "enumeration", "events", "methods", and
2044 // "properties".
2045
2046 return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != nullptr
2047 && ! (s == "set" || s == "get"
2048 || s == "enumeration" || s == "events"
2049 || s == "methods" || s == "properties"));
2050 }
2051 }
2052
2053 DEFUN (iskeyword, args, , 2050 DEFUN (iskeyword, args, ,
2054 doc: /* -*- texinfo -*- 2051 doc: /* -*- texinfo -*-
2055 @deftypefn {} {} iskeyword () 2052 @deftypefn {} {} iskeyword ()
2056 @deftypefnx {} {} iskeyword (@var{name}) 2053 @deftypefnx {} {} iskeyword (@var{name})
2057 Return true if @var{name} is an Octave keyword. 2054 Return true if @var{name} is an Octave keyword.
2078 2075
2079 for (int i = 0; i < TOTAL_KEYWORDS; i++) 2076 for (int i = 0; i < TOTAL_KEYWORDS; i++)
2080 { 2077 {
2081 std::string kword = wordlist[i].name; 2078 std::string kword = wordlist[i].name;
2082 2079
2083 if (kword != "set" && kword != "get") 2080 if (! (kword == "set" || kword == "get"
2081 || kword == "enumeration" || kword == "events"
2082 || kword == "methods" || kword == "properties"))
2084 lst[j++] = kword; 2083 lst[j++] = kword;
2085 } 2084 }
2086 2085
2087 lst.resize (j); 2086 lst.resize (j);
2088 2087
2578 && m_interpreter.is_variable (name)) 2577 && m_interpreter.is_variable (name))
2579 || (m_pending_local_variables.find (name) 2578 || (m_pending_local_variables.find (name)
2580 != m_pending_local_variables.end ())); 2579 != m_pending_local_variables.end ()));
2581 } 2580 }
2582 2581
2583 // Handle keywords. Return -1 if the keyword should be ignored.
2584
2585 bool
2586 base_lexer::is_keyword_token (const std::string& s)
2587 {
2588 int len = s.length ();
2589
2590 return octave_kw_hash::in_word_set (s.c_str (), len);
2591 }
2592
2593 int 2582 int
2594 base_lexer::make_keyword_token (const std::string& s) 2583 base_lexer::make_keyword_token (const std::string& s)
2595 { 2584 {
2596 int slen = s.length (); 2585 int slen = s.length ();
2597 2586
2852 p1 = p2 + 1; 2841 p1 = p2 + 1;
2853 } 2842 }
2854 else 2843 else
2855 s_part = s.substr (p1); 2844 s_part = s.substr (p1);
2856 2845
2857 if (is_keyword_token (s_part)) 2846 if (iskeyword (s_part))
2858 return true; 2847 return true;
2859 } 2848 }
2860 while (p2 != std::string::npos); 2849 while (p2 != std::string::npos);
2861 2850
2862 return false; 2851 return false;
3084 size_t pos = txt.find ("@"); 3073 size_t pos = txt.find ("@");
3085 3074
3086 std::string meth = txt.substr (0, pos); 3075 std::string meth = txt.substr (0, pos);
3087 std::string cls = txt.substr (pos + 1); 3076 std::string cls = txt.substr (pos + 1);
3088 3077
3089 bool kw_token = (is_keyword_token (meth) 3078 if (iskeyword (meth) || fq_identifier_contains_keyword (cls))
3090 || fq_identifier_contains_keyword (cls));
3091
3092 if (kw_token)
3093 { 3079 {
3094 token *tok 3080 token *tok
3095 = new token (LEXICAL_ERROR, 3081 = new token (LEXICAL_ERROR,
3096 "method, class, and package names may not be keywords", 3082 "method, class, and package names may not be keywords",
3097 m_tok_beg, m_tok_end); 3083 m_tok_beg, m_tok_end);
3191 m_looking_for_object_index = true; 3177 m_looking_for_object_index = true;
3192 3178
3193 return STRUCT_ELT; 3179 return STRUCT_ELT;
3194 } 3180 }
3195 3181
3196 // If ident is a keyword token, then is_keyword_token will set 3182 // If ident is a keyword token, then make_keyword_token will set
3197 // m_at_beginning_of_statement. For example, if tok is an IF 3183 // m_at_beginning_of_statement. For example, if tok is an IF
3198 // token, then m_at_beginning_of_statement will be false. 3184 // token, then m_at_beginning_of_statement will be false.
3199 3185
3200 int kw_token = make_keyword_token (ident); 3186 int kw_token = make_keyword_token (ident);
3201 3187