4ebd13ddd0d8304a3067c5a221185224c4f2a5aa
[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 %}
104 %start theme_objects
105
106 %union {
107         int integer;
108         float realnum;
109         char *string;
110         struct decor decor;
111         struct space space;
112         struct theme theme;
113         struct material material;
114         struct style style;
115         GSList *list;
116         GHashTable *hash;
117         struct vector vector;
118         ObCursor dir;
119         ObFrameContext context;
120         RrSurfaceColorType gradient;
121 }
122
123 %token NORTH NORTHEAST EAST SOUTHEAST SOUTH SOUTHWEST
124 %token WEST NORTHWEST NONE UNCHANGED
125 %token LCB RCB LB RB
126 %token LEFT_ARROW RIGHT_ARROW DOUBLE_ARROW
127 %token SEMICOLON AT COLON DEFAULT NOT
128 %token PLUS MINUS
129 %token <string> STRING ID
130 %token <integer> NUMBER SUBST BULK BIG LITTLE
131 %token THEME FRAME SPACE GEOMETRY MATERIAL GRADIENT
132 %token CONTEXT CURSOR UP ANCHOR STYLE TEXTURE OPACITY
133 %token SHAPEOF DECOR
134 %type <decor> decor
135 %type <decor> decoritems styleitem
136 %type <space> space
137 %type <style> style styleitems
138 %type <hash> styles
139 %type <material> material_props
140 %type <realnum> opacity
141 %type <space> spaceconstraints
142 %type <vector> up anchor
143 %type <dir> cursor
144 %type <context> context
145 %type <gradient> gradient
146 %%
147
148 theme_object    : material_decl
149                 | theme
150                 ;
151
152 theme_objects   : /* empty */
153                 | theme_objects theme_object
154                 ;
155
156 theme           : THEME ID LCB styles RCB {
157                         struct theme *out;
158                         out = malloc(sizeof(struct theme));
159                         out->name = $2;
160                         out->styles = $4;
161                         g_hash_table_insert(pc->target->themes, $2, out);
162                 }
163                 ;
164
165 opacity         : OPACITY LB NUMBER RB { $$ = $3; }
166                 ;
167
168 material_props  : /* empty */ { memset(&$$, 0, sizeof($$)); }
169                 | material_props opacity { $$ = $1; $$.opacity = $2;}
170                 | material_props gradient
171                 ;
172
173 material_decl   : MATERIAL ID LCB material_props RCB {
174                         struct material *out;
175                         out = malloc(sizeof(struct material));
176                         *out = $4;
177                         g_hash_table_insert(pc->target->materials, $2, out);
178                 }
179                 ;
180
181 anchor          : ANCHOR LB NUMBER NUMBER NUMBER RB {
182                         $$.x = $3;
183                         $$.y = $4;
184                         $$.z = $5;
185                 }
186                 ;
187
188 up              : UP LB NUMBER NUMBER NUMBER RB {
189                         $$.x = $3;
190                         $$.y = $4;
191                         $$.z = $5;
192                 }
193                 ;
194
195 spaceconstraints: /* empty */ { memset(&$$, 0, sizeof($$)); }
196                 | spaceconstraints anchor { $1.anchor = $2; $$ = $1; }
197                 | spaceconstraints up     { $1.up = $2; $$ = $1; }
198                 ;
199
200 space           : SPACE LCB spaceconstraints RCB {
201                         $$ = $3;
202                 }
203                 ;
204
205 shape           : SHAPEOF LB ID RB
206                 ;
207
208 geometry_item   : /* empty */
209                 | shape
210                 ;
211
212 geometry        : GEOMETRY LCB geometry_item RCB
213                 ;
214
215 material_use    : MATERIAL LB ID RB {
216                         if (g_hash_table_lookup(pc->target->materials, $3) == NULL) {
217                                 snprintf(pc->error_buf, 4000, "No definition for material '%s'\n", $3);
218                                 obthemeerror(pc, pc->error_buf);
219                                 return 1;
220                         }
221                 }
222                 ;
223
224 styleitem       : decor
225                 ;
226
227 styleitems      : /* empty */ { $$.tree = NULL; $$.name = NULL; }
228                 | styleitems styleitem {
229                         struct decor *out = malloc(sizeof(struct decor));
230                         *out = $2;
231                         $1.tree = g_slist_prepend($1.tree, out);
232                         $$ = $1;
233                 }
234                 ;
235
236 styles          : /* empty */ { $$ = g_hash_table_new(g_str_hash, g_str_equal); }
237                 | styles style {
238                         struct style *out = malloc(sizeof(struct style));
239                         *out = $2;
240                         $$ = $1;
241                         g_hash_table_insert($1, out->name, out);
242                 }
243                 ;
244
245 style           : STYLE ID LCB styleitems RCB {
246                         $$ = $4;
247                         $$.name = $2;
248                 }
249                 ;
250
251 decoritems      : /* empty */ {
252                         memset(&$$, 0, sizeof($$));
253                         $$.space.up.y = -1;
254                         $$.cursor = OB_CURSOR_NONE;
255                 }
256                 | decoritems decor {
257                         struct decor *out = malloc(sizeof(struct decor));
258                         *out = $2;
259                         $$ = $1;
260                         $$.children = g_slist_append($1.children, out);
261                 }
262                 | decoritems space { $1.space = $2; $$ = $1; }
263                 | decoritems material_use
264                 | decoritems geometry
265                 | decoritems texture
266                 | decoritems context { $1.context = $2; }
267                 | decoritems cursor { $1.cursor = $2; }
268                 ;
269
270                 ;
271
272 decor           : DECOR ID LCB decoritems RCB {
273                         $$ = $4;
274                         $$.name = $2;
275                 }
276                 ;
277
278 texture         : TEXTURE LCB RCB
279                 ;
280
281 context         : CONTEXT LB ID RB {
282                         ObFrameContext frc;
283                         frc = context_from_string($3);
284                         if (frc == -1) {
285                                 snprintf(pc->error_buf, 4000, "Illegal context '%s'\n", $3);
286                                 obthemeerror(pc, pc->error_buf);
287                                 return 1;
288                         }
289                 }
290                 ;
291
292 cursor          : CURSOR LB NORTH RB { $$ = OB_CURSOR_NORTH; }
293                 | CURSOR LB NORTHEAST RB { $$ = OB_CURSOR_NORTHEAST; }
294                 | CURSOR LB EAST RB { $$ = OB_CURSOR_EAST; }
295                 | CURSOR LB SOUTHEAST RB { $$ = OB_CURSOR_SOUTHEAST; }
296                 | CURSOR LB SOUTH RB { $$ = OB_CURSOR_SOUTH; }
297                 | CURSOR LB SOUTHWEST RB { $$ = OB_CURSOR_SOUTHWEST; }
298                 | CURSOR LB WEST RB { $$ = OB_CURSOR_WEST; }
299                 | CURSOR LB NORTHWEST RB { $$ = OB_CURSOR_NORTHWEST; }
300 //              | CURSOR LB NONE RB { $$ = OB_CURSOR_NORTHEAST; }
301                 | CURSOR LB UNCHANGED RB { $$ = OB_CURSOR_NONE; }
302                 ;
303 gradient        : GRADIENT LB ID RB {
304                         $$ = gradient_from_string($3);
305                         if ($$ == -1) {
306                                 snprintf(pc->error_buf, 4000, "No gradient named '%s'\n", $3);
307                                 obthemeerror(pc, pc->error_buf);
308                                 return 1;
309                         }
310                 }
311                 ;
312
313 %%