wip
[henge/apc.git] / src / parser.y
index 85c6c50..c1f15f4 100644 (file)
 /* Asset Package Compiler */
-%code requires{
-  #include <stdint.h>
+%code requires  {
   #include <unitypes.h>
-  #include "apc.h"
 }
+
 %{
   #include <stdio.h>
   #include <string.h>
   #include <dirent.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(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 <unitypes.h>
+  #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 <val> NUM
-%token <str> PATH
-%token <ref> REF
-%token <val> HEIGHT
-%token <val> WIDTH
-%token <val> D
-%token <name> NAME
-//nonterminals
-%type <int> 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_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);
 }