2 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6 * (C) 1998-2002 GNOME Foundation
7 * Copyright (C) 2002-2009 Morten Welinder
10 * Miguel de Icaza (miguel@gnu.org)
11 * Jody Goldberg (jody@gnome.org)
12 * Morten Welinder (terra@diku.dk)
13 * Almer S. Tigelaar (almer@gnome.org)
15 #include <gnumeric-config.h>
16 #include <glib/gi18n-lib.h>
18 #include "number-match.h"
20 #include "expr-impl.h"
21 #include "expr-name.h"
25 #include "gnm-format.h"
26 #include "application.h"
27 #include "parse-util.h"
31 #include <goffice/goffice.h>
39 /* ------------------------------------------------------------------------- */
40 /* Allocation with disposal-on-error */
43 * If some dork enters "=1+2+2*(1+" we have already allocated space for
44 * "1+2", "2", and "1" before the parser sees the syntax error and warps
45 * us to the error production in the "line" non-terminal.
47 * To make sure we can clean up, we register every allocation. On success,
48 * nothing should be left (except the final expression which is unregistered),
49 * but on failure we must free everything allocated.
51 * Note: there is some room left for optimisation here. Talk to terra@diku.dk
52 * before you set out to do it.
56 free_expr_list_list
(GSList
*list
)
59 for
(l
= list
; l
; l
= l
->next
)
60 gnm_expr_list_unref
(l
->data
);
64 typedef
void (*ParseDeallocator
) (void *);
65 static GPtrArray
*deallocate_stack
;
68 deallocate_init
(void)
70 deallocate_stack
= g_ptr_array_new
();
74 deallocate_uninit
(void)
76 g_ptr_array_free
(deallocate_stack
, TRUE
);
77 deallocate_stack
= NULL
;
85 for
(i
= 0; i
< (int)deallocate_stack
->len
; i
+= 2) {
86 ParseDeallocator freer
= g_ptr_array_index
(deallocate_stack
, i
+ 1);
87 freer
(g_ptr_array_index
(deallocate_stack
, i
));
90 g_ptr_array_set_size
(deallocate_stack
, 0);
94 deallocate_assert_empty
(void)
96 if
(deallocate_stack
->len
== 0)
99 g_warning
("deallocate_stack not empty as expected.");
104 register_allocation
(gpointer data
, ParseDeallocator freer
)
106 /* It's handy to be able to register and unregister NULLs. */
110 * There are really only a few different freers, so we
111 * could encode the freer in the lower bits of the data
112 * pointer. Unfortunately, no-one can predict how high
113 * Miguel would jump when he found out.
115 len
= deallocate_stack
->len
;
116 g_ptr_array_set_size
(deallocate_stack
, len
+ 2);
117 g_ptr_array_index
(deallocate_stack
, len
) = data
;
118 g_ptr_array_index
(deallocate_stack
, len
+ 1) = freer
;
121 /* Returning the pointer here improved readability of the caller. */
125 #define register_expr_allocation(expr) \
126 register_allocation
((gpointer
)(expr
), (ParseDeallocator
)&gnm_expr_free
)
128 #define register_expr_list_allocation(list) \
129 register_allocation
((list
), (ParseDeallocator
)&gnm_expr_list_unref
)
131 #define register_expr_list_list_allocation(list) \
132 register_allocation
((list
), (ParseDeallocator
)&free_expr_list_list
)
135 unregister_allocation
(void const *data
)
139 /* It's handy to be able to register and unregister NULLs. */
143 pos
= deallocate_stack
->len
- 2;
144 if
(pos
>= 0 && data
== g_ptr_array_index
(deallocate_stack
, pos
)) {
145 g_ptr_array_set_size
(deallocate_stack
, pos
);
150 * Bummer. In certain error cases, it is possible that the parser
151 * will reduce after it has discovered a token that will lead to an
152 * error. "2/16/1800 00:00" (without the quotes) is an example.
153 * The first "00" is registered before the second division is
156 * Another example is 564077 where we deallocate out of order.
158 * This isn't a big deal -- we will just look at the entries below
161 for
(i
= pos
- 2; i
>= 0; i
-= 2) {
162 if
(data
== g_ptr_array_index
(deallocate_stack
, i
)) {
163 g_ptr_array_remove_index
(deallocate_stack
, i
);
164 g_ptr_array_remove_index
(deallocate_stack
, i
);
169 g_warning
("Unbalanced allocation registration");
172 /* ------------------------------------------------------------------------- */
174 /* Bison/Yacc internals */
175 static int yylex (void);
176 static int yyerror (char const *s
);
179 char const *ptr
; /* current position of the lexer */
180 char const *start
; /* start of the expression */
182 /* Location where the parsing is taking place */
183 GnmParsePos
const *pos
;
185 /* loaded from convs with locale specific mappings */
186 gunichar decimal_point
;
189 gunichar array_col_sep
;
190 gunichar array_row_sep
;
191 /* if arg_sep conflicts with array_col_sep or array_row_sep */
192 int in_array_sep_is
; /* token id */
194 GnmExprParseFlags flags
;
195 GnmConventions
const *convs
;
198 int in_array
; /* toggled in the lexer for '{' and '}' */
201 GnmParseError
*error;
204 /* The error returned from the */
205 static ParserState
*state
;
208 report_err
(ParserState
*state
, GError
*err
,
209 char const *last
, int guesstimate_of_length
)
211 if
(state
->error != NULL
) {
212 state
->error->err
= err
;
213 state
->error->end_char
= last
- state
->start
;
214 state
->error->begin_char
= state
->error->end_char
- guesstimate_of_length
;
215 if
(state
->error->begin_char
< 0)
216 state
->error->begin_char
= 0;
222 is_signed
(const GnmExpr
*expr
)
224 if
(GNM_EXPR_GET_OPER
(expr
) == GNM_EXPR_OP_UNARY_NEG
)
227 if
(GNM_EXPR_GET_OPER
(expr
) == GNM_EXPR_OP_UNARY_PLUS
)
230 if
(GNM_EXPR_GET_OPER
(expr
) == GNM_EXPR_OP_CONSTANT
) {
231 GnmValue
const *v
= expr
->constant.value
;
232 return VALUE_IS_FLOAT
(v
) && value_get_as_float
(v
) < 0;
238 /* Handle -cst for use in arrays. Don't handle other types here. */
240 fold_negative_constant
(GnmExpr
*expr
)
242 if
(expr
&& GNM_EXPR_GET_OPER
(expr
) == GNM_EXPR_OP_CONSTANT
) {
243 GnmValue
*v
= (GnmValue
*)expr
->constant.value
;
245 if
(VALUE_IS_FLOAT
(v
)) {
246 gnm_float f
= value_get_as_float
(v
);
247 expr
->constant.value
= value_new_float
(0 - f
);
256 /* Handle +cst for use in arrays. Don't handle other types here. */
258 fold_positive_constant
(GnmExpr
*expr
)
260 if
(expr
&& GNM_EXPR_GET_OPER
(expr
) == GNM_EXPR_OP_CONSTANT
) {
261 const GnmValue
*v
= expr
->constant.value
;
262 if
(VALUE_IS_FLOAT
(v
))
270 build_unary_op
(GnmExprOp op
, GnmExpr
*expr
)
272 if
(!expr
) return NULL
;
274 unregister_allocation
(expr
);
275 return register_expr_allocation
(gnm_expr_new_unary
(op
, expr
));
279 build_binop
(GnmExpr
*l
, GnmExprOp op
, GnmExpr
*r
)
281 if
(!l ||
!r
) return NULL
;
283 unregister_allocation
(r
);
284 unregister_allocation
(l
);
285 return register_expr_allocation
(gnm_expr_new_binary
(l
, op
, r
));
289 build_logical
(GnmExpr
*l
, gboolean is_and
, GnmExpr
*r
)
291 static GnmFunc
*and_func
= NULL
, *or_func
= NULL
;
293 if
(!l ||
!r
) return NULL
;
295 if
(and_func
== NULL
)
296 and_func
= gnm_func_lookup
("AND", NULL
);
298 or_func
= gnm_func_lookup
("OR", NULL
);
300 unregister_allocation
(r
);
301 unregister_allocation
(l
);
302 return register_expr_allocation
303 (gnm_expr_new_funcall2
(is_and ? and_func
: or_func
, l
, r
));
307 build_not
(GnmExpr
*expr
)
309 static GnmFunc
*not_func
= NULL
;
311 if
(!expr
) return NULL
;
313 if
(not_func
== NULL
)
314 not_func
= gnm_func_lookup
("NOT", NULL
);
315 unregister_allocation
(expr
);
316 return register_expr_allocation
317 (gnm_expr_new_funcall1
(not_func
, expr
));
321 build_exp
(GnmExpr
*l
, GnmExpr
*r
)
325 l
= build_unary_op
(GNM_EXPR_OP_PAREN
, l
);
328 if
(GNM_EXPR_GET_OPER
(l
) == GNM_EXPR_OP_EXP
) {
329 /* Add ()s to x^y^z */
330 l
= build_unary_op
(GNM_EXPR_OP_PAREN
, l
);
333 if
(GNM_EXPR_GET_OPER
(r
) == GNM_EXPR_OP_EXP
) {
334 /* Add ()s to x^y^z */
335 r
= build_unary_op
(GNM_EXPR_OP_PAREN
, r
);
338 return build_binop
(l
, GNM_EXPR_OP_EXP
, r
);
342 * Build an array expression.
344 * Returns NULL on failure. Caller must YYERROR in that case.
347 build_array
(GSList
*cols
)
353 report_err
(state
, g_error_new
(1, PERR_INVALID_EMPTY
,
354 _
("An array must have at least 1 element")),
359 mx
= g_list_length
(cols
->data
);
360 array
= value_new_array_empty
(mx
, g_slist_length
(cols
));
364 GSList
*row
= cols
->data
;
366 while
(row
&& x
< mx
) {
367 GnmExpr
const *expr
= row
->data
;
368 GnmValue
const *v
= expr
->constant.value
;
370 g_assert
(expr
&& GNM_EXPR_GET_OPER
(expr
) == GNM_EXPR_OP_CONSTANT
);
372 value_array_set
(array
, x
, y
, value_dup
(v
));
378 /* parser_error = PARSE_ERR_SYNTAX; */
379 report_err
(state
, g_error_new
(1, PERR_ASYMETRIC_ARRAY
,
380 _
("Arrays must be rectangular")),
382 value_release
(array
);
389 return register_expr_allocation
(gnm_expr_new_constant
(array
));
393 * Build a range constructor.
395 * Returns NULL on failure. Caller must YYERROR in that case.
398 build_range_ctor
(GnmExpr
*l
, GnmExpr
*r
, GnmExpr
*validate
)
400 if
(!l ||
!r
) return NULL
;
402 if
(validate
!= NULL
) {
403 if
(GNM_EXPR_GET_OPER
(validate
) != GNM_EXPR_OP_CELLREF ||
404 validate
->cellref.ref.sheet
!= NULL
) {
405 report_err
(state
, g_error_new
(1, PERR_UNEXPECTED_TOKEN
,
406 _
("Constructed ranges use simple references")),
412 unregister_allocation
(r
);
413 unregister_allocation
(l
);
414 return register_expr_allocation
(gnm_expr_new_range_ctor
(l
, r
));
418 * Build an intersection expression.
420 * Returns NULL on failure. Caller must YYERROR in that case.
423 build_intersect
(GnmExpr
*l
, GnmExpr
*r
)
425 if
(!l ||
!r
) return NULL
;
427 if
(gnm_expr_is_rangeref
(l
) && gnm_expr_is_rangeref
(r
))
428 return build_binop
(l
, GNM_EXPR_OP_INTERSECT
, r
);
429 report_err
(state
, g_error_new
(1, PERR_SET_CONTENT_MUST_BE_RANGE
,
430 _
("All entries in the set must be references")),
436 * Build a set expression.
438 * Returns NULL on failure. Caller must YYERROR in that case.
441 build_set
(GnmExprList
*list
)
443 /* verify that every thing is a ref */
445 for
(ptr
= list
; ptr
!= NULL
; ptr
= ptr
->next
) {
446 GnmExpr
const *expr
= ptr
->data
;
447 if
(!expr ||
!gnm_expr_is_rangeref
(expr
)) {
448 report_err
(state
, g_error_new
(1, PERR_SET_CONTENT_MUST_BE_RANGE
,
449 _
("All entries in the set must be references")),
455 unregister_allocation
(list
);
456 return register_expr_allocation
(gnm_expr_new_set
(list
));
460 * parse_string_as_value :
462 * Try to parse the entered text as a basic value (empty, bool, int,
463 * gnm_float, err) if this succeeds, we store this as a GnmValue otherwise, we
467 parse_string_as_value
(GnmExpr
*str
)
469 GnmValue
*v
= format_match_simple
(value_peek_string
(str
->constant.value
));
472 unregister_allocation
(str
);
474 return register_expr_allocation
(gnm_expr_new_constant
(v
));
479 static const GnmExpr
*
480 parser_simple_name
(const char *str
, Sheet
*sheet
)
487 parse_pos_init_sheet
(&pp
, sheet
);
488 nexpr
= expr_name_lookup
(&pp
, str
);
490 nexpr
= expr_name_lookup
(state
->pos
, str
);
493 if
(state
->flags
& GNM_EXPR_PARSE_UNKNOWN_NAMES_ARE_INVALID
) {
496 ? g_error_new
(1, PERR_UNKNOWN_NAME
,
497 _
("Name '%s' does not exist in sheet '%s'"),
498 str
, sheet
->name_quoted
)
499 : g_error_new
(1, PERR_UNKNOWN_NAME
,
500 _
("Name '%s' does not exist"),
502 report_err
(state
, e
, state
->ptr
, 0);
504 } else if
(!sheet
&& state
->flags
& GNM_EXPR_PARSE_UNKNOWN_NAMES_ARE_STRINGS
) {
505 res
= gnm_expr_new_constant
(value_new_string
(str
));
506 } else if
(state
->convs
->input.name_validate
(str
)) {
507 GnmParsePos pp
= *state
->pos
;
509 /* Create a place holder */
510 nexpr
= expr_name_add
(&pp
, str
, NULL
, NULL
, TRUE
, NULL
);
511 res
= gnm_expr_new_name
(nexpr
, sheet
, NULL
);
513 report_err
(state
, g_error_new
(1, PERR_UNKNOWN_NAME
,
514 _
("'%s' cannot be used as a name"),
520 res
= gnm_expr_new_name
(nexpr
, sheet
, NULL
);
526 * parser_simple_val_or_name :
527 * @str : An expression with oper constant, whose value is a string.
529 * Check to see if a string is a simple value or failing that a named
530 * expression, if it is not create a placeholder name for it.
533 parser_simple_val_or_name
(GnmExpr
*str_expr
)
536 char const *str
= value_peek_string
(str_expr
->constant.value
);
537 GnmValue
*v
= format_match_simple
(str
);
539 /* if it is not a simple value see if it is a name */
541 res
= parser_simple_name
(str
, NULL
);
543 res
= gnm_expr_new_constant
(v
);
545 unregister_allocation
(str_expr
);
546 gnm_expr_free
(str_expr
);
547 return register_expr_allocation
(res
);
551 parser_sheet_by_name
(Workbook
*wb
, GnmExpr
*name_expr
)
553 char const *name
= value_peek_string
(name_expr
->constant.value
);
559 sheet
= workbook_sheet_by_name
(wb
, name
);
561 /* Applix has absolute and relative sheet references */
562 if
(sheet
== NULL
&& *name
== '$' &&
563 state
->convs
->allow_absolute_sheet_references
)
564 sheet
= workbook_sheet_by_name
(wb
, name
+ 1);
567 /* TODO : length is broken in the context of quoted names or
568 * names with escaped character */
569 /* -1 is a kludge. We know that this routine is only called
570 * when the last token was SHEET_SEP */
571 report_err
(state
, g_error_new
(1, PERR_UNKNOWN_SHEET
,
572 _
("Unknown sheet '%s'"), name
),
573 state
->ptr
-1, strlen
(name
));
578 /* Make byacc happier */
579 static int yyparse (void);
591 %type
<list
> opt_exp arg_list array_row array_rows
592 %type
<expr
> exp array_exp function string_opt_quote cellref
593 %token
<expr
> STRING QUOTED_STRING CONSTANT RANGEREF tok_GTE tok_LTE tok_NE tok_AND tok_OR tok_NOT INTERSECT
594 %token ARG_SEP ARRAY_COL_SEP ARRAY_ROW_SEP SHEET_SEP INVALID_TOKEN
595 %type
<sheet
> sheetref
596 %type
<wb
> workbookref
597 %token
<wb
> tok_WORKBOOKREF
599 %left
'<' '>' '=' tok_GTE tok_LTE tok_NE
606 %nonassoc tok_NEG tok_PLUS tok_NOT
609 %left RANGE_INTERSECT
614 unregister_allocation
($2);
615 unregister_allocation
($1);
616 state
->result
= gnm_expr_list_prepend
($1, $2);
620 if
(state
->result
!= NULL
) {
621 gnm_expr_list_unref
(state
->result
);
622 state
->result
= NULL
;
627 opt_exp
: opt_exp exp ARG_SEP
{
628 unregister_allocation
($2);
629 unregister_allocation
($1);
630 $$
= gnm_expr_list_prepend
($1, $2);
631 register_expr_list_allocation
($$
);
633 |
{ $$
= NULL
; register_expr_list_allocation
($$
); }
636 exp: CONSTANT
{ $$
= $1; }
637 | QUOTED_STRING
{ $$
= $1; }
639 $$
= parser_simple_val_or_name
($1);
640 if
($$
== NULL
) { YYERROR; }
642 | cellref
{ $$
= $1; }
643 | exp
'+' exp
{ $$
= build_binop
($1, GNM_EXPR_OP_ADD
, $3); }
644 | exp
'-' exp
{ $$
= build_binop
($1, GNM_EXPR_OP_SUB
, $3); }
645 | exp
'*' exp
{ $$
= build_binop
($1, GNM_EXPR_OP_MULT
, $3); }
646 | exp
'/' exp
{ $$
= build_binop
($1, GNM_EXPR_OP_DIV
, $3); }
647 | exp tok_RIGHT_EXP exp
{ $$
= build_exp
($1, $3); }
648 | exp tok_LEFT_EXP exp
{ $$
= build_exp
($1, $3); }
649 | exp
'&' exp
{ $$
= build_binop
($1, GNM_EXPR_OP_CAT
, $3); }
650 | exp
'=' exp
{ $$
= build_binop
($1, GNM_EXPR_OP_EQUAL
, $3); }
651 | exp
'<' exp
{ $$
= build_binop
($1, GNM_EXPR_OP_LT
, $3); }
652 | exp
'>' exp
{ $$
= build_binop
($1, GNM_EXPR_OP_GT
, $3); }
653 | exp tok_GTE exp
{ $$
= build_binop
($1, GNM_EXPR_OP_GTE
, $3); }
654 | exp tok_NE exp
{ $$
= build_binop
($1, GNM_EXPR_OP_NOT_EQUAL
, $3); }
655 | exp tok_LTE exp
{ $$
= build_binop
($1, GNM_EXPR_OP_LTE
, $3); }
656 | exp tok_AND exp
{ $$
= build_logical
($1, TRUE
, $3); }
657 | exp tok_OR exp
{ $$
= build_logical
($1, FALSE
, $3); }
658 | exp RANGE_INTERSECT exp
{
659 $$
= build_intersect
($1, $3);
660 if
($$
== NULL
) { YYERROR; }
663 |
'-' exp %prec tok_NEG
{
664 GnmExpr
*tmp
= fold_negative_constant
($2);
665 $$
= tmp ? tmp
: build_unary_op
(GNM_EXPR_OP_UNARY_NEG
, $2);
667 |
'+' exp %prec tok_PLUS
{
668 /* Don't fold here. */
669 $$
= build_unary_op
(GNM_EXPR_OP_UNARY_PLUS
, $2);
671 | tok_NOT exp
{ $$
= build_not
($2); }
672 | exp
'%' { $$
= build_unary_op
(GNM_EXPR_OP_PERCENTAGE
, $1); }
676 report_err
(state
, g_error_new
(1, PERR_INVALID_EMPTY
,
677 _
("() is an invalid expression")),
681 if
($2->next
== NULL
) {
682 unregister_allocation
($2);
683 $$
= register_expr_allocation
(gnm_expr_new_unary
(GNM_EXPR_OP_PAREN
, $2->data
));
684 /* NOTE : free list not content */
685 gnm_expr_list_free
($2);
688 if
($$
== NULL
) { YYERROR; }
692 |
'{' array_rows
'}' {
693 unregister_allocation
($2);
694 $$
= build_array
($2);
695 free_expr_list_list
($2);
696 if
($$
== NULL
) { YYERROR; }
701 char const *name
= value_peek_string
($2->constant.value
);
702 GnmExpr
const *ename
= parser_simple_name
(name
, $1);
705 unregister_allocation
($2); gnm_expr_free
($2);
706 $$
= register_expr_allocation
(ename
);
711 | workbookref STRING
{
712 GnmNamedExpr
*nexpr
= NULL
;
713 char const *name
= value_peek_string
($2->constant.value
);
714 GnmParsePos pos
= *state
->pos
;
718 nexpr
= expr_name_lookup
(&pos
, name
);
720 unregister_allocation
($2); gnm_expr_free
($2);
721 $$
= register_expr_allocation
(gnm_expr_new_name
(nexpr
, NULL
, $1));
723 report_err
(state
, g_error_new
(1, PERR_UNKNOWN_NAME
,
724 _
("Name '%s' does not exist in workbook"),
726 state
->ptr
, strlen
(name
));
732 function
: STRING
'(' arg_list
')' {
733 char const *name
= value_peek_string
($1->constant.value
);
734 GnmExpr
const *f_call
= (*state
->convs
->input.func
) (
735 state
->convs
, state
->pos
->wb
, name
, $3);
739 /* We're done with the function name. */
740 unregister_allocation
($1); gnm_expr_free
($1);
741 unregister_allocation
($3);
742 $$
= register_expr_allocation
(f_call
);
749 string_opt_quote
: STRING
753 opt_sheet_sep
: SHEET_SEP
756 /* only used for names */
757 workbookref
: tok_WORKBOOKREF opt_sheet_sep
758 |
'[' string_opt_quote
']' {
759 char const *wb_name
= value_peek_string
($2->constant.value
);
760 Workbook
*ref_wb
= state
->pos
764 ? state
->pos
->sheet
->workbook
768 state
->convs
->input.external_wb
(state
->convs
,
773 unregister_allocation
($2); gnm_expr_free
($2);
776 /* kludge to produce better error messages
777 * we know that the last token read will be the ']'
780 report_err
(state
, g_error_new
(1, PERR_UNKNOWN_WORKBOOK
,
781 _
("Unknown workbook '%s'"), wb_name
),
782 state
->ptr
- 1, strlen
(wb_name
));
787 /* Special syntax for global names shadowed by sheet names. */
788 Workbook
*wb
= state
->pos
792 ? state
->pos
->sheet
->workbook
797 report_err
(state
, g_error_new
(1, PERR_UNKNOWN_WORKBOOK
,
798 _
("Unknown workbook")),
805 /* does not need to handle 3d case. this is only used for names.
806 * 3d cell references are handled in the lexer
808 sheetref: string_opt_quote SHEET_SEP
{
809 Sheet
*sheet
= parser_sheet_by_name
(state
->pos
->wb
, $1);
811 unregister_allocation
($1); gnm_expr_free
($1);
817 | workbookref string_opt_quote SHEET_SEP
{
819 Sheet
*sheet
= parser_sheet_by_name
(wb
, $2);
821 unregister_allocation
($2); gnm_expr_free
($2);
829 cellref: RANGEREF
{ $$
= $1; }
830 | function RANGE_SEP function
{
831 $$
= build_range_ctor
($1, $3, NULL
);
832 if
($$
== NULL
) { YYERROR; }
834 | RANGEREF RANGE_SEP function
{
835 $$
= build_range_ctor
($1, $3, $1);
836 if
($$
== NULL
) { YYERROR; }
838 | function RANGE_SEP RANGEREF
{
839 $$
= build_range_ctor
($1, $3, $3);
840 if
($$
== NULL
) { YYERROR; }
842 | RANGEREF RANGE_SEP RANGEREF
{
843 $$
= build_range_ctor
($1, $3, NULL
);
844 if
($$
== NULL
) { YYERROR; }
849 unregister_allocation
($1);
850 $$
= gnm_expr_list_prepend
(NULL
, $1);
851 register_expr_list_allocation
($$
);
853 | exp ARG_SEP arg_list
{
855 unregister_allocation
($3);
856 unregister_allocation
($1);
859 tmp
= gnm_expr_list_prepend
(NULL
, gnm_expr_new_constant
(value_new_empty
()));
861 $$
= gnm_expr_list_prepend
(tmp
, $1);
862 register_expr_list_allocation
($$
);
866 unregister_allocation
($2);
869 tmp
= gnm_expr_list_prepend
(NULL
, gnm_expr_new_constant
(value_new_empty
()));
871 $$
= gnm_expr_list_prepend
(tmp
, gnm_expr_new_constant
(value_new_empty
()));
872 register_expr_list_allocation
($$
);
877 array_exp: CONSTANT
{ $$
= $1; }
879 GnmExpr
*tmp
= fold_negative_constant
($2);
880 if
(!tmp
) { YYERROR; }
884 GnmExpr
*tmp
= fold_positive_constant
($2);
885 if
(!tmp
) { YYERROR; }
888 | string_opt_quote
{ $$
= parse_string_as_value
($1); }
892 array_row
: { $$
= NULL
; }
894 unregister_allocation
($1);
895 $$
= g_slist_prepend
(NULL
, $1);
896 register_expr_list_allocation
($$
);
898 | array_exp ARRAY_COL_SEP array_row
{
899 unregister_allocation
($3);
900 unregister_allocation
($1);
901 $$
= g_slist_prepend
($3, $1);
902 register_expr_list_allocation
($$
);
906 array_rows: array_row
{
907 unregister_allocation
($1);
908 $$
= g_slist_prepend
(NULL
, $1);
909 register_expr_list_list_allocation
($$
);
911 | array_row ARRAY_ROW_SEP array_rows
{
912 unregister_allocation
($3);
913 unregister_allocation
($1);
914 $$
= g_slist_prepend
($3, $1);
915 register_expr_list_list_allocation
($$
);
922 find_matching_close
(char const *str
, char const **res
)
926 char const *tmp
= str
;
927 str
= find_matching_close
(str
+ 1, res
);
928 if
(*str
!= ')' && *res
== NULL
) {
934 } else if
(*str
== ')')
936 else if
(*str
== '\'' ||
*str
== '\"') {
937 GString
*dummy
= g_string_new
(NULL
);
938 char const *end
= go_strunescape
(dummy
, str
);
939 g_string_free
(dummy
, TRUE
);
941 return str
+ strlen
(str
);
943 continue
; /* skip incrementing str */
945 str
= g_utf8_next_char
(str
);
952 eat_space
(ParserState
*state
, int res
)
954 /* help the user by ignoring pointless spaces after an
955 * arg_sep. We know they are going to be errors and
956 * the spaces can not be operators in this context */
957 while
(*state
->ptr
== ' ')
963 * Do we want to ignore space before a given character?
966 ignore_space_before
(gunichar c
)
969 case
'*': case
'/': case
'+': case
'-': case
'%': case
'^': case
'&':
970 case
'>': case
'<': case
'=':
973 case
'"': case
'\'': /* Refers to opening quote only. */
974 case UNICODE_LOGICAL_NOT_C
:
975 case UNICODE_LOGICAL_AND_C
:
976 case UNICODE_LOGICAL_OR_C
:
977 case UNICODE_MINUS_SIGN_C
:
978 case UNICODE_DIVISION_SLASH_C
:
979 case UNICODE_NOT_EQUAL_TO_C
:
980 case UNICODE_LESS_THAN_OR_EQUAL_TO_C
:
981 case UNICODE_GREATER_THAN_OR_EQUAL_TO_C
:
990 * Do we want to ignore space after a given character?
993 ignore_space_after
(gunichar c
)
996 case
'*': case
'/': case
'+': case
'-': case
'%': case
'^': case
'&':
997 case
'>': case
'<': case
'=':
999 case
'"': case
'\'': /* Refers to closing quote only [not actually hit]. */
1000 case UNICODE_LOGICAL_NOT_C
:
1001 case UNICODE_LOGICAL_AND_C
:
1002 case UNICODE_LOGICAL_OR_C
:
1003 case UNICODE_MINUS_SIGN_C
:
1004 case UNICODE_DIVISION_SLASH_C
:
1005 case UNICODE_NOT_EQUAL_TO_C
:
1006 case UNICODE_LESS_THAN_OR_EQUAL_TO_C
:
1007 case UNICODE_GREATER_THAN_OR_EQUAL_TO_C
:
1016 open_paren
(const char *p
)
1018 while
(g_unichar_isspace
(g_utf8_get_char
(p
)))
1019 p
= g_utf8_next_char
(p
);
1027 char const *start
, *end
;
1029 gboolean is_number
= FALSE
;
1030 gboolean is_space
= FALSE
;
1031 gboolean error_token
= FALSE
;
1034 * Some special logic to handle space as intersection char.
1035 * Any number of white space characters are treated as one
1038 * Also, if we are not using space for that, drop spaces.
1040 while
(g_unichar_isspace
(g_utf8_get_char
(state
->ptr
))) {
1041 state
->ptr
= g_utf8_next_char
(state
->ptr
);
1044 if
(is_space
&& state
->convs
->intersection_char
== ' ' &&
1045 !ignore_space_before
(g_utf8_get_char
(state
->ptr
)))
1046 return RANGE_INTERSECT
;
1049 c
= g_utf8_get_char
(start
);
1052 state
->ptr
= g_utf8_next_char
(state
->ptr
);
1054 if
(c
== state
->convs
->intersection_char
)
1055 return RANGE_INTERSECT
;
1057 if
(c
== '&' && state
->convs
->decode_ampersands
) {
1058 if
(!strncmp
(state
->ptr
, "amp;", 4)) {
1063 if
(!strncmp
(state
->ptr
, "lt;", 3)) {
1065 if
(*state
->ptr
== '='){
1069 if
(!strncmp
(state
->ptr
, ">", 4)) {
1075 if
(!strncmp
(state
->ptr
, "gt;", 3)) {
1077 if
(*state
->ptr
== '='){
1083 if
(!strncmp
(state
->ptr
, "apos;", 5) ||
1084 !strncmp
(state
->ptr
, "quot;", 5)) {
1085 char const *quotes_end
;
1090 if
(*state
->ptr
== 'q') {
1091 quotes_end
= """;
1094 quotes_end
= "'";
1101 state
->ptr
= strstr
(state
->ptr
, quotes_end
);
1103 report_err
(state
, g_error_new
(1, PERR_MISSING_CLOSING_QUOTE
,
1104 _
("Could not find matching closing quote")),
1106 return INVALID_TOKEN
;
1108 if
(!strncmp
(state
->ptr
+ 6, quotes_end
, 6)) {
1109 state
->ptr
+= 2 * 6;
1110 goto double_quote_loop
;
1113 s
= string = g_malloc
(1 + state
->ptr
- p
);
1114 while
(p
!= state
->ptr
) {
1116 if
(!strncmp
(p
, "&", 5)) {
1120 } else if
(!strncmp
(p
, "<", 4)) {
1124 } else if
(!strncmp
(p
, ">", 4)) {
1128 } else if
(!strncmp
(p
, quotes_end
, 6)) {
1129 p
+= 12; /* two in a row is the escape mechanism */
1132 } else if
(!strncmp
(p
, """, 6)) {
1136 } else if
(!strncmp
(p
, "'", 6)) {
1148 v
= value_new_string_nocopy
(string);
1149 yylval.expr
= register_expr_allocation
(gnm_expr_new_constant
(v
));
1150 return QUOTED_STRING
;
1154 if
(c
== ':' && state
->convs
->range_sep_colon
)
1155 return eat_space
(state
, RANGE_SEP
);
1157 if
(c
== state
->convs
->sheet_name_sep
)
1158 return eat_space
(state
, SHEET_SEP
);
1160 if
(c
== '.' && *state
->ptr
== '.' && state
->convs
->range_sep_dotdot
) {
1165 if
(c
== '#' && state
->convs
->accept_hash_logicals
) {
1166 if
(!strncmp
(state
->ptr
, "NOT#", 4)) {
1168 return eat_space
(state
, tok_NOT
);
1170 if
(!strncmp
(state
->ptr
, "AND#", 4)) {
1172 return eat_space
(state
, tok_AND
);
1174 if
(!strncmp
(state
->ptr
, "OR#", 3)) {
1176 return eat_space
(state
, tok_OR
);
1180 if
(c
== state
->arg_sep
)
1181 return eat_space
(state
, state
->in_array ? state
->in_array_sep_is
: ARG_SEP
);
1182 if
((c
== state
->union_char
) && (state
->union_char
!= 0))
1183 return eat_space
(state
, ARG_SEP
);
1184 if
(c
== state
->array_col_sep
)
1185 return eat_space
(state
, ARRAY_COL_SEP
);
1186 if
(c
== state
->array_row_sep
)
1187 return eat_space
(state
, ARRAY_ROW_SEP
);
1189 end
= state
->convs
->input.range_ref
(&ref
, start
,
1190 state
->pos
, state
->convs
);
1192 * In order to parse "LOG10(1024)" in sheets with more than ~8500
1193 * columns we do not consider anything a rangeref if it is followed
1194 * by an opening parenthesis.
1196 if
(start
!= end
&& !open_paren
(end
)) {
1198 if
(invalid_sheet
== ref.a.sheet
) {
1199 yylval.expr
= register_expr_allocation
1200 (gnm_expr_new_constant
1201 (value_new_error_REF
(NULL
)));
1204 if
(state
->flags
& GNM_EXPR_PARSE_FORCE_ABSOLUTE_REFERENCES
) {
1205 if
(ref.a.col_relative
) {
1206 ref.a.col
+= state
->pos
->eval.col
;
1207 ref.a.col_relative
= FALSE
;
1209 if
(ref.b.col_relative
) {
1210 ref.b.col
+= state
->pos
->eval.col
;
1211 ref.b.col_relative
= FALSE
;
1213 if
(ref.a.row_relative
) {
1214 ref.a.row
+= state
->pos
->eval.row
;
1215 ref.a.row_relative
= FALSE
;
1217 if
(ref.b.row_relative
) {
1218 ref.b.row
+= state
->pos
->eval.row
;
1219 ref.b.row_relative
= FALSE
;
1221 } else if
(state
->flags
& GNM_EXPR_PARSE_FORCE_RELATIVE_REFERENCES
) {
1222 if
(!ref.a.col_relative
) {
1223 ref.a.col
-= state
->pos
->eval.col
;
1224 ref.a.col_relative
= TRUE
;
1226 if
(!ref.b.col_relative
) {
1227 ref.b.col
-= state
->pos
->eval.col
;
1228 ref.b.col_relative
= TRUE
;
1230 if
(!ref.a.row_relative
) {
1231 ref.a.row
-= state
->pos
->eval.row
;
1232 ref.a.row_relative
= TRUE
;
1234 if
(!ref.b.row_relative
) {
1235 ref.b.row
-= state
->pos
->eval.row
;
1236 ref.b.row_relative
= TRUE
;
1240 if
(ref.a.sheet
== NULL
&& (state
->flags
& GNM_EXPR_PARSE_FORCE_EXPLICIT_SHEET_REFERENCES
)) {
1241 ref.a.sheet
= state
->pos
->sheet
;
1242 if
(ref.a.sheet
== NULL
) {
1243 report_err
(state
, g_error_new
(1, PERR_SHEET_IS_REQUIRED
,
1244 _
("Sheet name is required")),
1246 return INVALID_TOKEN
;
1250 if
((ref.b.sheet
== NULL || ref.b.sheet
== ref.a.sheet
) &&
1251 ref.a.col
== ref.b.col
&&
1252 ref.a.col_relative
== ref.b.col_relative
&&
1253 ref.a.row
== ref.b.row
&&
1254 ref.a.row_relative
== ref.b.row_relative
) {
1255 yylval.expr
= register_expr_allocation
(gnm_expr_new_cellref
(&ref.a
));
1258 yylval.expr
= register_expr_allocation
(gnm_expr_new_constant
(
1259 value_new_cellrange_unsafe
(&ref.a
, &ref.b
)));
1263 /* Do NOT handle negative numbers here. That has to be done in the
1264 * parser otherwise we mishandle A1-1 when it looks like
1265 * rangeref CONSTANT */
1266 if
(c
== state
->decimal_point
) {
1267 /* Could be a number or a stand alone */
1268 if
(!g_unichar_isdigit
(g_utf8_get_char
(state
->ptr
)))
1271 } else if
(g_unichar_isdigit
(c
)) {
1272 /* find the end of the first portion of the number */
1274 c
= g_utf8_get_char
(state
->ptr
);
1275 state
->ptr
= g_utf8_next_char
(state
->ptr
);
1276 } while
(g_unichar_isdigit
(c
));
1285 if
(c
== state
->decimal_point || c
== 'e' || c
== 'E') {
1286 /* This is a floating point number */
1291 d
= gnm_utf8_strto
(start
, &end
);
1293 g_warning
("%s is not a double, but was expected to be one", start
);
1294 } else if
(errno
!= ERANGE
) {
1295 v
= value_new_float
(d
);
1297 } else if
(c
!= 'e' && c
!= 'E') {
1298 report_err
(state
, g_error_new
(1, PERR_OUT_OF_RANGE
,
1299 _
("The number is out of range")),
1300 state
->ptr
, end
- start
);
1301 return INVALID_TOKEN
;
1303 /* For an exponent it's hard to highlight the
1304 * right region w/o it turning into an ugly
1305 * hack, for now the cursor is put at the end.
1307 report_err
(state
, g_error_new
(1, PERR_OUT_OF_RANGE
,
1308 _
("The number is out of range")),
1310 return INVALID_TOKEN
;
1316 l
= gnm_utf8_strtol
(start
, &end
);
1318 g_warning
("%s is not an integer, but was expected to be one", start
);
1319 } else if
(errno
!= ERANGE
&& l
>= INT_MIN
&& l
<= INT_MAX
) {
1320 v
= value_new_int
(l
);
1326 d
= gnm_utf8_strto
(start
, &end
);
1327 if
(errno
!= ERANGE
) {
1328 v
= value_new_float
(d
);
1331 report_err
(state
, g_error_new
(1, PERR_OUT_OF_RANGE
,
1332 _
("The number is out of range")),
1333 state
->ptr
, end
- start
);
1334 return INVALID_TOKEN
;
1339 /* Very odd string, Could be a bound problem. Trigger an error */
1343 yylval.expr
= register_expr_allocation
(gnm_expr_new_constant
(v
));
1349 if
(state
->ptr
[0] != '"') {
1350 while
((tmp
= g_utf8_get_char
(state
->ptr
)) != 0 &&
1351 !g_unichar_isspace
(tmp
)) {
1352 state
->ptr
= g_utf8_next_char
(state
->ptr
);
1353 if
(tmp
== '!' || tmp
== '?' ||
1354 ((state
->ptr
- start
) == 4 && 0 == strncmp
(start
, "#N/A", 4))) {
1355 GOString
*name
= go_string_new_nocopy
(g_strndup
(start
, state
->ptr
- start
));
1356 yylval.expr
= register_expr_allocation
1357 (gnm_expr_new_constant
(
1358 value_new_error_str
(NULL
, name
)));
1359 go_string_unref
(name
);
1364 report_err
(state
, g_error_new
1365 (1, PERR_UNEXPECTED_TOKEN
,
1366 _
("Improperly formatted error token")),
1367 state
->ptr
, state
->ptr
- start
);
1369 return INVALID_TOKEN
;
1376 GString
*s
= g_string_new
(NULL
);
1377 char const *end
= state
->convs
->input.
string (start
, s
, state
->convs
);
1380 size_t len
= strlen
(start
);
1381 g_string_free
(s
, TRUE
);
1383 g_error_new
(1, PERR_MISSING_CLOSING_QUOTE
,
1384 _
("Could not find matching closing quote")),
1386 return INVALID_TOKEN
;
1389 state
->ptr
= (char *)end
;
1392 GnmValue
*v
= value_new_error
(NULL
, s
->str
);
1393 yylval.expr
= register_expr_allocation
(gnm_expr_new_constant
(v
));
1394 g_string_free
(s
, TRUE
);
1395 return eat_space
(state
, CONSTANT
);
1397 GnmValue
*v
= value_new_string_nocopy
(g_string_free
(s
, FALSE
));
1398 yylval.expr
= register_expr_allocation
(gnm_expr_new_constant
(v
));
1399 return eat_space
(state
, QUOTED_STRING
);
1404 const char *p
= state
->ptr
;
1405 GString
*s
= g_string_new
(NULL
);
1406 Workbook
*ref_wb
= state
->pos
1409 : (state
->pos
->sheet
1410 ? state
->pos
->sheet
->workbook
1414 while
(g_unichar_isspace
(g_utf8_get_char
(p
)))
1415 p
= g_utf8_next_char
(p
);
1417 if
(p
[0] == '"' || p
[0] == '\'') {
1418 p
= go_strunescape
(s
, p
);
1422 uc
= g_utf8_get_char
(p
);
1423 if
(!uc || uc
== ']' || g_unichar_isspace
(uc
))
1425 p
= g_utf8_next_char
(p
);
1426 g_string_append_unichar
(s
, uc
);
1430 while
(p
&& g_unichar_isspace
(g_utf8_get_char
(p
)))
1431 p
= g_utf8_next_char
(p
);
1433 if
(s
->len
== 0 ||
!p || p
[0] != ']') {
1434 g_string_free
(s
, TRUE
);
1438 yylval.wb
= state
->convs
->input.external_wb
(state
->convs
,
1441 g_string_free
(s
, TRUE
);
1446 return tok_WORKBOOKREF
;
1450 if
((end
= state
->convs
->input.name
(start
, state
->convs
))) {
1452 yylval.expr
= register_expr_allocation
(gnm_expr_new_constant
(
1453 value_new_string_nocopy
(g_strndup
(start
, state
->ptr
- start
))));
1459 if
(*state
->ptr
== '='){
1461 return eat_space
(state
, tok_LTE
);
1463 if
(*state
->ptr
== '>'){
1465 return eat_space
(state
, tok_NE
);
1467 return eat_space
(state
, c
);
1470 if
(*state
->ptr
== '='){
1472 return eat_space
(state
, tok_GTE
);
1474 return eat_space
(state
, c
);
1476 case
'\n': return
0;
1486 return state
->convs
->exp_is_left_associative
1490 case UNICODE_LOGICAL_NOT_C
: return tok_NOT
;
1491 case UNICODE_MINUS_SIGN_C
: return
'-';
1492 case UNICODE_DIVISION_SLASH_C
: return
'/';
1493 case UNICODE_LOGICAL_AND_C
: return tok_AND
;
1494 case UNICODE_LOGICAL_OR_C
: return tok_OR
;
1495 case UNICODE_NOT_EQUAL_TO_C
: return eat_space
(state
, tok_NE
);
1496 case UNICODE_LESS_THAN_OR_EQUAL_TO_C
: return eat_space
(state
, tok_LTE
);
1497 case UNICODE_GREATER_THAN_OR_EQUAL_TO_C
: return eat_space
(state
, tok_GTE
);
1500 if
(ignore_space_after
(c
))
1501 return eat_space
(state
, c
);
1507 yyerror (char const *s
)
1510 g_printerr
("Error: %s\n", s
);
1516 setup_state
(ParserState
*pstate
, const char *str
,
1517 GnmParsePos
const *pp
,
1518 GnmExprParseFlags flags
,
1519 GnmConventions
const *convs
,
1520 GnmParseError
*error)
1522 pstate
->start
= pstate
->ptr
= str
;
1525 pstate
->flags
= flags
;
1527 (NULL
!= convs
) ? convs
: ((NULL
!= pp
->sheet
) ? pp
->sheet
->convs
: gnm_conventions_default
);
1530 pstate
->decimal_point
= pstate
->convs
->decimal_sep_dot
1532 : g_utf8_get_char
(go_locale_get_decimal
()->str
); /* FIXME: one char handled. */
1534 if
(pstate
->convs
->arg_sep
!= 0)
1535 pstate
->arg_sep
= pstate
->convs
->arg_sep
;
1537 pstate
->arg_sep
= go_locale_get_arg_sep
();
1538 pstate
->union_char
= pstate
->convs
->union_char
;
1539 if
(pstate
->convs
->array_col_sep
!= 0)
1540 pstate
->array_col_sep
= pstate
->convs
->array_col_sep
;
1542 pstate
->array_col_sep
= go_locale_get_col_sep
();
1543 if
(pstate
->convs
->array_row_sep
!= 0)
1544 pstate
->array_row_sep
= pstate
->convs
->array_row_sep
;
1546 pstate
->array_row_sep
= go_locale_get_row_sep
();
1548 /* Some locales/conventions have ARG_SEP == ARRAY_ROW_SEP
1549 * eg {1\2\3;4\5\6} for XL style with ',' as a decimal
1550 * some have ARG_SEP == ARRAY_COL_SEPARATOR
1551 * eg {1,2,3;4,5,6} for XL style with '.' as a decimal
1552 * or {1;2;3|4;5;6} for OOo/
1553 * keep track of whether we are in an array to allow the lexer to
1555 if
(pstate
->arg_sep
== pstate
->array_col_sep
)
1556 pstate
->in_array_sep_is
= ARRAY_COL_SEP
;
1557 else if
(pstate
->arg_sep
== pstate
->array_row_sep
)
1558 pstate
->in_array_sep_is
= ARRAY_ROW_SEP
;
1560 pstate
->in_array_sep_is
= ARG_SEP
;
1561 pstate
->in_array
= 0;
1563 pstate
->result
= NULL
;
1564 pstate
->error = error;
1570 * gnm_expr_parse_str:
1572 * @str : The string to parse.
1573 * @pp : #GnmParsePos
1574 * @flags : See parse-utils for descriptions
1575 * @convs : optionally NULL #GnmConventions
1576 * @error : optionally NULL ptr to store details of error.
1578 * Parse a string. if @error is non-null it will be assumed that the
1579 * caller has passed a pointer to a GnmParseError struct AND that it will
1580 * take responsibility for freeing that struct and its contents.
1581 * with parse_error_free.
1582 * If @convs is NULL use the conventions from @pp.
1585 gnm_expr_parse_str
(char const *str
, GnmParsePos
const *pp
,
1586 GnmExprParseFlags flags
,
1587 GnmConventions
const *convs
,
1588 GnmParseError
*error)
1590 GnmExpr
const *expr
;
1593 g_return_val_if_fail
(str
!= NULL
, NULL
);
1594 g_return_val_if_fail
(pp
!= NULL
, NULL
);
1595 g_return_val_if_fail
(state
== NULL
, NULL
);
1597 if
(deallocate_stack
== NULL
)
1600 setup_state
(&pstate
, str
, pp
, flags
, convs
, error);
1604 if
(pstate.result
!= NULL
) {
1605 deallocate_assert_empty
();
1608 /* If this happens, something is very wrong */
1609 if
(pstate.
error != NULL
&& pstate.
error->message
!= NULL
) {
1610 g_warning
("An error occurred and the GnmExpr is non-null! This should not happen");
1611 g_warning
("Error message is %s (%d, %d)", pstate.
error->message
, pstate.
error->begin_char
,
1612 pstate.
error->end_char
);
1616 /* Do we have multiple expressions */
1617 if
(pstate.result
->next
!= NULL
) {
1618 if
(flags
& GNM_EXPR_PARSE_PERMIT_MULTIPLE_EXPRESSIONS
)
1619 expr
= gnm_expr_new_set
(g_slist_reverse
(pstate.result
));
1621 gnm_expr_list_unref
(pstate.result
);
1622 report_err
(&pstate
, g_error_new
(1, PERR_MULTIPLE_EXPRESSIONS
,
1623 _
("Multiple expressions are not supported in this context")),
1625 (pstate.ptr
- pstate.start
));
1629 /* Free the list, do not unref the content */
1630 expr
= pstate.result
->data
;
1631 gnm_expr_list_free
(pstate.result
);
1634 /* If there is no error message, attempt to be more detailed */
1635 if
(pstate.
error != NULL
&&
1636 (pstate.
error->err
== NULL || pstate.
error->err
->message
== NULL
)) {
1637 char const *last_token
= pstate.ptr
;
1639 if
(*last_token
== '\0') {
1640 char const *str
= pstate.start
;
1641 char const *res
= NULL
;
1642 char const *last
= find_matching_close
(str
, &res
);
1645 report_err
(&pstate
, g_error_new
(1, PERR_MISSING_PAREN_OPEN
,
1646 _
("Could not find matching opening parenthesis")),
1648 else if
(res
!= NULL
)
1649 report_err
(&pstate
, g_error_new
(1, PERR_MISSING_PAREN_CLOSE
,
1650 _
("Could not find matching closing parenthesis")),
1653 report_err
(&pstate
, g_error_new
(1, PERR_INVALID_EXPRESSION
,
1654 _
("Invalid expression")),
1655 pstate.ptr
, pstate.ptr
- pstate.start
);
1657 report_err
(&pstate
, g_error_new
(1, PERR_UNEXPECTED_TOKEN
,
1658 _
("Unexpected token %c"), *last_token
),
1667 deallocate_uninit
();
1669 return gnm_expr_top_new
(expr
);
1673 gnm_expr_lex_all
(char const *str
, GnmParsePos
const *pp
,
1674 GnmExprParseFlags flags
,
1675 GnmConventions
const *convs
)
1677 GnmLexerItem
*res
= NULL
;
1678 int n
= 0, alloc
= 0;
1680 GnmParseError
*error = NULL
;
1682 g_return_val_if_fail
(str
!= NULL
, NULL
);
1683 g_return_val_if_fail
(pp
!= NULL
, NULL
);
1685 if
(deallocate_stack
== NULL
)
1688 setup_state
(&pstate
, str
, pp
, flags
, convs
, error);
1694 alloc
= alloc
* 2 + 20;
1695 res
= g_renew
(GnmLexerItem
, res
, alloc
);
1698 res
[n
].start
= pstate.ptr
- pstate.start
;
1699 res
[n
].token
= yylex ();
1700 res
[n
].end
= pstate.ptr
- pstate.start
;
1702 if
(res
[n
].token
== 0)
1705 len
= res
[n
].end
- res
[n
].start
;
1706 /* Kill spaces that got eaten, but not a space operator */
1707 while
(len
> 1 && str
[res
[n
].start
] == ' ') {
1711 while
(len
> 1 && str
[res
[n
].end
- 1] == ' ') {