changeset 17677:fd712a12fe53

compatibility for power operator precedence and direction (bug #33304) * oct-parse.in.yy (power_expr): New non-terminal. (oper_expr): Use it for the RHS of POW and EPOW operators. * parser.tst: New tests.
author Axel Mathéi <axel.mathei@gmail.com>
date Thu, 10 Oct 2013 12:15:18 -0400
parents d41c8f96ed06
children 7b305b36b87e
files libinterp/parse-tree/oct-parse.in.yy test/parser.tst
diffstat 2 files changed, 61 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/oct-parse.in.yy
+++ b/libinterp/parse-tree/oct-parse.in.yy
@@ -238,7 +238,7 @@
 %type <tree_matrix_type> matrix_rows
 %type <tree_cell_type> cell_rows
 %type <tree_expression_type> matrix cell
-%type <tree_expression_type> primary_expr oper_expr
+%type <tree_expression_type> primary_expr oper_expr power_expr
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
 %type <tree_identifier_type> identifier fcn_name magic_tilde
 %type <tree_identifier_type> superclass_identifier meta_identifier
@@ -598,9 +598,9 @@
                   { $$ = parser.make_prefix_op ('+', $2, $1); }
                 | '-' oper_expr %prec UNARY
                   { $$ = parser.make_prefix_op ('-', $2, $1); }
-                | oper_expr POW oper_expr
+                | oper_expr POW power_expr
                   { $$ = parser.make_binary_op (POW, $1, $2, $3); }
-                | oper_expr EPOW oper_expr
+                | oper_expr EPOW power_expr
                   { $$ = parser.make_binary_op (EPOW, $1, $2, $3); }
                 | oper_expr '+' oper_expr
                   { $$ = parser.make_binary_op ('+', $1, $2, $3); }
@@ -624,6 +624,52 @@
                   { $$ = parser.make_binary_op (ELEFTDIV, $1, $2, $3); }
                 ;
 
+power_expr      : primary_expr
+                  { $$ = $1; }
+                | power_expr PLUS_PLUS
+                  { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); }
+                | power_expr MINUS_MINUS
+                  { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); }
+                | power_expr '(' ')'
+                  {
+                    $$ = parser.make_index_expression ($1, 0, '(');
+                    if (! $$)
+                      ABORT_PARSE;
+                  }
+                | power_expr '(' arg_list ')'
+                  {
+                    $$ = parser.make_index_expression ($1, $3, '(');
+                    if (! $$)
+                      ABORT_PARSE;
+                  }
+                | power_expr '{' '}'
+                  {
+                    $$ = parser.make_index_expression ($1, 0, '{');
+                    if (! $$)
+                      ABORT_PARSE;
+                  }
+                | power_expr '{' arg_list '}'
+                  {
+                    $$ = parser.make_index_expression ($1, $3, '{');
+                    if (! $$)
+                      ABORT_PARSE;
+                  }
+                | power_expr indirect_ref_op STRUCT_ELT
+                  { $$ = parser.make_indirect_ref ($1, $3->text ()); }
+                | power_expr indirect_ref_op '(' expression ')'
+                  { $$ = parser.make_indirect_ref ($1, $4); }
+                | PLUS_PLUS power_expr %prec POW
+                  { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); }
+                | MINUS_MINUS power_expr %prec POW
+                  { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); }
+                | EXPR_NOT power_expr %prec POW
+                  { $$ = parser.make_prefix_op (EXPR_NOT, $2, $1); }
+                | '+' power_expr %prec POW
+                  { $$ = parser.make_prefix_op ('+', $2, $1); }
+                | '-' power_expr %prec POW
+                  { $$ = parser.make_prefix_op ('-', $2, $1); }
+                ;
+
 colon_expr      : colon_expr1
                   { $$ = parser.finish_colon_expression ($1); }
                 ;
--- a/test/parser.tst
+++ b/test/parser.tst
@@ -80,7 +80,19 @@
 
 ## Level 11 (transpose and exponentiation)
 %!test
+%! a = 2;
+%! assert (2 ^a++, 4)
+%! assert (a, 3)
+%! assert (2 ^--a ^2, 16)
+%! assert (a, 2)
+%! assert (2 ^++a, 8)
+%! assert (a, 3)
+%! assert (a' ^2, 9)
+%! assert (2 ^sin(0), 1)
 %! assert (-2 ^2, -4);
+%! assert (2 ^+1 ^3, 8)
+%! assert (2 ^-1 ^3, 0.125)
+%! assert (2 ^~0 ^2, 4)
 %! assert (!0 ^0, false);
 %! assert (2*3 ^2, 18);
 %! assert (2+3 ^2, 11);