X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fapc.git;a=blobdiff_plain;f=src%2Fparser.y;h=c1f15f40289f1f37533f51316dd2be40bc143f39;hp=85c6c506c7325a0c0d3b237bdc846a3d57d2e526;hb=0dc97f87cbbe47ef84501678f302404d042428b1;hpb=c6453f4b6219125bf45a61cde2f44bd7a3154e17 diff --git a/src/parser.y b/src/parser.y index 85c6c50..c1f15f4 100644 --- a/src/parser.y +++ b/src/parser.y @@ -1,175 +1,181 @@ /* Asset Package Compiler */ -%code requires{ - #include +%code requires { #include - #include "apc.h" } + %{ #include #include #include - - extern int lexer_init(); //? - extern int lexer(); //? - extern void pop_cdat(void); - extern void push_cdat(uint8_t*); - extern void insert_vdat(void); - extern void insert_refid(int); - extern void insert_set_name(uint8_t*); - extern void insert_set_namelist(uint8_t*); - extern void insert_link_name(uint8_t*); - extern void insert_map(int, uint8_t*, int, int, uint8_t*); - extern void insert_mlink(uint8_t*, int); - extern void insert_vlink(uint8_t*, int); - extern void insert_framesheet(uint_t* int, int, int,int, uint8_t*); - - #define yylex lexer - - - void yyerror(); + #include + #include "ir.h" + + struct frame_spec_t { enum facing d; int w, h; }; + + extern long sys_pagesize; + extern int lexer(); + static void yyerror(char const*); + /* Stack-based class handler */ + static ir_class *class_stack, *csp; + static size_t class_stack_size; + static ir_class class_stack_init(void); + #define class_stack_pop() (*--csp) + static ir_class class_stack_push(ir_class); + + #define yylex lexer + #define yyclass (*csp) + #define yyclassld (ir_classld_from_class(yyclass)) %} %define parse.error verbose %define lr.type ielr - +%define api.pure full +%define api.push-pull push %union { - int ref; - int val; - uint8_t *str; - struct name* name; - void *voidp; + long long ref; + int val; + enum 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 MOPEN // ~ -%token HB -%token ROOT -%token SS -%token LINK //# -%token SCLOSE -%token CHILD -//terminals -%token NUM -%token PATH -%token REF -%token HEIGHT -%token WIDTH -%token D -%token NAME -//nonterminals -%type ref_id - /* Syntax Directed Translation Scheme of the APC grammar */ - -/* Rules */ +/* 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 +/* Init */ +%initial-action { class_stack_init(); } %% -cdat_buf: -class_block -; - -class: -NAME CLOPEN {push_cdat($1);} class_block CLCLOSE {pop_cdat();}; +/* Syntax Directed Translation Scheme of the APC grammar */ +progn: + class_list +| class_list statement_list +| statement_list ; class_list: -class_list class + class_list class | class ; -class_block: -class_list -| class_list statement_list -| statement_list +class: + NAME CLOPEN { class_stack_push(ir_class_addchild(yyclass, $1)); } + progn + CLCLOSE { class_stack_pop(); } ; statement_list: -statement_list statement -| statement + statement_list statement +| statement ; statement: -vdat_statement -| map_statement -| ref_statement -| olink -; - -ref_statement: -set_namelist ref_id {insert_set_refid($2);}; + 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); } ; -link_namelist: -link_namelist NAME {insert_link_name($2);}; -| NAME {}; +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_odat($2); } +| LINK set_ld MAP { $$ = ir_link_mdat($2,NULL); } +| LINK set_ld MAP NAME { $$ = ir_link_mdat($2,$4); } +| LINK set_ld SS { $$ = ir_link_vdat($2,NULL); } +| LINK set_ld SS NAME { $$ = ir_link_vdat($2,$4); } +| LINK set_ld AUDIO { $$ = ir_link_adat($2,NULL); } +| LINK set_ld AUDIO NAME { $$ = ir_link_adat($2,$4); } ; - -set_namelist: -set_namelist NAME {insert_set_name($2);}; -| NAME {insert_set_namelist($1);}; -; - -map_statement: -set_namelist MOPEN map -| set_namelist MOPEN mlink -; - -map: -NAME NUM NUM PATH {insert_map(0, $1, $2, $3, 0, $4);}; -| NAME PATH {insert_map($1, 0, 0, 0, 0, $2);}; -| NAME D PATH {insert_map($1, $2, 0, 0, 0, $3);}; -| NAME D NUM NUM PATH {insert_map($1, $2, $3, $4, 0, $5);}; -| NAME NUM NUM ref_id PATH {insert_map($1, 0, $2, $3, $4, $5);}; -| NAME ref_id PATH {insert_map($1, 0, 0, 0, $2, $3);}; -| NAME D ref_id PATH {insert_map($1, $2, 0, 0, $3, $4);}; -| NAME D NUM NUM ref_id PATH {insert_map($1, $2, $3, $4, $5, $6);}; -; - -//shift list_namelist name > reduce mlink -mlink: -MOPEN LINK NAME LINK link_namelist PATH {insert_mlink($3, 0); }; -| MOPEN LINK link_namelist PATH {insert_mlink(NULL, 0); }; -| MOPEN LINK ref_id PATH {insert_mlink(NULL, $3); }; -| MOPEN LINK NAME LINK ref_id PATH {insert_mlink($3,$5); }; +set_spec: + set_spec NAME { $$ = ir_set_addchild($1,$2); } +| NAME { $$ = ir_class_addset(yyclass,$1); } ; -//shift list_namelist name > reduce vlink -vlink: -LINK NAME LINK link_namelist PATH {insert_vlink($2, 0); }; -| LINK link_namelist PATH {insert_vlink(NULL, 0);}; -| LINK REF PATH {insert_vlink(NULL, $2);};//vdat of ref -| LINK NAME LINK REF PATH {insert_vlink($2, $4);};//modelname of ref +set_link: + set_link NAME { $$ = ir_setld_addchild($1,$2); } +| NAME { $$ = ir_setld_from_classld(yyclassld,$1) } ; - -olink: -set_namelist MOPEN REF +set_ld: + set_link { $$ = $1; } +| REF { $$ = ir_setld_from_ref($1); } ; -ref_id: -LINK REF {$$ = $2;}; -; - - -vdat_statement: -set_namelist SS spritesheet_statement -| set_namelist SS vlink -; - -spritesheet_statement: -NAME D HEIGHT WIDTH PATH {insert_framesheet($1, $2, $3, $4, 0, $5);}; -| NAME D PATH {insert_framesheet($1, $2, 0, 0, 0, $3);}; -| NAME HEIGHT WIDTH PATH {insert_framesheet($1, 0, $2, $3, 0, $4);}; -| NAME PATH {insert_framesheet($1, 0, 0, 0, 0, $2);}; -| NAME D HEIGHT WIDTH ref_id PATH {insert_framesheet($1, $2, $3, $4, $5, $6);}; -| NAME D ref_id PATH {insert_framesheet($1, $2, 0, 0, $3, $4);}; -| NAME HEIGHT WIDTH ref_id PATH {insert_framesheet($1, 0, $2, $3, $4, $5);}; -| NAME ref_id PATH {insert_framesheet($1, 0, 0, 0, $2, $3);}; +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}; } ; %% -void -yyerror (char const *s) -{ fprintf(stderr, "%s\n", s); +#define ERR_ALLOC "memory allocation error\n" + +/* print to stderr */ +static +void yyerror +( char const *s ) +{ fprintf(stderr, "%s\n", s); } + +/* Initialize the class stack + If the class_stack hasn't been allocated yet, allocates a page for pointers + to be stored in. Initializes class stack pointer, and inserts the root class + from IR + Returns the root class given by IR. +*/ +static +ir_class class_stack_init +( void ) +{ if (class_stack == NULL) + { class_stack_size = (size_t) sys_pagesize; + class_stack = (ir_class*) malloc(class_stack_size); + if (class_stack == NULL) + { yyerror(ERR_MEM); + exit(1); + } + } + csp = class_stack; + return class_stack_push(ir_class_root()); +} + +/* Add a Class to the Stack + Allocated in page-sized chunks, potentially infinite depth is supported. + Returns the input class. +*/ +static +ir_class class_stack_push +#define class_size (sizeof(*class_stack)) +( ir_class class ) +{ size_t class_stack_len = csp - class_stack; + ir_class* new_class_stack; + if ((class_stack_len * class_size + class_size) > class_stack_size) + { class_stack_size += (size_t) sys_pagesize; + new_class_stack = (ir_class*) realloc(class_stack, class_stack_size); + if (new_class_stack == NULL) + { free(class_stack); //realloc failure does not free class_stack + yyerror("realloc " ERR_MEM); + exit(1); + } + class_stack = new_class_stack; + csp = class_stack + class_stack_len; + } + return (*csp++ = class); }