Mercurial > audlegacy
comparison Plugins/Visualization/paranormal/pn/pnscriptparser.y @ 1507:0c5fdcf3f947 trunk
[svn] - incomplete stuff
author | nenolod |
---|---|
date | Sun, 06 Aug 2006 01:53:29 -0700 |
parents | |
children | 837983bac90f |
comparison
equal
deleted
inserted
replaced
1506:2a8e193c07a6 | 1507:0c5fdcf3f947 |
---|---|
1 %{ | |
2 #define yymaxdepth pn_script_parser_maxdepth | |
3 #define yyparse pn_script_parser_parse | |
4 #define yylex pn_script_parser_lex | |
5 #define yyerror pn_script_parser_error | |
6 #define yylval pn_script_parser_lval | |
7 #define yychar pn_script_parser_char | |
8 #define yydebug pn_script_parser_debug | |
9 #define yypact pn_script_parser_pact | |
10 #define yyr1 pn_script_parser_r1 | |
11 #define yyr2 pn_script_parser_r2 | |
12 #define yydef pn_script_parser_def | |
13 #define yychk pn_script_parser_chk | |
14 #define yypgo pn_script_parser_pgo | |
15 #define yyact pn_script_parser_act | |
16 #define yyexca pn_script_parser_exca | |
17 #define yyerrflag pn_script_parser_errflag | |
18 #define ynerrs pn_script_parser_nerrs | |
19 #define yyps pn_script_parser_ps | |
20 #define yypv pn_script_parser_pv | |
21 #define yys pn_script_parser_s | |
22 #define yy_yys pn_script_parser_yys | |
23 #define yystate pn_script_parser_state | |
24 #define yytmp pn_script_parser_tmp | |
25 #define yyv pn_script_parser_v | |
26 #define yy_yyv pn_script_parser_yyv | |
27 #define yyval pn_script_parser_val | |
28 #define yylloc pn_script_parser_lloc | |
29 #define yyreds pn_script_parser_reds | |
30 #define yytoks pn_script_parser_toks | |
31 #define yylhs pn_script_parser_yylhs | |
32 #define yylen pn_script_parser_yylen | |
33 #define yydefred pn_script_parser_yydefred | |
34 #define yydgoto pn_script_parser_yydgoto | |
35 #define yysindex pn_script_parser_yysindex | |
36 #define yyrindex pn_script_parser_yyrindex | |
37 #define yygindex pn_script_parser_yygindex | |
38 #define yytable pn_script_parser_yytable | |
39 #define yycheck pn_script_parser_yycheck | |
40 #define yyname pn_script_parser_yyname | |
41 #define yyrule pn_script_parser_yyrule | |
42 | |
43 #include <ctype.h> | |
44 #include <stdlib.h> | |
45 #include <glib.h> | |
46 #include <pn/pnscript.h> | |
47 | |
48 /* define this to dump the parser output to stdout */ | |
49 /* #define PN_PRINT_OPS 1 */ | |
50 | |
51 int yyerror (char *s); | |
52 int yylex (void); | |
53 | |
54 static gboolean parse_failed; | |
55 | |
56 /* Are we on the size-determining pass? */ | |
57 static gboolean size_pass; | |
58 | |
59 /* Used during the size pass to determine the size of the constant table */ | |
60 static GArray *temp_constant_table = NULL; | |
61 | |
62 /* The code size */ | |
63 static guint code_size; | |
64 | |
65 /* The current code byte */ | |
66 static guint *code_ptr; | |
67 | |
68 /* Input variables used during parsing */ | |
69 static PnScript *parse_script; | |
70 static const gchar *parse_string; | |
71 %} | |
72 | |
73 %union { | |
74 gdouble *constant; | |
75 PnVariable *variable; | |
76 } | |
77 | |
78 %token <constant> CONSTANT | |
79 %token <variable> VARIABLE | |
80 /* Functions */ | |
81 %token ABS_FUNC | |
82 %token MAX_FUNC | |
83 %token MIN_FUNC | |
84 %token SIN_FUNC | |
85 %token COS_FUNC | |
86 %token TAN_FUNC | |
87 %token ASIN_FUNC | |
88 %token ACOS_FUNC | |
89 %token ATAN_FUNC | |
90 | |
91 | |
92 %right '=' | |
93 %left '-' '+' | |
94 %left '*' '/' | |
95 %left NEG | |
96 %right '^' | |
97 | |
98 %% | |
99 | |
100 script | |
101 : /* empty */ | |
102 | script statement | |
103 ; | |
104 | |
105 statement | |
106 : equation ';' | |
107 { | |
108 if (size_pass) | |
109 code_size += sizeof (guint); | |
110 else | |
111 { | |
112 *code_ptr++ = PN_OP_POP; | |
113 | |
114 #ifdef PN_PRINT_OPS | |
115 g_print ("POP\n"); | |
116 #endif /* PN_PRINT_OPS */ | |
117 } | |
118 } | |
119 ; | |
120 | |
121 equation | |
122 : VARIABLE '=' expression | |
123 { | |
124 if (size_pass) | |
125 code_size += sizeof (guint) + sizeof (gdouble *); | |
126 else | |
127 { | |
128 *code_ptr++ = PN_OP_SET; | |
129 *code_ptr++ = (guint) $1; | |
130 | |
131 #ifdef PN_PRINT_OPS | |
132 g_print ("SET %s\n", $1->name); | |
133 #endif /* PN_PRINT_OPS */ | |
134 } | |
135 } | |
136 | |
137 expression | |
138 : CONSTANT | |
139 { | |
140 if (size_pass) | |
141 code_size += sizeof (guint) + sizeof (gdouble *); | |
142 else | |
143 { | |
144 *code_ptr++ = PN_OP_PUSHC; | |
145 *code_ptr++ = GPOINTER_TO_UINT ($1); | |
146 | |
147 #ifdef PN_PRINT_OPS | |
148 g_print ("PUSHC %f\n", *$1); | |
149 #endif /* PN_PRINT_OPS */ | |
150 } | |
151 } | |
152 | VARIABLE | |
153 { | |
154 if (size_pass) | |
155 code_size += sizeof (guint) + sizeof (gdouble *); | |
156 else | |
157 { | |
158 *code_ptr++ = PN_OP_PUSHV; | |
159 *code_ptr++ = (guint) $1; | |
160 | |
161 #ifdef PN_PRINT_OPS | |
162 g_print ("PUSHV %s\n", $1->name); | |
163 #endif /* PN_PRINT_OPS */ | |
164 } | |
165 } | |
166 | equation | |
167 | ABS_FUNC '(' expression ')' | |
168 { | |
169 if (size_pass) | |
170 code_size += sizeof (guint); | |
171 else | |
172 { | |
173 *code_ptr++ = PN_OP_ABS; | |
174 #ifdef PN_PRINT_OPS | |
175 g_print ("ABS\n"); | |
176 #endif /* PN_PRINT_OPS */ | |
177 } | |
178 } | |
179 | MAX_FUNC '(' expression ',' expression ')' | |
180 { | |
181 if (size_pass) | |
182 code_size += sizeof (guint); | |
183 else | |
184 { | |
185 *code_ptr++ = PN_OP_MAX; | |
186 #ifdef PN_PRINT_OPS | |
187 g_print ("MAX\n"); | |
188 #endif /* PN_PRINT_OPS */ | |
189 } | |
190 } | |
191 | MIN_FUNC '(' expression ',' expression ')' | |
192 { | |
193 if (size_pass) | |
194 code_size += sizeof (guint); | |
195 else | |
196 { | |
197 *code_ptr++ = PN_OP_MIN; | |
198 | |
199 #ifdef PN_PRINT_OPS | |
200 g_print ("MIN\n"); | |
201 #endif /* PN_PRINT_OPS */ | |
202 } | |
203 | |
204 } | |
205 | SIN_FUNC '(' expression ')' | |
206 { | |
207 if (size_pass) | |
208 code_size += sizeof (guint); | |
209 else | |
210 { | |
211 *code_ptr++ = PN_OP_SIN; | |
212 | |
213 #ifdef PN_PRINT_OPS | |
214 g_print ("SIN\n"); | |
215 #endif /* PN_PRINT_OPS */ | |
216 } | |
217 | |
218 } | |
219 | COS_FUNC '(' expression ')' | |
220 { | |
221 if (size_pass) | |
222 code_size += sizeof (guint); | |
223 else | |
224 { | |
225 *code_ptr++ = PN_OP_COS; | |
226 | |
227 #ifdef PN_PRINT_OPS | |
228 g_print ("COS\n"); | |
229 #endif /* PN_PRINT_OPS */ | |
230 } | |
231 | |
232 } | |
233 | TAN_FUNC '(' expression ')' | |
234 { | |
235 if (size_pass) | |
236 code_size += sizeof (guint); | |
237 else | |
238 { | |
239 *code_ptr++ = PN_OP_TAN; | |
240 | |
241 #ifdef PN_PRINT_OPS | |
242 g_print ("TAN\n"); | |
243 #endif /* PN_PRINT_OPS */ | |
244 } | |
245 | |
246 } | |
247 | ASIN_FUNC '(' expression ')' | |
248 { | |
249 if (size_pass) | |
250 code_size += sizeof (guint); | |
251 else | |
252 { | |
253 *code_ptr++ = PN_OP_ASIN; | |
254 | |
255 #ifdef PN_PRINT_OPS | |
256 g_print ("ASIN\n"); | |
257 #endif /* PN_PRINT_OPS */ | |
258 } | |
259 | |
260 } | |
261 | ACOS_FUNC '(' expression ')' | |
262 { | |
263 if (size_pass) | |
264 code_size += sizeof (guint); | |
265 else | |
266 { | |
267 *code_ptr++ = PN_OP_ACOS; | |
268 | |
269 #ifdef PN_PRINT_OPS | |
270 g_print ("ACOS\n"); | |
271 #endif /* PN_PRINT_OPS */ | |
272 } | |
273 | |
274 } | |
275 | ATAN_FUNC '(' expression ')' | |
276 { | |
277 if (size_pass) | |
278 code_size += sizeof (guint); | |
279 else | |
280 { | |
281 *code_ptr++ = PN_OP_ATAN; | |
282 | |
283 #ifdef PN_PRINT_OPS | |
284 g_print ("ATAN\n"); | |
285 #endif /* PN_PRINT_OPS */ | |
286 } | |
287 | |
288 } | |
289 | expression '+' expression | |
290 { | |
291 if (size_pass) | |
292 code_size += sizeof (guint); | |
293 else | |
294 { | |
295 *code_ptr++ = PN_OP_ADD; | |
296 | |
297 #ifdef PN_PRINT_OPS | |
298 g_print ("ADD\n"); | |
299 #endif /* PN_PRINT_OPS */ | |
300 } | |
301 } | |
302 | expression '-' expression | |
303 { | |
304 if (size_pass) | |
305 code_size += sizeof (guint); | |
306 else | |
307 { | |
308 *code_ptr++ = PN_OP_SUB; | |
309 #ifdef PN_PRINT_OPS | |
310 g_print ("SUB\n"); | |
311 #endif /* PN_PRINT_OPS */ | |
312 } | |
313 } | |
314 | expression '*' expression | |
315 { | |
316 if (size_pass) | |
317 code_size += sizeof (guint); | |
318 else | |
319 { | |
320 *code_ptr++ = PN_OP_MUL; | |
321 | |
322 #ifdef PN_PRINT_OPS | |
323 g_print ("MUL\n"); | |
324 #endif /* PN_PRINT_OPS */ | |
325 } | |
326 } | |
327 | expression '/' expression | |
328 { | |
329 if (size_pass) | |
330 code_size += sizeof (guint); | |
331 else | |
332 { | |
333 *code_ptr++ = PN_OP_DIV; | |
334 | |
335 #ifdef PN_PRINT_OPS | |
336 g_print ("DIV\n"); | |
337 #endif /* PN_PRINT_OPS */ | |
338 } | |
339 } | |
340 | '-' expression %prec NEG | |
341 { | |
342 if (size_pass) | |
343 code_size += sizeof (guint); | |
344 else | |
345 { | |
346 *code_ptr++ = PN_OP_NEG; | |
347 | |
348 #ifdef PN_PRINT_OPS | |
349 g_print ("NEG\n"); | |
350 #endif /* PN_PRINT_OPS */ | |
351 } | |
352 } | |
353 | expression '^' expression | |
354 { | |
355 if (size_pass) | |
356 code_size += sizeof (guint); | |
357 else | |
358 { | |
359 *code_ptr++ = PN_OP_POW; | |
360 | |
361 #ifdef PN_PRINT_OPS | |
362 g_print ("POW\n"); | |
363 #endif /* PN_PRINT_OPS */ | |
364 } | |
365 } | |
366 | '(' expression ')' | |
367 ; | |
368 | |
369 %% | |
370 | |
371 static gdouble | |
372 get_named_constant_value (const gchar *name) | |
373 { | |
374 if (g_strcasecmp (name, "pi") == 0) | |
375 return G_PI; | |
376 | |
377 /* This is a failure, so don't make a "zero" :) */ | |
378 return 0.0; | |
379 } | |
380 | |
381 static guint | |
382 get_function_token_type (const gchar *name) | |
383 { | |
384 if (g_strcasecmp (name, "abs") == 0) | |
385 return ABS_FUNC; | |
386 if (g_strcasecmp (name, "max") == 0) | |
387 return MAX_FUNC; | |
388 if (g_strcasecmp (name, "min") == 0) | |
389 return MIN_FUNC; | |
390 if (g_strcasecmp (name, "sin") == 0) | |
391 return SIN_FUNC; | |
392 if (g_strcasecmp (name, "cos") == 0) | |
393 return COS_FUNC; | |
394 if (g_strcasecmp (name, "tan") == 0) | |
395 return TAN_FUNC; | |
396 if (g_strcasecmp (name, "asin") == 0) | |
397 return ASIN_FUNC; | |
398 if (g_strcasecmp (name, "acos") == 0) | |
399 return ACOS_FUNC; | |
400 if (g_strcasecmp (name, "atan") == 0) | |
401 return ATAN_FUNC; | |
402 | |
403 return 0; | |
404 } | |
405 | |
406 static gdouble* | |
407 get_constant_ptr (gdouble value) | |
408 { | |
409 guint i; | |
410 | |
411 if (size_pass) | |
412 { | |
413 for (i=0; i<temp_constant_table->len; i++) | |
414 if (g_array_index (temp_constant_table, gdouble, i) == value) | |
415 return (gdouble *) TRUE; | |
416 | |
417 /* Add a constant */ | |
418 g_array_append_val (temp_constant_table, value); | |
419 return (gdouble *) TRUE; | |
420 } | |
421 else | |
422 { | |
423 for (i=0; i<temp_constant_table->len; i++) | |
424 if (parse_script->constant_table[i] == value) | |
425 return &parse_script->constant_table[i]; | |
426 | |
427 return NULL; /* This should never be reached */ | |
428 } | |
429 } | |
430 | |
431 int | |
432 yylex (void) | |
433 { | |
434 /* Skip whitespaces */ | |
435 while (isspace (*parse_string)) parse_string++; | |
436 | |
437 /* Handle the end of the string */ | |
438 if (*parse_string == '\0') | |
439 return 0; | |
440 | |
441 /* Handle unnamed (numeric) constants */ | |
442 if (*parse_string == '.' || isdigit (*parse_string)) | |
443 { | |
444 gdouble value; | |
445 | |
446 value = strtod (parse_string, (char **) &parse_string); | |
447 yylval.constant = get_constant_ptr (value); | |
448 | |
449 return CONSTANT; | |
450 } | |
451 | |
452 /* Handle alphanumeric symbols */ | |
453 if (isalpha (*parse_string)) | |
454 { | |
455 const gchar *symbol_start = parse_string; | |
456 guint function_token; | |
457 gchar *symbol_name; | |
458 | |
459 while (isalnum (*parse_string) || *parse_string == '_') parse_string++; | |
460 | |
461 symbol_name = g_strndup (symbol_start, parse_string - symbol_start); | |
462 | |
463 /* Handle a named constant (e.g. 'pi') */ | |
464 if (get_named_constant_value (symbol_name)) | |
465 { | |
466 yylval.constant = get_constant_ptr (get_named_constant_value (symbol_name)); | |
467 | |
468 g_free (symbol_name); | |
469 | |
470 return CONSTANT; | |
471 } | |
472 | |
473 /* Handle a function (e.g. 'max') */ | |
474 if ((function_token = get_function_token_type (symbol_name))) | |
475 { | |
476 g_free (symbol_name); | |
477 | |
478 return function_token; | |
479 } | |
480 | |
481 /* Handle a variable */ | |
482 if (! size_pass) | |
483 yylval.variable = pn_symbol_table_ref_variable_by_name (parse_script->symbol_table, | |
484 symbol_name); | |
485 | |
486 g_free (symbol_name); | |
487 | |
488 return VARIABLE; | |
489 } | |
490 | |
491 /* Handle a single-character symbol (or invalid tokens) */ | |
492 return *parse_string++; | |
493 } | |
494 | |
495 int | |
496 yyerror (char *s) | |
497 { | |
498 parse_failed = TRUE; | |
499 | |
500 return 0; | |
501 } | |
502 | |
503 gboolean | |
504 pn_script_internal_parse_string (PnScript *script, const gchar *string) | |
505 { | |
506 guint i; | |
507 | |
508 g_return_val_if_fail (script != NULL, FALSE); | |
509 g_return_val_if_fail (PN_IS_SCRIPT (script), FALSE); | |
510 g_return_val_if_fail (string != NULL, FALSE); | |
511 | |
512 /* Make a new temp constant table if needed */ | |
513 if (! temp_constant_table) | |
514 temp_constant_table = g_array_new (FALSE, FALSE, sizeof (gdouble)); | |
515 | |
516 parse_failed = FALSE; | |
517 | |
518 parse_script = script; | |
519 parse_string = string; | |
520 | |
521 /* First determine the code size */ | |
522 size_pass = TRUE; | |
523 code_size = 0; | |
524 yyparse (); | |
525 | |
526 if (parse_failed) | |
527 return FALSE; | |
528 | |
529 if (code_size == 0) | |
530 return TRUE; | |
531 | |
532 /* Now generate the real code */ | |
533 size_pass = FALSE; | |
534 parse_string = string; | |
535 script->code = g_malloc (code_size); | |
536 script->constant_table = g_malloc (temp_constant_table->len * sizeof (gdouble)); | |
537 for (i=0; i<temp_constant_table->len; i++) | |
538 script->constant_table[i] = g_array_index (temp_constant_table, gdouble, i); | |
539 code_ptr = script->code; | |
540 yyparse (); | |
541 g_array_set_size (temp_constant_table, 0); | |
542 | |
543 /* Terminate the script, replacing the last POP with an END */ | |
544 *(code_ptr-1) = PN_OP_END; | |
545 | |
546 #ifdef PN_PRINT_OPS | |
547 g_print ("END\n"); | |
548 #endif /* PN_PRINT_OPS */ | |
549 | |
550 return TRUE; | |
551 } |