Mercurial > octave
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 |