Commit aa228a54 authored by Morten Welinder's avatar Morten Welinder

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

parent 31eeb936
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.
......
......@@ -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
......
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
......
......@@ -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 *
......
......@@ -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;
......
......@@ -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. */
......
......@@ -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 '/';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment