summaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2004-05-26 02:35:29 +0000
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2004-05-26 02:35:29 +0000
commit4b4d8a7e742b8ee74139c53477db78b6b0c49acb (patch)
tree6f5765b663bb23e6df8435cb2a011290e1575360 /gcc/fortran
parentce716239506030d8c9d37085625ea702668d1fd8 (diff)
downloadgcc-4b4d8a7e742b8ee74139c53477db78b6b0c49acb.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@82277 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog10
-rw-r--r--gcc/fortran/matchexp.c133
2 files changed, 129 insertions, 14 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index c9a4f7decd5..74228782f57 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,13 @@
+2004-05-25 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.
+
2004-05-25 Paul Brook <paul@codesourcery.com>
* expr.c (check_inquiry): Remove bogus tests.
diff --git a/gcc/fortran/matchexp.c b/gcc/fortran/matchexp.c
index f0c227f95b8..539a91a31c1 100644
--- a/gcc/fortran/matchexp.c
+++ b/gcc/fortran/matchexp.c
@@ -222,6 +222,38 @@ match_level_1 (gfc_expr ** result)
}
+/* 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)
{
@@ -241,7 +273,7 @@ match_mult_operand (gfc_expr ** result)
where = *gfc_current_locus ();
- m = match_mult_operand (&exp);
+ m = match_ext_mult_operand (&exp);
if (m == MATCH_NO)
gfc_error ("Expected exponent in expression at %C");
if (m != MATCH_YES)
@@ -266,6 +298,46 @@ match_mult_operand (gfc_expr ** result)
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;
@@ -295,7 +367,7 @@ match_add_operand (gfc_expr ** result)
where = *gfc_current_locus ();
- m = match_mult_operand (&e);
+ m = match_ext_mult_operand (&e);
if (m == MATCH_NO)
{
gfc_set_locus (&old_loc);
@@ -329,15 +401,43 @@ match_add_operand (gfc_expr ** result)
}
-static int
-match_add_op (void)
+static match
+match_ext_add_operand (gfc_expr ** result)
{
+ gfc_expr *all, *e;
+ locus where;
+ match m;
+ int i;
- if (next_operator (INTRINSIC_MINUS))
- return -1;
- if (next_operator (INTRINSIC_PLUS))
- return 1;
- return 0;
+ 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;
}
@@ -354,12 +454,17 @@ match_level_2 (gfc_expr ** result)
where = *gfc_current_locus ();
i = match_add_op ();
- m = match_add_operand (&e);
- if (i != 0 && m == MATCH_NO)
+ if (i != 0)
{
- gfc_error (expression_syntax);
- m = MATCH_ERROR;
+ 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;
@@ -391,7 +496,7 @@ match_level_2 (gfc_expr ** result)
if (i == 0)
break;
- m = match_add_operand (&e);
+ m = match_ext_add_operand (&e);
if (m == MATCH_NO)
gfc_error (expression_syntax);
if (m != MATCH_YES)