2 /* Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
4 This file is part of Oleo, the GNU Spreadsheet.
6 Oleo is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 Oleo is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Oleo; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 %nonassoc
'<' LE
'>' GE
36 %token L_FN0 L_FN1 L_FN2 L_FN3 L_FN4 L_FNN
37 %token L_FN1R L_FN2R L_FN3R L_FN4R L_FNNR
46 #define obstack_chunk_alloc ck_malloc
47 #define obstack_chunk_free free
59 void yyerror (char *);
64 extern VOIDSTAR hash_find
();
66 /* This table contains a list of the infix single-char functions */
67 unsigned char fnin
[] = {
68 SUM
, DIFF
, DIV
, PROD
, MOD
, /* AND, OR, */ POW
, EQUAL
, IF
, CONCAT
, 0
71 #define YYSTYPE _y_y_s_t_y_p_e
72 typedef
struct node
*YYSTYPE;
75 YYSTYPE make_list
(YYSTYPE, YYSTYPE);
82 extern
struct obstack tmp_mem
;
90 parse_error
=PARSE_ERR
;
99 ($1)->n_x.v_subs
[0]=$3;
100 ($1)->n_x.v_subs
[1]=(struct node
*)0;
102 | L_FN2
'(' exp
',' exp
')' {
103 ($1)->n_x.v_subs
[0]=$3;
104 ($1)->n_x.v_subs
[1]=$5;
106 | L_FN3
'(' exp
',' exp
',' exp
')' {
107 ($1)->n_x.v_subs
[0]=make_list
($3,$5);
108 ($1)->n_x.v_subs
[1]=$7;
110 | L_FN4
'(' exp
',' exp
',' exp
',' exp
')' {
111 ($1)->n_x.v_subs
[0]=make_list
($3,$5);
112 ($1)->n_x.v_subs
[1]=make_list
($7,$9);
114 | L_FNN
'(' exp_list
')' {
115 ($1)->n_x.v_subs
[0]=(struct node
*)0;
116 ($1)->n_x.v_subs
[1]=$3;
118 | L_FN1R
'(' L_RANGE
')' {
119 $1->n_x.v_subs
[0]=$3;
121 | L_FN1R
'(' L_VAR
')' {
122 $1->n_x.v_subs
[0]=$3;
125 | L_FN2R
'(' L_RANGE
',' exp
')' {
126 $1->n_x.v_subs
[0]=$3;
127 $1->n_x.v_subs
[1]=$5;
129 | L_FN2R
'(' L_VAR
',' exp
')' {
130 $1->n_x.v_subs
[0]=$3;
131 $1->n_x.v_subs
[1]=$5;
134 /* JF: These should be FN2R, but I'm hacking this for SYLNK */
135 | L_FN2R
'(' L_RANGE
',' exp
',' exp
')' {
136 if
($1->comp_value
!=F_INDEX
)
137 parse_error
=PARSE_ERR
;
138 $1->comp_value
=F_INDEX2
;
139 $1->n_x.v_subs
[0]=make_list
($3,$5);
140 $1->n_x.v_subs
[1]=$7;
142 | L_FN2R
'(' L_VAR
',' exp
',' exp
')' {
143 if
($1->comp_value
!=F_INDEX
)
144 parse_error
=PARSE_ERR
;
145 $1->comp_value
=F_INDEX2
;
146 $1->n_x.v_subs
[0]=make_list
($3,$5);
147 $1->n_x.v_subs
[1]=$7;
150 | L_FN3R
'(' L_RANGE
',' exp
',' exp
')' {
151 ($1)->n_x.v_subs
[0]=make_list
($3,$5);
152 ($1)->n_x.v_subs
[1]=$7;
154 | L_FN3R
'(' L_VAR
',' exp
',' exp
')' {
155 ($1)->n_x.v_subs
[0]=make_list
($3,$5);
156 ($1)->n_x.v_subs
[1]=$7;
159 | L_FNNR
'(' range_exp_list
')' {
160 ($1)->n_x.v_subs
[0]=(struct node
*)0;
161 ($1)->n_x.v_subs
[1]=$3;
163 | exp
'?' exp
':' exp
{
165 $2->n_x.v_subs
[0]=$4;
166 $2->n_x.v_subs
[1]=$5;
167 $4->n_x.v_subs
[0]=$1;
168 $4->n_x.v_subs
[1]=$3;
171 $2->n_x.v_subs[0]=$1;
172 $2->n_x.v_subs[1]=$3;
175 $2->n_x.v_subs
[0]=$1;
176 $2->n_x.v_subs
[1]=$3;
179 $2->n_x.v_subs
[0]=$1;
180 $2->n_x.v_subs
[1]=$3;
183 $2->n_x.v_subs
[0]=$1;
184 $2->n_x.v_subs
[1]=$3;
187 $2->n_x.v_subs
[0]=$1;
188 $2->n_x.v_subs
[1]=$3;
191 $2->n_x.v_subs
[0]=$1;
192 $2->n_x.v_subs
[1]=$3;
195 $2->n_x.v_subs
[0]=$1;
196 $2->n_x.v_subs
[1]=$3;
199 $2->n_x.v_subs
[0]=$1;
200 $2->n_x.v_subs
[1]=$3;
203 $2->n_x.v_subs
[0]=$1;
204 $2->n_x.v_subs
[1]=$3;
207 $2->n_x.v_subs
[0]=$1;
208 $2->n_x.v_subs
[1]=$3;
211 $2->n_x.v_subs
[0]=$1;
212 $2->n_x.v_subs
[1]=$3;
215 $2->n_x.v_subs
[0]=$1;
216 $2->n_x.v_subs
[1]=$3;
219 $2->n_x.v_subs
[0]=$1;
220 $2->n_x.v_subs
[1]=$3;
223 $2->n_x.v_subs
[0]=$1;
224 $2->n_x.v_subs
[1]=$3;
226 |
'-' exp %prec NEG
{
227 if
($2->comp_value
==CONST_FLT
) {
228 $2->n_x.v_float
= -($2->n_x.v_float
);
231 } else if
($2->comp_value
==CONST_INT
) {
232 $2->n_x.v_int
= -($2->n_x.v_int
);
236 $1->comp_value
= NEGATE
;
237 $1->n_x.v_subs
[0]=$2;
238 $1->n_x.v_subs
[1]=(struct node
*)0;
242 $1->n_x.v_subs
[0]=$2;
243 $1->n_x.v_subs
[1]=(struct node
*)0;
249 parse_error
=NO_CLOSE
;
257 parse_error
=NO_CLOSE
;
263 { $$
= make_list
($1, 0); }
265 { $$
= make_list
($3, $1); }
272 range_exp_list: range_exp
273 { $$
=make_list
($1, 0); }
274 | range_exp_list
',' range_exp
275 { $$
=make_list
($3,$1); }
285 yyerror FUN1
(char *, s
)
288 parse_error
=PARSE_ERR
;
292 make_list FUN2
(YYSTYPE, car
, YYSTYPE, cdr
)
296 ret
=(YYSTYPE)obstack_alloc
(&tmp_mem
,sizeof
(*ret
));
298 ret
->n_x.v_subs
[0]=car
;
299 ret
->n_x.v_subs
[1]=cdr
;
305 extern
struct node
*yylval;
308 unsigned char parse_cell_or_range
(char **,struct rng
*);
310 unsigned char parse_cell_or_range
();
321 unsigned char byte_value
;
324 /* unsigned char *ptr; */
333 while
(isspace
(*instr
))
336 if
(ch
=='(' || ch
==',' || ch
==')')
339 new
=(struct node
*)obstack_alloc
(&tmp_mem
,sizeof
(struct node
));
346 case
'0': case
'1': case
'2': case
'3': case
'4': case
'5': case
'6':
347 case
'7': case
'8': case
'9': case
'.':
353 while
(isdigit
(*tmp_str
) ||
(!isflt
&& *tmp_str
=='.' && ++isflt
))
355 if
(*tmp_str
=='e' ||
*tmp_str
=='E') {
358 if
(*tmp_str
=='-' ||
*tmp_str
=='+')
360 while
(isdigit
(*tmp_str
))
364 new
->n_x.v_float
=astof
((char **)(&begin
));
365 byte_value
=CONST_FLT
;
367 new
->n_x.v_int
=astol
((char **)(&begin
));
370 new
->n_x.v_float
=astof
((char **)(&begin
));
371 byte_value
=CONST_FLT
;
373 byte_value
=CONST_INT
;
381 while
(*instr
&& *instr
!='"') {
382 if
(*instr
=='\\' && instr
[1])
387 parse_error
=NO_QUOTE
;
390 tmp_str
=new
->n_x.v_string
=(char *)ck_malloc
(1+instr
-begin
);
391 while
(begin
!=instr
) {
396 if
(begin
[0]>='0' && begin
[0]<='7') {
397 if
(begin
[1]>='0' && begin
[1]<='7') {
398 if
(begin
[2]>='0' && begin
[2]<='7') {
399 n
=(begin
[2]-'0') + (010 * (begin
[1]-'0')) + ( 0100 * (begin
[0]-'0'));
402 n
=(begin
[1]-'0') + (010 * (begin
[0]-'0'));
413 *tmp_str
++= *begin
++;
417 byte_value
=CONST_STR
;
423 case
'*': case
'/': case
'%': case
'&':
424 /* case '|': */ case
'^': case
'=':
430 for
(ptr
= fnin
;*ptr
;ptr
++)
431 if
(the_funs
[*ptr
].fn_str
[0]==ch
)
435 panic
("Can't find fnin[] entry for '%c'",ch
);
449 byte_value
= (ch
=='<') ? LESS
: (ch
=='>') ? GREATER
: NOT
;
453 byte_value
= (ch
=='<') ? LESSEQ
: (ch
=='>') ? GREATEQ
: NOTEQUAL
;
454 ch
= (ch
=='<') ? LE
: (ch
=='>') ? GE
: NE
;
467 parse_error
=BAD_CHAR
;
472 while
(*instr
&& (isalnum
(*instr
) ||
*instr
=='_'))
476 if
(!stricmp
(begin
,tname
))
478 else if
(!stricmp
(begin
,fname
))
480 else if
(!stricmp
(begin
,iname
) && (begin
[4]==0 ||
!stricmp
(begin
+4,"inity")))
481 byte_value
=CONST_INF
;
482 else if
(!stricmp
(begin
,mname
) ||
483 !stricmp
(begin
,"#ninf"))
484 byte_value
=CONST_NINF
;
485 else if
(!stricmp
(begin
,nname
) ||
486 !stricmp
(begin
,"#nan"))
487 byte_value
=CONST_NAN
;
489 for
(n
=1;n
<=ERR_MAX
;n
++)
490 if
(!stricmp
(begin
,ename
[n
]))
495 byte_value
=CONST_ERR
;
502 if
(!a0
&& (ch
=='@' || ch
=='$'))
507 while
(*instr
&& (isalpha
(*instr
) || isdigit
(*instr
) ||
*instr
=='_'))
512 byte_value
=parse_cell_or_range
(&begin
,&(new
->n_x.v_rng
));
514 if
((byte_value
& ~
0x3)==R_CELL
)
522 while
(*instr
&& (isalpha
(*instr
) || isdigit
(*instr
) ||
*instr
=='_'))
526 while
(isspace
(*instr
))
532 new
->n_x.v_var
=find_or_make_var
(begin
,n
);
538 fp
=hash_find
(parse_hash
,begin
);
542 parse_error
=BAD_FUNC
;
546 if
(fp
>=the_funs
&& fp
<=&the_funs
[USR1
])
547 byte_value
=fp
-the_funs
;
549 for
(nn
=0;nn
<n_usr_funs
;nn
++) {
550 if
(fp
>=&usr_funs
[nn
][0] && fp
<=&usr_funs
[nn
][usr_n_funs
[nn
]]) {
552 new
->sub_value
=fp
-&usr_funs
[nn
][0];
558 io_error_msg
("Couln't turn fp into a ##");
559 parse_error
=BAD_FUNC
;
566 ch
= byte_value
==F_IF ? L_FN3
: L_FN2
;
567 else if
(fp
->fn_argt
[0]=='R' || fp
->fn_argt
[0]=='E')
568 ch
=L_FN1R
-1+fp
->fn_argn
-X_A0
;
570 ch
=L_FN0
+ fp
->fn_argn
-X_A0
;
574 /* new->node_type=ch; */
575 new
->comp_value
=byte_value
;
581 0 if it doesn't look like a cell or a range,
582 R_CELL if it is a cell (ptr now points past the characters, lr and lc hold the row and col of the cell)
583 RANGE if it is a range (ptr points past the chars)
586 parse_cell_or_range FUN2
(char **,ptr
, struct rng
*,retp
)
591 int abz
= ROWREL|COLREL
;
602 if
(tmpc
<MIN_COL || tmpc
>MAX_COL
)
610 for
(tmpr
=0;isdigit
(*p
);p
++)
611 tmpr
=tmpr
*10 + *p
- '0';
613 if
(tmpr
<MIN_ROW || tmpr
>MAX_ROW
)
616 if
(*p
==':' ||
*p
=='.') {
617 unsigned tmpc1
,tmpr1
;
619 abz
= ((abz
&COLREL
) ? LCREL
: 0)|
((abz
&ROWREL
) ? LRREL
: 0)|HRREL|HCREL
;
627 tmpc1
=str_to_col
(&p
);
628 if
(tmpc1
<MIN_COL || tmpc1
>MAX_COL
)
636 for
(tmpr1
=0;isdigit
(*p
);p
++)
637 tmpr1
=tmpr1
*10 + *p
- '0';
638 if
(tmpr1
<MIN_ROW || tmpr1
>MAX_ROW
)
658 retp
->lr
= retp
->hr
= tmpr
;
659 retp
->lc
= retp
->hc
= tmpc
;
670 #define CK_ABS_R(x) if((x)<MIN_ROW || (x)>MAX_ROW) \
674 #define CK_REL_R(x) if( ((x)>0 && MAX_ROW-(x)<cur_row) \
675 ||
((x
)<0 && MIN_ROW
-(x
)>cur_row
)) \
679 #define CK_ABS_C(x) if((x)<MIN_COL || (x)>MAX_COL) \
683 #define CK_REL_C(x) if( ((x)>0 && MAX_COL-(x)<cur_col) \
684 ||
((x
)<0 && MIN_COL
-(x
)>cur_col
)) \
688 #define MAYBEREL(p) (*(p)=='[' && (isdigit((p)[1]) || (((p)[1]=='+' || (p)[1]=='-') && isdigit((p)[2]))))
707 retp
->lr
= retp
->hr
=num
;
708 } else if
(MAYBEREL
(p
)) {
712 retp
->lr
= retp
->hr
=num
+cur_row
;
715 retr
=RANGE|LRREL|HRREL
;
719 retp
->hr
=num
+cur_row
;
723 } else if
(retc ||
*p
=='c' ||
*p
=='C') {
725 retp
->lr
= retp
->hr
=cur_row
;
728 if
(*p
==':' && retr
!=(RANGE|LRREL|HRREL
)) {
729 retr
= (retr
&ROWREL
) ? RANGE|LRREL
: RANGE
;
735 } else if
(MAYBEREL
(p
)) {
739 retp
->hr
=num
+cur_row
;
762 retp
->lc
= retp
->hc
=num
;
763 } else if
(MAYBEREL
(p
)) {
767 retp
->lc
= retp
->hc
=num
+cur_col
;
770 retc
=RANGE|LCREL|HCREL
;
774 retp
->hc
=num
+cur_col
;
778 } else if
(retr ||
*p
=='r' ||
*p
=='R') {
780 retp
->lc
= retp
->hc
=cur_col
;
783 if
(*p
==':' && retc
!=(RANGE|LCREL|HCREL
)) {
784 retc
= (retc
&COLREL
) ? RANGE|LCREL
: RANGE
;
790 } else if
(MAYBEREL
(p
)) {
794 retp
->hc
=num
+cur_col
;
810 if
((retr|ROWREL
)==(R_CELL|ROWREL
))
811 return
(retr
&ROWREL
) ?
(RANGE|LRREL|HRREL
) : RANGE
;
818 if
((retc|COLREL
)==(R_CELL|COLREL
))
819 return
(retc
&COLREL
) ?
(RANGE|LCREL|HCREL
) : RANGE
;
829 if
(retp
->lr
>retp
->hr
)
830 tmp
=retp
->lr
,retp
->lr
=retp
->hr
,retp
->hr
=tmp
;
831 if
(retp
->lc
>retp
->hc
)
832 tmp
=retp
->lc
,retp
->lc
=retp
->hc
,retp
->hc
=tmp
;
834 if
((retr|ROWREL
)==(R_CELL|ROWREL
)) {
835 if
((retc|COLREL
)==(R_CELL|COLREL
))
837 return
(retr
&ROWREL
) ?
(retc|LRREL|HRREL
) : retc
;
839 if
((retc|COLREL
)==(R_CELL|COLREL
))
840 return
(retc
&COLREL
) ?
(retr|LCREL|HCREL
) : retr
;
846 str_to_col FUN1
(char **,str
)
856 if
(!isalpha
((cc
=str
[0][1]))) {
858 return MIN_COL
+ (isupper
(c
) ? c
-'A' : c
-'a');
860 if
(!isalpha
((ccc
=str
[0][2]))) {
862 return MIN_COL
+26 + (isupper
(c
) ? c
-'A' : c
-'a')*26 + (isupper
(cc
) ? cc
-'A' : cc
-'a');
865 if
(!isalpha
((cccc
=str
[0][3]))) {
867 return MIN_COL
+702 + (isupper
(c
) ? c
-'A' : c
-'a')*26*26 + (isupper
(cc
) ? cc
-'A' : cc
-'a')*26 + (isupper
(ccc
) ? ccc
-'A' : ccc
-'a');
869 if
(!isalpha
(str
[0][4])) {
871 return MIN_COL
+18278 + (isupper
(c
) ? c
-'A' : c
-'a')*26*26*26 + (isupper
(cc
) ? cc
-'A' : cc
-'a')*26*26 + (isupper
(ccc
) ? ccc
-'A' : ccc
-'a')*26 + (isupper
(cccc
) ? cccc
-'A' : cccc
-'a');