[gnumeric] Parsing: Make '^' left-associative in ODF files.



commit aa228a5492102cbb0c1d4b817aaa3ba49e9b52b3
Author: Morten Welinder <terra gnome org>
Date:   Wed Jun 10 21:46:47 2009 -0400

    Parsing: Make '^' left-associative in ODF files.
---
 ChangeLog                            |   10 ++++++
 NEWS                                 |    1 +
 plugins/openoffice/ChangeLog         |    6 ++++
 plugins/openoffice/openoffice-read.c |   10 ++++--
 src/parse-util.c                     |    1 +
 src/parse-util.h                     |    3 ++
 src/parser.y                         |   53 +++++++++++++++++++--------------
 7 files changed, 58 insertions(+), 26 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 90b70f1..4f932ca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2009-06-10  Morten Welinder  <terra gnome org>
 
+	* src/parser.y (yylex): Return LEFT_EXP_TOKEN or RIGHT_EXP_TOKEN
+	for '^'.
+	(yyparse): Handle LEFT_EXP_TOKEN and RIGHT_EXP_TOKEN instead of
+	'^'.
+
+	* src/parse-util.h (struct _GnmConventions): Add associativity
+	switch for '^'.
+
+	* src/parse-util.c (gnm_conventions_new_full): Init it.
+
 	* src/parser.y: Change x^y^z into x^(y^z) to indicate how we
 	parsed it.
 
