second preliminary version
[calc.git] / parser.c
CommitLineData
bc97a989
LM
1#include <malloc.h>
2#include <stdlib.h>
3
4#include "debug.h"
5#include "fdprintf.h"
6
7#include "parser.h"
8
9/* compare codes */
10
11int codecmp (char *ref, char *str)
12{
13 int sig;
14
15 while (*ref != '\0') {
16 sig = *str++ - *ref++;
17 if (sig != 0) {
18 return (sig > 0) ? 1 : -1;
19 }
20 }
21
22 return 0;
23}
24
25/* allocate new element */
26
27element_t *newelement (func_t function, int nbops)
28{
29 element_t *new = (element_t *) calloc (1, sizeof (element_t));
30 if (new == NULL) {
31 VERBOSE (ERROR, fdprintf (stdfderr, "can't allocate memory\n"));
32 return NULL;
33 }
34 new->func = function;
35 new->nbops = nbops;
36
37 return new;
38}
39
40/* functions */
41
42#define NB_OPERATORS 7
43
44keyword_t operators[NB_OPERATORS] = {
45 { "+ ", Add, 2, 1 },
46 { "+\t", Add, 2, 1 },
47 { "- ", Sub, 2, 1 },
49223129 48 { "-\t", Sub, 2, 1 },
bc97a989
LM
49 { "*", Mul, 2, 1 },
50 { "/", Div, 2, 1 },
51 { "^", Pow, 2, 1 }
52};
53
54#define NB_FUNCTIONS 7
55keyword_t functions[NB_FUNCTIONS] = {
56 { "sqrt", Sqr, 1, 4 },
57 { "pow", Pow, 2, 3 },
58 { "cos", Cos, 1, 3 },
59 { "sin", Sin, 1, 3 },
60 { "atan", Atn, 1, 4 },
61 { "exp", Exp, 1, 3 },
62 { "log", Log, 1, 3 }
63};
64
65/* parser function */
66
0b489a77
LM
67element_t *parser (char *str, char **next)
68{
bc97a989 69 element_t *root = NULL;
0b489a77 70 int i, j;
bc97a989 71
49223129
LM
72 VERBOSE (DEBUG, PRINTOUT ("Starting parsing\n"));
73
bc97a989
LM
74 /* main loop */
75 while (*str != '\0') {
76 int found = 0;
77 element_t *new = NULL;
49223129 78 VERBOSE (INFO, PRINTOUT ("Processing: %s\n", str));
bc97a989
LM
79
80 /* skip spaces and tabs */
81
82 if ((*str == ' ') || (*str == '\t')) {
83 str++;
84 continue;
85 }
86
0b489a77
LM
87 /* skip commas */
88
89 if (*str == ',') {
90 if (root == NULL) {
91 return ERROR_OP;
92 } else if (root->func != Set) {
93 new = newelement (Set, MAX_OPERANDS);
94 new->ops[0] = root;
95 root = new;
96 }
97 str++;
98 continue;
99 }
100
101 /* check for parent */
102
0b489a77 103 if (*str == '(') {
49223129 104 VERBOSE (DEBUG, PRINTOUT ("start processing bracket\n"));
0b489a77 105 new = parser (str + 1, &str);
49223129
LM
106 if (new == ERROR_OP) {
107 return ERROR_OP;
0b489a77
LM
108 }
109 if (root) {
110 for (i = 0, j = 0; i < root->nbops; i++) {
111 if (root->ops[i] == NULL) {
112 if (new->func == Set) {
113 root->ops[i] = new->ops[j++];
114 if (new->ops[j] == NULL) {
115 found = 1;
116 break;
117 }
118 } else {
119 root->ops[i] = new;
120 found = 1;
121 break;
122 }
123 }
124 }
125 if (!found) {
126 return ERROR_OP;
127 }
0b489a77 128 }
49223129
LM
129 VERBOSE (DEBUG, PRINTOUT ("stop processing bracket\n"));
130 if (next != NULL) {
131 *next = str;
132 }
133 return root;
134 }
135 if (*str == ')') {
136 if (next != NULL) {
137 *next = str + 1;
138 }
139 return root;
0b489a77
LM
140 }
141
bc97a989
LM
142 /* look for operators */
143
144 for (i = 0; i < NB_OPERATORS; i++) {
145 keyword_t *operator = operators + i;
146 if (codecmp (operator->keyword, str) == 0) {
49223129
LM
147 VERBOSE (DEBUG, PRINTOUT ("start processing operator\n"));
148 str += operator->offset;
149 if ((root) && (root->func != Set)) {
150 VERBOSE (INFO, PRINTOUT ("Oper: %d\n", operator->func));
bc97a989
LM
151 new = newelement (operator->func, operator->nbops);
152 if (new == NULL) {
0b489a77 153 return ERROR_OP;
bc97a989
LM
154 }
155 new->ops[0] = root;
156 root = new;
49223129
LM
157 new = parser (str, &str);
158 if (new == ERROR_OP) {
159 return ERROR_OP;
160 }
161 root->ops[1] = new;
162 } else {
0b489a77 163 return ERROR_OP;
bc97a989 164 }
bc97a989 165 found = 1;
49223129 166 VERBOSE (DEBUG, PRINTOUT ("stop processing operator\n"));
bc97a989
LM
167 break;
168 }
169 }
170 if (found) {
bc97a989
LM
171 continue;
172 }
49223129 173
bc97a989
LM
174 /* look for functions */
175
176 for (i = 0; i < NB_FUNCTIONS; i++) {
177 keyword_t *function = functions + i;
178 if (codecmp (function->keyword, str) == 0) {
49223129 179 VERBOSE (DEBUG, PRINTOUT ("start processing function\n"));
bc97a989 180 if (root == NULL) {
49223129 181 VERBOSE (INFO, PRINTOUT ("Func: %d\n", function->func));
bc97a989
LM
182 new = newelement (function->func, function->nbops);
183 if (new == NULL) {
0b489a77 184 return ERROR_OP;
bc97a989
LM
185 }
186 root = new;
187 } else {
0b489a77 188 return ERROR_OP;
bc97a989
LM
189 }
190 str += function->offset;
191 found = 1;
49223129 192 VERBOSE (DEBUG, PRINTOUT ("stop processing function\n"));
bc97a989
LM
193 break;
194 }
195 }
196 if (found) {
bc97a989
LM
197 continue;
198 }
199
0b489a77 200 /* last attend to detect addition and substraction */
bc97a989 201
0b489a77
LM
202 if (((*str == '-') || (*str == '+')) &&
203 ((*(str + 1) >= '0') && (*(str + 1) <= '9')) &&
204 ((root) && (root->func == Val))) {
49223129 205 VERBOSE (INFO, PRINTOUT ("Oper: %d\n", Add));
bc97a989
LM
206 new = newelement (Add, 2);
207 if (new == NULL) {
0b489a77 208 return ERROR_OP;
bc97a989
LM
209 }
210 new->ops[0] = root;
211 root = new;
0b489a77 212 }
bc97a989
LM
213
214 /* look for number */
215
49223129
LM
216 if (((*str >= '0') && (*str <= '9')) || (*str == '.')) {
217 VERBOSE (DEBUG, PRINTOUT ("start processing value\n"));
bc97a989
LM
218 char *pt;
219 float value = strtof (str, &pt);
49223129 220 VERBOSE (INFO, PRINTOUT ("Value: %f\n", value));
bc97a989
LM
221 if (str != pt) {
222 new = newelement (Val, 1);
bc97a989 223 if (new == NULL) {
0b489a77 224 return ERROR_OP;
bc97a989 225 }
49223129 226 new->value = value;
bc97a989
LM
227 if (root == NULL) {
228 root = new;
229 } else {
0b489a77
LM
230 if (root->func == Val) {
231 element_t *set = newelement (Set, MAX_OPERANDS);
232 if (set == NULL) {
233 return ERROR_OP;
234 }
235 set->ops[0] = root;
236 root = set;
237 }
bc97a989
LM
238 for (i = 0; i < root->nbops; i++) {
239 if (root->ops[i] == NULL) {
240 root->ops[i] = new;
241 found = 1;
242 break;
243 }
244 }
245 if (!found) {
0b489a77 246 return ERROR_OP;
bc97a989
LM
247 }
248 }
249 str = pt;
250 found = 1;
251 }
49223129 252 VERBOSE (DEBUG, PRINTOUT ("stop processing value\n"));
bc97a989
LM
253 }
254
255 /* error */
256
257 if (!found) {
0b489a77 258 return ERROR_OP;
bc97a989
LM
259 }
260
261 }
262
49223129
LM
263 if (next != NULL) {
264 *next = str;
265 }
bc97a989
LM
266 return root;
267}
268
269/* print element tree */
270
271void print_element (element_t *root, int level)
272{
273 char *func = NULL;
274 int i;
275
49223129 276 if ((root == NULL) || (root == ERROR_OP)) {
bc97a989 277 return;
49223129
LM
278 }
279
bc97a989
LM
280 for (i = 0; i < level; i++) {
281 PRINTOUT (" ");
282 }
283
284 switch (root->func) {
285 case Val: func = "Value"; break;
0b489a77 286 case Set: func = "Set"; break;
bc97a989
LM
287 case Add: func = "Addition"; break;
288 case Sub: func = "Subtraction"; break;
289 case Mul: func = "Multiplication"; break;
290 case Div: func = "Division"; break;
291 case Pow: func = "Power"; break;
292 case Sqr: func = "Square Root"; break;
293 case Cos: func = "Cosine"; break;
294 case Sin: func = "Sine"; break;
295 case Atn: func = "Arc Tangent"; break;
296 case Log: func = "Logarithm"; break;
297 case Exp: func = "Exponantial"; break;
298 }
299
300 PRINTOUT ("Function: %s\n", func);
301
302 if (root->func == Val) {
303 for (i = 0; i < level; i++) {
304 PRINTOUT (" ");
305 }
306 PRINTOUT ("value: %f\n", root->value);
307 } else {
308 for (i = 0; i < root->nbops; i++) {
309 print_element (root->ops[i], level + 1);
310 }
311 }
312}
313
314/* vim: set ts=4 sw=4 et: */