repair brokeness provided by a foolish Makefile
[manmower/obtheme.git] / obtheme.y
1 %pure-parser
2 %name-prefix "obtheme"
3 %parse-param {struct parser_control *pc}
4 %{
5 #include <assert.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <limits.h>
12 #include <unistd.h>
13 #include "frame.h"
14 #include "misc.h"
15 #include "render.h"
16 #include "obtheme.h"
17 #include "obtheme.tab.h"
18
19 YY_DECL;
20
21 struct context_table_item {
22         char *name;
23         ObFrameContext val;
24 };
25
26 /* some of these contexts don't make any sense for a theme... */
27 static struct context_table_item contexts[OB_FRAME_NUM_CONTEXTS] = {
28         {"none", OB_FRAME_CONTEXT_NONE},
29         {"desktop", OB_FRAME_CONTEXT_DESKTOP},
30         {"root", OB_FRAME_CONTEXT_ROOT},
31         {"client", OB_FRAME_CONTEXT_CLIENT},
32         {"titlebar", OB_FRAME_CONTEXT_TITLEBAR},
33         {"frame", OB_FRAME_CONTEXT_FRAME},
34         {"blcorner", OB_FRAME_CONTEXT_BLCORNER},
35         {"brcorner", OB_FRAME_CONTEXT_BRCORNER},
36         {"tlcorner", OB_FRAME_CONTEXT_TLCORNER},
37         {"trcorner", OB_FRAME_CONTEXT_TRCORNER},
38         {"top", OB_FRAME_CONTEXT_TOP},
39         {"bottom", OB_FRAME_CONTEXT_BOTTOM},
40         {"left", OB_FRAME_CONTEXT_LEFT},
41         {"right", OB_FRAME_CONTEXT_RIGHT},
42         {"maximize", OB_FRAME_CONTEXT_MAXIMIZE},
43         {"alldesktops", OB_FRAME_CONTEXT_ALLDESKTOPS},
44         {"shade", OB_FRAME_CONTEXT_SHADE},
45         {"iconify", OB_FRAME_CONTEXT_ICONIFY},
46         {"icon", OB_FRAME_CONTEXT_ICON},
47         {"close", OB_FRAME_CONTEXT_CLOSE},
48         {"moveresize", OB_FRAME_CONTEXT_MOVE_RESIZE}
49 };
50
51 static ObFrameContext context_from_string(char *str)
52 {
53         int i;
54         for (i = 0; i < OB_FRAME_NUM_CONTEXTS; i++)
55                 if (strcmp(contexts[i].name, str) == 1)
56                         return contexts[i].val;
57         return -1;
58 }
59
60 struct gradient_table_item {
61         char *name;
62         RrSurfaceColorType val;
63 };
64
65 struct gradient_table_item gradients[RR_SURFACE_NUM_TYPES] = {
66         {"none", RR_SURFACE_NONE},
67         {"parentrel", RR_SURFACE_PARENTREL},
68         {"solid", RR_SURFACE_SOLID},
69         {"split", RR_SURFACE_SPLIT_VERTICAL},
70         {"horizontal", RR_SURFACE_HORIZONTAL},
71         {"vertical", RR_SURFACE_VERTICAL},
72         {"diagonal", RR_SURFACE_DIAGONAL},
73         {"cross_diagonal", RR_SURFACE_CROSS_DIAGONAL},
74         {"pyramid", RR_SURFACE_PYRAMID},
75         {"mirror_horizontal", RR_SURFACE_MIRROR_HORIZONTAL},
76 };
77
78 static RrSurfaceColorType gradient_from_string(char *str)
79 {
80         int i;
81
82         for (i = 0; i < RR_SURFACE_NUM_TYPES; i++)
83                 if (strcmp(gradients[i].name, str) == 1)
84                         return gradients[i].val;
85
86         return -1;
87 }
88
89 struct parser_control *parser_init(struct obthemedata *otd)
90 {
91         struct parser_control *out;
92         out = calloc(1, sizeof(struct parser_control));
93         out->include_stack_ptr = 0;
94         out->target = otd;
95         return out;
96 }
97
98 void parser_finish(struct parser_control *c)
99 {
100         free(c);
101 }
102
103 struct expression *exdup(struct expression in)
104 {
105         struct expression *out;
106         out = malloc(sizeof(struct expression));
107         *out = in;
108         return out;
109 }
110
111 %}
112 %start theme_objects
113
114 %union {
115         int integer;
116         float realnum;
117         char *string;
118         struct decor decor;
119         struct space space;
120         struct theme theme;
121         struct material material;
122         struct style style;
123         GSList *list;
124         GHashTable *hash;
125         struct vector vector;
126         ObCursor dir;
127         ObFrameContext context;
128         RrSurfaceColorType gradient;
129         struct expression expr;
130         struct variable var;
131         struct texture tex;
132         struct material *matptr;
133         struct box box;
134         struct geometry geometry;
135 }
136
137 %token NORTH NORTHEAST EAST SOUTHEAST SOUTH SOUTHWEST
138 %token WEST NORTHWEST NONE UNCHANGED
139 %token LCB RCB LB RB TO
140 %token LEFT_ARROW RIGHT_ARROW DOUBLE_ARROW
141 %token SEMICOLON AT COLON DEFAULT NOT
142 %token PLUS MINUS STAR SLASH COMMA BOX
143 %token <string> STRING ID
144 %token <integer> NUMBER SUBST BULK BIG LITTLE
145 %token THEME FRAME SPACE GEOMETRY MATERIAL GRADIENT
146 %token CONTEXT CURSOR UP ANCHOR STYLE TEXTURE OPACITY
147 %token SHAPEOF DECOR DOT IMAGE
148 %type <decor> decor
149 %type <decor> decoritems styleitem
150 %type <space> space
151 %type <style> style styleitems
152 %type <hash> styles
153 %type <material> material_props
154 %type <realnum> opacity
155 %type <space> spaceconstraints
156 %type <vector> up anchor
157 %type <dir> cursor
158 %type <context> context
159 %type <gradient> gradient
160 %type <expr> expression
161 %type <var> variable
162 %type <tex> texture image texitems
163 %type <matptr> material_use
164 %type <box> box
165 %type <geometry> geometry geometry_item
166 %left PLUS MINUS
167 %left STAR SLASH
168 %left LB
169 %%
170
171 theme_object    : material_decl
172                 | theme
173                 ;
174
175 theme_objects   : /* empty */
176                 | theme_objects theme_object
177                 ;
178
179 theme           : THEME ID LCB styles RCB {
180                         struct theme *out;
181                         out = malloc(sizeof(struct theme));
182                         out->name = $2;
183                         out->styles = $4;
184                         g_hash_table_insert(pc->target->themes, $2, out);
185                 }
186                 ;
187
188 opacity         : OPACITY LB NUMBER RB { $$ = $3; }
189                 ;
190
191 material_props  : /* empty */ { memset(&$$, 0, sizeof($$)); }
192                 | material_props opacity { $$ = $1; $$.opacity = $2;}
193                 | material_props gradient
194                 ;
195
196 material_decl   : MATERIAL ID LCB material_props RCB {
197                         struct material *out;
198                         out = malloc(sizeof(struct material));
199                         *out = $4;
200                         g_hash_table_insert(pc->target->materials, $2, out);
201                 }
202                 ;
203
204 anchor          : ANCHOR LB expression COMMA expression COMMA expression RB {
205                         $$.x = $3;
206                         $$.y = $5;
207                         $$.z = $7;
208                 }
209                 ;
210
211 up              : UP LB expression COMMA expression COMMA expression RB {
212                         $$.x = $3;
213                         $$.y = $5;
214                         $$.z = $7;
215                 }
216                 ;
217
218 spaceconstraints: /* empty */ { memset(&$$, 0, sizeof($$));
219                         $$.anchor.x.op = OB_THEME_EQL;
220                         $$.anchor.x.v.number = 0;
221                         $$.anchor.y.op = OB_THEME_EQL;
222                         $$.anchor.y.v.number = 0;
223                         $$.anchor.z.op = OB_THEME_EQL;
224                         $$.anchor.z.v.number = 0;
225                         $$.up.x.op = OB_THEME_EQL;
226                         $$.up.x.v.number = 0;
227                         $$.up.y.op = OB_THEME_EQL;
228                         $$.up.y.v.number = 1;
229                         $$.up.z.op = OB_THEME_EQL;
230                         $$.up.z.v.number = 0;
231                 }
232                 | spaceconstraints anchor { $1.anchor = $2; $$ = $1; }
233                 | spaceconstraints up     { $1.up = $2; $$ = $1; }
234                 ;
235
236 space           : SPACE LCB spaceconstraints RCB {
237                         $$ = $3;
238                 }
239                 ;
240
241 shape           : SHAPEOF LB ID RB
242                 ;
243
244 box             : BOX LB expression COMMA expression COMMA expression RB TO
245                    LB expression COMMA expression COMMA expression RB {
246                         $$.start.x = $3;
247                         $$.start.y = $5;
248                         $$.start.z = $7;
249                         $$.end.x = $11;
250                         $$.end.y = $13;
251                         $$.end.z = $15;
252                 }
253                 ;
254
255 geometry_item   : /* empty */
256                 | shape
257                 | box { $$.box = $1; }
258                 ;
259
260 geometry        : GEOMETRY LCB geometry_item RCB {
261                         $$ = $3;
262                 }
263                 ;
264
265 material_use    : MATERIAL LB ID RB {
266                         $$ = g_hash_table_lookup(pc->target->materials, $3);
267                         if ($$ == NULL) {
268                                 snprintf(pc->error_buf, 4000, "No definition for material '%s'\n", $3);
269                                 obthemeerror(pc, pc->error_buf);
270                                 return 1;
271                         }
272                 }
273                 ;
274
275 styleitem       : decor
276                 ;
277
278 styleitems      : /* empty */ { $$.tree = NULL; $$.name = NULL; }
279                 | styleitems styleitem {
280                         struct decor *out = malloc(sizeof(struct decor));
281                         *out = $2;
282                         $1.tree = g_slist_prepend($1.tree, out);
283                         $$ = $1;
284                 }
285                 ;
286
287 styles          : /* empty */ { $$ = g_hash_table_new(g_str_hash, g_str_equal); }
288                 | styles style {
289                         struct style *out = malloc(sizeof(struct style));
290                         *out = $2;
291                         $$ = $1;
292                         g_hash_table_insert($1, out->name, out);
293                 }
294                 ;
295
296 style           : STYLE ID LCB styleitems RCB {
297                         $$ = $4;
298                         $$.name = $2;
299                 }
300                 ;
301
302 decoritems      : /* empty */ {
303                         memset(&$$, 0, sizeof($$));
304 //                      $$.space.up.y = -1;  XXX need a sane default!
305                         $$.cursor = OB_CURSOR_NONE;
306                         $$.space.anchor.x.op = OB_THEME_EQL;
307                         $$.space.anchor.x.v.number = 1;
308                         $$.space.anchor.y.op = OB_THEME_EQL;
309                         $$.space.anchor.y.v.number = 1;
310                         $$.space.anchor.z.op = OB_THEME_EQL;
311                         $$.space.anchor.z.v.number = 1;
312                         $$.space.up.x.op = OB_THEME_EQL;
313                         $$.space.up.x.v.number = 1;
314                         $$.space.up.y.op = OB_THEME_EQL;
315                         $$.space.up.y.v.number = 1;
316                         $$.space.up.z.op = OB_THEME_EQL;
317                         $$.space.up.z.v.number = 1;
318                         $$.texture.present = 0;
319                         $$.material = NULL;
320                 }
321                 | decoritems decor {
322                         struct decor *out = malloc(sizeof(struct decor));
323                         *out = $2;
324                         $$ = $1;
325                         $$.children = g_slist_append($1.children, out);
326                 }
327                 | decoritems space { $1.space = $2; $$ = $1; }
328                 | decoritems material_use { $1.material = $2; $$ = $1; }
329                 | decoritems geometry { $1.geometry = $2; $$ = $1;}
330                 | decoritems texture { $1.texture = $2; $$ = $1; } //XXX multitexture?
331                 | decoritems context { $1.context = $2; $$ = $1; }
332                 | decoritems cursor { $1.cursor = $2; $$ = $1; }
333                 ;
334
335                 ;
336
337 decor           : DECOR ID LCB decoritems RCB {
338                         $$ = $4;
339                         $$.name = $2;
340                 }
341                 ;
342
343 image           : IMAGE LB STRING RB {
344                         $$.present = 1;
345                         $$.internal = 0;
346                         $$.name = $3;
347                 }
348                 | IMAGE LB ID RB {
349                         $$.present = 1;
350                         $$.internal = 1;
351                         $$.name = $3;
352                 }
353                 ;
354
355 texitems        : image { $$ = $1; }
356                 ;
357
358 texture         : TEXTURE LCB texitems RCB { $$ = $3; }
359                 ;
360
361 context         : CONTEXT LB ID RB {
362                         ObFrameContext frc;
363                         frc = context_from_string($3);
364                         if (frc == -1) {
365                                 snprintf(pc->error_buf, 4000, "Illegal context '%s'\n", $3);
366                                 obthemeerror(pc, pc->error_buf);
367                                 return 1;
368                         }
369                 }
370                 ;
371
372 cursor          : CURSOR LB NORTH RB { $$ = OB_CURSOR_NORTH; }
373                 | CURSOR LB NORTHEAST RB { $$ = OB_CURSOR_NORTHEAST; }
374                 | CURSOR LB EAST RB { $$ = OB_CURSOR_EAST; }
375                 | CURSOR LB SOUTHEAST RB { $$ = OB_CURSOR_SOUTHEAST; }
376                 | CURSOR LB SOUTH RB { $$ = OB_CURSOR_SOUTH; }
377                 | CURSOR LB SOUTHWEST RB { $$ = OB_CURSOR_SOUTHWEST; }
378                 | CURSOR LB WEST RB { $$ = OB_CURSOR_WEST; }
379                 | CURSOR LB NORTHWEST RB { $$ = OB_CURSOR_NORTHWEST; }
380 //              | CURSOR LB NONE RB { $$ = OB_CURSOR_NORTHEAST; }
381                 | CURSOR LB UNCHANGED RB { $$ = OB_CURSOR_NONE; }
382                 ;
383 gradient        : GRADIENT LB ID RB {
384                         $$ = gradient_from_string($3);
385                         if ($$ == -1) {
386                                 snprintf(pc->error_buf, 4000, "No gradient named '%s'\n", $3);
387                                 obthemeerror(pc, pc->error_buf);
388                                 return 1;
389                         }
390                 }
391                 ;
392
393 variable        : ID DOT ID { $$.base = $1; $$.member = $3; }
394                 | ID        { $$.base = $1; $$.member = NULL; }
395                 | NUMBER    { $$.base = NULL; $$.number = $1; }
396                 ;
397
398 expression      : MINUS expression {
399                         $$.op = OB_THEME_INV;
400                         $$.a = exdup($2);
401                 }
402                 | expression STAR expression {
403                         $$.op = OB_THEME_MUL;
404                         $$.a = exdup($1);
405                         $$.b = exdup($3);
406                 }
407                 | expression SLASH expression {
408                         $$.op = OB_THEME_DIV;
409                         $$.a = exdup($1);
410                         $$.b = exdup($3);
411                 }
412                 | expression PLUS expression {
413                         $$.op = OB_THEME_ADD;
414                         $$.a = exdup($1);
415                         $$.b = exdup($3);
416                 }
417                 | expression MINUS expression {
418                         $$.op = OB_THEME_SUB;
419                         $$.a = exdup($1);
420                         $$.b = exdup($3);
421                 }
422                 | variable {
423                         $$.op = OB_THEME_EQL;
424                         $$.v = $1;
425                 }
426                 | LB expression RB { $$ = $2; }
427                 ;
428
429 %%