diff --git a/NEWS b/NEWS
index f69a53e..df67e58 100644
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,7 @@ Morten:
 	* Implement new functions COT and ACOT.  [#585270]
 	* Fix GCD.  [#585271]
 	* Change x^y^z into x^(y^z) to indicate parsing.
+	* Parse x^y^z as (x^y)^z from ODF files.  [#585277]
 
 --------------------------------------------------------------------------
 Gnumeric 1.9.8
diff --git a/plugins/openoffice/ChangeLog b/plugins/openoffice/ChangeLog
index 32f9cad..de6cb98 100644
--- a/plugins/openoffice/ChangeLog
+++ b/plugins/openoffice/ChangeLog
@@ -1,3 +1,9 @@
+2009-06-10  Morten Welinder  <terra gnome org>
+
+	* openoffice-read.c (oo_load_convention): Mark '^'
+	left-associative in Excel formulas.
+	(oo_conventions_new): Ditto for OO formulas.
+
 2009-06-10 Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	openoffice-write.c (odf_write_content): export print area to ODF 
diff --git a/plugins/openoffice/openoffice-read.c b/plugins/openoffice/openoffice-read.c
index 773a661..0401165 100644
--- a/plugins/openoffice/openoffice-read.c
+++ b/plugins/openoffice/openoffice-read.c
@@ -597,6 +597,7 @@ oo_conventions_new (void)
 	GnmConventions *conv = gnm_conventions_new ();
 
 	conv->decode_ampersands	= TRUE;
+	conv->exp_is_left_associative = TRUE;
 
 	conv->intersection_char	= '!';
 	conv->decimal_sep_dot	= TRUE;
@@ -613,19 +614,22 @@ oo_conventions_new (void)
 static void
 oo_load_convention (OOParseState *state, OOFormula type)
 {
+	GnmConventions *convs;
+
 	g_return_if_fail (state->convs[type] == NULL);
 
 	switch (type) {
 	case FORMULA_MICROSOFT:
-		state->convs[type] = gnm_xml_io_conventions ();
+		convs = gnm_xml_io_conventions ();
+		convs->exp_is_left_associative = TRUE;
 		break;
 	case FORMULA_OPENFORMULA:
 	default:
-		state->convs[type] =  oo_conventions_new ();
+		convs = oo_conventions_new ();
 		break;
 	}
 
-	
+	state->convs[type] = convs;
 }
 
 static GnmExprTop const *
diff --git a/src/parse-util.c b/src/parse-util.c
index 541484b..fc129bb 100644
--- a/src/parse-util.c
+++ b/src/parse-util.c
@@ -1329,6 +1329,7 @@ gnm_conventions_new_full (unsigned size)
 
 	convs->sheet_name_sep		= '!';
 	convs->intersection_char	= ' ';
+	convs->exp_is_left_associative  = FALSE;
 	convs->input.range_ref		= rangeref_parse;
 	convs->input.name		= std_name_parser;
 	convs->input.func		= std_func_map;
diff --git a/src/parse-util.h b/src/parse-util.h
index 5583264..df8cf3c 100644
--- a/src/parse-util.h
+++ b/src/parse-util.h
@@ -130,6 +130,9 @@ struct _GnmConventions {
 	/* Accept prefix #NOT# and infixs #AND# and #OR#.  */
 	gboolean accept_hash_logicals;
 
+	/* If TRUE, parse x^y^z as (x^y)^z.  */
+	gboolean exp_is_left_associative;
+
 /* Import specific functions ------------------------------------- */
 	struct {
 		/* Called a lot for anything that might be a reference.  */
diff --git a/src/parser.y b/src/parser.y
index 2c4b491..8c3ec03 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -327,6 +327,27 @@ build_not (GnmExpr *expr)
 		(gnm_expr_new_funcall1 (not_func, expr));
 }
 
+static GnmExpr *
+build_exp (GnmExpr *l, GnmExpr *r)
+{
+	if (is_signed (l)) {
+		/* See bug 115941 */
+		l = build_unary_op (GNM_EXPR_OP_PAREN, l);
+	}
+
+	if (GNM_EXPR_GET_OPER (l) == GNM_EXPR_OP_EXP) {
+		/* Add ()s to x^y^z */
+		l = build_unary_op (GNM_EXPR_OP_PAREN, l);
+	}
+
+	if (GNM_EXPR_GET_OPER (r) == GNM_EXPR_OP_EXP) {
+		/* Add ()s to x^y^z */
+		r = build_unary_op (GNM_EXPR_OP_PAREN, r);
+	}
+
+	return build_binop (l, GNM_EXPR_OP_EXP, r);
+}
+
 /*
  * Build an array expression.
  *
@@ -560,7 +581,8 @@ int yyparse (void);
 %left '&'
 %left '-' '+'
 %left '*' '/'
-%right '^'
+%right RIGHT_EXP_TOKEN
+%left LEFT_EXP_TOKEN
 %nonassoc '%'
 %nonassoc NEG PLUS NOT
 %left AND OR
@@ -603,28 +625,8 @@ exp:	  CONSTANT 	{ $$ = $1; }
 	| exp '-' exp	{ $$ = build_binop ($1, GNM_EXPR_OP_SUB,	$3); }
 	| exp '*' exp	{ $$ = build_binop ($1, GNM_EXPR_OP_MULT,	$3); }
 	| exp '/' exp	{ $$ = build_binop ($1, GNM_EXPR_OP_DIV,	$3); }
-	| exp '^' exp	{
-		GnmExpr *l = $1;
-		GnmExpr *r = $3;
-
-		if (is_signed (l)) {
-			/* See bug 115941 */
-			l = build_unary_op (GNM_EXPR_OP_PAREN, l);
-		}
-
-		if (GNM_EXPR_GET_OPER (l) == GNM_EXPR_OP_EXP) {
-			/* Add ()s to x^y^z */
-			/* I don't think this can currently happen.  */
-			l = build_unary_op (GNM_EXPR_OP_PAREN, l);
-		}
-
-		if (GNM_EXPR_GET_OPER (r) == GNM_EXPR_OP_EXP) {
-			/* Add ()s to x^y^z */
-			r = build_unary_op (GNM_EXPR_OP_PAREN, r);
-		}
-
-		$$ = build_binop (l, GNM_EXPR_OP_EXP, r);
-	}
+	| exp RIGHT_EXP_TOKEN exp { $$ = build_exp ($1, $3); }
+	| exp LEFT_EXP_TOKEN exp { $$ = build_exp ($1, $3); }
 	| exp '&' exp	{ $$ = build_binop ($1, GNM_EXPR_OP_CAT,	$3); }
 	| exp '=' exp	{ $$ = build_binop ($1, GNM_EXPR_OP_EQUAL,	$3); }
 	| exp '<' exp	{ $$ = build_binop ($1, GNM_EXPR_OP_LT,		$3); }
@@ -1394,6 +1396,11 @@ yylex (void)
 		state->in_array--;
 		return c;
 
+	case '^':
+		return state->convs->exp_is_left_associative
+			? LEFT_EXP_TOKEN
+			: RIGHT_EXP_TOKEN;
+
 	case UNICODE_LOGICAL_NOT_C: return NOT;
 	case UNICODE_MINUS_SIGN_C: return '-';
 	case UNICODE_DIVISION_SLASH_C: return '/';



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]