microfixes
[henge/apc.git] / src / parser.y
1 /* Asset Package Compiler */
2
3 %code requires {
4 #include <unitypes.h>
5 #include "ir.h"
6 typedef struct class_state_t yycstate;
7 struct frame_spec_t { ir_facing d; int w, h; };
8 }
9 %code provides {
10 yycstate* yycstate_new(void);
11 void yycstate_delete(yycstate*);
12 }
13 %code {
14 #include <stdio.h>
15 #include <string.h>
16 #include <dirent.h>
17 #include <unitypes.h>
18 #include "ir.h"
19
20 struct class_state_t {
21 ir_class *csp;
22 ir_class class_stack[];
23 };
24
25 extern long sys_pagesize;
26 extern int lexer();
27 static void yyerror(char const*);
28 /* Stack-based class handler */
29 #define CLASS_POP(CS) (*--(CS-csp))
30 #define CLASS_PUSH(CS,CL) (*(CS->csp)++ = CL)
31 #define yyclass(CS) (*(CS->csp))
32 #define yyclassld(CS) (ir_classld_from_class(yyclass(CS)))
33 }
34 %define parse.error verbose
35 %define lr.type ielr
36 %define api.pure full
37 %define api.push-pull push
38 %parse-param {yycstate* cs}
39 %union {
40 long long ref;
41 int val;
42 ir_facing face;
43 uint8_t* str;
44 ir_class class;
45 ir_set set;
46 ir_setld ld;
47 ir_setdata data;
48 struct frame_spec_t frame_spec;
49 }
50 /* Operators */
51 %token CLOPEN //(
52 %token CLCLOSE //)
53 %token MAP //~
54 %token AUDIO //AUDIO
55 %token SS //SS
56 %token LINK //#
57 /* Terminals */
58 %token <val> NUM
59 %token <str> PATH
60 %token <ref> REF
61 %token <face> FACING
62 %token <str> NAME
63 /* Types */
64 %type<data> data_spec
65 %type<set> set_spec
66 %type<ld> set_ld set_link
67 %type<frame_spec> frame_spec
68 %%
69 /* Syntax Directed Translation Scheme of the APC grammar */
70 progn:
71 class_list
72 | class_list statement_list
73 | statement_list
74 ;
75
76 class_list:
77 class_list class
78 | class
79 ;
80
81 class:
82 NAME CLOPEN { CLASS_PUSH(cs,ir_class_addchild(yyclass, $1)); }
83 progn
84 CLCLOSE { CLASS_POP(cs); }
85 ;
86
87 statement_list:
88 statement_list statement
89 | statement
90 ;
91
92 statement:
93 set_spec data_spec REF PATH { ir_data_assign_path($2,$4); ir_set_assign_data($1,$2); ir_set_assign_ref($1,$3); }
94 | set_spec data_spec PATH { ir_data_assign_path($2,$3); ir_set_assign_data($1,$2); }
95 | set_spec REF PATH { ir_set_assign_ref($1,$2); }
96 ;
97
98 data_spec:
99 SS NAME frame_spec { $$ = ir_framesheet($2,$3.d,$3.w,$3.h); }
100 | MAP NAME frame_spec { $$ = ir_mapsheet($2,$3.d,$3.w,$3.h); }
101 | AUDIO NAME { $$ = ir_audio($2); }
102 | LINK set_ld { $$ = ir_link_odat($2); }
103 | LINK set_ld MAP { $$ = ir_link_mdat($2,NULL); }
104 | LINK set_ld MAP NAME { $$ = ir_link_mdat($2,$4); }
105 | LINK set_ld SS { $$ = ir_link_vdat($2,NULL); }
106 | LINK set_ld SS NAME { $$ = ir_link_vdat($2,$4); }
107 | LINK set_ld AUDIO { $$ = ir_link_adat($2,NULL); }
108 | LINK set_ld AUDIO NAME { $$ = ir_link_adat($2,$4); }
109 ;
110
111 set_spec:
112 set_spec NAME { $$ = ir_set_addchild($1,$2); }
113 | NAME { $$ = ir_class_addset(yyclass,$1); }
114 ;
115
116 set_link:
117 set_link NAME { $$ = ir_setld_addchild($1,$2); }
118 | NAME { $$ = ir_setld_from_classld(yyclassld,$1) }
119 ;
120
121 set_ld:
122 set_link { $$ = $1; }
123 | REF { $$ = ir_setld_from_ref($1); }
124 ;
125
126 frame_spec:
127 NUM NUM { $$ = (struct frame_spec_t) {SFACE,$1,$2}; }
128 | FACING { $$ = (struct frame_spec_t) {$1,0,0}; }
129 | FACING NUM NUM { $$ = (struct frame_spec_t) {$1,$2,$3}; }
130 ;
131
132 %%
133
134 static
135 void yyerror
136 ( char const *s )
137 { fprintf(stderr, "%s\n", s); }
138
139 yycstate* yycstate_new
140 ( void )
141 { yycstate* class_state;
142 class_state = (yycstate*) malloc((size_t) sys_pagesize);
143 if(class_state == NULL)
144 { yyerror(ERR_MEM);
145 exit(1);
146 }
147 class_state->csp = &class_state->class_stack[0];
148 CLASS_PUSH(class_state, ir_class_root());
149 return class_state;
150 }
151
152 void yycstate_delete
153 ( yycstate* class_state )
154 { free(class_state); }