added typeof, void expressions
[swftools.git] / lib / as3 / parser.y
index 319bd80..7415c96 100644 (file)
 %token<token> KW_NEW "new"
 %token<token> KW_NATIVE
 %token<token> KW_FUNCTION "function"
+%token<token> KW_UNDEFINED "undefined"
 %token<token> KW_FOR "for"
 %token<token> KW_CLASS "class"
 %token<token> KW_CONST "const"
 %token<token> KW_SET "set"
+%token<token> KW_VOID "void"
 %token<token> KW_STATIC
 %token<token> KW_IMPORT "import"
 %token<token> KW_RETURN "return"
+%token<token> KW_TYPEOF "typeof"
 %token<token> KW_INTERFACE "interface"
 %token<token> KW_NULL "null"
 %token<token> KW_VAR "var"
 %token<token> T_EQEQ "=="
 %token<token> T_EQEQEQ "==="
 %token<token> T_NE "!="
+%token<token> T_NEE "!=="
 %token<token> T_LE "<="
 %token<token> T_GE ">="
 %token<token> T_DIVBY "/=" 
 %left below_semicolon
 %left ';'
 %left ','
+%nonassoc below_assignment // for ?:, contrary to spec
 %right '=' "*=" "/=" "%=" "+=" "-=" "<<=" ">>=" ">>>=" "&=" "^=" "|="
 %right '?' ':'
 %left "||"
 %nonassoc '^'
 %nonassoc '&'
 %nonassoc "==" "!=" "===" "!=="
+%nonassoc "is" "as"
 %nonassoc "<=" '<' ">=" '>' "instanceof" // TODO: support "a < b < c" syntax?
 %left "<<" ">>" ">>>" 
 %left below_minus
 %left '-' '+'
 %left '/' '*' '%'
-%left plusplus_prefix minusminus_prefix '~' '!' "delete" "typeof" //FIXME: *unary* + - should be here, too
+%left plusplus_prefix minusminus_prefix '~' '!' "void" "delete" "typeof" //FIXME: *unary* + - should be here, too
 %left "--" "++" 
-%nonassoc "is" "as"
 %left '[' ']' '{' "new" '.' ".." "::"
 %nonassoc T_IDENTIFIER
 %left below_else
 // needed for "return" precedence:
 %nonassoc T_STRING T_REGEXP
 %nonassoc T_INT T_UINT T_BYTE T_SHORT T_FLOAT
