comparison libinterp/parse-tree/lex.ll @ 29900:da6e5914ddaf

handle all binary operators the same when detecting command syntax (bug #60882) This change breaks Matlab compatibility when parsing things like x += 2 Matlab will handle this as a command-style function call with two arguments '+=' and '2'. Octave will now treat this as a computed assignment (the variable X incremented by 2). Octave will still handle x +=2 as a command-style function call when parsing this statement inside a function. At the command line, Octave will recognize this statement as a computed assignment expression if X is already defined to be a variable. Note that command lines are parsed completely before executing anything, so in octave> clear x octave> x = 1; x +=2 the "x +=2" statement will be parsed as a command-style function call because the parser does not find a definition for X as a variable when that portion of the command line is parsed. * lex.ll (CMD_OR_COMPUTED_ASSIGN_OP): Delete macro. Change all uses to CMD_OR_OP instead. (base_lexer::handle_identifier): Don't call mark_may_be_command for token if we are at the top level and the identifier has already been recognized as a variable. * parser.tst: Update test.
author John W. Eaton <jwe@octave.org>
date Wed, 21 Jul 2021 09:49:09 -0400
parents e2e493712818
children ef865fcd4611
comparison
equal deleted inserted replaced
29899:853e4b7ae0d5 29900:da6e5914ddaf
180 } \ 180 } \
181 else \ 181 else \
182 return curr_lexer->handle_op (TOK, false, COMPAT); \ 182 return curr_lexer->handle_op (TOK, false, COMPAT); \
183 } \ 183 } \
184 while (0) 184 while (0)
185
186 #if 0
187 // Use the following to handle computed assignment operators
188 // (+=, -=, etc.) in word list commands in a way that is compatible
189 // with Matlab. However, that will also make it impossible to use
190 // these operators with a space before them:
191 //
192 // x = 1;
193 // x+=2; ## ok
194 // x+= 2; ## ok
195 // x +=2; ## error: invalid use of symbol as both variable and command
196 // x += 2; ## error: invalid use of symbol as both variable and command
197 //
198 # define CMD_OR_COMPUTED_ASSIGN_OP(PATTERN, TOK) \
199 do \
200 { \
201 curr_lexer->lexer_debug (PATTERN); \
202 \
203 if (curr_lexer->previous_token_may_be_command () \
204 && curr_lexer->space_follows_previous_token ()) \
205 { \
206 yyless (0); \
207 curr_lexer->push_start_state (COMMAND_START); \
208 } \
209 else \
210 return curr_lexer->handle_op (TOK, false, false); \
211 } \
212 while (0)
213 #else
214 # define CMD_OR_COMPUTED_ASSIGN_OP(PATTERN, TOK) \
215 return curr_lexer->handle_op (TOK, false, false)
216 #endif
217 185
218 #define CMD_OR_UNARY_OP(PATTERN, TOK, COMPAT) \ 186 #define CMD_OR_UNARY_OP(PATTERN, TOK, COMPAT) \
219 do \ 187 do \
220 { \ 188 { \
221 curr_lexer->lexer_debug (PATTERN); \ 189 curr_lexer->lexer_debug (PATTERN); \
1834 curr_lexer->lexer_debug ("="); 1802 curr_lexer->lexer_debug ("=");
1835 1803
1836 return curr_lexer->handle_op ('='); 1804 return curr_lexer->handle_op ('=');
1837 } 1805 }
1838 1806
1839 "+=" { CMD_OR_COMPUTED_ASSIGN_OP ("+=", ADD_EQ); } 1807 "+=" { CMD_OR_OP ("+=", ADD_EQ, false); }
1840 "-=" { CMD_OR_COMPUTED_ASSIGN_OP ("-=", SUB_EQ); } 1808 "-=" { CMD_OR_OP ("-=", SUB_EQ, false); }
1841 "*=" { CMD_OR_COMPUTED_ASSIGN_OP ("*=", MUL_EQ); } 1809 "*=" { CMD_OR_OP ("*=", MUL_EQ, false); }
1842 "/=" { CMD_OR_COMPUTED_ASSIGN_OP ("/=", DIV_EQ); } 1810 "/=" { CMD_OR_OP ("/=", DIV_EQ, false); }
1843 "\\=" { CMD_OR_COMPUTED_ASSIGN_OP ("\\=", LEFTDIV_EQ); } 1811 "\\=" { CMD_OR_OP ("\\=", LEFTDIV_EQ, false); }
1844 ".+=" { CMD_OR_COMPUTED_ASSIGN_OP (".+=", ADD_EQ); } 1812 ".+=" { CMD_OR_OP (".+=", ADD_EQ, false); }
1845 ".-=" { CMD_OR_COMPUTED_ASSIGN_OP (".-=", SUB_EQ); } 1813 ".-=" { CMD_OR_OP (".-=", SUB_EQ, false); }
1846 ".*=" { CMD_OR_COMPUTED_ASSIGN_OP (".*=", EMUL_EQ); } 1814 ".*=" { CMD_OR_OP (".*=", EMUL_EQ, false); }
1847 "./=" { CMD_OR_COMPUTED_ASSIGN_OP ("./=", EDIV_EQ); } 1815 "./=" { CMD_OR_OP ("./=", EDIV_EQ, false); }
1848 ".\\=" { CMD_OR_COMPUTED_ASSIGN_OP (".\\=", ELEFTDIV_EQ); } 1816 ".\\=" { CMD_OR_OP (".\\=", ELEFTDIV_EQ, false); }
1849 "^=" { CMD_OR_COMPUTED_ASSIGN_OP ("^=", POW_EQ); } 1817 "^=" { CMD_OR_OP ("^=", POW_EQ, false); }
1850 "**=" { CMD_OR_COMPUTED_ASSIGN_OP ("^=", POW_EQ); } 1818 "**=" { CMD_OR_OP ("^=", POW_EQ, false); }
1851 ".^=" { CMD_OR_COMPUTED_ASSIGN_OP (".^=", EPOW_EQ); } 1819 ".^=" { CMD_OR_OP (".^=", EPOW_EQ, false); }
1852 ".**=" { CMD_OR_COMPUTED_ASSIGN_OP (".^=", EPOW_EQ); } 1820 ".**=" { CMD_OR_OP (".^=", EPOW_EQ, false); }
1853 "&=" { CMD_OR_COMPUTED_ASSIGN_OP ("&=", AND_EQ); } 1821 "&=" { CMD_OR_OP ("&=", AND_EQ, false); }
1854 "|=" { CMD_OR_COMPUTED_ASSIGN_OP ("|=", OR_EQ); } 1822 "|=" { CMD_OR_OP ("|=", OR_EQ, false); }
1855 1823
1856 %{ 1824 %{
1857 // In Matlab, '{' may also trigger command syntax. 1825 // In Matlab, '{' may also trigger command syntax.
1858 %} 1826 %}
1859 1827
3582 return count_token_internal (kw_token); 3550 return count_token_internal (kw_token);
3583 } 3551 }
3584 3552
3585 token *tok = new token (NAME, ident, m_tok_beg, m_tok_end); 3553 token *tok = new token (NAME, ident, m_tok_beg, m_tok_end);
3586 3554
3587 // The following symbols are handled specially so that things like 3555 // For compatibility with Matlab, the following symbols are
3556 // handled specially so that things like
3588 // 3557 //
3589 // pi +1 3558 // pi +1
3590 // 3559 //
3591 // are parsed as an addition expression instead of as a command-style 3560 // are parsed as an addition expression instead of as a command-style
3592 // function call with the argument "+1". 3561 // function call with the argument "+1". Also for compatibility with
3562 // Matlab, if we are at the top level workspace, do not consider IDENT
3563 // as a possible command if it is already known to be a variable.
3593 3564
3594 if (m_at_beginning_of_statement 3565 if (m_at_beginning_of_statement
3595 && ! (m_parsing_anon_fcn_body 3566 && ! (m_parsing_anon_fcn_body
3596 || ident == "e" || ident == "pi" 3567 || ident == "e" || ident == "pi"
3597 || ident == "I" || ident == "i" 3568 || ident == "I" || ident == "i"
3598 || ident == "J" || ident == "j" 3569 || ident == "J" || ident == "j"
3599 || ident == "Inf" || ident == "inf" 3570 || ident == "Inf" || ident == "inf"
3600 || ident == "NaN" || ident == "nan")) 3571 || ident == "NaN" || ident == "nan"
3572 || (m_interpreter.at_top_level ()
3573 && m_interpreter.is_variable (ident))))
3601 tok->mark_may_be_command (); 3574 tok->mark_may_be_command ();
3602 3575
3603 push_token (tok); 3576 push_token (tok);
3604 3577
3605 // The magic end index can't be indexed. 3578 // The magic end index can't be indexed.