/* Asset Package Compiler */
-%code requires {
+
+%code requires {
#include <unitypes.h>
}
+%code provides {
+ typedef struct class_state_t yycstate;
+ yycstate* yycstate_new(void);
+ void yycstate_delete(yycstate*);
+}
+
%{
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <unitypes.h>
- 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(uint8_t*,int, int, int, int, uint8_t*);
- extern void insert_mlink(uint8_t*, int);
- extern void insert_vlink(uint8_t*, int);
- extern void insert_framesheet(uint8_t* ,int, int, int,int, uint8_t*);
-
- #define yylex lexer
+ #include "ir.h"
+
+ struct class_state_t {
+ ir_class *csp;
+ size_t class_stack_size;
+ ir_class *class_stack;
+ };
- void yyerror();
+ 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_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
+%parse-param {yycstate* cs}
%union {
- long long ref;
- int val;
- uint8_t* str;
- 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 <val> NUM
-%token <str> PATH
-%token <ref> REF
-%token <val> HEIGHT
-%token <val> WIDTH
-%token <val> D
-%token <str> NAME
-//nonterminals
-%type <val> 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 <val> NUM
+%token <str> PATH
+%token <ref> REF
+%token <face> FACING
+%token <str> NAME
+/* Types */
+%type<data> data_spec
+%type<set> set_spec
+%type<ld> set_ld set_link
+%type<frame_spec> 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_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);};
+set_spec:
+ set_spec NAME { $$ = ir_set_addchild($1,$2); }
+| NAME { $$ = ir_class_addset(yyclass,$1); }
;
-map_statement:
-set_namelist MOPEN map
-| set_namelist MOPEN mlink
+set_link:
+ set_link NAME { $$ = ir_setld_addchild($1,$2); }
+| NAME { $$ = ir_setld_from_classld(yyclassld,$1) }
;
-map:
-NAME NUM NUM PATH {insert_map($1, 0, $3, 0, 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);};
+set_ld:
+ set_link { $$ = $1; }
+| REF { $$ = ir_setld_from_ref($1); }
;
-//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); };
+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}; }
;
-//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
-;
+%%
+#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());
+}
-olink:
-set_namelist MOPEN REF
-;
+/* 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);
+}
-ref_id:
-LINK REF {$$ = $2;};
-;
+yycstate*
+yycstate_new
+( void )
+{ yycstate* class_state;
+ class_state = (yycstate*) malloc((size_t) sys_pagesize);
-vdat_statement:
-set_namelist SS spritesheet_statement
-| set_namelist SS vlink
-;
+ if(class_state == NULL)
+ { yyerror(ERR_MEM);
+ exit(1);
+ }
+
+ class_state.class_stack = class_stack;
+ class_state.csp = class_state.class_stack;
+ class_state.class_stack_size = (size_t) sys_pagesize;
+ class_stack_push(ir_class_root());
-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);};
-;
+ return class_state;
-%%
+}
void
-yyerror (char const *s)
-{ fprintf(stderr, "%s\n", s);
+yycstate_delete
+( yycstate* class_state )
+{
+ free(class_state);
+
}