[gnumeric] Parsing: Make '^' left-associative in ODF files.
- From: Morten Welinder <mortenw src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnumeric] Parsing: Make '^' left-associative in ODF files.
- Date: Wed, 10 Jun 2009 21:47:18 -0400 (EDT)
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]