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