Commit | Line | Data |
---|---|---|
efc7f434 KB |
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: 6.8 $ | |
13 | */ | |
14 | ||
15 | ||
16 | ||
17 | %{ | |
18 | #include <curses.h> | |
19 | #include "sc.h" | |
20 | ||
21 | #define ENULL (struct enode *)0 | |
22 | ||
23 | char *strcpy(); | |
24 | %} | |
25 | ||
26 | %union { | |
27 | int ival; | |
28 | double fval; | |
29 | struct ent_ptr ent; | |
30 | struct enode *enode; | |
31 | char *sval; | |
32 | struct range_s rval; | |
33 | } | |
34 | ||
35 | %type <ent> var | |
36 | %type <fval> num | |
37 | %type <rval> range | |
38 | %type <rval> var_or_range | |
39 | %type <sval> strarg | |
40 | %type <enode> e term expr_list | |
41 | %token <sval> STRING | |
42 | %token <ival> NUMBER | |
43 | %token <fval> FNUMBER | |
44 | %token <rval> RANGE | |
45 | %token <rval> VAR | |
46 | %token <sval> WORD | |
47 | %token <ival> COL | |
48 | %token S_FORMAT | |
49 | %token S_LABEL | |
50 | %token S_LEFTSTRING | |
51 | %token S_RIGHTSTRING | |
52 | %token S_GET | |
53 | %token S_PUT | |
54 | %token S_MERGE | |
55 | %token S_LET | |
56 | %token S_WRITE | |
57 | %token S_TBL | |
58 | %token S_COPY | |
59 | %token S_SHOW | |
60 | %token S_ERASE | |
61 | %token S_FILL | |
62 | %token S_GOTO | |
63 | %token S_DEFINE | |
64 | %token S_UNDEFINE | |
65 | %token S_VALUE | |
66 | %token S_MDIR | |
67 | %token S_HIDE | |
68 | %token S_SET | |
69 | ||
70 | %token K_FIXED | |
71 | %token K_SUM | |
72 | %token K_PROD | |
73 | %token K_AVG | |
74 | %token K_STDDEV | |
75 | %token K_COUNT | |
76 | %token K_ABS | |
77 | %token K_ACOS | |
78 | %token K_ASIN | |
79 | %token K_ATAN | |
80 | %token K_ATAN2 | |
81 | %token K_CEIL | |
82 | %token K_COS | |
83 | %token K_EXP | |
84 | %token K_FABS | |
85 | %token K_FLOOR | |
86 | %token K_HYPOT | |
87 | %token K_LN | |
88 | %token K_LOG | |
89 | %token K_PI | |
90 | %token K_POW | |
91 | %token K_SIN | |
92 | %token K_SQRT | |
93 | %token K_TAN | |
94 | %token K_DTR | |
95 | %token K_RTD | |
96 | %token K_MAX | |
97 | %token K_MIN | |
98 | %token K_RND | |
99 | %token K_ROUND | |
100 | %token K_IF | |
101 | ||
102 | %token K_PV | |
103 | %token K_FV | |
104 | %token K_PMT | |
105 | ||
106 | %token K_HOUR | |
107 | %token K_MINUTE | |
108 | %token K_SECOND | |
109 | %token K_MONTH | |
110 | %token K_DAY | |
111 | %token K_YEAR | |
112 | %token K_NOW | |
113 | %token K_DATE | |
114 | %token K_DTS | |
115 | %token K_TTS | |
116 | %token K_FMT | |
117 | %token K_SUBSTR | |
118 | %token K_STON | |
119 | %token K_EQS | |
120 | %token K_EXT | |
121 | %token K_NVAL | |
122 | %token K_SVAL | |
123 | %token K_LOOKUP | |
124 | %token K_HLOOKUP | |
125 | %token K_VLOOKUP | |
126 | %token K_INDEX | |
127 | %token K_STINDEX | |
128 | %token K_AUTO | |
129 | %token K_AUTOCALC | |
130 | %token K_BYROWS | |
131 | %token K_BYCOLS | |
132 | %token K_BYGRAPH | |
133 | %token K_ITERATIONS | |
134 | %token K_NUMERIC | |
135 | %token K_PRESCALE | |
136 | %token K_EXTFUN | |
137 | %token K_CELLCUR | |
138 | %token K_TOPROW | |
139 | %token K_TBLSTYLE | |
140 | %token K_TBL | |
141 | %token K_LATEX | |
142 | %token K_TEX | |
143 | ||
144 | %left '?' ':' | |
145 | %left '|' | |
146 | %left '&' | |
147 | %nonassoc '<' '=' '>' '!' | |
148 | %left '+' '-' '#' | |
149 | %left '*' '/' '%' | |
150 | %left '^' | |
151 | ||
152 | %% | |
153 | command: S_LET var_or_range '=' e | |
154 | { let($2.left.vp, $4); } | |
155 | | S_LABEL var_or_range '=' e | |
156 | { slet($2.left.vp, $4, 0); } | |
157 | | S_LEFTSTRING var_or_range '=' e | |
158 | { slet($2.left.vp, $4, -1); } | |
159 | | S_RIGHTSTRING var_or_range '=' e | |
160 | { slet($2.left.vp, $4, 1); } | |
161 | | S_FORMAT COL ':' COL NUMBER NUMBER | |
162 | { doformat($2,$4,$5,$6); } | |
163 | | S_FORMAT COL NUMBER NUMBER | |
164 | { doformat($2,$2,$3,$4); } | |
165 | | S_GET strarg { /* This tmp hack is because readfile | |
166 | * recurses back through yyparse. */ | |
167 | char *tmp; | |
168 | tmp = $2; | |
169 | readfile (tmp, 1); | |
170 | xfree(tmp); | |
171 | } | |
172 | | S_MERGE strarg { | |
173 | char *tmp; | |
174 | tmp = $2; | |
175 | readfile (tmp, 0); | |
176 | xfree(tmp); | |
177 | } | |
178 | | S_MDIR strarg | |
179 | { if (mdir) xfree(mdir); mdir = $2; } | |
180 | | S_PUT strarg range | |
181 | { (void) writefile($2, ($3.left.vp)->row, | |
182 | ($3.left.vp)->col, ($3.right.vp)->row, | |
183 | ($3.right.vp)->col); | |
184 | xfree($2); } | |
185 | | S_PUT strarg | |
186 | { (void) writefile ($2, 0, 0, maxrow, maxcol); | |
187 | xfree($2); } | |
188 | | S_WRITE strarg range { (void) printfile($2, ($3.left.vp)->row, | |
189 | ($3.left.vp)->col, ($3.right.vp)->row, | |
190 | ($3.right.vp)->col); | |
191 | xfree($2); } | |
192 | | S_WRITE strarg { (void) printfile ($2, 0, 0, maxrow, maxcol); | |
193 | xfree($2); } | |
194 | | S_TBL strarg range { (void) tblprintfile($2, ($3.left.vp)->row, | |
195 | ($3.left.vp)->col, ($3.right.vp)->row, | |
196 | ($3.right.vp)->col); | |
197 | xfree($2); } | |
198 | | S_TBL strarg { (void)tblprintfile ($2, 0, 0, maxrow, maxcol); | |
199 | xfree($2); } | |
200 | | S_SHOW COL ':' COL | |
201 | { showcol( $2, $4); } | |
202 | | S_SHOW NUMBER ':' NUMBER | |
203 | { showrow( $2, $4); } | |
204 | | S_HIDE COL | |
205 | { hide_col( $2 ); } | |
206 | | S_HIDE NUMBER | |
207 | { hide_row( $2 ); } | |
208 | | S_COPY range var_or_range | |
209 | { copy($2.left.vp,$2.right.vp, | |
210 | $3.left.vp,$3.right.vp); } | |
211 | | S_ERASE | |
212 | { eraser(lookat(showsr, showsc), | |
213 | lookat(currow, curcol)); } | |
214 | | S_ERASE var_or_range | |
215 | { eraser($2.left.vp, $2.right.vp); } | |
216 | | S_VALUE { valueize_area(showsr, showsc, currow, curcol); | |
217 | modflg++; } | |
218 | | S_VALUE var_or_range { valueize_area(($2.left.vp)->row, | |
219 | ($2.left.vp)->col, | |
220 | ($2.right.vp)->row, | |
221 | ($2.right.vp)->col); modflg++; } | |
222 | | S_FILL num num { fill(lookat(showsr, showsc), | |
223 | lookat(currow, curcol), $2, $3); } | |
224 | | S_FILL var_or_range num num | |
225 | { fill($2.left.vp, $2.right.vp, $3, $4); } | |
226 | | S_GOTO var_or_range {moveto($2.left.vp->row, $2.left.vp->col);} | |
227 | | S_GOTO num {num_search($2);} | |
228 | | S_GOTO STRING {str_search($2);} | |
229 | | S_GOTO {go_last();} | |
230 | | S_DEFINE strarg { struct ent_ptr arg1, arg2; | |
231 | arg1.vp = lookat(showsr, showsc); | |
232 | arg1.vf = 0; | |
233 | arg2.vp = lookat(currow, curcol); | |
234 | arg2.vf = 0; | |
235 | add_range($2, arg1, arg2, 1); } | |
236 | ||
237 | | S_DEFINE strarg range { add_range($2, $3.left, $3.right, 1); } | |
238 | | S_DEFINE strarg var { add_range($2, $3, $3, 0); } | |
239 | | S_UNDEFINE var_or_range { del_range($2.left.vp, $2.right.vp); } | |
240 | | S_SET setlist | |
241 | | /* nothing */ | |
242 | | error; | |
243 | ||
244 | term: var { $$ = new_var('v', $1); } | |
245 | | K_FIXED term { $$ = new ('f', ENULL, $2); } | |
246 | | '@' K_SUM '(' var_or_range ')' | |
247 | { $$ = new_range(REDUCE | '+', $4); } | |
248 | | '@' K_PROD '(' var_or_range ')' | |
249 | { $$ = new_range (REDUCE | '*', $4); } | |
250 | | '@' K_AVG '(' var_or_range ')' | |
251 | { $$ = new_range (REDUCE | 'a', $4); } | |
252 | | '@' K_STDDEV '(' var_or_range ')' | |
253 | { $$ = new_range (REDUCE | 's', $4); } | |
254 | | '@' K_COUNT '(' var_or_range ')' | |
255 | { $$ = new_range (REDUCE | 'c', $4); } | |
256 | | '@' K_MAX '(' var_or_range ')' | |
257 | { $$ = new_range (REDUCE | MAX, $4); } | |
258 | | '@' K_MAX '(' e ',' expr_list ')' | |
259 | { $$ = new(LMAX, $6, $4); } | |
260 | | '@' K_MIN '(' var_or_range ')' | |
261 | { $$ = new_range (REDUCE | MIN, $4); } | |
262 | | '@' K_MIN '(' e ',' expr_list ')' | |
263 | { $$ = new(LMIN, $6, $4); } | |
264 | | '@' K_ABS '(' e ')' { $$ = new(ABS, ENULL, $4); } | |
265 | | '@' K_ACOS '(' e ')' { $$ = new(ACOS, ENULL, $4); } | |
266 | | '@' K_ASIN '(' e ')' { $$ = new(ASIN, ENULL, $4); } | |
267 | | '@' K_ATAN '(' e ')' { $$ = new(ATAN, ENULL, $4); } | |
268 | | '@' K_ATAN2 '(' e ',' e ')' { $$ = new(ATAN2, $4, $6); } | |
269 | | '@' K_CEIL '(' e ')' { $$ = new(CEIL, ENULL, $4); } | |
270 | | '@' K_COS '(' e ')' { $$ = new(COS, ENULL, $4); } | |
271 | | '@' K_EXP '(' e ')' { $$ = new(EXP, ENULL, $4); } | |
272 | | '@' K_FABS '(' e ')' { $$ = new(FABS, ENULL, $4); } | |
273 | | '@' K_FLOOR '(' e ')' { $$ = new(FLOOR, ENULL, $4); } | |
274 | | '@' K_HYPOT '(' e ',' e ')' { $$ = new(HYPOT, $4, $6); } | |
275 | | '@' K_LN '(' e ')' { $$ = new(LOG, ENULL, $4); } | |
276 | | '@' K_LOG '(' e ')' { $$ = new(LOG10, ENULL, $4); } | |
277 | | '@' K_POW '(' e ',' e ')' { $$ = new(POW, $4, $6); } | |
278 | | '@' K_SIN '(' e ')' { $$ = new(SIN, ENULL, $4); } | |
279 | | '@' K_SQRT '(' e ')' { $$ = new(SQRT, ENULL, $4); } | |
280 | | '@' K_TAN '(' e ')' { $$ = new(TAN, ENULL, $4); } | |
281 | | '@' K_DTR '(' e ')' { $$ = new(DTR, ENULL, $4); } | |
282 | | '@' K_RTD '(' e ')' { $$ = new(RTD, ENULL, $4); } | |
283 | | '@' K_RND '(' e ')' { $$ = new(RND, ENULL, $4); } | |
284 | | '@' K_ROUND '(' e ',' e ')' { $$ = new(ROUND, $4, $6); } | |
285 | | '@' K_IF '(' e ',' e ',' e ')' { $$ = new(IF, $4,new(',',$6,$8)); } | |
286 | ||
287 | | '@' K_PV '(' e ',' e ',' e ')' { $$ = new(PV, $4,new(':',$6,$8)); } | |
288 | | '@' K_FV '(' e ',' e ',' e ')' { $$ = new(FV, $4,new(':',$6,$8)); } | |
289 | | '@' K_PMT '(' e ',' e ',' e ')' { $$ = new(PMT, $4,new(':',$6,$8)); } | |
290 | ||
291 | | '@' K_HOUR '(' e ')' { $$ = new(HOUR,ENULL, $4); } | |
292 | | '@' K_MINUTE '(' e ')' { $$ = new(MINUTE,ENULL, $4); } | |
293 | | '@' K_SECOND '(' e ')' { $$ = new(SECOND,ENULL, $4); } | |
294 | | '@' K_MONTH '(' e ')' { $$ = new(MONTH,ENULL,$4); } | |
295 | | '@' K_DAY '(' e ')' { $$ = new(DAY, ENULL, $4); } | |
296 | | '@' K_YEAR '(' e ')' { $$ = new(YEAR, ENULL, $4); } | |
297 | | '@' K_NOW { $$ = new(NOW, ENULL, ENULL);} | |
298 | | '@' K_DTS '(' e ',' e ',' e ')' | |
299 | { $$ = new(DTS, $4, new(',', $6, $8));} | |
300 | | '@' K_TTS '(' e ',' e ',' e ')' | |
301 | { $$ = new(TTS, $4, new(',', $6, $8));} | |
302 | | '@' K_STON '(' e ')' { $$ = new(STON, ENULL, $4); } | |
303 | | '@' K_EQS '(' e ',' e ')' { $$ = new (EQS, $4, $6); } | |
304 | | '@' K_DATE '(' e ')' { $$ = new(DATE, ENULL, $4); } | |
305 | | '@' K_FMT '(' e ',' e ')' { $$ = new(FMT, $4, $6); } | |
306 | | '@' K_INDEX '(' e ',' var_or_range ')' | |
307 | { $$ = new(INDEX, $4, new_range(REDUCE | INDEX, $6)); } | |
308 | | '@' K_LOOKUP '(' e ',' var_or_range ')' | |
309 | { $$ = new(LOOKUP, $4, new_range(REDUCE | LOOKUP, $6)); } | |
310 | | '@' K_HLOOKUP '(' e ',' var_or_range ',' e ')' | |
311 | { $$ = new(HLOOKUP, new(',', $4, $8), | |
312 | new_range(REDUCE | HLOOKUP, $6)); } | |
313 | | '@' K_VLOOKUP '(' e ',' var_or_range ',' e ')' | |
314 | { $$ = new(VLOOKUP, new(',', $4, $8), | |
315 | new_range(REDUCE | VLOOKUP, $6)); } | |
316 | | '@' K_STINDEX '(' e ',' var_or_range ')' | |
317 | { $$ = new(STINDEX, $4, new_range(REDUCE | STINDEX, $6)); } | |
318 | | '@' K_EXT '(' e ',' e ')' { $$ = new(EXT, $4, $6); } | |
319 | | '@' K_NVAL '(' e ',' e ')' { $$ = new(NVAL, $4, $6); } | |
320 | | '@' K_SVAL '(' e ',' e ')' { $$ = new(SVAL, $4, $6); } | |
321 | | '@' K_SUBSTR '(' e ',' e ',' e ')' | |
322 | { $$ = new(SUBSTR, $4, new(',', $6, $8)); } | |
323 | | '(' e ')' { $$ = $2; } | |
324 | | '+' term { $$ = $2; } | |
325 | | '-' term { $$ = new ('m', ENULL, $2); } | |
326 | | NUMBER { $$ = new_const('k', (double) $1); } | |
327 | | FNUMBER { $$ = new_const('k', $1); } | |
328 | | K_PI { $$ = new_const('k', (double)3.14159265358979323846); } | |
329 | | STRING { $$ = new_str($1); } | |
330 | | '~' term { $$ = new ('~', ENULL, $2); } | |
331 | | '!' term { $$ = new ('~', ENULL, $2); } | |
332 | ; | |
333 | ||
334 | e: e '+' e { $$ = new ('+', $1, $3); } | |
335 | | e '-' e { $$ = new ('-', $1, $3); } | |
336 | | e '*' e { $$ = new ('*', $1, $3); } | |
337 | | e '/' e { $$ = new ('/', $1, $3); } | |
338 | | e '%' e { $$ = new ('%', $1, $3); } | |
339 | | e '^' e { $$ = new ('^', $1, $3); } | |
340 | | term | |
341 | | e '?' e ':' e { $$ = new ('?', $1, new(':', $3, $5)); } | |
342 | | e '<' e { $$ = new ('<', $1, $3); } | |
343 | | e '=' e { $$ = new ('=', $1, $3); } | |
344 | | e '>' e { $$ = new ('>', $1, $3); } | |
345 | | e '&' e { $$ = new ('&', $1, $3); } | |
346 | | e '|' e { $$ = new ('|', $1, $3); } | |
347 | | e '<' '=' e { $$ = new ('~', ENULL, new ('>', $1, $4)); } | |
348 | | e '!' '=' e { $$ = new ('~', ENULL, new ('=', $1, $4)); } | |
349 | | e '>' '=' e { $$ = new ('~', ENULL, new ('<', $1, $4)); } | |
350 | | e '#' e { $$ = new ('#', $1, $3); } | |
351 | ; | |
352 | ||
353 | expr_list: e { $$ = new(ELIST, ENULL, $1); } | |
354 | | expr_list ',' e { $$ = new(ELIST, $1, $3); } | |
355 | ; | |
356 | ||
357 | range: var ':' var { $$.left = $1; $$.right = $3; } | |
358 | | RANGE { $$ = $1; } | |
359 | ; | |
360 | ||
361 | var: COL NUMBER { $$.vp = lookat($2 , $1); $$.vf = 0;} | |
362 | | '$' COL NUMBER { $$.vp = lookat($3 , $2); | |
363 | $$.vf = FIX_COL;} | |
364 | | COL '$' NUMBER { $$.vp = lookat($3 , $1); | |
365 | $$.vf = FIX_ROW;} | |
366 | | '$' COL '$' NUMBER { $$.vp = lookat($4 , $2); | |
367 | $$.vf = FIX_ROW | FIX_COL;} | |
368 | | VAR { $$ = $1.left; } | |
369 | ; | |
370 | ||
371 | var_or_range: range { $$ = $1; } | |
372 | | var { $$.left = $1; $$.right = $1; } | |
373 | ; | |
374 | ||
375 | num: NUMBER { $$ = (double) $1; } | |
376 | | FNUMBER { $$ = $1; } | |
377 | | '-' num { $$ = -$2; } | |
378 | | '+' num { $$ = $2; } | |
379 | ; | |
380 | ||
381 | strarg: STRING { $$ = $1; } | |
382 | | var { | |
383 | char *s, *s1; | |
384 | s1 = $1.vp->label; | |
385 | if (!s1) | |
386 | s1 = "NULL_STRING"; | |
387 | s = xmalloc((unsigned)strlen(s1)+1); | |
388 | (void) strcpy(s, s1); | |
389 | $$ = s; | |
390 | } | |
391 | ; | |
392 | ||
393 | setlist : | |
394 | | setlist setitem | |
395 | ; | |
396 | ||
397 | setitem : K_AUTO { setauto(1); } | |
398 | | K_AUTOCALC { setauto(1); } | |
399 | | '~' K_AUTO { setauto(0); } | |
400 | | '~' K_AUTOCALC { setauto(0); } | |
401 | | '!' K_AUTO { setauto(0); } | |
402 | | '!' K_AUTOCALC { setauto(0); } | |
403 | | K_BYCOLS { setorder(BYCOLS); } | |
404 | | K_BYROWS { setorder(BYROWS); } | |
405 | | K_BYGRAPH { setorder(BYGRAPH); } | |
406 | | K_NUMERIC { numeric = 1; } | |
407 | | '!' K_NUMERIC { numeric = 0; } | |
408 | | K_PRESCALE { prescale = 0.01; } | |
409 | | '!' K_PRESCALE { prescale = 1.0; } | |
410 | | K_EXTFUN { extfunc = 1; } | |
411 | | '!' K_EXTFUN { extfunc = 0; } | |
412 | | K_CELLCUR { showcell = 1; } | |
413 | | '!' K_CELLCUR { showcell = 0; } | |
414 | | K_TOPROW { showtop = 1; } | |
415 | | '!' K_TOPROW { showtop = 0; } | |
416 | | K_ITERATIONS '=' NUMBER { setiterations($3); } | |
417 | | K_TBLSTYLE '=' NUMBER { tbl_style = $3; } | |
418 | | K_TBLSTYLE '=' K_TBL { tbl_style = TBL; } | |
419 | | K_TBLSTYLE '=' K_LATEX { tbl_style = LATEX; } | |
420 | | K_TBLSTYLE '=' K_TEX { tbl_style = TEX; } | |
421 | ; |