X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Fparser.y;h=6055295d6be40445a7cc886e3514c31b99df386b;hb=cb219dabe7e390834eb9c09a3e1f02ce28550847;hp=c104f550e41aff6e20a589700e29d21ef5307eaa;hpb=499c73edd0924ce0d7ddbdc0c6af6a5536457021;p=swftools.git diff --git a/lib/as3/parser.y b/lib/as3/parser.y index c104f55..6055295 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -1,54 +1,3 @@ -//%glr-parser -//%expect-rr 1 -%error-verbose - -%token T_IDENTIFIER -%token T_STRING -%token T_REGEXP -%token T_DOTDOT ".." -%token T_COLONCOLON "::" -%token T_GE ">=" -%token T_LE "<=" -%token T_EQEQ "==" -%token T_PLUSPLUS "++" -%token T_MINUSMINUS "--" -%token T_IMPLEMENTS -%token T_NAMESPACE -%token T_PACKAGE -%token T_PROTECTED -%token T_PUBLIC -%token T_PRIVATE -%token T_UINT -%token T_USE -%token T_INTERNAL -%token T_INT -%token T_NEW -%token T_NATIVE -%token T_FUNCTION -%token T_FOR -%token T_CLASS -%token T_CONST -%token T_SET -%token T_STATIC -%token T_IMPORT -%token T_INTERFACE -%token T_NUMBER -%token T_NULL -%token T_FALSE -%token T_TRUE -%token T_BOOLEAN -%token T_VAR -%token T_AS -%token T_IS -%token T_DYNAMIC -%token T_OVERRIDE -%token T_FINAL -%token T_GET -%token T_EXTENDS - - -%token T_EMPTY - %{ #include #include @@ -58,6 +7,172 @@ #include "files.h" #include "tokenizer.h" #include "registry.h" +#include "code.h" +#include "opcodes.h" +%} + +//%glr-parser +//%expect-rr 1 +%error-verbose + +%union tokenunion { + tokenptr_t token; + multiname_t*multiname; + multiname_list_t*multiname_list; + int number_int; + unsigned int number_uint; + double number_float; + struct _code*code; + struct _code_list*code_list; +} + + +%token T_IDENTIFIER +%token T_STRING +%token T_REGEXP +%token T_EMPTY +%token T_INT +%token T_UINT +%token T_BYTE +%token T_SHORT +%token T_FLOAT + +%token KW_IMPLEMENTS +%token KW_NAMESPACE +%token KW_PACKAGE "package" +%token KW_PROTECTED +%token KW_PUBLIC +%token KW_PRIVATE +%token KW_USE "use" +%token KW_INTERNAL +%token KW_NEW "new" +%token KW_NATIVE +%token KW_FUNCTION "function" +%token KW_FOR "for" +%token KW_CLASS "class" +%token KW_CONST "const" +%token KW_SET "set" +%token KW_STATIC +%token KW_IMPORT "import" +%token KW_INTERFACE "interface" +%token KW_NULL +%token KW_VAR "var" +%token KW_DYNAMIC +%token KW_OVERRIDE +%token KW_FINAL +%token KW_GET "get" +%token KW_EXTENDS +%token KW_FALSE "False" +%token KW_TRUE "True" +%token KW_BOOLEAN "Boolean" +%token KW_UINT "uint" +%token KW_INT "int" +%token KW_NUMBER "Number" +%token KW_STRING "String" +%token KW_IS "is" +%token KW_AS "as" + +%token T_EQEQ "==" +%token T_LE "<=" +%token T_GE ">=" +%token T_DIVBY "/=" +%token T_MODBY "%=" +%token T_PLUSBY "+=" +%token T_MINUSBY "-=" +%token T_SHRBY ">>=" +%token T_SHLBY "<<=" +%token T_USHRBY ">>>=" +%token T_OROR "||" +%token T_ANDAND "&&" +%token T_COLONCOLON "::" +%token T_MINUSMINUS "--" +%token T_PLUSPLUS "++" +%token T_DOTDOT ".." +%token T_SHL "<<" +%token T_USHR ">>>" +%token T_SHR ">>" +%token T_SEMICOLON ';' +%token T_STAR '*' +%token T_DOT '.' + +%type CODE +%type CODEPIECE CODEPIECE2 +%type PACKAGE_DECLARATION +%type FUNCTION_DECLARATION +%type VARIABLE_DECLARATION +%type CLASS_DECLARATION +%type NAMESPACE_DECLARATION +%type INTERFACE_DECLARATION +%type EXPRESSION +%type MAYBEEXPRESSION +%type E +%type CONSTANT +%type FOR +%type USE +%type ASSIGNMENT +%type IMPORT +%type MAYBETYPE +%type PACKAGESPEC +%type GETSET +%type PARAM +%type PARAMS +%type PARAM_LIST +%type MODIFIERS +%type MODIFIER_LIST +%type IMPLEMENTS_LIST +%type EXTENDS +%type EXTENDS_LIST +%type PACKAGEANDCLASS +%type PACKAGEANDCLASS_LIST +%type MULTILEVELIDENTIFIER +%type TYPE +%type VAR +%type VARIABLE +%type VAR_READ +%type NEW +%type X_IDENTIFIER +%type MODIFIER +%type PACKAGE +%type FUNCTIONCALL +%type MAYBE_EXPRESSION_LIST EXPRESSION_LIST + +// precendence: from low to high +// http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000012.html + +%left prec_none +%right '?' ':' +%nonassoc '=' +%nonassoc "/=" "%=" +%nonassoc "+=" "-=" +%nonassoc ">>=" +%nonassoc "<<=" +%nonassoc ">>>=" +%nonassoc "||" +%nonassoc "&&" +%nonassoc '|' +%nonassoc '^' +%nonassoc '&' +%nonassoc "!=" "==" "<=" '<' ">=" '>' // TODO: support "a < b < c" syntax? +%nonassoc "is" +%left '-' +%left '+' +%left "<<" +%left ">>>" +%left ">>" +%left '%' +%left '/' +%left '*' +%left '!' +%left '~' +%left "--" "++" +%left '[' +%nonassoc "as" +%left '.' ".." "::" +%nonassoc T_IDENTIFIER +%left '(' + + +%{ static int yyerror(char*s) { @@ -87,6 +202,18 @@ static token_t* concat3(token_t* t1, token_t* t2, token_t* t3) t->text[l1+l2+l3] = 0; return t; } +static char* concat3str(const char* t1, const char* t2, const char* t3) +{ + int l1 = strlen(t1); + int l2 = strlen(t2); + int l3 = strlen(t3); + char*text = malloc(l1+l2+l3+1); + memcpy(text , t1, l1); + memcpy(text+l1, t2, l2); + memcpy(text+l1+l2, t3, l3); + text[l1+l2+l3] = 0; + return text; +} typedef struct _import { char*path; @@ -102,12 +229,15 @@ typedef struct _state { char*package; char*function; + abc_method_body_t*m; import_list_t*imports; /* class data */ char*classname; abc_class_t*cls; + array_t*vars; + } state_t; static state_t* state = 0; @@ -116,7 +246,7 @@ DECLARE_LIST(state); static state_list_t*state_stack=0; -static void initialize_state() +void initialize_state() { NEW(state_t, s); NEW(state_list_t, sl); @@ -124,27 +254,41 @@ static void initialize_state() state = sl->state = s; state->file = abc_file_new(); + state->file->flags &= ~ABCFILE_LAZY; state->level = 0; state->init = abc_initscript(state->file, 0, 0); abc_method_body_t*m = state->init->method->body; __ getlocal_0(m); __ pushscope(m); + __ findpropstrict(m, "[package]::trace"); + __ pushstring(m, "[entering global init function]"); + __ callpropvoid(m, "[package]::trace", 1); } -static void finalize_state() +void* finalize_state() { if(state->level) { syntaxerror("unexpected end of file"); } abc_method_body_t*m = state->init->method->body; //__ popscope(m); + + __ findpropstrict(m, "[package]::trace"); + __ pushstring(m, "[leaving global init function]"); + __ callpropvoid(m, "[package]::trace", 1); __ returnvoid(m); + return state->file; } static void new_state() { NEW(state_t, s); NEW(state_list_t, sl); + + if(state->m) { + syntaxerror("not able to start another method scope"); + } + memcpy(s, state, sizeof(state_t)); //shallow copy sl->next = state_stack; sl->state = s; @@ -179,28 +323,35 @@ static void endpackage() old_state(); } -static void startclass(token_t*modifiers, token_t*name, token_t*extends, token_t*implements) +char*globalclass=0; +static void startclass(token_t*modifiers, token_t*name, multiname_t*extends, multiname_list_t*implements) { - token_list_t*t; if(state->cls) { syntaxerror("inner classes now allowed"); } new_state(); state->classname = name->text; printf("entering class %s\n", name->text); + token_list_t*t=0; printf(" modifiers: ");for(t=modifiers->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n"); - printf(" extends: %s\n", extends->text); - printf(" implements (%d): ", list_length(implements->tokens));for(t=implements->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n"); + printf(" extends: %s\n", multiname_tostring(extends)); + + multiname_list_t*mlist=0; + printf(" implements (%d): ", list_length(implements)); + for(mlist=implements;mlist;mlist=mlist->next) { + printf("%s ", multiname_tostring(mlist->multiname)); + } + printf("\n"); char public=0,internal=0,final=0,sealed=1; for(t=modifiers->tokens;t;t=t->next) { - if(t->token->type == T_INTERNAL) { + if(t->token->type == KW_INTERNAL) { /* the programmer is being explicit- being internal is the default anyway */ internal = 1; - } else if(t->token->type == T_PUBLIC) { + } else if(t->token->type == KW_PUBLIC) { public = 1; - } else if(t->token->type == T_FINAL) { + } else if(t->token->type == KW_FINAL) { final = 1; } else { syntaxerror("modifier \"%s\" not supported in class declaration", t->token->text); @@ -220,20 +371,12 @@ static void startclass(token_t*modifiers, token_t*name, token_t*extends, token_t else syntaxerror("public classes only allowed inside a package"); - /* try to find the superclass */ - multiname_t* superclass = 0; - if(extends->type != T_EMPTY) { - superclass = registry_findclass(extends->text); - } else { - superclass = registry_getobjectclass(); - } - - state->cls = abc_class_new(state->file, classname, superclass); + state->cls = abc_class_new(state->file, classname, extends); if(final) abc_class_final(state->cls); if(sealed) abc_class_sealed(state->cls); - for(t=implements->tokens;t;t=t->next) { - abc_class_add_interface(state->cls, registry_findclass(t->token->text)); + for(mlist=implements;mlist;mlist=mlist->next) { + abc_class_add_interface(state->cls, mlist->multiname); } /* now write the construction code for this class */ @@ -241,27 +384,43 @@ static void startclass(token_t*modifiers, token_t*name, token_t*extends, token_t abc_method_body_t*m = state->init->method->body; __ getglobalscope(m); - multiname_t*s = superclass; + multiname_t*s = extends; + int count=0; + while(s) { - //TODO: invert //TODO: take a look at the current scope stack, maybe // we can re-use something + s = registry_getsuperclass(s); + if(!s) + break; __ getlex2(m, s); __ pushscope(m); - s = registry_getsuperclass(s); + m->code = m->code->prev->prev; // invert count++; } + /* continue appending after last op end */ + while(m->code && m->code->next) m->code = m->code->next; + /* TODO: if this is one of *our* classes, we can also do a getglobalscope/getslot (which references the init function's slots) */ - __ getlex2(m, superclass); + __ getlex2(m, extends); + __ dup(m); + __ pushscope(m); // we get a Verify Error #1107 if this is not the top scope __ newclass(m,state->cls); - while(count--) { __ popscope(m); } __ setslot(m, slotindex); + + if(!globalclass && public && multiname_equals(registry_getMovieClip(),extends)) { + if(state->package && state->package[0]) { + globalclass = concat3str(state->package, ".", state->classname); + } else { + globalclass = strdup(state->classname); + } + } } static void endclass() @@ -284,7 +443,7 @@ static void print_imports() } } static void startfunction(token_t*ns, token_t*mod, token_t*getset, token_t*name, - token_t*params, token_t*type) + token_t*params, multiname_t*type) { token_list_t*t; new_state(); @@ -295,21 +454,45 @@ static void startfunction(token_t*ns, token_t*mod, token_t*getset, token_t*name, printf(" getset: %s\n", getset->text); printf(" params: ");for(t=params->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n"); printf(" mod: ");for(t=mod->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n"); - printf(" type: %s\n", type->text); + printf(" type: %s\n", multiname_tostring(type)); print_imports(); + + if(!strcmp(state->classname,name->text)) { + state->m = abc_class_constructor(state->cls, type, 0); + } else { + state->m = abc_class_method(state->cls, type, name->text, 0); + } + state->vars = array_new(); + array_append(state->vars, "this", 0); + + __ getlocal_0(state->m); + __ pushscope(state->m); } static void endfunction() { printf("leaving function %s\n", state->function); + __ returnvoid(state->m); + old_state(); } -static int newvariable(token_t*mod, token_t*varconst, token_t*name, token_t*type) +static int newvariable(token_t*mod, token_t*varconst, token_t*name, multiname_t*type) { token_list_t*t; printf("defining new variable %s\n", name->text); printf(" mod: ");for(t=mod->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n"); printf(" access: ");printf("%s\n", varconst->text); - printf(" type: ");printf("%s\n", type->text); + printf(" type: ");printf("%s\n", multiname_tostring(type)); + + if(!state->vars) + syntaxerror("not allowed to defined variables outside a method"); + + int index = array_find(state->vars, name->text); + if(index>=0) { + syntaxerror("Variable %s already defined", name->text); + } else { + index = array_append(state->vars, name->text, 0); + } + return index; } static token_t* empty_token() { @@ -340,122 +523,143 @@ void extend_s(token_t*list, char*seperator, token_t*add) { } %} -%% -PROGRAM: CODE PROGRAM -PROGRAM: - -//EMPTY: { -// token_t* t = malloc(sizeof(token_t)); -// t->text = strdup(""); -// t->type = T_EMPTY; -// $$ = t; -//} +%% -CODE: CODE CODEPIECE {$$=$1;} -CODE: CODEPIECE {$$=empty_token();} +PROGRAM: MAYBECODE MAYBECODE: CODE MAYBECODE: -CODEPIECE: ';' -CODEPIECE: VARIABLE_DECLARATION {$$=$1;} -CODEPIECE: PACKAGE_DECLARATION -CODEPIECE: IMPORT -CODEPIECE: NAMESPACE_DECLARATION -CODEPIECE: CLASS_DECLARATION -CODEPIECE: INTERFACE_DECLARATION -CODEPIECE: FUNCTION_DECLARATION -CODEPIECE: EXPRESSION -CODEPIECE: FOR -CODEPIECE: USE -CODEPIECE: ASSIGNMENT - -PACKAGE_DECLARATION : T_PACKAGE MULTILEVELIDENTIFIER '{' {startpackage($2)} MAYBECODE '}' {endpackage()} -PACKAGE_DECLARATION : T_PACKAGE '{' {startpackage(0)} MAYBECODE '}' {endpackage()} - -IMPORT : T_IMPORT PACKAGESPEC {addimport($2);} - -TYPE : BUILTIN_TYPE | '*' | T_IDENTIFIER -// TODO: do we need this? all it does it is clutter up our keyword space -BUILTIN_TYPE : T_STRING -BUILTIN_TYPE : T_NUMBER -BUILTIN_TYPE : T_INT -BUILTIN_TYPE : T_UINT -BUILTIN_TYPE : T_BOOLEAN -BUILTIN_TYPE : T_NULL +CODE: CODE CODEPIECE2 {$$=$1;} +CODE: CODEPIECE2 {$$=empty_token();} + +CODEPIECE2: CODEPIECE { + if(state->m) { + state->m->code = code_append(state->m->code, $1); + } +} + +CODEPIECE: ';' {/*TODO*/$$=code_new();} +CODEPIECE: VARIABLE_DECLARATION {$$=$1} +CODEPIECE: PACKAGE_DECLARATION {/*TODO*/$$=code_new();} +CODEPIECE: IMPORT {/*TODO*/$$=code_new();} +CODEPIECE: NAMESPACE_DECLARATION {/*TODO*/$$=code_new();} +CODEPIECE: CLASS_DECLARATION {/*TODO*/$$=code_new();} +CODEPIECE: INTERFACE_DECLARATION {/*TODO*/$$=code_new();} +CODEPIECE: FUNCTION_DECLARATION {/*TODO*/$$=code_new();} +CODEPIECE: EXPRESSION {/*calculate and discard*/$$=$1;$$=abc_pop($$);} +CODEPIECE: FOR {/*TODO*/$$=code_new();} +CODEPIECE: USE {/*TODO*/$$=code_new();} +CODEPIECE: ASSIGNMENT {/*TODO*/$$=code_new();} + +PACKAGE_DECLARATION : "package" MULTILEVELIDENTIFIER '{' {startpackage($2)} MAYBECODE '}' {endpackage()} +PACKAGE_DECLARATION : "package" '{' {startpackage(0)} MAYBECODE '}' {endpackage()} + +IMPORT : "import" PACKAGESPEC {addimport($2);} + +TYPE : PACKAGEANDCLASS {$$=$1;} + | '*' {$$=registry_getanytype();} + | "String" {$$=registry_getstringclass();} + | "int" {$$=registry_getintclass();} + | "uint" {$$=registry_getuintclass();} + | "Boolean" {$$=registry_getbooleanclass();} + | "Number" {$$=registry_getnumberclass();} MAYBETYPE: ':' TYPE {$$=$2;} -MAYBETYPE: {$$=empty_token();} +MAYBETYPE: {$$=0;} //FUNCTION_HEADER: NAMESPACE MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')' -FUNCTION_HEADER: MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')' +FUNCTION_HEADER: MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')' MAYBETYPE -FUNCTION_DECLARATION: MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')' +FUNCTION_DECLARATION: MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')' MAYBETYPE '{' {startfunction(0,$1,$3,$4,$6,$8)} MAYBECODE '}' {endfunction()} -NAMESPACE_DECLARATION : MODIFIERS T_NAMESPACE T_IDENTIFIER -NAMESPACE_DECLARATION : MODIFIERS T_NAMESPACE T_IDENTIFIER '=' T_IDENTIFIER -NAMESPACE_DECLARATION : MODIFIERS T_NAMESPACE T_IDENTIFIER '=' T_STRING +NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER +NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER '=' T_IDENTIFIER +NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER '=' T_STRING //NAMESPACE : {$$=empty_token();} //NAMESPACE : T_IDENTIFIER {$$=$1}; -CONSTANT : T_NUMBER -CONSTANT : T_STRING -CONSTANT : T_TRUE | T_FALSE -CONSTANT : T_NULL +CONSTANT : T_BYTE {$$ = abc_pushbyte(0, $1);} +CONSTANT : T_SHORT {$$ = abc_pushshort(0, $1);} +CONSTANT : T_INT {$$ = abc_pushint(0, $1);} +CONSTANT : T_UINT {$$ = abc_pushuint(0, $1);} +CONSTANT : T_FLOAT {$$ = abc_pushdouble(0, $1);} +CONSTANT : T_STRING {$$ = abc_pushstring(0, $1->text);} +CONSTANT : KW_TRUE {$$ = abc_pushtrue(0);} +CONSTANT : KW_FALSE {$$ = abc_pushfalse(0);} +CONSTANT : KW_NULL {$$ = abc_pushnull(0);} -VAR : T_CONST | T_VAR +VAR : "const" | "var" // type annotation // TODO: NAMESPACE -VARIABLE_DECLARATION : MODIFIERS VAR T_IDENTIFIER MAYBETYPE { +VARIABLE_DECLARATION : MODIFIERS VAR T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION { int i = newvariable($1,$2,$3,$4); + $$=code_new(); + $$ = $5; + $$ = abc_setlocal($$, i); } -VARIABLE_DECLARATION : MODIFIERS VAR T_IDENTIFIER MAYBETYPE '=' EXPRESSION { - int i = newvariable($1,$2,$3,$4); - //setvariable(i,$6); + +MAYBEEXPRESSION : '=' EXPRESSION {$$=$2;} + | {$$=code_new();} + +EXPRESSION : E %prec prec_none /*precendence below '-x'*/ {$$ = $1;} + +E : CONSTANT +E : VAR_READ %prec T_IDENTIFIER {$$ = $1;} +E : NEW {$$ = abc_pushundefined(0); /* FIXME */} +E : T_REGEXP {$$ = abc_pushundefined(0); /* FIXME */} +E : FUNCTIONCALL +E : E '<' E +E : E '>' E +E : E "<=" E +E : E ">=" E +E : E "==" E +E : E '+' E +E : E '-' E +E : E '/' E +E : E '%' E +E : E '*' E +E : E "++" +E : E "--" +E : E "as" TYPE +E : E "is" TYPE +E : '(' E ')' {$$=$2;} +E : '-' E {$$=$2;} + +NEW : "new" T_IDENTIFIER + | "new" T_IDENTIFIER '(' ')' + | "new" T_IDENTIFIER '(' EXPRESSION_LIST ')' + +FUNCTIONCALL : T_IDENTIFIER '(' MAYBE_EXPRESSION_LIST ')' { + /* TODO: use abc_call (for calling local variables), + abc_callstatic (for calling own methods) */ + $$ = code_new(); + $$ = abc_findproperty($$, $1->text); + code_list_t*l = $3; + // push parameters on stack + while(l) { + $$ = code_append($$, l->code); + l = l->next; + } + $$ = abc_callproperty($$, $1->text, list_length($3)); } -// operator prescendence: -// http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000012.html -EXPRESSION : EXPRESSION '<' EXPRESSION -EXPRESSION : EXPRESSION '>' EXPRESSION -EXPRESSION : EXPRESSION "<=" EXPRESSION -EXPRESSION : EXPRESSION ">=" EXPRESSION -EXPRESSION : EXPRESSION "==" EXPRESSION -EXPRESSION : EXPRESSION '+' TERM -EXPRESSION : EXPRESSION '-' TERM -EXPRESSION : TERM -EXPRESSION : '-' TERM -TERM : TERM '*' FACTOR -TERM : TERM '/' FACTOR -TERM : EMOD -EMOD: FACTOR "++" -EMOD: FACTOR "--" -EMOD: FACTOR -FACTOR : '(' EXPRESSION ')' -FACTOR : CONSTANT -FACTOR : VARIABLE -FACTOR : FUNCTIONCALL -FACTOR : T_REGEXP -FACTOR : NEW -FACTOR : IS -FACTOR : AS - -IS : EXPRESSION T_IS TYPE -AS : EXPRESSION T_AS TYPE -NEW : T_NEW T_IDENTIFIER | T_NEW T_IDENTIFIER '(' ')' -NEW : T_NEW T_IDENTIFIER '(' EXPRESSIONLIST ')' - -FUNCTIONCALL : VARIABLE '(' EXPRESSIONLIST ')' -FUNCTIONCALL : VARIABLE '(' ')' - -EXPRESSIONLIST : EXPRESSION -EXPRESSIONLIST : EXPRESSION ',' EXPRESSIONLIST +MAYBE_EXPRESSION_LIST : {} +MAYBE_EXPRESSION_LIST : EXPRESSION_LIST +EXPRESSION_LIST : EXPRESSION {$$=list_new();list_append($$,$1);} +EXPRESSION_LIST : EXPRESSION_LIST ',' EXPRESSION {list_append($$,$3);} +VAR_READ : T_IDENTIFIER { + int i = array_find(state->vars, $1->text); + if(i<0) + syntaxerror("unknown variable"); + $$ = abc_getlocal(0, i); +} VARIABLE : T_IDENTIFIER VARIABLE : VARIABLE '.' T_IDENTIFIER VARIABLE : VARIABLE ".." T_IDENTIFIER // descendants @@ -464,27 +668,27 @@ VARIABLE : VARIABLE "::" '[' EXPRESSION ']' // qualified expression VARIABLE : VARIABLE '[' EXPRESSION ']' // unqualified expression ASSIGNMENT : VARIABLE '=' EXPRESSION -NEW_ASSIGNMENT : T_VAR VARIABLE MAYBETYPE '=' EXPRESSION +NEW_ASSIGNMENT : "var" VARIABLE MAYBETYPE '=' EXPRESSION -FOR : T_FOR '(' NEW_ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}' -FOR : T_FOR '(' ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}' +FOR : "for" '(' NEW_ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}' +FOR : "for" '(' ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}' -USE : T_USE T_NAMESPACE T_IDENTIFIER +USE : "use" KW_NAMESPACE T_IDENTIFIER // keywords which also may be identifiers -X_IDENTIFIER : T_IDENTIFIER | T_PACKAGE +X_IDENTIFIER : T_IDENTIFIER | KW_PACKAGE PACKAGESPEC : PACKAGESPEC '.' PACKAGESPEC {if($1->text[0]=='*') syntaxerror("wildcard in the middle of path"); $$ = concat3($1,$2,$3);} PACKAGESPEC : X_IDENTIFIER {$$=$1;} PACKAGESPEC : '*' {$$=$1;} -GETSET : T_GET {$$=$1;} - | T_SET {$$=$1;} +GETSET : "get" {$$=$1;} + | "set" {$$=$1;} | {$$=empty_token();} -CLASS_DECLARATION : MODIFIERS T_CLASS T_IDENTIFIER EXTENDS IMPLEMENTS_LIST '{' {startclass($1,$3,$4,$5);} MAYBE_DECLARATION_LIST '}' {endclass();} -INTERFACE_DECLARATION : MODIFIERS T_INTERFACE T_IDENTIFIER EXTENDS_LIST '{' MAYBE_IDECLARATION_LIST '}' +CLASS_DECLARATION : MODIFIERS "class" T_IDENTIFIER EXTENDS IMPLEMENTS_LIST '{' {startclass($1,$3,$4,$5);} MAYBE_DECLARATION_LIST '}' {endclass();} +INTERFACE_DECLARATION : MODIFIERS "interface" T_IDENTIFIER EXTENDS_LIST '{' MAYBE_IDECLARATION_LIST '}' PARAMS: {$$=empty_token();} PARAMS: PARAM_LIST {$$=$1;} @@ -496,7 +700,7 @@ MODIFIERS : {$$=empty_token();} MODIFIERS : MODIFIER_LIST {$$=$1} MODIFIER_LIST : MODIFIER MODIFIER_LIST {extend($2,$1);$$=$2;} MODIFIER_LIST : MODIFIER {$$=empty_token();extend($$,$1);} -MODIFIER : T_PUBLIC | T_PRIVATE | T_PROTECTED | T_STATIC | T_DYNAMIC | T_FINAL | T_OVERRIDE | T_NATIVE | T_INTERNAL +MODIFIER : KW_PUBLIC | KW_PRIVATE | KW_PROTECTED | KW_STATIC | KW_DYNAMIC | KW_FINAL | KW_OVERRIDE | KW_NATIVE | KW_INTERNAL DECLARATION : VARIABLE_DECLARATION DECLARATION : FUNCTION_DECLARATION @@ -504,23 +708,28 @@ DECLARATION : FUNCTION_DECLARATION IDECLARATION : VARIABLE_DECLARATION IDECLARATION : FUNCTION_DECLARATION -IMPLEMENTS_LIST : {$$=empty_token();} -IMPLEMENTS_LIST : T_IMPLEMENTS MIDENTIFIER_LIST {$$=$2;} +IMPLEMENTS_LIST : {$$=list_new();} +IMPLEMENTS_LIST : KW_IMPLEMENTS PACKAGEANDCLASS_LIST {$$=$2;} -EXTENDS : {$$=empty_token();} -EXTENDS : T_EXTENDS MULTILEVELIDENTIFIER {$$=$2;} +EXTENDS : {$$=registry_getobjectclass();} +EXTENDS : KW_EXTENDS PACKAGEANDCLASS {$$=$2;} -EXTENDS_LIST : {$$=empty_token();} -EXTENDS_LIST : T_EXTENDS MIDENTIFIER_LIST {$$=$2;} +EXTENDS_LIST : {$$=list_new();} +EXTENDS_LIST : KW_EXTENDS PACKAGEANDCLASS_LIST {$$=$2;} //IDENTIFIER_LIST : T_IDENTIFIER ',' IDENTIFIER_LIST {extend($3,$1);$$=$3;} //IDENTIFIER_LIST : T_IDENTIFIER {$$=empty_token();extend($$,$1);} -MULTILEVELIDENTIFIER : T_IDENTIFIER {$$=empty_token();extend($$,$1);} -MULTILEVELIDENTIFIER : MULTILEVELIDENTIFIER '.' X_IDENTIFIER {extend_s($1,".",$3);$$=$1;} +PACKAGEANDCLASS : T_IDENTIFIER {$$ = registry_findclass(state->package, $1->text);} +PACKAGEANDCLASS : PACKAGE '.' T_IDENTIFIER {$$ = registry_findclass($1->text, $3->text);} +PACKAGE : X_IDENTIFIER +PACKAGE : PACKAGE '.' X_IDENTIFIER {$$=$1;extend_s($$,".",$3);} -MIDENTIFIER_LIST : MULTILEVELIDENTIFIER {$$=empty_token();extend($$,$1);} -MIDENTIFIER_LIST : MIDENTIFIER_LIST ',' MULTILEVELIDENTIFIER {extend($1,$3);$$=$1;} +MULTILEVELIDENTIFIER : MULTILEVELIDENTIFIER '.' X_IDENTIFIER {$$=$1;extend_s($$, ".", $3)} +MULTILEVELIDENTIFIER : T_IDENTIFIER {$$=$1;extend($$,$1)}; + +PACKAGEANDCLASS_LIST : PACKAGEANDCLASS {$$=list_new();list_append($$, $1);} +PACKAGEANDCLASS_LIST : PACKAGEANDCLASS_LIST ',' PACKAGEANDCLASS {$$=$1;list_append($$,$3);} MAYBE_DECLARATION_LIST : MAYBE_DECLARATION_LIST : DECLARATION_LIST @@ -532,76 +741,7 @@ MAYBE_IDECLARATION_LIST : IDECLARATION_LIST IDECLARATION_LIST : IDECLARATION IDECLARATION_LIST : IDECLARATION_LIST FUNCTION_HEADER +// chapter 14 // keywords: as break case catch class const continue default delete do else extends false finally for function if implements import in instanceof interface internal is native new null package private protected public return super switch this throw to true try typeof use var void while with // syntactic keywords: each get set namespace include dynamic final native override static -// chapter 14 - - -%% - -#ifdef MAIN - -#include -#include -#include -#include -void test_lexer() -{ - while(1) { - int token = yylex(); - if(token==T_EOF) - break; - if(token>=32 && token<256) { - printf("'%c'\n", token); - } else { - printf("%s\n", token2string(avm2_lval)); - } - } -} - -int main(int argn, char*argv[]) -{ - //FILE*fi = fopen("/home/kramm/c/flex/text.as", "rb"); - char*filename = "include.as"; - char buf[512]; - if(argn>1) - filename=argv[1]; - - add_include_dir(getcwd(buf, 512)); - char*fullfilename = enter_file(filename, 0); - - FILE*fi = fopen(fullfilename, "rb"); - if(!fi) { - perror(fullfilename); - return 1; - } - initialize_state(); - avm2_set_in(fi); - - if(argn>2 && !strcmp(argv[2], "-lex")) { - test_lexer(); - return 0; - } - avm2_parse(); - - finalize_state(); - - SWF swf; - memset(&swf, 0, sizeof(swf)); - swf.fileVersion = 9; - swf.frameRate = 0x2500; - swf.movieSize.xmin = swf.movieSize.ymin = 0; - swf.movieSize.xmax = 1024*20; - swf.movieSize.ymax = 768*20; - TAG*tag = swf.firstTag = swf_InsertTag(0, ST_DOABC); - swf_WriteABC(tag, state->file); - swf_InsertTag(tag, ST_END); - - int f = open("abc.swf",O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0644); - swf_WriteSWF(f,&swf); - close(f); - - return 0; -} -#endif