default variant
[henge/apc.git] / src / parser.y
index e509890..e1fe896 100644 (file)
 /* Asset Package Compiler */
-%code requires  {
-  #include <unitypes.h>
-}
 
-%{
+%code requires {
+  #include <unitypes.h>
+  #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 <stdio.h>
   #include <string.h>
   #include <dirent.h>
-
-  extern int lexer_init(); //?
-  extern int lexer(); //?
-  extern void pop_cdat(void);
-  extern void push_cdat(struct name*);
-  extern void insert_vdat(void);
-  extern void insert_refid(int);
-  extern void insert_refid(int);
-  extern void insert_set_name(struct name*);
-  extern void insert_set_namelist(struct name*);
-  extern void insert_link_name(struct name*);
-  extern void insert_map(struct name*,int, int, int, int, uint8_t*);
-  extern void insert_mlink(struct name*, int);
-  extern void insert_vlink(struct name*, int);
-  extern void insert_framesheet(struct name* ,int, int, int,int, uint8_t*);
+  #include <unitypes.h>
+  #include "ir.h"
   
-  #define yylex lexer
-
-
-  void yyerror();
-%}
+  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 DEFAULT_VARIANT "default"
+}
 %define parse.error verbose
+%define parse.lac full
 %define lr.type ielr
-
+%define api.pure full
+%define api.push-pull push
+%parse-param {yycstate* cs}
 %union {
-  int ref;
-  int val;
-  uint8_t* str;
-  struct name* name;
-  void *voidp;
+  uint32_t   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         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 <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
 %%
-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   { yyclass_push(cs,ir_class_addchild(yyclass(cs), $1)); }
+  progn
+  CLCLOSE       { yyclass_pop(cs); }
+| CLCLOSE       { yyclass_pop(cs); }
 ;
 
 statement_list:
-statement_list statement
-| statement
+  statement_list statement
+| statement    
 ;
 
 statement:
-vdat_statement
-| map_statement
-| ref_statement
-| olink
+  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); }
 ;
 
-ref_statement:
-set_namelist ref_id                                  {insert_refid($2);};
+data_spec:
+  SS NAME frame_spec     { $$ = ir_framesheet($2,$3.d,$3.w,$3.h); }
+| SS frame_spec          { $$ = ir_framesheet(DEFAULT_VARIANT,$2.d,$2.w,$2.h); }
+| MAP NAME frame_spec    { $$ = ir_mapsheet($2,$3.d,$3.w,$3.h); }
+| MAP frame_spec         { $$ = ir_mapsheet(DEFAULT_VARIANT,$2.d,$2.w,$2.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); }
 ;
 
-link_namelist:
-link_namelist NAME                                {insert_link_name($2);};
-| NAME                                            {};
+set_spec:
+  set_spec NAME          { $$ = ir_set_addchild($1,$2); }
+| NAME                   { $$ = ir_class_addset(yyclass(cs),$1); }
 ;
 
-
-set_namelist:
-set_namelist NAME                                     {insert_set_name($2);};
-| NAME                                             {insert_set_namelist($1);};
+set_link:
+  set_link NAME          { $$ = ir_setld_addchild($1,$2); }
+| NAME                   { $$ = ir_setld_from_classld(yyclassld(cs),$1); }
 ;
 
-map_statement:
-set_namelist MOPEN map
-| set_namelist MOPEN mlink
+set_ld:
+  set_link               { $$ = $1; }
+| REF                    { $$ = ir_setld_from_ref($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);};
-;
-
-//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);     };
-;
-
-//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
-;
-
-
-olink:
-set_namelist MOPEN REF 
+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}; }
+| %empty                 { $$ = (struct frame_spec_t) {SFACE,0,0}; }
 ;
 
-ref_id:
-LINK REF                                            {$$ = $2;};
-;
+%%
 
+static
+void yyerror
+( yycstate* cs,
+  char const *s
+)
+{ ir_class* iter;
+  fprintf(stderr, "[class->");
+  for (iter = cs->class_stack; iter < cs->csp; iter++)
+    fprintf(stderr, "%s/", ir_class_name(*iter));
+  fprintf(stderr, "]\n\t");
+  fprintf(stderr, "%s\n", s);
+}
 
-vdat_statement:
-set_namelist SS spritesheet_statement
-| set_namelist SS vlink                   
-;
+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;
+}
 
-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);};
-;
+static inline
+ir_class yyclass_pop
+( yycstate* cs )
+{ cs->csp--;
+  return *(cs->csp + 1);
+}
 
-%%
+static inline
+ir_class yyclass_push
+( yycstate* cs,
+  ir_class class
+)
+{ return *++(cs->csp) = class; }
 
-void
-yyerror (char const *s)
-{ fprintf(stderr, "%s\n", s);
-}
+void yycstate_delete
+( yycstate* class_state )
+{ free(class_state); }