1 %{	/* sswf_grammar.y -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2009 */
2 	/* grammar parser for the SWF scripting tool */
3 
4 /*
5 
6 Copyright (c) 2002-2009 Made to Order Software Corp.
7 
8 Permission is hereby granted, free of charge, to any
9 person obtaining a copy of this software and
10 associated documentation files (the "Software"), to
11 deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify,
13 merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom
15 the Software is furnished to do so, subject to the
16 following conditions:
17 
18 The above copyright notice and this permission notice
19 shall be included in all copies or substantial
20 portions of the Software.
21 
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
23 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
26 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 SOFTWARE.
32 
33 */
34 
35 
36 #include	"sswf.h"
37 
38 #define	YYPARSE_PARAM		result
39 static	void			yyerror(const char *msg);
40 
41 
42 
43 %}
44 
45 
46 
47 %union
48 {
49 	struct node_t		*node;
50 	enum node_type_t	type;		/* for UNIT */
51 	int			unused;
52 };
53 
54 
55 /* terminals */
56 %token	<node> STRING VALUE IDENTIFIER OBJECT
57 %token	<type> UNIT_ANGLE UNIT_COLOR UNIT_RATIO UNIT_SIZE UNIT_SPEED UNIT_TIME
58 %token	<unused> FOR IF ACTION_SCRIPT ELSE
59 
60 
61 /* all these yacc expressions are nodes */
62 %type	<node> start expr_list expr group_expr block_expr
63 %type	<node> object opt_name opt_else
64 %type	<node> object_definition definition
65 
66 
67 
68 /* expressions are like in C/C++ */
69 %left	'='
70 %left	'?' ':'
71 %left	RANGE
72 %left	LOGICAL_OR
73 %left	LOGICAL_XOR
74 %left	LOGICAL_AND
75 %left	'|'
76 %left	'^'
77 %left	'&'
78 %left	EQUAL NOT_EQUAL '<' LESS_EQUAL '>' GREATER_EQUAL
79 %right	SHIFT_LEFT SHIFT_RIGHT SHIFT_RIGHT_UNSIGNED ROTATE_LEFT ROTATE_RIGHT
80 %left	MIN_OP MAX_OP
81 %left	'+' '-'
82 %left	'*' '/' '%'
83 %right	POWER
84 %right	POS NEG '!' '~'
85 %left	'['
86 %right	'.'
87 %left	UNIT_ANGLE
88 %left	UNIT_COLOR
89 %left	UNIT_RATIO
90 %left	UNIT_SIZE
91 %left	UNIT_SPEED
92 %left	UNIT_TIME
93 
94 
95 
96 %%
97 
98 /**** START ****/
99 start:
100 	  expr_list opt_end
101 	  {
102 	  	/* the returned value is the result */
103 		* (struct node_t **) result = $1;
104 	  }
105 	;
106 
107 opt_end:
108 	  /* empty */
109 	| colons
110 	;
111 
112 colons:
113 	  ';'
114 	| colons ';'
115 	;
116 
117 /**** EXPRESSIONS ****/
118 expr_list:
119 	  block_expr
120 	  {
121 	  	$$ = $1;
122 	  }
123 	| expr_list colons block_expr
124 	  {
125 		$$ = $1;
126 		node_link_tail($$, $3);
127 	  }
128 	;
129 
130 block_expr:
131 	  expr
132 	  {
133 	  	$$ = $1;
134 	  }
135 	| '{' expr_list '}'
136 	  {
137 		/* this is equivalent to a LIST without a name */
138 		$$ = node_alloc(NODE_TYPE_OBJECT, NODE_SUBTYPE_BLOCK, @1.first_line);
139 		/* left = NULL -- always unamed object */
140 		node_link_right($$, $2);
141 		node_link_object($$);
142 	  }
143 	;
144 
145 group_expr:
146 	  expr
147 	  {
148 		$$ = $1;
149 	  }
150 	| group_expr ',' expr
151 	  {
152 		$$ = $1;
153 		node_link_tail($$, $3);
154 	  }
155 	;
156 
157 expr:
158 	  expr UNIT_ANGLE		%prec UNIT_ANGLE
159 	  {
160 		$$ = $1;
161 		$$->unit[NODE_UNIT_ANGLE] = $2;
162 	  }
163 	| expr UNIT_COLOR		%prec UNIT_COLOR
164 	  {
165 		$$ = $1;
166 		$$->unit[NODE_UNIT_COLOR] = $2;
167 	  }
168 	| expr UNIT_RATIO		%prec UNIT_RATIO
169 	  {
170 		$$ = $1;
171 		$$->unit[NODE_UNIT_RATIO] = $2;
172 	  }
173 	| expr UNIT_SIZE		%prec UNIT_SIZE
174 	  {
175 		$$ = $1;
176 		$$->unit[NODE_UNIT_SIZE] = $2;
177 	  }
178 	| expr UNIT_SPEED		%prec UNIT_SPEED
179 	  {
180 		$$ = $1;
181 		$$->unit[NODE_UNIT_SPEED] = $2;
182 	  }
183 	| expr UNIT_TIME		%prec UNIT_TIME
184 	  {
185 		$$ = $1;
186 		$$->unit[NODE_UNIT_TIME] = $2;
187 	  }
188 	| expr '.' expr
189 	  {
190 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_FIELD, @1.first_line);
191 		node_link_left($$, $1);
192 		node_link_right($$, $3);
193 	  }
194 	| expr '[' group_expr ']'
195 	  {
196 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_SUBSCRIPT, @1.first_line);
197 		node_link_left($$, $1);
198 		node_link_right($$, $3);
199 	  }
200 	| '$' '(' group_expr ')'
201 	  {
202 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_EXPAND, @1.first_line);
203 		node_link_left($$, $3);
204 	  }
205 	| '(' group_expr ')'
206 	  {
207 		if($2->next != NULL) {
208 			/* Check whether the expr returns a list of nodes...
209 			 * This happens when a comma is used between multiple expressions.
210 			 * We need to have a 'GROUP' node because all the children are affected
211 			 * by the following token(s) such as a UNIT.
212 			 */
213 			$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_GROUP, @1.first_line);
214 			node_link_left($$, $2);
215 		}
216 		else {
217 			/* no worry, we don't need to add another node */
218 		  	$$ = $2;
219 		}
220 	  }
221 	| '+' expr		%prec POS
222 	  {
223 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_IDENTITY, @1.first_line);
224 		node_link_left($$, $2);
225 	  }
226 	| '-' expr		%prec NEG
227 	  {
228 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_NEGATE, @1.first_line);
229 		node_link_left($$, $2);
230 	  }
231 	| '!' expr		%prec '!'
232 	  {
233 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_LOGICAL_NOT, @1.first_line);
234 		node_link_left($$, $2);
235 	  }
236 	| '~' expr		%prec '~'
237 	  {
238 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_NOT, @1.first_line);
239 		node_link_left($$, $2);
240 	  }
241 	| IDENTIFIER '(' ')'
242 	  {
243 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_FUNCTION, @1.first_line);
244 		node_link_left($$, $1);
245 		/* right = NULL -- no parameters */
246 	  }
247 	| IDENTIFIER '(' group_expr ')'
248 	  {
249 	  	$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_FUNCTION, @1.first_line);
250 		node_link_left($$, $1);
251 		node_link_right($$, $3);
252 	  }
253 	| expr POWER expr
254 	  {
255 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_POWER, @1.first_line);
256 		node_link_left($$, $1);
257 		node_link_right($$, $3);
258 	  }
259 	| expr '*' expr
260 	  {
261 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_MULTIPLY, @1.first_line);
262 		node_link_left($$, $1);
263 		node_link_right($$, $3);
264 	  }
265 	| expr '/' expr
266 	  {
267 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_DIVIDE, @1.first_line);
268 		node_link_left($$, $1);
269 		node_link_right($$, $3);
270 	  }
271 	| expr '%' expr
272 	  {
273 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_MODULO, @1.first_line);
274 		node_link_left($$, $1);
275 		node_link_right($$, $3);
276 	  }
277 	| expr '+' expr
278 	  {
279 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_ADD, @1.first_line);
280 		node_link_left($$, $1);
281 		node_link_right($$, $3);
282 	  }
283 	| expr '-' expr
284 	  {
285 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_SUBTRACT, @1.first_line);
286 		node_link_left($$, $1);
287 		node_link_right($$, $3);
288 	  }
289 	| expr MIN_OP expr
290 	  {
291 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_MINIMUM, @1.first_line);
292 		node_link_left($$, $1);
293 		node_link_right($$, $3);
294 	  }
295 	| expr MAX_OP expr
296 	  {
297 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_MAXIMUM, @1.first_line);
298 		node_link_left($$, $1);
299 		node_link_right($$, $3);
300 	  }
301 	| expr SHIFT_LEFT expr
302 	  {
303 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_SHIFT_LEFT, @1.first_line);
304 		node_link_left($$, $1);
305 		node_link_right($$, $3);
306 	  }
307 	| expr SHIFT_RIGHT expr
308 	  {
309 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_SHIFT_RIGHT, @1.first_line);
310 		node_link_left($$, $1);
311 		node_link_right($$, $3);
312 	  }
313 	| expr SHIFT_RIGHT_UNSIGNED expr
314 	  {
315 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_SHIFT_RIGHT_UNSIGNED, @1.first_line);
316 		node_link_left($$, $1);
317 		node_link_right($$, $3);
318 	  }
319 	| expr ROTATE_LEFT expr
320 	  {
321 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_ROTATE_LEFT, @1.first_line);
322 		node_link_left($$, $1);
323 		node_link_right($$, $3);
324 	  }
325 	| expr ROTATE_RIGHT expr
326 	  {
327 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_ROTATE_RIGHT, @1.first_line);
328 		node_link_left($$, $1);
329 		node_link_right($$, $3);
330 	  }
331 	| expr EQUAL expr
332 	  {
333 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_EQUAL, @1.first_line);
334 		node_link_left($$, $1);
335 		node_link_right($$, $3);
336 	  }
337 	| expr NOT_EQUAL expr
338 	  {
339 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_NOT_EQUAL, @1.first_line);
340 		node_link_left($$, $1);
341 		node_link_right($$, $3);
342 	  }
343 	| expr '<' expr
344 	  {
345 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_LESS, @1.first_line);
346 		node_link_left($$, $1);
347 		node_link_right($$, $3);
348 	  }
349 	| expr LESS_EQUAL expr
350 	  {
351 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_LESS_EQUAL, @1.first_line);
352 		node_link_left($$, $1);
353 		node_link_right($$, $3);
354 	  }
355 	| expr '>' expr
356 	  {
357 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_GREATER, @1.first_line);
358 		node_link_left($$, $1);
359 		node_link_right($$, $3);
360 	  }
361 	| expr GREATER_EQUAL expr
362 	  {
363 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_GREATER_EQUAL, @1.first_line);
364 		node_link_left($$, $1);
365 		node_link_right($$, $3);
366 	  }
367 	| expr '&' expr
368 	  {
369 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_AND, @1.first_line);
370 		node_link_left($$, $1);
371 		node_link_right($$, $3);
372 	  }
373 	| expr '^' expr
374 	  {
375 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_XOR, @1.first_line);
376 		node_link_left($$, $1);
377 		node_link_right($$, $3);
378 	  }
379 	| expr '|' expr
380 	  {
381 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_OR, @1.first_line);
382 		node_link_left($$, $1);
383 		node_link_right($$, $3);
384 	  }
385 	| expr LOGICAL_AND expr
386 	  {
387 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_LOGICAL_AND, @1.first_line);
388 		node_link_left($$, $1);
389 		node_link_right($$, $3);
390 	  }
391 	| expr LOGICAL_XOR expr
392 	  {
393 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_LOGICAL_XOR, @1.first_line);
394 		node_link_left($$, $1);
395 		node_link_right($$, $3);
396 	  }
397 	| expr LOGICAL_OR expr
398 	  {
399 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_LOGICAL_OR, @1.first_line);
400 		node_link_left($$, $1);
401 		node_link_right($$, $3);
402 	  }
403 	| expr RANGE expr
404 	  {
405 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_RANGE, @1.first_line);
406 		if($1->type == NODE_TYPE_OPERATOR && $1->sub_type == NODE_SUBTYPE_RANGE) {
407 			fprintf(stderr, "ERROR: at line #%d: can't have two ranges defined one after another.\n", @2.first_line);
408 			return -1;
409 		}
410 		if($3->type == NODE_TYPE_OPERATOR && $3->sub_type == NODE_SUBTYPE_RANGE) {
411 			fprintf(stderr, "ERROR: at line #%d: can't have two ranges defined one after another.\n", @2.first_line);
412 			return -1;
413 		}
414 		node_link_left($$, $1);
415 		node_link_right($$, $3);
416 	  }
417 	| expr '?' group_expr ':' expr
418 	  {
419 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_SELECT, @1.first_line);
420 		node_link_select($$, $1);
421 		node_link_left($$, $3);
422 		node_link_right($$, $5);
423 	  }
424 	| IF '(' group_expr ')' '{' expr_list opt_end '}' opt_else
425 	  {
426 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_IF, @1.first_line);
427 		node_link_select($$, $3);
428 		node_link_left($$, $6);
429 		node_link_right($$, $9);	/* may be a null pointer */
430 	  }
431 	| IDENTIFIER '=' expr
432 	  {
433 		$$ = node_alloc(NODE_TYPE_OBJECT, NODE_SUBTYPE_VARIABLE, @1.first_line);
434 		node_link_left($$, $1);
435 		node_link_right($$, $3);
436 		node_link_object($$);
437 	  }
438 	| object
439 	  {
440 	  	$$ = $1;
441 	  }
442 	| IDENTIFIER
443 	  {
444 	  	$$ = $1;
445 	  }
446 	| VALUE
447 	  {
448 	  	$$ = $1;
449 	  }
450 	| STRING
451 	  {
452 	  	$$ = $1;
453 	  }
454 	;
455 
456 
457 opt_else:
458 	  /* empty */
459 	  {
460 	  	$$ = NULL;
461 	  }
462 	| ELSE '{' expr_list opt_end '}'
463 	  {
464 		$$ = $3;
465 	  }
466 	| ELSE IF '(' group_expr ')' '{' expr_list opt_end '}' opt_else
467 	  {
468 		$$ = node_alloc(NODE_TYPE_OPERATOR, NODE_SUBTYPE_IF, @1.first_line);
469 		node_link_select($$, $4);
470 		node_link_left($$, $7);
471 		node_link_right($$, $10);	/* may be a null pointer */
472 	  }
473 	;
474 
475 /**** OBJECTS ****/
476 object:
477 	  OBJECT opt_name '{' object_definition opt_end '}'
478 	  {
479 		$$ = $1;
480 		/* keep only non-empty names, it simplifies some other parts of the code! */
481 		if($2 != NULL && $2->string != NULL && *$2->string != '\0') {
482 			node_link_left($$, $2);
483 		}
484 		node_link_right($$, $4);
485 		node_link_object($$);
486 	  }
487 	| OBJECT opt_name '{' opt_end '}'
488 	  {
489 		$$ = $1;
490 		if($2 != NULL && $2->string != NULL && *$2->string != '\0') {
491 			node_link_left($$, $2);
492 		}
493 		/* right = NULL -- no data for this object */
494 		node_link_object($$);
495 	  }
496 	| OBJECT opt_name
497 	  {
498 		$$ = $1;
499 		if($2 != NULL && $2->string != NULL && *$2->string != '\0') {
500 			node_link_left($$, $2);
501 		}
502 		/* right = NULL -- no data for this object */
503 		node_link_object($$);
504 	  }
505 	| ACTION_SCRIPT opt_name '{'
506 		{ sswf_read_actionscript(1); }
507 		STRING
508 		{ sswf_read_actionscript(0); }
509 		'}'
510 	  {
511 	  	struct node_t	*n;
512 
513 		/*
514 		 * Note: we use the 1st line of the STRING so we can generate
515 		 * proper errors in the Javascript compiler.
516 		 */
517 		$$ = node_alloc(NODE_TYPE_OBJECT, NODE_SUBTYPE_ACTION_SCRIPT, @5.first_line);
518 		if($2 != NULL && $2->string != NULL && *$2->string != '\0') {
519 			node_link_left($$, $2);
520 		}
521 	  	n = node_alloc(NODE_TYPE_DEFINITION, NODE_SUBTYPE_UNKNOWN, @1.first_line);
522 		/* left = NULL -- no label */
523 		node_link_right(n, $5);
524 		node_link_right($$, n);
525 		node_link_object($$);
526 	  }
527 	;
528 
529 
530 opt_name:
531 	  /* empty */
532 	  {
533 		$$ = NULL;
534 	  }
535 	| IDENTIFIER
536 	  {
537 	  	$$ = $1;
538 	  }
539 	| STRING
540 	  {
541 	  	$$ = $1;
542 	  }
543 	;
544 
545 
546 
547 
548 /* object definitions are specific to the object sub-type but they can all be parsed the same way
549    we will generate errors later when we transform the data to the final structures */
550 object_definition:
551 	  definition
552 	  {
553 	  	$$ = $1;
554 	  }
555 	| object_definition colons definition
556 	  {
557 		$$ = $1;
558 		node_link_tail($$, $3);
559 	  }
560 	;
561 
562 
563 definition:
564 	  IDENTIFIER ':' group_expr
565 	  {
566 	  	$$ = node_alloc(NODE_TYPE_DEFINITION, NODE_SUBTYPE_UNKNOWN, @1.first_line);
567 		node_link_left($$, $1);
568 		node_link_right($$, $3);
569 	  }
570 	| group_expr
571 	  {
572 	  	$$ = node_alloc(NODE_TYPE_DEFINITION, NODE_SUBTYPE_UNKNOWN, @1.first_line);
573 		/* left = NULL -- no label */
574 		node_link_right($$, $1);
575 	  }
576 	| FOR '(' IDENTIFIER '=' expr ';' expr ';' expr ')' '{' object_definition opt_end '}'
577 	  {
578 		struct node_t	*for_obj, *var, *result, *block;
579 
580 		block = node_alloc(NODE_TYPE_OBJECT, NODE_SUBTYPE_BLOCK, @1.first_line);
581 		/* node_link_left() -- no name/label */
582 		node_link_right(block, $12);
583 
584 		var = node_alloc(NODE_TYPE_OBJECT, NODE_SUBTYPE_VARIABLE, @1.first_line);
585 		result = node_alloc(NODE_TYPE_INTEGER, NODE_SUBTYPE_UNKNOWN, @1.first_line);
586 		node_link_left(var, $3);
587 		node_link_right(var, result);	/* the result of different expr's */
588 		node_link_object(var);
589 
590 		node_link_tail(var, $5);
591 		node_link_tail(var, $7);
592 		node_link_tail(var, $9);
593 		node_link_tail(var, block);
594 
595 		for_obj = node_alloc(NODE_TYPE_OBJECT, NODE_SUBTYPE_FOR, @1.first_line);
596 		/*node_link_left(for_obj, ...) -- no name for a loop - should we use the variable name? */
597 		node_link_right(for_obj, var);
598 		/*node_link_object(for_obj);	-- this makes this software crash and it's not necessary (no name!) */
599 
600 	  	$$ = node_alloc(NODE_TYPE_DEFINITION, NODE_SUBTYPE_UNKNOWN, @1.first_line);
601 		/* left = NULL -- no label */
602 		node_link_right($$, for_obj);
603 	  }
604 	;
605 
606 
607 %%
608 
609 
610 void yyerror(const char *msg)
611 {
612 	/* TODO: enhance this message! */
613 	printf("YACC ERROR at line #%d in file \"%s\": %s.\n", yylloc.first_line, lex_filename, msg);
614 }
615 
616 
617 
618 
619