📄 swf5compiler.y
字号:
/* $Id: swf5compiler.y,v 1.18 2003/12/14 11:18:07 whamann Exp $ */%start program%{#include <time.h>#include <string.h>#include <stdlib.h>#include "compile.h"#include "action.h"#include "assembler.h"#define YYPARSE_PARAM bufferBuffer bf, bc;%}%union{ Buffer action; char *str; SWFGetUrl2Method getURLMethod; int op; int intVal; int len; double doubleVal; struct { Buffer buffer; int count; } exprlist; struct switchcase switchcase; struct switchcases switchcases; struct { Buffer obj, ident, memexpr; } lval;}/* tokens etc. */%token BREAK CONTINUE FUNCTION ELSE SWITCH CASE DEFAULT FOR IN IF WHILE%token DO VAR NEW DELETE RETURN END WITH ASM EVAL%token RANDOM GETTIMER LENGTH CONCAT SUBSTR TRACE INT ORD CHR GETURL%token GETURL1 NEXTFRAME PREVFRAME PLAY STOP TOGGLEQUALITY STOPSOUNDS%token DUP SWAP POP PUSH SETREGISTER CALLFUNCTION CALLMETHOD%token AND OR XOR MODULO ADD LESSTHAN EQUALS%token INC DEC TYPEOF INSTANCEOF ENUMERATE INITOBJECT INITARRAY GETMEMBER%token SETMEMBER SHIFTLEFT SHIFTRIGHT SHIFTRIGHT2 VAREQUALS OLDADD SUBTRACT%token MULTIPLY DIVIDE OLDEQUALS OLDLESSTHAN LOGICALAND LOGICALOR NOT%token STRINGEQ STRINGLENGTH SUBSTRING GETVARIABLE SETVARIABLE%token SETTARGETEXPRESSION DUPLICATEMOVIECLIP REMOVEMOVIECLIP%token STRINGLESSTHAN MBLENGTH MBSUBSTRING MBORD MBCHR%token BRANCHALWAYS BRANCHIFTRUE GETURL2 POST GET%token LOADVARIABLES LOADMOVIE LOADVARIABLESNUM LOADMOVIENUM%token CALLFRAME STARTDRAG STOPDRAG GOTOFRAME SETTARGET%token NULLVAL%token <intVal> INTEGER%token <doubleVal> DOUBLE%token <intVal> BOOLEAN%token <str> REGISTER/* these two are strdup'ed in compiler.flex, so free them up here */%token <str> STRING%token <str> IDENTIFIER%token EQ "=="%token LE "<="%token GE ">="%token NE "!="%token LAN "&&"%token LOR "||"%token INCR "++"%token DECR "--"%token IEQ "+="%token DEQ "/="%token MEQ "*="%token SEQ "-="%token REQ "%="%token AEQ "&="%token OEQ "|="%token SHL "<<"%token SHR ">>"%token SHR2 ">>>"%token SHLEQ "<<="%token SHREQ ">>="%token SHR2EQ ">>>="/* ascending order of ops ..? */%nonassoc NOELSE%nonassoc ELSE%left ','%right '=' "*=" "/=" "%=" "+=" "-=" "&=" "|=" "^=" ">>=" ">>>=" "<<="%right '?' ':'%left "&&" "||"%left "==" "!="%left '<' '>' "<=" ">="%left '&' '|' '^'%left "<<" ">>" ">>>"%left '+' '-'%left '*' '/' '%'%nonassoc "++" "--"%right '!' '~' UMINUS%right POSTFIX%right TYPEOF%nonassoc INSTANCEOF%left '.' '[' ']'%type <action> program code%type <action> stmt stmts%type <action> if_stmt iter_stmt cont_stmt break_stmt return_stmt%type <action> with_stmt%type <action> switch_stmt%type <action> anon_function_decl function_decl anycode%type <action> void_function_call function_call method_call%type <action> assign_stmt assign_stmts assign_stmts_opt%type <action> expr expr_or_obj objexpr expr_opt obj_ref%type <action> emptybraces level init_vars init_var primary lvalue_expr%type <lval> lvalue%type <exprlist> expr_list objexpr_list formals_list%type <switchcase> switch_case%type <switchcases> switch_cases%type <op> assignop incdecop%type <getURLMethod> urlmethod%type <str> identifier%type <len> opcode opcode_list push_item with push_list/*%type <intVal> integer%type <doubleVal> double*/%%/* rules */program : { bf = newBuffer(); bc = newBuffer(); } code { Buffer b = newBuffer(); bufferWriteConstants(b); bufferConcat(b, bf); bufferConcat(b, bc); *((Buffer *)buffer) = b; } | /* nothing */ { Buffer b = newBuffer(); *((Buffer *)buffer) = b; } ;code : anycode | code anycode ;anycode : stmt { bufferConcat(bc, $1); } | function_decl { bufferConcat(bf, $1); } ;stmts : stmt { $$ = $1; } | stmts stmt { $$ = $1; bufferConcat($$, $2); } ;emptybraces : '{' '}' { } ;stmt : emptybraces { $$ = NULL; } | '{' stmts '}' { $$ = $2; } | ';' { $$ = NULL; } | assign_stmt ';' { $$ = $1; } | if_stmt | iter_stmt | cont_stmt | break_stmt | switch_stmt | return_stmt | with_stmt ;with_stmt : WITH '(' expr ')' '{' stmts '}' { $$ = $3; bufferWriteOp($$, SWFACTION_WITH); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($6)); bufferConcat($$, $6); } ;// only possible if there is an active CTX_FUNCTION// in some contexts, may have to pop a few values ...return_stmt : RETURN ';' { int tmp = chkctx(CTX_FUNCTION); if(tmp < 0) swf5error("return outside function"); $$ = newBuffer(); while(--tmp >= 0) bufferWriteOp($$, SWFACTION_POP); bufferWriteNull($$); bufferWriteOp($$, SWFACTION_RETURN); } | RETURN expr_or_obj ';' { int tmp = chkctx(CTX_FUNCTION); if(tmp < 0) swf5error("return outside function"); $$ = newBuffer(); while(--tmp >= 0) bufferWriteOp($$, SWFACTION_POP); bufferConcat($$, $2); bufferWriteOp($$, SWFACTION_RETURN); } ;assign_stmts : assign_stmt | assign_stmts ',' assign_stmt { bufferConcat($1, $3); } ;if_stmt : IF '(' expr ')' stmt ELSE stmt { $$ = $3; bufferWriteOp($$, SWFACTION_BRANCHIFTRUE); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($7)+5); bufferConcat($$, $7); bufferWriteOp($$, SWFACTION_BRANCHALWAYS); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($5)); bufferConcat($$, $5); } | IF '(' expr ')' stmt %prec NOELSE { $$ = $3; bufferWriteOp($$, SWFACTION_LOGICALNOT); bufferWriteOp($$, SWFACTION_BRANCHIFTRUE); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($5)); bufferConcat($$, $5); } ;expr_opt : /* empty */ { $$ = NULL; } | expr { $$ = $1; } ;switch_init : SWITCH { addctx(CTX_SWITCH); } ;switch_stmt : switch_init '(' expr ')' '{' switch_cases '}' { $$ = $3; bufferResolveSwitch($$, &$6); bufferResolveJumps($$); bufferWriteOp($$, SWFACTION_POP); delctx(CTX_SWITCH); /* FIXME: continue in switch continues surrounding loop, if any */ } ;/* XXX */switch_cases : /* empty */ { $$.count = 0; $$.list = 0; } | switch_cases switch_case { $$ = $1; $$.list = (struct switchcase*) realloc($$.list, ($$.count+1) * sizeof(struct switchcase)); $$.list[$$.count] = $2; $$.count++; } ;switch_case : CASE expr ':' stmts BREAK ';' { $$.cond = $2; $$.action = $4; $$.isbreak = 1; } | CASE expr ':' stmts { $$.cond = $2; $$.action = $4; $$.isbreak = 0; } | DEFAULT ':' stmts { $$.cond = NULL; $$.action = $3; $$.isbreak = 0; } ;/* there's GOT to be a better way than this.. */identifier : IDENTIFIER | NEW { $$ = strdup("new"); } | DELETE { $$ = strdup("delete"); } | RANDOM { $$ = strdup("random"); } | GETTIMER { $$ = strdup("getTimer"); } | LENGTH { $$ = strdup("length"); } | CONCAT { $$ = strdup("concat"); } | SUBSTR { $$ = strdup("substr"); } | TRACE { $$ = strdup("trace"); } | INT { $$ = strdup("int"); } | ORD { $$ = strdup("ord"); } | CHR { $$ = strdup("chr"); } | GETURL { $$ = strdup("getURL"); } | GETURL1 { $$ = strdup("getURL1"); } | NEXTFRAME { $$ = strdup("nextFrame"); } | PREVFRAME { $$ = strdup("prevFrame"); } | PLAY { $$ = strdup("play"); } | STOP { $$ = strdup("stop"); } | TOGGLEQUALITY { $$ = strdup("toggleQuality"); } | STOPSOUNDS { $$ = strdup("stopSounds"); } | DUP { $$ = strdup("dup"); } | SWAP { $$ = strdup("swap"); } | POP { $$ = strdup("pop"); } | PUSH { $$ = strdup("push"); } | SETREGISTER { $$ = strdup("setRegister"); } | CALLFUNCTION { $$ = strdup("callFunction"); } | CALLMETHOD { $$ = strdup("callMethod"); } | AND { $$ = strdup("and"); } | OR { $$ = strdup("or"); } | XOR { $$ = strdup("xor"); } | MODULO { $$ = strdup("modulo"); } | ADD { $$ = strdup("add"); } | LESSTHAN { $$ = strdup("lessThan"); } | EQUALS { $$ = strdup("equals"); } | INC { $$ = strdup("inc"); } | DEC { $$ = strdup("dec"); } | TYPEOF { $$ = strdup("typeof"); } | INSTANCEOF { $$ = strdup("instanceof"); } | ENUMERATE { $$ = strdup("enumerate"); } | INITOBJECT { $$ = strdup("initobject"); } | INITARRAY { $$ = strdup("initarray"); } | GETMEMBER { $$ = strdup("getmember"); } | SETMEMBER { $$ = strdup("setmember"); } | SHIFTLEFT { $$ = strdup("shiftleft"); } | SHIFTRIGHT { $$ = strdup("shiftright"); } | SHIFTRIGHT2 { $$ = strdup("shiftright2"); } | VAREQUALS { $$ = strdup("varequals"); } | OLDADD { $$ = strdup("oldAdd"); } | SUBTRACT { $$ = strdup("subtract"); } | MULTIPLY { $$ = strdup("multiply"); } | DIVIDE { $$ = strdup("divide"); } | OLDEQUALS { $$ = strdup("oldequals"); } | OLDLESSTHAN { $$ = strdup("oldlessthan"); } | LOGICALAND { $$ = strdup("logicaland"); } | LOGICALOR { $$ = strdup("logicalor"); } | NOT { $$ = strdup("not"); } | STRINGEQ { $$ = strdup("stringeq"); } | STRINGLENGTH { $$ = strdup("stringlength"); } | SUBSTRING { $$ = strdup("substring"); } | GETVARIABLE { $$ = strdup("getvariable"); } | SETVARIABLE { $$ = strdup("setvariable"); } | SETTARGETEXPRESSION { $$ = strdup("settargetexpression"); } | DUPLICATEMOVIECLIP { $$ = strdup("duplicatemovieclip"); } | REMOVEMOVIECLIP { $$ = strdup("removemovieclip"); } | STARTDRAG { $$ = strdup("startdrag"); } | STOPDRAG { $$ = strdup("stopdrag"); } | STRINGLESSTHAN { $$ = strdup("stringlessthan"); } | MBLENGTH { $$ = strdup("mblength"); } | MBSUBSTRING { $$ = strdup("mbsubstring"); } | MBORD { $$ = strdup("mbord"); } | MBCHR { $$ = strdup("mbchr"); } | BRANCHALWAYS { $$ = strdup("branchalways"); } | BRANCHIFTRUE { $$ = strdup("branchiftrue"); } | GETURL2 { $$ = strdup("getURL2"); } | POST { $$ = strdup("post"); } | GET { $$ = strdup("get"); } | LOADVARIABLES { $$ = strdup("loadvariables"); } | LOADMOVIE { $$ = strdup("loadmovie"); } ;formals_list : /* empty */ { $$.buffer = newBuffer(); $$.count = 0; } | identifier { $$.buffer = newBuffer(); bufferWriteHardString($$.buffer, (byte*)$1, strlen($1)+1); $$.count = 1; } | formals_list ',' identifier { $$ = $1; bufferWriteHardString($$.buffer, (byte*)$3, strlen($3)+1); ++$$.count; } ;function_init : FUNCTION { addctx(CTX_FUNCTION); } ;function_decl : function_init identifier '(' formals_list ')' stmt { $$ = newBuffer(); bufferWriteOp($$, SWFACTION_DEFINEFUNCTION); bufferWriteS16($$, strlen($2) + bufferLength($4.buffer) + 5); bufferWriteHardString($$, (byte*) $2, strlen($2)+1); bufferWriteS16($$, $4.count); bufferConcat($$, $4.buffer); bufferWriteS16($$, bufferLength($6)); bufferConcat($$, $6); delctx(CTX_FUNCTION); } ;obj_ref : identifier { $$ = newBuffer(); bufferWriteString($$, $1, strlen($1)+1); free($1); } | expr '.' identifier { $$ = $1; bufferWriteString($$, $3, strlen($3)+1); bufferWriteOp($$, SWFACTION_GETMEMBER); free($3); } | expr '[' expr ']' { $$ = $1; bufferConcat($$, $3); bufferWriteOp($$, SWFACTION_GETMEMBER); } | function_call | method_call ;while_init : WHILE { addctx(CTX_LOOP); } ;do_init : DO { addctx(CTX_LOOP); } ;for_init : /* empty */ { addctx(CTX_LOOP); } ;for_in_init : /* empty */ { addctx(CTX_FOR_IN); } ;iter_stmt : while_init '(' expr ')' stmt { $$ = $3; bufferWriteOp($$, SWFACTION_LOGICALNOT); bufferWriteOp($$, SWFACTION_BRANCHIFTRUE); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($5)+5); bufferConcat($$, $5); bufferWriteOp($$, SWFACTION_BRANCHALWAYS); bufferWriteS16($$, 2); bufferWriteS16($$, -(bufferLength($$)+2)); bufferResolveJumps($$); delctx(CTX_LOOP); } | do_init stmt WHILE '(' expr ')' { if($2) { $$ = $2; bufferConcat($$, $5); } else $$ = $5; bufferWriteOp($$, SWFACTION_BRANCHIFTRUE); bufferWriteS16($$, 2); bufferWriteS16($$, -(bufferLength($$)+2)); bufferResolveJumps($$); delctx(CTX_LOOP); } | FOR '(' assign_stmts_opt ';' expr_opt ';' assign_stmts_opt ')' for_init stmt { if($3) $$ = $3; else $$ = newBuffer(); if($7) { bufferWriteOp($$, SWFACTION_BRANCHALWAYS); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($7)); } else $7 = newBuffer(); if($5) { bufferConcat($7, $5); bufferWriteOp($7, SWFACTION_LOGICALNOT); bufferWriteOp($7, SWFACTION_BRANCHIFTRUE); bufferWriteS16($7, 2); bufferWriteS16($7, bufferLength($10)+5); } bufferConcat($7, $10); bufferWriteOp($7, SWFACTION_BRANCHALWAYS); bufferWriteS16($7, 2); bufferWriteS16($7, -(bufferLength($7)+2)); bufferResolveJumps($7); bufferConcat($$, $7); delctx(CTX_LOOP); } | FOR '(' identifier IN obj_ref ')' for_in_init stmt { Buffer b2, b3; int tmp; $$ = $5; bufferWriteOp($$, SWFACTION_ENUMERATE); b2 = newBuffer(); bufferWriteSetRegister(b2, 0); bufferWriteOp(b2, SWFACTION_PUSHDATA); bufferWriteS16(b2, 1); bufferWriteU8(b2, 2); bufferWriteOp(b2, SWFACTION_NEWEQUALS); bufferWriteOp(b2, SWFACTION_BRANCHIFTRUE); bufferWriteS16(b2, 2); b3 = newBuffer();/* basically a lvalue could be used here rather than an ident !!! *//* probably by using reg1 for the test rather than reg0 */ bufferWriteString(b3, $3, strlen($3)+1); bufferWriteRegister(b3, 0); bufferWriteOp(b3, SWFACTION_SETVARIABLE); bufferConcat(b3, $8); bufferWriteS16(b2, bufferLength(b3) + 5); tmp = bufferLength(b2) + bufferLength(b3) + 5; bufferConcat($$, b2); bufferWriteOp(b3, SWFACTION_BRANCHALWAYS); bufferWriteS16(b3, 2); bufferWriteS16(b3, -tmp); bufferResolveJumps(b3); bufferConcat($$, b3); delctx(CTX_FOR_IN); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -