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 }