file copied from ming 0.3alpha2
[swftools.git] / lib / action / swf4compiler.y
1 /* $Id: swf4compiler.y,v 1.1 2004/02/02 10:12:34 kramm Exp $ */
2
3 %start program
4
5 %{
6
7 #include <time.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include "compile.h"
11 #include "action.h"
12
13 #define YYPARSE_PARAM buffer
14
15 %}
16
17 %union {
18   Buffer action;
19   char *str;
20   SWFActionFunction function;
21   SWFGetUrl2Method getURLMethod;
22 }
23
24 /* tokens etc. */
25 %token BREAK
26 %token FOR
27 %token CONTINUE
28 %token IF
29 %token ELSE
30 %token DO
31 %token WHILE
32
33 %token THIS
34
35 /* functions */
36 %token EVAL
37 %token TIME
38 %token RANDOM
39 %token LENGTH
40 %token INT
41 %token CONCAT
42 %token DUPLICATECLIP
43 %token REMOVECLIP
44 %token TRACE
45 %token STARTDRAG
46 %token STOPDRAG
47 %token ORD
48 %token CHR
49 %token CALLFRAME
50 %token GETURL
51 %token GETURL1
52 %token LOADMOVIE
53 %token LOADVARIABLES
54 %token POSTURL
55 %token SUBSTR
56
57 %token GETPROPERTY
58
59 /* v3 functions */
60 %token NEXTFRAME
61 %token PREVFRAME
62 %token PLAY
63 %token STOP
64 %token TOGGLEQUALITY
65 %token STOPSOUNDS
66 %token GOTOFRAME
67 %token GOTOANDPLAY
68 %token FRAMELOADED
69 %token SETTARGET
70
71 /* high level functions */
72 %token TELLTARGET
73
74 /* these three are strdup'ed in compiler.flex, so free them here */
75 %token <str> STRING
76 %token <str> NUMBER
77 %token <str> IDENTIFIER
78 %token <str> PATH
79
80 %token <getURLMethod> GETURL_METHOD
81
82 %token EQ "=="
83 %token LE "<="
84 %token GE ">="
85 %token NE "!="
86 %token LAN "&&"
87 %token LOR "||"
88 %token INC "++"
89 %token DEC "--"
90 %token IEQ "+="
91 %token DEQ "/="
92 %token MEQ "*="
93 %token SEQ "-="
94 %token STREQ "==="
95 %token STRNE "!=="
96 %token STRCMP "<=>"
97 %token PARENT ".."
98
99 %token END "end"
100
101 /* ascending order of ops ..? */
102 %left ','
103 %right '=' "*=" "/=" "+=" "-="
104 %right '?' ':'
105 %left "&&" "||"
106 %left "==" "!=" "===" "!=="
107 %left '<' '>' "<=" ">=" "<=>"
108 %left '&'
109 %left '+' '-'
110 %left '*' '/'
111 %right "++" "--" UMINUS '!'
112 %right POSTFIX
113 %right NEGATE
114
115 %type <action> elem
116 %type <action> elems
117 %type <action> stmt
118 %type <action> statements
119 %type <action> if_stmt
120 %type <action> iter_stmt
121 %type <action> cont_stmt
122 %type <action> break_stmt
123 %type <action> expr_opt
124 %type <action> void_function_call
125 %type <action> function_call
126 %type <action> lhs_expr
127 %type <action> pf_expr
128 %type <action> rhs_expr
129 %type <action> assign_stmt
130 %type <action> assign_stmts
131 %type <action> assign_stmts_opt
132 %type <action> expr
133 %type <action> program
134
135 /* make sure to free these, too! */
136 %type <str>    sprite
137 %type <str>    variable
138
139 %%
140
141 /* rules */
142
143 program
144         : elems
145                 { *((Buffer *)buffer) = $1; }
146
147         ;
148
149 elems
150         : elem
151         | elems elem
152                 { bufferConcat($1, $2); }
153         ;
154
155 elem
156         : stmt
157         ;
158
159 stmt
160         : '{' '}'                               { $$ = NULL; }
161         | '{' statements '}'                    { $$ = $2; }
162         | ';'                                   { $$ = NULL; }
163         | assign_stmt ';'
164         | if_stmt
165         | iter_stmt
166         | cont_stmt
167         | break_stmt
168         ;
169
170 assign_stmts
171         : assign_stmt
172         | assign_stmts ',' assign_stmt          { bufferConcat($1, $3); }
173         ;
174
175 statements
176         : /* empty */   { $$ = NULL; }
177         | stmt
178         | statements stmt
179                         { bufferConcat($1, $2); }
180         ;
181
182 if_stmt
183         /* XXX- I haven't tested the frameloaded() stuff yet.. */
184
185         : IF '(' FRAMELOADED '(' NUMBER ')' ')' stmt ELSE stmt
186                 { $$ = newBuffer();
187                   bufferWriteU8($$, SWFACTION_WAITFORFRAME);
188                   bufferWriteS16($$, 3);
189                   bufferWriteS16($$, atoi($5));
190                   free($5);
191                   bufferWriteU8($$, 1);         /* if not loaded, jump to.. */
192                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
193                   bufferWriteS16($$, 2);
194                   bufferWriteS16($$, bufferLength($10)+5);
195                   bufferConcat($$, $10);                          /* ..here */
196                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
197                   bufferWriteS16($$, 2);
198                   bufferWriteS16($$, bufferLength($8));
199                   bufferConcat($$, $8); }
200
201         | IF '(' FRAMELOADED '(' NUMBER ')' ')' stmt
202                 { $$ = newBuffer();
203                   bufferWriteU8($$, SWFACTION_WAITFORFRAME);
204                   bufferWriteS16($$, 3);
205                   bufferWriteS16($$, atoi($5));
206                   free($5);
207                   bufferWriteU8($$, 1);         /* if not loaded, jump to.. */
208                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
209                   bufferWriteS16($$, 2);
210                   bufferWriteS16($$, 5);
211                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);      /* ..here */
212                   bufferWriteS16($$, 2);
213                   bufferWriteS16($$, bufferLength($8));   /* ..and then out */
214                   bufferConcat($$, $8); }
215
216         /* make this case cleaner.. */
217         | IF '(' '!' FRAMELOADED '(' NUMBER ')' ')' stmt
218                 { $$ = newBuffer();
219                   bufferWriteU8($$, SWFACTION_WAITFORFRAME);
220                   bufferWriteS16($$, 3);
221                   bufferWriteS16($$, atoi($6));
222                   free($6);
223                   bufferWriteU8($$, 1);         /* if not loaded, jump to.. */
224                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
225                   bufferWriteS16($$, 2);
226                   bufferWriteS16($$, bufferLength($9));
227                   bufferConcat($$, $9); }                         /* ..here */
228
229         | IF '(' FRAMELOADED '(' expr ')' ')' stmt ELSE stmt
230                 { $$ = $5;
231                   bufferWriteU8($$, SWFACTION_WAITFORFRAMEEXPRESSION);
232                   bufferWriteS16($$, 1);
233                   bufferWriteU8($$, 1);         /* if not loaded, jump to.. */
234                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
235                   bufferWriteS16($$, 2);
236                   bufferWriteS16($$, bufferLength($10)+5);
237                   bufferConcat($$, $10);                          /* ..here */
238                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
239                   bufferWriteS16($$, 2);
240                   bufferWriteS16($$, bufferLength($8));
241                   bufferConcat($$, $8); }
242
243         | IF '(' FRAMELOADED '(' expr ')' ')' stmt
244                 { $$ = $5;
245                   bufferWriteU8($$, SWFACTION_WAITFORFRAMEEXPRESSION);
246                   bufferWriteS16($$, 1);
247                   bufferWriteU8($$, 1);         /* if not loaded, jump to.. */
248                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
249                   bufferWriteS16($$, 2);
250                   bufferWriteS16($$, 5);
251                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);      /* ..here */
252                   bufferWriteS16($$, 2);
253                   bufferWriteS16($$, bufferLength($8));   /* ..and then out */
254                   bufferConcat($$, $8); }
255
256         /* make this case cleaner.. */
257         | IF '(' '!' FRAMELOADED '(' expr ')' ')' stmt
258                 { $$ = $6;
259                   bufferWriteU8($$, SWFACTION_WAITFORFRAMEEXPRESSION);
260                   bufferWriteS16($$, 1);
261                   bufferWriteU8($$, 1);         /* if not loaded, jump to.. */
262                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
263                   bufferWriteS16($$, 2);
264                   bufferWriteS16($$, bufferLength($9));
265                   bufferConcat($$, $9); }                         /* ..here */
266
267         | IF '(' expr ')' stmt ELSE stmt
268                 { bufferWriteU8($3, SWFACTION_BRANCHIFTRUE);
269                   bufferWriteS16($3, 2);
270                   bufferWriteS16($3, bufferLength($7)+5);
271                   bufferConcat($3, $7);
272                   bufferWriteU8($3, SWFACTION_BRANCHALWAYS);
273                   bufferWriteS16($3, 2);
274                   bufferWriteS16($3, bufferLength($5));
275                   bufferConcat($3, $5);
276                   $$ = $3; }
277
278         | IF '(' expr ')' stmt
279                 { bufferWriteU8($3, SWFACTION_LOGICALNOT);
280                   bufferWriteU8($3, SWFACTION_BRANCHIFTRUE);
281                   bufferWriteS16($3, 2);
282                   bufferWriteS16($3, bufferLength($5));
283                   bufferConcat($3, $5);
284                   $$ = $3; }
285         ;
286
287 expr_opt
288         : /* empty */   { $$ = NULL; }
289         | expr          { $$ = $1; }
290         ;
291
292 /* not thought out yet..
293 switch_stmt
294         : SWITCH '(' expr ')' '{'
295                 { $$ = $3;
296                   pushLoop(); }
297           switch_cases '}'
298                 { bufferConcat($$, $7); }
299         ;
300
301 switch_cases
302         : switch_cases switch_case
303         | switch_case
304         ;
305
306 switch_case
307         : CASE INTEGER ':' stmt
308                 { $$ = newBuffer(); }
309         ;
310 */
311
312 iter_stmt
313         : WHILE '(' '!' FRAMELOADED '(' NUMBER ')' ')' stmt
314                 { $$ = newBuffer();
315                   bufferWriteU8($$, SWFACTION_WAITFORFRAME);
316                   bufferWriteS16($$, 3);
317                   bufferWriteS16($$, atoi($6));
318                   free($6);
319                   bufferWriteU8($$, 1);         /* if not loaded, jump to.. */
320                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
321                   bufferWriteS16($$, 2);
322                   bufferWriteS16($$, bufferLength($9)+5);
323                   bufferConcat($$, $9);                           /* ..here */
324                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
325                   bufferWriteS16($$, 2);
326                   bufferWriteS16($$, -(bufferLength($$)+2)); }
327
328         | WHILE '(' expr ')' stmt
329                 { $$ = $3;
330                   bufferWriteU8($$, SWFACTION_LOGICALNOT);
331                   bufferWriteU8($$, SWFACTION_BRANCHIFTRUE);
332                   bufferWriteS16($$, 2);
333                   bufferWriteS16($$, bufferLength($5)+5);
334                   bufferConcat($$, $5);
335                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
336                   bufferWriteS16($$, 2);
337                   bufferWriteS16($$, -(bufferLength($$)+2));
338                   bufferResolveJumps($$); }
339
340         | DO stmt WHILE '(' expr ')'
341                 { $$ = $2;
342                   bufferConcat($$, $5);
343                   bufferWriteU8($$, SWFACTION_BRANCHIFTRUE);
344                   bufferWriteS16($$, 2);
345                   bufferWriteS16($$, -(bufferLength($$)+2));
346                   bufferResolveJumps($$); }
347
348         | FOR '(' assign_stmts_opt ';' expr_opt ';' assign_stmts_opt ')' stmt
349                 { if (!$5)
350                     $5 = newBuffer();
351                   else {
352                     bufferWriteU8($5, SWFACTION_LOGICALNOT);
353                     bufferWriteU8($5, SWFACTION_BRANCHIFTRUE);
354                     bufferWriteS16($5, 2);
355                     bufferWriteS16($5, bufferLength($9)+bufferLength($7)+5);
356                   }
357                   bufferConcat($5, $9);
358                   bufferConcat($5, $7);
359                   bufferWriteU8($5, SWFACTION_BRANCHALWAYS);
360                   bufferWriteS16($5, 2);
361                   bufferWriteS16($5, -(bufferLength($5)+2));
362                   bufferResolveJumps($5);
363                   $$ = $3;
364                   if(!$$) $$ = newBuffer();
365                   bufferConcat($$, $5);
366                 }
367         ;
368
369 assign_stmts_opt
370         : /* empty */                           { $$ = NULL; }
371         | assign_stmts
372         ;
373
374 cont_stmt
375         : CONTINUE ';'
376                 { $$ = newBuffer();
377                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
378                   bufferWriteS16($$, 2);
379                   bufferWriteS16($$, MAGIC_CONTINUE_NUMBER); }
380         ;
381
382 break_stmt
383         : BREAK ';'
384                 { $$ = newBuffer();
385                   bufferWriteU8($$, SWFACTION_BRANCHALWAYS);
386                   bufferWriteS16($$, 2);
387                   bufferWriteS16($$, MAGIC_BREAK_NUMBER); }
388         ;
389
390 void_function_call
391         : STOPDRAG '(' ')' /* no args */
392                 { $$ = newBuffer();
393                   bufferWriteU8($$, SWFACTION_STOPDRAGMOVIE); }
394
395         | CALLFRAME '(' variable ')'
396                 { $$ = newBuffer();
397                   bufferWriteString($$, $3, strlen($3)+1);
398                   bufferWriteU8($$, SWFACTION_CALLFRAME);
399                   bufferWriteS16($$, 0);
400                   free($3); }
401
402         | CALLFRAME '(' STRING ')'
403                 { $$ = newBuffer();
404                   bufferWriteString($$, $3, strlen($3)+1);
405                   bufferWriteU8($$, SWFACTION_CALLFRAME);
406                   bufferWriteS16($$, 0);
407                   free($3); }
408
409         | REMOVECLIP '(' expr ')'
410                 { $$ = $3;
411                   bufferWriteU8($$, SWFACTION_REMOVECLIP); }
412
413         | TRACE '(' expr ')'
414                 { $$ = $3;
415                   bufferWriteU8($$, SWFACTION_TRACE); }
416
417         /* getURL2(url, window, [method]) */
418         | GETURL '(' expr ',' expr ')'
419                 { $$ = $3;
420                   bufferConcat($$, $5);
421                   bufferWriteU8($$, SWFACTION_GETURL2);
422                   bufferWriteS16($$, 1);
423                   bufferWriteU8($$, GETURL_METHOD_NOSEND); }
424
425         | GETURL '(' expr ',' expr ',' GETURL_METHOD ')'
426                 { $$ = $3;
427                   bufferConcat($$, $5);
428                   bufferWriteU8($$, SWFACTION_GETURL2);
429                   bufferWriteS16($$, 1);
430                   bufferWriteU8($$, $7); }
431
432         | GETURL1 '(' STRING ',' STRING ')'
433                 { $$ = newBuffer();
434                   bufferWriteU8($$, SWFACTION_GETURL);
435                   bufferWriteS16($$, strlen($3) + strlen($5) + 2);
436                   bufferWriteHardString($$, (byte*)$3, strlen($3));
437                   bufferWriteU8($$, 0);
438                   bufferWriteHardString($$, (byte*)$5, strlen($5));
439                   bufferWriteU8($$, 0); }
440
441         | LOADMOVIE '(' expr ',' expr ')'
442                 { $$ = $3;
443                   bufferConcat($$, $5);
444                   bufferWriteU8($$, SWFACTION_GETURL2);
445                   bufferWriteS16($$, 1);
446                   bufferWriteU8($$, GETURL_METHOD_NOSEND | GETURL_LOADMOVIE); }
447
448         | LOADMOVIE '(' expr ',' expr ',' GETURL_METHOD ')'
449                 { $$ = $3;
450                   bufferConcat($$, $5);
451                   bufferWriteU8($$, SWFACTION_GETURL2);
452                   bufferWriteS16($$, 1);
453                   bufferWriteU8($$, $7 | GETURL_LOADMOVIE); }
454
455         | LOADVARIABLES '(' expr ',' expr ')'
456                 { $$ = $3;
457                   bufferConcat($$, $5);
458                   bufferWriteU8($$, SWFACTION_GETURL2);
459                   bufferWriteS16($$, 1);
460                   bufferWriteU8($$, GETURL_METHOD_NOSEND | GETURL_LOADVARIABLES); }
461
462         | LOADVARIABLES '(' expr ',' expr ',' GETURL_METHOD ')'
463                 { $$ = $3;
464                   bufferConcat($$, $5);
465                   bufferWriteU8($$, SWFACTION_GETURL2);
466                   bufferWriteS16($$, 1);
467                   bufferWriteU8($$, $7 | GETURL_LOADVARIABLES); }
468
469         /* startDrag(target, lock, [left, right, top, bottom]) */
470         | STARTDRAG '(' expr ',' expr ')'
471                 { $$ = newBuffer();
472                   bufferWriteString($$, "0", 2); /* no constraint */
473                   bufferConcat($$, $5);
474                   bufferConcat($$, $3);
475                   bufferWriteU8($$, SWFACTION_STARTDRAGMOVIE); }
476
477         | STARTDRAG '(' expr ',' expr ',' expr ',' expr ',' expr ',' expr ')'
478                 { $$ = newBuffer();
479                   bufferConcat($$, $7);
480                   bufferConcat($$, $11);
481                   bufferConcat($$, $9);
482                   bufferConcat($$, $13);
483                   bufferWriteString($$, "1", 2); /* has constraint */
484                   bufferConcat($$, $5);
485                   bufferConcat($$, $3);
486                   bufferWriteU8($$, SWFACTION_STARTDRAGMOVIE); }
487
488         /* duplicateClip(target, new, depth) */
489         | DUPLICATECLIP '(' expr ',' expr ',' expr ')'
490                 { $$ = $3;
491                   bufferConcat($$, $5);
492                   bufferConcat($$, $7);
493                   bufferWriteWTHITProperty($$);
494                   bufferWriteU8($$, SWFACTION_ADD); /* see docs for explanation */
495                   bufferWriteU8($$, SWFACTION_DUPLICATECLIP); }
496
497         /* v3 actions */
498         | NEXTFRAME '(' ')'
499                 { $$ = newBuffer();
500                   bufferWriteU8($$, SWFACTION_NEXTFRAME); }
501                 
502         | PREVFRAME '(' ')'
503                 { $$ = newBuffer();
504                   bufferWriteU8($$, SWFACTION_PREVFRAME); }
505
506         | PLAY '(' ')'
507                 { $$ = newBuffer();
508                   bufferWriteU8($$, SWFACTION_PLAY); }
509
510         | STOP '(' ')'
511                 { $$ = newBuffer();
512                   bufferWriteU8($$, SWFACTION_STOP); }
513
514         | TOGGLEQUALITY '(' ')'
515                 { $$ = newBuffer();
516                   bufferWriteU8($$, SWFACTION_TOGGLEQUALITY); }
517
518         | STOPSOUNDS '(' ')'
519                 { $$ = newBuffer();
520                   bufferWriteU8($$, SWFACTION_STOPSOUNDS); }
521
522         | GOTOFRAME '(' NUMBER ')'
523                 { $$ = newBuffer();
524                   bufferWriteU8($$, SWFACTION_GOTOFRAME);
525                   bufferWriteS16($$, 2);
526                   bufferWriteS16($$, atoi($3));
527                   free($3); }
528
529         | GOTOFRAME '(' STRING ')'
530                 { $$ = newBuffer();
531                   bufferWriteU8($$, SWFACTION_GOTOLABEL);
532                   bufferWriteS16($$, strlen($3)+1);
533                   bufferWriteHardString($$, (byte*)$3, strlen($3)+1);
534                   free($3); }
535
536         | GOTOFRAME '(' expr ')'
537                 { $$ = $3;
538                   bufferWriteU8($$, SWFACTION_GOTOEXPRESSION);
539                   bufferWriteS16($$, 1);
540                   bufferWriteU8($$, 0); } /* XXX - and stop */
541
542         | GOTOANDPLAY '(' expr ')'
543                 { $$ = $3;
544                   bufferWriteU8($$, SWFACTION_GOTOEXPRESSION);
545                   bufferWriteS16($$, 1);
546                   bufferWriteU8($$, 1); } /* XXX - and play */
547
548         | SETTARGET '(' STRING ')'
549                 { $$ = newBuffer();
550                   bufferWriteU8($$, SWFACTION_SETTARGET);
551                   bufferWriteS16($$, strlen($3)+1);
552                   bufferWriteHardString($$, (byte*)$3, strlen($3)+1);
553                   free($3); }
554
555         | SETTARGET '(' expr ')'
556                 { $$ = $3;
557                   bufferWriteU8($$, SWFACTION_SETTARGETEXPRESSION); }
558
559         | TELLTARGET '(' STRING ')' stmt
560                 { $$ = newBuffer();
561                         /* SetTarget(STRING) */
562                   bufferWriteU8($$, SWFACTION_SETTARGET);
563                   bufferWriteS16($$, strlen($3)+1);
564                   bufferWriteHardString($$, (byte*)$3, strlen($3)+1);
565                         /* stmt */
566                   bufferConcat($$, $5);
567                         /* SetTarget('') */
568                   bufferWriteU8($$, SWFACTION_SETTARGET);
569                   bufferWriteS16($$, 1);
570                   bufferWriteU8($$, 0);
571                   free($3); }
572
573         | TELLTARGET '(' expr ')' stmt
574                 { $$ = $3;
575                         /* SetTarget(expr) */
576                   bufferWriteU8($$, SWFACTION_SETTARGETEXPRESSION); 
577                         /* stmt */
578                   bufferConcat($$, $5);
579                         /* SetTarget('') */
580                   bufferWriteU8($$, SWFACTION_SETTARGET);
581                   bufferWriteS16($$, 1);
582                   bufferWriteU8($$, 0); }
583         ;
584
585 function_call
586         : EVAL '(' expr ')'
587                 { $$ = $3;
588                   bufferWriteU8($$, SWFACTION_GETVARIABLE); }
589
590         | TIME '(' ')'
591                 { $$ = newBuffer();
592                   bufferWriteU8($$, SWFACTION_GETTIMER); }
593
594         | RANDOM '(' expr ')'
595                 { $$ = $3;
596                   bufferWriteU8($$, SWFACTION_RANDOM); }
597
598         | LENGTH '(' expr ')'
599                 { $$ = $3;
600                   bufferWriteU8($$, SWFACTION_STRINGLENGTH); }
601
602         | INT '(' expr ')'
603                 { $$ = $3;
604                   bufferWriteU8($$, SWFACTION_INT); }
605
606         | ORD '(' expr ')'
607                 { $$ = $3;
608                   bufferWriteU8($$, SWFACTION_ORD); }
609
610         | CHR '(' expr ')'
611                 { $$ = $3;
612                   bufferWriteU8($$, SWFACTION_CHR); }
613
614         | CONCAT '(' expr ',' expr ')'
615                 { $$ = $3;
616                   bufferConcat($$, $5);
617                   bufferWriteU8($$, SWFACTION_STRINGCONCAT); }
618
619         | SUBSTR '(' expr ',' expr ',' expr ')'
620                 { $$ = $3;
621                   bufferConcat($$, $5);
622                   bufferConcat($$, $7);
623                   bufferWriteU8($$, SWFACTION_SUBSTRING); }
624
625         | GETPROPERTY '(' expr ',' STRING ')'
626                 { $$ = newBuffer();
627                   bufferConcat($$, $3);
628                   bufferWriteGetProperty($$, $5);
629                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
630                   free($5); }
631         ;
632
633 pf_expr
634         : lhs_expr "++" %prec POSTFIX
635                 { $$ = newBuffer();
636                   bufferWriteBuffer($$, $1);
637                   bufferWriteU8($$, SWFACTION_GETVARIABLE);
638                   bufferWriteBuffer($$, $1);
639                   bufferConcat($$, $1);
640                   bufferWriteU8($$, SWFACTION_GETVARIABLE);
641                   bufferWriteString($$, "1", 2);
642                   bufferWriteU8($$, SWFACTION_ADD);
643                   bufferWriteU8($$, SWFACTION_SETVARIABLE); }
644
645         | lhs_expr "--" %prec POSTFIX
646                 { $$ = newBuffer();
647                   bufferWriteBuffer($$, $1);
648                   bufferWriteU8($$, SWFACTION_GETVARIABLE);
649                   bufferWriteBuffer($$, $1);
650                   bufferConcat($$, $1);
651                   bufferWriteU8($$, SWFACTION_GETVARIABLE);
652                   bufferWriteString($$, "1", 2);
653                   bufferWriteU8($$, SWFACTION_SUBTRACT);
654                   bufferWriteU8($$, SWFACTION_SETVARIABLE); }
655         ;
656
657 /* these leave a value on the stack */
658 rhs_expr
659         : function_call
660
661         | '(' rhs_expr ')'
662                 { $$ = $2; }
663
664         | NUMBER
665                 { $$ = newBuffer();
666                   bufferWriteString($$, $1, strlen($1)+1);
667                   free($1); }
668
669         | '-' NUMBER %prec NEGATE
670                 { $$ = newBuffer();
671                   bufferWriteString($$, "-", 2);
672                   bufferWriteString($$, $2, strlen($2)+1);
673                   free($2); }
674
675         | STRING
676                 { $$ = newBuffer();
677                   bufferWriteString($$, $1, strlen($1)+1);
678                   free($1); }
679
680         | variable
681                 { $$ = newBuffer();
682                   bufferWriteString($$, $1, strlen($1)+1);
683                   bufferWriteU8($$, SWFACTION_GETVARIABLE);
684                   free($1); }
685
686         | sprite
687                 { $$ = newBuffer();
688                   bufferWriteString($$, $1, strlen($1)+1);
689                   free($1); }
690
691         | sprite '.' IDENTIFIER
692                 { $$ = newBuffer();
693                   bufferWriteString($$, $1, strlen($1)+1);
694                   bufferWriteGetProperty($$, $3);
695                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
696                   free($3);
697                   free($1); }
698
699         | "++" sprite '.' IDENTIFIER
700                 { $$ = newBuffer();
701                   bufferWriteString($$, $2, strlen($2)+1);
702                   bufferWriteGetProperty($$, $4);
703                   bufferWriteString($$, $2, strlen($2)+1);
704                   bufferWriteSetProperty($$, $4);
705                   bufferWriteString($$, $2, strlen($2)+1);
706                   bufferWriteGetProperty($$, $4);
707                   bufferWriteString($$, "1", 2);
708                   bufferWriteU8($$, SWFACTION_ADD);
709                   bufferWriteU8($$, SWFACTION_SETPROPERTY);
710                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
711                   free($2);
712                   free($4); }
713
714         | "++" lhs_expr
715                 { $$ = $2;
716                   bufferWriteU8($$, SWFACTION_DUP);
717                   bufferWriteU8($$, SWFACTION_DUP);
718                   bufferWriteU8($$, SWFACTION_GETVARIABLE);
719                   bufferWriteString($$, "1", 2);
720                   bufferWriteU8($$, SWFACTION_ADD);
721                   bufferWriteU8($$, SWFACTION_SETVARIABLE);
722                   bufferWriteU8($$, SWFACTION_GETVARIABLE); }
723
724         | "--" sprite '.' IDENTIFIER
725                 { $$ = newBuffer();
726                   bufferWriteString($$, $2, strlen($2)+1);
727                   bufferWriteGetProperty($$, $4);
728                   bufferWriteString($$, $2, strlen($2)+1);
729                   bufferWriteSetProperty($$, $4);
730                   bufferWriteString($$, $2, strlen($2)+1);
731                   bufferWriteGetProperty($$, $4);
732                   bufferWriteString($$, "1", 2);
733                   bufferWriteU8($$, SWFACTION_ADD);
734                   bufferWriteU8($$, SWFACTION_SETPROPERTY);
735                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
736                   free($2);
737                   free($4); }
738
739         | "--" lhs_expr
740                 { $$ = $2;
741                   bufferWriteU8($$, SWFACTION_DUP);
742                   bufferWriteU8($$, SWFACTION_DUP);
743                   bufferWriteU8($$, SWFACTION_GETVARIABLE);
744                   bufferWriteString($$, "1", 2);
745                   bufferWriteU8($$, SWFACTION_SUBTRACT);
746                   bufferWriteU8($$, SWFACTION_SETVARIABLE);
747                   bufferWriteU8($$, SWFACTION_GETVARIABLE); }
748
749         | '-' rhs_expr %prec UMINUS
750                 { $$ = $2;
751                   bufferWriteString($2, "-1", 3);
752                   bufferWriteU8($2, SWFACTION_MULTIPLY); }
753
754         | '!' rhs_expr
755                 { $$ = $2;
756                   bufferWriteU8($2, SWFACTION_LOGICALNOT); }
757
758         | lhs_expr '=' rhs_expr /* assign and leave copy on stack */
759                 { $$ = $1;
760                   bufferConcat($$, $3);
761                   bufferWriteU8($$, SWFACTION_DUP);
762                   bufferWriteU8($$, SWFACTION_SETVARIABLE); }
763
764         | rhs_expr '*' rhs_expr
765                 { $$ = $1;
766                   bufferConcat($$, $3);
767                   bufferWriteU8($$, SWFACTION_MULTIPLY); }
768
769         | rhs_expr '/' rhs_expr
770                 { $$ = $1;
771                   bufferConcat($$, $3);
772                   bufferWriteU8($$, SWFACTION_DIVIDE); }
773
774         | rhs_expr '+' rhs_expr
775                 { $$ = $1;
776                   bufferConcat($$, $3);
777                   bufferWriteU8($$, SWFACTION_ADD); }
778
779         | rhs_expr '-' rhs_expr
780                 { $$ = $1;
781                   bufferConcat($$, $3);
782                   bufferWriteU8($$, SWFACTION_SUBTRACT); }
783
784         | rhs_expr '&' rhs_expr
785                 { $$ = $1;
786                   bufferConcat($$, $3);
787                   bufferWriteU8($$, SWFACTION_STRINGCONCAT); }
788
789         | rhs_expr '<' rhs_expr
790                 { $$ = $1;
791                   bufferConcat($$, $3);
792                   bufferWriteU8($$, SWFACTION_LESSTHAN); }
793
794         | rhs_expr '>' rhs_expr
795                 { $$ = $3;
796                   bufferConcat($$, $1);
797                   bufferWriteU8($$, SWFACTION_LESSTHAN); }
798
799         | rhs_expr "<=" rhs_expr
800                 { $$ = $3;
801                   bufferConcat($$, $1);
802                   bufferWriteU8($$, SWFACTION_LESSTHAN);
803                   bufferWriteU8($$, SWFACTION_LOGICALNOT); }
804
805         | rhs_expr ">=" rhs_expr
806                 { bufferConcat($1, $3);
807                   bufferWriteU8($1, SWFACTION_LESSTHAN);
808                   bufferWriteU8($1, SWFACTION_LOGICALNOT); }
809
810         | rhs_expr "!==" rhs_expr
811                 { bufferConcat($1, $3);
812                   bufferWriteU8($1, SWFACTION_STRINGEQ);
813                   bufferWriteU8($1, SWFACTION_LOGICALNOT); }
814
815         | rhs_expr "===" rhs_expr
816                 { bufferConcat($1, $3);
817                   bufferWriteU8($1, SWFACTION_STRINGEQ); }
818
819         | rhs_expr "<=>" rhs_expr
820                 { bufferConcat($1, $3);
821                   bufferWriteU8($1, SWFACTION_STRINGCOMPARE); }
822
823         | rhs_expr "==" rhs_expr
824                 { bufferConcat($1, $3);
825                   bufferWriteU8($1, SWFACTION_EQUAL); }
826
827         | rhs_expr "!=" rhs_expr
828                 { bufferConcat($1, $3);
829                   bufferWriteU8($1, SWFACTION_EQUAL);
830                   bufferWriteU8($1, SWFACTION_LOGICALNOT); }
831
832         | rhs_expr "&&" rhs_expr
833                 { bufferConcat($1, $3);
834                   bufferWriteU8($1, SWFACTION_LOGICALAND); }
835
836         | rhs_expr "||" rhs_expr
837                 { bufferConcat($1, $3);
838                   bufferWriteU8($1, SWFACTION_LOGICALOR); }
839
840         | rhs_expr '?' rhs_expr ':' rhs_expr
841                 { bufferWriteU8($1, SWFACTION_BRANCHIFTRUE);
842                   bufferWriteS16($1, 2);
843                   bufferWriteS16($1, bufferLength($5)+5);
844                   bufferConcat($1, $5);
845                   bufferWriteU8($1, SWFACTION_BRANCHALWAYS);
846                   bufferWriteS16($1, 2);
847                   bufferWriteS16($1, bufferLength($3));
848                   bufferConcat($1, $3); }
849         ;
850
851 variable
852         : IDENTIFIER
853
854         | sprite ':' IDENTIFIER
855                 { $$ = $1;
856                   $$ = stringConcat($$, strdup(":"));
857                   $$ = stringConcat($$, $3); }
858         ;
859
860 sprite
861         : THIS
862                 { $$ = strdup(""); }
863
864         | '.'
865                 { $$ = strdup(""); }
866
867         | '/'
868                 { $$ = strdup("/"); }
869
870         | PARENT
871                 { $$ = strdup(".."); }
872
873         | IDENTIFIER
874                 { $$ = $1; }
875
876         | PATH
877                 { $$ = $1; }
878         ;
879
880 lhs_expr
881         : variable
882                 { $$ = newBuffer();
883                   bufferWriteString($$, $1, strlen($1)+1);
884                   free($1); }
885
886         | STRING
887                 { $$ = newBuffer();
888                   bufferWriteString($$, $1, strlen($1)+1);
889                   free($1); }
890
891         | '(' rhs_expr ')'      { $$ = $2; }
892         ;
893
894 assign_stmt
895         : pf_expr
896
897         | void_function_call
898
899         | "++" lhs_expr
900                 { $$ = $2;
901                   bufferWriteBuffer($$, $2);
902                   bufferWriteU8($$, SWFACTION_GETVARIABLE);
903                   bufferWriteString($$, "1", 2);
904                   bufferWriteU8($$, SWFACTION_ADD);
905                   bufferWriteU8($$, SWFACTION_SETVARIABLE); }
906
907         | "--" lhs_expr
908                 { $$ = $2;
909                   bufferWriteBuffer($$, $2);
910                   bufferWriteU8($$, SWFACTION_GETVARIABLE);
911                   bufferWriteString($$, "1", 2);
912                   bufferWriteU8($$, SWFACTION_SUBTRACT);
913                   bufferWriteU8($$, SWFACTION_SETVARIABLE); }
914
915         | "++" sprite '.' IDENTIFIER
916                 { $$ = newBuffer();
917                   bufferWriteString($$, $2, strlen($2)+1);
918                   bufferWriteGetProperty($$, $4);
919                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
920                   bufferWriteString($$, "1", 2);
921                   bufferWriteU8($$, SWFACTION_ADD);
922                   bufferWriteString($$, $2, strlen($2)+1);
923                   bufferWriteSetProperty($$, $4);
924                   bufferWriteU8($$, SWFACTION_SETPROPERTY);
925                   free($2);
926                   free($4); }
927
928         | "--" sprite '.' IDENTIFIER
929                 { $$ = newBuffer();
930                   bufferWriteString($$, $2, strlen($2)+1);
931                   bufferWriteGetProperty($$, $4);
932                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
933                   bufferWriteString($$, "1", 2);
934                   bufferWriteU8($$, SWFACTION_SUBTRACT);
935                   bufferWriteString($$, $2, strlen($2)+1);
936                   bufferWriteSetProperty($$, $4);
937                   bufferWriteU8($$, SWFACTION_SETPROPERTY);
938                   free($2);
939                   free($4); }
940
941         | lhs_expr '=' rhs_expr
942                 { bufferConcat($1, $3);
943                   bufferWriteU8($1, SWFACTION_SETVARIABLE); }
944
945         | lhs_expr "*=" rhs_expr
946                 { bufferWriteBuffer($1, $1);
947                   bufferWriteU8($1, SWFACTION_GETVARIABLE);
948                   bufferConcat($1, $3);
949                   bufferWriteU8($1, SWFACTION_MULTIPLY);
950                   bufferWriteU8($1, SWFACTION_SETVARIABLE); }
951
952         | lhs_expr "/=" rhs_expr
953                 { bufferWriteBuffer($1, $1);
954                   bufferWriteU8($1, SWFACTION_GETVARIABLE);
955                   bufferConcat($1, $3);
956                   bufferWriteU8($1, SWFACTION_DIVIDE);
957                   bufferWriteU8($1, SWFACTION_SETVARIABLE); }
958
959         | lhs_expr "+=" rhs_expr
960                 { bufferWriteBuffer($1, $1);
961                   bufferWriteU8($1, SWFACTION_GETVARIABLE);
962                   bufferConcat($1, $3);
963                   bufferWriteU8($1, SWFACTION_ADD);
964                   bufferWriteU8($1, SWFACTION_SETVARIABLE); }
965
966         | lhs_expr "-=" rhs_expr
967                 { bufferWriteBuffer($1, $1);
968                   bufferWriteU8($1, SWFACTION_GETVARIABLE);
969                   bufferConcat($1, $3);
970                   bufferWriteU8($1, SWFACTION_SUBTRACT);
971                   bufferWriteU8($1, SWFACTION_SETVARIABLE); }
972
973         | sprite '.' IDENTIFIER '=' rhs_expr
974                 { $$ = newBuffer();
975                   bufferWriteString($$, $1, strlen($1)+1);
976                   bufferWriteSetProperty($$, $3);
977                   bufferConcat($$,$5);
978                   bufferWriteU8($$, SWFACTION_SETPROPERTY);
979                   free($1);
980                   free($3); }
981
982         | sprite '.' IDENTIFIER "*=" rhs_expr
983                 { $$ = newBuffer();
984                   bufferWriteString($$, $1, strlen($1)+1);
985                   bufferWriteSetProperty($$, $3);
986                   bufferWriteString($$, $1, strlen($1)+1);
987                   bufferWriteGetProperty($$, $3);
988                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
989                   bufferConcat($$, $5);
990                   bufferWriteU8($$, SWFACTION_MULTIPLY);
991                   bufferWriteU8($$, SWFACTION_SETPROPERTY);
992                   free($1);
993                   free($3); }
994
995         | sprite '.' IDENTIFIER "/=" rhs_expr
996                 { $$ = newBuffer();
997                   bufferWriteString($$, $1, strlen($1)+1);
998                   bufferWriteSetProperty($$, $3);
999                   bufferWriteString($$, $1, strlen($1)+1);
1000                   bufferWriteGetProperty($$, $3);
1001                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
1002                   bufferConcat($$, $5);
1003                   bufferWriteU8($$, SWFACTION_DIVIDE);
1004                   bufferWriteU8($$, SWFACTION_SETPROPERTY);
1005                   free($1);
1006                   free($3); }
1007
1008         | sprite '.' IDENTIFIER "+=" rhs_expr
1009                 { $$ = newBuffer();
1010                   bufferWriteString($$, $1, strlen($1)+1);
1011                   bufferWriteSetProperty($$, $3);
1012                   bufferWriteString($$, $1, strlen($1)+1);
1013                   bufferWriteGetProperty($$, $3);
1014                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
1015                   bufferConcat($$, $5);
1016                   bufferWriteU8($$, SWFACTION_ADD);
1017                   bufferWriteU8($$, SWFACTION_SETPROPERTY);
1018                   free($1);
1019                   free($3); }
1020
1021         | sprite '.' IDENTIFIER "-=" rhs_expr
1022                 { $$ = newBuffer();
1023                   bufferWriteString($$, $1, strlen($1)+1);
1024                   bufferWriteSetProperty($$, $3);
1025                   bufferWriteString($$, $1, strlen($1)+1);
1026                   bufferWriteGetProperty($$, $3);
1027                   bufferWriteU8($$, SWFACTION_GETPROPERTY);
1028                   bufferConcat($$, $5);
1029                   bufferWriteU8($$, SWFACTION_SUBTRACT);
1030                   bufferWriteU8($$, SWFACTION_SETPROPERTY);
1031                   free($1);
1032                   free($3); }
1033         ;
1034
1035 expr
1036         : rhs_expr
1037         ;
1038
1039 %%