📄 swf5compiler.y
字号:
/* $Id: swf5compiler.y,v 1.103 2008/07/20 10:17:21 strk Exp $ */%start program%{#include <time.h>#include <string.h>#include <stdlib.h>#include "compile.h"#include "actiontypes.h"#include "assembler.h"#define YYERROR_VERBOSE 1#define YYPARSE_PARAM buffer//#define DEBUG 1#ifdef _MSC_VER #define strcasecmp stricmp #endifBuffer bf, bc;static int classContext = 0;%}%union{ Buffer action; char *str; SWFGetUrl2Method getURLMethod; int op; int intVal; int len; double doubleVal; ASFunction function; ASClass clazz; ASClassMember classMember; struct exprlist_s exprlist; struct switchcase switchcase; struct switchcases switchcases; struct { Buffer obj, ident, memexpr; } lval;}/* * we expect 53 shift/reduce conflicts * see also: http://www.gnu.org/software/bison/manual/html_mono/bison.html#Shift_002fReduce */%expect 53/* tokens etc. */%token BREAK CONTINUE FUNCTION ELSE SWITCH CASE DEFAULT FOR IN IF WHILE%token DO VAR NEW DELETE TARGETPATH 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 NEWOBJECT NEWMETHOD%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 CAST %token LOADVARIABLES LOADMOVIE LOADVARIABLESNUM LOADMOVIENUM%token CALLFRAME STARTDRAG STOPDRAG GOTOANDSTOP GOTOANDPLAY SETTARGET %token GETPROPERTY SETPROPERTY TONUMBER TOSTRING %token TRY THROW CATCH FINALLY THIS%token EXTENDS IMPLEMENTS FSCOMMAND2 CLASS PUBLIC PRIVATE%token NULLVAL%token UNDEFINED%token <intVal> INTEGER%token <doubleVal> DOUBLE%token <intVal> BOOLEAN%token <str> REGISTER%token BROKENSTRING/* these two are strdup'ed in compiler.flex, so free them up here */%token <str> STRING%token <str> IDENTIFIER%token EQ "=="%token EEQ "==="%token NEE "!=="%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 ">>>="%token _P_X _P_Y _P_XSCALE _P_YSCALE _P_CURRENTFRAME _P_TOTALFRAMES _P_ALPHA%token _P_VISIBLE _P_WIDTH _P_HEIGHT _P_ROTATION _P_TARGET _P_FRAMESLOADED %token _P_NAME _P_DROPTARGET _P_URL _P_HIGHQUALITY _P_FOCUSRECT _P_SOUNDBUFTIME%token _P_QUALITY _P_XMOUSE _P_YMOUSE/* 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> try_catch_stmt throw_stmt%type <action> with_stmt%type <action> switch_stmt%type <action> 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 inpart obj_ref obj_ref_for_delete_only%type <action> emptybraces level init_vars init_var primary lvalue_expr%type <action> delete_call primary_constant%type <classMember> class_stmts class_stmt class_vars class_var class_body %type <lval> lvalue %type <intVal> property%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 function_identifier%type <function> function_decl%type <len> opcode opcode_list push_item with push_list%type <clazz> class_decl/*%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 { if(swfVersion > 6) bufferWriteFunction(bf, $1, 2); else bufferWriteFunction(bf, $1, 1); } | class_decl { bufferWriteClass(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 | try_catch_stmt ';' | throw_stmt ;class_stmts : class_stmt | class_stmts class_stmt { $$ = $1; ASClassMember_append($1, $2); } ;class_stmt : access_attr function_decl { $$ = newASClassMember_function($2); } | access_attr VAR class_vars ';' { $$ = $3; } ;class_init : CLASS { if(classContext) { swf5error("Nested classes are not allowed\n"); YYABORT; } classContext = 1; } ; class_body : emptybraces {$$ = NULL; } | '{' class_stmts '}' { $$ = $2; } ; class_decl : class_init identifier class_body { $$ = newASClass($2, $3); classContext = 0; } ;access_attr : // empty | PUBLIC | PRIVATE ;type_attr : | ':' identifierclass_vars : class_var | class_vars ',' class_var { $$ = $1; ASClassMember_append($1, $3); } ;class_var : identifier type_attr '=' primary_constant { ASVariable v = newASVariable($1, $4); $$ = newASClassMember_variable(v); } | identifier type_attr { ASVariable v = newASVariable($1, NULL); $$ = newASClassMember_variable(v); } ;throw_stmt : THROW expr_or_obj ';' { $$ = $2; bufferWriteOp($$, SWFACTION_THROW); } ;try_catch_stmt : TRY stmt { $$ = newBuffer(); bufferWriteOp($$, SWFACTION_TRY); bufferWriteS16($$, 8); /* TRY tag length */ bufferWriteU8($$, 0); /* flags */ bufferWriteS16($$, bufferLength($2)); /* try block length */ bufferWriteS16($$, 0); /* catch block length */ bufferWriteS16($$, 0); /* finally block length */ bufferWriteU8($$, 0); /* catch name - empty string */ bufferConcat($$, $2); /* append TRY body */ } | TRY stmt CATCH '(' identifier ')' stmt { $$ = newBuffer(); bufferWriteOp($$, SWFACTION_TRY); bufferWriteS16($$, 8+strlen($5)); /* TRY tag length */ bufferWriteU8($$, 1); /* flags */ bufferWriteS16($$, bufferLength($2)+5); /* try block length + JUMP length */ bufferWriteS16($$, bufferLength($7)); /* catch block length */ bufferWriteS16($$, 0); /* finally block length */ bufferWriteHardString($$, $5, strlen($5)+1); /* catch name */ bufferConcat($$, $2); /* append TRY body */ bufferWriteOp($$, SWFACTION_JUMP); /* jump after catch */ bufferWriteS16($$, 2); /* ... */ bufferWriteS16($$, bufferLength($7)); /* ... */ bufferConcat($$, $7); /* append CATCH body */ } | TRY stmt FINALLY stmt { $$ = newBuffer(); bufferWriteOp($$, SWFACTION_TRY); bufferWriteS16($$, 8); /* TRY tag length */ bufferWriteU8($$, 2); /* flags */ bufferWriteS16($$, bufferLength($2)); /* try block length */ bufferWriteS16($$, 0); /* catch block length */ bufferWriteS16($$, bufferLength($4)); /* finally block length */ bufferWriteU8($$, 0); /* catch name - empty string */ bufferConcat($$, $2); /* append TRY body */ bufferConcat($$, $4); /* append FINALLY body */ } | TRY stmt CATCH '(' identifier ')' stmt FINALLY stmt { $$ = newBuffer(); bufferWriteOp($$, SWFACTION_TRY); bufferWriteS16($$, 8+strlen($5)); /* TRY tag length */ bufferWriteU8($$, 3); /* flags */ bufferWriteS16($$, bufferLength($2)+5); /* try block length + JUMP length */ bufferWriteS16($$, bufferLength($7)); /* catch block length */ bufferWriteS16($$, bufferLength($9)); /* finally block length */ bufferWriteHardString($$, $5, strlen($5)+1); /* catch name */ bufferConcat($$, $2); /* append TRY body */ bufferWriteOp($$, SWFACTION_JUMP); /* jump after catch */ bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($7)); bufferConcat($$, $7); /* append CATCH body */ bufferConcat($$, $9); /* append FINALLY body */ } ;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"); YYABORT; } $$ = newBuffer(); while(--tmp >= 0) bufferWriteOp($$, SWFACTION_POP); bufferWriteUndef($$); bufferWriteOp($$, SWFACTION_RETURN); } | RETURN expr_or_obj ';' { int tmp = chkctx(CTX_FUNCTION); if(tmp < 0) { swf5error("return outside function"); YYABORT; } $$ = 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_IF); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($7)+5); bufferConcatSimple($$, $7); bufferWriteOp($$, SWFACTION_JUMP); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($5)); bufferConcatSimple($$, $5); } | IF '(' expr ')' stmt %prec NOELSE { $$ = $3; bufferWriteOp($$, SWFACTION_LOGICALNOT); bufferWriteOp($$, SWFACTION_IF); bufferWriteS16($$, 2); bufferWriteS16($$, bufferLength($5)); bufferConcatSimple($$, $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 { $$.cond = $2; $$.action = $4; if(chkctx(CTX_BREAK) == CTX_BREAK) { delctx(CTX_BREAK); $$.isbreak = 1; } else $$.isbreak = 0; } | DEFAULT ':' stmts { $$.cond = NULL; $$.action = $3; if(chkctx(CTX_BREAK) == CTX_BREAK) { delctx(CTX_BREAK); $$.isbreak = 1; } else $$.isbreak = 0; } ;/* there's GOT to be a better way than this.. *//* What is this for exactly ? */identifier : IDENTIFIER | TARGETPATH { $$ = strdup("targetPath"); } | 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"); } | ENUMERATE { $$ = strdup("enumerate"); } | INITOBJECT { $$ = strdup("initobject"); } | INITARRAY { $$ = strdup("initarray"); } | GETMEMBER { $$ = strdup("getmember"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -