1 /*	SC	A Spreadsheet Calculator
2  *		Command and expression parser
3  *
4  *		original by James Gosling, September 1982
5  *		modified by Mark Weiser and Bruce Israel,
6  *			University of Maryland
7  *
8  * 		more mods Robert Bond 12/86
9  *
10  *		More mods by Alan Silverstein, 3/88, see list of changes.
11  *
12  *		$Revision: 1.1 $
13  */
14 
15 
16 
17 %{
18 #include <config.h>
19 #include <curses.h>
20 
21 #ifdef HAVE_X11_X_H
22 #include <X11/Xlib.h>
23 #include <X11/Xutil.h>
24 #endif
25 
26 #ifdef IEEE_MATH
27 # include <ieeefp.h>
28 #endif /* IEEE_MATH */
29 
30 #include <math.h>
31 #include "sc.h"
32 
33 #ifndef PI
34 #define PI (double)3.14159265358979323846
35 #endif
36 
37 #define ENULL (struct enode *)0
38 %}
39 
40 %union {
41     int ival;
42     double fval;
43     struct ent_ptr ent;
44     struct enode *enode;
45     char *sval;
46     struct range_s rval;
47 }
48 
49 /* types */
50 %type <ent> var
51 %type <fval> num
52 %type <rval> range
53 %type <rval> var_or_range
54 %type <sval> strarg
55 %type <enode> e term expr_list
56 %token <sval> STRING
57 %token <ival> NUMBER
58 %token <fval> FNUMBER
59 %token <rval> RANGE
60 %token <rval> VAR
61 %token <sval> WORD
62 %token <ival> COL
63 
64 /* assignment/range commands */
65 %token S_COPY
66 %token S_DEFINE
67 %token S_ERASE
68 %token S_FILL
69 %token S_FMT
70 %token S_FORMAT
71 %token S_HIDE
72 %token S_LABEL
73 %token S_LEFTSTRING
74 %token S_LET
75 %token S_LOCK
76 %token S_RIGHTSTRING
77 %token S_SHOW
78 %token S_UNDEFINE
79 %token S_UNLOCK
80 %token S_VALUE
81 
82 /* file handling commands */
83 %token S_GET
84 %token S_MDIR
85 %token S_MERGE
86 %token S_PUT
87 %token S_READ
88 %token S_TBL
89 %token S_WRITE
90 
91 
92 /* other commands */
93 %token S_EVALALL
94 %token S_GOTO
95 %token S_SET
96 
97 %token K_ABS
98 %token K_ACOS
99 %token K_ASIN
100 %token K_ATAN
101 %token K_ATAN2
102 %token K_AVG
103 %token K_CEIL
104 %token K_COS
105 %token K_COUNT
106 %token K_DTR
107 %token K_ERROR
108 %token K_EXP
109 %token K_FABS
110 %token K_FIXED
111 %token K_FLOOR
112 %token K_HYPOT
113 %token K_IF
114 %token K_INVALID
115 %token K_LN
116 %token K_LOG
117 %token K_MAX
118 %token K_MIN
119 %token K_PI
120 %token K_POW
121 %token K_PROD
122 %token K_RND
123 %token K_ROUND
124 %token K_RTD
125 %token K_SIN
126 %token K_SQRT
127 %token K_STDDEV
128 %token K_SUM
129 %token K_TAN
130 
131 /* finacial */
132 %token K_FV	/* @fv(e1,e2,e3) computes the future value */
133 %token K_IRR	/* @irr(range)	 computes the internal rate of return */
134 %token K_PMT
135 %token K_PV
136 
137 /* time/date */
138 %token K_HOUR	/* @hour(e)	number of hours since midnight: 0 to 23 */
139 %token K_MINUTE	/* @minute(e)	the number of minutes past the hour: 0 to 59 */
140 %token K_SECOND	/* @second(e)	the number of seconds past the minute: 0-59 */
141 %token K_MONTH	/* @month(e)	Return the month: 1 (Jan) to 12 (Dec) */
142 %token K_DAY	/* @day(e)	Return the day of the month: 1 to 31 */
143 %token K_YEAR	/* @year(e)	Return the year.  Valid years begin with 1970*/
144 %token K_DATE	/* @date(e)	Convert the time in seconds to a date */
145 %token K_DTS	/* @dts(m,d,y)	Return m/d/y encoded in seconds since 1970 */
146 %token K_NOW	/* @now		Return the time encoded in seconds since 1970*/
147 %token K_TTS	/* @tts(h,m,s)	Return h:m:s encoded in seconds since midnight*/
148 
149 /* type conversion */
150 %token K_FMT	/* @fmt(se,e)	Convert a number to a string using sprintf(3)*/
151 %token K_STON	/* @ston(se)	Convert string expr se to a numeric */
152 
153 %token K_SUBSTR
154 %token K_UPPER
155 %token K_LOWER
156 %token K_CAPITAL
157 %token K_EQS
158 %token K_EXT
159 %token K_NVAL
160 %token K_SVAL
161 %token K_LOOKUP
162 %token K_HLOOKUP
163 %token K_VLOOKUP
164 %token K_INDEX
165 %token K_STINDEX
166 %token K_AUTO
167 %token K_AUTOCALC
168 %token K_BYROWS
169 %token K_BYCOLS
170 %token K_ITERATIONS
171 %token K_NUMERIC
172 %token K_PRESCALE
173 %token K_EXTFUN
174 %token K_CELLCUR
175 %token K_TOPROW
176 %token K_TBLSTYLE
177 %token K_TBL
178 %token K_LATEX
179 %token K_SLATEX
180 %token K_TEX
181 %token K_FRAME
182 %token K_RNDINFINITY
183 %token K_MYROW
184 %token K_MYCOL
185 %token K_COLTOA
186 %token K_CRACTION
187 %token K_CRROW
188 %token K_CRCOL
189 %token K_ROWLIMIT
190 %token K_COLLIMIT
191 %token K_NUMITER
192 %token K_MATRIX_ADD
193 %token K_MATRIX_SUB
194 %token K_MATRIX_INV
195 %token K_MATRIX_MULT
196 %token K_MATRIX_TRANS
197 %token K_GRAPH
198 
199 %left '?' ':'
200 %left '|'
201 %left '&'
202 %nonassoc '<' '=' '>' '!'
203 %left '+' '-' '#'
204 %left '*' '/' '%'
205 %left '^'
206 
207 %%
208 command:
209 /* assignment commands */
210 		S_LET var_or_range '=' e
211 				{ let($2.left.vp, $4); }
212 	|	S_LABEL var_or_range '=' e
213 				{ slet($2.left.vp, $4, 0); }
214 	|	S_LEFTSTRING var_or_range '=' e
215 				{ slet($2.left.vp, $4, -1); }
216 	|	S_RIGHTSTRING var_or_range '=' e
217 				{ slet($2.left.vp, $4, 1); }
218 
219 /* range commands */
220 	|	S_COPY range var_or_range
221 				{ copy($2.left.vp,$2.right.vp,
222 				$3.left.vp,$3.right.vp); }
223 		/* destination conforms to the source */
224 	|	S_COPY var range
225 				{ copy($2.vp,NULL, $3.left.vp,$3.right.vp); }
226 	|	S_ERASE       	{ eraser(lookat(showsr, showsc),
227 				        lookat(currow, curcol)); }
228 	|	S_ERASE var_or_range
229 					{ eraser($2.left.vp, $2.right.vp); }
230 	|	S_FORMAT COL ':' COL NUMBER NUMBER NUMBER
231 				{ doformat($2,$4,$5,$6,$7); }
232 	|	S_FORMAT COL NUMBER NUMBER NUMBER
233 				{ doformat($2,$2,$3,$4,$5); }
234         |       S_FORMAT COL ':' COL NUMBER NUMBER
235                                 { doformat($2,$4,$5,$6, REFMTFIX); }
236         |       S_FORMAT COL NUMBER NUMBER
237                                 { doformat($2,$2,$3,$4, REFMTFIX); }
238  	|	S_HIDE COL
239  					{ hide_col( $2 ); }
240  	|	S_HIDE NUMBER
241  					{ hide_row( $2 ); }
242 	|       S_SHOW COL ':' COL
243 					{ showcol( $2, $4); }
244 	|       S_SHOW NUMBER ':' NUMBER
245 					{ showrow( $2, $4); }
246 	|	S_VALUE       { valueize_area(showsr, showsc, currow, curcol);
247 				 modflg++; }
248 	|	S_VALUE var_or_range { valueize_area(($2.left.vp)->row,
249 					($2.left.vp)->col,
250 					($2.right.vp)->row,
251 					($2.right.vp)->col); modflg++; }
252 	|	S_FILL num num  { fill(lookat(showsr, showsc),
253 				      lookat(currow, curcol), $2, $3); }
254 	|	S_FILL var_or_range num num
255 				{ fill($2.left.vp, $2.right.vp, $3, $4); }
256 	|	S_FMT var_or_range STRING
257 				{ format_cell($2.left.vp, $2.right.vp, $3); }
258 	|	S_LOCK
259 					{ lock_cells(lookat(showsr, showsc),
260 				        lookat(currow, curcol)); }
261 	|	S_LOCK var_or_range
262 				{ lock_cells($2.left.vp, $2.right.vp); }
263 	|	S_UNLOCK
264 					{ unlock_cells(lookat(showsr, showsc),
265 				        lookat(currow, curcol)); }
266 	|	S_UNLOCK var_or_range
267 				{ unlock_cells($2.left.vp, $2.right.vp); }
268 	|	S_DEFINE strarg       { struct ent_ptr arg1, arg2;
269 					arg1.vp = lookat(showsr, showsc);
270 					arg1.vf = 0;
271 					arg2.vp = lookat(currow, curcol);
272 					arg2.vf = 0;
273                                         if (arg1.vp == arg2.vp)
274                                            add_range($2, arg2, arg2, 0);
275                                         else
276                                            add_range($2, arg1, arg2, 1); }
277 
278 	|	S_DEFINE strarg range	{ add_range($2, $3.left, $3.right, 1); }
279 	|	S_DEFINE strarg var	{ add_range($2, $3, $3, 0); }
280 	|	S_UNDEFINE var_or_range	{ del_range($2.left.vp, $2.right.vp); }
281 
282 /* file handling commands */
283 	|	S_GET strarg	{  /* This tmp hack is because readfile
284 				    * recurses back through yyparse. */
285 				  char *tmp;
286 				  tmp = $2;
287 				  readfile (tmp, 1);
288 				  scxfree(tmp);
289 				}
290 	|	S_MDIR strarg
291 				{ if (mdir) scxfree(mdir); mdir = $2; }
292 	|	S_MERGE strarg	{
293 				  char *tmp;
294 				  tmp = $2;
295 				  readfile (tmp, 0);
296 				  scxfree(tmp);
297 				}
298 	|       S_PUT strarg range
299 				{ (void) writefile($2, ($3.left.vp)->row,
300 			 	($3.left.vp)->col, ($3.right.vp)->row,
301 			 	($3.right.vp)->col);
302 			 	scxfree($2); }
303 	|	S_PUT strarg
304 				{ (void) writefile ($2, 0, 0, maxrow, maxcol);
305 			 	scxfree($2); }
306 	|	S_READ strarg
307 				{ (void) readstrfile($2, currow, curcol,
308 					-1, -1);
309 			 	scxfree($2); }
310 	|	S_READ strarg range
311 				{ (void) readstrfile($2, ($3.left.vp)->row,
312 					($3.left.vp)->col,
313 					($3.right.vp)->row,
314 					($3.right.vp)->col);
315 			 	scxfree($2); }
316 	|	S_READ strarg var
317 				{ (void) readstrfile($2, $3.vp->row,
318 					$3.vp->col,
319 					-1, -1);
320 			 	scxfree($2); }
321 	|       S_TBL strarg range { (void) tblprintfile($2, ($3.left.vp)->row,
322 			 ($3.left.vp)->col, ($3.right.vp)->row,
323 			 ($3.right.vp)->col);
324 			 scxfree($2); }
325 	|	S_TBL strarg	{ (void)tblprintfile ($2, 0, 0, maxrow, maxcol);
326 			 scxfree($2); }
327 	|       S_WRITE strarg range { (void) printfile($2, ($3.left.vp)->row,
328 			 ($3.left.vp)->col, ($3.right.vp)->row,
329 			 ($3.right.vp)->col);
330 			 scxfree($2); }
331 	|	S_WRITE strarg	{ (void) printfile ($2, 0, 0, maxrow, maxcol);
332 			 scxfree($2); }
333 
334 /* other commands */
335 	|	S_EVALALL		{ EvalAll(); }
336 	|	S_GOTO var_or_range {moveto($2.left.vp->row, $2.left.vp->col);}
337 	|       S_GOTO num		{ num_search($2, 0); }
338 	|       S_GOTO errlist
339 	|       S_GOTO STRING		{ str_search($2); }
340 	|	S_GOTO			{ go_last(); }
341  	|	S_SET setlist
342 	|	/* nothing */
343 	|	error;
344 
345 /* terminals: functions, cells, string variables */
346 term: 		var			{ $$ = new_var(O_VAR, $1); }
347 	|	K_FIXED term		{ $$ = new ('f', ENULL, $2); }
348 	|       '@' K_SUM '(' var_or_range ')'
349 				{ $$ = new_range(REDUCE | '+', $4); }
350 	|       '@' K_PROD '(' var_or_range ')'
351 				{ $$ = new_range (REDUCE | '*', $4); }
352 	|       '@' K_AVG '(' var_or_range ')'
353 				{ $$ = new_range (REDUCE | 'a', $4); }
354 	|       '@' K_STDDEV '(' var_or_range ')'
355 				{ $$ = new_range (REDUCE | 's', $4); }
356 	|       '@' K_COUNT '(' var_or_range ')'
357 				{ $$ = new_range (REDUCE | 'c', $4); }
358 	|       '@' K_MAX '(' var_or_range ')'
359 				{ $$ = new_range (REDUCE | MAXR, $4); }
360 	|	'@' K_MAX '(' e ',' expr_list ')'
361 				{ $$ = new(LMAX, $6, $4); }
362 	|       '@' K_MIN '(' var_or_range ')'
363 				{ $$ = new_range (REDUCE | MINR, $4); }
364 	|	'@' K_MIN '(' e ',' expr_list ')'
365 				{ $$ = new(LMIN, $6, $4); }
366 	| '@' K_ABS '(' e ')'		{ $$ = new(ABS, ENULL, $4); }
367 	| '@' K_ACOS '(' e ')'		{ $$ = new(ACOS, ENULL, $4); }
368 	| '@' K_ASIN '(' e ')'		{ $$ = new(ASIN, ENULL, $4); }
369 	| '@' K_ATAN '(' e ')'		{ $$ = new(ATAN, ENULL, $4); }
370 	| '@' K_ATAN2 '(' e ',' e ')'	{ $$ = new(ATAN2, $4, $6); }
371 	| '@' K_CEIL '(' e ')'		{ $$ = new(CEIL, ENULL, $4); }
372 	| '@' K_COS '(' e ')'		{ $$ = new(COS, ENULL, $4); }
373 	| '@' K_EXP '(' e ')'		{ $$ = new(EXP, ENULL, $4); }
374 	| '@' K_FABS '(' e ')'		{ $$ = new(FABS, ENULL, $4); }
375 	| '@' K_FLOOR '(' e ')'		{ $$ = new(FLOOR, ENULL, $4); }
376 	| '@' K_HYPOT '(' e ',' e ')'	{ $$ = new(HYPOT, $4, $6); }
377 	| '@' K_LN '(' e ')'		{ $$ = new(LOG, ENULL, $4); }
378 	| '@' K_LOG '(' e ')'		{ $$ = new(LOG10, ENULL, $4); }
379 	| '@' K_POW '(' e ',' e ')'	{ $$ = new(POW, $4, $6); }
380 	| '@' K_SIN '(' e ')'		{ $$ = new(SIN, ENULL, $4); }
381 	| '@' K_SQRT '(' e ')'		{ $$ = new(SQRT, ENULL, $4); }
382 	| '@' K_TAN '(' e ')'		{ $$ = new(TAN, ENULL, $4); }
383 	| '@' K_DTR '(' e ')'		{ $$ = new(DTR, ENULL, $4); }
384 	| '@' K_RTD '(' e ')'		{ $$ = new(RTD, ENULL, $4); }
385 	| '@' K_RND '(' e ')'		{ $$ = new(RND, ENULL, $4); }
386 	| '@' K_ROUND '(' e ',' e ')'	{ $$ = new(ROUND, $4, $6); }
387 	| '@' K_IF  '(' e ',' e ',' e ')' { $$ = new(IF,  $4,new(',',$6,$8)); }
388 
389 /* finacial */
390 	| '@' K_IRR  '(' var_or_range ')' { $$ = new_range(REDUCE | IRR, $4); }
391  	| '@' K_FV  '(' e ',' e ',' e ')' { $$ = new(FV,  $4,new(':',$6,$8)); }
392  	| '@' K_PMT '(' e ',' e ',' e ')' { $$ = new(PMT, $4,new(':',$6,$8)); }
393 	| '@' K_PV  '(' e ',' e ',' e ')' { $$ = new(PV,  $4,new(':',$6,$8)); }
394 
395 /* time/date */
396 	| '@' K_HOUR '(' e ')'		{ $$ = new(HOUR,ENULL, $4); }
397 	| '@' K_MINUTE '(' e ')'	{ $$ = new(MINUTE,ENULL, $4); }
398 	| '@' K_SECOND '(' e ')'	{ $$ = new(SECOND,ENULL, $4); }
399 	| '@' K_MONTH '(' e ')'		{ $$ = new(MONTH,ENULL,$4); }
400 	| '@' K_DAY '(' e ')'		{ $$ = new(DAY, ENULL, $4); }
401 	| '@' K_YEAR '(' e ')'		{ $$ = new(YEAR, ENULL, $4); }
402 	| '@' K_NOW			{ $$ = new(NOW, ENULL, ENULL);}
403 	| '@' K_DTS '(' e ',' e ',' e ')'
404 					{ $$ = new(DTS, $4, new(',', $6, $8));}
405 	| '@' K_TTS '(' e ',' e ',' e ')'
406 					{ $$ = new(TTS, $4, new(',', $6, $8));}
407 
408 /* type conversion */
409 	| '@' K_FMT  '(' e ',' e ')'	{ $$ = new(FMT, $4, $6); }
410 	| '@' K_STON '(' e ')'		{ $$ = new(STON, ENULL, $4); }
411 
412 	| '@' K_EQS '(' e ',' e ')'	{ $$ = new (EQS, $4, $6); }
413 	| '@' K_DATE '(' e ')'		{ $$ = new(DATE, ENULL, $4); }
414 	| '@' K_UPPER '(' e ')'		{ $$ = new(UPPER, ENULL, $4); }
415 	| '@' K_LOWER '(' e ')'		{ $$ = new(LOWER, ENULL, $4); }
416 	| '@' K_CAPITAL '(' e ')'	{ $$ = new(CAPITAL, ENULL, $4); }
417 	| '@' K_INDEX  '(' e ',' var_or_range ')'
418 		 { $$ = new(INDEX, $4, new_range(REDUCE | INDEX, $6)); }
419 	| '@' K_LOOKUP  '(' e ',' var_or_range ')'
420 		 { $$ = new(LOOKUP, $4, new_range(REDUCE | LOOKUP, $6)); }
421 	| '@' K_HLOOKUP  '(' e ',' var_or_range ',' e ')'
422 		 { $$ = new(HLOOKUP, new(',', $4, $8),
423 		    new_range((REDUCE | HLOOKUP), $6)); }
424 	| '@' K_VLOOKUP  '(' e ',' var_or_range ',' e ')'
425 		 { $$ = new(VLOOKUP, new(',', $4, $8),
426 		    new_range((REDUCE | VLOOKUP), $6)); }
427 	| '@' K_STINDEX  '(' e ',' var_or_range ')'
428 		 { $$ = new(STINDEX, $4, new_range((REDUCE | STINDEX), $6)); }
429 	| '@' K_EXT  '(' e ',' e ')'	{ $$ = new(EXT, $4, $6); }
430 	| '@' K_NVAL '(' e ',' e ')'	{ $$ = new(NVAL, $4, $6); }
431 	| '@' K_SVAL '(' e ',' e ')'	{ $$ = new(SVAL, $4, $6); }
432 	| '@' K_SUBSTR '(' e ',' e ',' e ')'
433 				{ $$ = new(SUBSTR, $4, new(',', $6, $8)); }
434 	|	'(' e ')'	{ $$ = $2; }
435 	|	'+' term	{ $$ = $2; }
436 	|	'-' term	{ $$ = new ('m', ENULL, $2); }
437 	|	NUMBER		{ $$ = new_const(O_CONST, (double) $1); }
438 	|	FNUMBER		{ $$ = new_const(O_CONST, $1); }
439 	|	NUMBER '_' NUMBER '_' NUMBER
440 		{
441 			int y = $5;
442 
443 			/* Convert 'NN' to years since 1970.
444 			 * (or 2000, fix by 2070)
445 			 */
446 			if (y < 100) {		/* Full year not given */
447 				if (y >= 70)	/* 70-99 == Years since 1900 */
448 					y += 1900;
449 				else		/* 00-69 == Years since 2000 */
450 					y += 2000;
451 			}
452 			$$ = new_const(O_CONST, dodts($1, $3, y));
453 		}
454 	|	K_PI { $$ = new_const(O_CONST, PI); }
455 	| '@'   K_PI { $$ = new_const(O_CONST, PI); }
456 	|	STRING	        { $$ = new_str($1); }
457 	|	'~' term	{ $$ = new ('~', ENULL, $2); }
458 	|	'!' term	{ $$ = new ('~', ENULL, $2); }
459 	| '@' K_MYROW			{ $$ = new(MYROW, ENULL, ENULL);}
460 	| '@' K_MYCOL			{ $$ = new(MYCOL, ENULL, ENULL);}
461 	| '@' K_COLTOA '(' e ')'	{ $$ = new(COLTOA, ENULL, $4);}
462 	| '@' K_NUMITER			{ $$ = new(NUMITER, ENULL, ENULL);}
463 
464 	/* Matrix stuff */
465 	| '@' K_MATRIX_ADD '(' var_or_range ',' var_or_range ',' var_or_range ')'
466 /*			{ $$ = new_range(MATRIX_ADD, $4, new_range(':', $6, $8)); }*/
467 			{}
468 	| '@' K_MATRIX_SUB '(' var_or_range ',' var_or_range ',' var_or_range ')'
469 /*			{ $$ = new_range(MATRIX_SUB, $4, new_range(':', $6, $8)); }*/
470 			{}
471 	| '@' K_MATRIX_INV '(' var_or_range ',' var_or_range ')'
472 /*			{ $$ = new_range(MATRIX_INV, $4, $6 ); }*/
473 			{}
474 	| '@' K_MATRIX_MULT '(' var_or_range ',' var_or_range ',' var_or_range ')'
475 /*			{ $$ = new_range(MATRIX_MULT, $4, new_range(':', $6, $8)); }*/
476 			{}
477 	| '@' K_MATRIX_TRANS '(' var_or_range ',' var_or_range ')'
478 /*			{ $$ = new_range(MATRIX_TRANS, $4, $6 ); }*/
479 			{}
480 	;
481 
482 /* expressions */
483 e:		e '+' e		{ $$ = new ('+', $1, $3); }
484 	|	e '-' e		{ $$ = new ('-', $1, $3); }
485 	|	e '*' e		{ $$ = new ('*', $1, $3); }
486 	|	e '/' e		{ $$ = new ('/', $1, $3); }
487 	|	e '%' e		{ $$ = new ('%', $1, $3); }
488 	|	e '^' e		{ $$ = new ('^', $1, $3); }
489 	|	term
490 	|	e '?' e ':' e	{ $$ = new ('?', $1, new(':', $3, $5)); }
491 	|	e '<' e		{ $$ = new ('<', $1, $3); }
492 	|	e '=' e		{ $$ = new ('=', $1, $3); }
493 	|	e '>' e		{ $$ = new ('>', $1, $3); }
494 	|	e '&' e		{ $$ = new ('&', $1, $3); }
495 	|	e '|' e		{ $$ = new ('|', $1, $3); }
496 	|	e '<' '=' e	{ $$ = new ('~', ENULL, new ('>', $1, $4)); }
497 	|	e '!' '=' e	{ $$ = new ('~', ENULL, new ('=', $1, $4)); }
498 	|	e '<' '>' e	{ $$ = new ('~', ENULL, new ('=', $1, $4)); }
499 	|	e '>' '=' e	{ $$ = new ('~', ENULL, new ('<', $1, $4)); }
500 	|	e '#' e		{ $$ = new ('#', $1, $3); }
501 	;
502 
503 /* list of expressions */
504 expr_list:	e		{ $$ = new(ELIST, ENULL, $1); }
505 	|	expr_list ',' e	{ $$ = new(ELIST, $1, $3); }
506 	;
507 
508 range:		var ':' var	{ $$.left = $1; $$.right = $3; }
509 	| 	RANGE		{ $$ = $1; }
510 	;
511 
512 var:		COL NUMBER	{ $$.vp = lookat($2 , $1); $$.vf = 0; }
513 	|	'$' COL NUMBER	{ $$.vp = lookat($3 , $2);
514 					$$.vf = FIX_COL; }
515 	|	COL '$' NUMBER	{ $$.vp = lookat($3 , $1);
516 					$$.vf = FIX_ROW; }
517 	|	'$' COL '$' NUMBER { $$.vp = lookat($4 , $2);
518 					$$.vf = FIX_ROW | FIX_COL; }
519 	|	VAR		{ $$ = $1.left; }
520 	;
521 
522 var_or_range:	range		{ $$ = $1; }
523 	|	var		{ $$.left = $1; $$.right = $1; }
524 	;
525 
526 /* a number */
527 num:		NUMBER		{ $$ = (double) $1; }
528 	|	FNUMBER		{ $$ = $1; }
529 	|	'-' num		{ $$ = -$2; }
530 	|	'+' num		{ $$ = $2; }
531 	;
532 
533 /* a string argument */
534 strarg:		STRING		{ $$ = $1; }
535 	|	var		{
536 				    char *s, *s1;
537 				    s1 = $1.vp->label;
538 				    if (!s1)
539 					s1 = "NULL_STRING";
540 				    s = scxmalloc((unsigned)(strlen(s1)+1));
541 				    (void) strcpy(s, s1);
542 				    $$ = s;
543 				}
544   	;
545 
546 /* allows >=1 'setitem's to be listed in the same 'set' command */
547 setlist :
548 	|	setlist	setitem
549 	;
550 
551 /* things that you can 'set' */
552 setitem	:	K_AUTO		{ setauto(1); }
553 	|	K_AUTOCALC	{ setauto(1); }
554 	|	'~' K_AUTO	{ setauto(0); }
555 	|	'~' K_AUTOCALC	{ setauto(0); }
556 	|	'!' K_AUTO	{ setauto(0); }
557 	|	'!' K_AUTOCALC	{ setauto(0); }
558 	|	K_BYCOLS	{ setorder(BYCOLS); }
559 	|	K_BYROWS	{ setorder(BYROWS); }
560 	|	K_NUMERIC	{ numeric = 1; }
561 	|	'!' K_NUMERIC	{ numeric = 0; }
562 	|	K_PRESCALE	{ prescale = 0.01; }
563 	|	'!' K_PRESCALE	{ prescale = 1.0; }
564 	|	K_EXTFUN	{ extfunc = 1; }
565 	|	'!' K_EXTFUN	{ extfunc = 0; }
566 	|	K_CELLCUR	{ showcell = 1; }
567 	|	'!' K_CELLCUR	{ showcell = 0; }
568 	|	K_TOPROW	{ showtop = 1; }
569 	|	'!' K_TOPROW	{ showtop = 0; }
570 	|	K_ITERATIONS '=' NUMBER	{ setiterations($3); }
571 	|	K_TBLSTYLE '=' NUMBER	{ tbl_style = $3; }
572 	|	K_TBLSTYLE '=' K_TBL	{ tbl_style = TBL; }
573 	|	K_TBLSTYLE '=' K_LATEX	{ tbl_style = LATEX; }
574 	|	K_TBLSTYLE '=' K_SLATEX	{ tbl_style = SLATEX; }
575 	|	K_TBLSTYLE '=' K_TEX	{ tbl_style = TEX; }
576 	|	K_TBLSTYLE '=' K_FRAME	{ tbl_style = FRAME; }
577 	|	K_RNDINFINITY		{ rndinfinity = 1; FullUpdate++; }
578 	|	'!' K_RNDINFINITY	{ rndinfinity = 0; FullUpdate++; }
579 	|	K_CRACTION '=' NUMBER	{ craction = $3; }
580 	|	K_ROWLIMIT '=' NUMBER	{ rowlimit = $3; }
581 	|	K_COLLIMIT '=' NUMBER	{ collimit = $3; }
582   	;
583 
584 /* types of errors, to 'goto' */
585 errlist :	K_ERROR		{ num_search((double)0, CELLERROR); }
586 	|	K_INVALID	{ num_search((double)0, CELLINVALID); }
587 	;
588