/* Asset Package Compiler */ %code requires { #include #include "ir.h" #include "apc.h" typedef struct class_state_t yycstate; struct frame_spec_t { apc_facing d; int w, h; }; } %code provides { yycstate* yycstate_new(void); void yycstate_delete(yycstate*); } %code { #include #include #include #include #include "ir.h" struct class_state_t { ir_class *csp; ir_class class_stack[]; }; extern long sys_pagesize; extern int lexer(); static void yyerror(yycstate*, char const*); static inline ir_class yyclass_push(yycstate*, ir_class); static inline ir_class yyclass_pop(yycstate*); /* Stack-based class handler */ #define yyclass(CS) (*(CS->csp)) #define yyclassld(CS) (ir_classld_from_class(yyclass(CS))) } %define parse.error verbose %define lr.type ielr %define api.pure full %define api.push-pull push %parse-param {yycstate* cs} %union { long long ref; int val; apc_facing face; uint8_t* str; ir_class class; ir_set set; ir_setld ld; ir_setdata data; struct frame_spec_t frame_spec; } /* Operators */ %token CLOPEN //( %token CLCLOSE //) %token MAP //~ %token AUDIO //AUDIO %token SS //SS %token LINK //# /* Terminals */ %token NUM %token PATH %token REF %token FACING %token NAME /* Types */ %type data_spec %type set_spec %type set_ld set_link %type frame_spec %% /* Syntax Directed Translation Scheme of the APC grammar */ progn: class_list | class_list statement_list | statement_list ; class_list: class_list class | class ; class: NAME CLOPEN { yyclass_push(cs,ir_class_addchild(yyclass(cs), $1)); } progn CLCLOSE { yyclass_pop(cs); } ; statement_list: statement_list statement | statement ; statement: set_spec data_spec REF PATH { ir_data_assign_path($2,$4); ir_set_assign_data($1,$2); ir_set_assign_ref($1,$3); } | set_spec data_spec PATH { ir_data_assign_path($2,$3); ir_set_assign_data($1,$2); } | set_spec REF PATH { ir_set_assign_ref($1,$2); } ; data_spec: SS NAME frame_spec { $$ = ir_framesheet($2,$3.d,$3.w,$3.h); } | MAP NAME frame_spec { $$ = ir_mapsheet($2,$3.d,$3.w,$3.h); } | AUDIO NAME { $$ = ir_audio($2); } | LINK set_ld { $$ = ir_link(OLINK, $2, NULL); } | LINK set_ld MAP { $$ = ir_link(MLINK, $2,NULL); } | LINK set_ld MAP NAME { $$ = ir_link(MLINK, $2,$4); } | LINK set_ld SS { $$ = ir_link(VLINK, $2,NULL); } | LINK set_ld SS NAME { $$ = ir_link(VLINK, $2,$4); } | LINK set_ld AUDIO { $$ = ir_link(ALINK, $2,NULL); } | LINK set_ld AUDIO NAME { $$ = ir_link(ALINK, $2,$4); } ; set_spec: set_spec NAME { $$ = ir_set_addchild($1,$2); } | NAME { $$ = ir_class_addset(yyclass(cs),$1); } ; set_link: set_link NAME { $$ = ir_setld_addchild($1,$2); } | NAME { $$ = ir_setld_from_classld(yyclassld(cs),$1); } ; set_ld: set_link { $$ = $1; } | REF { $$ = ir_setld_from_ref($1); } ; frame_spec: NUM NUM { $$ = (struct frame_spec_t) {SFACE,$1,$2}; } | FACING { $$ = (struct frame_spec_t) {$1,0,0}; } | FACING NUM NUM { $$ = (struct frame_spec_t) {$1,$2,$3}; } ; %% static void yyerror ( yycstate* cs, char const *s ) { fprintf(stderr, "%s\n", s); } yycstate* yycstate_new ( void ) { yycstate* class_state; class_state = (yycstate*) malloc((size_t) sys_pagesize); if(class_state == NULL) { yyerror(class_state, "Memory allocation error."); return NULL; } class_state->csp = class_state->class_stack; *(class_state->csp) = ir_class_root(); return class_state; } static inline ir_class yyclass_pop ( yycstate* cs ) { return *((cs->csp)--); } static inline ir_class yyclass_push ( yycstate* cs, ir_class class ) { return *++(cs->csp) = class; } void yycstate_delete ( yycstate* class_state ) { free(class_state); }