+//NAMESPACE : {$$=empty_token();}
+//NAMESPACE : T_IDENTIFIER {$$=$1};
+
+CONSTANT : T_BYTE {$$.c = abc_pushbyte(0, $1);
+ //MULTINAME(m, registry_getintclass());
+ //$$.c = abc_coerce2($$.c, &m); // FIXME
+ $$.t = TYPE_INT;
+ }
+CONSTANT : T_SHORT {$$.c = abc_pushshort(0, $1);
+ $$.t = TYPE_INT;
+ }
+CONSTANT : T_INT {$$.c = abc_pushint(0, $1);
+ $$.t = TYPE_INT;
+ }
+CONSTANT : T_UINT {$$.c = abc_pushuint(0, $1);
+ $$.t = TYPE_UINT;
+ }
+CONSTANT : T_FLOAT {$$.c = abc_pushdouble(0, $1);
+ $$.t = TYPE_FLOAT;
+ }
+CONSTANT : T_STRING {$$.c = abc_pushstring(0, $1);
+ $$.t = TYPE_STRING;
+ }
+CONSTANT : KW_TRUE {$$.c = abc_pushtrue(0);
+ $$.t = TYPE_BOOLEAN;
+ }
+CONSTANT : KW_FALSE {$$.c = abc_pushfalse(0);
+ $$.t = TYPE_BOOLEAN;
+ }
+CONSTANT : KW_NULL {$$.c = abc_pushnull(0);
+ $$.t = TYPE_NULL;
+ }
+
+USE_NAMESPACE : "use" "namespace" T_IDENTIFIER
+
+
+EXPRESSION : E %prec prec_none /*precedence below '-x'*/ {$$ = $1;}
+VOIDEXPRESSION : E %prec prec_none {$$=$1.c;/*calculate and discard*/$$=abc_pop($$);}
+
+E : CONSTANT
+E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
+E : NEW {$$ = $1;}
+E : T_REGEXP {$$.c = abc_pushundefined(0); /* FIXME */
+ $$.t = TYPE_ANY;
+ }
+E : FUNCTIONCALL
+E : E '<' E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterequals($$.c);$$.c=abc_not($$.c);
+ $$.t = TYPE_BOOLEAN;
+ }
+E : E '>' E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterthan($$.c);
+ $$.t = TYPE_BOOLEAN;
+ }
+E : E "<=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterthan($$.c);$$.c=abc_not($$.c);
+ $$.t = TYPE_BOOLEAN;
+ }
+E : E ">=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterequals($$.c);
+ $$.t = TYPE_BOOLEAN;
+ }
+E : E "==" E {$$.c = code_append($1.c,$3.c);$$.c = abc_equals($$.c);
+ $$.t = TYPE_BOOLEAN;
+ }
+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_equals($$.c);$$.c = abc_not($$.c);
+ $$.t = TYPE_BOOLEAN;
+ }
+
+E : E "||" E {$$.t = join_types($1.t, $3.t, 'O');
+ $$.c = $1.c;
+ $$.c = converttype($$.c, $1.t, $$.t);
+ $$.c = abc_dup($$.c);
+ code_t*jmp = $$.c = abc_iftrue($$.c, 0);
+ $$.c = abc_pop($$.c);
+ $$.c = code_append($$.c,$3.c);
+ $$.c = converttype($$.c, $1.t, $$.t);
+ code_t*label = $$.c = abc_label($$.c);
+ jmp->branch = label;
+ }
+E : E "&&" E {$$.t = join_types($1.t, $3.t, 'A');
+ $$.c = $1.c;
+ $$.c = converttype($$.c, $1.t, $$.t);
+ $$.c = abc_dup($$.c);
+ code_t*jmp = $$.c = abc_iffalse($$.c, 0);
+ $$.c = abc_pop($$.c);
+ $$.c = code_append($$.c,$3.c);
+ $$.c = converttype($$.c, $1.t, $$.t);
+ code_t*label = $$.c = abc_label($$.c);
+ jmp->branch = label;
+ }
+
+//E : E '.' T_IDENTIFIER '(' ')'
+// {$$.c = 0; // FIXME
+// $$.t = 0;
+// }
+
+E : E '.' T_IDENTIFIER
+ {$$.c = $1.c;
+ if($$.t) {
+ namespace_t ns = {$$.t->access, (char*)$$.t->package};
+ multiname_t m = {QNAME, &ns, 0, $3->text};
+ $$.c = abc_getproperty2($$.c, &m);
+ /* FIXME: get type of ($1.t).$3 */
+ $$.t = registry_getanytype();
+ } else {
+ namespace_t ns = {ACCESS_PACKAGE, ""};
+ multiname_t m = {QNAME, &ns, 0, $3->text};
+ $$.c = abc_getproperty2($$.c, &m);
+ $$.t = registry_getanytype();
+ }
+ }
+
+E : '!' E {$$.c=$2.c;
+ $$.c = abc_not($$.c);
+ $$.t = TYPE_BOOLEAN;
+ }
+
+E : E '-' E
+E : E '/' E
+E : E '+' E {$$.c = code_append($1.c,$3.c);$$.c = abc_add($$.c);$$.c=abc_coerce_a($$.c);
+ $$.t = join_types($1.t, $3.t, '+');
+ }
+E : E '%' E {$$.c = code_append($1.c,$3.c);$$.c = abc_modulo($$.c);$$.c=abc_coerce_a($$.c);
+ $$.t = join_types($1.t, $3.t, '%');
+ }
+E : E '*' E {$$.c = code_append($1.c,$3.c);$$.c = abc_multiply($$.c);$$.c=abc_coerce_a($$.c);
+ $$.t = join_types($1.t, $3.t, '*');
+ }
+
+E : E "as" E
+E : E "is" E
+E : '(' E ')' {$$=$2;}
+E : '-' E {$$=$2;}
+
+E : LH "+=" E {$$.c = $1.read;$$.c=code_append($$.c,$3.c);$$.c=abc_add($$.c);
+ classinfo_t*type = join_types($1.type, $3.t, '+');
+ $$.c=converttype($$.c, type, $1.type);
+ $$.c=abc_dup($$.c);$$.c=code_append($$.c,$1.write);
+ $$.t = $1.type;
+ }
+E : LH "-=" E {$$.c = $1.read;$$.c=code_append($$.c,$3.c);$$.c=abc_add($$.c);
+ classinfo_t*type = join_types($1.type, $3.t, '-');
+ $$.c=converttype($$.c, type, $1.type);
+ $$.c=abc_dup($$.c);$$.c=code_append($$.c,$1.write);
+ $$.t = $1.type;
+ }
+
+// TODO: use inclocal where appropriate
+E : LH "++" {$$.c = $1.read;
+ classinfo_t*type = $1.type;
+ if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
+ $$.c=abc_increment_i($$.c);
+ } else {
+ $$.c=abc_increment($$.c);
+ type = TYPE_NUMBER;
+ }
+ $$.c=converttype($$.c, type, $1.type);
+ $$.c=abc_dup($$.c);$$.c=code_append($$.c,$1.write);
+ $$.t = $1.type;
+ }
+E : LH "--" {$$.c = $1.read;
+ classinfo_t*type = $1.type;
+ if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
+ $$.c=abc_decrement_i($$.c);
+ } else {
+ $$.c=abc_decrement($$.c);
+ type = TYPE_NUMBER;
+ }
+ $$.c=converttype($$.c, type, $1.type);
+ $$.c=abc_dup($$.c);$$.c=code_append($$.c,$1.write);
+ $$.t = $1.type;
+ }
+
+LH: T_IDENTIFIER {
+ int i = find_variable_safe($1->text, &$$.type);
+ $$.read = abc_getlocal(0, i);
+ $$.write = abc_setlocal(0, i);
+}