This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR fortran/13912: Consecutive arithmetic operators


The following patch is my proposed solution to PR fortran/13912 by
allowing (possibly nested) unary operators after other arithmetic
(binary and unary) operators as a GNU extension.  This functionality
is supported by g77 (when not -pedantic) and other fortran compilers
though not strictly legal in the latest ISO fortran standards.

In the source code below I've documented this extension in terms of
the necessary tweaks to section 7.1.1.3 of the draft ISO/IEC 1539-1
document.  The structure of the code follows from the grammar.  Note
that with -std=f95 or -std=f2003, i.e. when we don't permit GNU
extensions, ext-mult-operand and ext-add-operand behave identically
to the original mult-operand and add-operand respecitively, i.e. no
change to the official grammar.

Note also that precedence of these operators remains similar to
that described in the fortran standard, i.e. that unary + and -
are low precedence.  This means that A + - B * C is interpreted as
A + (- (B * C)) [whereas in C it's high precedence: A + ((-B) * C).]


I've confirmed that this allows the code example in PR 13912 to
compile, as well as the examples I posted earlier today on the fortran
mailing list.  These examples can all be added as testcases to the
gfortran testsuite, just as soon as we resolve when we should and
shouldn't warn: http://gcc.gnu.org/ml/fortran/2004-05/msg00316.html
[Note only issuing a warning with -pedantic follows g77's behaviour]


The following patch has been tested on i686-pc-linux-gnu with a full
bootstrap, including gfortran, and tested with a make check-gfortran
with no new failures.

Ok for mainline?


2004-05-24  Roger Sayle  <roger@eyesopen.com>

	PR fortran/13912
	* matchexp.c: Allow unary operators after arithmetic operators
	as a GNU extension.
	(match_ext_mult_operand, match_ext_add_operand): New functions.
	(match_mult_operand): Tweak to call match_ext_mult_operand.
	(match_add_operand): Tweak to call match_ext_mult_operand.
	(match_level_2): Rearrange to call match_ext_add_operand.


Index: matchexp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/matchexp.c,v
retrieving revision 1.3
diff -c -3 -p -r1.3 matchexp.c
*** matchexp.c	14 May 2004 13:00:04 -0000	1.3
--- matchexp.c	25 May 2004 03:19:31 -0000
*************** match_level_1 (gfc_expr ** result)
*** 222,227 ****
--- 222,259 ----
  }


+ /* As a GNU extension we support an expanded level-2 expression syntax.
+    Via this extension we support (arbitrary) nesting of unary plus and
+    minus operations following unary and binary operators, such as **.
+    The grammar of section 7.1.1.3 is effectively rewitten as:
+
+ 	R704  mult-operand     is level-1-expr [ power-op ext-mult-operand ]
+ 	R704' ext-mult-operand is add-op ext-mult-operand
+ 			       or mult-operand
+ 	R705  add-operand      is add-operand mult-op ext-mult-operand
+ 			       or mult-operand
+ 	R705' ext-add-operand  is add-op ext-add-operand
+ 			       or add-operand
+ 	R706  level-2-expr     is [ level-2-expr ] add-op ext-add-operand
+ 			       or add-operand
+  */
+
+ static match match_ext_mult_operand (gfc_expr ** result);
+ static match match_ext_add_operand (gfc_expr ** result);
+
+
+ static int
+ match_add_op (void)
+ {
+
+   if (next_operator (INTRINSIC_MINUS))
+     return -1;
+   if (next_operator (INTRINSIC_PLUS))
+     return 1;
+   return 0;
+ }
+
+
  static match
  match_mult_operand (gfc_expr ** result)
  {
*************** match_mult_operand (gfc_expr ** result)
*** 241,247 ****

    where = *gfc_current_locus ();

!   m = match_mult_operand (&exp);
    if (m == MATCH_NO)
      gfc_error ("Expected exponent in expression at %C");
    if (m != MATCH_YES)
--- 273,279 ----

    where = *gfc_current_locus ();

!   m = match_ext_mult_operand (&exp);
    if (m == MATCH_NO)
      gfc_error ("Expected exponent in expression at %C");
    if (m != MATCH_YES)
*************** match_mult_operand (gfc_expr ** result)
*** 266,271 ****
--- 298,343 ----


  static match
+ match_ext_mult_operand (gfc_expr ** result)
+ {
+   gfc_expr *all, *e;
+   locus where;
+   match m;
+   int i;
+
+   where = *gfc_current_locus ();
+   i = match_add_op ();
+
+   if (i == 0)
+     return match_mult_operand (result);
+
+   if (gfc_notify_std (GFC_STD_GNU, "Extension: Unary operator following"
+ 		      " arithmetic operator (use parentheses) at %C")
+       == FAILURE)
+     return MATCH_ERROR;
+
+   m = match_ext_mult_operand (&e);
+   if (m != MATCH_YES)
+     return m;
+
+   if (i == -1)
+     all = gfc_uminus (e);
+   else
+     all = gfc_uplus (e);
+
+   if (all == NULL)
+     {
+       gfc_free_expr (e);
+       return MATCH_ERROR;
+     }
+
+   all->where = where;
+   *result = all;
+   return MATCH_YES;
+ }
+
+
+ static match
  match_add_operand (gfc_expr ** result)
  {
    gfc_expr *all, *e, *total;
*************** match_add_operand (gfc_expr ** result)
*** 295,301 ****

        where = *gfc_current_locus ();

!       m = match_mult_operand (&e);
        if (m == MATCH_NO)
  	{
  	  gfc_set_locus (&old_loc);
--- 367,373 ----

        where = *gfc_current_locus ();

!       m = match_ext_mult_operand (&e);
        if (m == MATCH_NO)
  	{
  	  gfc_set_locus (&old_loc);
*************** match_add_operand (gfc_expr ** result)
*** 329,343 ****
  }


! static int
! match_add_op (void)
  {

!   if (next_operator (INTRINSIC_MINUS))
!     return -1;
!   if (next_operator (INTRINSIC_PLUS))
!     return 1;
!   return 0;
  }


--- 401,443 ----
  }


! static match
! match_ext_add_operand (gfc_expr ** result)
  {
+   gfc_expr *all, *e;
+   locus where;
+   match m;
+   int i;

!   where = *gfc_current_locus ();
!   i = match_add_op ();
!
!   if (i == 0)
!     return match_add_operand (result);
!
!   if (gfc_notify_std (GFC_STD_GNU, "Extension: Unary operator following"
! 		      " arithmetic operator (use parentheses) at %C")
!       == FAILURE)
!     return MATCH_ERROR;
!
!   m = match_ext_add_operand (&e);
!   if (m != MATCH_YES)
!     return m;
!
!   if (i == -1)
!     all = gfc_uminus (e);
!   else
!     all = gfc_uplus (e);
!
!   if (all == NULL)
!     {
!       gfc_free_expr (e);
!       return MATCH_ERROR;
!     }
!
!   all->where = where;
!   *result = all;
!   return MATCH_YES;
  }


*************** match_level_2 (gfc_expr ** result)
*** 354,365 ****
    where = *gfc_current_locus ();
    i = match_add_op ();

!   m = match_add_operand (&e);
!   if (i != 0 && m == MATCH_NO)
      {
!       gfc_error (expression_syntax);
!       m = MATCH_ERROR;
      }

    if (m != MATCH_YES)
      return m;
--- 454,470 ----
    where = *gfc_current_locus ();
    i = match_add_op ();

!   if (i != 0)
      {
!       m = match_ext_add_operand (&e);
!       if (m == MATCH_NO)
! 	{
! 	  gfc_error (expression_syntax);
! 	  m = MATCH_ERROR;
! 	}
      }
+   else
+     m = match_add_operand (&e);

    if (m != MATCH_YES)
      return m;
*************** match_level_2 (gfc_expr ** result)
*** 391,397 ****
        if (i == 0)
  	break;

!       m = match_add_operand (&e);
        if (m == MATCH_NO)
  	gfc_error (expression_syntax);
        if (m != MATCH_YES)
--- 496,502 ----
        if (i == 0)
  	break;

!       m = match_ext_add_operand (&e);
        if (m == MATCH_NO)
  	gfc_error (expression_syntax);
        if (m != MATCH_YES)


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]