Mercurial > ~dholland > hg > ag > index.cgi
comparison tests/agcl/parsifal/ss-fp.syn @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13d2b8934445 |
---|---|
1 { | |
2 /* | |
3 Copyright 1992, Jerome T. Holland | |
4 See the file COPYING for license and usage terms. | |
5 */ | |
6 | |
7 #include "ssd.h" | |
8 #include "kb.h" | |
9 #include "num.h" | |
10 | |
11 } | |
12 | |
13 cell name request = 255 | |
14 input line request = 254 | |
15 block request = 253 | |
16 | |
17 [ | |
18 ~allow macros | |
19 ~backtrack | |
20 ~case sensitive | |
21 ~declare pcb | |
22 ~diagnose errors | |
23 error trace | |
24 ~lines and columns | |
25 pointer input | |
26 ~test range | |
27 rule coverage | |
28 parser file name = "#.cpp" | |
29 default token type = number | |
30 disregard space | |
31 ] | |
32 | |
33 letter = 'A-Z' | |
34 bound variable = 'A-Z' | |
35 digit = '0-9' | |
36 nonzero digit = '1-9' | |
37 eof = 0 | |
38 space = ' ' | |
39 decimal point = '.' | |
40 pi = 'ã' //character code 227 | |
41 | |
42 | |
43 (void) grammar | |
44 -> cell name request, cell name:cp, eof =goto_cell = cp; | |
45 -> input line request, input line | |
46 -> conditional expression:x, | |
47 ['\n', conditional expression]..., eof =xvalue = x; | |
48 -> block request, cell name:f, to, cell name:l, | |
49 eof =first_cell=f, last_cell = l; | |
50 | |
51 (void) input line | |
52 -> cell name: loc, '=' =stuff_cell(loc); | |
53 -> '@',cell name:f, to, cell name:l,'/', | |
54 format:fmt, eof =stuff_format(fmt,f,l); | |
55 | |
56 to | |
57 -> '.', '.'? | |
58 | |
59 (format_code) format | |
60 ->'a',':', alignment:a, ',', | |
61 'c',':', conversion:c, ',', | |
62 'd',':', integer:n ={ | |
63 format_code f; | |
64 f.alignment = a; | |
65 f.conversion =c; | |
66 f.decimals = n; | |
67 f.flag = 0; | |
68 return f; | |
69 } | |
70 | |
71 (int) alignment | |
72 -> 'L' =0; | |
73 -> 'C' =1; | |
74 -> 'R' =2; | |
75 | |
76 (int) conversion | |
77 -> 'C' =0; | |
78 -> 'F' =1; | |
79 -> 'G' =2; | |
80 | |
81 (pair<int>) cell name | |
82 -> column id:col, integer:row =id_cell(row-1,col); | |
83 | |
84 (int) column id | |
85 -> letter:a, letter:b =rel_column_id(a-'A'+1, b-'A'); | |
86 -> letter:a =rel_column_id(0, a-'A'); | |
87 | |
88 (int) integer | |
89 -> nonzero digit:d =d-'0'; | |
90 -> integer:n, digit:d =10*n + d-'0'; | |
91 | |
92 conditional expression | |
93 -> x expression | |
94 -> expression:x, ':', disjunction:c, ';', conditional expression:y ={ | |
95 number z; | |
96 switch (c.tv){ | |
97 case 0: | |
98 z = y; | |
99 break; | |
100 case 1: | |
101 z = x; | |
102 break; | |
103 case 2: | |
104 z.error = 1; | |
105 } | |
106 return z; | |
107 } | |
108 | |
109 disjunction | |
110 -> conjunction | |
111 -> disjunction:x, '|', conjunction:y =x||y; | |
112 | |
113 conjunction | |
114 -> logical value | |
115 -> conjunction:x, '&', logical value:y =x&&y; | |
116 | |
117 logical value | |
118 -> comparison | |
119 -> '(', disjunction:x, ')' =x; | |
120 -> '!', '(', disjunction:x, ')' =!x; | |
121 | |
122 comparison | |
123 -> partial comparison:x, '<', expression:y =x<y; | |
124 -> partial comparison:x, '>', expression:y =x>y; | |
125 -> partial comparison:x, "<=", expression:y =x<=y; | |
126 -> partial comparison:x, ">=", expression:y =x>=y; | |
127 -> partial comparison:x, "==", expression:y =x==y; | |
128 -> partial comparison:x, "!=", expression:y =x!=y; | |
129 | |
130 partial comparison | |
131 -> x expression | |
132 -> comparison | |
133 | |
134 x expression | |
135 -> expression | |
136 -> summation | |
137 -> expression:x, '+', summation:y =x+y; | |
138 -> expression:x, '-', summation:y =x-y; | |
139 | |
140 expression | |
141 -> term | |
142 -> expression:x, '+', term:y =x+y; | |
143 -> expression:x, '-', term:y =x-y; | |
144 | |
145 term | |
146 -> xxfactor | |
147 -> term:x, '*', xxfactor:y =x*y; | |
148 | |
149 xxfactor | |
150 -> xfactor | |
151 -> function:f, xfactor:y =apply(f,y); | |
152 -> factor:x, function:f, xfactor:y =x*apply(f,y); | |
153 | |
154 xfactor | |
155 -> yfactor | |
156 -> base:x, '^', xfactor:n =pow(x,n); | |
157 -> '-', xfactor:x =-x; | |
158 | |
159 yfactor | |
160 -> factor | |
161 -> yfactor:x, '/', factor:y =x/y; | |
162 | |
163 factor | |
164 -> simple factor | |
165 -> simple factor:x, r value:y =x*y; | |
166 -> r value | |
167 | |
168 simple factor | |
169 -> l value | |
170 -> c value | |
171 -> simple factor:x, c value:y =x*y; | |
172 | |
173 l value | |
174 -> number | |
175 | |
176 c value | |
177 -> cell name:cp =cell_value(cp); | |
178 -> parens | |
179 -> pi =num(M_PI); | |
180 -> sigma, cell name:first, '.', '.'?, cell name:last =sum_cells(first,last); | |
181 | |
182 r value | |
183 -> bound variable:k =bound_variable[k-'A']; | |
184 | |
185 summation | |
186 -> sigma:xb, x expression string:xf, ':', bound variable:k, '=', | |
187 x expression:f, ',', x expression:s, "...", x expression:l = | |
188 summation(xb,xf,k-'A', f, s, l); | |
189 | |
190 (char *) sigma | |
191 -> 'ä' =(char *)PCB.pointer; //character code 228 | |
192 | |
193 (char *) x expression string | |
194 -> x expression =(char *)PCB.pointer; | |
195 | |
196 base | |
197 -> l value | |
198 -> c value | |
199 -> r value | |
200 | |
201 parens | |
202 -> '(', conditional expression:x, ')' =x; | |
203 | |
204 (function_name) function | |
205 -> "abs" =fabs; | |
206 -> "acos" = acos; | |
207 -> "asin" = asin; | |
208 -> "atan" = atan; | |
209 -> "cosh" = cosh; | |
210 -> "cos" =cos; | |
211 -> "exp" =exp; | |
212 -> "log10" = log10; | |
213 -> "log" = log; | |
214 -> "pow10" = pow10d; | |
215 -> "round" = round; | |
216 -> "sinh" = sinh; | |
217 -> "sin" =sin; | |
218 -> "sqr" =sqr; | |
219 -> "sqrt" = sqrt; | |
220 -> "tanh" = tanh; | |
221 -> "tan" = tan; | |
222 -> "trunc" = trunc; | |
223 | |
224 number | |
225 -> integer part:x, decimal point? =num(x); | |
226 -> integer part:x, decimal point, fraction part:y =num(x+y); | |
227 -> decimal point, fraction part:x =num(x); | |
228 | |
229 (double) integer part | |
230 -> digit:d =d-'0'; | |
231 -> integer part:n, digit:d =10*n+d-'0'; | |
232 | |
233 (double) fraction part | |
234 -> digit:d =(d-'0')/10.; | |
235 -> digit:d, fraction part:f =(d-'0'+f)/10.; | |
236 | |
237 { | |
238 fp_pcb_type *fp_pcb; | |
239 #define PCB (*fp_pcb) | |
240 | |
241 | |
242 #define CELL_NAME_REQUEST 255 | |
243 #define INPUT_LINE_REQUEST 254 | |
244 #define BLOCK_REQUEST 253 | |
245 | |
246 #define SYNTAX_ERROR | |
247 #define PARSER_STACK_OVERFLOW | |
248 | |
249 static int cell_refs; | |
250 static int error_flag; | |
251 | |
252 static number bound_variable[26]; | |
253 static number xvalue; | |
254 | |
255 number num(double x) { | |
256 number n; | |
257 n.error = 0; | |
258 n.truth = 1; | |
259 n.v = x; | |
260 return n; | |
261 } | |
262 | |
263 void init_bv(void) { | |
264 int i; | |
265 for (i = 0; i < 26; i++) bound_variable[i].error = 1; | |
266 } | |
267 | |
268 double round(double x) { | |
269 long n = x+.5; | |
270 return n; | |
271 } | |
272 | |
273 double trunc(double x) { | |
274 long n = x; | |
275 return n; | |
276 } | |
277 | |
278 double sqr(double x) { | |
279 return x*x; | |
280 } | |
281 | |
282 double pow10d(double x) { | |
283 long n = x; | |
284 return pow10d(n); | |
285 } | |
286 | |
287 number cell_value(pair<int> loc) { | |
288 number x; | |
289 cell_pointer cp; | |
290 int save_ef = error_flag; | |
291 | |
292 cell_refs++; | |
293 cp = ss[loc.row][loc.col]; | |
294 if (cp == NULL) { | |
295 x.truth = 1; | |
296 x.v = 0; | |
297 return x; | |
298 } | |
299 if (cp->type == text) { | |
300 x.error = 1; | |
301 x.truth = 0; | |
302 return x; | |
303 } | |
304 if (cp->type == formula) { | |
305 if ((inserted_columns || inserted_rows)); | |
306 else if (recalc_flag) { | |
307 if (cp->recalc == recalc_count) eval(cp); | |
308 if (cp->recalc & 1) circular_flag = 1; | |
309 } | |
310 } | |
311 x.error = cp->error; | |
312 x.truth = 1; | |
313 x.v = cp->value; | |
314 return x; | |
315 } | |
316 | |
317 void eval(cell_pointer cp) { | |
318 fp_pcb_type pcb, *save_pcb = fp_pcb; | |
319 | |
320 fp_pcb = &pcb; | |
321 cell_refs = 0; | |
322 PCB.pointer = (unsigned char *) &cp->text; | |
323 cp->recalc += recalc_flag; | |
324 error_flag = 0; | |
325 fp(); | |
326 cp->recalc += recalc_flag; | |
327 if (PCB.exit_flag != 1) {cp->type = text; cp->error = 1; return;} | |
328 else if (cell_refs == 0) cp->type = value; | |
329 else cp->type = formula; | |
330 { | |
331 cp->error = xvalue.error; | |
332 cp->value = xvalue.v; | |
333 } | |
334 fp_pcb = save_pcb; | |
335 } | |
336 | |
337 number evalx(char *xs) { | |
338 fp_pcb_type pcb, *save_pcb = fp_pcb; | |
339 number x; | |
340 | |
341 fp_pcb = &pcb; | |
342 PCB.pointer = (unsigned char *) xs; | |
343 error_flag = 0; | |
344 fp(); | |
345 fp_pcb = save_pcb; | |
346 return xvalue; | |
347 } | |
348 | |
349 pair<int> id_cell(int row, int col) { | |
350 pair<int> goto_cell = {0,0}; | |
351 if (row >= MAXROWS || col >= MAXCOLS) { | |
352 PCB.exit_flag = 5; | |
353 return goto_cell; | |
354 } | |
355 if (inserted_rows && row >= new_row) row += inserted_rows; | |
356 goto_cell.row = row; | |
357 goto_cell.col = col; | |
358 if (inserted_columns == 0 && inserted_rows == 0) return goto_cell; | |
359 sprintf((char *)icnptr,"%d",row+1); | |
360 icnptr += strlen((char *)icnptr); | |
361 icoptr = PCB.pointer; | |
362 return goto_cell; | |
363 } | |
364 | |
365 int matherr(struct exception *e) { | |
366 error_flag++; | |
367 e->retval = 0; | |
368 return 1; | |
369 } | |
370 | |
371 number apply(double(*f)(double), number n) { | |
372 number r; | |
373 if (n.error) return n; | |
374 error_flag = 0; | |
375 r.v = f(n.v); | |
376 r.error = error_flag != 0; | |
377 return r; | |
378 } | |
379 | |
380 number pow(number x, number n) { | |
381 number r; | |
382 r.error = x.error || n.error; | |
383 if (r.error) return r; | |
384 r.v = pow(x.v, n.v); | |
385 return r; | |
386 } | |
387 | |
388 void parse_block(void) { | |
389 int flag; | |
390 fp_pcb_type pcb; | |
391 | |
392 fp_pcb = &pcb; | |
393 PCB.pointer = (unsigned char *) text_buffer; | |
394 text_buffer[0] = BLOCK_REQUEST; | |
395 fp(); | |
396 flag = PCB.exit_flag != 1 | |
397 || first_cell.row > last_cell.row | |
398 || first_cell.col > last_cell.col | |
399 || last_cell.row > MAXROWS | |
400 || last_cell.col > MAXCOLS; | |
401 if (flag) { | |
402 kb_pcb.reduction_token = kb_bad_block_token; | |
403 display_message(&bad_block_message); | |
404 set_cursor(text_cursor); | |
405 } | |
406 else _setcursortype(_NOCURSOR); | |
407 } | |
408 | |
409 void parse_cell_name(void) { | |
410 int flag; | |
411 fp_pcb_type pcb; | |
412 | |
413 fp_pcb = &pcb; | |
414 PCB.pointer = (unsigned char *) text_buffer; | |
415 text_buffer[0] = CELL_NAME_REQUEST; | |
416 fp(); | |
417 flag = PCB.exit_flag != 1 | |
418 || goto_cell.row > MAXROWS | |
419 || goto_cell.col > MAXCOLS; | |
420 if (flag) { | |
421 kb_pcb.reduction_token = kb_bad_cell_name_token; | |
422 display_message(&bad_cell_message); | |
423 set_cursor(text_cursor); | |
424 } | |
425 else _setcursortype(_NOCURSOR); | |
426 } | |
427 | |
428 int rel_column_id(int a, int b) { | |
429 int cn = 26*a + b; | |
430 int nidc = a?2:1; | |
431 int n; | |
432 unsigned char case_bit = 0; | |
433 char *cp; | |
434 | |
435 if (inserted_columns == 0 && inserted_rows == 0) return cn; | |
436 if (cn >= new_column) cn += inserted_columns; | |
437 n = (PCB.pointer - icoptr) - nidc; | |
438 memmove((char *)icnptr, (char *)icoptr, n); | |
439 icnptr += n; | |
440 cp = (char *)PCB.pointer; | |
441 while (nidc--) case_bit |= *--cp; | |
442 case_bit &= 0x20; | |
443 cp = column_label(cn,case_bit); | |
444 strcpy((char *)icnptr,cp); | |
445 icnptr += strlen(cp); | |
446 return cn; | |
447 } | |
448 | |
449 void relabel_formula(cell_pointer cp) { | |
450 fp_pcb_type pcb, *save_pcb = fp_pcb; | |
451 | |
452 fp_pcb = &pcb; | |
453 icoptr = PCB.pointer = (unsigned char *) &cp->text; | |
454 icnptr = (unsigned char *) relabel_buf; | |
455 fp(); | |
456 assert(PCB.exit_flag == 1); | |
457 strcpy((char *)icnptr, (char *)icoptr); | |
458 cp = (cell_descriptor *) realloc(cp, sizeof(cell_descriptor) + strlen(relabel_buf)); | |
459 assert(cp); | |
460 strcpy(cp->text, relabel_buf); | |
461 fp_pcb = save_pcb; | |
462 } | |
463 | |
464 void scan_input_line(void) { | |
465 fp_pcb_type pcb, *save_pcb = fp_pcb; | |
466 | |
467 fp_pcb = &pcb; | |
468 PCB.pointer = (unsigned char *) text_buffer; | |
469 text_buffer[0] = INPUT_LINE_REQUEST; | |
470 fp(); | |
471 fp_pcb = save_pcb; | |
472 } | |
473 | |
474 void set_column_width(void) { | |
475 int n; | |
476 char *tb = text_buffer + 1; | |
477 int flag; | |
478 | |
479 highlight_off(); | |
480 for (n = 0; *tb;) n = 10*n + *tb++ - '0'; | |
481 flag = n < 3 || n > 75; | |
482 if (flag) { | |
483 kb_pcb.reduction_token = kb_column_width_request_token; | |
484 display_message(&bad_cw_message); | |
485 beep(); | |
486 set_cursor(text_cursor); | |
487 return; | |
488 } | |
489 _setcursortype(_NOCURSOR); | |
490 if (ac.scc.col + n > 81) move_data_left(); | |
491 cols[ac.ssc.col].width = n; | |
492 display_column_guide(); | |
493 update_screen(); | |
494 highlight_on(); | |
495 } | |
496 | |
497 | |
498 void stuff_cell(pair<int> loc) { | |
499 char *tb = (char *) fp_pcb->pointer; | |
500 cell_pointer cp = (cell_descriptor *) realloc( | |
501 ss[loc.row][loc.col], | |
502 sizeof(cell_descriptor) + strlen(tb)); | |
503 | |
504 assert(cp); | |
505 if (loc.row > max_row) max_row = loc.row; | |
506 if (loc.col > max_col) max_col = loc.col; | |
507 strcpy(cp->text, tb); | |
508 ss[loc.row][loc.col] = cp; | |
509 cp->recalc = recalc_count; | |
510 eval(cp); | |
511 } | |
512 | |
513 void stuff_format(format_code f,pair<int> first,pair<int> last){ | |
514 int i,j; | |
515 for (i=first.row;i<=last.row;i++) for (j=first.col;j<=last.col;j++) { | |
516 fmt[i][j] = f; | |
517 } | |
518 if (last.row > fmt_max_row) fmt_max_row = last.row; | |
519 if (last.col > fmt_max_col) fmt_max_col = last.col; | |
520 } | |
521 | |
522 number sum_cells(pair<int> first,pair<int> last){ | |
523 pair<int> cp; | |
524 number sum; | |
525 sum.error = sum.truth = 1; | |
526 sum.v = 0; | |
527 for (cp.row = first.row; cp.row <= last.row; cp.row++) | |
528 for (cp.col = first.col; cp.col <= last.col; cp.col++) { | |
529 number cv = cell_value(cp); | |
530 if (cv.error) return sum; | |
531 sum.v += cv.v; | |
532 } | |
533 sum.error = 0; | |
534 return sum; | |
535 } | |
536 | |
537 number summation(char *xb, char *xf, int bv, number f, number s, number l) { | |
538 number sum; | |
539 int k; | |
540 char *xs; | |
541 number delta; | |
542 int n; | |
543 | |
544 sum.error = f.error + s.error + l.error; | |
545 sum.v = 0; | |
546 if (sum.error) return sum; | |
547 k = (int) (xf - xb); | |
548 xs = (char *) malloc(k+1); | |
549 memmove(xs,xb,k); | |
550 xs[k] = 0; | |
551 delta = s-f; | |
552 if (delta.v == 0) { | |
553 sum.error = 1; | |
554 return sum; | |
555 } | |
556 n = ((l-f+delta)/delta).v + .5; | |
557 while (n--) { | |
558 bound_variable[bv] = f; | |
559 sum = sum + evalx(xs); | |
560 if (sum.error) break; | |
561 f = f+delta; | |
562 } | |
563 bound_variable[bv].error = 1; | |
564 free(xs); | |
565 return sum; | |
566 } | |
567 | |
568 | |
569 } | |
570 | |
571 | |
572 |