This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[PATCH] PR fortran/13912: Consecutive arithmetic operators
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: fortran at gcc dot gnu dot org
- Date: Mon, 24 May 2004 22:28:20 -0600 (MDT)
- Subject: [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