-%nonassoc "false" "true" "null"
+%nonassoc "false" "true" "null" "undefined"
 
      
 %{
@@ -1411,9 +1416,9 @@ STATICCONSTANT : T_UINT {$$ = constant_new_uint($1);}
 STATICCONSTANT : T_FLOAT {$$ = constant_new_float($1);}
 STATICCONSTANT : T_STRING {$$ = constant_new_string2($1.str,$1.len);}
 //STATICCONSTANT : T_NAMESPACE {$$ = constant_new_namespace($1);}
-STATICCONSTANT : KW_TRUE {$$ = constant_new_true($1);}
-STATICCONSTANT : KW_FALSE {$$ = constant_new_false($1);}
-STATICCONSTANT : KW_NULL {$$ = constant_new_null($1);}
+STATICCONSTANT : "true" {$$ = constant_new_true($1);}
+STATICCONSTANT : "false" {$$ = constant_new_false($1);}
+STATICCONSTANT : "null" {$$ = constant_new_null($1);}
 
 /* ------------ classes and interfaces (body, functions) ------- */
 
@@ -1492,11 +1497,13 @@ QNAME_LIST : QNAME_LIST ',' QNAME {$$=$1;list_append($$,$3);}
 
 TYPE : QNAME      {$$=$1;}
      | '*'        {$$=registry_getanytype();}
+    /*
      |  "String"  {$$=registry_getstringclass();}
      |  "int"     {$$=registry_getintclass();}
      |  "uint"    {$$=registry_getuintclass();}
      |  "Boolean" {$$=registry_getbooleanclass();}
      |  "Number"  {$$=registry_getnumberclass();}
+    */
 
 MAYBETYPE: ':' TYPE {$$=$2;}
 MAYBETYPE:          {$$=0;}
@@ -1588,9 +1595,8 @@ FUNCTIONCALL : E '(' MAYBE_EXPRESSION_LIST ')' {
    
     memberinfo_t*f = 0;
    
-    if(TYPE_IS_FUNCTION($1.t) &&
-       (f = registry_findmember($1.t, "call"))) {
-        $$.t = f->return_type;
+    if(TYPE_IS_FUNCTION($1.t) && $1.t->function) {
+        $$.t = $1.t->function->return_type;
     } else {
         $$.c = abc_coerce_a($$.c);
         $$.t = TYPE_ANY;
@@ -1668,13 +1674,16 @@ CONSTANT : T_FLOAT {$$.c = abc_pushdouble(0, $1);
 CONSTANT : T_STRING {$$.c = abc_pushstring2(0, &$1);
                      $$.t = TYPE_STRING;
                     }
-CONSTANT : KW_TRUE {$$.c = abc_pushtrue(0);
+CONSTANT : "undefined" {$$.c = abc_pushundefined(0);
+                    $$.t = TYPE_ANY;
+                   }
+CONSTANT : "true" {$$.c = abc_pushtrue(0);
                     $$.t = TYPE_BOOLEAN;
                    }
-CONSTANT : KW_FALSE {$$.c = abc_pushfalse(0);
+CONSTANT : "false" {$$.c = abc_pushfalse(0);
                      $$.t = TYPE_BOOLEAN;
                     }
-CONSTANT : KW_NULL {$$.c = abc_pushnull(0);
+CONSTANT : "null" {$$.c = abc_pushnull(0);
                     $$.t = TYPE_NULL;
                    }
 
@@ -1696,6 +1705,9 @@ E : E "==" E {$$.c = code_append($1.c,$3.c);$$.c = abc_equals($$.c);
              }
 E : E "===" E {$$.c = code_append($1.c,$3.c);$$.c = abc_strictequals($$.c);
               $$.t = TYPE_BOOLEAN;
+              }
+E : E "!==" E {$$.c = code_append($1.c,$3.c);$$.c = abc_strictequals($$.c);$$.c = abc_not($$.c);
+              $$.t = TYPE_BOOLEAN;
              }
 E : E "!=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_equals($$.c);$$.c = abc_not($$.c);
               $$.t = TYPE_BOOLEAN;
@@ -1745,6 +1757,11 @@ E : E '&' E {$$.c = code_append($1.c,$3.c);
              $$.t = TYPE_INT;
             }
 
+E : E '^' E {$$.c = code_append($1.c,$3.c);
+             $$.c = abc_bitxor($$.c);
+             $$.t = TYPE_INT;
+            }
+
 E : E '|' E {$$.c = code_append($1.c,$3.c);
              $$.c = abc_bitor($$.c);
              $$.t = TYPE_INT;
@@ -1759,6 +1776,19 @@ E : E '-' E {$$.c = code_append($1.c,$3.c);
                 $$.t = TYPE_NUMBER;
              }
             }
+E : E ">>" E {$$.c = code_append($1.c,$3.c);
+             $$.c = abc_rshift($$.c);
+             $$.t = TYPE_INT;
+            }
+E : E ">>>" E {$$.c = code_append($1.c,$3.c);
+             $$.c = abc_urshift($$.c);
+             $$.t = TYPE_INT;
+            }
+E : E "<<" E {$$.c = code_append($1.c,$3.c);
+             $$.c = abc_lshift($$.c);
+             $$.t = TYPE_INT;
+            }
+
 E : E '/' E {$$.c = code_append($1.c,$3.c);
              $$.c = abc_divide($$.c);
              $$.t = TYPE_NUMBER;
@@ -1781,9 +1811,41 @@ E : E '*' E {$$.c = code_append($1.c,$3.c);
              }
             }
 
-E : E "as" E
-E : E "is" E
-E : '(' E ')' {$$=$2;}
+E : E "as" E {char use_astype=0; // flash player's astype works differently than astypelate
+              if(use_astype && TYPE_IS_CLASS($3.t)) {
+                MULTINAME(m,$3.t->cls);
+                $$.c = abc_astype2($1.c, &m);
+                $$.t = $3.t->cls;
+              } else {
+                $$.c = code_append($1.c, $3.c);
+                $$.c = abc_astypelate($$.c);
+                $$.t = TYPE_ANY;
+              }
+             }
+
+E : E "is" E {$$.c = code_append($1.c, $3.c);
+              $$.c = abc_istypelate($$.c);
+              $$.t = TYPE_BOOLEAN;
+             }
+
+E : "typeof" '(' E ')' {
+              $$.c = $3.c;
+              $$.c = abc_typeof($$.c);
+              $$.t = TYPE_STRING;
+             }
+
+E : "void" E {
+              $$.c = cut_last_push($2.c);
+              $$.c = abc_pushundefined($$.c);
+              $$.t = TYPE_ANY;
+             }
+
+E : "void" { $$.c = abc_pushundefined(0);
+             $$.t = TYPE_ANY;
+           }
+
+E : '(' EXPRESSION ')' {$$=$2;} //allow commas in here, too
+
 E : '-' E {
   $$=$2;
   if(IS_INT($2)) {
@@ -1815,6 +1877,7 @@ E : E "*=" E {
                $$.c = toreadwrite($1.c, c, 0, 0);
                $$.t = $1.t;
               }
+
 E : E "%=" E { 
                code_t*c = abc_modulo($3.c);
                c=converttype(c, join_types($1.t, $3.t, '%'), $1.t);
@@ -1875,6 +1938,17 @@ E : E '=' E { code_t*c = 0;
               $$.t = $1.t;
             }
 
+E : E '?' E ':' E %prec below_assignment { 
+              $$.c = $1.c;
+              code_t*j1 = $$.c = abc_iffalse($$.c, 0);
+              $$.c = code_append($$.c, $3.c);
+              code_t*j2 = $$.c = abc_jump($$.c, 0);
+              $$.c = j1->branch = abc_label($$.c);
+              $$.c = code_append($$.c, $5.c);
+              $$.c = j2->branch = abc_label($$.c);
+              $$.t = join_types($3.t,$5.t,'?');
+            }
+
 // TODO: use inclocal where appropriate
 E : E "++" { code_t*c = 0;
              classinfo_t*type = $1.t;
@@ -2038,7 +2112,7 @@ VAR_READ : T_IDENTIFIER {
     /* unknown object, let the avm2 resolve it */
     } else {
         if(strcmp($1,"trace"))
-            warning("Couldn't resolve %s, doing late binding", $1);
+            warning("Couldn't resolve '%s', doing late binding", $1);
         state->late_binding = 1;
                 
         multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $1};