1: /* formula parser
2: Copyright (C) 1992-2000 Michigan State University
3:
4: The CAPA system is free software; you can redistribute it and/or
5: modify it under the terms of the GNU Library General Public License as
6: published by the Free Software Foundation; either version 2 of the
7: License, or (at your option) any later version.
8:
9: The CAPA system is distributed in the hope that it will be useful,
10: but WITHOUT ANY WARRANTY; without even the implied warranty of
11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12: Library General Public License for more details.
13:
14: You should have received a copy of the GNU Library General Public
15: License along with the CAPA system; see the file COPYING. If not,
16: write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17: Boston, MA 02111-1307, USA. */
18:
19: /* ====================================================== */
20: /* capaFormula.y created by Isaac Tsai @ Feb 1999 */
21: /* copyrighted by Isaac Tsai 1999 */
22: /* TODO: checking user inputs 2/27/99 IT */
23: /* ====================================================== */
24: %{
25: #include <stdio.h>
26: #include <ctype.h>
27: #include <string.h>
28: #include <math.h>
29: #include "capaParser.h" /* _symbol structure def */
30: #include "capaCommon.h"
31: #include "capaFunction.h"
32: #ifdef YYSTYPE
33: #undef YYSTYPE
34: #endif
35: #define YYSTYPE Symbol_p
36: #include "capaToken.h"
37:
38: #ifdef __hpux
39: #include <stdlib.h>
40: #include <alloca.h>
41: #endif
42:
43: #ifdef FML_DBUG
44: #define FMLDBUG_PR1(xx) { printf(xx); fflush(stdout); }
45: #define FMLDBUG_PR2(xx,yy) { printf(xx,yy); fflush(stdout); }
46: #define FMLDBUG_PR3(xx,yy,zz) { printf(xx,yy,zz); fflush(stdout); }
47: #else
48: #define FMLDBUG_PR1(xx) { }
49: #define FMLDBUG_PR2(xx,yy) { }
50: #define FMLDBUG_PR3(xx,yy,zz) { }
51: #endif
52:
53: #define ADD_op 1
54: #define SUB_op 2
55: #define MUL_op 3
56: #define DIV_op 4
57: #define IDIV_op 5
58: #define NOT_DEFINED_op 9
59:
60:
61: /* =============================================================== */
62:
63: extern int Func_idx;
64: extern Symbol FuncStack[MAX_FUNC_NEST];
65: void fml_error(char *msg);
66: double FormulaVal;
67: int FormulaParseOK=1;
68:
69: %}
70:
71:
72: %token F_NUMBER V_ID F_ID EoI F_ERROR
73: %left F_PLUS F_MINUS
74: %left F_MULT F_DIV F_MOD
75: %token F_POW F_LPAR F_RPAR F_COMMA
76:
77:
78: %start f_expr
79:
80:
81: %%
82:
83: f_expr : block { switch($1->s_type) {
84: case I_VAR:
85: case I_CONSTANT: FormulaVal = (double)($1->s_int);
86: break;
87: case R_VAR:
88: case R_CONSTANT: FormulaVal = $1->s_real;
89: break;
90: case S_VAR:
91: case S_CONSTANT: FormulaParseOK = 0;
92: break;
93: default: FormulaParseOK = 0;
94: break;
95: }
96: capa_mfree((char *)$1);
97: FMLDBUG_PR1("[f_expr <= block ]\n");
98: }
99: ;
100:
101: block : block F_PLUS term { $$ = symbols_op($1, $3, ADD_op); }
102: | block F_MINUS term { $$ = symbols_op($1, $3, SUB_op); }
103: | term { $$ = $1; }
104: | F_ERROR { FormulaParseOK = 0; FMLDBUG_PR1("[F_ERROR]\n"); return 0;}
105: | error { FormulaParseOK = 0; FMLDBUG_PR1("[ERROR]\n"); return 0; }
106: ;
107:
108: term : term F_MULT basic_constr { $$ = symbols_op($1, $3, MUL_op); }
109: | term F_DIV basic_constr { $$ = symbols_op($1, $3, DIV_op); }
110: | term F_MOD basic_constr { $$ = symbols_op($1, $3, IDIV_op); }
111: | basic_constr { $$ = $1; }
112: ;
113:
114: basic_constr : basic_constr F_POW basic_item { $$ = f_symbol_pow($1,$3);
115: FMLDBUG_PR3("[%.16g ^ %.16g] ",$1->s_real,$3->s_real); }
116: | basic_item { $$ = $1; }
117: ;
118:
119: arg_list : arg_list F_COMMA block { $$ = $1;
120: $$->s_argc++;
121: $$->s_argp = addto_arglist($1->s_argp, $3);
122: }
123: | block { $$ = $1;
124: $$->s_argc = 1;
125: $$->s_argp = new_arglist($1);
126: }
127: ;
128:
129: basic_item : F_ID F_LPAR F_RPAR { int tmp;
130:
131: Func_idx--;
132: if(Func_idx >= 0 ) {
133: tmp = match_function(FuncStack[Func_idx].s_name,0);
134: $$ = do_function(tmp, 0, NULL );
135: capa_mfree(FuncStack[Func_idx].s_name);
136: }
137: }
138: | F_ID F_LPAR arg_list F_RPAR { int tmp;
139:
140: Func_idx--;
141: if(Func_idx >= 0 ) {
142: tmp = match_function(FuncStack[Func_idx].s_name,$3->s_argc);
143: $$ = do_function(tmp, $3->s_argc, $3->s_argp);
144: capa_mfree(FuncStack[Func_idx].s_name);
145: free_arglist($3->s_argp);
146: }
147: }
148: | V_ID { FMLDBUG_PR3("[V %s = %.16g] ",$1->s_name, $1->s_real);
149: $$ = $1;
150: }
151: | F_MINUS basic_item { $$ = $2;
152: switch($2->s_type) {
153: case I_VAR: $$ = (Symbol *)capa_malloc(sizeof(Symbol),1);
154: $$->s_type = I_CONSTANT;
155: case I_CONSTANT: $$->s_int = - $2->s_int; break;
156: case R_VAR: $$ = (Symbol *)capa_malloc(sizeof(Symbol),1);
157: $$->s_type = R_CONSTANT;
158: case R_CONSTANT: $$->s_real = (-1.0)*($2->s_real);
159: break;
160: case S_VAR:
161: case S_CONSTANT: break;
162: default: break;
163: }
164: }
165: | F_PLUS basic_item { $$ = $2; }
166: | F_NUMBER { FMLDBUG_PR2("[F %.16g] ",$1->s_real);
167: $$ = $1;
168: }
169: | F_LPAR block F_RPAR { $$ = $2; }
170: ;
171: %%
172: void
173: fml_error(char *msg)
174: {
175: FormulaParseOK=0;
176: printf("Error Parsing: %s\n",msg);
177:
178: }
179: /* ---------------------------------------------------- */
180: Symbol *
181: f_symbol_pow(ap,bp) Symbol *ap; Symbol *bp;
182: {
183: Symbol *cp;
184: double a, b;
185: int error = 0;
186:
187: cp = NULL;
188: switch(ap->s_type) {
189: case I_VAR: a = (double)(ap->s_int);
190: break;
191: case I_CONSTANT: a = (double)(ap->s_int); capa_mfree((char *)ap);
192: break;
193: case R_VAR: a = ap->s_real;
194: break;
195: case R_CONSTANT: a = ap->s_real; capa_mfree((char *)ap);
196: break;
197: case S_VAR:
198: case S_CONSTANT:
199: default: error = 1; break;
200: }
201: switch(bp->s_type) {
202: case I_VAR: b = (double)(bp->s_int);
203: break;
204: case I_CONSTANT: b = (double)(bp->s_int); capa_mfree((char *)bp);
205: break;
206: case R_VAR: b = bp->s_real;
207: break;
208: case R_CONSTANT: b = bp->s_real; capa_mfree((char *)bp);
209: break;
210: case S_VAR:
211: case S_CONSTANT:
212: default: error = 1; break;
213: }
214: if ((!(((double)((int)b)) == b)) && (a < 0.0)) {
215: error = 1;
216: }
217: if (!error) {
218: cp = (Symbol *)capa_malloc(sizeof(Symbol),1);
219: cp->s_type = R_CONSTANT;
220: cp->s_real = pow(a,b);
221:
222: }
223: return (cp);
224: }
225:
226: /* ============================================================================= */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>