📄 swf4compiler.y
字号:
/* $Id: swf4compiler.y,v 1.15 2007/11/22 10:33:30 krechert Exp $ */%start program%{#include <time.h>#include <string.h>#include <stdlib.h>#include "compile.h"#include "actiontypes.h"#include "assembler.h"#define YYPARSE_PARAM buffer#define YYERROR_VERBOSE 1%}%union { Buffer action; char *str; SWFActionFunction function; SWFGetUrl2Method getURLMethod; int len;}/* tokens etc. */%token BREAK%token FOR%token CONTINUE%token IF%token ELSE%token DO%token WHILE%token THIS/* functions */%token EVAL%token TIME%token RANDOM%token LENGTH%token INT%token CONCAT%token DUPLICATECLIP%token REMOVECLIP%token TRACE%token STARTDRAG%token STOPDRAG%token ORD%token CHR%token CALLFRAME%token GETURL%token GETURL1%token LOADMOVIE%token LOADVARIABLES%token POSTURL%token SUBSTR%token GETPROPERTY/* v3 functions */%token NEXTFRAME%token PREVFRAME%token PLAY%token STOP%token TOGGLEQUALITY%token STOPSOUNDS%token GOTOFRAME%token GOTOANDPLAY%token FRAMELOADED%token SETTARGET%token ASM/* v4 ASM */%token ASMADD ASMDIVIDE ASMMULTIPLY ASMEQUALS ASMLESS ASMLOGICALAND ASMLOGICALOR ASMLOGICALNOT %token ASMSTRINGAND ASMSTRINGEQUALS ASMSTRINGEXTRACT ASMSTRINGLENGTH ASMMBSTRINGEXTRACT %token ASMMBSTRINGLENGTH ASMPOP ASMPUSH ASMASCIITOCHAR ASMCHARTOASCII ASMTOINTEGER%token ASMCALL ASMIF ASMJUMP ASMGETVARIABLE ASMSETVARIABLE ASMGETURL2 ASMGETPROPERTY %token ASMGOTOFRAME2 ASMREMOVESPRITE ASMSETPROPERTY ASMSETTARGET2 ASMSTARTDRAG%token ASMWAITFORFRAME2 ASMCLONESPRITE ASMENDDRAG ASMGETTIME ASMRANDOMNUMBER ASMTRACE%token ASMMBASCIITOCHAR ASMMBCHARTOASCII ASMSUBSTRACT ASMSTRINGLESS /* high level functions */%token TELLTARGET%token BROKENSTRING/* these three are strdup'ed in compiler.flex, so free them here */%token <str> STRING%token <str> NUMBER%token <str> IDENTIFIER%token <str> PATH%type <getURLMethod> urlmethod%token EQ "=="%token LE "<="%token GE ">="%token NE "!="%token LAN "&&"%token LOR "||"%token INC "++"%token DEC "--"%token IEQ "+="%token DEQ "/="%token MEQ "*="%token SEQ "-="%token STREQ "==="%token STRNE "!=="%token STRCMP "<=>"%token PARENT ".."%token END "end"/* ascending order of ops ..? */%left ','%right '=' "*=" "/=" "+=" "-="%right '?' ':'%left "&&" "||"%left "==" "!=" "===" "!=="%left '<' '>' "<=" ">=" "<=>"%left '&'%left '+' '-'%left '*' '/'%right "++" "--" UMINUS '!'%right POSTFIX%right NEGATE%type <action> elem%type <action> elems%type <action> stmt%type <action> statements%type <action> if_stmt%type <action> iter_stmt%type <action> cont_stmt%type <action> break_stmt%type <action> expr_opt%type <action> void_function_call%type <action> function_call%type <action> lhs_expr%type <action> pf_expr%type <action> rhs_expr%type <action> assign_stmt%type <action> assign_stmts%type <action> assign_stmts_opt%type <action> expr%type <action> program%type <len> opcode opcode_list push_item push_list/* make sure to free these, too! */%type <str> sprite%type <str> variable%%/* rules */program : elems { *((Buffer *)buffer) = $1; } ;elems : elem | elems elem { bufferConcat($1, $2); } ;elem : stmt ;stmt : '{' '}' { $$ = NULL; } | '{' statements '}' { $$ = $2; } | ';' { $$ = NULL; } | assign_stmt ';' | if_stmt | iter_stmt | cont_stmt | break_stmt ;assign_stmts : assign_stmt | assign_stmts ',' assign_stmt { bufferConcat($1, $3); } ;statements : /* empty */ { $$ = NULL; } | stmt | statements stmt { bufferConcat($1, $2); } ;if_stmt /* XXX- I haven't tested the frameloaded() stuff yet.. */ : IF '(' FRAMELOADED '(' NUMBER ')' ')' stmt ELSE stmt { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_WAITFORFRAME); bufferWriteS16($$, 3); bufferWriteS16($$, atoi($5)); free($5); bufferWriteU8($$, 1); /* if not loaded, jump to.. */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($10)+5); bufferConcat($$, $10); /* ..here */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($8)); bufferConcat($$, $8); } | IF '(' FRAMELOADED '(' NUMBER ')' ')' stmt { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_WAITFORFRAME); bufferWriteS16($$, 3); bufferWriteS16($$, atoi($5)); free($5); bufferWriteU8($$, 1); /* if not loaded, jump to.. */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, 5); bufferWriteU8($$, SWFACTION_JUMP); /* ..here */ bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($8)); /* ..and then out */ bufferConcat($$, $8); } /* make this case cleaner.. */ | IF '(' '!' FRAMELOADED '(' NUMBER ')' ')' stmt { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_WAITFORFRAME); bufferWriteS16($$, 3); bufferWriteS16($$, atoi($6)); free($6); bufferWriteU8($$, 1); /* if not loaded, jump to.. */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($9)); bufferConcat($$, $9); } /* ..here */ | IF '(' FRAMELOADED '(' expr ')' ')' stmt ELSE stmt { $$ = $5; bufferWriteU8($$, SWFACTION_WAITFORFRAME2); bufferWriteS16($$, 1); bufferWriteU8($$, 1); /* if not loaded, jump to.. */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($10)+5); bufferConcat($$, $10); /* ..here */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($8)); bufferConcat($$, $8); } | IF '(' FRAMELOADED '(' expr ')' ')' stmt { $$ = $5; bufferWriteU8($$, SWFACTION_WAITFORFRAME2); bufferWriteS16($$, 1); bufferWriteU8($$, 1); /* if not loaded, jump to.. */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, 5); bufferWriteU8($$, SWFACTION_JUMP); /* ..here */ bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($8)); /* ..and then out */ bufferConcat($$, $8); } /* make this case cleaner.. */ | IF '(' '!' FRAMELOADED '(' expr ')' ')' stmt { $$ = $6; bufferWriteU8($$, SWFACTION_WAITFORFRAME2); bufferWriteS16($$, 1); bufferWriteU8($$, 1); /* if not loaded, jump to.. */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($9)); bufferConcat($$, $9); } /* ..here */ | IF '(' expr ')' stmt ELSE stmt { bufferWriteU8($3, SWFACTION_IF); bufferWriteS16($3, 2); bufferWriteS16($3, bufferLength($7)+5); bufferConcat($3, $7); bufferWriteU8($3, SWFACTION_JUMP); bufferWriteS16($3, 2); bufferWriteS16($3, bufferLength($5)); bufferConcat($3, $5); $$ = $3; } | IF '(' expr ')' stmt { bufferWriteU8($3, SWFACTION_LOGICALNOT); bufferWriteU8($3, SWFACTION_IF); bufferWriteS16($3, 2); bufferWriteS16($3, bufferLength($5)); bufferConcat($3, $5); $$ = $3; } ;expr_opt : /* empty */ { $$ = NULL; } | expr { $$ = $1; } ;/* not thought out yet..switch_stmt : SWITCH '(' expr ')' '{' { $$ = $3; pushLoop(); } switch_cases '}' { bufferConcat($$, $7); } ;switch_cases : switch_cases switch_case | switch_case ;switch_case : CASE INTEGER ':' stmt { $$ = newBuffer(); } ;*/iter_stmt : WHILE '(' '!' FRAMELOADED '(' NUMBER ')' ')' stmt { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_WAITFORFRAME); bufferWriteS16($$, 3); bufferWriteS16($$, atoi($6)); free($6); bufferWriteU8($$, 1); /* if not loaded, jump to.. */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($9)+5); bufferConcat($$, $9); /* ..here */ bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, -(bufferLength($$)+2)); } | WHILE '(' expr ')' stmt { $$ = $3; bufferWriteU8($$, SWFACTION_LOGICALNOT); bufferWriteU8($$, SWFACTION_IF); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($5)+5); bufferConcat($$, $5); bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, -(bufferLength($$)+2)); bufferResolveJumps($$); } | DO stmt WHILE '(' expr ')' { $$ = $2; bufferConcat($$, $5); bufferWriteU8($$, SWFACTION_IF); bufferWriteS16($$, 2); bufferWriteS16($$, -(bufferLength($$)+2)); bufferResolveJumps($$); } | FOR '(' assign_stmts_opt ';' expr_opt ';' assign_stmts_opt ')' stmt { if (!$5) $5 = newBuffer(); else { bufferWriteU8($5, SWFACTION_LOGICALNOT); bufferWriteU8($5, SWFACTION_IF); bufferWriteS16($5, 2); bufferWriteS16($5, bufferLength($9)+bufferLength($7)+5); } bufferConcat($5, $9); bufferConcat($5, $7); bufferWriteU8($5, SWFACTION_JUMP); bufferWriteS16($5, 2); bufferWriteS16($5, -(bufferLength($5)+2)); bufferResolveJumps($5); $$ = $3; if(!$$) $$ = newBuffer(); bufferConcat($$, $5); } ;assign_stmts_opt : /* empty */ { $$ = NULL; } | assign_stmts ;cont_stmt : CONTINUE ';' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, MAGIC_CONTINUE_NUMBER); } ;break_stmt : BREAK ';' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, MAGIC_BREAK_NUMBER); } ;urlmethod : /* empty */ { $$ = GETURL_METHOD_NOSEND; } | ',' STRING { if(strcmp($2, "GET") == 0) $$ = GETURL_METHOD_GET; else if(strcmp($2, "POST") == 0) $$ = GETURL_METHOD_POST; } ;void_function_call : STOPDRAG '(' ')' /* no args */ { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_ENDDRAG); } | CALLFRAME '(' variable ')' { $$ = newBuffer(); bufferWriteString($$, $3, strlen($3)+1); bufferWriteU8($$, SWFACTION_CALLFRAME); bufferWriteS16($$, 0); free($3); } | CALLFRAME '(' STRING ')' { $$ = newBuffer(); bufferWriteString($$, $3, strlen($3)+1); bufferWriteU8($$, SWFACTION_CALLFRAME); bufferWriteS16($$, 0); free($3); } | REMOVECLIP '(' expr ')' { $$ = $3; bufferWriteU8($$, SWFACTION_REMOVECLIP); } | TRACE '(' expr ')' { $$ = $3; bufferWriteU8($$, SWFACTION_TRACE); } /* getURL2(url, window, [method]) */ | GETURL '(' expr ',' expr ')' { $$ = $3; bufferConcat($$, $5); bufferWriteU8($$, SWFACTION_GETURL2); bufferWriteS16($$, 1); bufferWriteU8($$, GETURL_METHOD_NOSEND); } | GETURL '(' expr ',' expr urlmethod ')' { $$ = $3; bufferConcat($$, $5); bufferWriteU8($$, SWFACTION_GETURL2); bufferWriteS16($$, 1); bufferWriteU8($$, $6); } | GETURL1 '(' STRING ',' STRING ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_GETURL); bufferWriteS16($$, strlen($3) + strlen($5) + 2); bufferWriteHardString($$, $3, strlen($3)); bufferWriteU8($$, 0); bufferWriteHardString($$, $5, strlen($5)); bufferWriteU8($$, 0); } | LOADMOVIE '(' expr ',' expr urlmethod ')' { $$ = $3; bufferConcat($$, $5); bufferWriteU8($$, SWFACTION_GETURL2); bufferWriteS16($$, 1); bufferWriteU8($$, $6 | GETURL_LOADMOVIE); } | LOADVARIABLES '(' expr ',' expr urlmethod ')' { $$ = $3; bufferConcat($$, $5); bufferWriteU8($$, SWFACTION_GETURL2); bufferWriteS16($$, 1); bufferWriteU8($$, 0xc0 + $6); } /* startDrag(target, lock, [left, right, top, bottom]) */ | STARTDRAG '(' expr ',' expr ')' { $$ = newBuffer(); bufferWriteString($$, "0", 2); /* no constraint */ bufferConcat($$, $5); bufferConcat($$, $3); bufferWriteU8($$, SWFACTION_STARTDRAG); } | STARTDRAG '(' expr ',' expr ',' expr ',' expr ',' expr ',' expr ')' { $$ = newBuffer(); bufferConcat($$, $7); bufferConcat($$, $11); bufferConcat($$, $9); bufferConcat($$, $13); bufferWriteString($$, "1", 2); /* has constraint */ bufferConcat($$, $5); bufferConcat($$, $3); bufferWriteU8($$, SWFACTION_STARTDRAG); } /* duplicateClip(target, new, depth) */ | DUPLICATECLIP '(' expr ',' expr ',' expr ')' { $$ = $3; bufferConcat($$, $5); bufferConcat($$, $7); bufferWriteWTHITProperty($$); bufferWriteU8($$, SWFACTION_ADD); /* see docs for explanation */ bufferWriteU8($$, SWFACTION_DUPLICATECLIP); } /* v3 actions */ | NEXTFRAME '(' ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_NEXTFRAME); } | PREVFRAME '(' ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_PREVFRAME); } | PLAY '(' ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_PLAY); } | STOP '(' ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_STOP); } | TOGGLEQUALITY '(' ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_TOGGLEQUALITY); } | STOPSOUNDS '(' ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_STOPSOUNDS); } | GOTOFRAME '(' NUMBER ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_GOTOFRAME); bufferWriteS16($$, 2); bufferWriteS16($$, atoi($3)); free($3); } | GOTOFRAME '(' STRING ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_GOTOLABEL); bufferWriteS16($$, strlen($3)+1); bufferWriteHardString($$, $3, strlen($3)+1); free($3); } | GOTOFRAME '(' expr ')' { $$ = $3; bufferWriteU8($$, SWFACTION_GOTOFRAME2); bufferWriteS16($$, 1); bufferWriteU8($$, 0); } /* XXX - and stop */ | GOTOANDPLAY '(' expr ')' { $$ = $3; bufferWriteU8($$, SWFACTION_GOTOFRAME2); bufferWriteS16($$, 1); bufferWriteU8($$, 1); } /* XXX - and play */ | SETTARGET '(' STRING ')' { $$ = newBuffer(); bufferWriteU8($$, SWFACTION_SETTARGET); bufferWriteS16($$, strlen($3)+1); bufferWriteHardString($$, $3, strlen($3)+1); free($3); } | SETTARGET '(' expr ')'
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -